Skip to content

Commit ccd25bb

Browse files
ttaylorr-oaigitster
authored andcommitted
repack: retain cruft packs in MIDXs containing kept packs
When performing a geometric repack with 'repack.midxMustContainCruft' set to "false", Git uses '--stdin-packs=follow' to copy (once-cruft) objects needed for reachability closure out of cruft packs. .keep packs do not need to participate in that walk, though they *are* included in the resulting MIDX. A .keep pack can contain a commit that reaches an object whose only copy is in a cruft pack. When there is no previous MIDX and the repack writes a new pack, neither `midx_has_unknown_packs()` nor the `!names.nr` fallback require that cruft pack to be included. If the kept commit (or a descendant of it) is selected for bitmap coverage, the bitmap writer fails because the MIDX does not contain all of its reachable objects. Include cruft packs whenever the MIDX contains kept packs. This also retains cruft when the kept packs happen to have full closure, or when '--pack-kept-objects' lets the repack walk them. It avoids having to establish their closure before deciding which packs the MIDX needs. Add a test that packs the tip commit and its tree into a kept pack, leaving its parent in the cruft pack. The new commit's blob remains loose, making the geometric repack write a new pack and bypass the no-new-packs fallback. Verify that the repack succeeds and that we are able to successfully write a bitmap. Signed-off-by: Taylor Blau <ttaylorr@openai.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 2196564 commit ccd25bb

2 files changed

Lines changed: 25 additions & 0 deletions

File tree

‎repack-midx.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ static void midx_included_packs(struct string_list *include,
197197
}
198198

199199
if (opts->midx_must_contain_cruft ||
200+
existing->kept_packs.nr ||
200201
midx_has_unknown_packs(include, geometry, existing)) {
201202
/*
202203
* If there are one or more unknown pack(s) present (see
@@ -209,6 +210,10 @@ static void midx_included_packs(struct string_list *include,
209210
* reachability closure if the MIDX is bitmapped and one
210211
* or more of the bitmap's selected commits reaches a
211212
* once-cruft object that was later made reachable.
213+
*
214+
* Kept packs may also depend on cruft objects, since
215+
* they are included above without necessarily being
216+
* traversed by the repack.
212217
*/
213218
for_each_string_list_item(item, &existing->cruft_packs) {
214219
/*

‎t/t7704-repack-cruft.sh‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,26 @@ test_expect_success 'incremental repack includes cruft for MIDX bitmaps' '
798798
)
799799
'
800800

801+
test_expect_success 'geometric repack includes cruft for kept packs' '
802+
setup_cruft_exclude_tests kept-cruft &&
803+
(
804+
cd kept-cruft &&
805+
806+
# Keep HEAD and its tree outside the geometric repack. Its
807+
# parent is reachable again, but still in the cruft pack.
808+
git rev-parse HEAD HEAD^{tree} >objects &&
809+
pack=$(git pack-objects $packdir/pack <objects) &&
810+
touch $packdir/pack-$pack.keep &&
811+
git prune-packed &&
812+
813+
# The new blob is still loose, so this writes a pack instead
814+
# of taking the no-new-packs fallback.
815+
GIT_TEST_MULTI_PACK_INDEX=0 \
816+
git repack -d --geometric=2 --write-midx --write-bitmap-index &&
817+
git rev-list --test-bitmap HEAD
818+
)
819+
'
820+
801821
test_expect_success 'repack --write-midx includes cruft when instructed' '
802822
setup_cruft_exclude_tests exclude-cruft-when-instructed &&
803823
(

0 commit comments

Comments
 (0)