builtin/repack: actually drop filtered promisor blobs

Make --drop-filtered remove the enumerated promisor blobs instead of
only listing them.

The drop set is computed before repack_promisor_objects() runs, and on
a real run it is passed in so the rebuilt promisor pack omits those
blobs. --drop-filtered implies -d so the old promisor packs, which
still contain the dropped blobs, are removed. Without this the blobs
would survive in the redundant packs. The existing repack machinery
performs the write-before-delete and fsync, so the drop is crash-safe.

The dropped blobs become absent locally but remain recoverable from the
promisor remote, so a later access lazy-fetches them back
transparently. --dry-run keeps its previous behavior, i.e. it lists the
candidates and changes nothing.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Siddharth Asthana <siddharthasthana31@gmail.com>
Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Siddharth Shrimali
2026-08-06 16:52:00 +05:30
committed by Junio C Hamano
parent 0bed9fda6c
commit 79f361aeb1
3 changed files with 23 additions and 4 deletions

View File

@@ -286,9 +286,6 @@ int cmd_repack(int argc,
die(_("--dry-run only takes effect with --drop-filtered"));
if (drop_filtered) {
if (!dry_run)
die(_("--drop-filtered doesn't work without --dry-run yet"));
if (!po_args.filter_options.choice)
die(_("--drop-filtered requires --filter"));
@@ -321,6 +318,14 @@ int cmd_repack(int argc,
write_bitmaps = 0;
/*
* Dropping objects means rebuilding the promisor packs
* without them and then removing the old packs, so the
* redundant packs must be deleted. Imply -d on a real run.
*/
if (!dry_run)
delete_redundant = 1;
ret = enumerate_promisor_blobs(repo, &po_args.filter_options, &drop_oids);
if (ret)
@@ -446,7 +451,8 @@ int cmd_repack(int argc,
strvec_push(&cmd.args, "--delta-islands");
if (pack_everything & ALL_INTO_ONE) {
repack_promisor_objects(repo, &po_args, &names, packtmp, NULL);
repack_promisor_objects(repo, &po_args, &names, packtmp,
(drop_filtered && !dry_run) ? &drop_oids : NULL);
if (existing_packs_has_non_kept(&existing) &&
delete_redundant &&

View File

@@ -120,6 +120,7 @@ int enumerate_promisor_blobs(struct repository *repo,
/*
* Apply the filter to find which blobs exceed the threshold.
* The caller has to_drop and is responsible for clearing it.
*/
ret = list_objects_filter__filter_oidset(repo,
(struct list_objects_filter_options *)filter,

View File

@@ -134,4 +134,16 @@ test_expect_success '--dry-run does not remove the filtered objects' '
git -C repo cat-file -e "$BIG"
'
test_expect_success '--drop-filtered removes the promisor blob locally' '
BIG=$(cat big_oid) &&
SMALL=$(cat small_oid) &&
git -C repo -c repack.writeBitmaps=false \
repack --drop-filtered --filter=blob:limit=1k -a &&
git -C repo cat-file --batch-all-objects --batch-check="%(objectname)" >present &&
! grep -q "$BIG" present &&
grep -q "$SMALL" present
'
test_done