Skip to content

Commit e08f7bb

Browse files
ttaylorrgitster
authored andcommitted
builtin/repack.c: invalidate MIDX only when necessary
In 525e18c (midx: clear midx on repack, 2018-07-12), 'git repack' learned to remove a multi-pack-index file if it added or removed a pack from the object store. This mechanism is a little over-eager, since it is only necessary to drop a MIDX if 'git repack' removes a pack that the MIDX references. Adding a pack outside of the MIDX does not require invalidating the MIDX, and likewise for removing a pack the MIDX does not know about. Teach 'git repack' to check for this by loading the MIDX, and checking whether the to-be-removed pack is known to the MIDX. This requires a slightly odd alternation to a test in t5319, which is explained with a comment. A new test is added to show that the MIDX is left alone when both packs known to it are marked as .keep, but two packs unknown to it are removed and combined into one new pack. Helped-by: Derrick Stolee <[email protected]> Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 47ae905 commit e08f7bb

File tree

2 files changed

+47
-9
lines changed

2 files changed

+47
-9
lines changed

builtin/repack.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,11 @@ static void get_non_kept_pack_filenames(struct string_list *fname_list,
133133
static void remove_redundant_pack(const char *dir_name, const char *base_name)
134134
{
135135
struct strbuf buf = STRBUF_INIT;
136-
strbuf_addf(&buf, "%s/%s.pack", dir_name, base_name);
136+
struct multi_pack_index *m = get_multi_pack_index(the_repository);
137+
strbuf_addf(&buf, "%s.pack", base_name);
138+
if (m && midx_contains_pack(m, buf.buf))
139+
clear_midx_file(the_repository);
140+
strbuf_insertf(&buf, 0, "%s/", dir_name);
137141
unlink_pack_path(buf.buf, 1);
138142
strbuf_release(&buf);
139143
}
@@ -286,7 +290,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
286290
int keep_unreachable = 0;
287291
struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
288292
int no_update_server_info = 0;
289-
int midx_cleared = 0;
290293
struct pack_objects_args po_args = {NULL};
291294

292295
struct option builtin_repack_options[] = {
@@ -439,11 +442,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
439442
for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
440443
char *fname, *fname_old;
441444

442-
if (!midx_cleared) {
443-
clear_midx_file(the_repository);
444-
midx_cleared = 1;
445-
}
446-
447445
fname = mkpathdup("%s/pack-%s%s", packdir,
448446
item->string, exts[ext].name);
449447
if (!file_exists(fname)) {

t/t5319-multi-pack-index.sh

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,52 @@ test_expect_success 'repack with the --no-progress option' '
348348
test_line_count = 0 err
349349
'
350350

351-
test_expect_success 'repack removes multi-pack-index' '
351+
test_expect_success 'repack removes multi-pack-index when deleting packs' '
352352
test_path_is_file $objdir/pack/multi-pack-index &&
353-
GIT_TEST_MULTI_PACK_INDEX=0 git repack -adf &&
353+
# Set GIT_TEST_MULTI_PACK_INDEX to 0 to avoid writing a new
354+
# multi-pack-index after repacking, but set "core.multiPackIndex" to
355+
# true so that "git repack" can read the existing MIDX.
356+
GIT_TEST_MULTI_PACK_INDEX=0 git -c core.multiPackIndex repack -adf &&
354357
test_path_is_missing $objdir/pack/multi-pack-index
355358
'
356359

360+
test_expect_success 'repack preserves multi-pack-index when creating packs' '
361+
git init preserve &&
362+
test_when_finished "rm -fr preserve" &&
363+
(
364+
cd preserve &&
365+
packdir=.git/objects/pack &&
366+
midx=$packdir/multi-pack-index &&
367+
368+
test_commit 1 &&
369+
pack1=$(git pack-objects --all $packdir/pack) &&
370+
touch $packdir/pack-$pack1.keep &&
371+
test_commit 2 &&
372+
pack2=$(git pack-objects --revs $packdir/pack) &&
373+
touch $packdir/pack-$pack2.keep &&
374+
375+
git multi-pack-index write &&
376+
cp $midx $midx.bak &&
377+
378+
cat >pack-input <<-EOF &&
379+
HEAD
380+
^HEAD~1
381+
EOF
382+
test_commit 3 &&
383+
pack3=$(git pack-objects --revs $packdir/pack <pack-input) &&
384+
test_commit 4 &&
385+
pack4=$(git pack-objects --revs $packdir/pack <pack-input) &&
386+
387+
GIT_TEST_MULTI_PACK_INDEX=0 git -c core.multiPackIndex repack -ad &&
388+
ls -la $packdir &&
389+
test_path_is_file $packdir/pack-$pack1.pack &&
390+
test_path_is_file $packdir/pack-$pack2.pack &&
391+
test_path_is_missing $packdir/pack-$pack3.pack &&
392+
test_path_is_missing $packdir/pack-$pack4.pack &&
393+
test_cmp_bin $midx.bak $midx
394+
)
395+
'
396+
357397
compare_results_with_midx "after repack"
358398

359399
test_expect_success 'multi-pack-index and pack-bitmap' '

0 commit comments

Comments
 (0)