105 lines
2.9 KiB
Go
105 lines
2.9 KiB
Go
// Command toolchains refuses any manifest but the owner's declaring a language's toolchain package (novox/hq
|
|
// ADR 0477 clause 4, issue 1573): the package go only in modules/go, and nodejs and npm only in modules/nodejs.
|
|
// Everything that compiles or runs that language requires the owner's provision instead (go-toolchain,
|
|
// node-toolchain), so the package is declared once, and a node without the owner refuses the module that
|
|
// needs it at resolution rather than failing at its first build. The owners must declare their packages.
|
|
//
|
|
// go run . <catalogue root>
|
|
//
|
|
// Exits 1 on a finding.
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
)
|
|
|
|
// Owners names, for each toolchain package, the one module that declares it.
|
|
var Owners = map[string]string{
|
|
"go": "go",
|
|
"nodejs": "nodejs",
|
|
"npm": "nodejs",
|
|
}
|
|
|
|
// Finding is one refusal: Module declares Package, which Owner alone may, or (Missing) Owner does not declare
|
|
// the Package it owns.
|
|
type Finding struct {
|
|
Module, Package, Owner string
|
|
Missing bool
|
|
}
|
|
|
|
// Check reads every manifest under root/modules and answers what it refuses.
|
|
func Check(root string) ([]Finding, error) {
|
|
manifests, err := filepath.Glob(filepath.Join(root, "modules", "*", "module.json"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sort.Strings(manifests)
|
|
var out []Finding
|
|
declared := map[string]map[string]bool{} // module -> packages
|
|
for _, path := range manifests {
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var m struct {
|
|
Module string `json:"module"`
|
|
Resources []struct {
|
|
Type string `json:"type"`
|
|
Package string `json:"package"`
|
|
} `json:"resources"`
|
|
}
|
|
if err := json.Unmarshal(raw, &m); err != nil {
|
|
return nil, fmt.Errorf("%s: %w", path, err)
|
|
}
|
|
declared[m.Module] = map[string]bool{}
|
|
for _, r := range m.Resources {
|
|
if r.Type != "package" {
|
|
continue
|
|
}
|
|
declared[m.Module][r.Package] = true
|
|
if owner, ok := Owners[r.Package]; ok && owner != m.Module {
|
|
out = append(out, Finding{Module: m.Module, Package: r.Package, Owner: owner})
|
|
}
|
|
}
|
|
}
|
|
var pkgs []string
|
|
for p := range Owners {
|
|
pkgs = append(pkgs, p)
|
|
}
|
|
sort.Strings(pkgs)
|
|
for _, p := range pkgs {
|
|
if !declared[Owners[p]][p] {
|
|
out = append(out, Finding{Module: Owners[p], Package: p, Owner: Owners[p], Missing: true})
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func main() {
|
|
root := "."
|
|
if len(os.Args) > 1 {
|
|
root = os.Args[1]
|
|
}
|
|
found, err := Check(root)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
for _, f := range found {
|
|
if f.Missing {
|
|
fmt.Printf("%s does not declare the package %s it owns (novox/hq ADR 0477 clause 4)\n", f.Owner, f.Package)
|
|
continue
|
|
}
|
|
fmt.Printf("%s declares the package %s: only %s may; require its provision instead (novox/hq ADR 0477 clause 4)\n",
|
|
f.Module, f.Package, f.Owner)
|
|
}
|
|
if len(found) > 0 {
|
|
os.Exit(1)
|
|
}
|
|
fmt.Println("toolchains: go, nodejs and npm are declared only by their owners")
|
|
}
|