Message ID | 20250117104639.65608-7-usmanakinyemi202@gmail.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Introduce os-version Capability with Configurable Options | expand |
On Fri, Jan 17, 2025 at 5:47 AM Usman Akinyemi <usmanakinyemi202@gmail.com> wrote: > 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. > > Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com> > --- > diff --git 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_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 && As an aid to future readers, please add an explanation either in the commit message or as a comment here in the code explaining why Windows is being singled out as special. > diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh > @@ -53,6 +53,35 @@ test_expect_success 'test capability advertisement' ' > +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 && Ditto.
Usman Akinyemi <usmanakinyemi202@gmail.com> writes: > 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). After reading the above rationale, I doubt the usefulness of this feature even more. Shouldn't that kind of anomalies be handled by compat/ layer to make their uname(2) emulated, or allow get_uname_info() to be customized at compile time by platform implementations, to yield more useful pieces of information instead? That way, we do not need to add another mechanism that lets people spawn an arbitrary command while Git is running, we do not need to worry about security implications, and we do not need to worry about people abusing the facility to throw totally random and useless garbage information at the other end to make their stats useless. I'll skip the overly wide documentation changes. > diff --git a/Documentation/config/transfer.txt b/Documentation/config/transfer.txt > ... > diff --git a/Documentation/gitprotocol-v2.txt b/Documentation/gitprotocol-v2.txt > ... > +test_expect_success 'test capability advertisement with osVersion.command config set' ' > + test_config osVersion.command "uname -srvm" && If osversion.command configuration variable turns out to be acceptable addition, I do not think we want to use "uname -srvm" as its value for its test. Do you know for sure how portable srvm is? If you use something like "printf ' \001a\011b\015\012c '", you do not even have to worry about how portable srvm is and on top, you can test your unprintable-redacting logic in the code. But all of that may be moot, if we take the "fewer customization at runtime" approach. Thanks.
On January 17, 2025 5:34 PM, Junio C Hamano wrote: >Usman Akinyemi <usmanakinyemi202@gmail.com> writes: > >> 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). > >After reading the above rationale, I doubt the usefulness of this feature even more. > >Shouldn't that kind of anomalies be handled by compat/ layer to make their >uname(2) emulated, or allow get_uname_info() to be customized at compile time >by platform implementations, to yield more useful pieces of information instead? > >That way, we do not need to add another mechanism that lets people spawn an >arbitrary command while Git is running, we do not need to worry about security >implications, and we do not need to worry about people abusing the facility to >throw totally random and useless garbage information at the other end to make >their stats useless. > >I'll skip the overly wide documentation changes. > >> diff --git a/Documentation/config/transfer.txt >> b/Documentation/config/transfer.txt >> ... >> diff --git a/Documentation/gitprotocol-v2.txt >> b/Documentation/gitprotocol-v2.txt >> ... > >> +test_expect_success 'test capability advertisement with osVersion.command >config set' ' >> + test_config osVersion.command "uname -srvm" && > >If osversion.command configuration variable turns out to be acceptable addition, I >do not think we want to use "uname -srvm" as its value for its test. Do you know >for sure how portable srvm is? > >If you use something like "printf ' \001a\011b\015\012c '", you do not even have >to worry about how portable srvm is and on top, you can test your unprintable- >redacting logic in the code. > >But all of that may be moot, if we take the "fewer customization at runtime" >approach. On my box, uname -srvm = "NONSTOP_KERNEL L24 08 NSV-D". Is this going to Break anything?
<rsbecker@nexbridge.com> writes: > On my box, uname -srvm = "NONSTOP_KERNEL L24 08 NSV-D". Is this going to > Break anything? If you are happy with that string, then there is no need for osversion.command configuration variable, is there?
On January 17, 2025 6:06 PM, Junio C Hamano wrote: ><rsbecker@nexbridge.com> writes: > >> On my box, uname -srvm = "NONSTOP_KERNEL L24 08 NSV-D". Is this going >> to Break anything? > >If you are happy with that string, then there is no need for osversion.command >configuration variable, is there? I am fine with that string. If that's what will work by default, it should be fine. Sorry about my confusion.
On Sat, Jan 18, 2025 at 3:14 AM Eric Sunshine <sunshine@sunshineco.com> wrote: > > On Fri, Jan 17, 2025 at 5:47 AM Usman Akinyemi > <usmanakinyemi202@gmail.com> wrote: > > 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. > > > > Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com> > > --- > > diff --git 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_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 && > > As an aid to future readers, please add an explanation either in the > commit message or as a comment here in the code explaining why Windows > is being singled out as special. > Hi Eric, The previous commit which introduced this has this information, can we do some form of referencing ? > > diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh > > @@ -53,6 +53,35 @@ test_expect_success 'test capability advertisement' ' > > +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 && > > Ditto.
On Mon, Jan 20, 2025 at 1:17 PM Usman Akinyemi <usmanakinyemi202@gmail.com> wrote: > On Sat, Jan 18, 2025 at 3:14 AM Eric Sunshine <sunshine@sunshineco.com> wrote: > > On Fri, Jan 17, 2025 at 5:47 AM Usman Akinyemi > > <usmanakinyemi202@gmail.com> wrote: > > > + if test_have_prereq !WINDOWS > > > + then > > > + printf "\nos-version=%s\n" $(uname -srvm | test_redact_non_printables) >>agent_and_long_osversion > > > + fi && > > > > As an aid to future readers, please add an explanation either in the > > commit message or as a comment here in the code explaining why Windows > > is being singled out as special. > > The previous commit which introduced this has this information, > can we do some form of referencing ? My main concern is that someone looking at this change in the future -- who did not have the benefit of reading the cover letter or the review discussion -- may have a hard time understanding why Windows is singled out by this patch. As long as you give some sort of explanation, whether in the code or in the commit message, then you save that future user from having to figure it out on his or her own. So, your suggestion of referencing some other commit may work. Augmenting the commit message of this patch with something along the lines of: As with the previous commit, we skip the tests on Windows. may be enough to tell the reader where to look for the explanation.
On Sat, Jan 18, 2025 at 4:03 AM Junio C Hamano <gitster@pobox.com> wrote: > > Usman Akinyemi <usmanakinyemi202@gmail.com> writes: > > > 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). > > After reading the above rationale, I doubt the usefulness of this > feature even more. > > Shouldn't that kind of anomalies be handled by compat/ layer to make > their uname(2) emulated, or allow get_uname_info() to be customized > at compile time by platform implementations, to yield more useful > pieces of information instead? > > That way, we do not need to add another mechanism that lets people > spawn an arbitrary command while Git is running, we do not need to > worry about security implications, and we do not need to worry about > people abusing the facility to throw totally random and useless > garbage information at the other end to make their stats useless. Hi Junio, Thanks for the review. This config option was added at Randall's request. Randall wrote: "Instead of an override, what about a knob that specifies the uname command to use to build the value. Personally, I would use `uname -s -r -v` on NonStop to get the kernel version used in the build. The difficulty on my platform is that this is not truly useful info. The effective build OS compatibility version is in a #define __L_Series_RVU and __H_Series_RVU, so the knob might be needed in git_compat_util.h or similar. This comes from the compiler arguments, which are not yet captured." So, the difficulty is that the compile time information might not be useful. This patch is the last patch of the series and can be a stand alone also. Thank you. > > I'll skip the overly wide documentation changes. > > > diff --git a/Documentation/config/transfer.txt b/Documentation/config/transfer.txt > > ... > > diff --git a/Documentation/gitprotocol-v2.txt b/Documentation/gitprotocol-v2.txt > > ... > > > +test_expect_success 'test capability advertisement with osVersion.command config set' ' > > + test_config osVersion.command "uname -srvm" && > > If osversion.command configuration variable turns out to be > acceptable addition, I do not think we want to use "uname -srvm" as > its value for its test. Do you know for sure how portable srvm is? > > If you use something like "printf ' \001a\011b\015\012c '", you do > not even have to worry about how portable srvm is and on top, you > can test your unprintable-redacting logic in the code. > > But all of that may be moot, if we take the "fewer customization at > runtime" approach. > > Thanks.
On Tue, Jan 21, 2025 at 12:11 AM Eric Sunshine <sunshine@sunshineco.com> wrote: > > On Mon, Jan 20, 2025 at 1:17 PM Usman Akinyemi > <usmanakinyemi202@gmail.com> wrote: > > On Sat, Jan 18, 2025 at 3:14 AM Eric Sunshine <sunshine@sunshineco.com> wrote: > > > On Fri, Jan 17, 2025 at 5:47 AM Usman Akinyemi > > > <usmanakinyemi202@gmail.com> wrote: > > > > + if test_have_prereq !WINDOWS > > > > + then > > > > + printf "\nos-version=%s\n" $(uname -srvm | test_redact_non_printables) >>agent_and_long_osversion > > > > + fi && > > > > > > As an aid to future readers, please add an explanation either in the > > > commit message or as a comment here in the code explaining why Windows > > > is being singled out as special. > > > > The previous commit which introduced this has this information, > > can we do some form of referencing ? > > My main concern is that someone looking at this change in the future > -- who did not have the benefit of reading the cover letter or the > review discussion -- may have a hard time understanding why Windows is > singled out by this patch. As long as you give some sort of > explanation, whether in the code or in the commit message, then you > save that future user from having to figure it out on his or her own. > > So, your suggestion of referencing some other commit may work. > Augmenting the commit message of this patch with something along the > lines of: > > As with the previous commit, we skip the tests on Windows. > > may be enough to tell the reader where to look for the explanation. Yeah, thanks, this looks better and clearer. I will add this in the next iteration if we agree to include the osversion.command config. Thank you. Usman Akinyemi.
Usman Akinyemi <usmanakinyemi202@gmail.com> writes: >> That way, we do not need to add another mechanism that lets people >> spawn an arbitrary command while Git is running, we do not need to >> worry about security implications, and we do not need to worry about >> people abusing the facility to throw totally random and useless >> garbage information at the other end to make their stats useless. > > Thanks for the review. > This config option was added at Randall's request. > > Randall wrote: > > "Instead of an override, what about a knob that specifies the uname > command to use to build the value. Personally, I would use `uname -s > -r -v` on NonStop to get the kernel version used in the build. The > difficulty on my platform is that this is not truly useful info. The > effective build OS compatibility version is in a #define > __L_Series_RVU and __H_Series_RVU, so the knob might be needed in > git_compat_util.h or similar. This comes from the compiler arguments, > which are not yet captured." > > So, the difficulty is that the compile time information might not be useful. It only tells us that uname(2) gives useless information on the platform, but there are other ways to ask the system for more useful information. Isn't that the same deal with how useful information is obtained from not uname(2), since a useful one does not exist there, but from GetVersion() on mingw? We do not have to spawn an external process on MinGW to do this---we shouldn't have to do so on NonStop, either. We should be able to make a call into a NonStop specific code you or Randal add in compat/ from get_uname_info() to hide the platform-specific details, no?
On January 21, 2025 2:14 PM, Junio C Hamano wrote: >Usman Akinyemi <usmanakinyemi202@gmail.com> writes: > >>> That way, we do not need to add another mechanism that lets people >>> spawn an arbitrary command while Git is running, we do not need to >>> worry about security implications, and we do not need to worry about >>> people abusing the facility to throw totally random and useless >>> garbage information at the other end to make their stats useless. >> >> Thanks for the review. >> This config option was added at Randall's request. >> >> Randall wrote: >> >> "Instead of an override, what about a knob that specifies the uname >> command to use to build the value. Personally, I would use `uname -s >> -r -v` on NonStop to get the kernel version used in the build. The >> difficulty on my platform is that this is not truly useful info. The >> effective build OS compatibility version is in a #define >> __L_Series_RVU and __H_Series_RVU, so the knob might be needed in >> git_compat_util.h or similar. This comes from the compiler arguments, >> which are not yet captured." >> >> So, the difficulty is that the compile time information might not be useful. > >It only tells us that uname(2) gives useless information on the platform, but there >are other ways to ask the system for more useful information. Isn't that the same >deal with how useful information is obtained from not uname(2), since a useful one >does not exist there, but from GetVersion() on mingw? We do not have to spawn >an external process on MinGW to do this---we shouldn't have to do so on NonStop, >either. We should be able to make a call into a NonStop specific code you or Randal >add in compat/ from get_uname_info() to hide the platform-specific details, no? I agree. One this series is finalized, I can put together a patch to obtain OS details on NonStop from proprietary calls. Not something I am happy about doing, but it is what it is. I still do not get why people cannot just run 'uname -a' instead of this integration. From a support standpoint, knowing what OS level was used in the build is more useful that git telling me what I can get from uname. But I accept that others want this, so I'm going with it - once the code is accepted into base git.
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); }
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(-)