[PATCH v2 31/49] builtin/repack.c: remove ref snapshotting from builtin

Taylor Blau
2025-10-15T22:28:52Z

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>
---
Makefile | 1 +
builtin/repack.c | 68 ------------------------------------------
meson.build | 1 +
repack-midx.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++
repack.h | 4 +++
5 files changed, 83 insertions(+), 68 deletions(-)
create mode 100644 repack-midx.c

diff --git a/Makefile b/Makefile
index a1ccac235d..4b0a122428 100644
--- a/Makefile
+++ b/Makefile
@@ -1251,6 +1251,7 @@ LIB_OBJS += refspec.o
LIB_OBJS += remote.o
LIB_OBJS += repack.o
LIB_OBJS += repack-geometry.o
+LIB_OBJS += repack-midx.o
LIB_OBJS += repack-promisor.o
LIB_OBJS += replace-object.o
LIB_OBJS += repo-settings.o
diff --git a/builtin/repack.c b/builtin/repack.c
index e2313c80c3..7713721826 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -178,74 +178,6 @@ static int midx_has_unknown_packs(char **midx_pack_names,
return 0;
}

-struct midx_snapshot_ref_data {
- struct repository *repo;
- struct tempfile *f;
- struct oidset seen;
- int preferred;
-};
-
-static int midx_snapshot_ref_one(const char *refname UNUSED,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flag UNUSED, void *_data)
-{
- struct midx_snapshot_ref_data *data = _data;
- struct object_id peeled;
-
- if (!peel_iterated_oid(data->repo, oid, &peeled))
- oid = &peeled;
-
- if (oidset_insert(&data->seen, oid))
- return 0; /* already seen */
-
- if (odb_read_object_info(data->repo->objects, oid, NULL) != OBJ_COMMIT)
- return 0;
-
- fprintf(data->f->fp, "%s%s\n", data->preferred ? "+" : "",
- oid_to_hex(oid));
-
- return 0;
-}
-
-static void midx_snapshot_refs(struct repository *repo, struct tempfile *f)
-{
- struct midx_snapshot_ref_data data;
- const struct string_list *preferred = bitmap_preferred_tips(repo);
-
- data.repo = repo;
- data.f = f;
- data.preferred = 0;
- oidset_init(&data.seen, 0);
-
- if (!fdopen_tempfile(f, "w"))
- die(_("could not open tempfile %s for writing"),
- get_tempfile_path(f));
-
- if (preferred) {
- struct string_list_item *item;
-
- data.preferred = 1;
- for_each_string_list_item(item, preferred)
- refs_for_each_ref_in(get_main_ref_store(repo),
- item->string,
- midx_snapshot_ref_one, &data);
- data.preferred = 0;
- }
-
- refs_for_each_ref(get_main_ref_store(repo),
- midx_snapshot_ref_one, &data);
-
- if (close_tempfile_gently(f)) {
- int save_errno = errno;
- delete_tempfile(&f);
- errno = save_errno;
- die_errno(_("could not close refs snapshot tempfile"));
- }
-
- oidset_clear(&data.seen);
-}
-
static void midx_included_packs(struct string_list *include,
struct existing_packs *existing,
char **midx_pack_names,
diff --git a/meson.build b/meson.build
index 9afd45ea45..0373d5c454 100644
--- a/meson.build
+++ b/meson.build
@@ -464,6 +464,7 @@ libgit_sources = [
'remote.c',
'repack.c',
'repack-geometry.c',
+ 'repack-midx.c',
'repack-promisor.c',
'replace-object.c',
'repo-settings.c',
diff --git a/repack-midx.c b/repack-midx.c
new file mode 100644
index 0000000000..354df729a5
--- /dev/null
+++ b/repack-midx.c
@@ -0,0 +1,77 @@
+#include "git-compat-util.h"
+#include "repack.h"
+#include "hash.h"
+#include "hex.h"
+#include "odb.h"
+#include "oidset.h"
+#include "pack-bitmap.h"
+#include "refs.h"
+#include "tempfile.h"
+
+struct midx_snapshot_ref_data {
+ struct repository *repo;
+ struct tempfile *f;
+ struct oidset seen;
+ int preferred;
+};
+
+static int midx_snapshot_ref_one(const char *refname UNUSED,
+ const char *referent UNUSED,
+ const struct object_id *oid,
+ int flag UNUSED, void *_data)
+{
+ struct midx_snapshot_ref_data *data = _data;
+ struct object_id peeled;
+
+ if (!peel_iterated_oid(data->repo, oid, &peeled))
+ oid = &peeled;
+
+ if (oidset_insert(&data->seen, oid))
+ return 0; /* already seen */
+
+ if (odb_read_object_info(data->repo->objects, oid, NULL) != OBJ_COMMIT)
+ return 0;
+
+ fprintf(data->f->fp, "%s%s\n", data->preferred ? "+" : "",
+ oid_to_hex(oid));
+
+ return 0;
+}
+
+void midx_snapshot_refs(struct repository *repo, struct tempfile *f)
+{
+ struct midx_snapshot_ref_data data;
+ const struct string_list *preferred = bitmap_preferred_tips(repo);
+
+ data.repo = repo;
+ data.f = f;
+ data.preferred = 0;
+ oidset_init(&data.seen, 0);
+
+ if (!fdopen_tempfile(f, "w"))
+ die(_("could not open tempfile %s for writing"),
+ get_tempfile_path(f));
+
+ if (preferred) {
+ struct string_list_item *item;
+
+ data.preferred = 1;
+ for_each_string_list_item(item, preferred)
+ refs_for_each_ref_in(get_main_ref_store(repo),
+ item->string,
+ midx_snapshot_ref_one, &data);
+ data.preferred = 0;
+ }
+
+ refs_for_each_ref(get_main_ref_store(repo),
+ midx_snapshot_ref_one, &data);
+
+ if (close_tempfile_gently(f)) {
+ int save_errno = errno;
+ delete_tempfile(&f);
+ errno = save_errno;
+ die_errno(_("could not close refs snapshot tempfile"));
+ }
+
+ oidset_clear(&data.seen);
+}
diff --git a/repack.h b/repack.h
index cea7969ae4..803e129224 100644
--- a/repack.h
+++ b/repack.h
@@ -98,4 +98,8 @@ void pack_geometry_remove_redundant(struct pack_geometry *geometry,
const char *packdir);
void pack_geometry_release(struct pack_geometry *geometry);

+struct tempfile;
+
+void midx_snapshot_refs(struct repository *repo, struct tempfile *f);
+
#endif /* REPACK_H */
--
2.51.0.540.ga7423965ad8