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)