From 3e38d04bd41791c8f50e008adb5cb09f876d4edf Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Fri, 26 Jun 2026 15:02:20 -0400 Subject: [PATCH] repack: mark geometric progression of packs as retained In non-geometric repacks, any packs which repack wishes to delete are handled via the `existing_packs` struct, which has a mechanism to retain would-be-deleted packs (e.g., if we happened to write a new pack identical to one otherwise marked for deletion). In geometric repacks, repack removes any rewritten packs (alternatively, any packs which were combined in order to restore a geometric progression) by enumerating them via `pack_geometry_remove_redundant()`. Prepare to use the `existing_packs` deletion machinery for geometric repacks by marking any non-kept packs above the geometric split line as retained. Do the same for promisor packs, which have their own split point. This commit only records which packs the later deletion pass must keep; it does not change which packs are written or removed. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- builtin/repack.c | 2 ++ repack.c | 27 +++++++++++++++++++++++++++ repack.h | 3 +++ 3 files changed, 32 insertions(+) diff --git a/builtin/repack.c b/builtin/repack.c index 1524a9c13a..ce979d86d9 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -325,6 +325,8 @@ int cmd_repack(int argc, } pack_geometry_init(&geometry, &existing, &po_args); pack_geometry_split(&geometry); + + existing_packs_retain_from_geometry(&existing, &geometry); } prepare_pack_objects(&cmd, &po_args, packtmp); diff --git a/repack.c b/repack.c index 986c74ac7e..9b3cb42543 100644 --- a/repack.c +++ b/repack.c @@ -254,6 +254,33 @@ void existing_packs_retain_cruft(struct existing_packs *existing, existing_packs_mark_retained(item); } +static void existing_packs_retain_non_kept(struct existing_packs *existing, + struct packed_git *p) +{ + struct string_list_item *item; + + if (!p->pack_local) + return; + + item = locate_existing_pack(&existing->non_kept_packs, p); + if (!item) + BUG("could not find non-kept pack '%s'", pack_basename(p)); + + existing_packs_mark_retained(item); +} + +void existing_packs_retain_from_geometry(struct existing_packs *existing, + const struct pack_geometry *geometry) +{ + uint32_t i; + + for (i = geometry->split; i < geometry->pack_nr; i++) + existing_packs_retain_non_kept(existing, geometry->pack[i]); + for (i = geometry->promisor_split; i < geometry->promisor_pack_nr; i++) + existing_packs_retain_non_kept(existing, + geometry->promisor_pack[i]); +} + void existing_packs_mark_for_deletion(struct existing_packs *existing, struct string_list *names) diff --git a/repack.h b/repack.h index f9fbc895f0..bb4c944d0c 100644 --- a/repack.h +++ b/repack.h @@ -54,6 +54,7 @@ int finish_pack_objects_cmd(const struct git_hash_algo *algop, struct repository; struct packed_git; +struct pack_geometry; struct existing_packs { struct repository *repo; @@ -82,6 +83,8 @@ int existing_packs_has_non_kept(const struct existing_packs *existing); int existing_pack_is_marked_for_deletion(struct string_list_item *item); void existing_packs_retain_cruft(struct existing_packs *existing, struct packed_git *cruft); +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);