Move the Go build source reader out of internal/builder so the builder can go (issue 1851, C1a)

This commit is contained in:
2026-10-23 15:06:31 +02:00
parent 791786d5b8
commit b506852388
6 changed files with 21 additions and 19 deletions
+4 -4
View File
@@ -5,6 +5,7 @@ import (
"errors"
"flag"
"fmt"
"github.com/novox/mesh-controller/internal/gosource"
"regexp"
"slices"
"sort"
@@ -13,7 +14,6 @@ import (
"time"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"github.com/novox/mesh-controller/internal/builder"
"github.com/novox/mesh-controller/internal/inventory"
"github.com/novox/mesh-controller/internal/link"
)
@@ -483,7 +483,7 @@ func whyMoved(e inventory.Entry, read []inventory.ReadRepository, m link.SourceM
held := func(paths []string) []string {
var in []string
for _, p := range m.Paths {
if builder.SourceHolds(paths, p) {
if gosource.SourceHolds(paths, p) {
in = append(in, p)
}
}
@@ -670,7 +670,7 @@ func readsFrom(read []inventory.ReadRepository, m link.SourceMoved) bool {
return true
}
for _, p := range m.Paths {
if builder.SourceHolds(r.Paths, p) {
if gosource.SourceHolds(r.Paths, p) {
return true
}
}
@@ -695,7 +695,7 @@ func ownSource(read []inventory.ReadRepository) []string {
// for a module built from the repository's root.
func readsFile(e inventory.Entry, read []inventory.ReadRepository, p string) bool {
if own := ownSource(read); own != nil {
return builder.SourceHolds(own, p)
return gosource.SourceHolds(own, p)
}
return readsDirectory(e, p)
}
+5 -4
View File
@@ -4,6 +4,7 @@ package builder
import (
"context"
"github.com/novox/mesh-controller/internal/gosource"
"os"
"path/filepath"
"slices"
@@ -108,7 +109,7 @@ func TestAnImageCompilingGoIsHandedItsBuildSourceAndSaysIt(t *testing.T) {
}
for file, want := range map[string]bool{"proxy/main.go": true, "internal/shared/s.go": true, "go.mod": true,
"cmd/ctl/main.go": false, "README.md": false} {
if SourceHolds(ctx.Paths, file) != want {
if gosource.SourceHolds(ctx.Paths, file) != want {
t.Errorf("the context's build source holds %s: %v, wanted %v (%v)", file, !want, want, ctx.Paths)
}
}
@@ -147,8 +148,8 @@ func TestAnArchiveOfTheWholeDirectoryHoldsIt(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if len(got.Sources) != 1 || !SourceHolds(got.Sources[0].Paths, "modules/look/a/b.css") ||
SourceHolds(got.Sources[0].Paths, "modules/other/x") {
if len(got.Sources) != 1 || !gosource.SourceHolds(got.Sources[0].Paths, "modules/look/a/b.css") ||
gosource.SourceHolds(got.Sources[0].Paths, "modules/other/x") {
t.Fatalf("sources %+v", got.Sources)
}
}
@@ -190,7 +191,7 @@ func TestAGoBundleSaysItsClosureAndAnUntoldImageNothing(t *testing.T) {
}
for file, want := range map[string]bool{"cmd/ctl/main.go": true, "internal/shared/s.go": true, ManifestName: true,
"go.sum": true, "proxy/main.go": false, "README.md": false, "internal/only/o.go": false} {
if SourceHolds(got.Sources[0].Paths, file) != want {
if gosource.SourceHolds(got.Sources[0].Paths, file) != want {
t.Errorf("%s: held %v, wanted %v (%v)", file, !want, want, got.Sources[0].Paths)
}
}
+4 -3
View File
@@ -9,6 +9,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/novox/mesh-controller/internal/gosource"
"io"
"io/fs"
"os"
@@ -1207,13 +1208,13 @@ func one(ctx context.Context, run Runner, publish Publisher,
// merge elsewhere in that repository is no change to it — and a recipe that copies a file outside
// it fails here, naming the file, rather than building from something no merge is mapped onto.
if a.Compiles != "" {
paths, err := GoBuildSource(buildDir, a.Compiles)
paths, err := gosource.GoBuildSource(buildDir, a.Compiles)
if err != nil {
return catalogue.Built{}, fmt.Errorf("%s: %s compiles %s, whose build source cannot be read: %w",
module, a.Name, a.Compiles, err)
}
narrowed := filepath.Join(workspace, "narrow-"+a.Name)
sum, err := narrowTree(buildDir, narrowed, paths)
sum, err := gosource.NarrowTree(buildDir, narrowed, paths)
if err != nil {
return catalogue.Built{}, fmt.Errorf("%s: handing %s its build source: %w", module, a.Name, err)
}
@@ -1311,7 +1312,7 @@ func one(ctx context.Context, run Runner, publish Publisher,
// A Go program's build source is its import closure (novox/hq ADR 0267 rule 1). Not read, it is the
// module's whole directory, as before — said, so the wider plan has a reason a person can find.
if chain.Language == "go" {
if paths, err := GoBuildSource(tree, a.From); err != nil {
if paths, err := gosource.GoBuildSource(tree, a.From); err != nil {
say("bundle", "%s's build source is its whole directory: %v", a.Name, err)
src.ownWhole()
} else {
@@ -1,4 +1,4 @@
package builder
package gosource
import (
"bufio"
@@ -448,11 +448,11 @@ func embedRoot(pattern string) string {
return path.Clean(strings.Join(kept, "/"))
}
// narrowTree copies into dst the files of src a build source holds, and nothing else — never `.git` — and
// NarrowTree copies into dst the files of src a build source holds, and nothing else — never `.git` — and
// returns a fingerprint of what it copied: each file's path, mode and content, hashed in path order. **A
// build handed only its build source cannot read past it** (novox/hq ADR 0267 rule 3): a recipe that
// copies a file outside it fails, naming the file, where it would have built and been missed.
func narrowTree(src, dst string, entries []string) (string, error) {
func NarrowTree(src, dst string, entries []string) (string, error) {
if err := os.RemoveAll(dst); err != nil {
return "", err
}
@@ -1,6 +1,6 @@
//go:build integration
package builder
package gosource
import (
"os"
@@ -1,4 +1,4 @@
package builder
package gosource
import (
"os"
@@ -146,7 +146,7 @@ func TestANarrowedTreeHoldsTheBuildSourceAndNothingElse(t *testing.T) {
t.Fatal(err)
}
dst := filepath.Join(t.TempDir(), "narrow")
one, err := narrowTree(src, dst, entries)
one, err := NarrowTree(src, dst, entries)
if err != nil {
t.Fatal(err)
}
@@ -160,13 +160,13 @@ func TestANarrowedTreeHoldsTheBuildSourceAndNothingElse(t *testing.T) {
// Outside the build source: one fingerprint.
files["README.md"] = "changed"
files["unrelated/u.go"] = "package unrelated\n\nconst Changed = 1\n"
again, err := narrowTree(aGoTree(t, files), filepath.Join(t.TempDir(), "n"), entries)
again, err := NarrowTree(aGoTree(t, files), filepath.Join(t.TempDir(), "n"), entries)
if err != nil || again != one {
t.Fatalf("a change outside the build source changed its fingerprint: %s %s %v", one, again, err)
}
// Inside it: another.
files["lib/lib.go"] = "package lib\n\nconst X = 2\n"
moved, err := narrowTree(aGoTree(t, files), filepath.Join(t.TempDir(), "n"), entries)
moved, err := NarrowTree(aGoTree(t, files), filepath.Join(t.TempDir(), "n"), entries)
if err != nil || moved == one {
t.Fatalf("a change inside the build source kept its fingerprint: %s %v", moved, err)
}