]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb/source: generalize `reprepare()` callback
authorPatrick Steinhardt <ps@pks.im>
Mon, 22 Jun 2026 08:47:54 +0000 (10:47 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 22 Jun 2026 17:41:03 +0000 (10:41 -0700)
The `reprepare()` callback function can be used to flush caches of a
given object source and then prepare it anew. This is for example used
when a concurrent process may have written new objects. Ultimately, this
can be seen as doing two separate steps:

  1. We drop any caches.

  2. We prepare the source.

We have one callsite in git-grep(1) though that really only want to do
(2). This is done by reaching into the "files" backend directly and then
calling `odb_source_packed_prepare()`, which of course may not work with
alternate backends.

We could in theory just call `reprepare()` here, and that would likely
not have any significant downside. But this would certainly feel like a
code smell.

Instead, generalize the `reprepare()` callback to `prepare()` with a
flag that optionally instructs the backend to also flush the caches,
which allows us to drop the external `odb_source_packed_prepare()`
declaration.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/grep.c
midx.c
odb.c
odb.h
odb/source-files.c
odb/source-inmemory.c
odb/source-loose.c
odb/source-packed.c
odb/source-packed.h
odb/source.h
packfile.c

index 8080d1bf5ec2b47280535b3758547e993031ab52..7361bf071ed1623a2df5e8dc16ec5be172ea596e 100644 (file)
 #include "setup.h"
 #include "submodule.h"
 #include "submodule-config.h"
-#include "object-file.h"
 #include "object-name.h"
 #include "odb.h"
+#include "odb/source.h"
 #include "oid-array.h"
 #include "oidset.h"
-#include "packfile.h"
 #include "pager.h"
 #include "path.h"
 #include "promisor-remote.h"
@@ -1361,10 +1360,8 @@ int cmd_grep(int argc,
                        struct odb_source *source;
 
                        odb_prepare_alternates(the_repository->objects);
-                       for (source = the_repository->objects->sources; source; source = source->next) {
-                               struct odb_source_files *files = odb_source_files_downcast(source);
-                               odb_source_packed_prepare(files->packed);
-                       }
+                       for (source = the_repository->objects->sources; source; source = source->next)
+                               odb_source_prepare(source, 0);
                }
 
                start_threads(&opt);
diff --git a/midx.c b/midx.c
index cc6b94f9dd4fba3a5e632e4558aa9f7ffe9ff7b4..76c3f92cc374b80caeb0a13ccd6ae6f2eb4b9cdb 100644 (file)
--- a/midx.c
+++ b/midx.c
@@ -101,7 +101,7 @@ static int midx_read_object_offsets(const unsigned char *chunk_start,
 
 struct multi_pack_index *get_multi_pack_index(struct odb_source_packed *source)
 {
-       odb_source_packed_prepare(source);
+       odb_source_prepare(&source->base, 0);
        return source->midx;
 }
 
diff --git a/odb.c b/odb.c
index 965ef68e4eca222bc1af9a900665916b2231068f..7b45390e129680f79988121bfab8840276a338f4 100644 (file)
--- a/odb.c
+++ b/odb.c
@@ -1086,7 +1086,7 @@ void odb_reprepare(struct object_database *o)
        odb_prepare_alternates(o);
 
        for (source = o->sources; source; source = source->next)
-               odb_source_reprepare(source);
+               odb_source_prepare(source, ODB_PREPARE_FLUSH_CACHES);
 
        o->object_count_valid = 0;
 
diff --git a/odb.h b/odb.h
index 0030467a52a4e514ae3830195b5caf46259f9a95..c14c9030e47648ae3d0c2accaa7ea1fc101d1b37 100644 (file)
--- a/odb.h
+++ b/odb.h
@@ -124,6 +124,14 @@ void odb_free(struct object_database *o);
  */
 void odb_close(struct object_database *o);
 
+enum odb_prepare_flags {
+       /*
+        * Flush caches, reload alternates and then re-prepare each object
+        * source so that new objects may become accessible.
+        */
+       ODB_PREPARE_FLUSH_CACHES = (1 << 0),
+};
+
 /*
  * Clear caches, reload alternates and then reload object sources so that new
  * objects may become accessible.
index 3bc6419dd7e2f9c56a2fc58db63ea29c8e699bf3..ad9e0b52f9134cf01530586ca145069a769076cf 100644 (file)
@@ -41,11 +41,12 @@ static void odb_source_files_close(struct odb_source *source)
        odb_source_close(&files->packed->base);
 }
 
-static void odb_source_files_reprepare(struct odb_source *source)
+static void odb_source_files_prepare(struct odb_source *source,
+                                    enum odb_prepare_flags flags)
 {
        struct odb_source_files *files = odb_source_files_downcast(source);
-       odb_source_reprepare(&files->loose->base);
-       odb_source_reprepare(&files->packed->base);
+       odb_source_prepare(&files->loose->base, flags);
+       odb_source_prepare(&files->packed->base, flags);
 }
 
 static int odb_source_files_read_object_info(struct odb_source *source,
@@ -273,7 +274,7 @@ struct odb_source_files *odb_source_files_new(struct object_database *odb,
 
        files->base.free = odb_source_files_free;
        files->base.close = odb_source_files_close;
-       files->base.reprepare = odb_source_files_reprepare;
+       files->base.prepare = odb_source_files_prepare;
        files->base.read_object_info = odb_source_files_read_object_info;
        files->base.read_object_stream = odb_source_files_read_object_stream;
        files->base.for_each_object = odb_source_files_for_each_object;
index e004566d768b01c62163c9cfef34a664ba102a56..cc5e9e62cbb5e773f71779a609825ba82d3867d0 100644 (file)
@@ -325,7 +325,8 @@ static void odb_source_inmemory_close(struct odb_source *source UNUSED)
 {
 }
 
-static void odb_source_inmemory_reprepare(struct odb_source *source UNUSED)
+static void odb_source_inmemory_prepare(struct odb_source *source UNUSED,
+                                       enum odb_prepare_flags flags UNUSED)
 {
 }
 
@@ -365,7 +366,7 @@ struct odb_source_inmemory *odb_source_inmemory_new(struct object_database *odb)
 
        source->base.free = odb_source_inmemory_free;
        source->base.close = odb_source_inmemory_close;
-       source->base.reprepare = odb_source_inmemory_reprepare;
+       source->base.prepare = odb_source_inmemory_prepare;
        source->base.read_object_info = odb_source_inmemory_read_object_info;
        source->base.read_object_stream = odb_source_inmemory_read_object_stream;
        source->base.for_each_object = odb_source_inmemory_for_each_object;
index 7d7ea2fb842537fe924e4761d5b56f8bbfde1e4d..af46316e35d60bd58a5a2062f70cb2dafdc7c9c3 100644 (file)
@@ -672,10 +672,12 @@ static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
               sizeof(loose->subdir_seen));
 }
 
-static void odb_source_loose_reprepare(struct odb_source *source)
+static void odb_source_loose_prepare(struct odb_source *source,
+                                    enum odb_prepare_flags flags)
 {
        struct odb_source_loose *loose = odb_source_loose_downcast(source);
-       odb_source_loose_clear_cache(loose);
+       if (flags & ODB_PREPARE_FLUSH_CACHES)
+               odb_source_loose_clear_cache(loose);
 }
 
 static void odb_source_loose_close(struct odb_source *source UNUSED)
@@ -716,7 +718,7 @@ struct odb_source_loose *odb_source_loose_new(struct object_database *odb,
 
        loose->base.free = odb_source_loose_free;
        loose->base.close = odb_source_loose_close;
-       loose->base.reprepare = odb_source_loose_reprepare;
+       loose->base.prepare = odb_source_loose_prepare;
        loose->base.read_object_info = odb_source_loose_read_object_info;
        loose->base.read_object_stream = odb_source_loose_read_object_stream;
        loose->base.for_each_object = odb_source_loose_for_each_object;
index 42c28fba0e34b260d5e059b56acf11be6a56d63f..fa5a072488d5c701c52b7bb4beef5fdb629e04b8 100644 (file)
@@ -15,7 +15,7 @@ static int find_pack_entry(struct odb_source_packed *store,
 {
        struct packfile_list_entry *l;
 
-       odb_source_packed_prepare(store);
+       odb_source_prepare(&store->base, 0);
        if (store->midx && fill_midx_entry(store->midx, oid, e))
                return 1;
 
@@ -47,7 +47,7 @@ static int odb_source_packed_read_object_info(struct odb_source *source,
         * been added since the last time we have prepared the packfile store.
         */
        if (flags & OBJECT_INFO_SECOND_READ)
-               odb_source_reprepare(source);
+               odb_source_prepare(source, ODB_PREPARE_FLUSH_CACHES);
 
        if (!find_pack_entry(packed, oid, &e))
                return 1;
@@ -668,27 +668,25 @@ static int sort_pack(const struct packfile_list_entry *a,
        return -1;
 }
 
-void odb_source_packed_prepare(struct odb_source_packed *source)
+static void odb_source_packed_prepare(struct odb_source *source,
+                                     enum odb_prepare_flags flags)
 {
-       if (source->initialized)
+       struct odb_source_packed *packed = odb_source_packed_downcast(source);
+
+       if (flags & ODB_PREPARE_FLUSH_CACHES)
+               packed->initialized = false;
+       if (packed->initialized)
                return;
 
-       prepare_multi_pack_index_one(source);
-       prepare_packed_git_one(source);
+       prepare_multi_pack_index_one(packed);
+       prepare_packed_git_one(packed);
 
-       sort_packs(&source->packs.head, sort_pack);
-       for (struct packfile_list_entry *e = source->packs.head; e; e = e->next)
+       sort_packs(&packed->packs.head, sort_pack);
+       for (struct packfile_list_entry *e = packed->packs.head; e; e = e->next)
                if (!e->next)
-                       source->packs.tail = e;
+                       packed->packs.tail = e;
 
-       source->initialized = true;
-}
-
-static void odb_source_packed_reprepare(struct odb_source *source)
-{
-       struct odb_source_packed *packed = odb_source_packed_downcast(source);
-       packed->initialized = false;
-       odb_source_packed_prepare(packed);
+       packed->initialized = true;
 }
 
 static void odb_source_packed_reparent(const char *name UNUSED,
@@ -744,7 +742,7 @@ struct odb_source_packed *odb_source_packed_new(struct object_database *odb,
 
        packed->base.free = odb_source_packed_free;
        packed->base.close = odb_source_packed_close;
-       packed->base.reprepare = odb_source_packed_reprepare;
+       packed->base.prepare = odb_source_packed_prepare;
        packed->base.read_object_info = odb_source_packed_read_object_info;
        packed->base.read_object_stream = odb_source_packed_read_object_stream;
        packed->base.for_each_object = odb_source_packed_for_each_object;
index 88994098c18e7d12ac6d57566d63ecdf5cdc35a6..d5230ac68c12972fa327e4a56c2fff319e00b19a 100644 (file)
@@ -82,13 +82,4 @@ static inline struct odb_source_packed *odb_source_packed_downcast(struct odb_so
        return container_of(source, struct odb_source_packed, base);
 }
 
-/*
- * Prepare the source by loading packfiles and multi-pack indices for
- * all alternates. This becomes a no-op if the source is already prepared.
- *
- * It shouldn't typically be necessary to call this function directly, as
- * functions that access the source know to prepare it.
- */
-void odb_source_packed_prepare(struct odb_source_packed *source);
-
 #endif
index b9a7642b2c3c02a66eab401c7e00e4adcc5169bc..bbf1da3819e0a5340de6fbe2c80786088c4fd840 100644 (file)
@@ -83,11 +83,12 @@ struct odb_source {
        void (*close)(struct odb_source *source);
 
        /*
-        * This callback is expected to clear underlying caches of the object
-        * database source. The function is called when the repository has for
-        * example just been repacked so that new objects will become visible.
+        * This callback is expected to prepare the source so that it becomes
+        * ready for use. It optionally clears underlying caches of the object
+        * database source.
         */
-       void (*reprepare)(struct odb_source *source);
+       void (*prepare)(struct odb_source *source,
+                       enum odb_prepare_flags flags);
 
        /*
         * This callback is expected to read object information from the object
@@ -308,13 +309,14 @@ static inline void odb_source_close(struct odb_source *source)
 }
 
 /*
- * Reprepare the object database source and clear any caches. Depending on the
+ * Prepare the object database source and clear any caches. Depending on the
  * backend used this may have the effect that concurrently-written objects
  * become visible.
  */
-static inline void odb_source_reprepare(struct odb_source *source)
+static inline void odb_source_prepare(struct odb_source *source,
+                                     enum odb_prepare_flags flags)
 {
-       source->reprepare(source);
+       source->prepare(source, flags);
 }
 
 /*
index 59cee7925daf0be593eef5d0c7c4dca131dec08f..d78fae981a8ad877cafd6f9362a8082b2fbddebf 100644 (file)
@@ -855,7 +855,7 @@ void for_each_file_in_pack_dir(const char *objdir,
 
 struct packfile_list_entry *packfile_store_get_packs(struct odb_source_packed *store)
 {
-       odb_source_packed_prepare(store);
+       odb_source_prepare(&store->base, 0);
 
        if (store->midx) {
                struct multi_pack_index *m = store->midx;