builtin/repack.c: remove ref snapshotting from builtin
When writing a MIDX, 'git repack' takes a snapshot of the repository's references and writes the result out to a file, which it then passes to 'git multi-pack-index write' via the '--refs-snapshot'. This is done in order to make bitmap selections with respect to what we are packing, thus avoiding a race where an incoming reference update causes us to try and write a bitmap for a commit not present in the MIDX. Extract this functionality out into a new repack-midx.c compilation unit, and expose the necessary functions via the repack.h API. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Taylor Blau committed
Oct 15, 2025 at 18:28 UTC
ccb7f822d520472026a12250e1390683706a8154
5 files changed
+83
-68
Makefile
+1
@@ -1138,6 +1138,7 @@ LIB_OBJS += refspec.o
1138
LIB_OBJS += remote.o
1139
LIB_OBJS += repack.o
1140
LIB_OBJS += repack-geometry.o
1141
+LIB_OBJS += repack-midx.o
1142
LIB_OBJS += repack-promisor.o
1143
LIB_OBJS += replace-object.o
1144
LIB_OBJS += repo-settings.o
builtin/repack.c
-68
@@ -178,74 +178,6 @@ static int midx_has_unknown_packs(char **midx_pack_names,
178
return 0;
179
}
180
181
-struct midx_snapshot_ref_data {
182
- struct repository *repo;
183
- struct tempfile *f;
184
- struct oidset seen;
185
- int preferred;
186
-};
187
-
188
-static int midx_snapshot_ref_one(const char *refname UNUSED,
189
- const char *referent UNUSED,
190
- const struct object_id *oid,
191
- int flag UNUSED, void *_data)
192
-{
193
- struct midx_snapshot_ref_data *data = _data;
194
- struct object_id peeled;
195
-
196
- if (!peel_iterated_oid(data->repo, oid, &peeled))
197
- oid = &peeled;
198
-
199
- if (oidset_insert(&data->seen, oid))
200
- return 0; /* already seen */
201
-
202
- if (odb_read_object_info(data->repo->objects, oid, NULL) != OBJ_COMMIT)
203
- return 0;
204
-
205
- fprintf(data->f->fp, "%s%s\n", data->preferred ? "+" : "",
206
- oid_to_hex(oid));
207
-
208
- return 0;
209
-}
210
-
211
-static void midx_snapshot_refs(struct repository *repo, struct tempfile *f)
212
-{
213
- struct midx_snapshot_ref_data data;
214
- const struct string_list *preferred = bitmap_preferred_tips(repo);
215
-
216
- data.repo = repo;
217
- data.f = f;
218
- data.preferred = 0;
219
- oidset_init(&data.seen, 0);
220
-
221
- if (!fdopen_tempfile(f, "w"))
222
- die(_("could not open tempfile %s for writing"),
223
- get_tempfile_path(f));
224
-
225
- if (preferred) {
226
- struct string_list_item *item;
227
-
228
- data.preferred = 1;
229
- for_each_string_list_item(item, preferred)
230
- refs_for_each_ref_in(get_main_ref_store(repo),
231
- item->string,
232
- midx_snapshot_ref_one, &data);
233
- data.preferred = 0;
234
- }
235
-
236
- refs_for_each_ref(get_main_ref_store(repo),
237
- midx_snapshot_ref_one, &data);
238
-
239
- if (close_tempfile_gently(f)) {
240
- int save_errno = errno;
241
- delete_tempfile(&f);
242
- errno = save_errno;
243
- die_errno(_("could not close refs snapshot tempfile"));
244
- }
245
-
246
- oidset_clear(&data.seen);
247
-}
248
-
181
static void midx_included_packs(struct string_list *include,
182
struct existing_packs *existing,
183
char **midx_pack_names,
meson.build
+1
@@ -464,6 +464,7 @@ libgit_sources = [
464
'remote.c',
465
'repack.c',
466
'repack-geometry.c',
467
+ 'repack-midx.c',
468
'repack-promisor.c',
469
'replace-object.c',
470
'repo-settings.c',
repack-midx.c
new
+77
@@ -0,0 +1,77 @@
1
+#include "git-compat-util.h"
2
+#include "repack.h"
3
+#include "hash.h"
4
+#include "hex.h"
5
+#include "odb.h"
6
+#include "oidset.h"
7
+#include "pack-bitmap.h"
8
+#include "refs.h"
9
+#include "tempfile.h"
10
+
11
+struct midx_snapshot_ref_data {
12
+ struct repository *repo;
13
+ struct tempfile *f;
14
+ struct oidset seen;
15
+ int preferred;
16
+};
17
+
18
+static int midx_snapshot_ref_one(const char *refname UNUSED,
19
+ const char *referent UNUSED,
20
+ const struct object_id *oid,
21
+ int flag UNUSED, void *_data)
22
+{
23
+ struct midx_snapshot_ref_data *data = _data;
24
+ struct object_id peeled;
25
+
26
+ if (!peel_iterated_oid(data->repo, oid, &peeled))
27
+ oid = &peeled;
28
+
29
+ if (oidset_insert(&data->seen, oid))
30
+ return 0; /* already seen */
31
+
32
+ if (odb_read_object_info(data->repo->objects, oid, NULL) != OBJ_COMMIT)
33
+ return 0;
34
+
35
+ fprintf(data->f->fp, "%s%s\n", data->preferred ? "+" : "",
36
+ oid_to_hex(oid));
37
+
38
+ return 0;
39
+}
40
+
41
+void midx_snapshot_refs(struct repository *repo, struct tempfile *f)
42
+{
43
+ struct midx_snapshot_ref_data data;
44
+ const struct string_list *preferred = bitmap_preferred_tips(repo);
45
+
46
+ data.repo = repo;
47
+ data.f = f;
48
+ data.preferred = 0;
49
+ oidset_init(&data.seen, 0);
50
+
51
+ if (!fdopen_tempfile(f, "w"))
52
+ die(_("could not open tempfile %s for writing"),
53
+ get_tempfile_path(f));
54
+
55
+ if (preferred) {
56
+ struct string_list_item *item;
57
+
58
+ data.preferred = 1;
59
+ for_each_string_list_item(item, preferred)
60
+ refs_for_each_ref_in(get_main_ref_store(repo),
61
+ item->string,
62
+ midx_snapshot_ref_one, &data);
63
+ data.preferred = 0;
64
+ }
65
+
66
+ refs_for_each_ref(get_main_ref_store(repo),
67
+ midx_snapshot_ref_one, &data);
68
+
69
+ if (close_tempfile_gently(f)) {
70
+ int save_errno = errno;
71
+ delete_tempfile(&f);
72
+ errno = save_errno;
73
+ die_errno(_("could not close refs snapshot tempfile"));
74
+ }
75
+
76
+ oidset_clear(&data.seen);
77
+}
repack.h
+4
@@ -98,4 +98,8 @@ void pack_geometry_remove_redundant(struct pack_geometry *geometry,
98
const char *packdir);
99
void pack_geometry_release(struct pack_geometry *geometry);
100
101
+struct tempfile;
102
+
103
+void midx_snapshot_refs(struct repository *repo, struct tempfile *f);
104
+
105
#endif /* REPACK_H */