odb: make creation of on-disk structures pluggable

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>

Patrick Steinhardt committed Jul 24, 2026 at 05:48 UTC 2691faaee4b06a0caeb144cb05550273b021cece
3 files changed +62 -15
odb/source-files.c
+19
@@ -9,6 +9,7 @@
9 #include "odb/source-files.h"
10 #include "odb/source-loose.h"
11 #include "packfile.h"
12 +#include "path.h"
13 #include "strbuf.h"
14 #include "write-or-die.h"
15
@@ -41,6 +42,23 @@ static void odb_source_files_close(struct odb_source *source)
42 odb_source_close(&files->packed->base);
43 }
44
45 +static int odb_source_files_create_on_disk(struct odb_source *source)
46 +{
47 + struct strbuf path = STRBUF_INIT;
48 +
49 + safe_create_dir(source->odb->repo, source->path, 1);
50 +
51 + strbuf_addf(&path, "%s/pack", source->path);
52 + safe_create_dir(source->odb->repo, path.buf, 1);
53 +
54 + strbuf_reset(&path);
55 + strbuf_addf(&path, "%s/info", source->path);
56 + safe_create_dir(source->odb->repo, path.buf, 1);
57 +
58 + strbuf_release(&path);
59 + return 0;
60 +}
61 +
62 static void odb_source_files_prepare(struct odb_source *source,
63 enum odb_prepare_flags flags)
64 {
@@ -271,6 +289,7 @@ struct odb_source_files *odb_source_files_new(struct object_database *odb,
289
290 files->base.free = odb_source_files_free;
291 files->base.close = odb_source_files_close;
292 + files->base.create_on_disk = odb_source_files_create_on_disk;
293 files->base.prepare = odb_source_files_prepare;
294 files->base.read_object_info = odb_source_files_read_object_info;
295 files->base.read_object_stream = odb_source_files_read_object_stream;
odb/source.h
+23
@@ -89,6 +89,18 @@ struct odb_source {
89 */
90 void (*close)(struct odb_source *source);
91
92 + /*
93 + * This callback is expected to create on-disk data structures that are
94 + * required for this source to operate.
95 + *
96 + * The callback is expected to return 0 on success, a negative error
97 + * code otherwise.
98 + *
99 + * This callback may be NULL in case the source does not need any
100 + * on-disk setup.
101 + */
102 + int (*create_on_disk)(struct odb_source *source);
103 +
104 /*
105 * This callback is expected to prepare the source so that it becomes
106 * 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)
328 source->close(source);
329 }
330
331 +/*
332 + * Create on-disk data structures that are required for this source to operate
333 + * correctly. Returns 0 on success, a negative error code otherwise.
334 + */
335 +static inline int odb_source_create_on_disk(struct odb_source *source)
336 +{
337 + if (!source->create_on_disk)
338 + return 0;
339 + return source->create_on_disk(source);
340 +}
341 +
342 /*
343 * Prepare the object database source and clear any caches. Depending on the
344 * backend used this may have the effect that concurrently-written objects
setup.c
+20 -15
@@ -2666,29 +2666,34 @@ static int create_default_files(struct repository *repo,
2666 static void create_object_database(struct repository *repo)
2667 {
2668 char *object_directory, *alternate_object_directories;
2669 - struct strbuf path = STRBUF_INIT;
2670 - size_t baselen;
2669
2670 get_object_directories(&object_directory, &alternate_object_directories);
2673 - repo->objects = odb_new(repo, object_directory,
2674 - alternate_object_directories);
2671
2676 - strbuf_addstr(&path, repo_get_object_directory(repo));
2677 - baselen = path.len;
2678 -
2679 - safe_create_dir(repo, path.buf, 1);
2672 + /*
2673 + * Create the "objects" directory in the common directory. This is done
2674 + * so that the repository can be discovered regardless of the backend
2675 + * used.
2676 + *
2677 + * Note that we only do this in case the object directory wasn't
2678 + * overwritten via an environment variable. If it _is_ being overridden
2679 + * then we skip this step, as the repository won't be discoverable
2680 + * anyway without the environment variable.
2681 + */
2682 + if (!object_directory) {
2683 + struct strbuf objects_dir = STRBUF_INIT;
2684 + repo_common_path_append(repo, &objects_dir, "objects");
2685 + safe_create_dir(repo, objects_dir.buf, 1);
2686 + strbuf_release(&objects_dir);
2687 + }
2688
2681 - strbuf_setlen(&path, baselen);
2682 - strbuf_addstr(&path, "/pack");
2683 - safe_create_dir(repo, path.buf, 1);
2689 + repo->objects = odb_new(repo, object_directory,
2690 + alternate_object_directories);
2691
2685 - strbuf_setlen(&path, baselen);
2686 - strbuf_addstr(&path, "/info");
2687 - safe_create_dir(repo, path.buf, 1);
2692 + if (odb_source_create_on_disk(repo->objects->sources) < 0)
2693 + die("failed creating object database");
2694
2695 free(alternate_object_directories);
2696 free(object_directory);
2691 - strbuf_release(&path);
2697 }
2698
2699 static void separate_git_dir(const char *git_dir, const char *git_link)