diff --git a/Documentation/git-clone.adoc b/Documentation/git-clone.adoc index 27e4d13942..07f7cf1a98 100644 --- a/Documentation/git-clone.adoc +++ b/Documentation/git-clone.adoc @@ -350,7 +350,10 @@ or `--mirror` is given) `--ref-storage-format=`:: -Specify the given ref storage format for the repository. The valid values are: +Specify the given ref storage __ for the repository. Backends that +require additional configuration accept a payload in the form +`://`, for example a connection string identifying the +database that shall store the references. The valid values are: + include::ref-storage-format.adoc[] diff --git a/Documentation/git-init.adoc b/Documentation/git-init.adoc index 73e1f787cb..b02af22ad1 100644 --- a/Documentation/git-init.adoc +++ b/Documentation/git-init.adoc @@ -58,7 +58,10 @@ values are `sha1` and (if enabled) `sha256`. `sha1` is the default. include::object-format-disclaimer.adoc[] `--ref-storage-format=`:: -Specify the given ref storage __ for the repository. The valid values are: +Specify the given ref storage __ for the repository. Backends that +require additional configuration accept a payload in the form +`://`, for example a connection string identifying the +database that shall store the references. The valid values are: + include::ref-storage-format.adoc[] diff --git a/builtin/clone.c b/builtin/clone.c index dd722e4de1..9812aaec8f 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -901,7 +901,7 @@ int cmd_clone(int argc, char *option_origin = NULL; struct string_list option_not = STRING_LIST_INIT_NODUP; const char *real_git_dir = NULL; - const char *ref_storage_format_str = NULL; + const char *ref_storage_format_uri = NULL; const char *option_upload_pack = "git-upload-pack"; int option_progress = -1; int option_sparse_checkout = 0; @@ -981,7 +981,7 @@ int cmd_clone(int argc, N_("any cloned submodules will be shallow")), OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"), N_("separate git dir from working tree")), - OPT_STRING(0, "ref-storage-format", &ref_storage_format_str, N_("format"), + OPT_STRING(0, "ref-storage-format", &ref_storage_format_uri, N_("format"), N_("specify the reference storage format to use")), OPT_ALIAS_F(0, "ref-format", "ref-storage-format", PARSE_OPT_HIDDEN), OPT_STRING_LIST('c', "config", &option_config, N_("key=value"), @@ -1028,10 +1028,10 @@ int cmd_clone(int argc, if (option_single_branch == -1) option_single_branch = deepen ? 1 : 0; - if (ref_storage_format_str) { - ref_storage_format = ref_storage_format_by_name(ref_storage_format_str); + if (ref_storage_format_uri) { + ref_storage_format = ref_storage_format_by_uri(ref_storage_format_uri, NULL); if (ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) - die(_("unknown ref storage format '%s'"), ref_storage_format_str); + die(_("unknown ref storage format '%s'"), ref_storage_format_uri); } if (option_mirror) { @@ -1187,7 +1187,7 @@ int cmd_clone(int argc, * their on-disk data structures. */ init_db(the_repository, git_dir, real_git_dir, work_tree, option_template, - GIT_HASH_UNKNOWN, ref_storage_format, NULL, + GIT_HASH_UNKNOWN, ref_storage_format_uri, NULL, do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB); diff --git a/builtin/init-db.c b/builtin/init-db.c index 1612413af0..7a65d1673b 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -83,10 +83,9 @@ int cmd_init_db(int argc, unsigned int flags = 0; int bare = startup_info->force_bare_repository ? 1 : -1; const char *object_format = NULL; - const char *ref_storage_format_str = NULL; + const char *ref_storage_format_uri = NULL; const char *initial_branch = NULL; int hash_algo = GIT_HASH_UNKNOWN; - enum ref_storage_format ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN; int init_shared_repository = -1; const struct option init_db_options[] = { OPT_STRING(0, "template", &template_dir, N_("template-directory"), @@ -109,7 +108,7 @@ int cmd_init_db(int argc, N_("override the name of the initial branch")), OPT_STRING(0, "object-format", &object_format, N_("hash"), N_("specify the hash algorithm to use")), - OPT_STRING(0, "ref-storage-format", &ref_storage_format_str, N_("format"), + OPT_STRING(0, "ref-storage-format", &ref_storage_format_uri, N_("format"), N_("specify the reference storage format to use")), OPT_ALIAS_F(0, "ref-format", "ref-storage-format", PARSE_OPT_HIDDEN), OPT_END() @@ -174,12 +173,6 @@ int cmd_init_db(int argc, die(_("unknown hash algorithm '%s'"), object_format); } - if (ref_storage_format_str) { - ref_storage_format = ref_storage_format_by_name(ref_storage_format_str); - if (ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) - die(_("unknown ref storage format '%s'"), ref_storage_format_str); - } - if (init_shared_repository != -1) repo_settings_set_shared_repository(the_repository, init_shared_repository); @@ -250,8 +243,8 @@ int cmd_init_db(int argc, flags |= INIT_DB_EXIST_OK; ret = init_db(the_repository, git_dir, real_git_dir, work_tree, - template_dir, hash_algo, ref_storage_format, initial_branch, - init_shared_repository, flags); + template_dir, hash_algo, ref_storage_format_uri, + initial_branch, init_shared_repository, flags); free(template_dir_to_free); free(real_git_dir_to_free); diff --git a/setup.c b/setup.c index df8cbf196d..13f4a0aba9 100644 --- a/setup.c +++ b/setup.c @@ -2727,7 +2727,8 @@ out: } static void repository_format_configure(struct repository_format *repo_fmt, - int hash, enum ref_storage_format ref_storage_format) + int hash, + const char *ref_storage_format_uri) { struct default_format_config cfg = { .hash = GIT_HASH_UNKNOWN, @@ -2738,6 +2739,7 @@ static void repository_format_configure(struct repository_format *repo_fmt, .ignore_repo = 1, .ignore_worktree = 1, }; + enum ref_storage_format ref_storage_format; char *ref_storage_payload = NULL; const char *env; @@ -2791,8 +2793,12 @@ static void repository_format_configure(struct repository_format *repo_fmt, * 7. Otherwise, we fall back to the default ref storage format * compiled into Git. */ - if (ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN) { - /* nothing to do */ + if (ref_storage_format_uri) { + ref_storage_format = ref_storage_format_by_uri(ref_storage_format_uri, + &ref_storage_payload); + if (ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) + die(_("unknown ref storage format specified via command line: '%s'"), + ref_storage_format_uri); } else if ((env = getenv(GIT_REF_STORAGE_FORMAT_ENVIRONMENT))) { ref_storage_format = ref_storage_format_by_uri(env, &ref_storage_payload); if (ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) @@ -2845,7 +2851,7 @@ int init_db(struct repository *repo, const char *real_git_dir, const char *worktree, const char *template_dir, int hash, - enum ref_storage_format ref_storage_format, + const char *ref_storage_format_uri, const char *initial_branch, int init_shared_repository, unsigned int flags) { @@ -2882,7 +2888,7 @@ int init_db(struct repository *repo, * is an attempt to reinitialize new repository with an old tool. */ read_and_verify_repository_format(&repo_fmt, repo_get_git_dir(repo), NULL); - repository_format_configure(&repo_fmt, hash, ref_storage_format); + repository_format_configure(&repo_fmt, hash, ref_storage_format_uri); if (apply_repository_format(repo, &repo_fmt, APPLY_REPOSITORY_FORMAT_HONOR_ENV, &err) < 0) die("%s", err.buf); diff --git a/setup.h b/setup.h index 763fd384e8..f04d2984b4 100644 --- a/setup.h +++ b/setup.h @@ -265,7 +265,7 @@ int init_db(struct repository *repo, const char *real_git_dir, const char *worktree, const char *template_dir, int hash_algo, - enum ref_storage_format ref_storage_format, + const char *ref_storage_format_uri, const char *initial_branch, int init_shared_repository, unsigned int flags); void initialize_repository_version(struct repository *repo, diff --git a/t/t0001-init.sh b/t/t0001-init.sh index fe5bc3d3e1..f1d227f271 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -833,7 +833,7 @@ done test_expect_success 'init with --ref-storage-format=garbage' ' test_when_finished "rm -rf refformat" && cat >expect <<-EOF && - fatal: unknown ref storage format ${SQ}garbage${SQ} + fatal: unknown ref storage format specified via command line: ${SQ}garbage${SQ} EOF test_must_fail git init --ref-storage-format=garbage refformat 2>err && test_cmp expect err diff --git a/t/t1423-ref-backend.sh b/t/t1423-ref-backend.sh index 525b2a19b4..ee2bb66b99 100755 --- a/t/t1423-ref-backend.sh +++ b/t/t1423-ref-backend.sh @@ -254,6 +254,36 @@ test_expect_success 'initializing repository with alt ref directory' ' ) ' +test_expect_success 'initializing repository with --ref-storage-format and payload' ' + test_when_finished "rm -rf repo refdir" && + mkdir refdir && + BACKEND="$(test_detect_ref_format)://$(pwd)/refdir" && + git init --ref-storage-format="$BACKEND" repo && + verify_files_exist repo/.git refdir && + + git -C repo config get extensions.refstorage >actual && + echo $BACKEND >expect && + test_cmp expect actual && + + test_commit -C repo 1 && + git -C repo refs list >out && + test_grep "refs/tags/1" out && + + # Reinitializing the repository is fine when not specifying any format. + git -C repo init && + # Reinitializing with the same backend is fine, too. + git -C repo init --ref-storage-format="$BACKEND" && + # Reinitializing without a payload should fail. + test_must_fail git -C repo init --ref-storage-format="$(test_detect_ref_format)" 2>err && + test_grep "attempt to reinitialize repository with different reference storage payload" err && + # Reinitializing with a different payload should fail, too. + test_must_fail git -C repo init --ref-storage-format="$(test_detect_ref_format)://$(pwd)/other" 2>err && + test_grep "attempt to reinitialize repository with different reference storage payload" err && + + git -C repo config get extensions.refstorage >actual && + test_cmp expect actual +' + test_expect_success 'cloning repository with alt ref directory' ' test_when_finished "rm -rf source repo refdir" && mkdir refdir &&