Merge pull request #326 from matrix-org/rav/more_spec_versioning

Put each bit of spec in its own directory
This commit is contained in:
Richard van der Hoff 2016-05-06 08:43:41 +01:00
commit 0e4a4e1e44
5 changed files with 107 additions and 57 deletions

View file

@ -103,7 +103,7 @@ func makeWalker(base string, w *fsnotify.Watcher) filepath.WalkFunc {
// log.Printf("Adding watch on %s", path) // log.Printf("Adding watch on %s", path)
if err := w.Add(path); err != nil { if err := w.Add(path); err != nil {
log.Fatalf("Failed to add watch: %v", err) log.Fatalf("Failed to add watch on %s: %v", path, err)
} }
return nil return nil
} }
@ -166,20 +166,35 @@ func populateOnce(dir string) {
toServe.Store(bytesOrErr{nil, fmt.Errorf("error generating spec: %v\nOutput from gendoc:\n%v", err, b.String())}) toServe.Store(bytesOrErr{nil, fmt.Errorf("error generating spec: %v\nOutput from gendoc:\n%v", err, b.String())})
return return
} }
fis, err := ioutil.ReadDir(path.Join(dir, "scripts", "gen"))
if err != nil {
toServe.Store(bytesOrErr{nil, err})
return
}
files := make(map[string][]byte) files := make(map[string][]byte)
for _, fi := range fis { base := path.Join(dir, "scripts", "gen")
bytes, err := ioutil.ReadFile(path.Join(dir, "scripts", "gen", fi.Name())) walker := func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
rel, err := filepath.Rel(base, path)
if err != nil {
return fmt.Errorf("Failed to get relative path of %s: %v", path, err)
}
bytes, err := ioutil.ReadFile(path)
if err != nil {
return err
}
files[rel] = bytes
return nil
}
err = filepath.Walk(base, walker)
if err != nil { if err != nil {
toServe.Store(bytesOrErr{nil, fmt.Errorf("error reading spec: %v", err)}) toServe.Store(bytesOrErr{nil, fmt.Errorf("error reading spec: %v", err)})
return return
} }
files[fi.Name()] = bytes
}
toServe.Store(bytesOrErr{files, nil}) toServe.Store(bytesOrErr{files, nil})
} }

View file

@ -6,6 +6,7 @@ import copy
import fileinput import fileinput
import glob import glob
import os import os
import os.path
import re import re
import shutil import shutil
import subprocess import subprocess
@ -277,16 +278,10 @@ def run_through_template(input_files, set_verbose, substitutions):
cwd="../templating" cwd="../templating"
) )
def get_build_targets(targets_listing):
with open(targets_listing, "r") as targ_file:
all_targets = yaml.load(targ_file.read())
return all_targets["targets"].keys()
""" """
Extract and resolve groups for the given target in the given targets listing. Extract and resolve groups for the given target in the given targets listing.
Args: Args:
targets_listing (str): The path to a YAML file containing a list of targets all_targets (dict): The parsed YAML file containing a list of targets
target_name (str): The name of the target to extract from the listings. target_name (str): The name of the target to extract from the listings.
Returns: Returns:
dict: Containing "filees" (a list of file paths), "relative_title_styles" dict: Containing "filees" (a list of file paths), "relative_title_styles"
@ -294,14 +289,12 @@ Returns:
(a list of characters which represent the global title style to follow, (a list of characters which represent the global title style to follow,
with the top section title first, the second section second, and so on.) with the top section title first, the second section second, and so on.)
""" """
def get_build_target(targets_listing, target_name): def get_build_target(all_targets, target_name):
build_target = { build_target = {
"title_styles": [], "title_styles": [],
"relative_title_styles": {}, "relative_title_styles": {},
"files": [] "files": []
} }
with open(targets_listing, "r") as targ_file:
all_targets = yaml.load(targ_file.read())
build_target["title_styles"] = all_targets["title_styles"] build_target["title_styles"] = all_targets["title_styles"]
build_target["relative_title_styles"] = all_targets["relative_title_styles"] build_target["relative_title_styles"] = all_targets["relative_title_styles"]
@ -396,8 +389,11 @@ def cleanup_env():
def main(targets, keep_intermediates, substitutions): def main(targets, keep_intermediates, substitutions):
prepare_env() prepare_env()
with open("../specification/targets.yaml", "r") as targ_file:
target_defs = yaml.load(targ_file.read())
if targets == ["all"]: if targets == ["all"]:
targets = get_build_targets("../specification/targets.yaml") + ["howtos"] targets = target_defs["targets"].keys() + ["howtos"]
log("Building spec [target=%s]" % targets) log("Building spec [target=%s]" % targets)
@ -408,7 +404,7 @@ def main(targets, keep_intermediates, substitutions):
if target_name == "howtos": if target_name == "howtos":
shutil.copy("../supporting-docs/howtos/client-server.rst", templated_file) shutil.copy("../supporting-docs/howtos/client-server.rst", templated_file)
else: else:
target = get_build_target("../specification/targets.yaml", target_name) target = get_build_target(target_defs, target_name)
build_spec(target=target, out_filename=templated_file) build_spec(target=target, out_filename=templated_file)
templated_files.append(templated_file) templated_files.append(templated_file)
@ -416,12 +412,26 @@ def main(targets, keep_intermediates, substitutions):
run_through_template(templated_files, VERBOSE, substitutions) run_through_template(templated_files, VERBOSE, substitutions)
for target_name in targets: for target_name in targets:
target = target_defs["targets"].get(target_name)
version_label = None
if target:
version_label = target.get("version_label")
if version_label:
for old, new in substitutions.items():
version_label = version_label.replace(old, new)
templated_file = "tmp/templated_%s.rst" % (target_name,) templated_file = "tmp/templated_%s.rst" % (target_name,)
rst_file = "tmp/spec_%s.rst" % (target_name,) rst_file = "tmp/spec_%s.rst" % (target_name,)
html_file = "gen/%s.html" % (target_name,) if version_label:
d = os.path.join("gen", target_name)
if not os.path.exists(d):
os.mkdir(d)
html_file = os.path.join(d, "%s.html" % version_label)
else:
html_file = "gen/%s.html" % (target_name, )
fix_relative_titles( fix_relative_titles(
target=target, filename=templated_file, target=target_defs, filename=templated_file,
out_filename=rst_file, out_filename=rst_file,
) )
rst2html(rst_file, html_file) rst2html(rst_file, html_file)

View file

@ -21,6 +21,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path" "path"
"path/filepath"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@ -353,30 +354,45 @@ func (s *server) serveSpec(w http.ResponseWriter, req *http.Request) {
return return
} }
pathToContent = make(map[string][]byte)
scriptsdir := path.Join(dst, "scripts")
base := path.Join(scriptsdir, "gen")
walker := func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
rel, err := filepath.Rel(base, path)
if err != nil {
return fmt.Errorf("Failed to get relative path of %s: %v", path, err)
}
if styleLikeMatrixDotOrg { if styleLikeMatrixDotOrg {
cmd := exec.Command("./add-matrix-org-stylings.sh", *includesDir) cmd := exec.Command("./add-matrix-org-stylings.pl", *includesDir, path)
cmd.Dir = path.Join(dst, "scripts") cmd.Dir = scriptsdir
var b bytes.Buffer var b bytes.Buffer
cmd.Stderr = &b cmd.Stderr = &b
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
writeError(w, 500, fmt.Errorf("error styling spec: %v\nOutput:\n%v", err, b.String())) return fmt.Errorf("error styling spec: %v\nOutput:\n%v", err, b.String())
return
} }
} }
fis, err := ioutil.ReadDir(path.Join(dst, "scripts", "gen")) bytes, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
writeError(w, 500, fmt.Errorf("Error reading directory: %v", err)) return fmt.Errorf("Error reading spec: %v", err)
} }
pathToContent = make(map[string][]byte) pathToContent[rel] = bytes
for _, fi := range fis { return nil
b, err := ioutil.ReadFile(path.Join(dst, "scripts", "gen", fi.Name())) }
err = filepath.Walk(base, walker)
if err != nil { if err != nil {
writeError(w, 500, fmt.Errorf("Error reading spec: %v", err)) writeError(w, 500, err)
return return
} }
pathToContent[fi.Name()] = b
}
cache.Add(sha, pathToContent) cache.Add(sha, pathToContent)
} }
@ -499,13 +515,15 @@ func (s *server) serveHTMLDiff(w http.ResponseWriter, req *http.Request) {
return return
} }
cmd := exec.Command(htmlDiffer, path.Join(base, "scripts", "gen", requestedPath), path.Join(head, "scripts", "gen", requestedPath)) cmd := exec.Command(htmlDiffer, path.Join(base, "scripts", "gen", requestedPath), path.Join(head, "scripts", "gen", requestedPath))
var b bytes.Buffer var stdout bytes.Buffer
cmd.Stdout = &b var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
writeError(w, 500, fmt.Errorf("error running HTML differ: %v", err)) writeError(w, 500, fmt.Errorf("error running HTML differ: %v\nOutput:\n%v", err, stderr.String()))
return return
} }
w.Write(b.Bytes()) w.Write(stdout.Bytes())
} }
func findHTMLDiffer() (string, error) { func findHTMLDiffer() (string, error) {

View file

@ -12,19 +12,24 @@ targets:
- { 1: modules.rst } - { 1: modules.rst }
- { 2: feature_profiles.rst } - { 2: feature_profiles.rst }
- { 2: "group:modules" } # reference a group of files - { 2: "group:modules" } # reference a group of files
version_label: "%CLIENT_RELEASE_LABEL%"
application_service: application_service:
files: files:
- application_service_api.rst - application_service_api.rst
version_label: unstable
server_server: server_server:
files: files:
- server_server_api.rst - server_server_api.rst
- { 1: event_signing.rst } - { 1: event_signing.rst }
version_label: "%SERVER_RELEASE_LABEL%"
identity_service: identity_service:
files: files:
- identity_service_api.rst - identity_service_api.rst
version_label: unstable
push_gateway: push_gateway:
files: files:
- push_gateway.rst - push_gateway.rst
version_label: unstable
appendices: appendices:
files: files:
- appendices.rst - appendices.rst

View file

@ -541,25 +541,27 @@ class MatrixUnits(Units):
return event_types return event_types
def load_apis(self, substitutions): def load_apis(self, substitutions):
cs_ver = substitutions.get("%CLIENT_RELEASE_LABEL%", "unstable")
fed_ver = substitutions.get("%SERVER_RELEASE_LABEL%", "unstable")
return { return {
"rows": [{ "rows": [{
"key": "`Client-Server API <client_server.html>`_", "key": "`Client-Server API <client_server/"+cs_ver+".html>`_",
"type": substitutions.get("%CLIENT_RELEASE_LABEL%", "unstable"), "type": cs_ver,
"desc": "Interaction between clients and servers", "desc": "Interaction between clients and servers",
}, { }, {
"key": "`Server-Server API <server_server.html>`_", "key": "`Server-Server API <server_server/"+fed_ver+".html>`_",
"type": substitutions.get("%SERVER_RELEASE_LABEL%", "unstable"), "type": fed_ver,
"desc": "Federation between servers", "desc": "Federation between servers",
}, { }, {
"key": "`Application Service API <application_service.html>`_", "key": "`Application Service API <application_service/unstable.html>`_",
"type": substitutions.get("%CLIENT_RELEASE_LABEL%", "unstable"), "type": "unstable",
"desc": "Privileged server plugins", "desc": "Privileged server plugins",
}, { }, {
"key": "`Identity Service API <identity_service.html>`_", "key": "`Identity Service API <identity_service/unstable.html>`_",
"type": "unstable", "type": "unstable",
"desc": "Mapping of third party IDs with Matrix ID", "desc": "Mapping of third party IDs with Matrix ID",
}, { }, {
"key": "`Push Gateway API <push_gateway.html>`_", "key": "`Push Gateway API <push_gateway/unstable.html>`_",
"type": "unstable", "type": "unstable",
"desc": "Push notifications for Matrix events", "desc": "Push notifications for Matrix events",
}] }]