From 413dd13fe35d6ac97f00b76fe584ea1da6c37274 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 28 Oct 2026 16:34:43 +0100 Subject: [PATCH] Accept a merged message with no trees, so a merge that leaves a repository with no module.json still reaches the indexer (issue 1126) --- go/delivery/source.go | 7 ++++--- go/delivery/source_test.go | 10 ++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/go/delivery/source.go b/go/delivery/source.go index b39596a..99a4f68 100644 --- a/go/delivery/source.go +++ b/go/delivery/source.go @@ -688,9 +688,10 @@ func (f Forge) check() error { if f.Root == "" { return fmt.Errorf("delivery: a merged message needs the repository's root tree") } - if len(f.Trees) == 0 { - return fmt.Errorf("delivery: a merged message needs the tree of at least one directory holding a module.json") - } + // No trees is a merge that leaves the repository with no module.json anywhere (a documents repository, or one + // whose last module was removed): it is written all the same, so the indexer takes the merge in and drops the + // repository's modules (novox/hq issue 1126). An older writer always sent at least one tree, so none is unambiguous; + // such a message carries no manifests, locks or paths (checkInputs below: each names a directory of its trees). for dir, tree := range f.Trees { if tree == "" { return fmt.Errorf("delivery: a merged message's tree of the directory %q is empty", dir) diff --git a/go/delivery/source_test.go b/go/delivery/source_test.go index 33d1c12..1c90a60 100644 --- a/go/delivery/source_test.go +++ b/go/delivery/source_test.go @@ -272,9 +272,15 @@ func TestSourceValuesRefused(t *testing.T) { // 1200/AC4 _, err = EncodeForge(f) wantErr("merged without root", err, "root") f = sampleForges()[1] - f.Trees = nil + f.Trees, f.Manifests, f.Locks, f.Paths = nil, nil, nil, nil + if data, err := EncodeForge(f); err != nil { + t.Errorf("a merged message of a repository with no module.json is refused: %v", err) + } else if got, err := DecodeForge(data); err != nil || len(got.Trees) != 0 { + t.Errorf("a merged message with no trees comes back as %+v, %v", got, err) + } + f.Manifests = map[string]string{"modules/a": "{}"} _, err = EncodeForge(f) - wantErr("merged without trees", err, "tree") + wantErr("merged with a manifest and no trees", err, "modules/a") f = sampleForges()[1] f.Trees = map[string]string{"modules/a": ""} _, err = EncodeForge(f)