packfile: move list of packs into the packfile store

Move the list of packs into the packfile store. This follows the same logic as in a previous commit, where we moved the most-recently-used list of packs, as well. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Oct 30, 2025 at 11:38 UTC 589127caa73090040200989ff4d24c3d54f473f2
3 files changed +43 -60
builtin/fast-import.c
+2 -2
@@ -978,7 +978,7 @@ static int store_object(
978 if (e->idx.offset) {
979 duplicate_count_by_type[type]++;
980 return 1;
981 - } else if (find_oid_pack(&oid, packfile_store_get_packs(packs))) {
981 + } else if (packfile_list_find_oid(packfile_store_get_packs(packs), &oid)) {
982 e->type = type;
983 e->pack_id = MAX_PACK_ID;
984 e->idx.offset = 1; /* just not zero! */
@@ -1179,7 +1179,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
1179 duplicate_count_by_type[OBJ_BLOB]++;
1180 truncate_pack(&checkpoint);
1181
1182 - } else if (find_oid_pack(&oid, packfile_store_get_packs(packs))) {
1182 + } else if (packfile_list_find_oid(packfile_store_get_packs(packs), &oid)) {
1183 e->type = OBJ_BLOB;
1184 e->pack_id = MAX_PACK_ID;
1185 e->idx.offset = 1; /* just not zero! */
packfile.c
+37 -46
@@ -356,13 +356,14 @@ static void scan_windows(struct packed_git *p,
356
357 static int unuse_one_window(struct packed_git *current)
358 {
359 - struct packed_git *p, *lru_p = NULL;
359 + struct packfile_list_entry *e;
360 + struct packed_git *lru_p = NULL;
361 struct pack_window *lru_w = NULL, *lru_l = NULL;
362
363 if (current)
364 scan_windows(current, &lru_p, &lru_w, &lru_l);
364 - for (p = current->repo->objects->packfiles->packs; p; p = p->next)
365 - scan_windows(p, &lru_p, &lru_w, &lru_l);
365 + for (e = current->repo->objects->packfiles->packs.head; e; e = e->next)
366 + scan_windows(e->pack, &lru_p, &lru_w, &lru_l);
367 if (lru_p) {
368 munmap(lru_w->base, lru_w->len);
369 pack_mapped -= lru_w->len;
@@ -542,14 +543,15 @@ static void find_lru_pack(struct packed_git *p, struct packed_git **lru_p, struc
543
544 static int close_one_pack(struct repository *r)
545 {
545 - struct packed_git *p, *lru_p = NULL;
546 + struct packfile_list_entry *e;
547 + struct packed_git *lru_p = NULL;
548 struct pack_window *mru_w = NULL;
549 int accept_windows_inuse = 1;
550
549 - for (p = r->objects->packfiles->packs; p; p = p->next) {
550 - if (p->pack_fd == -1)
551 + for (e = r->objects->packfiles->packs.head; e; e = e->next) {
552 + if (e->pack->pack_fd == -1)
553 continue;
552 - find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse);
554 + find_lru_pack(e->pack, &lru_p, &mru_w, &accept_windows_inuse);
555 }
556
557 if (lru_p)
@@ -868,8 +870,7 @@ void packfile_store_add_pack(struct packfile_store *store,
870 if (pack->pack_fd != -1)
871 pack_open_fds++;
872
871 - pack->next = store->packs;
872 - store->packs = pack;
873 + packfile_list_prepend(&store->packs, pack);
874
875 strmap_put(&store->packs_by_path, pack->pack_name, pack);
876 }
@@ -1046,9 +1047,10 @@ static void prepare_packed_git_one(struct odb_source *source)
1047 string_list_clear(data.garbage, 0);
1048 }
1049
1049 -DEFINE_LIST_SORT(static, sort_packs, struct packed_git, next);
1050 +DEFINE_LIST_SORT(static, sort_packs, struct packfile_list_entry, next);
1051
1051 -static int sort_pack(const struct packed_git *a, const struct packed_git *b)
1052 +static int sort_pack(const struct packfile_list_entry *a,
1053 + const struct packfile_list_entry *b)
1054 {
1055 int st;
1056
@@ -1058,7 +1060,7 @@ static int sort_pack(const struct packed_git *a, const struct packed_git *b)
1060 * remote ones could be on a network mounted filesystem.
1061 * Favor local ones for these reasons.
1062 */
1061 - st = a->pack_local - b->pack_local;
1063 + st = a->pack->pack_local - b->pack->pack_local;
1064 if (st)
1065 return -st;
1066
@@ -1067,21 +1069,19 @@ static int sort_pack(const struct packed_git *a, const struct packed_git *b)
1069 * and more recent objects tend to get accessed more
1070 * often.
1071 */
1070 - if (a->mtime < b->mtime)
1072 + if (a->pack->mtime < b->pack->mtime)
1073 return 1;
1072 - else if (a->mtime == b->mtime)
1074 + else if (a->pack->mtime == b->pack->mtime)
1075 return 0;
1076 return -1;
1077 }
1078
1079 static void packfile_store_prepare_mru(struct packfile_store *store)
1080 {
1079 - struct packed_git *p;
1080 -
1081 packfile_list_clear(&store->mru);
1082
1083 - for (p = store->packs; p; p = p->next)
1084 - packfile_list_append(&store->mru, p);
1083 + for (struct packfile_list_entry *e = store->packs.head; e; e = e->next)
1084 + packfile_list_append(&store->mru, e->pack);
1085 }
1086
1087 void packfile_store_prepare(struct packfile_store *store)
@@ -1096,7 +1096,11 @@ void packfile_store_prepare(struct packfile_store *store)
1096 prepare_multi_pack_index_one(source);
1097 prepare_packed_git_one(source);
1098 }
1099 - sort_packs(&store->packs, sort_pack);
1099 +
1100 + sort_packs(&store->packs.head, sort_pack);
1101 + for (struct packfile_list_entry *e = store->packs.head; e; e = e->next)
1102 + if (!e->next)
1103 + store->packs.tail = e;
1104
1105 packfile_store_prepare_mru(store);
1106 store->initialized = true;
@@ -1108,7 +1112,7 @@ void packfile_store_reprepare(struct packfile_store *store)
1112 packfile_store_prepare(store);
1113 }
1114
1111 -struct packed_git *packfile_store_get_packs(struct packfile_store *store)
1115 +struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *store)
1116 {
1117 packfile_store_prepare(store);
1118
@@ -1120,7 +1124,7 @@ struct packed_git *packfile_store_get_packs(struct packfile_store *store)
1124 prepare_midx_pack(m, i);
1125 }
1126
1123 - return store->packs;
1127 + return store->packs.head;
1128 }
1129
1130 struct packfile_list_entry *packfile_store_get_packs_mru(struct packfile_store *store)
@@ -1276,11 +1280,11 @@ void mark_bad_packed_object(struct packed_git *p, const struct object_id *oid)
1280 const struct packed_git *has_packed_and_bad(struct repository *r,
1281 const struct object_id *oid)
1282 {
1279 - struct packed_git *p;
1283 + struct packfile_list_entry *e;
1284
1281 - for (p = r->objects->packfiles->packs; p; p = p->next)
1282 - if (oidset_contains(&p->bad_objects, oid))
1283 - return p;
1285 + for (e = r->objects->packfiles->packs.head; e; e = e->next)
1286 + if (oidset_contains(&e->pack->bad_objects, oid))
1287 + return e->pack;
1288 return NULL;
1289 }
1290
@@ -2088,19 +2092,6 @@ int is_pack_valid(struct packed_git *p)
2092 return !open_packed_git(p);
2093 }
2094
2091 -struct packed_git *find_oid_pack(const struct object_id *oid,
2092 - struct packed_git *packs)
2093 -{
2094 - struct packed_git *p;
2095 -
2096 - for (p = packs; p; p = p->next) {
2097 - if (find_pack_entry_one(oid, p))
2098 - return p;
2099 - }
2100 - return NULL;
2101 -
2102 -}
2103 -
2095 static int fill_pack_entry(const struct object_id *oid,
2096 struct pack_entry *e,
2097 struct packed_git *p)
@@ -2139,7 +2130,7 @@ int find_pack_entry(struct repository *r, const struct object_id *oid, struct pa
2130 if (source->midx && fill_midx_entry(source->midx, oid, e))
2131 return 1;
2132
2142 - if (!r->objects->packfiles->packs)
2133 + if (!r->objects->packfiles->packs.head)
2134 return 0;
2135
2136 for (l = r->objects->packfiles->mru.head; l; l = l->next) {
@@ -2404,19 +2395,19 @@ struct packfile_store *packfile_store_new(struct object_database *odb)
2395
2396 void packfile_store_free(struct packfile_store *store)
2397 {
2407 - for (struct packed_git *p = store->packs, *next; p; p = next) {
2408 - next = p->next;
2409 - free(p);
2410 - }
2398 + for (struct packfile_list_entry *e = store->packs.head; e; e = e->next)
2399 + free(e->pack);
2400 + packfile_list_clear(&store->packs);
2401 +
2402 strmap_clear(&store->packs_by_path, 0);
2403 free(store);
2404 }
2405
2406 void packfile_store_close(struct packfile_store *store)
2407 {
2417 - for (struct packed_git *p = store->packs; p; p = p->next) {
2418 - if (p->do_not_close)
2408 + for (struct packfile_list_entry *e = store->packs.head; e; e = e->next) {
2409 + if (e->pack->do_not_close)
2410 BUG("want to close pack marked 'do-not-close'");
2420 - close_pack(p);
2411 + close_pack(e->pack);
2412 }
2413 }
packfile.h
+4 -12
@@ -11,7 +11,6 @@
11 struct object_info;
12
13 struct packed_git {
14 - struct packed_git *next;
14 struct pack_window *windows;
15 off_t pack_size;
16 const void *index_data;
@@ -83,7 +82,7 @@ struct packfile_store {
82 * The list of packfiles in the order in which they are being added to
83 * the store.
84 */
86 - struct packed_git *packs;
85 + struct packfile_list packs;
86
87 /*
88 * Cache of packfiles which are marked as "kept", either because there
@@ -163,13 +162,14 @@ void packfile_store_add_pack(struct packfile_store *store,
162 * repository.
163 */
164 #define repo_for_each_pack(repo, p) \
166 - for (p = packfile_store_get_packs(repo->objects->packfiles); p; p = p->next)
165 + for (struct packfile_list_entry *e = packfile_store_get_packs(repo->objects->packfiles); \
166 + ((p) = (e ? e->pack : NULL)); e = e->next)
167
168 /*
169 * Get all packs managed by the given store, including packfiles that are
170 * referenced by multi-pack indices.
171 */
172 -struct packed_git *packfile_store_get_packs(struct packfile_store *store);
172 +struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *store);
173
174 /*
175 * Get all packs in most-recently-used order.
@@ -266,14 +266,6 @@ extern void (*report_garbage)(unsigned seen_bits, const char *path);
266 */
267 unsigned long repo_approximate_object_count(struct repository *r);
268
269 -/*
270 - * Find the pack within the "packs" list whose index contains the object "oid".
271 - * For general object lookups, you probably don't want this; use
272 - * find_pack_entry() instead.
273 - */
274 -struct packed_git *find_oid_pack(const struct object_id *oid,
275 - struct packed_git *packs);
276 -
269 void pack_report(struct repository *repo);
270
271 /*