aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--builtin/repack.c23
-rwxr-xr-xt/t5329-pack-objects-cruft.sh26
2 files changed, 46 insertions, 3 deletions
diff --git a/builtin/repack.c b/builtin/repack.c
index 36d1f03671..15071fadbe 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -23,6 +23,7 @@
#define PACK_CRUFT 4
#define DELETE_PACK 1
+#define CRUFT_PACK 2
static int pack_everything;
static int delta_base_offset = 1;
@@ -159,10 +160,15 @@ static void collect_pack_filenames(struct string_list *fname_nonkept_list,
fname = xmemdupz(e->d_name, len);
if ((extra_keep->nr > 0 && i < extra_keep->nr) ||
- (file_exists(mkpath("%s/%s.keep", packdir, fname))))
+ (file_exists(mkpath("%s/%s.keep", packdir, fname)))) {
string_list_append_nodup(fname_kept_list, fname);
- else
- string_list_append_nodup(fname_nonkept_list, fname);
+ } else {
+ struct string_list_item *item;
+ item = string_list_append_nodup(fname_nonkept_list,
+ fname);
+ if (file_exists(mkpath("%s/%s.mtimes", packdir, fname)))
+ item->util = (void*)(uintptr_t)CRUFT_PACK;
+ }
}
closedir(dir);
}
@@ -564,6 +570,17 @@ static void midx_included_packs(struct string_list *include,
string_list_insert(include, strbuf_detach(&buf, NULL));
}
+
+ for_each_string_list_item(item, existing_nonkept_packs) {
+ if (!((uintptr_t)item->util & CRUFT_PACK)) {
+ /*
+ * no need to check DELETE_PACK, since we're not
+ * doing an ALL_INTO_ONE repack
+ */
+ continue;
+ }
+ string_list_insert(include, xstrfmt("%s.idx", item->string));
+ }
} else {
for_each_string_list_item(item, existing_nonkept_packs) {
if ((uintptr_t)item->util & DELETE_PACK)
diff --git a/t/t5329-pack-objects-cruft.sh b/t/t5329-pack-objects-cruft.sh
index c82f973b41..8de87afce2 100755
--- a/t/t5329-pack-objects-cruft.sh
+++ b/t/t5329-pack-objects-cruft.sh
@@ -648,4 +648,30 @@ test_expect_success 'cruft --local drops unreachable objects' '
)
'
+test_expect_success 'MIDX bitmaps tolerate reachable cruft objects' '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit reachable &&
+ test_commit cruft &&
+ unreachable="$(git rev-parse cruft)" &&
+
+ git reset --hard $unreachable^ &&
+ git tag -d cruft &&
+ git reflog expire --all --expire=all &&
+
+ git repack --cruft -d &&
+
+ # resurrect the unreachable object via a new commit. the
+ # new commit will get selected for a bitmap, but be
+ # missing one of its parents from the selected packs.
+ git reset --hard $unreachable &&
+ test_commit resurrect &&
+
+ git repack --write-midx --write-bitmap-index --geometric=2 -d
+ )
+'
+
test_done