builtin/clone: introduce `--ref-format=` value flag

Introduce a new `--ref-format` value flag for git-clone(1) that allows the user to specify the ref format that is to be used for a newly initialized repository. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Dec 29, 2023 at 08:27 UTC 5ed860f51b7fa1ca1087c1b0502b199a86db964e
3 files changed +34 -1
Documentation/git-clone.txt
+6
@@ -311,6 +311,12 @@ or `--mirror` is given)
311 The result is Git repository can be separated from working
312 tree.
313
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 +
320 -j <n>::
321 --jobs <n>::
322 The number of submodules fetched at the same time.
builtin/clone.c
+11 -1
@@ -72,6 +72,7 @@ static char *remote_name = NULL;
72 static char *option_branch = NULL;
73 static struct string_list option_not = STRING_LIST_INIT_NODUP;
74 static const char *real_git_dir;
75 +static const char *ref_format;
76 static char *option_upload_pack = "git-upload-pack";
77 static int option_verbosity;
78 static int option_progress = -1;
@@ -157,6 +158,8 @@ static struct option builtin_clone_options[] = {
158 N_("any cloned submodules will be shallow")),
159 OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
160 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")),
163 OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
164 N_("set config inside the new repository")),
165 OPT_STRING_LIST(0, "server-option", &server_options,
@@ -932,6 +935,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
935 int submodule_progress;
936 int filter_submodules = 0;
937 int hash_algo;
938 + unsigned int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
939 const int do_not_override_repo_unix_permissions = -1;
940
941 struct transport_ls_refs_options transport_ls_refs_options =
@@ -957,6 +961,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
961 if (option_single_branch == -1)
962 option_single_branch = deepen ? 1 : 0;
963
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 +
970 if (option_mirror)
971 option_bare = 1;
972
@@ -1108,7 +1118,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
1118 * their on-disk data structures.
1119 */
1120 init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN,
1111 - REF_STORAGE_FORMAT_UNKNOWN, NULL,
1121 + ref_storage_format, NULL,
1122 do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
1123
1124 if (real_git_dir) {
t/t5601-clone.sh
+17
@@ -157,6 +157,23 @@ test_expect_success 'clone --mirror does not repeat tags' '
157
158 '
159
160 +test_expect_success 'clone with files ref format' '
161 + test_when_finished "rm -rf ref-storage" &&
162 + git clone --ref-format=files --mirror src ref-storage &&
163 + echo files >expect &&
164 + git -C ref-storage rev-parse --show-ref-format >actual &&
165 + test_cmp expect actual
166 +'
167 +
168 +test_expect_success 'clone with garbage ref format' '
169 + cat >expect <<-EOF &&
170 + fatal: unknown ref storage format ${SQ}garbage${SQ}
171 + EOF
172 + test_must_fail git clone --ref-format=garbage --mirror src ref-storage 2>err &&
173 + test_cmp expect err &&
174 + test_path_is_missing ref-storage
175 +'
176 +
177 test_expect_success 'clone to destination with trailing /' '
178
179 git clone src target-1/ &&