Judge a packaging module's news by plans that built it, over every plan since its build (hq ADR 0267, review)
A plan that closed without building a module hid a missed merge from it; a window of recent plans let an old closure back in once the plan that overtook it slid out; a merge the forge gave no time was acted on again every pass. A plan answering the merge's own commit is now a look at it, and clocks a little apart do not make a merge history.
This commit is contained in:
@@ -569,7 +569,13 @@ func mergeCandidates(m link.SourceMoved, entries []inventory.Entry,
|
||||
// build or plan of it after the merge already read the repository with the merge in it. Per
|
||||
// module, since a merge that moved only the module built from the repository says nothing
|
||||
// about the ones packaging it.
|
||||
if isHistory(m.MergedAt, lookedOf(read[e.Manifest.Module])) {
|
||||
// Judged with a margin for the forge's clock running behind the store's: too late a look
|
||||
// rebuilds once more, too early one would miss the merge.
|
||||
if lookedAtCommit(read[e.Manifest.Module], m.Commit) {
|
||||
continue
|
||||
}
|
||||
if looked := lookedOf(read[e.Manifest.Module]); !looked.IsZero() &&
|
||||
isHistory(m.MergedAt, looked.Add(-historyMargin)) {
|
||||
continue
|
||||
}
|
||||
packaging = append(packaging, e)
|
||||
@@ -578,6 +584,19 @@ func mergeCandidates(m link.SourceMoved, entries []inventory.Entry,
|
||||
return from, packaging, already
|
||||
}
|
||||
|
||||
// lookedAtCommit is whether a plan that built a module, or is building it, answered this merge commit.
|
||||
func lookedAtCommit(read []inventory.ReadRepository, commit string) bool {
|
||||
for _, r := range read {
|
||||
if slices.Contains(r.LookedAt, commit) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// historyMargin is how far a packaging module's last look is taken back before a merge is history for it.
|
||||
const historyMargin = time.Minute
|
||||
|
||||
// lookedOf is when a module packaging another repository was last looked at, as readForPlanning says.
|
||||
func lookedOf(read []inventory.ReadRepository) time.Time {
|
||||
var at time.Time
|
||||
@@ -761,8 +780,9 @@ func staleIn(read map[string][]inventory.ReadRepository, plans []inventory.Plan)
|
||||
}
|
||||
|
||||
// lookedAt is when a merge was last acted on for a module that packages another repository's source: its
|
||||
// newest build, or the newest plan that held it, whichever is later. A build asked after a merge clones that
|
||||
// repository with the merge in it, so an older merge is history for it.
|
||||
// newest build, or the newest plan that built it or is still building it, whichever is later. A build asked
|
||||
// after a merge clones that repository with the merge in it, so an older merge is history for it; a plan
|
||||
// that closed without building it looked at nothing.
|
||||
func lookedAt(name string, read []inventory.ReadRepository, plans []inventory.Plan) time.Time {
|
||||
var at time.Time
|
||||
for _, r := range read {
|
||||
@@ -771,7 +791,8 @@ func lookedAt(name string, read []inventory.ReadRepository, plans []inventory.Pl
|
||||
}
|
||||
}
|
||||
for _, p := range plans {
|
||||
if _, in := p.Modules[name]; in && p.Created.After(at) {
|
||||
s, in := p.Modules[name]
|
||||
if in && (p.Open() || (s != nil && s.State == "built")) && p.Created.After(at) {
|
||||
at = p.Created
|
||||
}
|
||||
}
|
||||
@@ -787,22 +808,35 @@ func readForPlanning(ctx context.Context, inv *inventory.Inventory) (map[string]
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plans, err := inv.RecentPlans(ctx, planLookBack)
|
||||
// Every plan since the oldest build whose source is recorded: one made after a module's build can have
|
||||
// overtaken it, however long ago, so no window of recent plans would do.
|
||||
var oldest time.Time
|
||||
for _, rs := range read {
|
||||
for _, r := range rs {
|
||||
if !r.Built.IsZero() && (oldest.IsZero() || r.Built.Before(oldest)) {
|
||||
oldest = r.Built
|
||||
}
|
||||
}
|
||||
}
|
||||
plans, err := inv.PlansSince(ctx, oldest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return planningView(read, plans), nil
|
||||
}
|
||||
|
||||
// planLookBack is how many recent plans judge whether a recorded build source is overtaken.
|
||||
const planLookBack = 500
|
||||
|
||||
// planningView is readForPlanning over what was read, so a test can hand it records.
|
||||
func planningView(read map[string][]inventory.ReadRepository, plans []inventory.Plan) map[string][]inventory.ReadRepository {
|
||||
stale := staleIn(read, plans)
|
||||
out := make(map[string][]inventory.ReadRepository, len(read))
|
||||
for name, rs := range read {
|
||||
looked := lookedAt(name, rs, plans)
|
||||
var commits []string
|
||||
for _, p := range plans {
|
||||
if st, in := p.Modules[name]; in && p.Commit != "" && (p.Open() || (st != nil && st.State == "built")) {
|
||||
commits = append(commits, p.Commit)
|
||||
}
|
||||
}
|
||||
var kept []inventory.ReadRepository
|
||||
for _, r := range rs {
|
||||
if stale[name] {
|
||||
@@ -811,7 +845,7 @@ func planningView(read map[string][]inventory.ReadRepository, plans []inventory.
|
||||
}
|
||||
r.Paths = nil
|
||||
}
|
||||
r.Looked = looked
|
||||
r.Looked, r.LookedAt = looked, commits
|
||||
kept = append(kept, r)
|
||||
}
|
||||
out[name] = kept
|
||||
|
||||
Reference in New Issue
Block a user