Keep a group member of the other kind's batch from being overtaken (hq issue 525)
A merge's group member counted as merged when its merge waited in any batch, but kinds never share a batch: the later member got a batch of its own, cut at once, and walked before the earlier member's batch was cut, breaking the group's order (ADR 0276 §5). Only a member kept in a batch of the merge's own kind counts as merged now; one kept in the other kind's keeps the merge waiting, and its batch names that member, so the two are cut in the order their windows close (review of #250).
This commit is contained in:
@@ -84,14 +84,29 @@ func memberOf(s string) groupMember {
|
||||
}
|
||||
|
||||
// groupWait says whether a merge heard now waits for the window for its delivery group, and why in words; nothing
|
||||
// when it names no head, its head names no group, or every other member is merged or closed. A member of another
|
||||
// repository whose merge this controller already keeps in a batch not yet cut is merged, whatever mesh-delivery
|
||||
// says yet (it marks a member merged once its walk opened). Asked before the plans are held: a slow answer holds
|
||||
// up no walk.
|
||||
func groupWait(ctx context.Context, inv *inventory.Inventory, m link.SourceMoved, held bool) (string, error) {
|
||||
// when it names no head, its head names no group, or every other member is merged or closed. own is the merge's
|
||||
// kind (ownPath).
|
||||
//
|
||||
// A member of another repository whose merge this controller already keeps in a batch not yet cut of the same
|
||||
// kind is merged, whatever mesh-delivery says yet (it marks a member merged once its walk opened): the merge joins
|
||||
// that batch by their head. One kept in a batch of the other kind keeps the merge waiting, whatever mesh-delivery
|
||||
// says (review of #250): kinds never share a batch, so the merge's batch is a new one, and cut at once it would
|
||||
// walk before that member's batch is cut and break the group's order (ADR 0276 decision 5). Waiting, the two
|
||||
// batches are cut in the order their windows close, an own-path one first at one look, as cutBatchesHeld cuts
|
||||
// every pair of kinds.
|
||||
//
|
||||
// Asked before the plans are held: a slow answer holds up no walk.
|
||||
func groupWait(ctx context.Context, inv *inventory.Inventory, m link.SourceMoved, held, own bool) (string, error) {
|
||||
if m.Head == "" {
|
||||
return "", nil
|
||||
}
|
||||
same, other, err := keptFromHead(ctx, inv, m.Head, own)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(other) > 0 {
|
||||
return "group " + m.Head + " has a member waiting in a batch of the other kind: " + strings.Join(other, ", "), nil
|
||||
}
|
||||
members, isGroup, err := deliveryGroupOf(ctx, held, m.Head)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("%s did not say whether group %s has a member still to merge (%v): it waits for the "+
|
||||
@@ -100,13 +115,9 @@ func groupWait(ctx context.Context, inv *inventory.Inventory, m link.SourceMoved
|
||||
if !isGroup {
|
||||
return "", nil
|
||||
}
|
||||
kept, err := keptFromHead(ctx, inv, m.Head)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var open []string
|
||||
for _, g := range members {
|
||||
if strings.EqualFold(g.Repository, m.Owner+"/"+m.Repo) || kept[strings.ToLower(g.Repository)] ||
|
||||
if strings.EqualFold(g.Repository, m.Owner+"/"+m.Repo) || same[strings.ToLower(g.Repository)] ||
|
||||
!openPullStates[g.State] {
|
||||
continue
|
||||
}
|
||||
@@ -118,23 +129,30 @@ func groupWait(ctx context.Context, inv *inventory.Inventory, m link.SourceMoved
|
||||
return "group " + m.Head + " has a member still to merge: " + strings.Join(open, ", "), nil
|
||||
}
|
||||
|
||||
// keptFromHead are the repositories (lower case) of the merges from a head that batches not yet cut hold.
|
||||
func keptFromHead(ctx context.Context, inv *inventory.Inventory, head string) (map[string]bool, error) {
|
||||
// keptFromHead are the merges from a head that batches not yet cut hold: the repositories (lower case) of those in
|
||||
// a batch of the kind own says, and, in words, each of the other kind with its batch.
|
||||
func keptFromHead(ctx context.Context, inv *inventory.Inventory, head string, own bool) (map[string]bool, []string, error) {
|
||||
batches, err := inv.Batches(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
out := map[string]bool{}
|
||||
same := map[string]bool{}
|
||||
var other []string
|
||||
for _, b := range batches {
|
||||
merges, err := inv.MergesOf(ctx, b.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, k := range merges {
|
||||
if announcedOf(k).Head == head {
|
||||
out[strings.ToLower(k.Repository)] = true
|
||||
if announcedOf(k).Head != head {
|
||||
continue
|
||||
}
|
||||
if b.OwnPath() == own {
|
||||
same[strings.ToLower(k.Repository)] = true
|
||||
} else {
|
||||
other = append(other, fmt.Sprintf("%s@%s in %s", k.Repository, short(k.Commit), b.ID))
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
return same, other, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user