// Package trunk is where a catalogue check finds the trunk's copy of a list that may only shrink (novox/hq ADR 0529 clause 2): // the file as the catalogue's base commit holds it, to judge a change's list against. // // A check in a merge check finds it in the clone of the change's own repository at its base commit, which the checker places // beside the change in MESH_CHECK_BESIDE as it places a sibling, under the repository's name. Run by hand, without that // directory, it reads the file from git at the merge base with origin/, as the script this // replaces did. A trunk that holds no such file had none: the list's first copy, which nothing was added to. Where no base // can be found at all, the comparison is not made, and the test says so in its log: NOT COMPARED, never a pass that looks like one. package trunk import ( "errors" "os" "os/exec" "path/filepath" "strings" "testing" ) // Repository is the catalogue's name beside a check. const Repository = "mesh-catalog" // BesideEnv is where a merge check says the clones beside the one checked are. const BesideEnv = "MESH_CHECK_BESIDE" // Copy is the trunk's copy of the file at rel (a path from the catalogue's root), written to a file of the test's own: its // path, and whether there is one. False with a log line when the trunk holds none or cannot be read; the caller then judges // the list as a first copy. func Copy(t testing.TB, rel string) (string, bool) { t.Helper() raw, found, how := Read(rel, "../..") if how != "" { t.Log(how) } if !found { return "", false } path := filepath.Join(t.TempDir(), filepath.Base(rel)) if err := os.WriteFile(path, raw, 0o644); err != nil { t.Fatal(err) } return path, true } // Read is the trunk's copy of rel, whether the trunk holds one, and a line to log when the comparison was not made or // where it was made. root is the catalogue's checkout (for git). func Read(rel, root string) (content []byte, found bool, say string) { if beside := os.Getenv(BesideEnv); beside != "" { dir := filepath.Join(beside, Repository) if _, err := os.Stat(dir); err == nil { raw, err := os.ReadFile(filepath.Join(dir, rel)) if errors.Is(err, os.ErrNotExist) { return nil, false, "the trunk holds no " + rel + " (read from " + dir + "): its first copy" } if err != nil { return nil, false, "NOT COMPARED WITH THE TRUNK: " + err.Error() } return raw, true, "judged against the trunk's " + rel + " in " + dir } } base := "origin/" + firstOf(os.Getenv("MESH_CHECK_BASE"), "main") mergeBase, err := git(root, "merge-base", "HEAD", base) if err != nil { return nil, false, "NOT COMPARED WITH THE TRUNK: no merge base with " + base + ", and no clone of the trunk in " + BesideEnv + "; " + rel + " is held to the list it was first written with" } raw, err := git(root, "show", strings.TrimSpace(string(mergeBase))+":"+rel) if err != nil { if _, exists := git(root, "cat-file", "-e", strings.TrimSpace(string(mergeBase))+":"+rel); exists != nil { return nil, false, "the trunk holds no " + rel + " at the merge base: its first copy" } return nil, false, "NOT COMPARED WITH THE TRUNK: " + err.Error() } return raw, true, "judged against the trunk's " + rel + " at the merge base with " + base } func git(dir string, args ...string) ([]byte, error) { cmd := exec.Command("git", args...) cmd.Dir = dir return cmd.Output() } func firstOf(s ...string) string { for _, x := range s { if x != "" { return x } } return "" }