]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb: make creation of on-disk structures pluggable
authorPatrick Steinhardt <ps@pks.im>
Fri, 24 Jul 2026 03:48:44 +0000 (05:48 +0200)
committerJunio C Hamano <gitster@pobox.com>
Fri, 24 Jul 2026 17:21:44 +0000 (10:21 -0700)
When creating a new "files" object database source we have to create a
couple of directories. These directories are of course specific to this
particular backend, and a different backend may require a setup that is
completely different.

Make the creation of on-disk structures pluggable to accommodate for
this.

Note that there is one exception though: the "objects" directory must
exist in a repository regardless of which backend is in use. If it
doesn't exist then the repository is not treated as a Git repository at
all. Consequently, we create this directory regardless of the backend.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
odb/source-files.c
odb/source.h
setup.c

index 413875851135a5372ab758d85532a784f6ae153e..0db6e681fee9e6fc8f684fcab22a13f92f272728 100644 (file)
@@ -9,6 +9,7 @@
 #include "odb/source-files.h"
 #include "odb/source-loose.h"
 #include "packfile.h"
+#include "path.h"
 #include "strbuf.h"
 #include "write-or-die.h"
 
@@ -41,6 +42,23 @@ static void odb_source_files_close(struct odb_source *source)
        odb_source_close(&files->packed->base);
 }
 
+static int odb_source_files_create_on_disk(struct odb_source *source)
+{
+       struct strbuf path = STRBUF_INIT;
+
+       safe_create_dir(source->odb->repo, source->path, 1);
+
+       strbuf_addf(&path, "%s/pack", source->path);
+       safe_create_dir(source->odb->repo, path.buf, 1);
+
+       strbuf_reset(&path);
+       strbuf_addf(&path, "%s/info", source->path);
+       safe_create_dir(source->odb->repo, path.buf, 1);
+
+       strbuf_release(&path);
+       return 0;
+}
+
 static void odb_source_files_prepare(struct odb_source *source,
                                     enum odb_prepare_flags flags)
 {
@@ -271,6 +289,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.create_on_disk = odb_source_files_create_on_disk;
        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;
index ab16d152f43082154dc47a8cb2013fb0a7397480..4abc418bdd70fca65793bdfa01d3f34953b00b80 100644 (file)
@@ -89,6 +89,18 @@ struct odb_source {
         */
        void (*close)(struct odb_source *source);
 
+       /*
+        * This callback is expected to create on-disk data structures that are
+        * required for this source to operate.
+        *
+        * The callback is expected to return 0 on success, a negative error
+        * code otherwise.
+        *
+        * This callback may be NULL in case the source does not need any
+        * on-disk setup.
+        */
+       int (*create_on_disk)(struct odb_source *source);
+
        /*
         * This callback is expected to prepare the source so that it becomes
         * ready for use. It optionally clears underlying caches of the object
@@ -316,6 +328,17 @@ static inline void odb_source_close(struct odb_source *source)
        source->close(source);
 }
 
+/*
+ * Create on-disk data structures that are required for this source to operate
+ * correctly. Returns 0 on success, a negative error code otherwise.
+ */
+static inline int odb_source_create_on_disk(struct odb_source *source)
+{
+       if (!source->create_on_disk)
+               return 0;
+       return source->create_on_disk(source);
+}
+
 /*
  * Prepare the object database source and clear any caches. Depending on the
  * backend used this may have the effect that concurrently-written objects
diff --git a/setup.c b/setup.c
index a7b1b9eaefff5529fd70e50fb29c9db9ca505879..14ef119cb793b6ec6241fc8d566b639b9c819edf 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -2666,29 +2666,34 @@ static int create_default_files(struct repository *repo,
 static void create_object_database(struct repository *repo)
 {
        char *object_directory, *alternate_object_directories;
-       struct strbuf path = STRBUF_INIT;
-       size_t baselen;
 
        get_object_directories(&object_directory, &alternate_object_directories);
-       repo->objects = odb_new(repo, object_directory,
-                               alternate_object_directories);
 
-       strbuf_addstr(&path, repo_get_object_directory(repo));
-       baselen = path.len;
-
-       safe_create_dir(repo, path.buf, 1);
+       /*
+        * Create the "objects" directory in the common directory. This is done
+        * so that the repository can be discovered regardless of the backend
+        * used.
+        *
+        * Note that we only do this in case the object directory wasn't
+        * overwritten via an environment variable. If it _is_ being overridden
+        * then we skip this step, as the repository won't be discoverable
+        * anyway without the environment variable.
+        */
+       if (!object_directory) {
+               struct strbuf objects_dir = STRBUF_INIT;
+               repo_common_path_append(repo, &objects_dir, "objects");
+               safe_create_dir(repo, objects_dir.buf, 1);
+               strbuf_release(&objects_dir);
+       }
 
-       strbuf_setlen(&path, baselen);
-       strbuf_addstr(&path, "/pack");
-       safe_create_dir(repo, path.buf, 1);
+       repo->objects = odb_new(repo, object_directory,
+                               alternate_object_directories);
 
-       strbuf_setlen(&path, baselen);
-       strbuf_addstr(&path, "/info");
-       safe_create_dir(repo, path.buf, 1);
+       if (odb_source_create_on_disk(repo->objects->sources) < 0)
+               die("failed creating object database");
 
        free(alternate_object_directories);
        free(object_directory);
-       strbuf_release(&path);
 }
 
 static void separate_git_dir(const char *git_dir, const char *git_link)