odb: move list of packfiles into `struct packfile_store`

The object database tracks the list of packfiles it currently knows about. With the introduction of the `struct packfile_store` we have a better place to host this list though. Move the list accordingly. Extract the logic from `odb_clear()` that knows to close all such packfiles and move it into the new subsystem, as well. 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 535b7a667a94d5882add829e30e20b6dfa076640
4 files changed +41 -29
odb.c
+2 -10
@@ -1038,16 +1038,8 @@ void odb_clear(struct object_database *o)
1038
1039 INIT_LIST_HEAD(&o->packed_git_mru);
1040 close_object_store(o);
1041 -
1042 - /*
1043 - * `close_object_store()` only closes the packfiles, but doesn't free
1044 - * them. We thus have to do this manually.
1045 - */
1046 - for (struct packed_git *p = o->packed_git, *next; p; p = next) {
1047 - next = p->next;
1048 - free(p);
1049 - }
1050 - o->packed_git = NULL;
1041 + packfile_store_free(o->packfiles);
1042 + o->packfiles = NULL;
1043
1044 hashmap_clear(&o->pack_map);
1045 string_list_clear(&o->submodule_source_paths, 0);
odb.h
-1
@@ -138,7 +138,6 @@ struct object_database {
138 * should only be accessed directly by packfile.c
139 */
140 struct packfile_store *packfiles;
141 - struct packed_git *packed_git;
141 /* A most-recently-used ordered version of the packed_git list. */
142 struct list_head packed_git_mru;
143
packfile.c
+25 -17
@@ -278,7 +278,7 @@ static int unuse_one_window(struct packed_git *current)
278
279 if (current)
280 scan_windows(current, &lru_p, &lru_w, &lru_l);
281 - for (p = current->repo->objects->packed_git; p; p = p->next)
281 + for (p = current->repo->objects->packfiles->packs; p; p = p->next)
282 scan_windows(p, &lru_p, &lru_w, &lru_l);
283 if (lru_p) {
284 munmap(lru_w->base, lru_w->len);
@@ -362,13 +362,8 @@ void close_pack(struct packed_git *p)
362 void close_object_store(struct object_database *o)
363 {
364 struct odb_source *source;
365 - struct packed_git *p;
365
367 - for (p = o->packed_git; p; p = p->next)
368 - if (p->do_not_close)
369 - BUG("want to close pack marked 'do-not-close'");
370 - else
371 - close_pack(p);
366 + packfile_store_close(o->packfiles);
367
368 for (source = o->sources; source; source = source->next) {
369 if (source->midx)
@@ -468,7 +463,7 @@ static int close_one_pack(struct repository *r)
463 struct pack_window *mru_w = NULL;
464 int accept_windows_inuse = 1;
465
471 - for (p = r->objects->packed_git; p; p = p->next) {
466 + for (p = r->objects->packfiles->packs; p; p = p->next) {
467 if (p->pack_fd == -1)
468 continue;
469 find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse);
@@ -789,8 +784,8 @@ void install_packed_git(struct repository *r, struct packed_git *pack)
784 if (pack->pack_fd != -1)
785 pack_open_fds++;
786
792 - pack->next = r->objects->packed_git;
793 - r->objects->packed_git = pack;
787 + pack->next = r->objects->packfiles->packs;
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);
@@ -974,7 +969,7 @@ unsigned long repo_approximate_object_count(struct repository *r)
969 count += m->num_objects;
970 }
971
977 - for (p = r->objects->packed_git; p; p = p->next) {
972 + for (p = r->objects->packfiles->packs; p; p = p->next) {
973 if (open_pack_index(p))
974 continue;
975 count += p->num_objects;
@@ -1015,7 +1010,7 @@ static int sort_pack(const struct packed_git *a, const struct packed_git *b)
1010
1011 static void rearrange_packed_git(struct repository *r)
1012 {
1018 - sort_packs(&r->objects->packed_git, sort_pack);
1013 + sort_packs(&r->objects->packfiles->packs, sort_pack);
1014 }
1015
1016 static void prepare_packed_git_mru(struct repository *r)
@@ -1024,7 +1019,7 @@ static void prepare_packed_git_mru(struct repository *r)
1019
1020 INIT_LIST_HEAD(&r->objects->packed_git_mru);
1021
1027 - for (p = r->objects->packed_git; p; p = p->next)
1022 + for (p = r->objects->packfiles->packs; p; p = p->next)
1023 list_add_tail(&p->mru, &r->objects->packed_git_mru);
1024 }
1025
@@ -1073,7 +1068,7 @@ void reprepare_packed_git(struct repository *r)
1068 struct packed_git *get_packed_git(struct repository *r)
1069 {
1070 prepare_packed_git(r);
1076 - return r->objects->packed_git;
1071 + return r->objects->packfiles->packs;
1072 }
1073
1074 struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
@@ -1094,7 +1089,7 @@ struct packed_git *get_all_packs(struct repository *r)
1089 prepare_midx_pack(m, i);
1090 }
1091
1097 - return r->objects->packed_git;
1092 + return r->objects->packfiles->packs;
1093 }
1094
1095 struct list_head *get_packed_git_mru(struct repository *r)
@@ -1219,7 +1214,7 @@ const struct packed_git *has_packed_and_bad(struct repository *r,
1214 {
1215 struct packed_git *p;
1216
1222 - for (p = r->objects->packed_git; p; p = p->next)
1217 + for (p = r->objects->packfiles->packs; p; p = p->next)
1218 if (oidset_contains(&p->bad_objects, oid))
1219 return p;
1220 return NULL;
@@ -2080,7 +2075,7 @@ int find_pack_entry(struct repository *r, const struct object_id *oid, struct pa
2075 if (source->midx && fill_midx_entry(source->midx, oid, e))
2076 return 1;
2077
2083 - if (!r->objects->packed_git)
2078 + if (!r->objects->packfiles->packs)
2079 return 0;
2080
2081 list_for_each(pos, &r->objects->packed_git_mru) {
@@ -2343,5 +2338,18 @@ struct packfile_store *packfile_store_new(struct object_database *odb)
2338
2339 void packfile_store_free(struct packfile_store *store)
2340 {
2341 + for (struct packed_git *p = store->packs, *next; p; p = next) {
2342 + next = p->next;
2343 + free(p);
2344 + }
2345 free(store);
2346 }
2347 +
2348 +void packfile_store_close(struct packfile_store *store)
2349 +{
2350 + for (struct packed_git *p = store->packs; p; p = p->next) {
2351 + if (p->do_not_close)
2352 + BUG("want to close pack marked 'do-not-close'");
2353 + close_pack(p);
2354 + }
2355 +}
packfile.h
+14 -1
@@ -57,6 +57,12 @@ struct packed_git {
57 */
58 struct packfile_store {
59 struct object_database *odb;
60 +
61 + /*
62 + * The list of packfiles in the order in which they are being added to
63 + * the store.
64 + */
65 + struct packed_git *packs;
66 };
67
68 /*
@@ -66,10 +72,17 @@ struct packfile_store {
72 struct packfile_store *packfile_store_new(struct object_database *odb);
73
74 /*
69 - * Free the packfile store and all its associated state.
75 + * Free the packfile store and all its associated state. All packfiles
76 + * tracked by the store will be closed.
77 */
78 void packfile_store_free(struct packfile_store *store);
79
80 +/*
81 + * Close all packfiles associated with this store. The packfiles won't be
82 + * free'd, so they can be re-opened at a later point in time.
83 + */
84 +void packfile_store_close(struct packfile_store *store);
85 +
86 static inline int pack_map_entry_cmp(const void *cmp_data UNUSED,
87 const struct hashmap_entry *entry,
88 const struct hashmap_entry *entry2,