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

[PATCH v2 6/6] version: introduce osversion.command config for os-version output

From
Usman Akinyemi <usmanakinyemi202@gmail.com>
Date
Jan 17, 2025, 10:46 UTC
Message-ID
<20250117104639.65608-7-usmanakinyemi202@gmail.com>
In-Reply-To
<20250117104639.65608-1-usmanakinyemi202@gmail.com>

Currently by default, the new `os-version` capability only exchange the operating system name between servers and clients i.e "Linux" or "Windows".

Let's introduce a new configuration option, `osversion.command`, to handle the string exchange between servers and clients. This option allows customization of the exchanged string by leveraging the output of the specified command. This customization might be especially useful on some quite uncommon platforms like NonStop where interesting OS information is available from other means than uname(2).

If this new configuration option is not set, the `os-version` capability exchanges just the operating system name.

Helped-by: Randall S. Becker <rsbecker@nexbridge.com>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
---
 Documentation/config/transfer.txt | 11 ++++++-
 Documentation/gitprotocol-v2.txt  | 25 ++++++++-------
 t/t5555-http-smart-common.sh      | 28 +++++++++++++++++
 t/t5701-git-serve.sh              | 29 ++++++++++++++++++
 version.c                         | 51 ++++++++++++++++++++++++++++++-
 5 files changed, 129 insertions(+), 15 deletions(-)
diff --git a/Documentation/config/transfer.txt b/Documentation/config/transfer.txt
index c368a893bd..c9f38c5796 100644
--- a/Documentation/config/transfer.txt
+++ b/Documentation/config/transfer.txt
@@ -131,4 +131,13 @@ transfer.advertiseOSVersion::
 	servers. It makes clients and servers send to each other a string
 	representing the operating system name, like "Linux" or "Windows".
 	This string is retrieved from the `sysname` field of the struct returned
-	by the uname(2) system call. Defaults to true.
+	by the uname(2) system call. If the `osVersion.command` is set, the
+	output of the command specified will be the string exchanged by the clients
+	and the servers. Defaults to true.
+
+osVersion.command::
+	If this variable is set, the specified command will be run and the output
+	will be used as the value `X` for `os-version` capability (in the form
+	`os-version=X`). `osVersion.command` is only used if `transfer.advertiseOSVersion`
+	is true. Refer to the linkgit:git-config[1] documentation to learn more about
+	`transfer.advertiseOSVersion` config option.
diff --git a/Documentation/gitprotocol-v2.txt b/Documentation/gitprotocol-v2.txt
index a332b55e4c..93a2e97ec0 100644
--- a/Documentation/gitprotocol-v2.txt
+++ b/Documentation/gitprotocol-v2.txt
@@ -193,20 +193,19 @@ the presence or absence of particular features.
 os-version
 ~~~~~~~~~~
 
-In the same way as the `agent` capability above, the server can
-advertise the `os-version` capability to notify the client the
-kind of operating system it is running on. The client may optionally
-send its own `os-version` capability, to notify the server the kind of
-operating system it is also running on in its request to the server
-(but it MUST NOT do so if the server did not advertise the os-version
-capability). The value of this capability may consist of ASCII printable
+In the same way as the `agent` capability above, the server can advertise
+the `os-version` capability to notify the client the kind of operating system
+it is running on. The client may optionally send its own `os-version` capability,
+to notify the server the kind of operating system it is also running on in its
+request to the server (but it MUST NOT do so if the server did not advertise the
+os-version capability). The value of this capability may consist of ASCII printable
 characters(from 33 to 126 inclusive) and are typically made from the result of
-`uname -s`(OS name e.g Linux). The os-version capability can be disabled
-entirely by setting the `transfer.advertiseOSVersion` config option
-to `false`. The `os-version` strings are purely informative for
-statistics and debugging purposes, and MUST NOT be used to
-programmatically assume the presence or absence of particular
-features.
+`uname -s`(OS name e.g Linux). If the `osVersion.command` is set, the value of this
+capability are made from the ouput of the command specified. The os-version capability
+can be disabled entirely by setting the `transfer.advertiseOSVersion` config option
+to `false`. The `os-version` strings are purely informative for statistics and
+debugging purposes, and MUST NOT be used to programmatically assume the presence or
+absence of particular features.
 
 ls-refs
 ~~~~~~~
diff --git a/t/t5555-http-smart-common.sh b/t/t5555-http-smart-common.sh
index 6f357a005a..1a3df3d090 100755
--- a/t/t5555-http-smart-common.sh
+++ b/t/t5555-http-smart-common.sh
@@ -150,6 +150,34 @@ test_expect_success 'git upload-pack --advertise-refs: v2' '
 	test_cmp actual expect
 '
 
+test_expect_success 'git upload-pack --advertise-refs: v2 with osVersion.command config set' '
+	test_config osVersion.command "uname -srvm" &&
+	printf "agent=FAKE" >agent_and_long_osversion &&
+
+	if test_have_prereq !WINDOWS
+	then
+		printf "\nos-version=%s\n" $(uname -srvm | test_redact_non_printables) >>agent_and_long_osversion
+	fi &&
+
+	cat >expect <<-EOF &&
+	version 2
+	$(cat agent_and_long_osversion)
+	ls-refs=unborn
+	fetch=shallow wait-for-done
+	server-option
+	object-format=$(test_oid algo)
+	0000
+	EOF
+
+	GIT_PROTOCOL=version=2 \
+	GIT_USER_AGENT=FAKE \
+	git upload-pack --advertise-refs . >out 2>err &&
+
+	test-tool pkt-line unpack <out >actual &&
+	test_must_be_empty err &&
+	test_cmp actual expect
+'
+
 test_expect_success 'git receive-pack --advertise-refs: v2' '
 	# There is no v2 yet for receive-pack, implicit v0
 	cat >expect <<-EOF &&
diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh
index 8a783b3924..1395ac4eba 100755
--- a/t/t5701-git-serve.sh
+++ b/t/t5701-git-serve.sh
@@ -53,6 +53,35 @@ test_expect_success 'test capability advertisement' '
 	test_cmp expect actual
 '
 
+test_expect_success 'test capability advertisement with osVersion.command config set' '
+	test_config osVersion.command "uname -srvm" &&
+	printf "agent=git/$(git version | cut -d" " -f3)" >agent_and_long_osversion &&
+
+	if test_have_prereq !WINDOWS
+	then
+		printf "\nos-version=%s\n" $(uname -srvm | test_redact_non_printables) >>agent_and_long_osversion
+	fi &&
+
+	test_oid_cache <<-EOF &&
+	wrong_algo sha1:sha256
+	wrong_algo sha256:sha1
+	EOF
+	cat >expect_long.base <<-EOF &&
+	version 2
+	$(cat agent_and_long_osversion)
+	ls-refs=unborn
+	fetch=shallow wait-for-done
+	server-option
+	object-format=$(test_oid algo)
+	EOF
+	cat expect_long.base expect.trailer >expect &&
+
+	GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \
+		--advertise-capabilities >out &&
+	test-tool pkt-line unpack <out >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'stateless-rpc flag does not list capabilities' '
 	# Empty request
 	test-tool pkt-line pack >in <<-EOF &&
diff --git a/version.c b/version.c
index ea334c3e9c..2aa55e56b5 100644
--- a/version.c
+++ b/version.c
@@ -1,9 +1,13 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
 #include "git-compat-util.h"
 #include "version.h"
 #include "version-def.h"
 #include "strbuf.h"
 #include "gettext.h"
 #include "config.h"
+#include "run-command.h"
+#include "alias.h"
 
 const char git_version_string[] = GIT_VERSION;
 const char git_built_from_commit_string[] = GIT_BUILT_FROM_COMMIT;
@@ -71,6 +75,50 @@ int get_uname_info(struct strbuf *buf, unsigned int full)
 	return 0;
 }
 
+/*
+ * Return -1 if unable to retrieve the osversion.command config or
+ * if the command is malformed; otherwise, return 0 if successful.
+ */
+static int fill_os_version_command(struct child_process *cmd)
+{
+	const char *os_version_command;
+	const char **argv;
+	char *os_version_copy;
+	int n;
+
+	if (git_config_get_string_tmp("osversion.command", &os_version_command))
+		return -1;
+
+	os_version_copy = xstrdup(os_version_command);
+	n = split_cmdline(os_version_copy, &argv);
+
+	if (n < 0) {
+		warning(_("malformed osVersion.command config option: %s"),
+			_(split_cmdline_strerror(n)));
+		free(os_version_copy);
+		return -1;
+	}
+
+	for (int i = 0; i < n; i++)
+		strvec_push(&cmd->args, argv[i]);
+	free(os_version_copy);
+	free(argv);
+
+	return 0;
+}
+
+static int capture_os_version(struct strbuf *buf)
+{
+	struct child_process cmd = CHILD_PROCESS_INIT;
+
+	if (fill_os_version_command(&cmd))
+		return -1;
+	if (capture_command(&cmd, buf, 0))
+		return -1;
+
+	return 0;
+}
+
 const char *os_version(void)
 {
 	static const char *os = NULL;
@@ -78,7 +126,8 @@ const char *os_version(void)
 	if (!os) {
 		struct strbuf buf = STRBUF_INIT;
 
-		get_uname_info(&buf, 0);
+		if (capture_os_version(&buf))
+			get_uname_info(&buf, 0);
 		os = strbuf_detach(&buf, NULL);
 	}
 
-- 
2.48.0
Previous: Junio C HamanoNext: Eric Sunshine
Message 46 of 107 in “[Outreachy] Introduce os-version Capability with Configurable Options”
  1. 0/4 [Outreachy] Introduce os-version Capability with Configurable OptionsUsman Akinyemi, Jan 6, 2025
  2. 1/4 version: refactor redact_non_printables()Usman Akinyemi, Jan 6, 2025
  3. Eric SunshineJan 6, 2025
  4. Usman AkinyemiJan 8, 2025
  5. 2/4 version: refactor get_uname_info()Usman Akinyemi, Jan 6, 2025
  6. Junio C HamanoJan 6, 2025
  7. Usman AkinyemiJan 8, 2025
  8. 3/4 connect: advertise OS versionUsman Akinyemi, Jan 6, 2025
  9. Junio C HamanoJan 6, 2025
  10. Usman AkinyemiJan 8, 2025
  11. Junio C HamanoJan 8, 2025
  12. Usman AkinyemiJan 9, 2025
  13. Junio C HamanoJan 9, 2025
  14. Usman AkinyemiJan 10, 2025
  15. Junio C HamanoJan 10, 2025
  16. Usman AkinyemiJan 11, 2025
  17. Junio C HamanoJan 13, 2025
  18. Usman AkinyemiJan 13, 2025
  19. Junio C HamanoJan 13, 2025
  20. rsbecker@nexbridge.comJan 13, 2025
  21. Eric SunshineJan 6, 2025
  22. Usman AkinyemiJan 8, 2025
  23. 4/4 version: introduce osversion.command config for os-version outputUsman Akinyemi, Jan 6, 2025
  24. 0/6 [Outreachy] Introduce os-version Capability with Configurable OptionsUsman Akinyemi, Jan 17, 2025
  25. 1/6 version: refactor redact_non_printables()Usman Akinyemi, Jan 17, 2025
  26. Junio C HamanoJan 17, 2025
  27. Junio C HamanoJan 17, 2025
  28. Usman AkinyemiJan 20, 2025
  29. Christian CouderJan 21, 2025
  30. Junio C HamanoJan 21, 2025
  31. 2/6 version: refactor get_uname_info()Usman Akinyemi, Jan 17, 2025
  32. 3/6 version: extend get_uname_info() to hide system detailsUsman Akinyemi, Jan 17, 2025
  33. Junio C HamanoJan 17, 2025
  34. 4/6 t5701: add setup test to remove side-effect dependencyUsman Akinyemi, Jan 17, 2025
  35. Junio C HamanoJan 17, 2025
  36. Usman AkinyemiJan 20, 2025
  37. Junio C HamanoJan 20, 2025
  38. Usman AkinyemiJan 21, 2025
  39. 5/6 connect: advertise OS versionUsman Akinyemi, Jan 17, 2025
  40. Junio C HamanoJan 17, 2025
  41. Junio C HamanoJan 17, 2025
  42. rsbecker@nexbridge.comJan 17, 2025
  43. Junio C HamanoJan 17, 2025
  44. Usman AkinyemiJan 20, 2025
  45. Junio C HamanoJan 21, 2025
  46. 6/6 version: introduce osversion.command config for os-version outputUsman Akinyemi, Jan 17, 2025
  47. Eric SunshineJan 17, 2025
  48. Usman AkinyemiJan 20, 2025
  49. Eric SunshineJan 20, 2025
  50. Usman AkinyemiJan 20, 2025
  51. Junio C HamanoJan 17, 2025
  52. rsbecker@nexbridge.comJan 17, 2025
  53. Junio C HamanoJan 17, 2025
  54. rsbecker@nexbridge.comJan 17, 2025
  55. Usman AkinyemiJan 20, 2025
  56. Junio C HamanoJan 21, 2025
  57. rsbecker@nexbridge.comJan 21, 2025
  58. 0/6 [Outreachy] Introduce os-version Capability with Configurable OptionsUsman Akinyemi, Jan 24, 2025
  59. 1/6 version: replace manual ASCII checks with isprint() for clarityUsman Akinyemi, Jan 24, 2025
  60. Junio C HamanoJan 24, 2025
  61. 2/6 version: refactor redact_non_printables()Usman Akinyemi, Jan 24, 2025
  62. 3/6 version: refactor get_uname_info()Usman Akinyemi, Jan 24, 2025
  63. 4/6 version: extend get_uname_info() to hide system detailsUsman Akinyemi, Jan 24, 2025
  64. 5/6 t5701: add setup test to remove side-effect dependencyUsman Akinyemi, Jan 24, 2025
  65. Junio C HamanoJan 24, 2025
  66. 6/6 connect: advertise OS versionUsman Akinyemi, Jan 24, 2025
  67. 0/6 [Outreachy] extend agent capability to include OS nameUsman Akinyemi, Feb 5, 2025
  68. 1/6 version: replace manual ASCII checks with isprint() for clarityUsman Akinyemi, Feb 5, 2025
  69. 2/6 version: refactor redact_non_printables()Usman Akinyemi, Feb 5, 2025
  70. 3/6 version: refactor get_uname_info()Usman Akinyemi, Feb 5, 2025
  71. 4/6 version: extend get_uname_info() to hide system detailsUsman Akinyemi, Feb 5, 2025
  72. 6/6 agent: advertise OS name via agent capabilityUsman Akinyemi, Feb 5, 2025
  73. Junio C HamanoFeb 5, 2025
  74. Usman AkinyemiFeb 6, 2025
  75. Junio C HamanoFeb 6, 2025
  76. Usman AkinyemiFeb 7, 2025
  77. Junio C HamanoFeb 7, 2025
  78. Usman AkinyemiFeb 7, 2025
  79. 5/6 t5701: add setup test to remove side-effect dependencyUsman Akinyemi, Feb 5, 2025
  80. 0/6 [Outreachy] extend agent capability to include OS nameUsman Akinyemi, Feb 14, 2025
  81. 1/6 version: replace manual ASCII checks with isprint() for clarityUsman Akinyemi, Feb 14, 2025
  82. 2/6 version: refactor redact_non_printables()Usman Akinyemi, Feb 14, 2025
  83. 3/6 version: refactor get_uname_info()Usman Akinyemi, Feb 14, 2025
  84. 4/6 version: extend get_uname_info() to hide system detailsUsman Akinyemi, Feb 14, 2025
  85. 5/6 t5701: add setup test to remove side-effect dependencyUsman Akinyemi, Feb 14, 2025
  86. Junio C HamanoFeb 14, 2025
  87. 6/6 agent: advertise OS name via agent capabilityUsman Akinyemi, Feb 14, 2025
  88. Junio C HamanoFeb 14, 2025
  89. Usman AkinyemiFeb 15, 2025
  90. 0/6 [Outreachy] extend agent capability to include OS nameUsman Akinyemi, Feb 15, 2025
  91. 1/6 version: replace manual ASCII checks with isprint() for clarityUsman Akinyemi, Feb 15, 2025
  92. 2/6 version: refactor redact_non_printables()Usman Akinyemi, Feb 15, 2025
  93. 3/6 version: refactor get_uname_info()Usman Akinyemi, Feb 15, 2025
  94. 4/6 version: extend get_uname_info() to hide system detailsUsman Akinyemi, Feb 15, 2025
  95. 5/6 t5701: add setup test to remove side-effect dependencyUsman Akinyemi, Feb 15, 2025
  96. 6/6 agent: advertise OS name via agent capabilityUsman Akinyemi, Feb 15, 2025
  97. Junio C HamanoFeb 18, 2025
  98. Junio C HamanoFeb 18, 2025
  99. Junio C HamanoJan 24, 2025
  100. Christian CouderJan 27, 2025
  101. Junio C HamanoJan 27, 2025
  102. Christian CouderJan 31, 2025
  103. Junio C HamanoJan 31, 2025
  104. Usman AkinyemiJan 31, 2025
  105. Junio C HamanoJan 31, 2025
  106. Usman AkinyemiJan 31, 2025
  107. Junio C HamanoJan 31, 2025

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.