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 <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
seen
Taylor Blau 2026-06-26 15:02:20 -04:00 committed by Junio C Hamano
parent d65798abb7
commit 3e38d04bd4
3 changed files with 32 additions and 0 deletions

View File

@ -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);

View File

@ -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)


View File

@ -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);