transport.c::handshake: make use of server options from remote
Utilize the `server_options` from the corresponding remote during the
handshake in `transport.c` when Git protocol v2 is detected. This helps
initialize the `server_options` in `transport.h:transport` if no server
options are set for the transport (typically via `--server-option` or
`-o`).
While another potential place to incorporate server options from the
remote is in `transport.c:transport_get`, setting server options for a
transport using a protocol other than v2 could lead to unexpected errors
(see `transport.c:die_if_server_options`).
Relevant tests and documentation have been updated accordingly.
Signed-off-by: Xing Xin <xingxin.xx@bytedance.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Xing Xin committedOct 8, 2024 at 03:38 UTC094f78a16a6c150ff125afd9c3f2773b47384c06
5 files changed+135
Documentation/fetch-options.txt
+3
index 80838fe37e..9dc7ac8dbd 100644--- a/Documentation/fetch-options.txt+++ b/Documentation/fetch-options.txt@@ -305,6 +305,9 @@ endif::git-pull[] 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 `remote.<name>.serverOption`+ are used instead. --show-forced-updates:: By default, git checks if a branch is force-updated during
Documentation/git-clone.txt
+3
index 8e925db7e9..409fb3a3af 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 `remote.<name>.serverOption`+ are used instead. `-n`:: `--no-checkout`::
Documentation/git-ls-remote.txt
+3
index 76c86c3ce4..d71c4ab3e2 100644--- a/Documentation/git-ls-remote.txt+++ b/Documentation/git-ls-remote.txt@@ -81,6 +81,9 @@ OPTIONS character. 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 `remote.<name>.serverOption`+ are used instead. <repository>:: The "remote" repository to query. This parameter can be
t/t5702-protocol-v2.sh
+123
index 1ef540f73d..5cec2061d2 100755--- a/t/t5702-protocol-v2.sh+++ b/t/t5702-protocol-v2.sh@@ -185,6 +185,43 @@ test_expect_success 'server-options are sent when using ls-remote' ' grep "server-option=world" log '+test_expect_success 'server-options from configuration are used by ls-remote' '+ test_when_finished "rm -rf log myclone" &&+ git clone "file://$(pwd)/file_parent" myclone &&+ cat >expect <<-EOF &&+ $(git -C file_parent rev-parse refs/heads/main)$(printf "\t")refs/heads/main+ EOF++ # Default server options from configuration are used+ git -C myclone config --add remote.origin.serverOption foo &&+ git -C myclone config --add remote.origin.serverOption bar &&+ GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \+ ls-remote origin main >actual &&+ test_cmp expect actual &&+ test_grep "ls-remote> server-option=foo" log &&+ test_grep "ls-remote> server-option=bar" log &&+ rm -f log &&++ # Empty value of remote.<name>.serverOption clears the list+ git -C myclone config --add remote.origin.serverOption "" &&+ git -C myclone config --add remote.origin.serverOption tar &&+ GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \+ ls-remote origin main >actual &&+ test_cmp expect actual &&+ test_grep "ls-remote> server-option=tar" log &&+ test_grep ! "ls-remote> server-option=foo" log &&+ test_grep ! "ls-remote> server-option=bar" log &&+ rm -f log &&++ # Server option from command line overrides those from configuration+ GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \+ ls-remote -o hello -o world origin main >actual &&+ test_cmp expect actual &&+ test_grep "ls-remote> server-option=hello" log &&+ test_grep "ls-remote> server-option=world" log &&+ test_grep ! "ls-remote> server-option=tar" 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" main 2>err &&@@ -381,6 +418,44 @@ test_expect_success 'server-options are sent when fetching' ' grep "server-option=world" log '+test_expect_success 'server-options from configuration are used by git-fetch' '+ test_when_finished "rm -rf log myclone" &&+ git clone "file://$(pwd)/file_parent" myclone &&+ git -C file_parent log -1 --format=%s >expect &&++ # Default server options from configuration are used+ git -C myclone config --add remote.origin.serverOption foo &&+ git -C myclone config --add remote.origin.serverOption bar &&+ GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \+ fetch origin main &&+ git -C myclone log -1 --format=%s origin/main >actual &&+ test_cmp expect actual &&+ test_grep "fetch> server-option=foo" log &&+ test_grep "fetch> server-option=bar" log &&+ rm -f log &&++ # Empty value of remote.<name>.serverOption clears the list+ git -C myclone config --add remote.origin.serverOption "" &&+ git -C myclone config --add remote.origin.serverOption tar &&+ GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \+ fetch origin main &&+ git -C myclone log -1 --format=%s origin/main >actual &&+ test_cmp expect actual &&+ test_grep "fetch> server-option=tar" log &&+ test_grep ! "fetch> server-option=foo" log &&+ test_grep ! "fetch> server-option=bar" log &&+ rm -f log &&++ # Server option from command line overrides those from configuration+ GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \+ fetch -o hello -o world origin main &&+ git -C myclone log -1 --format=%s origin/main >actual &&+ test_cmp expect actual &&+ test_grep "fetch> server-option=hello" log &&+ test_grep "fetch> server-option=world" log &&+ test_grep ! "fetch> server-option=tar" log+'+ test_expect_success 'warn if using server-option with fetch with legacy protocol' ' test_when_finished "rm -rf temp_child" &&@@ -404,6 +479,37 @@ test_expect_success 'server-options are sent when cloning' ' grep "server-option=world" log '+test_expect_success 'server-options from configuration are used by git-clone' '+ test_when_finished "rm -rf log myclone" &&++ # Default server options from configuration are used+ GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \+ -c remote.origin.serverOption=foo -c remote.origin.serverOption=bar \+ clone "file://$(pwd)/file_parent" myclone &&+ test_grep "clone> server-option=foo" log &&+ test_grep "clone> server-option=bar" log &&+ rm -rf log myclone &&++ # Empty value of remote.<name>.serverOption clears the list+ GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \+ -c remote.origin.serverOption=foo -c remote.origin.serverOption=bar \+ -c remote.origin.serverOption= -c remote.origin.serverOption=tar \+ clone "file://$(pwd)/file_parent" myclone &&+ test_grep "clone> server-option=tar" log &&+ test_grep ! "clone> server-option=foo" log &&+ test_grep ! "clone> server-option=bar" log &&+ rm -rf log myclone &&++ # Server option from command line overrides those from configuration+ GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \+ -c remote.origin.serverOption=tar \+ clone --server-option=hello --server-option=world \+ "file://$(pwd)/file_parent" myclone &&+ test_grep "clone> server-option=hello" log &&+ test_grep "clone> server-option=world" log &&+ test_grep ! "clone> server-option=tar" log+'+ test_expect_success 'warn if using server-option with clone with legacy protocol' ' test_when_finished "rm -rf myclone" &&@@ -415,6 +521,23 @@ test_expect_success 'warn if using server-option with clone with legacy protocol test_grep "server options require protocol version 2 or later" err '+test_expect_success 'server-option configuration with legacy protocol is ok' '+ test_when_finished "rm -rf myclone" &&++ env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \+ -c remote.origin.serverOption=foo -c remote.origin.serverOption=bar \+ clone "file://$(pwd)/file_parent" myclone+'++test_expect_success 'invalid server-option configuration' '+ test_when_finished "rm -rf myclone" &&++ test_must_fail git -c protocol.version=2 \+ -c remote.origin.serverOption \+ clone "file://$(pwd)/file_parent" myclone 2>err &&+ test_grep "error: missing value for '\''remote.origin.serveroption'\''" err+'+ test_expect_success 'upload-pack respects config using protocol v2' ' git init server && write_script server/.git/hook <<-\EOF &&
transport.c
+3
index 19b7e4cffd..47fda6a773 100644--- a/transport.c+++ b/transport.c@@ -334,6 +334,9 @@ static struct ref *handshake(struct transport *transport, int for_push, data->version = discover_version(&reader); switch (data->version) { case protocol_v2:+ if ((!transport->server_options || !transport->server_options->nr) &&+ transport->remote->server_options.nr)+ transport->server_options = &transport->remote->server_options; if (server_feature_v2("session-id", &server_sid)) trace2_data_string("transfer", NULL, "server-sid", server_sid); if (must_list_refs)