Skip to content

Commit d7497a4

Browse files
pks-tgitster
authored andcommitted
setup: introduce "extensions.refStorage" extension
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]: <[email protected]> Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 58be32f commit d7497a4

File tree

8 files changed

+69
-6
lines changed

8 files changed

+69
-6
lines changed

Documentation/config/extensions.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ Note that this setting should only be set by linkgit:git-init[1] or
77
linkgit:git-clone[1]. Trying to change it after initialization will not
88
work and will produce hard-to-diagnose issues.
99

10+
extensions.refStorage::
11+
Specify the ref storage format to use. The acceptable values are:
12+
+
13+
include::../ref-storage-format.txt[]
14+
+
15+
It is an error to specify this key unless `core.repositoryFormatVersion` is 1.
16+
+
17+
Note that this setting should only be set by linkgit:git-init[1] or
18+
linkgit:git-clone[1]. Trying to change it after initialization will not
19+
work and will produce hard-to-diagnose issues.
20+
1021
extensions.worktreeConfig::
1122
If enabled, then worktrees will load config settings from the
1223
`$GIT_DIR/config.worktree` file in addition to the

Documentation/ref-storage-format.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* `files` for loose files with packed-refs. This is the default.

Documentation/technical/repository-version.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,8 @@ If set, by default "git config" reads from both "config" and
100100
multiple working directory mode, "config" file is shared while
101101
"config.worktree" is per-working directory (i.e., it's in
102102
GIT_COMMON_DIR/worktrees/<id>/config.worktree)
103+
104+
==== `refStorage`
105+
106+
Specifies the file format for the ref database. The only valid value
107+
is `files` (loose references with a packed-refs file).

builtin/clone.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1291,7 +1291,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
12911291
* ours to the same thing.
12921292
*/
12931293
hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
1294-
initialize_repository_version(hash_algo, 1);
1294+
initialize_repository_version(hash_algo, the_repository->ref_storage_format, 1);
12951295
repo_set_hash_algo(the_repository, hash_algo);
12961296
create_reference_database(the_repository->ref_storage_format, NULL, 1);
12971297

setup.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,17 @@ static enum extension_result handle_extension(const char *var,
592592
"extensions.objectformat", value);
593593
data->hash_algo = format;
594594
return EXTENSION_OK;
595+
} else if (!strcmp(ext, "refstorage")) {
596+
unsigned int format;
597+
598+
if (!value)
599+
return config_error_nonbool(var);
600+
format = ref_storage_format_by_name(value);
601+
if (format == REF_STORAGE_FORMAT_UNKNOWN)
602+
return error(_("invalid value for '%s': '%s'"),
603+
"extensions.refstorage", value);
604+
data->ref_storage_format = format;
605+
return EXTENSION_OK;
595606
}
596607
return EXTENSION_UNKNOWN;
597608
}
@@ -1871,12 +1882,15 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree)
18711882
return 1;
18721883
}
18731884

1874-
void initialize_repository_version(int hash_algo, int reinit)
1885+
void initialize_repository_version(int hash_algo,
1886+
unsigned int ref_storage_format,
1887+
int reinit)
18751888
{
18761889
char repo_version_string[10];
18771890
int repo_version = GIT_REPO_VERSION;
18781891

1879-
if (hash_algo != GIT_HASH_SHA1)
1892+
if (hash_algo != GIT_HASH_SHA1 ||
1893+
ref_storage_format != REF_STORAGE_FORMAT_FILES)
18801894
repo_version = GIT_REPO_VERSION_READ;
18811895

18821896
/* This forces creation of new config file */
@@ -1889,6 +1903,10 @@ void initialize_repository_version(int hash_algo, int reinit)
18891903
hash_algos[hash_algo].name);
18901904
else if (reinit)
18911905
git_config_set_gently("extensions.objectformat", NULL);
1906+
1907+
if (ref_storage_format != REF_STORAGE_FORMAT_FILES)
1908+
git_config_set("extensions.refstorage",
1909+
ref_storage_format_to_name(ref_storage_format));
18921910
}
18931911

18941912
static int is_reinit(void)
@@ -2030,7 +2048,7 @@ static int create_default_files(const char *template_path,
20302048
adjust_shared_perm(get_git_dir());
20312049
}
20322050

2033-
initialize_repository_version(fmt->hash_algo, 0);
2051+
initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, 0);
20342052

20352053
/* Check filemode trustability */
20362054
path = git_path_buf(&buf, "config");

setup.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ int init_db(const char *git_dir, const char *real_git_dir,
180180
unsigned int ref_storage_format,
181181
const char *initial_branch, int init_shared_repository,
182182
unsigned int flags);
183-
void initialize_repository_version(int hash_algo, int reinit);
183+
void initialize_repository_version(int hash_algo,
184+
unsigned int ref_storage_format,
185+
int reinit);
184186
void create_reference_database(unsigned int ref_storage_format,
185187
const char *initial_branch, int quiet);
186188

t/t0001-init.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,32 @@ test_expect_success 'init rejects attempts to initialize with different hash' '
532532
test_must_fail git -C sha256 init --object-format=sha1
533533
'
534534

535+
test_expect_success DEFAULT_REPO_FORMAT 'extensions.refStorage is not allowed with repo version 0' '
536+
test_when_finished "rm -rf refstorage" &&
537+
git init refstorage &&
538+
git -C refstorage config extensions.refStorage files &&
539+
test_must_fail git -C refstorage rev-parse 2>err &&
540+
grep "repo version is 0, but v1-only extension found" err
541+
'
542+
543+
test_expect_success DEFAULT_REPO_FORMAT 'extensions.refStorage with files backend' '
544+
test_when_finished "rm -rf refstorage" &&
545+
git init refstorage &&
546+
git -C refstorage config core.repositoryformatversion 1 &&
547+
git -C refstorage config extensions.refStorage files &&
548+
test_commit -C refstorage A &&
549+
git -C refstorage rev-parse --verify HEAD
550+
'
551+
552+
test_expect_success DEFAULT_REPO_FORMAT 'extensions.refStorage with unknown backend' '
553+
test_when_finished "rm -rf refstorage" &&
554+
git init refstorage &&
555+
git -C refstorage config core.repositoryformatversion 1 &&
556+
git -C refstorage config extensions.refStorage garbage &&
557+
test_must_fail git -C refstorage rev-parse 2>err &&
558+
grep "invalid value for ${SQ}extensions.refstorage${SQ}: ${SQ}garbage${SQ}" err
559+
'
560+
535561
test_expect_success MINGW 'core.hidedotfiles = false' '
536562
git config --global core.hidedotfiles false &&
537563
rm -rf newdir &&

t/test-lib.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1937,7 +1937,7 @@ test_lazy_prereq SHA1 '
19371937
'
19381938

19391939
test_lazy_prereq DEFAULT_REPO_FORMAT '
1940-
test_have_prereq SHA1
1940+
test_have_prereq SHA1,REFFILES
19411941
'
19421942

19431943
# Ensure that no test accidentally triggers a Git command

0 commit comments

Comments
 (0)