odb: move packfile map into `struct packfile_store`

The object database tracks a map of packfiles by their respective paths, which is used to figure out whether a given packfile has already been loaded. With the introduction of the `struct packfile_store` we have a better place to host this list though. Move the map accordingly. `pack_map_entry_cmp()` isn't used anywhere but in "packfile.c" anymore after this change, so we convert it to a static function, as well. Note that we also drop the `inline` hint: the function is used as a callback function exclusively, and callbacks cannot be inlined. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Sep 23, 2025 at 12:17 UTC 14aaf5c9d889a4988ffc64b39fe38bd19b930a50
5 files changed +26 -26
midx.c
+1 -1
@@ -460,7 +460,7 @@ int prepare_midx_pack(struct multi_pack_index *m,
460 strbuf_addbuf(&key, &pack_name);
461 strbuf_strip_suffix(&key, ".idx");
462 strbuf_addstr(&key, ".pack");
463 - p = hashmap_get_entry_from_hash(&r->objects->pack_map,
463 + p = hashmap_get_entry_from_hash(&r->objects->packfiles->map,
464 strhash(key.buf), key.buf,
465 struct packed_git, packmap_ent);
466 if (!p) {
odb.c
-2
@@ -998,7 +998,6 @@ struct object_database *odb_new(struct repository *repo)
998 o->repo = repo;
999 o->packfiles = packfile_store_new(o);
1000 INIT_LIST_HEAD(&o->packed_git_mru);
1001 - hashmap_init(&o->pack_map, pack_map_entry_cmp, NULL, 0);
1001 pthread_mutex_init(&o->replace_mutex, NULL);
1002 string_list_init_dup(&o->submodule_source_paths);
1003 return o;
@@ -1041,6 +1040,5 @@ void odb_clear(struct object_database *o)
1040 packfile_store_free(o->packfiles);
1041 o->packfiles = NULL;
1042
1044 - hashmap_clear(&o->pack_map);
1043 string_list_clear(&o->submodule_source_paths, 0);
1044 }
odb.h
+1 -7
@@ -135,7 +135,7 @@ struct object_database {
135 /*
136 * private data
137 *
138 - * should only be accessed directly by packfile.c
138 + * Should only be accessed directly by packfile.c and midx.c.
139 */
140 struct packfile_store *packfiles;
141 /* A most-recently-used ordered version of the packed_git list. */
@@ -155,12 +155,6 @@ struct object_database {
155 struct cached_object_entry *cached_objects;
156 size_t cached_object_nr, cached_object_alloc;
157
158 - /*
159 - * A map of packfiles to packed_git structs for tracking which
160 - * packs have been loaded already.
161 - */
162 - struct hashmap pack_map;
163 -
158 /*
159 * A fast, rough count of the number of objects in the repository.
160 * These two fields are not meant for direct access. Use
packfile.c
+18 -2
@@ -788,7 +788,7 @@ void install_packed_git(struct repository *r, struct packed_git *pack)
788 r->objects->packfiles->packs = pack;
789
790 hashmap_entry_init(&pack->packmap_ent, strhash(pack->pack_name));
791 - hashmap_add(&r->objects->pack_map, &pack->packmap_ent);
791 + hashmap_add(&r->objects->packfiles->map, &pack->packmap_ent);
792 }
793
794 void (*report_garbage)(unsigned seen_bits, const char *path);
@@ -901,7 +901,7 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
901 hashmap_entry_init(&hent, hash);
902
903 /* Don't reopen a pack we already have. */
904 - if (!hashmap_get(&data->r->objects->pack_map, &hent, pack_name)) {
904 + if (!hashmap_get(&data->r->objects->packfiles->map, &hent, pack_name)) {
905 p = add_packed_git(data->r, full_name, full_name_len, data->local);
906 if (p)
907 install_packed_git(data->r, p);
@@ -2328,11 +2328,26 @@ int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *l
2328 return 0;
2329 }
2330
2331 +static int pack_map_entry_cmp(const void *cmp_data UNUSED,
2332 + const struct hashmap_entry *entry,
2333 + const struct hashmap_entry *entry2,
2334 + const void *keydata)
2335 +{
2336 + const char *key = keydata;
2337 + const struct packed_git *pg1, *pg2;
2338 +
2339 + pg1 = container_of(entry, const struct packed_git, packmap_ent);
2340 + pg2 = container_of(entry2, const struct packed_git, packmap_ent);
2341 +
2342 + return strcmp(pg1->pack_name, key ? key : pg2->pack_name);
2343 +}
2344 +
2345 struct packfile_store *packfile_store_new(struct object_database *odb)
2346 {
2347 struct packfile_store *store;
2348 CALLOC_ARRAY(store, 1);
2349 store->odb = odb;
2350 + hashmap_init(&store->map, pack_map_entry_cmp, NULL, 0);
2351 return store;
2352 }
2353
@@ -2342,6 +2357,7 @@ void packfile_store_free(struct packfile_store *store)
2357 next = p->next;
2358 free(p);
2359 }
2360 + hashmap_clear(&store->map);
2361 free(store);
2362 }
2363
packfile.h
+6 -14
@@ -64,6 +64,12 @@ struct packfile_store {
64 */
65 struct packed_git *packs;
66
67 + /*
68 + * A map of packfile names to packed_git structs for tracking which
69 + * packs have been loaded already.
70 + */
71 + struct hashmap map;
72 +
73 /*
74 * Whether packfiles have already been populated with this store's
75 * packs.
@@ -89,20 +95,6 @@ void packfile_store_free(struct packfile_store *store);
95 */
96 void packfile_store_close(struct packfile_store *store);
97
92 -static inline int pack_map_entry_cmp(const void *cmp_data UNUSED,
93 - const struct hashmap_entry *entry,
94 - const struct hashmap_entry *entry2,
95 - const void *keydata)
96 -{
97 - const char *key = keydata;
98 - const struct packed_git *pg1, *pg2;
99 -
100 - pg1 = container_of(entry, const struct packed_git, packmap_ent);
101 - pg2 = container_of(entry2, const struct packed_git, packmap_ent);
102 -
103 - return strcmp(pg1->pack_name, key ? key : pg2->pack_name);
104 -}
105 -
98 struct pack_window {
99 struct pack_window *next;
100 unsigned char *base;