As some issues that can happen with a Git client can be operating system specific, it can be useful for a server to know which OS a client is using. In the same way it can be useful for a client to know which OS a server is using. Let's add OS information exchange to the protocol in the same way some git version exchange is performed. Signed-off-by: Christian Couder <chriscool@xxxxxxxxxxxxx> --- Documentation/gitprotocol-v2.txt | 18 ++++++++++++++++++ connect.c | 3 +++ serve.c | 12 ++++++++++++ t/t5555-http-smart-common.sh | 3 +++ t/t5701-git-serve.sh | 3 +++ version.c | 29 +++++++++++++++++++++++++++++ version.h | 3 +++ 7 files changed, 71 insertions(+) diff --git a/Documentation/gitprotocol-v2.txt b/Documentation/gitprotocol-v2.txt index 414bc625d5..f676b2dc7a 100644 --- a/Documentation/gitprotocol-v2.txt +++ b/Documentation/gitprotocol-v2.txt @@ -190,6 +190,24 @@ printable ASCII characters except space (i.e., the byte range 32 < x < and debugging purposes, and MUST NOT be used to programmatically assume 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 with a value `X` (in the form +`os-version=X`) to notify the client that the server is running an +operating system that can be identified by `X`. The client may +optionally send its own `os-version` string by including the +`os-version` capability with a value `Y` (in the form `os-version=Y`) +in its request to the server (but it MUST NOT do so if the server did +not advertise the os-version capability). The `X` and `Y` strings may +contain any printable ASCII characters except space (i.e., the byte +range 32 < x < 127), and are typically made from the result of +`uname -srvm`. 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/connect.c b/connect.c index 0d77737a53..3a48806ddc 100644 --- a/connect.c +++ b/connect.c @@ -489,6 +489,9 @@ static void send_capabilities(int fd_out, struct packet_reader *reader) if (server_supports_v2("agent")) packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized()); + if (server_supports_v2("os-version")) + packet_write_fmt(fd_out, "os-version=%s", os_version_sanitized()); + if (server_feature_v2("object-format", &hash_name)) { int hash_algo = hash_algo_by_name(hash_name); if (hash_algo == GIT_HASH_UNKNOWN) diff --git a/serve.c b/serve.c index aa651b73e9..77eb5ebdaa 100644 --- a/serve.c +++ b/serve.c @@ -29,6 +29,14 @@ static int agent_advertise(struct repository *r UNUSED, return 1; } +static int os_version_advertise(struct repository *r UNUSED, + struct strbuf *value) +{ + if (value) + strbuf_addstr(value, os_version_sanitized()); + return 1; +} + static int object_format_advertise(struct repository *r, struct strbuf *value) { @@ -121,6 +129,10 @@ static struct protocol_capability capabilities[] = { .name = "agent", .advertise = agent_advertise, }, + { + .name = "os-version", + .advertise = os_version_advertise, + }, { .name = "ls-refs", .advertise = ls_refs_advertise, diff --git a/t/t5555-http-smart-common.sh b/t/t5555-http-smart-common.sh index 3dcb3340a3..c67739236f 100755 --- a/t/t5555-http-smart-common.sh +++ b/t/t5555-http-smart-common.sh @@ -124,9 +124,12 @@ test_expect_success 'git receive-pack --advertise-refs: v1' ' ' test_expect_success 'git upload-pack --advertise-refs: v2' ' + # Octal intervals \001-\040 and \177-\377 + # corresponds to decimal intervals 1-32 and 127-255 cat >expect <<-EOF && version 2 agent=FAKE + os-version=$(uname -srvm | tr -d "\n" | tr "[\001-\040][\177-\377]" ".") ls-refs=unborn fetch=shallow wait-for-done server-option diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh index c48830de8f..9c9a707e6a 100755 --- a/t/t5701-git-serve.sh +++ b/t/t5701-git-serve.sh @@ -13,9 +13,12 @@ test_expect_success 'test capability advertisement' ' wrong_algo sha1:sha256 wrong_algo sha256:sha1 EOF + # Octal intervals \001-\040 and \177-\377 + # corresponds to decimal intervals 1-32 and 127-255 cat >expect.base <<-EOF && version 2 agent=git/$(git version | cut -d" " -f3) + os-version=$(uname -srvm | tr -d "\n" | tr "[\001-\040][\177-\377]" ".") ls-refs=unborn fetch=shallow wait-for-done server-option diff --git a/version.c b/version.c index 10b9fa77d1..5b20ea0d7c 100644 --- a/version.c +++ b/version.c @@ -61,3 +61,32 @@ int get_uname_info(struct strbuf *buf) uname_info.machine); return 0; } + +const char *os_version(void) +{ + static const char *os = NULL; + + if (!os) { + struct strbuf buf = STRBUF_INIT; + + get_uname_info(&buf); + os = strbuf_detach(&buf, NULL); + } + + return os; +} + +const char *os_version_sanitized(void) +{ + static const char *os_sanitized = NULL; + + if (!os_sanitized) { + struct strbuf buf = STRBUF_INIT; + + strbuf_addstr(&buf, os_version()); + strbuf_sanitize(&buf); + os_sanitized = strbuf_detach(&buf, NULL); + } + + return os_sanitized; +} diff --git a/version.h b/version.h index afe3dbbab7..349952c8f2 100644 --- a/version.h +++ b/version.h @@ -14,4 +14,7 @@ const char *git_user_agent_sanitized(void); */ int get_uname_info(struct strbuf *buf); +const char *os_version(void); +const char *os_version_sanitized(void); + #endif /* VERSION_H */ -- 2.45.2.563.g6aa460b3cb