Introduce a new "extensions.refStorage" extension that allows us to
specify the ref storage format used by a repository. For now, the only
supported format is the "files" format, but this list will likely soon
be extended to also support the upcoming "reftable" format.
There have been discussions on the Git mailing list in the past around
how exactly this extension should look like. One alternative [1] that
was discussed was whether it would make sense to model the extension in
such a way that backends are arbitrarily stackable. This would allow for
a combined value of e.g. "loose,packed-refs" or "loose,reftable", which
indicates that new refs would be written via "loose" files backend and
compressed into "packed-refs" or "reftable" backends, respectively.
It is arguable though whether this flexibility and the complexity that
it brings with it is really required for now. It is not foreseeable that
there will be a proliferation of backends in the near-term future, and
the current set of existing formats and formats which are on the horizon
can easily be configured with the much simpler proposal where we have a
single value, only.
Furthermore, if we ever see that we indeed want to gain the ability to
arbitrarily stack the ref formats, then we can adapt the current
extension rather easily. Given that Git clients will refuse any unknown
value for the "extensions.refStorage" extension they would also know to
ignore a stacked "loose,packed-refs" in the future.
So let's stick with the easy proposal for the time being and wire up the
extension.
[1]: <pull.1408.git.1667846164.gitgitgadget@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committedDec 29, 2023 at 08:26 UTCd7497a42b05bb810afeb6acc8c9447b77b1f075d
8 files changed+69-6
Documentation/config/extensions.txt
+11
index bccaec7a96..66db0e15da 100644--- a/Documentation/config/extensions.txt+++ b/Documentation/config/extensions.txt@@ -7,6 +7,17 @@ Note that this setting should only be set by linkgit:git-init[1] or linkgit:git-clone[1]. Trying to change it after initialization will not work and will produce hard-to-diagnose issues.+extensions.refStorage::+ Specify the ref storage format to use. The acceptable values are:+++include::../ref-storage-format.txt[]+++It is an error to specify this key unless `core.repositoryFormatVersion` is 1.+++Note that this setting should only be set by linkgit:git-init[1] or+linkgit:git-clone[1]. Trying to change it after initialization will not+work and will produce hard-to-diagnose issues.+ extensions.worktreeConfig:: If enabled, then worktrees will load config settings from the `$GIT_DIR/config.worktree` file in addition to the
Documentation/ref-storage-format.txt
+1
new file mode 100644index 0000000000..1a65cac468--- /dev/null+++ b/Documentation/ref-storage-format.txt@@ -0,0 +1 @@+* `files` for loose files with packed-refs. This is the default.
Documentation/technical/repository-version.txt
+5
index 045a76756f..27be3741e6 100644--- a/Documentation/technical/repository-version.txt+++ b/Documentation/technical/repository-version.txt@@ -100,3 +100,8 @@ If set, by default "git config" reads from both "config" and multiple working directory mode, "config" file is shared while "config.worktree" is per-working directory (i.e., it's in GIT_COMMON_DIR/worktrees/<id>/config.worktree)++==== `refStorage`++Specifies the file format for the ref database. The only valid value+is `files` (loose references with a packed-refs file).
builtin/clone.c
+1-1
index 48aeb1b90b..0fb3816d0c 100644--- a/builtin/clone.c+++ b/builtin/clone.c@@ -1291,7 +1291,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) * ours to the same thing. */ hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));- initialize_repository_version(hash_algo, 1);+ initialize_repository_version(hash_algo, the_repository->ref_storage_format, 1); repo_set_hash_algo(the_repository, hash_algo); create_reference_database(the_repository->ref_storage_format, NULL, 1);
setup.c
+21-3
index 49570e6b3a..fb1413cabd 100644--- a/setup.c+++ b/setup.c@@ -592,6 +592,17 @@ static enum extension_result handle_extension(const char *var, "extensions.objectformat", value); data->hash_algo = format; return EXTENSION_OK;+ } else if (!strcmp(ext, "refstorage")) {+ unsigned int format;++ if (!value)+ return config_error_nonbool(var);+ format = ref_storage_format_by_name(value);+ if (format == REF_STORAGE_FORMAT_UNKNOWN)+ return error(_("invalid value for '%s': '%s'"),+ "extensions.refstorage", value);+ data->ref_storage_format = format;+ return EXTENSION_OK; } return EXTENSION_UNKNOWN; }@@ -1871,12 +1882,15 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree) return 1; }-void initialize_repository_version(int hash_algo, int reinit)+void initialize_repository_version(int hash_algo,+ unsigned int ref_storage_format,+ int reinit) { char repo_version_string[10]; int repo_version = GIT_REPO_VERSION;- if (hash_algo != GIT_HASH_SHA1)+ if (hash_algo != GIT_HASH_SHA1 ||+ ref_storage_format != REF_STORAGE_FORMAT_FILES) repo_version = GIT_REPO_VERSION_READ; /* This forces creation of new config file */@@ -1889,6 +1903,10 @@ void initialize_repository_version(int hash_algo, int reinit) hash_algos[hash_algo].name); else if (reinit) git_config_set_gently("extensions.objectformat", NULL);++ if (ref_storage_format != REF_STORAGE_FORMAT_FILES)+ git_config_set("extensions.refstorage",+ ref_storage_format_to_name(ref_storage_format)); } static int is_reinit(void)@@ -2030,7 +2048,7 @@ static int create_default_files(const char *template_path, adjust_shared_perm(get_git_dir()); }- initialize_repository_version(fmt->hash_algo, 0);+ initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, 0); /* Check filemode trustability */ path = git_path_buf(&buf, "config");
setup.h
+3-1
index 3d3eda7967..3599aec93c 100644--- a/setup.h+++ b/setup.h@@ -180,7 +180,9 @@ int init_db(const char *git_dir, const char *real_git_dir, unsigned int ref_storage_format, const char *initial_branch, int init_shared_repository, unsigned int flags);-void initialize_repository_version(int hash_algo, int reinit);+void initialize_repository_version(int hash_algo,+ unsigned int ref_storage_format,+ int reinit); void create_reference_database(unsigned int ref_storage_format, const char *initial_branch, int quiet);