From 5ff781e9fa3cfea4ac008c7e0e06a5f720b78060 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Fri, 26 Jun 2026 15:02:23 -0400 Subject: [PATCH] repack: teach MIDX retention about geometric rollups When writing an incremental MIDX, existing_packs_retain_midx_packs() marks packs in the existing MIDX chain as retained. This keeps them from being deleted by the later existing_packs deletion pass, since retained MIDX layers may still refer to those packs. Geometric repacks need a narrower rule. Packs below the split are rolled up into the newly-written pack, and should remain eligible for deletion even if the old MIDX chain mentions them. Packs above the split were marked as retained by the previous commit. Teach existing_packs_retain_midx_packs() to skip packs which are part of the geometric rollup. This does not change the current caller's behavior, since geometric repacks do not yet use the existing_packs deletion path. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- builtin/repack.c | 2 +- repack.c | 43 +++++++++++++++++++++++++++++++++++++++++-- repack.h | 3 ++- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/builtin/repack.c b/builtin/repack.c index ce979d86d9..66b46b8689 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -576,7 +576,7 @@ int cmd_repack(int argc, if (delete_redundant && pack_everything & ALL_INTO_ONE) { if (write_midx == REPACK_WRITE_MIDX_INCREMENTAL) - existing_packs_retain_midx_packs(&existing); + existing_packs_retain_midx_packs(&existing, &geometry); existing_packs_mark_for_deletion(&existing, &names); } diff --git a/repack.c b/repack.c index 9b3cb42543..c7b79a3c11 100644 --- a/repack.c +++ b/repack.c @@ -292,6 +292,39 @@ void existing_packs_mark_for_deletion(struct existing_packs *existing, &existing->cruft_packs); } +static int pack_geometry_contains_pack(struct packed_git **packs, + uint32_t packs_nr, + const char *base) +{ + struct strbuf buf = STRBUF_INIT; + uint32_t i; + + for (i = 0; i < packs_nr; i++) { + strbuf_reset(&buf); + strbuf_addstr(&buf, pack_basename(packs[i])); + strbuf_strip_suffix(&buf, ".pack"); + + if (!strcmp(buf.buf, base)) { + strbuf_release(&buf); + return 1; + } + } + + strbuf_release(&buf); + return 0; +} + +static int pack_geometry_contains_rollup(const struct pack_geometry *geometry, + const char *base) +{ + if (!geometry || !geometry->split_factor) + return 0; + + return pack_geometry_contains_pack(geometry->pack, geometry->split, base) || + pack_geometry_contains_pack(geometry->promisor_pack, + geometry->promisor_split, base); +} + /* * Mark every pack that is referenced by the existing MIDX chain as * retained, so that a subsequent call to @@ -300,9 +333,12 @@ void existing_packs_mark_for_deletion(struct existing_packs *existing, * This is used when writing an incremental MIDX layer on top of an * existing chain: retained layers continue to reference the same * packs on disk, so those packs must not be unlinked even if the - * freshly-written pack supersedes them. + * freshly-written pack supersedes them. When doing a geometric repack, + * packs below the split are rewritten into the new MIDX tip and should + * remain eligible for deletion. */ -void existing_packs_retain_midx_packs(struct existing_packs *existing) +void existing_packs_retain_midx_packs(struct existing_packs *existing, + const struct pack_geometry *geometry) { struct string_list_item *item; struct strbuf buf = STRBUF_INIT; @@ -315,6 +351,9 @@ void existing_packs_retain_midx_packs(struct existing_packs *existing) strbuf_strip_suffix(&buf, ".pack"); strbuf_strip_suffix(&buf, ".idx"); + if (pack_geometry_contains_rollup(geometry, buf.buf)) + continue; + found = string_list_lookup(&existing->non_kept_packs, buf.buf); if (found) existing_packs_mark_retained(found); diff --git a/repack.h b/repack.h index bb4c944d0c..f0d082df9e 100644 --- a/repack.h +++ b/repack.h @@ -87,7 +87,8 @@ void existing_packs_retain_from_geometry(struct existing_packs *existing, const struct pack_geometry *geometry); void existing_packs_mark_for_deletion(struct existing_packs *existing, struct string_list *names); -void existing_packs_retain_midx_packs(struct existing_packs *existing); +void existing_packs_retain_midx_packs(struct existing_packs *existing, + const struct pack_geometry *geometry); void existing_packs_remove_redundant(struct existing_packs *existing, const char *packdir, bool wrote_incremental_midx);