Merge branch 'jt/clone-server-option'

"git clone" learned a new --server-option option when talking over
the protocol version 2.

* jt/clone-server-option:
  clone: send server options when using protocol v2
  transport: die if server options are unsupported
This commit is contained in:
Junio C Hamano
2019-05-09 00:37:25 +09:00
5 changed files with 67 additions and 1 deletions

View File

@ -216,7 +216,8 @@ endif::git-pull[]
--server-option=<option>:: --server-option=<option>::
Transmit the given string to the server when communicating using Transmit the given string to the server when communicating using
protocol version 2. The given string must not contain a NUL or LF protocol version 2. The given string must not contain a NUL or LF
character. character. The server's handling of server options, including
unknown ones, is server-specific.
When multiple `--server-option=<option>` are given, they are all When multiple `--server-option=<option>` are given, they are all
sent to the other side in the order listed on the command line. sent to the other side in the order listed on the command line.

View File

@ -131,6 +131,14 @@ objects from the source repository into a pack in the cloned repository.
is specified. This flag forces progress status even if the is specified. This flag forces progress status even if the
standard error stream is not directed to a terminal. standard error stream is not directed to a terminal.
--server-option=<option>::
Transmit the given string to the server when communicating using
protocol version 2. The given string must not contain a NUL or LF
character. The server's handling of server options, including
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.
--no-checkout:: --no-checkout::
-n:: -n::
No checkout of HEAD is performed after the clone is complete. No checkout of HEAD is performed after the clone is complete.

View File

@ -66,6 +66,7 @@ static int option_dissociate;
static int max_jobs = -1; static int max_jobs = -1;
static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP; static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;
static struct list_objects_filter_options filter_options; static struct list_objects_filter_options filter_options;
static struct string_list server_options = STRING_LIST_INIT_NODUP;
static int recurse_submodules_cb(const struct option *opt, static int recurse_submodules_cb(const struct option *opt,
const char *arg, int unset) const char *arg, int unset)
@ -137,6 +138,8 @@ static struct option builtin_clone_options[] = {
N_("separate git dir from working tree")), N_("separate git dir from working tree")),
OPT_STRING_LIST('c', "config", &option_config, N_("key=value"), OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
N_("set config inside the new repository")), N_("set config inside the new repository")),
OPT_STRING_LIST(0, "server-option", &server_options,
N_("server-specific"), N_("option to transmit")),
OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"), OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
TRANSPORT_FAMILY_IPV4), TRANSPORT_FAMILY_IPV4),
OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"), OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
@ -1136,6 +1139,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
transport_set_option(transport, TRANS_OPT_UPLOADPACK, transport_set_option(transport, TRANS_OPT_UPLOADPACK,
option_upload_pack); option_upload_pack);
if (server_options.nr)
transport->server_options = &server_options;
if (filter_options.choice) { if (filter_options.choice) {
struct strbuf expanded_filter_spec = STRBUF_INIT; struct strbuf expanded_filter_spec = STRBUF_INIT;
expand_list_objects_filter_spec(&filter_options, expand_list_objects_filter_spec(&filter_options,

View File

@ -182,6 +182,13 @@ test_expect_success 'server-options are sent when using ls-remote' '
grep "server-option=world" log grep "server-option=world" log
' '
test_expect_success 'warn if using server-option with ls-remote with legacy protocol' '
test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \
ls-remote -o hello -o world "file://$(pwd)/file_parent" master 2>err &&
test_i18ngrep "see protocol.version in" err &&
test_i18ngrep "server options require protocol version 2 or later" err
'
test_expect_success 'clone with file:// using protocol v2' ' test_expect_success 'clone with file:// using protocol v2' '
test_when_finished "rm -f log" && test_when_finished "rm -f log" &&
@ -251,6 +258,40 @@ test_expect_success 'server-options are sent when fetching' '
grep "server-option=world" log grep "server-option=world" log
' '
test_expect_success 'warn if using server-option with fetch with legacy protocol' '
test_when_finished "rm -rf temp_child" &&
git init temp_child &&
test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -C temp_child -c protocol.version=0 \
fetch -o hello -o world "file://$(pwd)/file_parent" master 2>err &&
test_i18ngrep "see protocol.version in" err &&
test_i18ngrep "server options require protocol version 2 or later" err
'
test_expect_success 'server-options are sent when cloning' '
test_when_finished "rm -rf log myclone" &&
GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \
clone --server-option=hello --server-option=world \
"file://$(pwd)/file_parent" myclone &&
grep "server-option=hello" log &&
grep "server-option=world" log
'
test_expect_success 'warn if using server-option with clone with legacy protocol' '
test_when_finished "rm -rf myclone" &&
test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \
clone --server-option=hello --server-option=world \
"file://$(pwd)/file_parent" myclone 2>err &&
test_i18ngrep "see protocol.version in" err &&
test_i18ngrep "server options require protocol version 2 or later" err
'
test_expect_success 'upload-pack respects config using protocol v2' ' test_expect_success 'upload-pack respects config using protocol v2' '
git init server && git init server &&
write_script server/.git/hook <<-\EOF && write_script server/.git/hook <<-\EOF &&

View File

@ -252,6 +252,14 @@ static int connect_setup(struct transport *transport, int for_push)
return 0; return 0;
} }
static void die_if_server_options(struct transport *transport)
{
if (!transport->server_options || !transport->server_options->nr)
return;
advise(_("see protocol.version in 'git help config' for more details"));
die(_("server options require protocol version 2 or later"));
}
/* /*
* Obtains the protocol version from the transport and writes it to * Obtains the protocol version from the transport and writes it to
* transport->data->version, first connecting if not already connected. * transport->data->version, first connecting if not already connected.
@ -286,6 +294,7 @@ static struct ref *handshake(struct transport *transport, int for_push,
break; break;
case protocol_v1: case protocol_v1:
case protocol_v0: case protocol_v0:
die_if_server_options(transport);
get_remote_heads(&reader, &refs, get_remote_heads(&reader, &refs,
for_push ? REF_NORMAL : 0, for_push ? REF_NORMAL : 0,
&data->extra_have, &data->extra_have,
@ -362,6 +371,7 @@ static int fetch_refs_via_pack(struct transport *transport,
break; break;
case protocol_v1: case protocol_v1:
case protocol_v0: case protocol_v0:
die_if_server_options(transport);
refs = fetch_pack(&args, data->fd, refs = fetch_pack(&args, data->fd,
refs_tmp ? refs_tmp : transport->remote_refs, refs_tmp ? refs_tmp : transport->remote_refs,
to_fetch, nr_heads, &data->shallow, to_fetch, nr_heads, &data->shallow,