packfile: split up responsibilities of `reprepare_packed_git()`

In `reprepare_packed_git()` we perform a couple of operations:

  - We reload alternate object directories.

  - We clear the loose object cache.

  - We reprepare packfiles.

While the logic is hosted in "packfile.c", it clearly reaches into other
subsystems that aren't related to packfiles.

Split up the responsibility and introduce `odb_reprepare()` which now
becomes responsible for repreparing the whole object database. The
existing `reprepare_packed_git()` function is refactored accordingly and
only cares about reloading the packfile store now.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
main
Patrick Steinhardt 2025-09-23 12:17:08 +02:00 committed by Junio C Hamano
parent c36ecc0685
commit 78237ea53d
13 changed files with 55 additions and 35 deletions

View File

@ -53,7 +53,7 @@ static void download_batch(struct backfill_context *ctx)
* We likely have a new packfile. Add it to the packed list to
* avoid possible duplicate downloads of the same objects.
*/
reprepare_packed_git(ctx->repo);
odb_reprepare(ctx->repo->objects);
}

static int fill_missing_blobs(const char *path UNUSED,

View File

@ -1042,7 +1042,7 @@ int cmd_gc(int argc,
die(FAILED_RUN, "rerere");

report_garbage = report_pack_garbage;
reprepare_packed_git(the_repository);
odb_reprepare(the_repository->objects);
if (pack_garbage.nr > 0) {
close_object_store(the_repository->objects);
clean_pack_garbage();
@ -1491,7 +1491,7 @@ static off_t get_auto_pack_size(void)
struct packed_git *p;
struct repository *r = the_repository;

reprepare_packed_git(r);
odb_reprepare(r->objects);
for (p = get_all_packs(r); p; p = p->next) {
if (p->pack_size > max_size) {
second_largest_size = max_size;

View File

@ -2389,7 +2389,7 @@ static const char *unpack(int err_fd, struct shallow_info *si)
status = finish_command(&child);
if (status)
return "index-pack abnormal exit";
reprepare_packed_git(the_repository);
odb_reprepare(the_repository->objects);
}
return NULL;
}

View File

@ -1685,7 +1685,7 @@ int cmd_repack(int argc,
goto cleanup;
}

reprepare_packed_git(the_repository);
odb_reprepare(the_repository->objects);

if (delete_redundant) {
int opts = 0;

View File

@ -90,7 +90,7 @@ clear_exit:

strbuf_release(&packname);
/* Make objects we just wrote available to ourselves */
reprepare_packed_git(the_repository);
odb_reprepare(the_repository->objects);
}

/*

View File

@ -72,7 +72,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
* Before checking for promisor packs, be sure we have the
* latest pack-files loaded into memory.
*/
reprepare_packed_git(the_repository);
odb_reprepare(the_repository->objects);
do {
struct packed_git *p;


View File

@ -1983,7 +1983,7 @@ static void update_shallow(struct fetch_pack_args *args,
* remote is shallow, but this is a clone, there are
* no objects in repo to worry about. Accept any
* shallow points that exist in the pack (iow in repo
* after get_pack() and reprepare_packed_git())
* after get_pack() and odb_reprepare())
*/
struct oid_array extra = OID_ARRAY_INIT;
struct object_id *oid = si->shallow->oid;
@ -2108,7 +2108,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
&si, pack_lockfiles);
}
reprepare_packed_git(the_repository);
odb_reprepare(the_repository->objects);

if (!args->cloning && args->deepen) {
struct check_connected_options opt = CHECK_CONNECTED_INIT;

View File

@ -596,7 +596,7 @@ static enum get_oid_result get_short_oid(struct repository *r,
* or migrated from loose to packed.
*/
if (status == MISSING_OBJECT) {
reprepare_packed_git(r);
odb_reprepare(r->objects);
find_short_object_filename(&ds);
find_short_packed_object(&ds);
status = finish_object_disambiguation(&ds, oid);

27
odb.c
View File

@ -694,7 +694,7 @@ static int do_oid_object_info_extended(struct object_database *odb,

/* Not a loose object; someone else may have just packed it. */
if (!(flags & OBJECT_INFO_QUICK)) {
reprepare_packed_git(odb->repo);
odb_reprepare(odb->repo->objects);
if (find_pack_entry(odb->repo, real, &e))
break;
}
@ -1040,3 +1040,28 @@ void odb_clear(struct object_database *o)

string_list_clear(&o->submodule_source_paths, 0);
}

void odb_reprepare(struct object_database *o)
{
struct odb_source *source;

obj_read_lock();

/*
* Reprepare alt odbs, in case the alternates file was modified
* during the course of this process. This only _adds_ odbs to
* the linked list, so existing odbs will continue to exist for
* the lifetime of the process.
*/
o->loaded_alternates = 0;
odb_prepare_alternates(o);

for (source = o->sources; source; source = source->next)
odb_clear_loose_cache(source);

o->approximate_object_count_valid = 0;

packfile_store_reprepare(o->packfiles);

obj_read_unlock();
}

6
odb.h
View File

@ -161,6 +161,12 @@ struct object_database {
struct object_database *odb_new(struct repository *repo);
void odb_clear(struct object_database *o);

/*
* Clear caches, reload alternates and then reload object sources so that new
* objects may become accessible.
*/
void odb_reprepare(struct object_database *o);

/*
* Find source by its object directory path. Returns a `NULL` pointer in case
* the source could not be found.

View File

@ -1002,28 +1002,10 @@ static void packfile_store_prepare(struct packfile_store *store)
store->initialized = true;
}

void reprepare_packed_git(struct repository *r)
void packfile_store_reprepare(struct packfile_store *store)
{
struct odb_source *source;

obj_read_lock();

/*
* Reprepare alt odbs, in case the alternates file was modified
* during the course of this process. This only _adds_ odbs to
* the linked list, so existing odbs will continue to exist for
* the lifetime of the process.
*/
r->objects->loaded_alternates = 0;
odb_prepare_alternates(r->objects);

for (source = r->objects->sources; source; source = source->next)
odb_clear_loose_cache(source);

r->objects->approximate_object_count_valid = 0;
r->objects->packfiles->initialized = false;
packfile_store_prepare(r->objects->packfiles);
obj_read_unlock();
store->initialized = false;
packfile_store_prepare(store);
}

struct packed_git *get_packed_git(struct repository *r)
@ -1144,7 +1126,7 @@ unsigned long get_size_from_delta(struct packed_git *p,
*
* Other worrying sections could be the call to close_pack_fd(),
* which can close packs even with in-use windows, and to
* reprepare_packed_git(). Regarding the former, mmap doc says:
* odb_reprepare(). Regarding the former, mmap doc says:
* "closing the file descriptor does not unmap the region". And
* for the latter, it won't re-open already available packs.
*/

View File

@ -112,6 +112,14 @@ void packfile_store_free(struct packfile_store *store);
*/
void packfile_store_close(struct packfile_store *store);

/*
* Clear the packfile caches and try to look up any new packfiles that have
* appeared since last preparing the packfiles store.
*
* This function must be called under the `odb_read_lock()`.
*/
void packfile_store_reprepare(struct packfile_store *store);

struct pack_window {
struct pack_window *next;
unsigned char *base;
@ -188,7 +196,6 @@ int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
#define PACKDIR_FILE_GARBAGE 4
extern void (*report_garbage)(unsigned seen_bits, const char *path);

void reprepare_packed_git(struct repository *r);
void install_packed_git(struct repository *r, struct packed_git *pack);

struct packed_git *get_packed_git(struct repository *r);

View File

@ -450,7 +450,7 @@ static int fetch_with_fetch(struct transport *transport,
}
strbuf_release(&buf);

reprepare_packed_git(the_repository);
odb_reprepare(the_repository->objects);
return 0;
}