Skip to content

Commit cbb94dc

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. If this is not set, the `os-version` capability exchange just the operating system name. Mentored-by: Christian Couder <[email protected]> Signed-off-by: Usman Akinyemi <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent c3231ae commit cbb94dc

File tree

5 files changed

+129
-8
lines changed

5 files changed

+129
-8
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: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,13 @@ in its request to the server (but it MUST NOT do so if the server did
203203
not advertise the os-version capability). The `X` and `Y` strings may
204204
contain any printable ASCII characters except space (i.e., the byte
205205
range 32 < x < 127), and are typically made from the result of
206-
`uname -s`(OS name e.g Linux). The os-version capability can be disabled
207-
entirely by setting the `transfer.advertiseOSVersion` config option
208-
to `false`. The `os-version` strings are purely informative for
209-
statistics and debugging purposes, and MUST NOT be used to
210-
programmatically assume the presence or absence of particular
211-
features.
206+
`uname -s`(OS name e.g Linux). If the `osVersion.command` is set,
207+
the `X` and `Y` are made from the ouput of the command specified.
208+
The os-version capability can be disabled entirely by setting the
209+
`transfer.advertiseOSVersion` config option to `false`. The `os-version`
210+
strings are purely informative for statistics and debugging purposes, and
211+
MUST NOT be used to programmatically assume the presence or absence of
212+
particular features.
212213

213214
ls-refs
214215
~~~~~~~

t/t5555-http-smart-common.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,35 @@ test_expect_success 'git upload-pack --advertise-refs: v2' '
152152
test_cmp actual expect
153153
'
154154

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

t/t5701-git-serve.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,39 @@ test_expect_success 'test capability advertisement' '
4141
test_cmp expect actual
4242
'
4343

44+
test_expect_success 'test capability advertisement with osVersion.command config set' '
45+
# test_config is used here as we are not reusing any file output from here
46+
test_config osVersion.command "uname -srvm" &&
47+
printf "agent=git/$(git version | cut -d" " -f3)" >agent_and_long_os_name &&
48+
49+
if test_have_prereq !WINDOWS
50+
then
51+
printf "\nos-version=%s\n" $(uname -srvm | test_redact_non_printables) >>agent_and_long_os_name
52+
fi &&
53+
54+
test_oid_cache <<-EOF &&
55+
wrong_algo sha1:sha256
56+
wrong_algo sha256:sha1
57+
EOF
58+
cat >expect.base_long <<-EOF &&
59+
version 2
60+
$(cat agent_and_long_os_name)
61+
ls-refs=unborn
62+
fetch=shallow wait-for-done
63+
server-option
64+
object-format=$(test_oid algo)
65+
EOF
66+
cat >expect.trailer_long <<-EOF &&
67+
0000
68+
EOF
69+
cat expect.base_long expect.trailer_long >expect &&
70+
71+
GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \
72+
--advertise-capabilities >out &&
73+
test-tool pkt-line unpack <out >actual &&
74+
test_cmp expect actual
75+
'
76+
4477
test_expect_success 'stateless-rpc flag does not list capabilities' '
4578
# Empty request
4679
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;
@@ -72,14 +76,59 @@ int get_uname_info(struct strbuf *buf, unsigned int full)
7276
return 0;
7377
}
7478

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

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

82-
get_uname_info(&buf, 0);
130+
if (capture_os_version(&buf))
131+
get_uname_info(&buf, 0);
83132
os = strbuf_detach(&buf, NULL);
84133
}
85134

0 commit comments

Comments
 (0)