From b1ac78ecb9a14947eccaee8b6ea0cedab5046ce5 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 11 Jul 2025 12:07:26 +0200 Subject: [PATCH] repository: allow initialization with a specific refdb type While we only support initializing repositories with the "files" reference backend right now, we are in the process of implementing a second backend with the "reftable" format. And while we already have the infrastructure to decide which format a repository should use when we open it, we do not have infrastructure yet to create new repositories with a different reference format. Introduce a new field `git_repository_init_options::refdb_type`. If unset, we'll default to the "files" backend. Otherwise though, if set to a valid `git_refdb_t`, we will use that new format to initialize the repostiory. Note that for now the only thing we do is to write the "refStorage" extension accordingly. What we explicitly don't yet do is to also handle the backend-specific logic to initialize the refdb on disk. This will be implemented in subsequent commits. --- include/git2/repository.h | 7 +++++++ src/libgit2/refdb.h | 10 ++++++++++ src/libgit2/repository.c | 17 ++++++++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index 4bdcee37a..62faefa62 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -11,6 +11,7 @@ #include "types.h" #include "oid.h" #include "odb.h" +#include "refdb.h" #include "buffer.h" #include "commit.h" @@ -377,6 +378,12 @@ typedef struct { */ git_oid_t oid_type; #endif + + /** + * Type of the reference database to use for this repository, or 0 for + * default (currently "files"). + */ + git_refdb_t refdb_type; } git_repository_init_options; /** Current version for the `git_repository_init_options` structure */ diff --git a/src/libgit2/refdb.h b/src/libgit2/refdb.h index 7ee879ed9..b9ae592f3 100644 --- a/src/libgit2/refdb.h +++ b/src/libgit2/refdb.h @@ -125,6 +125,16 @@ int git_refdb_ensure_log(git_refdb *refdb, const char *refname); int git_refdb_lock(void **payload, git_refdb *db, const char *refname); int git_refdb_unlock(git_refdb *db, void *payload, int success, int update_reflog, const git_reference *ref, const git_signature *sig, const char *message); +GIT_INLINE(const char *) git_refdb_type_name(git_refdb_t type) +{ + switch (type) { + case GIT_REFDB_FILES: + return "files"; + default: + return "unknown"; + } +} + GIT_INLINE(git_refdb_t) git_refdb_type_fromstr(const char *name) { if (strcmp(name, "files") == 0) diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 147e4759b..98984029d 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -2379,7 +2379,8 @@ static int repo_init_config( const char *work_dir, uint32_t flags, uint32_t mode, - git_oid_t oid_type) + git_oid_t oid_type, + git_refdb_t refdb_type) { int error = 0; git_str cfg_path = GIT_STR_INIT, worktree_path = GIT_STR_INIT; @@ -2443,6 +2444,11 @@ static int repo_init_config( SET_REPO_CONFIG(string, "extensions.objectformat", git_oid_type_name(oid_type)); } + if (refdb_type != GIT_REFDB_FILES) { + SET_REPO_CONFIG(int32, "core.repositoryformatversion", 1); + SET_REPO_CONFIG(string, "extensions.refstorage", git_refdb_type_name(refdb_type)); + } + cleanup: git_str_dispose(&cfg_path); git_str_dispose(&worktree_path); @@ -2926,6 +2932,7 @@ int git_repository_init_ext( const char *wd; bool is_valid; git_oid_t oid_type = GIT_OID_DEFAULT; + git_refdb_t refdb_type = GIT_REFDB_FILES; int error; GIT_ASSERT_ARG(out); @@ -2938,6 +2945,8 @@ int git_repository_init_ext( if (opts->oid_type) oid_type = opts->oid_type; #endif + if (opts->refdb_type) + refdb_type = opts->refdb_type; if ((error = repo_init_directories(&repo_path, &wd_path, given_repo, opts)) < 0) goto out; @@ -2957,13 +2966,15 @@ int git_repository_init_ext( opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT; - if ((error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode, oid_type)) < 0) + if ((error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode, + oid_type, refdb_type)) < 0) goto out; /* TODO: reinitialize the templates */ } else { if ((error = repo_init_structure(repo_path.ptr, wd, opts)) < 0 || - (error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode, oid_type)) < 0 || + (error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode, + oid_type, refdb_type)) < 0 || (error = repo_init_head(repo_path.ptr, opts->initial_head)) < 0) goto out; }