From 9f7f50de8d1d91bb8f677ca04057ecdd7b2c4dd2 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 26 Oct 2026 18:08:59 +0100 Subject: [PATCH] =?UTF-8?q?A=20merged=20message=20of=20the=20catalogue=20c?= =?UTF-8?q?arries=20its=20placement=20files,=20so=20the=20indexer=20reads?= =?UTF-8?q?=20placement=20at=20the=20merge=20without=20asking=20the=20forg?= =?UTF-8?q?e=20again=20(issue=201126,=20ADR=200549=20=C2=A72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go/delivery/forge_inputs_test.go | 12 ++++++++---- go/delivery/source.go | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/go/delivery/forge_inputs_test.go b/go/delivery/forge_inputs_test.go index e027ff7..802aa77 100644 --- a/go/delivery/forge_inputs_test.go +++ b/go/delivery/forge_inputs_test.go @@ -9,9 +9,10 @@ const oddManifest = "{\n\t\"module\": \"a\",\n \"z\": 1, \"a\": [ \"x\",\"y\" func mergedWithInputs() Forge { return Forge{Kind: ForgeMerged, Repository: "novox/mesh-sdk", Number: 36, Head: "aaaa", Merge: "cccc", Root: "t0", - Trees: map[string]string{"a": "t1", "b": "t2"}, - Manifests: map[string]string{"a": oddManifest}, - Locks: map[string]map[string]string{"a": {"go.sum": strings.Repeat("ab", 32)}}} + Trees: map[string]string{"a": "t1", "b": "t2"}, + Manifests: map[string]string{"a": oddManifest}, + Locks: map[string]map[string]string{"a": {"go.sum": strings.Repeat("ab", 32)}}, + Placements: map[string]string{"ace": `{"v":1,"node":"ace","modules":[]}`}, PlacementsRead: true} } // 1442/AC1 @@ -21,7 +22,7 @@ func TestForgeMergedCarriesManifestsAndLocks(t *testing.T) { if err != nil { t.Fatal(err) } - for _, frag := range []string{`"manifests":{"a":`, `"locks":{"a":{"go.sum":`} { + for _, frag := range []string{`"manifests":{"a":`, `"locks":{"a":{"go.sum":`, `"placements":{"ace":`, `"placements-read":true`} { if !strings.Contains(string(data), frag) { t.Errorf("the encoding lacks %s: %s", frag, data) } @@ -47,6 +48,9 @@ func TestForgeMergedRefusesBadInputs(t *testing.T) { "locks outside trees": {func(f *Forge) { f.Locks["yy"] = map[string]string{"go.sum": "h"} }, `"yy"`}, "empty manifest": {func(f *Forge) { f.Manifests["b"] = "" }, `"b"`}, "empty lock hash": {func(f *Forge) { f.Locks["a"]["go.sum"] = "" }, `"a"`}, + "placements unsaid": {func(f *Forge) { f.PlacementsRead = false }, "placements-read"}, + "placement of no node": {func(f *Forge) { f.Placements["a.b"] = "{}" }, "names no node"}, + "placements on a pull": {func(f *Forge) { f.Kind, f.Action, f.Merge, f.Root, f.Trees = ForgePull, PullOpened, "", "", nil }, "only a merged message"}, } { f := mergedWithInputs() tc.mut(&f) diff --git a/go/delivery/source.go b/go/delivery/source.go index 535f771..71b4de1 100644 --- a/go/delivery/source.go +++ b/go/delivery/source.go @@ -537,6 +537,11 @@ type Forge struct { Act string `json:"act,omitempty"` Words string `json:"words,omitempty"` Open []OpenPull `json:"open,omitempty"` + // Placements are, on a merged message of the catalogue repository, every placement file of the merge commit, the + // bytes exact, by node (PlacementFile; novox/hq ADR 0549 ยง2), and PlacementsRead says they were read, so a catalogue + // whose last placement file was removed is told from a message that read none (older writers, another repository). + Placements map[string]string `json:"placements,omitempty"` + PlacementsRead bool `json:"placements-read,omitempty"` } func (f Forge) check() error { @@ -549,6 +554,17 @@ func (f Forge) check() error { if len(f.Open) > 0 { return fmt.Errorf("delivery: only an open message names open pull requests") } + if (len(f.Placements) > 0 || f.PlacementsRead) && f.Kind != ForgeMerged { + return fmt.Errorf("delivery: only a merged message carries placement files") + } + if len(f.Placements) > 0 && !f.PlacementsRead { + return fmt.Errorf("delivery: a message with placement files must say it read them (placements-read)") + } + for node := range f.Placements { + if err := checkName("node", node); err != nil { + return fmt.Errorf("delivery: a placement file names no node: %w", err) + } + } if err := checkRepository(f.Repository); err != nil { return err }