Skip to content

Commit 393879d

Browse files
committed
Merge branch 'tb/multi-pack-reuse-fix'
Assorted fixes to multi-pack-index code paths. * tb/multi-pack-reuse-fix: pack-revindex.c: guard against out-of-bounds pack lookups pack-bitmap.c: avoid uninitialized `pack_int_id` during reuse midx-write.c: do not read existing MIDX with `packs_to_include`
2 parents f4788a5 + e162aed commit 393879d

File tree

5 files changed

+103
-11
lines changed

5 files changed

+103
-11
lines changed

midx-write.c

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,27 @@ struct write_midx_context {
101101
};
102102

103103
static int should_include_pack(const struct write_midx_context *ctx,
104-
const char *file_name,
105-
int exclude_from_midx)
104+
const char *file_name)
106105
{
107-
if (exclude_from_midx && ctx->m && midx_contains_pack(ctx->m, file_name))
106+
/*
107+
* Note that at most one of ctx->m and ctx->to_include are set,
108+
* so we are testing midx_contains_pack() and
109+
* string_list_has_string() independently (guarded by the
110+
* appropriate NULL checks).
111+
*
112+
* We could support passing to_include while reusing an existing
113+
* MIDX, but don't currently since the reuse process drags
114+
* forward all packs from an existing MIDX (without checking
115+
* whether or not they appear in the to_include list).
116+
*
117+
* If we added support for that, these next two conditional
118+
* should be performed independently (likely checking
119+
* to_include before the existing MIDX).
120+
*/
121+
if (ctx->m && midx_contains_pack(ctx->m, file_name))
108122
return 0;
109-
if (ctx->to_include && !string_list_has_string(ctx->to_include,
110-
file_name))
123+
else if (ctx->to_include &&
124+
!string_list_has_string(ctx->to_include, file_name))
111125
return 0;
112126
return 1;
113127
}
@@ -121,7 +135,7 @@ static void add_pack_to_midx(const char *full_path, size_t full_path_len,
121135
if (ends_with(file_name, ".idx")) {
122136
display_progress(ctx->progress, ++ctx->pack_paths_checked);
123137

124-
if (!should_include_pack(ctx, file_name, 1))
138+
if (!should_include_pack(ctx, file_name))
125139
return;
126140

127141
ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
@@ -880,9 +894,6 @@ static int fill_packs_from_midx(struct write_midx_context *ctx,
880894
uint32_t i;
881895

882896
for (i = 0; i < ctx->m->num_packs; i++) {
883-
if (!should_include_pack(ctx, ctx->m->pack_names[i], 0))
884-
continue;
885-
886897
ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
887898

888899
if (flags & MIDX_WRITE_REV_INDEX || preferred_pack_name) {
@@ -937,7 +948,15 @@ static int write_midx_internal(const char *object_dir,
937948
die_errno(_("unable to create leading directories of %s"),
938949
midx_name.buf);
939950

940-
ctx.m = lookup_multi_pack_index(the_repository, object_dir);
951+
if (!packs_to_include) {
952+
/*
953+
* Only reference an existing MIDX when not filtering which
954+
* packs to include, since all packs and objects are copied
955+
* blindly from an existing MIDX if one is present.
956+
*/
957+
ctx.m = lookup_multi_pack_index(the_repository, object_dir);
958+
}
959+
941960
if (ctx.m && !midx_checksum_valid(ctx.m)) {
942961
warning(_("ignoring existing multi-pack-index; checksum mismatch"));
943962
ctx.m = NULL;
@@ -946,7 +965,6 @@ static int write_midx_internal(const char *object_dir,
946965
ctx.nr = 0;
947966
ctx.alloc = ctx.m ? ctx.m->num_packs : 16;
948967
ctx.info = NULL;
949-
ctx.to_include = packs_to_include;
950968
ALLOC_ARRAY(ctx.info, ctx.alloc);
951969

952970
if (ctx.m && fill_packs_from_midx(&ctx, preferred_pack_name,
@@ -963,6 +981,8 @@ static int write_midx_internal(const char *object_dir,
963981
else
964982
ctx.progress = NULL;
965983

984+
ctx.to_include = packs_to_include;
985+
966986
for_each_file_in_pack_dir(object_dir, add_pack_to_midx, &ctx);
967987
stop_progress(&ctx.progress);
968988

pack-bitmap.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,6 +2073,7 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
20732073
QSORT(packs, packs_nr, bitmapped_pack_cmp);
20742074
} else {
20752075
struct packed_git *pack;
2076+
uint32_t pack_int_id;
20762077

20772078
if (bitmap_is_midx(bitmap_git)) {
20782079
uint32_t preferred_pack_pos;
@@ -2083,12 +2084,24 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
20832084
}
20842085

20852086
pack = bitmap_git->midx->packs[preferred_pack_pos];
2087+
pack_int_id = preferred_pack_pos;
20862088
} else {
20872089
pack = bitmap_git->pack;
2090+
/*
2091+
* Any value for 'pack_int_id' will do here. When we
2092+
* process the pack via try_partial_reuse(), we won't
2093+
* use the `pack_int_id` field since we have a non-MIDX
2094+
* bitmap.
2095+
*
2096+
* Use '-1' as a sentinel value to make it clear
2097+
* that we do not expect to read this field.
2098+
*/
2099+
pack_int_id = -1;
20882100
}
20892101

20902102
ALLOC_GROW(packs, packs_nr + 1, packs_alloc);
20912103
packs[packs_nr].p = pack;
2104+
packs[packs_nr].pack_int_id = pack_int_id;
20922105
packs[packs_nr].bitmap_nr = pack->num_objects;
20932106
packs[packs_nr].bitmap_pos = 0;
20942107

pack-revindex.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,9 @@ static int midx_key_to_pack_pos(struct multi_pack_index *m,
527527
{
528528
uint32_t *found;
529529

530+
if (key->pack >= m->num_packs)
531+
BUG("MIDX pack lookup out of bounds (%"PRIu32" >= %"PRIu32")",
532+
key->pack, m->num_packs);
530533
/*
531534
* The preferred pack sorts first, so determine its identifier by
532535
* looking at the first object in pseudo-pack order.

t/t5326-multi-pack-bitmaps.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,4 +551,34 @@ do
551551
'
552552
done
553553

554+
test_expect_success 'remove one packfile between MIDX bitmap writes' '
555+
git init remove-pack-between-writes &&
556+
(
557+
cd remove-pack-between-writes &&
558+
559+
test_commit A &&
560+
test_commit B &&
561+
test_commit C &&
562+
563+
# Create packs with the prefix "pack-A", "pack-B",
564+
# "pack-C" to impose a lexicographic order on these
565+
# packs so the pack being removed is always from the
566+
# middle.
567+
packdir=.git/objects/pack &&
568+
A="$(echo A | git pack-objects $packdir/pack-A --revs)" &&
569+
B="$(echo B | git pack-objects $packdir/pack-B --revs)" &&
570+
C="$(echo C | git pack-objects $packdir/pack-C --revs)" &&
571+
572+
git multi-pack-index write --bitmap &&
573+
574+
cat >in <<-EOF &&
575+
pack-A-$A.idx
576+
pack-C-$C.idx
577+
EOF
578+
git multi-pack-index write --bitmap --stdin-packs <in &&
579+
580+
git rev-list --test-bitmap HEAD
581+
)
582+
'
583+
554584
test_done

t/t5332-multi-pack-reuse.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,30 @@ test_expect_success 'omit delta from uninteresting base (cross pack)' '
204204
test_pack_objects_reused_all $(($objects_nr - 1)) $packs_nr
205205
'
206206

207+
test_expect_success 'non-omitted delta in MIDX preferred pack' '
208+
test_config pack.allowPackReuse single &&
209+
210+
cat >p1.objects <<-EOF &&
211+
$(git rev-parse $base)
212+
^$(git rev-parse $delta^)
213+
EOF
214+
cat >p2.objects <<-EOF &&
215+
$(git rev-parse F)
216+
EOF
217+
218+
p1="$(git pack-objects --revs $packdir/pack <p1.objects)" &&
219+
p2="$(git pack-objects --revs $packdir/pack <p2.objects)" &&
220+
221+
cat >in <<-EOF &&
222+
pack-$p1.idx
223+
pack-$p2.idx
224+
EOF
225+
git multi-pack-index write --bitmap --stdin-packs \
226+
--preferred-pack=pack-$p1.pack <in &&
227+
228+
git show-index <$packdir/pack-$p1.idx >expect &&
229+
230+
test_pack_objects_reused_all $(wc -l <expect) 1
231+
'
232+
207233
test_done

0 commit comments

Comments
 (0)