The checker's judge counts the old sections from the trunk case as the indexer does, so a change adding a section at 0 is refused at the merge check (issue 1966 D4)

This commit is contained in:
2026-11-03 15:14:28 +01:00
parent 28a6858863
commit 2fdb0516cd
2 changed files with 56 additions and 1 deletions
+35 -1
View File
@@ -189,6 +189,7 @@ const Unnamed = "(between manifests)"
func Request(r composer.Request) (composer.Verdict, error) {
v := composer.Verdict{V: composer.Version, SDK: Identity()}
seen := map[string]bool{}
counts := trunkOldSections(r)
for _, c := range r.Cases {
if seen[c.Name] {
return composer.Verdict{}, fmt.Errorf("the case %q is named twice", c.Name)
@@ -201,7 +202,7 @@ func Request(r composer.Request) (composer.Verdict, error) {
}
raws[name] = m.Raw
}
refused, unnamed := Shelf(raws, r.Predefined, 0)
refused, unnamed := ShelfCounting(raws, r.Predefined, 0, counts)
cv := composer.CaseVerdict{Name: c.Name, Manifests: map[string]composer.ManifestRead{}}
for name := range raws {
if problems := refused[name]; len(problems) > 0 {
@@ -218,6 +219,39 @@ func Request(r composer.Request) (composer.Verdict, error) {
return v, nil
}
// TrunkCase is the case of a request holding the catalogue as the trunk holds it (the checker's JudgeTrunk).
const TrunkCase = "trunk"
// trunkOldSections counts the old sections the modules accepted at the trunk use, as the indexer counts them from its
// verdicts (issue 1966 D4, ADR 0595 §11): a change is refused at the merge check exactly as at take-in (judged once, ADR
// 0578). Nil where the request holds no trunk case, which refuses no use of a section.
func trunkOldSections(r composer.Request) OldSectionCounts {
for _, c := range r.Cases {
if c.Name != TrunkCase {
continue
}
raws := map[string][]byte{}
for name, m := range c.Manifests {
if len(m.Raw) > 0 {
raws[name] = m.Raw
}
}
refused, _ := Shelf(raws, r.Predefined, 0)
var accepted []catalogue.Manifest
for name, raw := range raws {
if len(refused[name]) > 0 {
continue
}
if m, err := catalogue.Decode(raw); err == nil {
m.Module = name
accepted = append(accepted, m)
}
}
return CountOldSections(accepted)
}
return nil
}
var (
identityOnce sync.Once
identity string
@@ -86,6 +86,27 @@ func TestTheJudge(t *testing.T) {
v.Cases[0].Manifests["b"].Accepted || !strings.Contains(v.Cases[0].Manifests["b"].Refused, `requires "amqp"`) {
t.Fatalf("request: %+v %v", v, err)
}
// 1966/AC11: the checker's judge counts the old sections from the trunk case as the indexer does from its verdicts (the
// foundation left out): a change adding logs where no trunk module uses them is refused, the foundation's accepted, and
// state, which a trunk module uses, is accepted.
old := composer.Request{V: composer.Version, Cases: []composer.Case{
{Name: "change", Manifests: map[string]composer.Manifest{
"user": {Raw: json.RawMessage(`{"module":"user","version":"1","state":["x"]}`)},
"late": {Raw: json.RawMessage(`{"module":"late","version":"1","logs":[{"name":"l"}]}`)},
"newer": {Raw: json.RawMessage(`{"module":"newer","version":"1","state":["y"]}`)},
"mesh-grants": {Raw: json.RawMessage(`{"module":"mesh-grants","version":"1","logs":[{"name":"l"}]}`)}}},
{Name: "trunk", Manifests: map[string]composer.Manifest{
"user": {Raw: json.RawMessage(`{"module":"user","version":"1","state":["x"]}`)},
"mesh-grants": {Raw: json.RawMessage(`{"module":"mesh-grants","version":"1","logs":[{"name":"l"}]}`)}}}}}
ov, err := Request(old)
if err != nil {
t.Fatal(err)
}
got := ov.Cases[0].Manifests
if got["late"].Accepted || !strings.Contains(got["late"].Refused, "late uses the old section logs") ||
!got["newer"].Accepted || !got["user"].Accepted || !got["mesh-grants"].Accepted {
t.Errorf("the change's old sections: %+v", got)
}
r.Cases[0].Manifests["c"] = composer.Manifest{Digest: strings.Repeat("a", 64)}
if _, err := Request(r); err == nil {
t.Fatal("a manifest left as a digest was judged")