packfile: split out packfile list logic

In the next commit we're about to introduce the "packed" object database source. This source will embed a packfile list, and consequently we'll have to include "packfile.h" to make the struct definition available. This will unfortunately lead to a cyclic dependency that we cannot resolve with a forward declaration. Split out the code that relates to the packfile list into a separate compilation unit so that both "packfile.h" and "odb/source-packed.h" can include it. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jun 17, 2026 at 08:39 UTC cf86a18ac3b4e49f49c2c19351de109064999827
6 files changed +117 -105
Makefile
+1
@@ -1233,6 +1233,7 @@ LIB_OBJS += pack-refs.o
1233 LIB_OBJS += pack-revindex.o
1234 LIB_OBJS += pack-write.o
1235 LIB_OBJS += packfile.o
1236 +LIB_OBJS += packfile-list.o
1237 LIB_OBJS += pager.o
1238 LIB_OBJS += parallel-checkout.o
1239 LIB_OBJS += parse.o
meson.build
+1
@@ -421,6 +421,7 @@ libgit_sources = [
421 'pack-revindex.c',
422 'pack-write.c',
423 'packfile.c',
424 + 'packfile-list.c',
425 'pager.c',
426 'parallel-checkout.c',
427 'parse.c',
packfile-list.c new
+86
@@ -0,0 +1,86 @@
1 +#include "git-compat-util.h"
2 +#include "packfile.h"
3 +#include "packfile-list.h"
4 +
5 +void packfile_list_clear(struct packfile_list *list)
6 +{
7 + struct packfile_list_entry *e, *next;
8 +
9 + for (e = list->head; e; e = next) {
10 + next = e->next;
11 + free(e);
12 + }
13 +
14 + list->head = list->tail = NULL;
15 +}
16 +
17 +static struct packfile_list_entry *packfile_list_remove_internal(struct packfile_list *list,
18 + struct packed_git *pack)
19 +{
20 + struct packfile_list_entry *e, *prev;
21 +
22 + for (e = list->head, prev = NULL; e; prev = e, e = e->next) {
23 + if (e->pack != pack)
24 + continue;
25 +
26 + if (prev)
27 + prev->next = e->next;
28 + if (list->head == e)
29 + list->head = e->next;
30 + if (list->tail == e)
31 + list->tail = prev;
32 +
33 + return e;
34 + }
35 +
36 + return NULL;
37 +}
38 +
39 +void packfile_list_remove(struct packfile_list *list, struct packed_git *pack)
40 +{
41 + free(packfile_list_remove_internal(list, pack));
42 +}
43 +
44 +void packfile_list_prepend(struct packfile_list *list, struct packed_git *pack)
45 +{
46 + struct packfile_list_entry *entry;
47 +
48 + entry = packfile_list_remove_internal(list, pack);
49 + if (!entry) {
50 + entry = xmalloc(sizeof(*entry));
51 + entry->pack = pack;
52 + }
53 + entry->next = list->head;
54 +
55 + list->head = entry;
56 + if (!list->tail)
57 + list->tail = entry;
58 +}
59 +
60 +void packfile_list_append(struct packfile_list *list, struct packed_git *pack)
61 +{
62 + struct packfile_list_entry *entry;
63 +
64 + entry = packfile_list_remove_internal(list, pack);
65 + if (!entry) {
66 + entry = xmalloc(sizeof(*entry));
67 + entry->pack = pack;
68 + }
69 + entry->next = NULL;
70 +
71 + if (list->tail) {
72 + list->tail->next = entry;
73 + list->tail = entry;
74 + } else {
75 + list->head = list->tail = entry;
76 + }
77 +}
78 +
79 +struct packed_git *packfile_list_find_oid(struct packfile_list_entry *packs,
80 + const struct object_id *oid)
81 +{
82 + for (; packs; packs = packs->next)
83 + if (find_pack_entry_one(oid, packs->pack))
84 + return packs->pack;
85 + return NULL;
86 +}
packfile-list.h new
+28
@@ -0,0 +1,28 @@
1 +#ifndef PACKFILE_LIST_H
2 +#define PACKFILE_LIST_H
3 +
4 +struct object_id;
5 +
6 +struct packfile_list {
7 + struct packfile_list_entry *head, *tail;
8 +};
9 +
10 +struct packfile_list_entry {
11 + struct packfile_list_entry *next;
12 + struct packed_git *pack;
13 +};
14 +
15 +void packfile_list_clear(struct packfile_list *list);
16 +void packfile_list_remove(struct packfile_list *list, struct packed_git *pack);
17 +void packfile_list_prepend(struct packfile_list *list, struct packed_git *pack);
18 +void packfile_list_append(struct packfile_list *list, struct packed_git *pack);
19 +
20 +/*
21 + * Find the pack within the "packs" list whose index contains the object
22 + * "oid". For general object lookups, you probably don't want this; use
23 + * find_pack_entry() instead.
24 + */
25 +struct packed_git *packfile_list_find_oid(struct packfile_list_entry *packs,
26 + const struct object_id *oid);
27 +
28 +#endif
packfile.c
-83
@@ -48,89 +48,6 @@ static size_t pack_mapped;
48 #define SZ_FMT PRIuMAX
49 static inline uintmax_t sz_fmt(size_t s) { return s; }
50
51 -void packfile_list_clear(struct packfile_list *list)
52 -{
53 - struct packfile_list_entry *e, *next;
54 -
55 - for (e = list->head; e; e = next) {
56 - next = e->next;
57 - free(e);
58 - }
59 -
60 - list->head = list->tail = NULL;
61 -}
62 -
63 -static struct packfile_list_entry *packfile_list_remove_internal(struct packfile_list *list,
64 - struct packed_git *pack)
65 -{
66 - struct packfile_list_entry *e, *prev;
67 -
68 - for (e = list->head, prev = NULL; e; prev = e, e = e->next) {
69 - if (e->pack != pack)
70 - continue;
71 -
72 - if (prev)
73 - prev->next = e->next;
74 - if (list->head == e)
75 - list->head = e->next;
76 - if (list->tail == e)
77 - list->tail = prev;
78 -
79 - return e;
80 - }
81 -
82 - return NULL;
83 -}
84 -
85 -void packfile_list_remove(struct packfile_list *list, struct packed_git *pack)
86 -{
87 - free(packfile_list_remove_internal(list, pack));
88 -}
89 -
90 -void packfile_list_prepend(struct packfile_list *list, struct packed_git *pack)
91 -{
92 - struct packfile_list_entry *entry;
93 -
94 - entry = packfile_list_remove_internal(list, pack);
95 - if (!entry) {
96 - entry = xmalloc(sizeof(*entry));
97 - entry->pack = pack;
98 - }
99 - entry->next = list->head;
100 -
101 - list->head = entry;
102 - if (!list->tail)
103 - list->tail = entry;
104 -}
105 -
106 -void packfile_list_append(struct packfile_list *list, struct packed_git *pack)
107 -{
108 - struct packfile_list_entry *entry;
109 -
110 - entry = packfile_list_remove_internal(list, pack);
111 - if (!entry) {
112 - entry = xmalloc(sizeof(*entry));
113 - entry->pack = pack;
114 - }
115 - entry->next = NULL;
116 -
117 - if (list->tail) {
118 - list->tail->next = entry;
119 - list->tail = entry;
120 - } else {
121 - list->head = list->tail = entry;
122 - }
123 -}
124 -
125 -struct packed_git *packfile_list_find_oid(struct packfile_list_entry *packs,
126 - const struct object_id *oid)
127 -{
128 - for (; packs; packs = packs->next)
129 - if (find_pack_entry_one(oid, packs->pack))
130 - return packs->pack;
131 - return NULL;
132 -}
133 -
51 void pack_report(struct repository *repo)
52 {
53 fprintf(stderr,
packfile.h
+1 -22
@@ -6,6 +6,7 @@
6 #include "odb.h"
7 #include "odb/source-files.h"
8 #include "oidset.h"
9 +#include "packfile-list.h"
10 #include "repository.h"
11 #include "strmap.h"
12
@@ -54,28 +55,6 @@ struct packed_git {
55 char pack_name[FLEX_ARRAY]; /* more */
56 };
57
57 -struct packfile_list {
58 - struct packfile_list_entry *head, *tail;
59 -};
60 -
61 -struct packfile_list_entry {
62 - struct packfile_list_entry *next;
63 - struct packed_git *pack;
64 -};
65 -
66 -void packfile_list_clear(struct packfile_list *list);
67 -void packfile_list_remove(struct packfile_list *list, struct packed_git *pack);
68 -void packfile_list_prepend(struct packfile_list *list, struct packed_git *pack);
69 -void packfile_list_append(struct packfile_list *list, struct packed_git *pack);
70 -
71 -/*
72 - * Find the pack within the "packs" list whose index contains the object
73 - * "oid". For general object lookups, you probably don't want this; use
74 - * find_pack_entry() instead.
75 - */
76 -struct packed_git *packfile_list_find_oid(struct packfile_list_entry *packs,
77 - const struct object_id *oid);
78 -
58 /*
59 * A store that manages packfiles for a given object database.
60 */