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>
This commit is contained in:
Taylor Blau
2025-10-15 18:28:50 -04:00
committed by Junio C Hamano
parent 62d3fa09b3
commit ccb7f822d5
5 changed files with 83 additions and 68 deletions

View File

@@ -1138,6 +1138,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

View File

@@ -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,

View File

@@ -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',

77
repack-midx.c Normal file
View File

@@ -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);
}

View File

@@ -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 */