Merge branch 'ps/object-store-midx' into ps/object-store-midx-dedup-info

* ps/object-store-midx:
  midx: remove now-unused linked list of multi-pack indices
  packfile: stop using linked MIDX list in `get_all_packs()`
  packfile: stop using linked MIDX list in `find_pack_entry()`
  packfile: refactor `get_multi_pack_index()` to work on sources
  midx: stop using linked list when closing MIDX
  packfile: refactor `prepare_packed_git_one()` to work on sources
  midx: start tracking per object database source
main
Junio C Hamano 2025-07-29 11:34:08 -07:00
commit 70b7b03f98
10 changed files with 107 additions and 124 deletions

View File

@ -1706,8 +1706,8 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
uint32_t found_mtime)
{
int want;
struct odb_source *source;
struct list_head *pos;
struct multi_pack_index *m;

if (!exclude && local && has_loose_object_nonlocal(oid))
return 0;
@ -1727,9 +1727,13 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
*found_offset = 0;
}

for (m = get_multi_pack_index(the_repository); m; m = m->next) {
odb_prepare_alternates(the_repository->objects);

for (source = the_repository->objects->sources; source; source = source->next) {
struct multi_pack_index *m = get_multi_pack_index(source);
struct pack_entry e;
if (fill_midx_entry(the_repository, oid, &e, m)) {

if (m && fill_midx_entry(the_repository, oid, &e, m)) {
want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime);
if (want != -1)
return want;

View File

@ -223,9 +223,9 @@ static void mark_packs_for_deletion(struct existing_packs *existing,
static void remove_redundant_pack(const char *dir_name, const char *base_name)
{
struct strbuf buf = STRBUF_INIT;
struct multi_pack_index *m = get_local_multi_pack_index(the_repository);
struct multi_pack_index *m = get_multi_pack_index(the_repository->objects->sources);
strbuf_addf(&buf, "%s.pack", base_name);
if (m && midx_contains_pack(m, buf.buf))
if (m && m->local && midx_contains_pack(m, buf.buf))
clear_midx_file(the_repository);
strbuf_insertf(&buf, 0, "%s/", dir_name);
unlink_pack_path(buf.buf, 1);
@ -1531,7 +1531,7 @@ int cmd_repack(int argc,
* midx_has_unknown_packs() will make the decision for
* us.
*/
if (!get_local_multi_pack_index(the_repository))
if (!get_multi_pack_index(the_repository->objects->sources))
midx_must_contain_cruft = 1;
}

@ -1614,9 +1614,9 @@ int cmd_repack(int argc,

string_list_sort(&names);

if (get_local_multi_pack_index(the_repository)) {
if (get_multi_pack_index(the_repository->objects->sources)) {
struct multi_pack_index *m =
get_local_multi_pack_index(the_repository);
get_multi_pack_index(the_repository->objects->sources);

ALLOC_ARRAY(midx_pack_names,
m->num_packs + m->num_packs_in_base);

View File

@ -916,26 +916,8 @@ cleanup:
static struct multi_pack_index *lookup_multi_pack_index(struct repository *r,
const char *object_dir)
{
struct multi_pack_index *result = NULL;
struct multi_pack_index *cur;
char *obj_dir_real = real_pathdup(object_dir, 1);
struct strbuf cur_path_real = STRBUF_INIT;

/* Ensure the given object_dir is local, or a known alternate. */
odb_find_source(r->objects, obj_dir_real);

for (cur = get_multi_pack_index(r); cur; cur = cur->next) {
strbuf_realpath(&cur_path_real, cur->object_dir, 1);
if (!strcmp(obj_dir_real, cur_path_real.buf)) {
result = cur;
goto cleanup;
}
}

cleanup:
free(obj_dir_real);
strbuf_release(&cur_path_real);
return result;
struct odb_source *source = odb_find_source(r->objects, object_dir);
return get_multi_pack_index(source);
}

static int fill_packs_from_midx(struct write_midx_context *ctx,

36
midx.c
View File

@ -401,7 +401,6 @@ void close_midx(struct multi_pack_index *m)
if (!m)
return;

close_midx(m->next);
close_midx(m->base_midx);

munmap((unsigned char *)m->data, m->data_len);
@ -724,32 +723,20 @@ int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id)
return 0;
}

int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local)
int prepare_multi_pack_index_one(struct odb_source *source, int local)
{
struct multi_pack_index *m;
struct multi_pack_index *m_search;
struct repository *r = source->odb->repo;

prepare_repo_settings(r);
if (!r->settings.core_multi_pack_index)
return 0;

for (m_search = r->objects->multi_pack_index; m_search; m_search = m_search->next)
if (!strcmp(object_dir, m_search->object_dir))
return 1;

m = load_multi_pack_index(r, object_dir, local);

if (m) {
struct multi_pack_index *mp = r->objects->multi_pack_index;
if (mp) {
m->next = mp->next;
mp->next = m;
} else
r->objects->multi_pack_index = m;
if (source->midx)
return 1;
}

return 0;
source->midx = load_multi_pack_index(r, source->path, local);

return !!source->midx;
}

int midx_checksum_valid(struct multi_pack_index *m)
@ -834,9 +821,14 @@ void clear_midx_file(struct repository *r)

get_midx_filename(r->hash_algo, &midx, r->objects->sources->path);

if (r->objects && r->objects->multi_pack_index) {
close_midx(r->objects->multi_pack_index);
r->objects->multi_pack_index = NULL;
if (r->objects) {
struct odb_source *source;

for (source = r->objects->sources; source; source = source->next) {
if (source->midx)
close_midx(source->midx);
source->midx = NULL;
}
}

if (remove_path(midx.buf))

5
midx.h
View File

@ -8,6 +8,7 @@ struct pack_entry;
struct repository;
struct bitmapped_pack;
struct git_hash_algo;
struct odb_source;

#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
#define MIDX_VERSION 1
@ -34,8 +35,6 @@ struct git_hash_algo;
"GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL"

struct multi_pack_index {
struct multi_pack_index *next;

const unsigned char *data;
size_t data_len;

@ -123,7 +122,7 @@ int fill_midx_entry(struct repository *r, const struct object_id *oid, struct pa
int midx_contains_pack(struct multi_pack_index *m,
const char *idx_or_pack_name);
int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id);
int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local);
int prepare_multi_pack_index_one(struct odb_source *source, int local);

/*
* Variant of write_midx_file which writes a MIDX containing only the packs

View File

@ -199,16 +199,20 @@ static void unique_in_pack(struct packed_git *p,

static void find_short_packed_object(struct disambiguate_state *ds)
{
struct multi_pack_index *m;
struct odb_source *source;
struct packed_git *p;

/* Skip, unless oids from the storage hash algorithm are wanted */
if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo))
return;

for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous;
m = m->next)
unique_in_midx(m, ds);
odb_prepare_alternates(ds->repo->objects);
for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) {
struct multi_pack_index *m = get_multi_pack_index(source);
if (m)
unique_in_midx(m, ds);
}

for (p = get_packed_git(ds->repo); p && !ds->ambiguous;
p = p->next)
unique_in_pack(p, ds);
@ -793,11 +797,15 @@ static void find_abbrev_len_for_pack(struct packed_git *p,

static void find_abbrev_len_packed(struct min_abbrev_data *mad)
{
struct multi_pack_index *m;
struct packed_git *p;

for (m = get_multi_pack_index(mad->repo); m; m = m->next)
find_abbrev_len_for_midx(m, mad);
odb_prepare_alternates(mad->repo->objects);
for (struct odb_source *source = mad->repo->objects->sources; source; source = source->next) {
struct multi_pack_index *m = get_multi_pack_index(source);
if (m)
find_abbrev_len_for_midx(m, mad);
}

for (p = get_packed_git(mad->repo); p; p = p->next)
find_abbrev_len_for_pack(p, mad);
}

16
odb.h
View File

@ -13,6 +13,7 @@ struct oidmap;
struct oidtree;
struct strbuf;
struct repository;
struct multi_pack_index;

/*
* Compute the exact path an alternate is at and returns it. In case of
@ -55,6 +56,13 @@ struct odb_source {
/* Map between object IDs for loose objects. */
struct loose_object_map *loose_map;

/*
* private data
*
* should only be accessed directly by packfile.c and midx.c
*/
struct multi_pack_index *midx;

/*
* This is a temporary object store created by the tmp_objdir
* facility. Disable ref updates since the objects in the store
@ -75,7 +83,6 @@ struct odb_source {
};

struct packed_git;
struct multi_pack_index;
struct cached_object_entry;

/*
@ -116,13 +123,6 @@ struct object_database {
struct commit_graph *commit_graph;
unsigned commit_graph_attempted : 1; /* if loading has been attempted */

/*
* private data
*
* should only be accessed directly by packfile.c and midx.c
*/
struct multi_pack_index *multi_pack_index;

/*
* private data
*

View File

@ -683,13 +683,15 @@ static int open_pack_bitmap(struct repository *r,
static int open_midx_bitmap(struct repository *r,
struct bitmap_index *bitmap_git)
{
struct odb_source *source;
int ret = -1;
struct multi_pack_index *midx;

assert(!bitmap_git->map);

for (midx = get_multi_pack_index(r); midx; midx = midx->next) {
if (!open_midx_bitmap_1(bitmap_git, midx))
odb_prepare_alternates(r->objects);
for (source = r->objects->sources; source; source = source->next) {
struct multi_pack_index *midx = get_multi_pack_index(source);
if (midx && !open_midx_bitmap_1(bitmap_git, midx))
ret = 0;
}
return ret;
@ -3345,11 +3347,18 @@ static int verify_bitmap_file(const struct git_hash_algo *algop,

int verify_bitmap_files(struct repository *r)
{
struct odb_source *source;
int res = 0;

for (struct multi_pack_index *m = get_multi_pack_index(r);
m; m = m->next) {
char *midx_bitmap_name = midx_bitmap_filename(m);
odb_prepare_alternates(r->objects);
for (source = r->objects->sources; source; source = source->next) {
struct multi_pack_index *m = get_multi_pack_index(source);
char *midx_bitmap_name;

if (!m)
continue;

midx_bitmap_name = midx_bitmap_filename(m);
res |= verify_bitmap_file(r->hash_algo, midx_bitmap_name);
free(midx_bitmap_name);
}

View File

@ -361,6 +361,7 @@ void close_pack(struct packed_git *p)

void close_object_store(struct object_database *o)
{
struct odb_source *source;
struct packed_git *p;

for (p = o->packed_git; p; p = p->next)
@ -369,9 +370,10 @@ void close_object_store(struct object_database *o)
else
close_pack(p);

if (o->multi_pack_index) {
close_midx(o->multi_pack_index);
o->multi_pack_index = NULL;
for (source = o->sources; source; source = source->next) {
if (source->midx)
close_midx(source->midx);
source->midx = NULL;
}

close_commit_graph(o);
@ -933,22 +935,17 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
report_garbage(PACKDIR_FILE_GARBAGE, full_name);
}

static void prepare_packed_git_one(struct repository *r, char *objdir, int local)
static void prepare_packed_git_one(struct odb_source *source, int local)
{
struct prepare_pack_data data;
struct string_list garbage = STRING_LIST_INIT_DUP;
struct prepare_pack_data data = {
.m = source->midx,
.r = source->odb->repo,
.garbage = &garbage,
.local = local,
};

data.m = r->objects->multi_pack_index;

/* look for the multi-pack-index for this object directory */
while (data.m && strcmp(data.m->object_dir, objdir))
data.m = data.m->next;

data.r = r;
data.garbage = &garbage;
data.local = local;

for_each_file_in_pack_dir(objdir, prepare_pack, &data);
for_each_file_in_pack_dir(source->path, prepare_pack, &data);

report_pack_garbage(data.garbage);
string_list_clear(data.garbage, 0);
@ -965,14 +962,18 @@ static void prepare_packed_git(struct repository *r);
unsigned long repo_approximate_object_count(struct repository *r)
{
if (!r->objects->approximate_object_count_valid) {
unsigned long count;
struct multi_pack_index *m;
struct odb_source *source;
unsigned long count = 0;
struct packed_git *p;

prepare_packed_git(r);
count = 0;
for (m = get_multi_pack_index(r); m; m = m->next)
count += m->num_objects;

for (source = r->objects->sources; source; source = source->next) {
struct multi_pack_index *m = get_multi_pack_index(source);
if (m)
count += m->num_objects;
}

for (p = r->objects->packed_git; p; p = p->next) {
if (open_pack_index(p))
continue;
@ -1037,8 +1038,8 @@ static void prepare_packed_git(struct repository *r)
odb_prepare_alternates(r->objects);
for (source = r->objects->sources; source; source = source->next) {
int local = (source == r->objects->sources);
prepare_multi_pack_index_one(r, source->path, local);
prepare_packed_git_one(r, source->path, local);
prepare_multi_pack_index_one(source, local);
prepare_packed_git_one(source, local);
}
rearrange_packed_git(r);

@ -1076,31 +1077,21 @@ struct packed_git *get_packed_git(struct repository *r)
return r->objects->packed_git;
}

struct multi_pack_index *get_multi_pack_index(struct repository *r)
struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
{
prepare_packed_git(r);
return r->objects->multi_pack_index;
}

struct multi_pack_index *get_local_multi_pack_index(struct repository *r)
{
struct multi_pack_index *m = get_multi_pack_index(r);

/* no need to iterate; we always put the local one first (if any) */
if (m && m->local)
return m;

return NULL;
prepare_packed_git(source->odb->repo);
return source->midx;
}

struct packed_git *get_all_packs(struct repository *r)
{
struct multi_pack_index *m;

prepare_packed_git(r);
for (m = r->objects->multi_pack_index; m; m = m->next) {
uint32_t i;
for (i = 0; i < m->num_packs + m->num_packs_in_base; i++)

for (struct odb_source *source = r->objects->sources; source; source = source->next) {
struct multi_pack_index *m = source->midx;
if (!m)
continue;
for (uint32_t i = 0; i < m->num_packs + m->num_packs_in_base; i++)
prepare_midx_pack(r, m, i);
}

@ -2083,16 +2074,15 @@ static int fill_pack_entry(const struct object_id *oid,
int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e)
{
struct list_head *pos;
struct multi_pack_index *m;

prepare_packed_git(r);
if (!r->objects->packed_git && !r->objects->multi_pack_index)
return 0;

for (m = r->objects->multi_pack_index; m; m = m->next) {
if (fill_midx_entry(r, oid, e, m))
for (struct odb_source *source = r->objects->sources; source; source = source->next)
if (source->midx && fill_midx_entry(r, oid, e, source->midx))
return 1;
}

if (!r->objects->packed_git)
return 0;

list_for_each(pos, &r->objects->packed_git_mru) {
struct packed_git *p = list_entry(pos, struct packed_git, mru);

View File

@ -147,8 +147,7 @@ void install_packed_git(struct repository *r, struct packed_git *pack);

struct packed_git *get_packed_git(struct repository *r);
struct list_head *get_packed_git_mru(struct repository *r);
struct multi_pack_index *get_multi_pack_index(struct repository *r);
struct multi_pack_index *get_local_multi_pack_index(struct repository *r);
struct multi_pack_index *get_multi_pack_index(struct odb_source *source);
struct packed_git *get_all_packs(struct repository *r);

/*