From 2aa43ec2496300c9eef4ceb0a01ed3f0e6eb483c Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 2 Nov 2026 18:26:53 +0100 Subject: [PATCH] Bridge reads no mesh package from a go.sum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only the indexer computes what a fingerprint takes (ADR 0593 §2): the merged and pull messages carry no Packages, and the kept inputs no longer hold them (D6). Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL --- .../integration_test.go | 5 +-- .../internal/bridge/bridge.go | 42 +++++++------------ .../internal/bridge/files_test.go | 20 +++------ .../internal/bridge/kept.go | 27 +++++------- 4 files changed, 32 insertions(+), 62 deletions(-) diff --git a/modules/mesh-delivery-forge-bridge/cmd/mesh-delivery-forge-bridge/integration_test.go b/modules/mesh-delivery-forge-bridge/cmd/mesh-delivery-forge-bridge/integration_test.go index ef91207..5f1592f 100644 --- a/modules/mesh-delivery-forge-bridge/cmd/mesh-delivery-forge-bridge/integration_test.go +++ b/modules/mesh-delivery-forge-bridge/cmd/mesh-delivery-forge-bridge/integration_test.go @@ -423,9 +423,8 @@ func TestBridgeWritesMergedMessage(t *testing.T) { // 1236/AC4, 1448/AC5 want := delivery.Forge{V: delivery.Version, Kind: "merged", Repository: "novox/mesh-delivery", Branch: "feat/x", Number: 12, Head: head, Merge: merge, Root: "r0", Trees: map[string]string{"": "t0", "modules/a": "t1"}, Manifests: map[string]string{"": string(manifest), "modules/a": string(manifest)}, - Locks: map[string]map[string]string{"modules/a": {"go.sum": hex.EncodeToString(sha256Sum(sum))}}, - // The mesh packages its go.sum names (ADR 0573 §2, issue 1585): this module's own go.sum names mesh-sdk. - Packages: map[string][]string{"modules/a": {"git.novox.be/novox/mesh-sdk/go"}}} + // No mesh package: only the indexer computes what a fingerprint takes (ADR 0593 §2). + Locks: map[string]map[string]string{"modules/a": {"go.sum": hex.EncodeToString(sha256Sum(sum))}}} if !delivery.SameForge(f, want) { t.Errorf("message = %+v, want %+v", f, want) } diff --git a/modules/mesh-delivery-forge-bridge/internal/bridge/bridge.go b/modules/mesh-delivery-forge-bridge/internal/bridge/bridge.go index 5f8fbd2..c8cb1a3 100644 --- a/modules/mesh-delivery-forge-bridge/internal/bridge/bridge.go +++ b/modules/mesh-delivery-forge-bridge/internal/bridge/bridge.go @@ -151,7 +151,7 @@ func ConvertKept(subject string, data []byte, trees Trees, files Files, kept Kep if action == delivery.PullUpdated && p.ModuleDirsSaid { f.Dirs, f.DirsKnown = p.ModuleDirs, true var err error - if f.Manifests, f.Locks, f.Packages, _, err = inputsRead(p.Owner, p.Repo, p.HeadSHA, p.ModuleDirs, files); err != nil { + if f.Manifests, f.Locks, _, err = inputsRead(p.Owner, p.Repo, p.HeadSHA, p.ModuleDirs, files); err != nil { return Message{}, fmt.Errorf("%w: %s: the manifests of %s/%s at the head %s: %v", ErrRetry, subject, p.Owner, p.Repo, p.HeadSHA, err) } } @@ -190,15 +190,15 @@ type read struct { // order the calls finish in, and the error is that of the first failing file in the order of dirs and LockFiles. After // a failure no further file is asked for, and inputsOf returns only when every call it started has returned. func inputsOf(owner, repo, ref string, dirs []string, files Files) (manifests map[string]string, locks map[string]map[string]string, err error) { - manifests, locks, _, _, err = inputsRead(owner, repo, ref, dirs, files) + manifests, locks, _, err = inputsRead(owner, repo, ref, dirs, files) return manifests, locks, err } -// inputsRead is inputsOf, and also answers the mesh packages each directory's go.sum names (delivery.MeshPackagesOf, -// novox/hq ADR 0573 §2; issue 1585) and, on a failure too, the directories whose manifest and lock files were all read, -// with their manifests and lock hashes: a merge keeps them by their tree, so its next try reads only the rest (issue -// 1126). -func inputsRead(owner, repo, ref string, dirs []string, files Files) (manifests map[string]string, locks map[string]map[string]string, packages map[string][]string, whole []string, err error) { +// inputsRead is inputsOf, and also answers, on a failure too, the directories whose manifest and lock files were all +// read, with their manifests and lock hashes: a merge keeps them by their tree, so its next try reads only the rest +// (issue 1126). It reads no mesh package a go.sum names: the indexer alone computes what a fingerprint takes (novox/hq +// ADR 0593 §2), so the message's Packages stay empty. +func inputsRead(owner, repo, ref string, dirs []string, files Files) (manifests map[string]string, locks map[string]map[string]string, whole []string, err error) { at := func(dir, name string) string { if dir == "" { return name @@ -242,7 +242,6 @@ func inputsRead(owner, repo, ref string, dirs []string, files Files) (manifests wg.Wait() manifests = map[string]string{} locks = map[string]map[string]string{} - packages = map[string][]string{} broken := map[string]bool{} // a directory with a file not read (failed, or never asked after a failure) for _, r := range reads { switch { @@ -262,11 +261,6 @@ func inputsRead(owner, repo, ref string, dirs []string, files Files) (manifests locks[r.dir] = map[string]string{} } locks[r.dir][path.Base(r.path)] = hex.EncodeToString(sum[:]) - if path.Base(r.path) == "go.sum" { - if p := delivery.MeshPackagesOf(r.raw); len(p) > 0 { - packages[r.dir] = p - } - } } } for _, dir := range dirs { @@ -278,9 +272,8 @@ func inputsRead(owner, repo, ref string, dirs []string, files Files) (manifests for dir := range broken { delete(manifests, dir) delete(locks, dir) - delete(packages, dir) } - return manifests, locks, packages, whole, err + return manifests, locks, whole, err } if len(manifests) == 0 { manifests = nil @@ -288,10 +281,7 @@ func inputsRead(owner, repo, ref string, dirs []string, files Files) (manifests if len(locks) == 0 { locks = nil } - if len(packages) == 0 { - packages = nil - } - return manifests, locks, packages, whole, nil + return manifests, locks, whole, nil } // merged is the merged message of a merge into the trunk: the trees of the merge commit, asked once. @@ -312,19 +302,15 @@ func merged(subject string, p pull, trees Trees, files Files, kept Kept) (Messag names = append(names, dir) } slices.Sort(names) - manifests, locks, packages, toRead := keptInputs(names, dirs, kept) - read, readLocks, readPackages, whole, err := inputsRead(p.Owner, p.Repo, p.MergeSHA, toRead, files) + manifests, locks, toRead := keptInputs(names, dirs, kept) + read, readLocks, whole, err := inputsRead(p.Owner, p.Repo, p.MergeSHA, toRead, files) if err != nil { - keep(whole, dirs, read, readLocks, readPackages, kept) // what was read whole is not asked again at the next try + keep(whole, dirs, read, readLocks, kept) // what was read whole is not asked again at the next try return Message{}, fmt.Errorf("%w: %s: the manifests of %s at the merge commit %s (%d of %d module directories read from the forge, the others kept by their tree): %v", ErrRetry, subject, repository, p.MergeSHA, len(toRead), len(names), err) } - keep(toRead, dirs, read, readLocks, readPackages, kept) + keep(toRead, dirs, read, readLocks, kept) maps.Copy(manifests, read) maps.Copy(locks, readLocks) - maps.Copy(packages, readPackages) - if len(packages) == 0 { - packages = nil - } if len(manifests) == 0 { manifests = nil } @@ -336,7 +322,7 @@ func merged(subject string, p pull, trees Trees, files Files, kept Kept) (Messag return Message{}, unreadable(subject, "%v", err) } f := delivery.Forge{Kind: delivery.ForgeMerged, Repository: repository, Branch: p.Head, Number: p.Number, - Head: p.HeadSHA, Merge: p.MergeSHA, Root: root, Trees: dirs, Manifests: manifests, Locks: locks, Packages: packages} + Head: p.HeadSHA, Merge: p.MergeSHA, Root: root, Trees: dirs, Manifests: manifests, Locks: locks} if repository == CatalogRepository { // The catalogue's predefined list at the merge (novox/hq ADR 0565 §2): the indexer keeps it for mesh-config. raw, err := files(p.Owner, p.Repo, PredefinedFile, p.MergeSHA) diff --git a/modules/mesh-delivery-forge-bridge/internal/bridge/files_test.go b/modules/mesh-delivery-forge-bridge/internal/bridge/files_test.go index 72de850..ce1f545 100644 --- a/modules/mesh-delivery-forge-bridge/internal/bridge/files_test.go +++ b/modules/mesh-delivery-forge-bridge/internal/bridge/files_test.go @@ -79,9 +79,9 @@ func TestMergedCarriesManifestsAndLocks(t *testing.T) { // 1448/AC1 if want := map[string]map[string]string{"modules/a": {"go.sum": hexSum(sum)}}; !reflect.DeepEqual(f.Locks, want) { t.Errorf("locks = %v, want %v", f.Locks, want) } - // Issue 1585 (ADR 0573 §2): and the mesh packages each go.sum names. - if want := map[string][]string{"modules/a": {"git.novox.be/novox/mesh-sdk/go"}}; !reflect.DeepEqual(f.Packages, want) { - t.Errorf("packages = %v, want %v", f.Packages, want) + // ADR 0593 §2 (D6): the bridge reads no mesh package; only the indexer computes what a fingerprint takes. + if len(f.Packages) != 0 || strings.Contains(string(msg.Data), `"packages"`) { + t.Errorf("the merged message carries packages: %v", f.Packages) } // ADR 0567: placement is the seat mesh-placement's: a merge of the catalogue carries no placement file and asks the // forge for none. @@ -134,8 +134,7 @@ func TestPullWithKnownDirsCarriesTheSameAtTheHead(t *testing.T) { // 1448/AC2 t.Fatal(err) } f, _ := delivery.DecodeForge(msg.Data) - if !reflect.DeepEqual(f.Manifests, map[string]string{"modules/a": string(manifest)}) || len(f.Locks) != 1 || - !reflect.DeepEqual(f.Packages, map[string][]string{"modules/a": {"git.novox.be/novox/mesh-sdk/go"}}) { + if !reflect.DeepEqual(f.Manifests, map[string]string{"modules/a": string(manifest)}) || len(f.Locks) != 1 || len(f.Packages) != 0 { t.Errorf("manifests %v locks %v packages %v", f.Manifests, f.Locks, f.Packages) } if len(forge.calls) == 0 || forge.calls[0].ref != head { @@ -394,14 +393,5 @@ func mergeReadsOnlyChangedDirs(t *testing.T) { if len(failing.calls) != 3 { t.Errorf("the try after a failure read %d files, want only modules/b's 3", len(failing.calls)) } - // Issue 1585: inputs kept before the bridge read the packages are read again, so no module loses the packages it uses. - for tree, in := range kept2 { - in.Packages, in.PackagesRead = nil, false - kept2[tree] = in - } - failing.calls = nil - again, err = ConvertKept(mergedSubject, mergedBody(nil), treesOf(&calls, "r1", trees, nil), failing.get, kept2) - if err != nil || string(again.Data) != string(whole.Data) || len(failing.calls) != 6 { - t.Errorf("inputs kept without their packages: %d files read, want 6; same message: %v (%v)", len(failing.calls), string(again.Data) == string(whole.Data), err) - } + // ADR 0593 §2: inputs an older bridge kept with the packages it read are taken as they are; their packages are left. } diff --git a/modules/mesh-delivery-forge-bridge/internal/bridge/kept.go b/modules/mesh-delivery-forge-bridge/internal/bridge/kept.go index 80531a6..6c68739 100644 --- a/modules/mesh-delivery-forge-bridge/internal/bridge/kept.go +++ b/modules/mesh-delivery-forge-bridge/internal/bridge/kept.go @@ -7,14 +7,12 @@ package bridge // every byte under it, so the manifest and the lock-file hashes read once at a tree hash are those of every later commit // whose directory has the same tree: a merge reads the forge only for the directories it changed. -// Inputs is what the bridge read of one module directory at one tree hash: its manifest, its lock files' hex sha256 -// by name (none when it has none) and the mesh packages its go.sum names (novox/hq ADR 0573 §2). PackagesRead says the -// packages were read: a value kept before the bridge read them is not taken, since its packages are not known. +// Inputs is what the bridge read of one module directory at one tree hash: its manifest and its lock files' hex sha256 +// by name (none when it has none). The bridge reads no mesh package (novox/hq ADR 0593 §2: only the indexer computes +// what a fingerprint takes); a value kept with the packages an older bridge read is taken, and those are left. type Inputs struct { - Manifest string `json:"manifest"` - Locks map[string]string `json:"locks,omitempty"` - Packages []string `json:"packages,omitempty"` - PackagesRead bool `json:"packages-read,omitempty"` + Manifest string `json:"manifest"` + Locks map[string]string `json:"locks,omitempty"` } // Kept holds Inputs by a directory's git tree hash (the bridge's state bucket inputs). Get answers false for a tree it @@ -25,8 +23,8 @@ type Kept interface { } // keptInputs splits dirs into the inputs kept for their tree hash and the directories still to read from the forge. -func keptInputs(dirs []string, trees map[string]string, kept Kept) (manifests map[string]string, locks map[string]map[string]string, packages map[string][]string, read []string) { - manifests, locks, packages = map[string]string{}, map[string]map[string]string{}, map[string][]string{} +func keptInputs(dirs []string, trees map[string]string, kept Kept) (manifests map[string]string, locks map[string]map[string]string, read []string) { + manifests, locks = map[string]string{}, map[string]map[string]string{} for _, dir := range dirs { tree := trees[dir] if kept == nil || tree == "" { @@ -34,7 +32,7 @@ func keptInputs(dirs []string, trees map[string]string, kept Kept) (manifests ma continue } in, ok := kept.Get(tree) - if !ok || !in.PackagesRead { + if !ok { read = append(read, dir) continue } @@ -42,22 +40,19 @@ func keptInputs(dirs []string, trees map[string]string, kept Kept) (manifests ma if len(in.Locks) > 0 { locks[dir] = in.Locks } - if len(in.Packages) > 0 { - packages[dir] = in.Packages - } } - return manifests, locks, packages, read + return manifests, locks, read } // keep puts what was read of each directory under its tree hash. -func keep(dirs []string, trees map[string]string, manifests map[string]string, locks map[string]map[string]string, packages map[string][]string, kept Kept) { +func keep(dirs []string, trees map[string]string, manifests map[string]string, locks map[string]map[string]string, kept Kept) { if kept == nil { return } for _, dir := range dirs { raw, ok := manifests[dir] if tree := trees[dir]; ok && tree != "" { - kept.Put(tree, Inputs{Manifest: raw, Locks: locks[dir], Packages: packages[dir], PackagesRead: true}) + kept.Put(tree, Inputs{Manifest: raw, Locks: locks[dir]}) } } }