179 lines
5.9 KiB
Go
179 lines
5.9 KiB
Go
// Command templates refuses a file's text kept inline in a manifest, outside the modules still to move (novox/hq
|
|
// ADR 0349 §2, design 57 package T5, issue 658).
|
|
//
|
|
// A file resource names its text as a template in its module's templates directory (`"template": "<dir>/<name>"`;
|
|
// the directory is the manifest's `"templates"`, files/ when it says none), which the module's build packs into an
|
|
// archive; the controller reads each template back into the file's content, so the
|
|
// mesh holds and composes what it would for the same text inline. A module whose file text has not yet moved is
|
|
// listed in the file `inline` beside this check, one per line. Every other module's file resources say no
|
|
// `content`; a module on the list that keeps none inline is taken off it; and a line the trunk's copy (the merge
|
|
// base's, given with -base) does not hold is refused, so the list only shrinks; while the trunk holds no copy, the
|
|
// modules in seed are the trunk's. When it is empty, no manifest in the catalogue carries file text.
|
|
//
|
|
// Only file resources are judged: a window-manager addition (`contributions`) takes no template and moves with the
|
|
// collections (design 57 package L2, issue 681).
|
|
//
|
|
// go run . [-base <the trunk's inline>] <catalogue root>
|
|
//
|
|
// Every refusal names the refused module's own templates directory. Exits 1 on a finding.
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
listFile = "inline"
|
|
listPathInCatalog = "checks/templates/" + listFile
|
|
)
|
|
|
|
// Check answers, per module that keeps any, the ids of its file resources that say their text inline.
|
|
func Check(root string) (map[string][]string, error) {
|
|
manifests, err := filepath.Glob(filepath.Join(root, "modules", "*", "module.json"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sort.Strings(manifests)
|
|
out := map[string][]string{}
|
|
for _, path := range manifests {
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var m struct {
|
|
Module string `json:"module"`
|
|
Resources []map[string]any `json:"resources"`
|
|
}
|
|
if err := json.Unmarshal(raw, &m); err != nil {
|
|
return nil, fmt.Errorf("%s: %w", path, err)
|
|
}
|
|
for _, r := range m.Resources {
|
|
if _, inline := r["content"]; inline && r["type"] == "file" {
|
|
out[m.Module] = append(out[m.Module], fmt.Sprint(r["id"]))
|
|
}
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// TemplatesDir answers the directory a module keeps its templates in, with a trailing slash: its manifest's
|
|
// `templates`, files/ when the manifest says none or cannot be read here.
|
|
func TemplatesDir(root, module string) string {
|
|
dir := "files/"
|
|
raw, err := os.ReadFile(filepath.Join(root, "modules", module, "module.json"))
|
|
if err != nil {
|
|
return dir
|
|
}
|
|
var m struct {
|
|
Templates string `json:"templates"`
|
|
}
|
|
if json.Unmarshal(raw, &m) == nil && m.Templates != "" {
|
|
dir = strings.TrimSuffix(m.Templates, "/") + "/"
|
|
}
|
|
return dir
|
|
}
|
|
|
|
// Refusal is the finding for a module that keeps file text inline and is not on the list.
|
|
func Refusal(module string, ids []string, dir string) string {
|
|
return fmt.Sprintf("%s keeps the text of %s inline and is not on %s: keep each file's text in %s and name it as "+
|
|
"the file's template, packed by the build's archive from %s (novox/hq ADR 0349 §2)",
|
|
module, strings.Join(ids, ", "), listPathInCatalog, dir, dir)
|
|
}
|
|
|
|
// Gained is the finding for a module the list gains against the trunk's copy.
|
|
func Gained(module, dir string) string {
|
|
return fmt.Sprintf("%s gains %s, which the trunk's copy does not hold: the list only shrinks — move its file text "+
|
|
"to %s instead (novox/hq ADR 0349 §2)", listPathInCatalog, module, dir)
|
|
}
|
|
|
|
// seed is the list as it was first written, standing for the trunk's copy until the trunk holds one.
|
|
var seed = map[string]bool{"asus-zephyrus-g14": true, "power": true, "showcase": true}
|
|
|
|
// Listed is the modules a list names, one per line; a line starting with # and a blank line are not modules.
|
|
func Listed(path string) (map[string]bool, error) {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
out := map[string]bool{}
|
|
s := bufio.NewScanner(f)
|
|
for s.Scan() {
|
|
line := strings.TrimSpace(s.Text())
|
|
if line == "" || strings.HasPrefix(line, "#") {
|
|
continue
|
|
}
|
|
out[line] = true
|
|
}
|
|
return out, s.Err()
|
|
}
|
|
|
|
// Judge answers the modules that keep file text inline and are not on the list (refused), the modules on the list
|
|
// that keep none (stale), and the modules on the list that the trunk's list does not hold (added).
|
|
func Judge(found map[string][]string, listed, base map[string]bool) (refused, stale, added []string) {
|
|
for m := range found {
|
|
if !listed[m] {
|
|
refused = append(refused, m)
|
|
}
|
|
}
|
|
for m := range listed {
|
|
if _, keeps := found[m]; !keeps {
|
|
stale = append(stale, m)
|
|
}
|
|
if !base[m] {
|
|
added = append(added, m)
|
|
}
|
|
}
|
|
sort.Strings(refused)
|
|
sort.Strings(stale)
|
|
sort.Strings(added)
|
|
return refused, stale, added
|
|
}
|
|
|
|
func main() {
|
|
basePath := flag.String("base", "", "the trunk's copy of inline (the merge base's); seed when absent")
|
|
flag.Parse()
|
|
root := "."
|
|
if flag.NArg() > 0 {
|
|
root = flag.Arg(0)
|
|
}
|
|
found, err := Check(root)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
listed, err := Listed(listFile)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
base := seed
|
|
if *basePath != "" {
|
|
if base, err = Listed(*basePath); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
refused, stale, added := Judge(found, listed, base)
|
|
for _, m := range refused {
|
|
fmt.Println(Refusal(m, found[m], TemplatesDir(root, m)))
|
|
}
|
|
for _, m := range stale {
|
|
fmt.Printf("%s names %s, which keeps no file text inline: take it off the list\n", listPathInCatalog, m)
|
|
}
|
|
for _, m := range added {
|
|
fmt.Println(Gained(m, TemplatesDir(root, m)))
|
|
}
|
|
if len(refused) > 0 || len(stale) > 0 || len(added) > 0 {
|
|
os.Exit(1)
|
|
}
|
|
fmt.Printf("templates: no module keeps a file's text inline but the %d listed\n", len(listed))
|
|
}
|