diff --git a/modules/mesh-delivery-indexer/internal/index/pending.go b/modules/mesh-delivery-indexer/internal/index/pending.go index 9999039f..08128919 100644 --- a/modules/mesh-delivery-indexer/internal/index/pending.go +++ b/modules/mesh-delivery-indexer/internal/index/pending.go @@ -1307,7 +1307,23 @@ func (ix *Indexer) DropPending(ctx context.Context, key, by, why string, abandon } e := entries[at] if !abandon { - covered := slices.ContainsFunc(entries[at+1:], func(o PendingEntry) bool { return o.Forge.Repository == e.Forge.Repository }) + // Covered: a later merge of the same repository, pending or taken in, has this merge's commit as an ancestor (ADR + // 0668 §6), asked of the forge (older); a later merge whose history does not hold it covers nothing. + covered := false + for _, o := range entries[at+1:] { + if o.Forge.Repository != e.Forge.Repository { + continue + } + in, err := ix.older(ctx, e.Forge.Repository, e.Forge.Merge, o.Forge.Merge) + if err != nil { + r.Answer = fmt.Sprintf("%s is not dropped: whether the later pending merge %s covers it is not read: %v", key, o.Key, err) + return r + } + if in { + covered = true + break + } + } if !covered { taken, err := ix.takenAlready(ctx, forgemsg.GroupMerge{Repository: e.Forge.Repository, Number: e.Forge.Number, Merge: e.Forge.Merge}) if err != nil { @@ -1317,7 +1333,7 @@ func (ix *Indexer) DropPending(ctx context.Context, key, by, why string, abandon covered = taken } if !covered { - r.Answer = fmt.Sprintf("%s is not dropped: no later merge of %s is pending and its taken merge does not cover %s, so its "+ + r.Answer = fmt.Sprintf("%s is not dropped: no later merge of %s, pending or taken in, has %s as an ancestor, so its "+ "changes would never be taken in (ADR 0633 §5); %s reads its message again, or abandon: true drops it all the same", key, e.Forge.Repository, e.Forge.Merge, TakeInPendingTool) return r diff --git a/modules/mesh-delivery-indexer/internal/index/pending_test.go b/modules/mesh-delivery-indexer/internal/index/pending_test.go index c0bd87e8..e41d3c03 100644 --- a/modules/mesh-delivery-indexer/internal/index/pending_test.go +++ b/modules/mesh-delivery-indexer/internal/index/pending_test.go @@ -711,6 +711,17 @@ func TestTakeIn(t *testing.T) { // 1585/T3-T13 (ADR 0633) answer.Waits[0].Said != takein.TakeInPendingEvent || len(answer.Waits[0].Keys) != 2 { t.Fatalf("indexer_pending = %+v", answer) } + // ADR 0668 §6: a later merge covers a pending one only when its commit has the pending merge's as an ancestor. + history := "cd" + b.ix.Contains = func(_ context.Context, _, commit, in string) (bool, error) { + i, j := strings.IndexByte(history, commit[0]), strings.IndexByte(history, in[0]) + return i >= 0 && j >= 0 && i <= j, nil + } + history = "dc" // m.3's commit is not in m.2's later history (a history rewritten) + if r := b.ix.DropPending(ctx, takein.PendingKey(2), "lead@shanks", "replaced by m.3", false); r.Stored || !strings.Contains(r.Answer, "as an ancestor") { + t.Fatalf("a drop a later merge not holding it would cover: %+v", r) + } + history = "cd" b.said = nil if r := b.ix.DropPending(ctx, takein.PendingKey(2), "lead@shanks", "replaced by m.3", false); !r.Stored { t.Fatalf("drop: %+v", r)