git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 3/5] transport.c::handshake: make use of server options from remote

From
XGXing Xin via GitGitGadget <gitgitgadget@gmail.com>
Date
Oct 8, 2024, 03:38 UTC
Message-ID
<f0835259b06aed6130e6ee7c5dc37cfebdc77393.1728358699.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1776.v3.git.git.1728358699.gitgitgadget@gmail.com>
From: Xing Xin <xingxin.xx@bytedance.com>

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>
---
 Documentation/fetch-options.txt |   3 +
 Documentation/git-clone.txt     |   3 +
 Documentation/git-ls-remote.txt |   3 +
 t/t5702-protocol-v2.sh          | 123 ++++++++++++++++++++++++++++++++
 transport.c                     |   3 +
 5 files changed, 135 insertions(+)
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 80838fe37ef..9dc7ac8dbdc 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
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 8e925db7e9c..409fb3a3af6 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`::
diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
index 76c86c3ce4f..d71c4ab3e29 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
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 1ef540f73d3..5cec2061d28 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 &&
diff --git a/transport.c b/transport.c
index 4d9e605b273..b416fc84567 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)
-- 
gitgitgadget
Previous: Xing Xin via GitGitGadgetNext: Xing Xin via GitGitGadget
Message 34 of 39 in “Support server option from configuration”
  1. 0/4 Support server option from configurationblanet via GitGitGadget, Sep 2, 2024
  2. 1/4 transport: add parse_transport_option() methodXing Xin via GitGitGadget, Sep 2, 2024
  3. 2/4 builtin/fetch.c: add fetch.serverOption configurationXing Xin via GitGitGadget, Sep 2, 2024
  4. Patrick SteinhardtSep 3, 2024
  5. 3/4 builtin/clone.c: recognize fetch.serverOption configurationXing Xin via GitGitGadget, Sep 2, 2024
  6. Patrick SteinhardtSep 3, 2024
  7. Xing XinSep 4, 2024
  8. Patrick SteinhardtSep 5, 2024
  9. Xing XinSep 5, 2024
  10. Patrick SteinhardtSep 5, 2024
  11. Junio C HamanoSep 5, 2024
  12. Xing XinSep 9, 2024
  13. Patrick SteinhardtSep 9, 2024
  14. Xing XinSep 23, 2024
  15. Junio C HamanoSep 9, 2024
  16. 4/4 builtin/ls-remote.c: recognize fetch.serverOption configurationXing Xin via GitGitGadget, Sep 2, 2024
  17. Patrick SteinhardtSep 3, 2024
  18. Patrick SteinhardtSep 3, 2024
  19. 0/5 Support server option from configurationblanet via GitGitGadget, Sep 23, 2024
  20. 1/5 transport: introduce parse_transport_option() methodXing Xin via GitGitGadget, Sep 23, 2024
  21. 2/5 remote: introduce remote.<name>.serverOption configurationXing Xin via GitGitGadget, Sep 23, 2024
  22. Patrick SteinhardtOct 7, 2024
  23. Xing XinOct 8, 2024
  24. 3/5 transport.c::handshake: make use of server options from remoteXing Xin via GitGitGadget, Sep 23, 2024
  25. 4/5 fetch: respect --server-option when fetching multiple remotesXing Xin via GitGitGadget, Sep 23, 2024
  26. Patrick SteinhardtOct 7, 2024
  27. 5/5 ls-remote: leakfix for not clearing server_optionsXing Xin via GitGitGadget, Sep 23, 2024
  28. Patrick SteinhardtOct 7, 2024
  29. Patrick SteinhardtOct 7, 2024
  30. Xing XinOct 8, 2024
  31. 0/5 Support server option from configurationblanet via GitGitGadget, Oct 8, 2024
  32. 1/5 transport: introduce parse_transport_option() methodXing Xin via GitGitGadget, Oct 8, 2024
  33. 2/5 remote: introduce remote.<name>.serverOption configurationXing Xin via GitGitGadget, Oct 8, 2024
  34. 3/5 transport.c::handshake: make use of server options from remoteXing Xin via GitGitGadget, Oct 8, 2024
  35. 4/5 fetch: respect --server-option when fetching multiple remotesXing Xin via GitGitGadget, Oct 8, 2024
  36. Junio C HamanoOct 8, 2024
  37. 5/5 ls-remote: leakfix for not clearing server_optionsXing Xin via GitGitGadget, Oct 8, 2024
  38. Patrick SteinhardtOct 8, 2024
  39. Junio C HamanoOct 8, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.