Skip to content

Commit 00fd49d

Browse files
ttaylorrgitster
authored andcommitted
midx: return a packed_git pointer from prepare_midx_pack()
The prepare_midx_pack() function is designed to convert a MIDX-specific pack_int_id for a given pack into a pointer into an actual `packed_git` structure. In general, these calls look something like: struct packed_git *p; if (prepare_midx_pack(the_repository, some_midx, some_pack_int_id)) die("could not load pack xyz"); p = some_midx->packs[some_pack_int_id]; , and in a pre-incremental MIDX world, this pattern works well. However, in a post-incremental MIDX world, this pattern is a little more prone to errors. These errors can happen when the given 'pack_int_id' is not usable as an index into the 'm->packs' array. And this happens in all layers but the bottom-most one in an incremental MIDX chain. Each layer stores only the packs that are local to that layer of the chain, and offsets them by the total number of packs in the base MIDX(s). But there is other awkwardness here. Thinking back to the above snippet, suppose that the pack with ID 'some_pack_int_id' is in a layer in the middle of the MIDX chain. Then it is still invalid to do: p = some_midx->packs[some_pack_int_id - some_midx->num_packs_in_base]; , becuase the top-most layer (here 'some_midx') may not even have that pack! So we would have to chase down the '->base_midx' pointer in order to get the correct result. midx.c has a helper to do this (called 'midx_for_pack()'), but it is meant only for internal use. That means that a full, working version of the above adjusted to handle incremental MIDXs would look something like: struct packed_git *p; if (prepare_midx_pack(the_repository, some_midx, some_pack_int_id)) die("could not load pack xyz"); while (m && pack_int_id < m->num_packs_in_base) m = m->base_midx; if (!m) BUG("broken midx?"); if (pack_int_id >= m->num_packs + m->num_packs_in_base) BUG("broken pack_int_id?"); p = m->packs[pack_int_id - m->num_packs_in_base]; , which is far too verbose to access a single pack by its pack_int_id in a MIDX chain. Let's instead have prepare_midx_pack() return a pointer to the packed_git structure itself, hiding the above as an implementation detail of prepare_midx_pack(). This patch turns the above snippet into: struct packed_git *p = prepare_midx_pack(the_repository, some_midx, some_pack_int_id); if (!p) die("could not load pack xyz"); making it far easier and less error-prone to access packs by their pack_int_id in a MIDX chain. (In the future, we may want to consider similar treatment for, e.g., the pack_names array. Likewise, it might make sense to rename the "packs" member of the MIDX structure to suggest that it shouldn't be accessed directly outside of midx.c.) Suggested-by: Jeff King <[email protected]> Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5dff093 commit 00fd49d

File tree

4 files changed

+67
-70
lines changed

4 files changed

+67
-70
lines changed

midx-write.c

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -943,25 +943,23 @@ static int fill_packs_from_midx_1(struct write_midx_context *ctx,
943943
int prepare_packs)
944944
{
945945
for (uint32_t i = 0; i < m->num_packs; i++) {
946-
/*
947-
* If generating a reverse index, need to have
948-
* packed_git's loaded to compare their
949-
* mtimes and object count.
950-
*/
946+
struct packed_git *p = NULL;
947+
948+
ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
951949
if (prepare_packs) {
952-
if (prepare_midx_pack(ctx->repo, m,
953-
m->num_packs_in_base + i)) {
950+
p = prepare_midx_pack(ctx->repo, m,
951+
m->num_packs_in_base + i);
952+
if (!p) {
954953
error(_("could not load pack"));
955954
return 1;
956955
}
957956

958-
if (open_pack_index(m->packs[i]))
957+
if (open_pack_index(p))
959958
die(_("could not open index for %s"),
960-
m->packs[i]->pack_name);
959+
p->pack_name);
961960
}
962961

963-
fill_pack_info(&ctx->info[ctx->nr++], m->packs[i],
964-
m->pack_names[i],
962+
fill_pack_info(&ctx->info[ctx->nr++], p, m->pack_names[i],
965963
m->num_packs_in_base + i);
966964
}
967965

@@ -1588,20 +1586,19 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla
15881586
_("Finding and deleting unreferenced packfiles"),
15891587
m->num_packs);
15901588
for (i = 0; i < m->num_packs; i++) {
1589+
struct packed_git *p;
15911590
char *pack_name;
15921591
display_progress(progress, i + 1);
15931592

15941593
if (count[i])
15951594
continue;
15961595

1597-
if (prepare_midx_pack(r, m, i))
1598-
continue;
1599-
1600-
if (m->packs[i]->pack_keep || m->packs[i]->is_cruft)
1596+
p = prepare_midx_pack(r, m, i);
1597+
if (!p || p->pack_keep || p->is_cruft)
16011598
continue;
16021599

1603-
pack_name = xstrdup(m->packs[i]->pack_name);
1604-
close_pack(m->packs[i]);
1600+
pack_name = xstrdup(p->pack_name);
1601+
close_pack(p);
16051602

16061603
string_list_insert(&packs_to_drop, m->pack_names[i]);
16071604
unlink_pack_path(pack_name, 0);
@@ -1649,9 +1646,9 @@ static int want_included_pack(struct repository *r,
16491646

16501647
ASSERT(m && !m->base_midx);
16511648

1652-
if (prepare_midx_pack(r, m, pack_int_id))
1649+
p = prepare_midx_pack(r, m, pack_int_id);
1650+
if (!p)
16531651
return 0;
1654-
p = m->packs[pack_int_id];
16551652
if (!pack_kept_objects && p->pack_keep)
16561653
return 0;
16571654
if (p->is_cruft)
@@ -1697,12 +1694,11 @@ static void fill_included_packs_batch(struct repository *r,
16971694
repo_config_get_bool(r, "repack.packkeptobjects", &pack_kept_objects);
16981695

16991696
for (i = 0; i < m->num_packs; i++) {
1700-
pack_info[i].pack_int_id = i;
1697+
struct packed_git *p = prepare_midx_pack(r, m, i);
17011698

1702-
if (prepare_midx_pack(r, m, i))
1703-
continue;
1704-
1705-
pack_info[i].mtime = m->packs[i]->mtime;
1699+
pack_info[i].pack_int_id = i;
1700+
if (p)
1701+
pack_info[i].mtime = p->mtime;
17061702
}
17071703

17081704
for (i = 0; i < m->num_objects; i++) {

midx.c

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -451,50 +451,48 @@ static uint32_t midx_for_pack(struct multi_pack_index **_m,
451451
return pack_int_id - m->num_packs_in_base;
452452
}
453453

454-
int prepare_midx_pack(struct repository *r, struct multi_pack_index *m,
455-
uint32_t pack_int_id)
454+
struct packed_git *prepare_midx_pack(struct repository *r,
455+
struct multi_pack_index *m,
456+
uint32_t pack_int_id)
456457
{
457-
struct strbuf pack_name = STRBUF_INIT;
458-
struct strbuf key = STRBUF_INIT;
459-
struct packed_git *p;
460-
461-
pack_int_id = midx_for_pack(&m, pack_int_id);
462-
463-
if (m->packs[pack_int_id] == MIDX_PACK_ERROR)
464-
return 1;
465-
if (m->packs[pack_int_id])
466-
return 0;
467-
468-
strbuf_addf(&pack_name, "%s/pack/%s", m->object_dir,
469-
m->pack_names[pack_int_id]);
470-
471-
/* pack_map holds the ".pack" name, but we have the .idx */
472-
strbuf_addbuf(&key, &pack_name);
473-
strbuf_strip_suffix(&key, ".idx");
474-
strbuf_addstr(&key, ".pack");
475-
p = hashmap_get_entry_from_hash(&r->objects->pack_map,
476-
strhash(key.buf), key.buf,
477-
struct packed_git, packmap_ent);
478-
if (!p) {
479-
p = add_packed_git(r, pack_name.buf, pack_name.len, m->local);
480-
if (p) {
481-
install_packed_git(r, p);
482-
list_add_tail(&p->mru, &r->objects->packed_git_mru);
458+
uint32_t pack_pos = midx_for_pack(&m, pack_int_id);
459+
460+
if (!m->packs[pack_pos]) {
461+
struct strbuf pack_name = STRBUF_INIT;
462+
struct strbuf key = STRBUF_INIT;
463+
struct packed_git *p;
464+
465+
strbuf_addf(&pack_name, "%s/pack/%s", m->object_dir,
466+
m->pack_names[pack_pos]);
467+
468+
/* pack_map holds the ".pack" name, but we have the .idx */
469+
strbuf_addbuf(&key, &pack_name);
470+
strbuf_strip_suffix(&key, ".idx");
471+
strbuf_addstr(&key, ".pack");
472+
p = hashmap_get_entry_from_hash(&r->objects->pack_map,
473+
strhash(key.buf), key.buf,
474+
struct packed_git, packmap_ent);
475+
if (!p) {
476+
p = add_packed_git(r, pack_name.buf, pack_name.len,
477+
m->local);
478+
if (p) {
479+
install_packed_git(r, p);
480+
list_add_tail(&p->mru,
481+
&r->objects->packed_git_mru);
482+
}
483483
}
484-
}
485484

486-
strbuf_release(&pack_name);
487-
strbuf_release(&key);
485+
strbuf_release(&pack_name);
486+
strbuf_release(&key);
488487

489-
if (!p) {
490-
m->packs[pack_int_id] = MIDX_PACK_ERROR;
491-
return 1;
488+
m->packs[pack_pos] = p ? p : MIDX_PACK_ERROR;
489+
if (p)
490+
p->multi_pack_index = 1;
492491
}
493492

494-
p->multi_pack_index = 1;
495-
m->packs[pack_int_id] = p;
496-
497-
return 0;
493+
if (m->packs[pack_pos] == MIDX_PACK_ERROR)
494+
return NULL;
495+
return m->packs[pack_pos];
498496
}
499497

500498
struct packed_git *nth_midxed_pack(struct multi_pack_index *m,
@@ -523,10 +521,11 @@ int nth_bitmapped_pack(struct repository *r, struct multi_pack_index *m,
523521
if (!m->chunk_bitmapped_packs)
524522
return error(_("MIDX does not contain the BTMP chunk"));
525523

526-
if (prepare_midx_pack(r, m, pack_int_id))
527-
return error(_("could not load bitmapped pack %"PRIu32), pack_int_id);
524+
bp->p = prepare_midx_pack(r, m, pack_int_id);
525+
if (!bp->p)
526+
return error(_("could not load bitmapped pack %"PRIu32),
527+
pack_int_id);
528528

529-
bp->p = m->packs[local_pack_int_id];
530529
bp->bitmap_pos = get_be32((char *)m->chunk_bitmapped_packs +
531530
MIDX_CHUNK_BITMAPPED_PACKS_WIDTH * local_pack_int_id);
532531
bp->bitmap_nr = get_be32((char *)m->chunk_bitmapped_packs +
@@ -623,9 +622,9 @@ int fill_midx_entry(struct repository *r,
623622
midx_for_object(&m, pos);
624623
pack_int_id = nth_midxed_pack_int_id(m, pos);
625624

626-
if (prepare_midx_pack(r, m, pack_int_id))
625+
p = prepare_midx_pack(r, m, pack_int_id);
626+
if (!p)
627627
return 0;
628-
p = m->packs[pack_int_id - m->num_packs_in_base];
629628

630629
/*
631630
* We are about to tell the caller where they can locate the
@@ -926,7 +925,7 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag
926925
_("Looking for referenced packfiles"),
927926
m->num_packs + m->num_packs_in_base);
928927
for (i = 0; i < m->num_packs + m->num_packs_in_base; i++) {
929-
if (prepare_midx_pack(r, m, i))
928+
if (!prepare_midx_pack(r, m, i))
930929
midx_report("failed to load pack in position %d", i);
931930

932931
display_progress(progress, i + 1);

midx.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ void get_split_midx_filename_ext(const struct git_hash_algo *hash_algo,
104104
struct multi_pack_index *load_multi_pack_index(struct repository *r,
105105
const char *object_dir,
106106
int local);
107-
int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t pack_int_id);
107+
struct packed_git *prepare_midx_pack(struct repository *r,
108+
struct multi_pack_index *m,
109+
uint32_t pack_int_id);
108110
struct packed_git *nth_midxed_pack(struct multi_pack_index *m,
109111
uint32_t pack_int_id);
110112
const char *nth_midxed_pack_name(struct multi_pack_index *m,

pack-bitmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
488488
}
489489

490490
for (i = 0; i < bitmap_git->midx->num_packs + bitmap_git->midx->num_packs_in_base; i++) {
491-
if (prepare_midx_pack(bitmap_repo(bitmap_git), bitmap_git->midx, i)) {
491+
if (!prepare_midx_pack(bitmap_repo(bitmap_git), bitmap_git->midx, i)) {
492492
warning(_("could not open pack %s"),
493493
nth_midxed_pack_name(bitmap_git->midx, i));
494494
goto cleanup;

0 commit comments

Comments
 (0)