packfile: refactor `get_multi_pack_index()` to work on sources

The function `get_multi_pack_index()` loads multi-pack indices via `prepare_packed_git()` and then returns the linked list of multi-pack indices that is stored in `struct object_database`. That list is in the process of being removed though in favor of storing the MIDX as part of the object database source it belongs to. Refactor `get_multi_pack_index()` so that it returns the multi-pack index for a single object source. Callers are now expected to call this function for each source they are interested in. This requires them to iterate through alternates, so we have to prepare alternate object sources before doing so. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jul 15, 2025 at 13:29 UTC 736bb725ebcd37d567455db2ac50524dea11223c
7 files changed +57 -62
builtin/pack-objects.c
+7 -3
@@ -1706,8 +1706,8 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
1706 uint32_t found_mtime)
1707 {
1708 int want;
1709 + struct odb_source *source;
1710 struct list_head *pos;
1710 - struct multi_pack_index *m;
1711
1712 if (!exclude && local && has_loose_object_nonlocal(oid))
1713 return 0;
@@ -1727,9 +1727,13 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
1727 *found_offset = 0;
1728 }
1729
1730 - for (m = get_multi_pack_index(the_repository); m; m = m->next) {
1730 + odb_prepare_alternates(the_repository->objects);
1731 +
1732 + for (source = the_repository->objects->sources; source; source = source->next) {
1733 + struct multi_pack_index *m = get_multi_pack_index(source);
1734 struct pack_entry e;
1732 - if (fill_midx_entry(the_repository, oid, &e, m)) {
1735 +
1736 + if (m && fill_midx_entry(the_repository, oid, &e, m)) {
1737 want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime);
1738 if (want != -1)
1739 return want;
builtin/repack.c
+5 -5
@@ -223,9 +223,9 @@ static void mark_packs_for_deletion(struct existing_packs *existing,
223 static void remove_redundant_pack(const char *dir_name, const char *base_name)
224 {
225 struct strbuf buf = STRBUF_INIT;
226 - struct multi_pack_index *m = get_local_multi_pack_index(the_repository);
226 + struct multi_pack_index *m = get_multi_pack_index(the_repository->objects->sources);
227 strbuf_addf(&buf, "%s.pack", base_name);
228 - if (m && midx_contains_pack(m, buf.buf))
228 + if (m && m->local && midx_contains_pack(m, buf.buf))
229 clear_midx_file(the_repository);
230 strbuf_insertf(&buf, 0, "%s/", dir_name);
231 unlink_pack_path(buf.buf, 1);
@@ -1531,7 +1531,7 @@ int cmd_repack(int argc,
1531 * midx_has_unknown_packs() will make the decision for
1532 * us.
1533 */
1534 - if (!get_local_multi_pack_index(the_repository))
1534 + if (!get_multi_pack_index(the_repository->objects->sources))
1535 midx_must_contain_cruft = 1;
1536 }
1537
@@ -1614,9 +1614,9 @@ int cmd_repack(int argc,
1614
1615 string_list_sort(&names);
1616
1617 - if (get_local_multi_pack_index(the_repository)) {
1617 + if (get_multi_pack_index(the_repository->objects->sources)) {
1618 struct multi_pack_index *m =
1619 - get_local_multi_pack_index(the_repository);
1619 + get_multi_pack_index(the_repository->objects->sources);
1620
1621 ALLOC_ARRAY(midx_pack_names,
1622 m->num_packs + m->num_packs_in_base);
midx-write.c
+2 -20
@@ -916,26 +916,8 @@ cleanup:
916 static struct multi_pack_index *lookup_multi_pack_index(struct repository *r,
917 const char *object_dir)
918 {
919 - struct multi_pack_index *result = NULL;
920 - struct multi_pack_index *cur;
921 - char *obj_dir_real = real_pathdup(object_dir, 1);
922 - struct strbuf cur_path_real = STRBUF_INIT;
923 -
924 - /* Ensure the given object_dir is local, or a known alternate. */
925 - odb_find_source(r->objects, obj_dir_real);
926 -
927 - for (cur = get_multi_pack_index(r); cur; cur = cur->next) {
928 - strbuf_realpath(&cur_path_real, cur->object_dir, 1);
929 - if (!strcmp(obj_dir_real, cur_path_real.buf)) {
930 - result = cur;
931 - goto cleanup;
932 - }
933 - }
934 -
935 -cleanup:
936 - free(obj_dir_real);
937 - strbuf_release(&cur_path_real);
938 - return result;
919 + struct odb_source *source = odb_find_source(r->objects, object_dir);
920 + return get_multi_pack_index(source);
921 }
922
923 static int fill_packs_from_midx(struct write_midx_context *ctx,
object-name.c
+15 -7
@@ -198,16 +198,20 @@ static void unique_in_pack(struct packed_git *p,
198
199 static void find_short_packed_object(struct disambiguate_state *ds)
200 {
201 - struct multi_pack_index *m;
201 + struct odb_source *source;
202 struct packed_git *p;
203
204 /* Skip, unless oids from the storage hash algorithm are wanted */
205 if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo))
206 return;
207
208 - for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous;
209 - m = m->next)
210 - unique_in_midx(m, ds);
208 + odb_prepare_alternates(ds->repo->objects);
209 + for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) {
210 + struct multi_pack_index *m = get_multi_pack_index(source);
211 + if (m)
212 + unique_in_midx(m, ds);
213 + }
214 +
215 for (p = get_packed_git(ds->repo); p && !ds->ambiguous;
216 p = p->next)
217 unique_in_pack(p, ds);
@@ -792,11 +796,15 @@ static void find_abbrev_len_for_pack(struct packed_git *p,
796
797 static void find_abbrev_len_packed(struct min_abbrev_data *mad)
798 {
795 - struct multi_pack_index *m;
799 struct packed_git *p;
800
798 - for (m = get_multi_pack_index(mad->repo); m; m = m->next)
799 - find_abbrev_len_for_midx(m, mad);
801 + odb_prepare_alternates(mad->repo->objects);
802 + for (struct odb_source *source = mad->repo->objects->sources; source; source = source->next) {
803 + struct multi_pack_index *m = get_multi_pack_index(source);
804 + if (m)
805 + find_abbrev_len_for_midx(m, mad);
806 + }
807 +
808 for (p = get_packed_git(mad->repo); p; p = p->next)
809 find_abbrev_len_for_pack(p, mad);
810 }
pack-bitmap.c
+15 -6
@@ -691,13 +691,15 @@ static int open_pack_bitmap(struct repository *r,
691 static int open_midx_bitmap(struct repository *r,
692 struct bitmap_index *bitmap_git)
693 {
694 + struct odb_source *source;
695 int ret = -1;
695 - struct multi_pack_index *midx;
696
697 assert(!bitmap_git->map);
698
699 - for (midx = get_multi_pack_index(r); midx; midx = midx->next) {
700 - if (!open_midx_bitmap_1(bitmap_git, midx))
699 + odb_prepare_alternates(r->objects);
700 + for (source = r->objects->sources; source; source = source->next) {
701 + struct multi_pack_index *midx = get_multi_pack_index(source);
702 + if (midx && !open_midx_bitmap_1(bitmap_git, midx))
703 ret = 0;
704 }
705 return ret;
@@ -3305,11 +3307,18 @@ static int verify_bitmap_file(const struct git_hash_algo *algop,
3307
3308 int verify_bitmap_files(struct repository *r)
3309 {
3310 + struct odb_source *source;
3311 int res = 0;
3312
3310 - for (struct multi_pack_index *m = get_multi_pack_index(r);
3311 - m; m = m->next) {
3312 - char *midx_bitmap_name = midx_bitmap_filename(m);
3313 + odb_prepare_alternates(r->objects);
3314 + for (source = r->objects->sources; source; source = source->next) {
3315 + struct multi_pack_index *m = get_multi_pack_index(source);
3316 + char *midx_bitmap_name;
3317 +
3318 + if (!m)
3319 + continue;
3320 +
3321 + midx_bitmap_name = midx_bitmap_filename(m);
3322 res |= verify_bitmap_file(r->hash_algo, midx_bitmap_name);
3323 free(midx_bitmap_name);
3324 }
packfile.c
+12 -19
@@ -963,14 +963,18 @@ static void prepare_packed_git(struct repository *r);
963 unsigned long repo_approximate_object_count(struct repository *r)
964 {
965 if (!r->objects->approximate_object_count_valid) {
966 - unsigned long count;
967 - struct multi_pack_index *m;
966 + struct odb_source *source;
967 + unsigned long count = 0;
968 struct packed_git *p;
969
970 prepare_packed_git(r);
971 - count = 0;
972 - for (m = get_multi_pack_index(r); m; m = m->next)
973 - count += m->num_objects;
971 +
972 + for (source = r->objects->sources; source; source = source->next) {
973 + struct multi_pack_index *m = get_multi_pack_index(source);
974 + if (m)
975 + count += m->num_objects;
976 + }
977 +
978 for (p = r->objects->packed_git; p; p = p->next) {
979 if (open_pack_index(p))
980 continue;
@@ -1074,21 +1078,10 @@ struct packed_git *get_packed_git(struct repository *r)
1078 return r->objects->packed_git;
1079 }
1080
1077 -struct multi_pack_index *get_multi_pack_index(struct repository *r)
1078 -{
1079 - prepare_packed_git(r);
1080 - return r->objects->multi_pack_index;
1081 -}
1082 -
1083 -struct multi_pack_index *get_local_multi_pack_index(struct repository *r)
1081 +struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
1082 {
1085 - struct multi_pack_index *m = get_multi_pack_index(r);
1086 -
1087 - /* no need to iterate; we always put the local one first (if any) */
1088 - if (m && m->local)
1089 - return m;
1090 -
1091 - return NULL;
1083 + prepare_packed_git(source->odb->repo);
1084 + return source->midx;
1085 }
1086
1087 struct packed_git *get_all_packs(struct repository *r)
packfile.h
+1 -2
@@ -147,8 +147,7 @@ void install_packed_git(struct repository *r, struct packed_git *pack);
147
148 struct packed_git *get_packed_git(struct repository *r);
149 struct list_head *get_packed_git_mru(struct repository *r);
150 -struct multi_pack_index *get_multi_pack_index(struct repository *r);
151 -struct multi_pack_index *get_local_multi_pack_index(struct repository *r);
150 +struct multi_pack_index *get_multi_pack_index(struct odb_source *source);
151 struct packed_git *get_all_packs(struct repository *r);
152
153 /*