Skip to content

Commit 5bf20d6

Browse files
committed
Merge branch 'ps/refstorage-extension' into ps/worktree-refdb-initialization
* ps/refstorage-extension: t9500: write "extensions.refstorage" into config builtin/clone: introduce `--ref-format=` value flag builtin/init: introduce `--ref-format=` value flag builtin/rev-parse: introduce `--show-ref-format` flag t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvar setup: introduce GIT_DEFAULT_REF_FORMAT envvar setup: introduce "extensions.refStorage" extension setup: set repository's formats on init setup: start tracking ref storage format refs: refactor logic to look up storage backends worktree: skip reading HEAD when repairing worktrees t: introduce DEFAULT_REPO_FORMAT prereq builtin/clone: create the refdb with the correct object format builtin/clone: skip reading HEAD when retrieving remote builtin/clone: set up sparse checkout later builtin/clone: fix bundle URIs with mismatching object formats remote-curl: rediscover repository when fetching refs setup: allow skipping creation of the refdb setup: extract function to create the refdb
2 parents 055bb6e + 1b22340 commit 5bf20d6

34 files changed

+479
-121
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/git-clone.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,12 @@ or `--mirror` is given)
311311
The result is Git repository can be separated from working
312312
tree.
313313

314+
--ref-format=<ref-format::
315+
316+
Specify the given ref storage format for the repository. The valid values are:
317+
+
318+
include::ref-storage-format.txt[]
319+
314320
-j <n>::
315321
--jobs <n>::
316322
The number of submodules fetched at the same time.

Documentation/git-init.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ SYNOPSIS
1111
[verse]
1212
'git init' [-q | --quiet] [--bare] [--template=<template-directory>]
1313
[--separate-git-dir <git-dir>] [--object-format=<format>]
14+
[--ref-format=<format>]
1415
[-b <branch-name> | --initial-branch=<branch-name>]
1516
[--shared[=<permissions>]] [<directory>]
1617

@@ -57,6 +58,12 @@ values are 'sha1' and (if enabled) 'sha256'. 'sha1' is the default.
5758
+
5859
include::object-format-disclaimer.txt[]
5960

61+
--ref-format=<format>::
62+
63+
Specify the given ref storage format for the repository. The valid values are:
64+
+
65+
include::ref-storage-format.txt[]
66+
6067
--template=<template-directory>::
6168

6269
Specify the directory from which templates will be used. (See the "TEMPLATE

Documentation/git-rev-parse.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,9 @@ The following options are unaffected by `--path-format`:
307307
input, multiple algorithms may be printed, space-separated.
308308
If not specified, the default is "storage".
309309

310+
--show-ref-format::
311+
Show the reference storage format used for the repository.
312+
310313

311314
Other Options
312315
~~~~~~~~~~~~~

Documentation/git.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,11 @@ double-quotes and respecting backslash escapes. E.g., the value
556556
is always used. The default is "sha1".
557557
See `--object-format` in linkgit:git-init[1].
558558

559+
`GIT_DEFAULT_REF_FORMAT`::
560+
If this variable is set, the default reference backend format for new
561+
repositories will be set to this value. The default is "files".
562+
See `--ref-format` in linkgit:git-init[1].
563+
559564
Git Commits
560565
~~~~~~~~~~~
561566
`GIT_AUTHOR_NAME`::

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: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ static char *remote_name = NULL;
7272
static char *option_branch = NULL;
7373
static struct string_list option_not = STRING_LIST_INIT_NODUP;
7474
static const char *real_git_dir;
75+
static const char *ref_format;
7576
static char *option_upload_pack = "git-upload-pack";
7677
static int option_verbosity;
7778
static int option_progress = -1;
@@ -157,6 +158,8 @@ static struct option builtin_clone_options[] = {
157158
N_("any cloned submodules will be shallow")),
158159
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
159160
N_("separate git dir from working tree")),
161+
OPT_STRING(0, "ref-format", &ref_format, N_("format"),
162+
N_("specify the reference format to use")),
160163
OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
161164
N_("set config inside the new repository")),
162165
OPT_STRING_LIST(0, "server-option", &server_options,
@@ -932,6 +935,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
932935
int submodule_progress;
933936
int filter_submodules = 0;
934937
int hash_algo;
938+
unsigned int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
935939
const int do_not_override_repo_unix_permissions = -1;
936940

937941
struct transport_ls_refs_options transport_ls_refs_options =
@@ -957,6 +961,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
957961
if (option_single_branch == -1)
958962
option_single_branch = deepen ? 1 : 0;
959963

964+
if (ref_format) {
965+
ref_storage_format = ref_storage_format_by_name(ref_format);
966+
if (ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN)
967+
die(_("unknown ref storage format '%s'"), ref_format);
968+
}
969+
960970
if (option_mirror)
961971
option_bare = 1;
962972

@@ -1101,8 +1111,15 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
11011111
}
11021112
}
11031113

1104-
init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
1105-
do_not_override_repo_unix_permissions, INIT_DB_QUIET);
1114+
/*
1115+
* Initialize the repository, but skip initializing the reference
1116+
* database. We do not yet know about the object format of the
1117+
* repository, and reference backends may persist that information into
1118+
* their on-disk data structures.
1119+
*/
1120+
init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN,
1121+
ref_storage_format, NULL,
1122+
do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
11061123

11071124
if (real_git_dir) {
11081125
free((char *)git_dir);
@@ -1189,10 +1206,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
11891206
if (option_required_reference.nr || option_optional_reference.nr)
11901207
setup_reference();
11911208

1192-
if (option_sparse_checkout && git_sparse_checkout_init(dir))
1193-
return 1;
1194-
1195-
remote = remote_get(remote_name);
1209+
remote = remote_get_early(remote_name);
11961210

11971211
refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
11981212
branch_top.buf);
@@ -1270,6 +1284,27 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
12701284
if (transport->smart_options && !deepen && !filter_options.choice)
12711285
transport->smart_options->check_self_contained_and_connected = 1;
12721286

1287+
strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
1288+
refspec_ref_prefixes(&remote->fetch,
1289+
&transport_ls_refs_options.ref_prefixes);
1290+
if (option_branch)
1291+
expand_ref_prefix(&transport_ls_refs_options.ref_prefixes,
1292+
option_branch);
1293+
if (!option_no_tags)
1294+
strvec_push(&transport_ls_refs_options.ref_prefixes,
1295+
"refs/tags/");
1296+
1297+
refs = transport_get_remote_refs(transport, &transport_ls_refs_options);
1298+
1299+
/*
1300+
* Now that we know what algorithm the remote side is using, let's set
1301+
* ours to the same thing.
1302+
*/
1303+
hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
1304+
initialize_repository_version(hash_algo, the_repository->ref_storage_format, 1);
1305+
repo_set_hash_algo(the_repository, hash_algo);
1306+
create_reference_database(the_repository->ref_storage_format, NULL, 1);
1307+
12731308
/*
12741309
* Before fetching from the remote, download and install bundle
12751310
* data from the --bundle-uri option.
@@ -1285,24 +1320,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
12851320
bundle_uri);
12861321
else if (has_heuristic)
12871322
git_config_set_gently("fetch.bundleuri", bundle_uri);
1288-
}
1289-
1290-
strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
1291-
refspec_ref_prefixes(&remote->fetch,
1292-
&transport_ls_refs_options.ref_prefixes);
1293-
if (option_branch)
1294-
expand_ref_prefix(&transport_ls_refs_options.ref_prefixes,
1295-
option_branch);
1296-
if (!option_no_tags)
1297-
strvec_push(&transport_ls_refs_options.ref_prefixes,
1298-
"refs/tags/");
1299-
1300-
refs = transport_get_remote_refs(transport, &transport_ls_refs_options);
1301-
1302-
if (refs)
1303-
mapped_refs = wanted_peer_refs(refs, &remote->fetch);
1304-
1305-
if (!bundle_uri) {
1323+
} else {
13061324
/*
13071325
* Populate transport->got_remote_bundle_uri and
13081326
* transport->bundle_uri. We might get nothing.
@@ -1323,13 +1341,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
13231341
}
13241342
}
13251343

1326-
/*
1327-
* Now that we know what algorithm the remote side is using,
1328-
* let's set ours to the same thing.
1329-
*/
1330-
hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
1331-
initialize_repository_version(hash_algo, 1);
1332-
repo_set_hash_algo(the_repository, hash_algo);
1344+
if (refs)
1345+
mapped_refs = wanted_peer_refs(refs, &remote->fetch);
13331346

13341347
if (mapped_refs) {
13351348
/*
@@ -1432,6 +1445,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
14321445
dissociate_from_references();
14331446
}
14341447

1448+
if (option_sparse_checkout && git_sparse_checkout_init(dir))
1449+
return 1;
1450+
14351451
junk_mode = JUNK_LEAVE_REPO;
14361452
err = checkout(submodule_progress, filter_submodules);
14371453

builtin/init-db.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "object-file.h"
1212
#include "parse-options.h"
1313
#include "path.h"
14+
#include "refs.h"
1415
#include "setup.h"
1516
#include "strbuf.h"
1617

@@ -57,6 +58,7 @@ static int shared_callback(const struct option *opt, const char *arg, int unset)
5758
static const char *const init_db_usage[] = {
5859
N_("git init [-q | --quiet] [--bare] [--template=<template-directory>]\n"
5960
" [--separate-git-dir <git-dir>] [--object-format=<format>]\n"
61+
" [--ref-format=<format>]\n"
6062
" [-b <branch-name> | --initial-branch=<branch-name>]\n"
6163
" [--shared[=<permissions>]] [<directory>]"),
6264
NULL
@@ -76,8 +78,10 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
7678
const char *template_dir = NULL;
7779
unsigned int flags = 0;
7880
const char *object_format = NULL;
81+
const char *ref_format = NULL;
7982
const char *initial_branch = NULL;
8083
int hash_algo = GIT_HASH_UNKNOWN;
84+
unsigned int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
8185
int init_shared_repository = -1;
8286
const struct option init_db_options[] = {
8387
OPT_STRING(0, "template", &template_dir, N_("template-directory"),
@@ -95,6 +99,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
9599
N_("override the name of the initial branch")),
96100
OPT_STRING(0, "object-format", &object_format, N_("hash"),
97101
N_("specify the hash algorithm to use")),
102+
OPT_STRING(0, "ref-format", &ref_format, N_("format"),
103+
N_("specify the reference format to use")),
98104
OPT_END()
99105
};
100106

@@ -158,6 +164,12 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
158164
die(_("unknown hash algorithm '%s'"), object_format);
159165
}
160166

167+
if (ref_format) {
168+
ref_storage_format = ref_storage_format_by_name(ref_format);
169+
if (ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN)
170+
die(_("unknown ref storage format '%s'"), ref_format);
171+
}
172+
161173
if (init_shared_repository != -1)
162174
set_shared_repository(init_shared_repository);
163175

@@ -236,5 +248,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
236248

237249
flags |= INIT_DB_EXIST_OK;
238250
return init_db(git_dir, real_git_dir, template_dir, hash_algo,
239-
initial_branch, init_shared_repository, flags);
251+
ref_storage_format, initial_branch,
252+
init_shared_repository, flags);
240253
}

builtin/rev-parse.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
10621062
puts(the_hash_algo->name);
10631063
continue;
10641064
}
1065+
if (!strcmp(arg, "--show-ref-format")) {
1066+
puts(ref_storage_format_to_name(the_repository->ref_storage_format));
1067+
continue;
1068+
}
10651069
if (!strcmp(arg, "--end-of-options")) {
10661070
seen_end_of_options = 1;
10671071
if (filter & (DO_FLAGS | DO_REVS))

0 commit comments

Comments
 (0)