]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb: introduce "in-memory" source
authorPatrick Steinhardt <ps@pks.im>
Fri, 10 Apr 2026 12:12:31 +0000 (14:12 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 14 May 2026 19:50:44 +0000 (04:50 +0900)
Next to our typical object database sources, each object database also
has an implicit source of "cached" objects. These cached objects only
exist in memory and some use cases:

  - They contain evergreen objects that we expect to always exist, like
    for example the empty tree.

  - They can be used to store temporary objects that we don't want to
    persist to disk, which is used by git-blame(1) to create a fake
    worktree commit.

Overall, their use is somewhat restricted though. For example, we don't
provide the ability to use it as a temporary object database source that
allows the user to write objects, but discard them after Git exists. So
while these cached objects behave almost like a source, they aren't used
as one.

This is about to change over the following commits, where we will turn
cached objects into a new "in-memory" source. This will allow us to use
it exactly the same as any other source by providing the same common
interface as the "files" source.

For now, the in-memory source only hosts the cached objects and doesn't
provide any logic yet. This will change with subsequent commits, where
we move respective functionality into the source.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Makefile
meson.build
odb.c
odb.h
odb/source-inmemory.c [new file with mode: 0644]
odb/source-inmemory.h [new file with mode: 0644]
odb/source.h

index 22a8993482b7bda41bf45e80be15507a3aa24037..3cda12c4556a6f8b695d44b87a11dbe6a53062ff 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1218,6 +1218,7 @@ LIB_OBJS += object.o
 LIB_OBJS += odb.o
 LIB_OBJS += odb/source.o
 LIB_OBJS += odb/source-files.o
+LIB_OBJS += odb/source-inmemory.o
 LIB_OBJS += odb/streaming.o
 LIB_OBJS += odb/transaction.o
 LIB_OBJS += oid-array.o
index 6dc23b3af2f387bf3a559a7a9002ae6f259ec580..ffa73ce7ce811c5e72991b2030eba4b726baccf8 100644 (file)
@@ -404,6 +404,7 @@ libgit_sources = [
   'odb.c',
   'odb/source.c',
   'odb/source-files.c',
+  'odb/source-inmemory.c',
   'odb/streaming.c',
   'odb/transaction.c',
   'oid-array.c',
diff --git a/odb.c b/odb.c
index 40a5e9c4e0ae53f04c4504abf94a4c92896dac2c..60e1eead25602a1682946b032f0b3a4e37d26ee2 100644 (file)
--- a/odb.c
+++ b/odb.c
@@ -14,6 +14,7 @@
 #include "object-file.h"
 #include "object-name.h"
 #include "odb.h"
+#include "odb/source-inmemory.h"
 #include "packfile.h"
 #include "path.h"
 #include "promisor-remote.h"
@@ -53,9 +54,9 @@ static const struct cached_object *find_cached_object(struct object_database *ob
                .type = OBJ_TREE,
                .buf = "",
        };
-       const struct cached_object_entry *co = object_store->cached_objects;
+       const struct cached_object_entry *co = object_store->inmemory_objects->objects;
 
-       for (size_t i = 0; i < object_store->cached_object_nr; i++, co++)
+       for (size_t i = 0; i < object_store->inmemory_objects->objects_nr; i++, co++)
                if (oideq(&co->oid, oid))
                        return &co->value;
 
@@ -792,9 +793,10 @@ int odb_pretend_object(struct object_database *odb,
            find_cached_object(odb, oid))
                return 0;
 
-       ALLOC_GROW(odb->cached_objects,
-                  odb->cached_object_nr + 1, odb->cached_object_alloc);
-       co = &odb->cached_objects[odb->cached_object_nr++];
+       ALLOC_GROW(odb->inmemory_objects->objects,
+                  odb->inmemory_objects->objects_nr + 1,
+                  odb->inmemory_objects->objects_alloc);
+       co = &odb->inmemory_objects->objects[odb->inmemory_objects->objects_nr++];
        co->value.size = len;
        co->value.type = type;
        co_buf = xmalloc(len);
@@ -1083,6 +1085,7 @@ struct object_database *odb_new(struct repository *repo,
        o->sources = odb_source_new(o, primary_source, true);
        o->sources_tail = &o->sources->next;
        o->alternate_db = xstrdup_or_null(secondary_sources);
+       o->inmemory_objects = odb_source_inmemory_new(o);
 
        free(to_free);
 
@@ -1123,9 +1126,11 @@ void odb_free(struct object_database *o)
        odb_close(o);
        odb_free_sources(o);
 
-       for (size_t i = 0; i < o->cached_object_nr; i++)
-               free((char *) o->cached_objects[i].value.buf);
-       free(o->cached_objects);
+       for (size_t i = 0; i < o->inmemory_objects->objects_nr; i++)
+               free((char *) o->inmemory_objects->objects[i].value.buf);
+       free(o->inmemory_objects->objects);
+       free(o->inmemory_objects->base.path);
+       free(o->inmemory_objects);
 
        string_list_clear(&o->submodule_source_paths, 0);
 
diff --git a/odb.h b/odb.h
index 9eb8355aca540be9aa9472f0fa2166eaf3aa04e7..c3a7edf9c848dd5103e0dad2fe301a7556cbacd6 100644 (file)
--- a/odb.h
+++ b/odb.h
@@ -8,6 +8,7 @@
 #include "thread-utils.h"
 
 struct cached_object_entry;
+struct odb_source_inmemory;
 struct packed_git;
 struct repository;
 struct strbuf;
@@ -80,8 +81,7 @@ struct object_database {
         * to write them into the object store (e.g. a browse-only
         * application).
         */
-       struct cached_object_entry *cached_objects;
-       size_t cached_object_nr, cached_object_alloc;
+       struct odb_source_inmemory *inmemory_objects;
 
        /*
         * A fast, rough count of the number of objects in the repository.
diff --git a/odb/source-inmemory.c b/odb/source-inmemory.c
new file mode 100644 (file)
index 0000000..c7ac5c2
--- /dev/null
@@ -0,0 +1,12 @@
+#include "git-compat-util.h"
+#include "odb/source-inmemory.h"
+
+struct odb_source_inmemory *odb_source_inmemory_new(struct object_database *odb)
+{
+       struct odb_source_inmemory *source;
+
+       CALLOC_ARRAY(source, 1);
+       odb_source_init(&source->base, odb, ODB_SOURCE_INMEMORY, "source", false);
+
+       return source;
+}
diff --git a/odb/source-inmemory.h b/odb/source-inmemory.h
new file mode 100644 (file)
index 0000000..15db068
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef ODB_SOURCE_INMEMORY_H
+#define ODB_SOURCE_INMEMORY_H
+
+#include "odb/source.h"
+
+struct cached_object_entry;
+
+/*
+ * An in-memory source that you can write objects to that shall be made
+ * available for reading, but that shouldn't ever be persisted to disk. Note
+ * that any objects written to this source will be stored in memory, so the
+ * number of objects you can store is limited by available system memory.
+ */
+struct odb_source_inmemory {
+       struct odb_source base;
+
+       struct cached_object_entry *objects;
+       size_t objects_nr, objects_alloc;
+};
+
+/* Create a new in-memory object database source. */
+struct odb_source_inmemory *odb_source_inmemory_new(struct object_database *odb);
+
+/*
+ * Cast the given object database source to the in-memory backend. This will
+ * cause a BUG in case the source doesn't use this backend.
+ */
+static inline struct odb_source_inmemory *odb_source_inmemory_downcast(struct odb_source *source)
+{
+       if (source->type != ODB_SOURCE_INMEMORY)
+               BUG("trying to downcast source of type '%d' to in-memory", source->type);
+       return container_of(source, struct odb_source_inmemory, base);
+}
+
+#endif
index f706e0608a48559885e21d1b7aab884bf6db47e7..0a440884e4f0ab002b085cdbbe2b49d4600c5e57 100644 (file)
@@ -13,6 +13,9 @@ enum odb_source_type {
 
        /* The "files" backend that uses loose objects and packfiles. */
        ODB_SOURCE_FILES,
+
+       /* The "in-memory" backend that stores objects in memory. */
+       ODB_SOURCE_INMEMORY,
 };
 
 struct object_id;