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>
Patrick Steinhardt committed
Sep 23, 2025 at 12:17 UTC
78237ea53d6546aeab7adb2c7547a1177311ccde
13 files changed
+55
-35
builtin/backfill.c
+1
-1
@@ -53,7 +53,7 @@ static void download_batch(struct backfill_context *ctx)
53
* We likely have a new packfile. Add it to the packed list to
54
* avoid possible duplicate downloads of the same objects.
55
*/
56
- reprepare_packed_git(ctx->repo);
56
+ odb_reprepare(ctx->repo->objects);
57
}
58
59
static int fill_missing_blobs(const char *path UNUSED,
builtin/gc.c
+2
-2
@@ -1042,7 +1042,7 @@ int cmd_gc(int argc,
1042
die(FAILED_RUN, "rerere");
1043
1044
report_garbage = report_pack_garbage;
1045
- reprepare_packed_git(the_repository);
1045
+ odb_reprepare(the_repository->objects);
1046
if (pack_garbage.nr > 0) {
1047
close_object_store(the_repository->objects);
1048
clean_pack_garbage();
@@ -1491,7 +1491,7 @@ static off_t get_auto_pack_size(void)
1491
struct packed_git *p;
1492
struct repository *r = the_repository;
1493
1494
- reprepare_packed_git(r);
1494
+ odb_reprepare(r->objects);
1495
for (p = get_all_packs(r); p; p = p->next) {
1496
if (p->pack_size > max_size) {
1497
second_largest_size = max_size;
builtin/receive-pack.c
+1
-1
@@ -2389,7 +2389,7 @@ static const char *unpack(int err_fd, struct shallow_info *si)
2389
status = finish_command(&child);
2390
if (status)
2391
return "index-pack abnormal exit";
2392
- reprepare_packed_git(the_repository);
2392
+ odb_reprepare(the_repository->objects);
2393
}
2394
return NULL;
2395
}
builtin/repack.c
+1
-1
@@ -1685,7 +1685,7 @@ int cmd_repack(int argc,
1685
goto cleanup;
1686
}
1687
1688
- reprepare_packed_git(the_repository);
1688
+ odb_reprepare(the_repository->objects);
1689
1690
if (delete_redundant) {
1691
int opts = 0;
bulk-checkin.c
+1
-1
@@ -90,7 +90,7 @@ clear_exit:
90
91
strbuf_release(&packname);
92
/* Make objects we just wrote available to ourselves */
93
- reprepare_packed_git(the_repository);
93
+ odb_reprepare(the_repository->objects);
94
}
95
96
/*
connected.c
+1
-1
@@ -72,7 +72,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
72
* Before checking for promisor packs, be sure we have the
73
* latest pack-files loaded into memory.
74
*/
75
- reprepare_packed_git(the_repository);
75
+ odb_reprepare(the_repository->objects);
76
do {
77
struct packed_git *p;
78
fetch-pack.c
+2
-2
@@ -1983,7 +1983,7 @@ static void update_shallow(struct fetch_pack_args *args,
1983
* remote is shallow, but this is a clone, there are
1984
* no objects in repo to worry about. Accept any
1985
* shallow points that exist in the pack (iow in repo
1986
- * after get_pack() and reprepare_packed_git())
1986
+ * after get_pack() and odb_reprepare())
1987
*/
1988
struct oid_array extra = OID_ARRAY_INIT;
1989
struct object_id *oid = si->shallow->oid;
@@ -2108,7 +2108,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
2108
ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
2109
&si, pack_lockfiles);
2110
}
2111
- reprepare_packed_git(the_repository);
2111
+ odb_reprepare(the_repository->objects);
2112
2113
if (!args->cloning && args->deepen) {
2114
struct check_connected_options opt = CHECK_CONNECTED_INIT;
object-name.c
+1
-1
@@ -596,7 +596,7 @@ static enum get_oid_result get_short_oid(struct repository *r,
596
* or migrated from loose to packed.
597
*/
598
if (status == MISSING_OBJECT) {
599
- reprepare_packed_git(r);
599
+ odb_reprepare(r->objects);
600
find_short_object_filename(&ds);
601
find_short_packed_object(&ds);
602
status = finish_object_disambiguation(&ds, oid);
odb.c
+26
-1
@@ -694,7 +694,7 @@ static int do_oid_object_info_extended(struct object_database *odb,
694
695
/* Not a loose object; someone else may have just packed it. */
696
if (!(flags & OBJECT_INFO_QUICK)) {
697
- reprepare_packed_git(odb->repo);
697
+ odb_reprepare(odb->repo->objects);
698
if (find_pack_entry(odb->repo, real, &e))
699
break;
700
}
@@ -1040,3 +1040,28 @@ void odb_clear(struct object_database *o)
1040
1041
string_list_clear(&o->submodule_source_paths, 0);
1042
}
1043
+
1044
+void odb_reprepare(struct object_database *o)
1045
+{
1046
+ struct odb_source *source;
1047
+
1048
+ obj_read_lock();
1049
+
1050
+ /*
1051
+ * Reprepare alt odbs, in case the alternates file was modified
1052
+ * during the course of this process. This only _adds_ odbs to
1053
+ * the linked list, so existing odbs will continue to exist for
1054
+ * the lifetime of the process.
1055
+ */
1056
+ o->loaded_alternates = 0;
1057
+ odb_prepare_alternates(o);
1058
+
1059
+ for (source = o->sources; source; source = source->next)
1060
+ odb_clear_loose_cache(source);
1061
+
1062
+ o->approximate_object_count_valid = 0;
1063
+
1064
+ packfile_store_reprepare(o->packfiles);
1065
+
1066
+ obj_read_unlock();
1067
+}
odb.h
+6
@@ -161,6 +161,12 @@ struct object_database {
161
struct object_database *odb_new(struct repository *repo);
162
void odb_clear(struct object_database *o);
163
164
+/*
165
+ * Clear caches, reload alternates and then reload object sources so that new
166
+ * objects may become accessible.
167
+ */
168
+void odb_reprepare(struct object_database *o);
169
+
170
/*
171
* Find source by its object directory path. Returns a `NULL` pointer in case
172
* the source could not be found.
packfile.c
+4
-22
@@ -1002,28 +1002,10 @@ static void packfile_store_prepare(struct packfile_store *store)
1002
store->initialized = true;
1003
}
1004
1005
-void reprepare_packed_git(struct repository *r)
1005
+void packfile_store_reprepare(struct packfile_store *store)
1006
{
1007
- struct odb_source *source;
1008
-
1009
- obj_read_lock();
1010
-
1011
- /*
1012
- * Reprepare alt odbs, in case the alternates file was modified
1013
- * during the course of this process. This only _adds_ odbs to
1014
- * the linked list, so existing odbs will continue to exist for
1015
- * the lifetime of the process.
1016
- */
1017
- r->objects->loaded_alternates = 0;
1018
- odb_prepare_alternates(r->objects);
1019
-
1020
- for (source = r->objects->sources; source; source = source->next)
1021
- odb_clear_loose_cache(source);
1022
-
1023
- r->objects->approximate_object_count_valid = 0;
1024
- r->objects->packfiles->initialized = false;
1025
- packfile_store_prepare(r->objects->packfiles);
1026
- obj_read_unlock();
1007
+ store->initialized = false;
1008
+ packfile_store_prepare(store);
1009
}
1010
1011
struct packed_git *get_packed_git(struct repository *r)
@@ -1144,7 +1126,7 @@ unsigned long get_size_from_delta(struct packed_git *p,
1126
*
1127
* Other worrying sections could be the call to close_pack_fd(),
1128
* which can close packs even with in-use windows, and to
1147
- * reprepare_packed_git(). Regarding the former, mmap doc says:
1129
+ * odb_reprepare(). Regarding the former, mmap doc says:
1130
* "closing the file descriptor does not unmap the region". And
1131
* for the latter, it won't re-open already available packs.
1132
*/
packfile.h
+8
-1
@@ -112,6 +112,14 @@ void packfile_store_free(struct packfile_store *store);
112
*/
113
void packfile_store_close(struct packfile_store *store);
114
115
+/*
116
+ * Clear the packfile caches and try to look up any new packfiles that have
117
+ * appeared since last preparing the packfiles store.
118
+ *
119
+ * This function must be called under the `odb_read_lock()`.
120
+ */
121
+void packfile_store_reprepare(struct packfile_store *store);
122
+
123
struct pack_window {
124
struct pack_window *next;
125
unsigned char *base;
@@ -188,7 +196,6 @@ int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
196
#define PACKDIR_FILE_GARBAGE 4
197
extern void (*report_garbage)(unsigned seen_bits, const char *path);
198
191
-void reprepare_packed_git(struct repository *r);
199
void install_packed_git(struct repository *r, struct packed_git *pack);
200
201
struct packed_git *get_packed_git(struct repository *r);
transport-helper.c
+1
-1
@@ -450,7 +450,7 @@ static int fetch_with_fetch(struct transport *transport,
450
}
451
strbuf_release(&buf);
452
453
- reprepare_packed_git(the_repository);
453
+ odb_reprepare(the_repository->objects);
454
return 0;
455
}
456