From: Patrick Steinhardt Date: Fri, 24 Jul 2026 03:48:44 +0000 (+0200) Subject: odb: make creation of on-disk structures pluggable X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2691faaee4b06a0caeb144cb05550273b021cece;p=thirdparty%2Fgit.git 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 Signed-off-by: Junio C Hamano --- diff --git a/odb/source-files.c b/odb/source-files.c index 4138758511..0db6e681fe 100644 --- a/odb/source-files.c +++ b/odb/source-files.c @@ -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; diff --git a/odb/source.h b/odb/source.h index ab16d152f4..4abc418bdd 100644 --- a/odb/source.h +++ b/odb/source.h @@ -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 a7b1b9eaef..14ef119cb7 100644 --- 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)