Skip to content

Commit 1b76f06

Browse files
committed
Merge branch 'tb/midx-write-cleanup'
Code clean-up around writing the .midx files. * tb/midx-write-cleanup: pack-bitmap.c: reimplement `midx_bitmap_filename()` with helper midx: replace `get_midx_rev_filename()` with a generic helper midx-write.c: support reading an existing MIDX with `packs_to_include` midx-write.c: extract `fill_packs_from_midx()` midx-write.c: extract `should_include_pack()` midx-write.c: pass `start_pack` to `compute_sorted_entries()` midx-write.c: reduce argument count for `get_sorted_entries()` midx-write.c: tolerate `--preferred-pack` without bitmaps
2 parents cd77e87 + 4cac79a commit 1b76f06

File tree

6 files changed

+117
-91
lines changed

6 files changed

+117
-91
lines changed

midx-write.c

Lines changed: 79 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,18 @@ struct write_midx_context {
100100
struct string_list *to_include;
101101
};
102102

103+
static int should_include_pack(const struct write_midx_context *ctx,
104+
const char *file_name,
105+
int exclude_from_midx)
106+
{
107+
if (exclude_from_midx && ctx->m && midx_contains_pack(ctx->m, file_name))
108+
return 0;
109+
if (ctx->to_include && !string_list_has_string(ctx->to_include,
110+
file_name))
111+
return 0;
112+
return 1;
113+
}
114+
103115
static void add_pack_to_midx(const char *full_path, size_t full_path_len,
104116
const char *file_name, void *data)
105117
{
@@ -108,29 +120,11 @@ static void add_pack_to_midx(const char *full_path, size_t full_path_len,
108120

109121
if (ends_with(file_name, ".idx")) {
110122
display_progress(ctx->progress, ++ctx->pack_paths_checked);
111-
/*
112-
* Note that at most one of ctx->m and ctx->to_include are set,
113-
* so we are testing midx_contains_pack() and
114-
* string_list_has_string() independently (guarded by the
115-
* appropriate NULL checks).
116-
*
117-
* We could support passing to_include while reusing an existing
118-
* MIDX, but don't currently since the reuse process drags
119-
* forward all packs from an existing MIDX (without checking
120-
* whether or not they appear in the to_include list).
121-
*
122-
* If we added support for that, these next two conditional
123-
* should be performed independently (likely checking
124-
* to_include before the existing MIDX).
125-
*/
126-
if (ctx->m && midx_contains_pack(ctx->m, file_name))
127-
return;
128-
else if (ctx->to_include &&
129-
!string_list_has_string(ctx->to_include, file_name))
123+
124+
if (!should_include_pack(ctx, file_name, 1))
130125
return;
131126

132127
ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
133-
134128
p = add_packed_git(full_path, full_path_len, 0);
135129
if (!p) {
136130
warning(_("failed to add packfile '%s'"),
@@ -299,21 +293,16 @@ static void midx_fanout_add_pack_fanout(struct midx_fanout *fanout,
299293
* Copy only the de-duplicated entries (selected by most-recent modified time
300294
* of a packfile containing the object).
301295
*/
302-
static struct pack_midx_entry *get_sorted_entries(struct multi_pack_index *m,
303-
struct pack_info *info,
304-
uint32_t nr_packs,
305-
size_t *nr_objects,
306-
int preferred_pack)
296+
static void compute_sorted_entries(struct write_midx_context *ctx,
297+
uint32_t start_pack)
307298
{
308299
uint32_t cur_fanout, cur_pack, cur_object;
309300
size_t alloc_objects, total_objects = 0;
310301
struct midx_fanout fanout = { 0 };
311-
struct pack_midx_entry *deduplicated_entries = NULL;
312-
uint32_t start_pack = m ? m->num_packs : 0;
313302

314-
for (cur_pack = start_pack; cur_pack < nr_packs; cur_pack++)
303+
for (cur_pack = start_pack; cur_pack < ctx->nr; cur_pack++)
315304
total_objects = st_add(total_objects,
316-
info[cur_pack].p->num_objects);
305+
ctx->info[cur_pack].p->num_objects);
317306

318307
/*
319308
* As we de-duplicate by fanout value, we expect the fanout
@@ -323,26 +312,26 @@ static struct pack_midx_entry *get_sorted_entries(struct multi_pack_index *m,
323312
alloc_objects = fanout.alloc = total_objects > 3200 ? total_objects / 200 : 16;
324313

325314
ALLOC_ARRAY(fanout.entries, fanout.alloc);
326-
ALLOC_ARRAY(deduplicated_entries, alloc_objects);
327-
*nr_objects = 0;
315+
ALLOC_ARRAY(ctx->entries, alloc_objects);
316+
ctx->entries_nr = 0;
328317

329318
for (cur_fanout = 0; cur_fanout < 256; cur_fanout++) {
330319
fanout.nr = 0;
331320

332-
if (m)
333-
midx_fanout_add_midx_fanout(&fanout, m, cur_fanout,
334-
preferred_pack);
321+
if (ctx->m)
322+
midx_fanout_add_midx_fanout(&fanout, ctx->m, cur_fanout,
323+
ctx->preferred_pack_idx);
335324

336-
for (cur_pack = start_pack; cur_pack < nr_packs; cur_pack++) {
337-
int preferred = cur_pack == preferred_pack;
325+
for (cur_pack = start_pack; cur_pack < ctx->nr; cur_pack++) {
326+
int preferred = cur_pack == ctx->preferred_pack_idx;
338327
midx_fanout_add_pack_fanout(&fanout,
339-
info, cur_pack,
328+
ctx->info, cur_pack,
340329
preferred, cur_fanout);
341330
}
342331

343-
if (-1 < preferred_pack && preferred_pack < start_pack)
344-
midx_fanout_add_pack_fanout(&fanout, info,
345-
preferred_pack, 1,
332+
if (-1 < ctx->preferred_pack_idx && ctx->preferred_pack_idx < start_pack)
333+
midx_fanout_add_pack_fanout(&fanout, ctx->info,
334+
ctx->preferred_pack_idx, 1,
346335
cur_fanout);
347336

348337
midx_fanout_sort(&fanout);
@@ -356,17 +345,16 @@ static struct pack_midx_entry *get_sorted_entries(struct multi_pack_index *m,
356345
&fanout.entries[cur_object].oid))
357346
continue;
358347

359-
ALLOC_GROW(deduplicated_entries, st_add(*nr_objects, 1),
348+
ALLOC_GROW(ctx->entries, st_add(ctx->entries_nr, 1),
360349
alloc_objects);
361-
memcpy(&deduplicated_entries[*nr_objects],
350+
memcpy(&ctx->entries[ctx->entries_nr],
362351
&fanout.entries[cur_object],
363352
sizeof(struct pack_midx_entry));
364-
(*nr_objects)++;
353+
ctx->entries_nr++;
365354
}
366355
}
367356

368357
free(fanout.entries);
369-
return deduplicated_entries;
370358
}
371359

372360
static int write_midx_pack_names(struct hashfile *f, void *data)
@@ -886,6 +874,43 @@ static struct multi_pack_index *lookup_multi_pack_index(struct repository *r,
886874
return result;
887875
}
888876

877+
static int fill_packs_from_midx(struct write_midx_context *ctx,
878+
const char *preferred_pack_name, uint32_t flags)
879+
{
880+
uint32_t i;
881+
882+
for (i = 0; i < ctx->m->num_packs; i++) {
883+
if (!should_include_pack(ctx, ctx->m->pack_names[i], 0))
884+
continue;
885+
886+
ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
887+
888+
if (flags & MIDX_WRITE_REV_INDEX || preferred_pack_name) {
889+
/*
890+
* If generating a reverse index, need to have
891+
* packed_git's loaded to compare their
892+
* mtimes and object count.
893+
*
894+
*
895+
* If a preferred pack is specified, need to
896+
* have packed_git's loaded to ensure the chosen
897+
* preferred pack has a non-zero object count.
898+
*/
899+
if (prepare_midx_pack(the_repository, ctx->m, i))
900+
return error(_("could not load pack"));
901+
902+
if (open_pack_index(ctx->m->packs[i]))
903+
die(_("could not open index for %s"),
904+
ctx->m->packs[i]->pack_name);
905+
}
906+
907+
fill_pack_info(&ctx->info[ctx->nr++], ctx->m->packs[i],
908+
ctx->m->pack_names[i], i);
909+
}
910+
911+
return 0;
912+
}
913+
889914
static int write_midx_internal(const char *object_dir,
890915
struct string_list *packs_to_include,
891916
struct string_list *packs_to_drop,
@@ -895,7 +920,7 @@ static int write_midx_internal(const char *object_dir,
895920
{
896921
struct strbuf midx_name = STRBUF_INIT;
897922
unsigned char midx_hash[GIT_MAX_RAWSZ];
898-
uint32_t i;
923+
uint32_t i, start_pack;
899924
struct hashfile *f = NULL;
900925
struct lock_file lk;
901926
struct write_midx_context ctx = { 0 };
@@ -912,15 +937,7 @@ static int write_midx_internal(const char *object_dir,
912937
die_errno(_("unable to create leading directories of %s"),
913938
midx_name.buf);
914939

915-
if (!packs_to_include) {
916-
/*
917-
* Only reference an existing MIDX when not filtering which
918-
* packs to include, since all packs and objects are copied
919-
* blindly from an existing MIDX if one is present.
920-
*/
921-
ctx.m = lookup_multi_pack_index(the_repository, object_dir);
922-
}
923-
940+
ctx.m = lookup_multi_pack_index(the_repository, object_dir);
924941
if (ctx.m && !midx_checksum_valid(ctx.m)) {
925942
warning(_("ignoring existing multi-pack-index; checksum mismatch"));
926943
ctx.m = NULL;
@@ -929,42 +946,23 @@ static int write_midx_internal(const char *object_dir,
929946
ctx.nr = 0;
930947
ctx.alloc = ctx.m ? ctx.m->num_packs : 16;
931948
ctx.info = NULL;
949+
ctx.to_include = packs_to_include;
932950
ALLOC_ARRAY(ctx.info, ctx.alloc);
933951

934-
if (ctx.m) {
935-
for (i = 0; i < ctx.m->num_packs; i++) {
936-
ALLOC_GROW(ctx.info, ctx.nr + 1, ctx.alloc);
937-
938-
if (flags & MIDX_WRITE_REV_INDEX) {
939-
/*
940-
* If generating a reverse index, need to have
941-
* packed_git's loaded to compare their
942-
* mtimes and object count.
943-
*/
944-
if (prepare_midx_pack(the_repository, ctx.m, i)) {
945-
error(_("could not load pack"));
946-
result = 1;
947-
goto cleanup;
948-
}
949-
950-
if (open_pack_index(ctx.m->packs[i]))
951-
die(_("could not open index for %s"),
952-
ctx.m->packs[i]->pack_name);
953-
}
954-
955-
fill_pack_info(&ctx.info[ctx.nr++], ctx.m->packs[i],
956-
ctx.m->pack_names[i], i);
957-
}
952+
if (ctx.m && fill_packs_from_midx(&ctx, preferred_pack_name,
953+
flags) < 0) {
954+
result = 1;
955+
goto cleanup;
958956
}
959957

958+
start_pack = ctx.nr;
959+
960960
ctx.pack_paths_checked = 0;
961961
if (flags & MIDX_PROGRESS)
962962
ctx.progress = start_delayed_progress(_("Adding packfiles to multi-pack-index"), 0);
963963
else
964964
ctx.progress = NULL;
965965

966-
ctx.to_include = packs_to_include;
967-
968966
for_each_file_in_pack_dir(object_dir, add_pack_to_midx, &ctx);
969967
stop_progress(&ctx.progress);
970968

@@ -1054,8 +1052,7 @@ static int write_midx_internal(const char *object_dir,
10541052
}
10551053
}
10561054

1057-
ctx.entries = get_sorted_entries(ctx.m, ctx.info, ctx.nr, &ctx.entries_nr,
1058-
ctx.preferred_pack_idx);
1055+
compute_sorted_entries(&ctx, start_pack);
10591056

10601057
ctx.large_offsets_needed = 0;
10611058
for (i = 0; i < ctx.entries_nr; i++) {

midx.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ const unsigned char *get_midx_checksum(struct multi_pack_index *m)
2525

2626
void get_midx_filename(struct strbuf *out, const char *object_dir)
2727
{
28-
strbuf_addf(out, "%s/pack/multi-pack-index", object_dir);
28+
get_midx_filename_ext(out, object_dir, NULL, NULL);
2929
}
3030

31-
void get_midx_rev_filename(struct strbuf *out, struct multi_pack_index *m)
31+
void get_midx_filename_ext(struct strbuf *out, const char *object_dir,
32+
const unsigned char *hash, const char *ext)
3233
{
33-
get_midx_filename(out, m->object_dir);
34-
strbuf_addf(out, "-%s.rev", hash_to_hex(get_midx_checksum(m)));
34+
strbuf_addf(out, "%s/pack/multi-pack-index", object_dir);
35+
if (ext)
36+
strbuf_addf(out, "-%s.%s", hash_to_hex(hash), ext);
3537
}
3638

3739
static int midx_read_oid_fanout(const unsigned char *chunk_start,

midx.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,13 @@ struct multi_pack_index {
7474
#define MIDX_WRITE_BITMAP_HASH_CACHE (1 << 3)
7575
#define MIDX_WRITE_BITMAP_LOOKUP_TABLE (1 << 4)
7676

77+
#define MIDX_EXT_REV "rev"
78+
#define MIDX_EXT_BITMAP "bitmap"
79+
7780
const unsigned char *get_midx_checksum(struct multi_pack_index *m);
7881
void get_midx_filename(struct strbuf *out, const char *object_dir);
79-
void get_midx_rev_filename(struct strbuf *out, struct multi_pack_index *m);
82+
void get_midx_filename_ext(struct strbuf *out, const char *object_dir,
83+
const unsigned char *hash, const char *ext);
8084

8185
struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local);
8286
int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t pack_int_id);

pack-bitmap.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,8 @@ static int load_bitmap_entries_v1(struct bitmap_index *index)
309309
char *midx_bitmap_filename(struct multi_pack_index *midx)
310310
{
311311
struct strbuf buf = STRBUF_INIT;
312-
313-
get_midx_filename(&buf, midx->object_dir);
314-
strbuf_addf(&buf, "-%s.bitmap", hash_to_hex(get_midx_checksum(midx)));
312+
get_midx_filename_ext(&buf, midx->object_dir, get_midx_checksum(midx),
313+
MIDX_EXT_BITMAP);
315314

316315
return strbuf_detach(&buf, NULL);
317316
}

pack-revindex.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,8 @@ int load_midx_revindex(struct multi_pack_index *m)
381381
trace2_data_string("load_midx_revindex", the_repository,
382382
"source", "rev");
383383

384-
get_midx_rev_filename(&revindex_name, m);
384+
get_midx_filename_ext(&revindex_name, m->object_dir,
385+
get_midx_checksum(m), MIDX_EXT_REV);
385386

386387
ret = load_revindex_from_disk(revindex_name.buf,
387388
m->num_objects,

t/t5319-multi-pack-index.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,29 @@ test_expect_success 'preferred packs must be non-empty' '
350350
)
351351
'
352352

353+
test_expect_success 'preferred pack from existing MIDX without bitmaps' '
354+
git init preferred-without-bitmaps &&
355+
(
356+
cd preferred-without-bitmaps &&
357+
358+
test_commit one &&
359+
pack="$(git pack-objects --all $objdir/pack/pack </dev/null)" &&
360+
361+
git multi-pack-index write &&
362+
363+
# make another pack so that the subsequent MIDX write
364+
# has something to do
365+
test_commit two &&
366+
git repack -d &&
367+
368+
# write a new MIDX without bitmaps reusing the singular
369+
# pack from the existing MIDX as the preferred pack in
370+
# the new MIDX
371+
git multi-pack-index write --preferred-pack=pack-$pack.pack
372+
)
373+
374+
'
375+
353376
test_expect_success 'verify multi-pack-index success' '
354377
git multi-pack-index verify --object-dir=$objdir
355378
'

0 commit comments

Comments
 (0)