[PATCH v3 8/8] commit-reach: move min_generation check into paint_queue_get()
From: Kristofer Karlsson via GitGitGadget <hidden>
Date: 2026-06-26 13:08:17
Subsystem:
documentation, the rest · Maintainers:
Jonathan Corbet, Linus Torvalds
From: Kristofer Karlsson <redacted> Consolidate the min_generation termination condition into paint_queue_get(), alongside the existing stale-entry and side-exhaustion checks. Move last_gen into struct paint_state so that commit_graph_generation() is called exactly once per dequeued commit and the result is shared across all termination checks and the monotonicity BUG assertion. The loop body in paint_down_to_common() reads state.last_gen instead of recomputing the generation number. Signed-off-by: Kristofer Karlsson <redacted> --- .../technical/paint-down-to-common.adoc | 9 ++++++ commit-reach.c | 31 +++++++++++-------- 2 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/Documentation/technical/paint-down-to-common.adoc b/Documentation/technical/paint-down-to-common.adoc
index 983dfcf233..eef249f4a4 100644
--- a/Documentation/technical/paint-down-to-common.adoc
+++ b/Documentation/technical/paint-down-to-common.adoc@@ -97,6 +97,8 @@ ends when one of the following conditions holds: 3. Side exhaustion: no pure PARENT1 or pure PARENT2 commits remain in the queue, no pending merge-base candidates exist, and the walk has entered the finite-generation region. + 4. Generation cutoff: the dequeued commit's generation is below + a caller-supplied `min_generation` threshold. Stale entry condition ~~~~~~~~~~~~~~~~~~~~~
@@ -121,6 +123,13 @@ time and an exhausted side cannot reappear. In the INFINITY region, commit-date ordering can violate this guarantee, so the check is skipped. +Generation cutoff +~~~~~~~~~~~~~~~~~ +Some callers (notably `remove_redundant()`) supply a `min_generation` +threshold -- the minimum generation of the input commits. No merge +base can have a generation below this threshold, so the walk +terminates as soon as it dequeues such a commit. + Related documentation ---------------------
diff --git a/commit-reach.c b/commit-reach.c
index 0248d6fedb..0cd785c31b 100644
--- a/commit-reach.c
+++ b/commit-reach.c@@ -89,6 +89,8 @@ struct paint_state { int p1_count; int p2_count; int pending_merge_bases; + timestamp_t min_generation; + timestamp_t last_gen; }; static void paint_count_update(struct paint_state *state,
@@ -138,11 +140,23 @@ static void paint_queue_put(struct paint_state *state, static struct commit *paint_queue_get(struct paint_state *state) { struct commit *commit = prio_queue_get(&state->queue); + timestamp_t generation; if (!commit) return NULL; commit->object.flags &= ~ENQUEUED; + generation = commit_graph_generation(commit); + + if (generation > state->last_gen) + BUG("bad generation skip %"PRItime" > %"PRItime" at %s", + generation, state->last_gen, + oid_to_hex(&commit->object.oid)); + state->last_gen = generation; + + /* generation cutoff */ + if (generation < state->min_generation) + return NULL; if (!state->pending_merge_bases) { /* only stale entries remain */
@@ -151,7 +165,7 @@ static struct commit *paint_queue_get(struct paint_state *state) /* one side is exhausted */ if ((!state->p1_count || !state->p2_count) && - commit_graph_generation(commit) < GENERATION_NUMBER_INFINITY) + generation < GENERATION_NUMBER_INFINITY) return NULL; }
@@ -177,9 +191,10 @@ static int paint_down_to_common(struct repository *r, struct commit *commit; int i; int steps = 0; - timestamp_t last_gen = GENERATION_NUMBER_INFINITY; struct commit_list **tail = result; + state.min_generation = min_generation; + state.last_gen = GENERATION_NUMBER_INFINITY; if (!min_generation && !corrected_commit_dates_enabled(r)) state.queue.compare = compare_commits_by_commit_date;
@@ -196,18 +211,8 @@ static int paint_down_to_common(struct repository *r, while ((commit = paint_queue_get(&state))) { struct commit_list *parents; int flags; - timestamp_t generation = commit_graph_generation(commit); steps++; - if (generation > last_gen) - BUG("bad generation skip %"PRItime" > %"PRItime" at %s", - generation, last_gen, - oid_to_hex(&commit->object.oid)); - last_gen = generation; - - if (generation < min_generation) - break; - flags = commit->object.flags & (PARENT1 | PARENT2 | STALE); if (flags == (PARENT1 | PARENT2)) { if (!(commit->object.flags & RESULT)) {
@@ -219,7 +224,7 @@ static int paint_down_to_common(struct repository *r, * descendant of this one. */ if (!(mb_flags & MERGE_BASE_FIND_ALL) && - generation < GENERATION_NUMBER_INFINITY) + state.last_gen < GENERATION_NUMBER_INFINITY) break; } /* Mark parents of a found merge stale */
--
gitgitgadget