From: Xing Xin <xingxin.xx@xxxxxxxxxxxxx> Teach git-clone to recognize the `fetch.serverOption` configuration as a default list of server options to send for Git protocol v2, if server options are not explicitly set via the command line. Note that `builtin/clone.c:cmd_clone` originally read the git config twice via `builtin/clone.c:git_clone_config`, which would duplicate server options if parsing logic were added there. Upon investigation, it was found that the first config read is unnecessary since all the global variables it sets are actually used after the second config read. Therefore, the first config read is replaced with a simple `config.c:git_default_config`. Tests and documentation have been updated accordingly. Signed-off-by: Xing Xin <xingxin.xx@xxxxxxxxxxxxx> --- Documentation/git-clone.txt | 3 +++ builtin/clone.c | 22 ++++++++++++++++------ t/t5702-protocol-v2.sh | 22 ++++++++++++++++++++-- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 8e925db7e9c..105645ed685 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -149,6 +149,9 @@ objects from the source repository into a pack in the cloned repository. unknown ones, is server-specific. When multiple ++--server-option=++__<option>__ are given, they are all sent to the other side in the order listed on the command line. + When no ++--server-option=++__<option>__ is given from the command + line, the values of configuration variable `fetch.serverOption` + are used instead. `-n`:: `--no-checkout`:: diff --git a/builtin/clone.c b/builtin/clone.c index 269b6e18a4e..5a1e2e769af 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -85,7 +85,8 @@ static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP; static struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT; static int option_filter_submodules = -1; /* unspecified */ static int config_filter_submodules = -1; /* unspecified */ -static struct string_list server_options = STRING_LIST_INIT_NODUP; +static struct string_list config_server_options = STRING_LIST_INIT_DUP; +static struct string_list option_server_options = STRING_LIST_INIT_DUP; static int option_remote_submodules; static const char *bundle_uri; @@ -160,7 +161,7 @@ static struct option builtin_clone_options[] = { N_("specify the reference format to use")), OPT_STRING_LIST('c', "config", &option_config, N_("key=value"), N_("set config inside the new repository")), - OPT_STRING_LIST(0, "server-option", &server_options, + OPT_STRING_LIST(0, "server-option", &option_server_options, N_("server-specific"), N_("option to transmit")), OPT_IPVERSION(&family), OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options), @@ -847,6 +848,12 @@ static int git_clone_config(const char *k, const char *v, config_reject_shallow = git_config_bool(k, v); if (!strcmp(k, "clone.filtersubmodules")) config_filter_submodules = git_config_bool(k, v); + if (!strcmp(k, "fetch.serveroption")) { + if (!v) + return config_error_nonbool(k); + parse_transport_option(v, &config_server_options); + return 0; + } return git_default_config(k, v, ctx, cb); } @@ -982,17 +989,20 @@ int cmd_clone(int argc, const char **argv, const char *prefix) int hash_algo; enum ref_storage_format ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN; const int do_not_override_repo_unix_permissions = -1; - + struct string_list *server_options = NULL; struct transport_ls_refs_options transport_ls_refs_options = TRANSPORT_LS_REFS_OPTIONS_INIT; packet_trace_identity("clone"); - git_config(git_clone_config, NULL); + git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, builtin_clone_options, builtin_clone_usage, 0); + server_options = option_server_options.nr ? + &option_server_options : &config_server_options; + if (argc > 2) usage_msg_opt(_("Too many arguments."), builtin_clone_usage, builtin_clone_options); @@ -1359,8 +1369,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix) transport_set_option(transport, TRANS_OPT_UPLOADPACK, option_upload_pack); - if (server_options.nr) - transport->server_options = &server_options; + if (server_options && server_options->nr) + transport->server_options = server_options; if (filter_options.choice) { const char *spec = diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index ae25400010e..3bf31fb570d 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -424,12 +424,30 @@ test_expect_success 'warn if using server-option with fetch with legacy protocol test_expect_success 'server-options are sent when cloning' ' test_when_finished "rm -rf log myclone" && + # Specify server options from command line GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \ clone --server-option=hello --server-option=world \ "file://$(pwd)/file_parent" myclone && + test_grep "server-option=hello" log && + test_grep "server-option=world" log && + rm -rf log myclone && - grep "server-option=hello" log && - grep "server-option=world" log + # Specify server options from fetch.serverOption config + GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \ + -c fetch.serverOption=hello -c fetch.serverOption=world \ + clone "file://$(pwd)/file_parent" myclone && + test_grep "server-option=hello" log && + test_grep "server-option=world" log && + rm -rf log myclone && + + # Cmdline server options take a higher priority + GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \ + -c fetch.serverOption=hello -c fetch.serverOption=world \ + clone --server-option=foo=bar \ + "file://$(pwd)/file_parent" myclone && + test_grep ! "server-option=hello" log && + test_grep ! "server-option=world" log && + test_grep "server-option=foo=bar" log ' test_expect_success 'warn if using server-option with clone with legacy protocol' ' -- gitgitgadget