Skip to content

Commit 923f6a8

Browse files
Unique-Usmangitster
authored andcommitted
version: introduce osversion.command config for os-version output
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent a0fc9a3 commit 923f6a8

File tree

5 files changed

+129
-15
lines changed

5 files changed

+129
-15
lines changed

Documentation/config/transfer.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,13 @@ transfer.advertiseOSVersion::
131131
servers. It makes clients and servers send to each other a string
132132
representing the operating system name, like "Linux" or "Windows".
133133
This string is retrieved from the `sysname` field of the struct returned
134-
by the uname(2) system call. Defaults to true.
134+
by the uname(2) system call. If the `osVersion.command` is set, the
135+
output of the command specified will be the string exchanged by the clients
136+
and the servers. Defaults to true.
137+
138+
osVersion.command::
139+
If this variable is set, the specified command will be run and the output
140+
will be used as the value `X` for `os-version` capability (in the form
141+
`os-version=X`). `osVersion.command` is only used if `transfer.advertiseOSVersion`
142+
is true. Refer to the linkgit:git-config[1] documentation to learn more about
143+
`transfer.advertiseOSVersion` config option.

Documentation/gitprotocol-v2.txt

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -193,20 +193,19 @@ the presence or absence of particular features.
193193
os-version
194194
~~~~~~~~~~
195195

196-
In the same way as the `agent` capability above, the server can
197-
advertise the `os-version` capability to notify the client the
198-
kind of operating system it is running on. The client may optionally
199-
send its own `os-version` capability, to notify the server the kind of
200-
operating system it is also running on in its request to the server
201-
(but it MUST NOT do so if the server did not advertise the os-version
202-
capability). The value of this capability may consist of ASCII printable
196+
In the same way as the `agent` capability above, the server can advertise
197+
the `os-version` capability to notify the client the kind of operating system
198+
it is running on. The client may optionally send its own `os-version` capability,
199+
to notify the server the kind of operating system it is also running on in its
200+
request to the server (but it MUST NOT do so if the server did not advertise the
201+
os-version capability). The value of this capability may consist of ASCII printable
203202
characters(from 33 to 126 inclusive) and are typically made from the result of
204-
`uname -s`(OS name e.g Linux). The os-version capability can be disabled
205-
entirely by setting the `transfer.advertiseOSVersion` config option
206-
to `false`. The `os-version` strings are purely informative for
207-
statistics and debugging purposes, and MUST NOT be used to
208-
programmatically assume the presence or absence of particular
209-
features.
203+
`uname -s`(OS name e.g Linux). If the `osVersion.command` is set, the value of this
204+
capability are made from the ouput of the command specified. The os-version capability
205+
can be disabled entirely by setting the `transfer.advertiseOSVersion` config option
206+
to `false`. The `os-version` strings are purely informative for statistics and
207+
debugging purposes, and MUST NOT be used to programmatically assume the presence or
208+
absence of particular features.
210209

211210
ls-refs
212211
~~~~~~~

t/t5555-http-smart-common.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,34 @@ test_expect_success 'git upload-pack --advertise-refs: v2' '
150150
test_cmp actual expect
151151
'
152152

153+
test_expect_success 'git upload-pack --advertise-refs: v2 with osVersion.command config set' '
154+
test_config osVersion.command "uname -srvm" &&
155+
printf "agent=FAKE" >agent_and_long_osversion &&
156+
157+
if test_have_prereq !WINDOWS
158+
then
159+
printf "\nos-version=%s\n" $(uname -srvm | test_redact_non_printables) >>agent_and_long_osversion
160+
fi &&
161+
162+
cat >expect <<-EOF &&
163+
version 2
164+
$(cat agent_and_long_osversion)
165+
ls-refs=unborn
166+
fetch=shallow wait-for-done
167+
server-option
168+
object-format=$(test_oid algo)
169+
0000
170+
EOF
171+
172+
GIT_PROTOCOL=version=2 \
173+
GIT_USER_AGENT=FAKE \
174+
git upload-pack --advertise-refs . >out 2>err &&
175+
176+
test-tool pkt-line unpack <out >actual &&
177+
test_must_be_empty err &&
178+
test_cmp actual expect
179+
'
180+
153181
test_expect_success 'git receive-pack --advertise-refs: v2' '
154182
# There is no v2 yet for receive-pack, implicit v0
155183
cat >expect <<-EOF &&

t/t5701-git-serve.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,35 @@ test_expect_success 'test capability advertisement' '
5353
test_cmp expect actual
5454
'
5555

56+
test_expect_success 'test capability advertisement with osVersion.command config set' '
57+
test_config osVersion.command "uname -srvm" &&
58+
printf "agent=git/$(git version | cut -d" " -f3)" >agent_and_long_osversion &&
59+
60+
if test_have_prereq !WINDOWS
61+
then
62+
printf "\nos-version=%s\n" $(uname -srvm | test_redact_non_printables) >>agent_and_long_osversion
63+
fi &&
64+
65+
test_oid_cache <<-EOF &&
66+
wrong_algo sha1:sha256
67+
wrong_algo sha256:sha1
68+
EOF
69+
cat >expect_long.base <<-EOF &&
70+
version 2
71+
$(cat agent_and_long_osversion)
72+
ls-refs=unborn
73+
fetch=shallow wait-for-done
74+
server-option
75+
object-format=$(test_oid algo)
76+
EOF
77+
cat expect_long.base expect.trailer >expect &&
78+
79+
GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \
80+
--advertise-capabilities >out &&
81+
test-tool pkt-line unpack <out >actual &&
82+
test_cmp expect actual
83+
'
84+
5685
test_expect_success 'stateless-rpc flag does not list capabilities' '
5786
# Empty request
5887
test-tool pkt-line pack >in <<-EOF &&

version.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
#define USE_THE_REPOSITORY_VARIABLE
2+
13
#include "git-compat-util.h"
24
#include "version.h"
35
#include "version-def.h"
46
#include "strbuf.h"
57
#include "gettext.h"
68
#include "config.h"
9+
#include "run-command.h"
10+
#include "alias.h"
711

812
const char git_version_string[] = GIT_VERSION;
913
const char git_built_from_commit_string[] = GIT_BUILT_FROM_COMMIT;
@@ -71,14 +75,59 @@ int get_uname_info(struct strbuf *buf, unsigned int full)
7175
return 0;
7276
}
7377

78+
/*
79+
* Return -1 if unable to retrieve the osversion.command config or
80+
* if the command is malformed; otherwise, return 0 if successful.
81+
*/
82+
static int fill_os_version_command(struct child_process *cmd)
83+
{
84+
const char *os_version_command;
85+
const char **argv;
86+
char *os_version_copy;
87+
int n;
88+
89+
if (git_config_get_string_tmp("osversion.command", &os_version_command))
90+
return -1;
91+
92+
os_version_copy = xstrdup(os_version_command);
93+
n = split_cmdline(os_version_copy, &argv);
94+
95+
if (n < 0) {
96+
warning(_("malformed osVersion.command config option: %s"),
97+
_(split_cmdline_strerror(n)));
98+
free(os_version_copy);
99+
return -1;
100+
}
101+
102+
for (int i = 0; i < n; i++)
103+
strvec_push(&cmd->args, argv[i]);
104+
free(os_version_copy);
105+
free(argv);
106+
107+
return 0;
108+
}
109+
110+
static int capture_os_version(struct strbuf *buf)
111+
{
112+
struct child_process cmd = CHILD_PROCESS_INIT;
113+
114+
if (fill_os_version_command(&cmd))
115+
return -1;
116+
if (capture_command(&cmd, buf, 0))
117+
return -1;
118+
119+
return 0;
120+
}
121+
74122
const char *os_version(void)
75123
{
76124
static const char *os = NULL;
77125

78126
if (!os) {
79127
struct strbuf buf = STRBUF_INIT;
80128

81-
get_uname_info(&buf, 0);
129+
if (capture_os_version(&buf))
130+
get_uname_info(&buf, 0);
82131
os = strbuf_detach(&buf, NULL);
83132
}
84133

0 commit comments

Comments
 (0)