]> git.ipfire.org Git - thirdparty/git.git/commitdiff
transport.c::handshake: make use of server options from remote
authorXing Xin <xingxin.xx@bytedance.com>
Tue, 8 Oct 2024 03:38:17 +0000 (03:38 +0000)
committerJunio C Hamano <gitster@pobox.com>
Tue, 8 Oct 2024 17:22:08 +0000 (10:22 -0700)
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>
Documentation/fetch-options.txt
Documentation/git-clone.txt
Documentation/git-ls-remote.txt
t/t5702-protocol-v2.sh
transport.c

index 80838fe37ef30e857c4f4cdeba724a528c0bb622..9dc7ac8dbdc4ca98e2f2d314c082fdebbd0b36ab 100644 (file)
@@ -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
index 8e925db7e9c6622237cf9dedbb0eb56eb7ead865..409fb3a3af69a2df1f0281a84a5961fa6e9c6d36 100644 (file)
@@ -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`::
index 76c86c3ce4fee0cabc8015a1a372e3931bd97155..d71c4ab3e290c512d599a2817e8ba3b8ca124f73 100644 (file)
@@ -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
index 1ef540f73d34756673423ff77fa46567bd34b2ab..5cec2061d28bb3e969c43a6eb286e1fd6ede44c1 100755 (executable)
@@ -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 &&
index 19b7e4cffd3f10198ba54bc184a2bb7a890d547a..47fda6a7732f4b8cdcb6e750f36b896a988ffd0b 100644 (file)
@@ -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)