Skip to content

Commit a31677d

Browse files
committed
Merge branch 'tb/repack-clearing-midx'
When a packfile is removed by "git repack", multi-pack-index gets cleared; the code was taught to do so less aggressively by first checking if the midx actually refers to a pack that no longer exists. * tb/repack-clearing-midx: midx: traverse the local MIDX first builtin/repack.c: invalidate MIDX only when necessary
2 parents bbdba3d + 59552fb commit a31677d

File tree

5 files changed

+65
-11
lines changed

5 files changed

+65
-11
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_local_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)) {

midx.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,12 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i
416416
m = load_multi_pack_index(object_dir, local);
417417

418418
if (m) {
419-
m->next = r->objects->multi_pack_index;
420-
r->objects->multi_pack_index = m;
419+
struct multi_pack_index *mp = r->objects->multi_pack_index;
420+
if (mp) {
421+
m->next = mp->next;
422+
mp->next = m;
423+
} else
424+
r->objects->multi_pack_index = m;
421425
return 1;
422426
}
423427

packfile.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,17 @@ struct multi_pack_index *get_multi_pack_index(struct repository *r)
10271027
return r->objects->multi_pack_index;
10281028
}
10291029

1030+
struct multi_pack_index *get_local_multi_pack_index(struct repository *r)
1031+
{
1032+
struct multi_pack_index *m = get_multi_pack_index(r);
1033+
1034+
/* no need to iterate; we always put the local one first (if any) */
1035+
if (m && m->local)
1036+
return m;
1037+
1038+
return NULL;
1039+
}
1040+
10301041
struct packed_git *get_all_packs(struct repository *r)
10311042
{
10321043
struct multi_pack_index *m;

packfile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void install_packed_git(struct repository *r, struct packed_git *pack);
5757
struct packed_git *get_packed_git(struct repository *r);
5858
struct list_head *get_packed_git_mru(struct repository *r);
5959
struct multi_pack_index *get_multi_pack_index(struct repository *r);
60+
struct multi_pack_index *get_local_multi_pack_index(struct repository *r);
6061
struct packed_git *get_all_packs(struct repository *r);
6162

6263
/*

t/t5319-multi-pack-index.sh

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,12 +382,52 @@ test_expect_success 'repack with the --no-progress option' '
382382
test_line_count = 0 err
383383
'
384384

385-
test_expect_success 'repack removes multi-pack-index' '
385+
test_expect_success 'repack removes multi-pack-index when deleting packs' '
386386
test_path_is_file $objdir/pack/multi-pack-index &&
387-
GIT_TEST_MULTI_PACK_INDEX=0 git repack -adf &&
387+
# Set GIT_TEST_MULTI_PACK_INDEX to 0 to avoid writing a new
388+
# multi-pack-index after repacking, but set "core.multiPackIndex" to
389+
# true so that "git repack" can read the existing MIDX.
390+
GIT_TEST_MULTI_PACK_INDEX=0 git -c core.multiPackIndex repack -adf &&
388391
test_path_is_missing $objdir/pack/multi-pack-index
389392
'
390393

394+
test_expect_success 'repack preserves multi-pack-index when creating packs' '
395+
git init preserve &&
396+
test_when_finished "rm -fr preserve" &&
397+
(
398+
cd preserve &&
399+
packdir=.git/objects/pack &&
400+
midx=$packdir/multi-pack-index &&
401+
402+
test_commit 1 &&
403+
pack1=$(git pack-objects --all $packdir/pack) &&
404+
touch $packdir/pack-$pack1.keep &&
405+
test_commit 2 &&
406+
pack2=$(git pack-objects --revs $packdir/pack) &&
407+
touch $packdir/pack-$pack2.keep &&
408+
409+
git multi-pack-index write &&
410+
cp $midx $midx.bak &&
411+
412+
cat >pack-input <<-EOF &&
413+
HEAD
414+
^HEAD~1
415+
EOF
416+
test_commit 3 &&
417+
pack3=$(git pack-objects --revs $packdir/pack <pack-input) &&
418+
test_commit 4 &&
419+
pack4=$(git pack-objects --revs $packdir/pack <pack-input) &&
420+
421+
GIT_TEST_MULTI_PACK_INDEX=0 git -c core.multiPackIndex repack -ad &&
422+
ls -la $packdir &&
423+
test_path_is_file $packdir/pack-$pack1.pack &&
424+
test_path_is_file $packdir/pack-$pack2.pack &&
425+
test_path_is_missing $packdir/pack-$pack3.pack &&
426+
test_path_is_missing $packdir/pack-$pack4.pack &&
427+
test_cmp_bin $midx.bak $midx
428+
)
429+
'
430+
391431
compare_results_with_midx "after repack"
392432

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

0 commit comments

Comments
 (0)