Skip to contentSkip to conversation

config: introduce an Operating System-specific `includeIf` condition

PATCH Superseded Johannes Schindelin via GitGitGadget 13 participants 26 messages Nov 21, 2022 – Apr 19, 2023 Documentation

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 config: introduce an Operating System-specific `includeIf` condition

From: Johannes Schindelin <[email protected]>

It is relatively common for users to maintain identical ~/.gitconfig files across all of their setups, using the includeIf construct liberally to adjust the settings to the respective setup as needed.

In case of Operating System-specific adjustments, Git currently offers no support to the users and they typically use a work-around like this:

[includeIf "gitdir:/home/"]
path = ~/.gitconfig-linux
[includeIf "gitdir:/Users/"]
path = ~/.gitconfig-mac
[includeIf "gitdir:C:"]
path = ~/.gitconfig-windows

However, this is fragile, as it would not even allow to discern between Operating Systems that happen to host their home directories in /home/, such as Linux and the BSDs.

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

This addresses https://github.com/git-for-windows/git/issues/4125

---
config: introduce an Operating System-specific includeIf condition

I was about to write up guidelines how to write this patch, but it turned out that it was much faster to write the patch instead.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1429%2Fdscho%2Finclude-if-os-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1429/dscho/include-if-os-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1429

 Documentation/config.txt |  5 +++++
 config.c                 | 11 +++++++++++
 t/t1309-early-config.sh  | 16 ++++++++++++++++
 3 files changed, 32 insertions(+)
Documentation/config.txt +5 -0
index e376d547ce0..2db73d8228e 100644
@@ -186,6 +186,11 @@ As for the naming of this keyword, it is for forwards compatibiliy with
 a naming scheme that supports more variable-based include conditions,
 but currently Git only supports the exact keyword described above.
 
+`os`::
+	The data that follows this keyword is taken as the name of an
+	Operating System; If it matches the output of `uname -s`, the
+	include condition is met.
+
 A few more notes on matching via `gitdir` and `gitdir/i`:
 
  * Symlinks in `$GIT_DIR` are not resolved before matching.
config.c +11 -0
index 9b0e9c93285..9ab311ae99b 100644
@@ -394,6 +394,15 @@ static int include_by_remote_url(struct config_include_data *inc,
 					     inc->remote_urls);
 }
 
+static int include_by_os(const char *cond, size_t cond_len)
+{
+	struct utsname uname_info;
+
+	return !uname(&uname_info) &&
+		!strncasecmp(uname_info.sysname, cond, cond_len) &&
+		!uname_info.sysname[cond_len];
+}
+
 static int include_condition_is_true(struct config_include_data *inc,
 				     const char *cond, size_t cond_len)
 {
@@ -408,6 +417,8 @@ static int include_condition_is_true(struct config_include_data *inc,
 	else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,
 				   &cond_len))
 		return include_by_remote_url(inc, cond, cond_len);
+	else if (skip_prefix_mem(cond, cond_len, "os:", &cond, &cond_len))
+		return include_by_os(cond, cond_len);
 
 	/* unknown conditionals are always false */
 	return 0;
t/t1309-early-config.sh +16 -0
index 537435b90ae..7da67af06e7 100755
@@ -100,4 +100,20 @@ test_expect_success 'onbranch config outside of git repo' '
 	nongit git help
 '
 
+test_expect_success '[includeIf "os:..."]' '
+	test_config x.y 0 &&
+	echo "[x] y = z" >.git/xyz &&
+
+	if test_have_prereq MINGW
+	then
+		uname_s=Windows
+	else
+		uname_s="$(uname -s)"
+	fi &&
+	test_config "includeIf.os:not-$uname_s.path" xyz &&
+	test 0 = "$(git  config x.y)" &&
+	test_config "includeIf.os:$uname_s.path" xyz &&
+	test z = "$(git config x.y)"
+'
+
 test_done

base-commit: e4a4b31577c7419497ac30cebe30d755b97752c5

Signature · 1 line
gitgitgadget
#1 lore raw
Quoted 16 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

It is relatively common for users to maintain identical ~/.gitconfig files across all of their setups, using the includeIf construct liberally to adjust the settings to the respective setup as needed.

In case of Operating System-specific adjustments, Git currently offers no support to the users and they typically use a work-around like this:

[includeIf "gitdir:/home/"]
path = ~/.gitconfig-linux
[includeIf "gitdir:/Users/"]
path = ~/.gitconfig-mac
[includeIf "gitdir:C:"]
path = ~/.gitconfig-windows

Quoted 3 lines

However, this is fragile, as it would not even allow to discern between Operating Systems that happen to host their home directories in /home/, such as Linux and the BSDs.

This looks like a really sensible thing to do, thanks.

Documentation/config.txt As for the naming of this keyword, it is for forwards compatibiliy with · line 192

Quoted 4 lines

+os::

Documentation/config.txt +3 -0
+	The data that follows this keyword is taken as the name of an
+	Operating System; If it matches the output of `uname -s`, the
+	include condition is met.

Here yu say it "matches uname -s", but later in the test we can see that's not the case. This is because compat/mingw.c is the source of that "Windows" string, which we use for the uname() at the C level.

I don't think we've needed to document it before, but we should do so here I'd think. Per
https://stackoverflow.com/questions/3466166/how-to-check-if-running-in-cygwin-mac-or-linux
users would follow these docs, try MinGw, then be confused, no?

config.c static int include_by_remote_url(struct config_include_data *inc, · line 402

Quoted 6 lines
config.c +6 -0
+static int include_by_os(const char *cond, size_t cond_len)
+{
+	struct utsname uname_info;
+
+	return !uname(&uname_info) &&
+		!strncasecmp(uname_info.sysname, cond, cond_len) &&

Our config.mak.uname doesn't to case-insensitive uname matching, and AFAIK these don't change between platforms versions. So why do we need to support LINUX, LiNuX etc. in addition to the canonical Linux?

I'm not opposed to it if there's a good reason, but as we have "gitdir" and "gitdir/i" shouldn't we make that "os/i" for consistency, if it's needed?

t/t1309-early-config.sh test_expect_success 'onbranch config outside of git repo' ' · line 113

Quoted 11 lines
t/t1309-early-config.sh +11 -0
+test_expect_success '[includeIf "os:..."]' '
+	test_config x.y 0 &&
+	echo "[x] y = z" >.git/xyz &&
+
+	if test_have_prereq MINGW
+	then
+		uname_s=Windows
+	else
+		uname_s="$(uname -s)"
+	fi &&
+	test_config "includeIf.os:not-$uname_s.path" xyz &&

Re above: If it is important to support LINUX etc. these tests should check it, they pass if it's converted to strncmp().

t/t1309-early-config.sh test_expect_success 'onbranch config outside of git repo' ' · line 114

Quoted 1 line
t/t1309-early-config.sh +1 -0
+	test 0 = "$(git  config x.y)" &&

Hides segfaults, use test_cmp or test_cmp_config?

t/t1309-early-config.sh test_expect_success 'onbranch config outside of git repo' ' · line 116

Quoted 2 lines
t/t1309-early-config.sh +2 -0
+	test_config "includeIf.os:$uname_s.path" xyz &&
+	test z = "$(git config x.y)"

Ditto segfault-hiding.

#2 lore raw

Hi Dscho and Ævar

Quoted 19 lines · Ævar Arnfjörð Bjarmason
Quoted 16 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

It is relatively common for users to maintain identical ~/.gitconfig files across all of their setups, using the includeIf construct liberally to adjust the settings to the respective setup as needed.

In case of Operating System-specific adjustments, Git currently offers no support to the users and they typically use a work-around like this:

[includeIf "gitdir:/home/"]
path = ~/.gitconfig-linux
[includeIf "gitdir:/Users/"]
path = ~/.gitconfig-mac
[includeIf "gitdir:C:"]
path = ~/.gitconfig-windows

Quoted 5 lines
Quoted 3 lines

However, this is fragile, as it would not even allow to discern between Operating Systems that happen to host their home directories in /home/, such as Linux and the BSDs.

This looks like a really sensible thing to do, thanks.

Yes, it looks like a really useful enhancement

Quoted 3 lines

Documentation/config.txt As for the naming of this keyword, it is for forwards compatibiliy with · line 191

Quoted 3 lines

+os::

Documentation/config.txt +2 -0
+	The data that follows this keyword is taken as the name of an
+	Operating System; If it matches the output of `uname -s`, the

Maybe add e.g. "Windows or Linux" after Operating System?

Quoted 11 lines

config.c static int include_by_remote_url(struct config_include_data *inc, · line 402

Quoted 6 lines
config.c +6 -0
+static int include_by_os(const char *cond, size_t cond_len)
+{
+	struct utsname uname_info;
+
+	return !uname(&uname_info) &&
+		!strncasecmp(uname_info.sysname, cond, cond_len) &&

Our config.mak.uname doesn't to case-insensitive uname matching, and AFAIK these don't change between platforms versions. So why do we need to support LINUX, LiNuX etc. in addition to the canonical Linux?

Quoted 3 lines

I'm not opposed to it if there's a good reason, but as we have "gitdir" and "gitdir/i" shouldn't we make that "os/i" for consistency, if it's needed?

Why should we penalize users who write "linux" rather than "Linux"? Making the comparison case insensitive seems eminently sensible. File systems can be case sensitive so having the option to specify whether a match for "gitdir" is case sensitive or not makes sense there but not for the name of an operating system.

Best Wishes

Phillip

#3 lore raw

Hi Phillip & Ævar,

[Ævar, in your mail, which I suggest could have used some editing for spelling and brevity, I found only the concern about uname -s relevant, and since Phillip's suggestion is more actionable than the somewhat diffuse excurse about something to do with something in a StackOverflow thread, I will only reply here.]

Quoted 10 lines · Phillip Wood
Quoted 7 lines · Ævar Arnfjörð Bjarmason

On Mon, Nov 21 2022, Johannes Schindelin via GitGitGadget wrote:

[...]

Documentation/config.txt As for the naming of this keyword, it is for forwards compatibiliy with · line 191

Quoted 3 lines

+os::

Documentation/config.txt +2 -0
+	The data that follows this keyword is taken as the name of an
+	Operating System; If it matches the output of `uname -s`, the

Maybe add e.g. "Windows or Linux" after Operating System?

Excellent idea. I'll also drop mentioning uname -s because it assumes more about the users' setup than can be assumed.

I also replaced a space character in the added test case that was doubled by mistake with a single one.

Ciao,
Dscho

#4 lore raw

PATCH v2 1/1 config: introduce an Operating System-specific `includeIf` condition

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

It is relatively common for users to maintain identical ~/.gitconfig files across all of their setups, using the includeIf construct liberally to adjust the settings to the respective setup as needed.

In case of Operating System-specific adjustments, Git currently offers no support to the users and they typically use a work-around like this:

[includeIf "gitdir:/home/"]
path = ~/.gitconfig-linux
[includeIf "gitdir:/Users/"]
path = ~/.gitconfig-mac
[includeIf "gitdir:C:"]
path = ~/.gitconfig-windows

However, this is fragile, as it would not even allow to discern between Operating Systems that happen to host their home directories in /home/, such as Linux and the BSDs.

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

This addresses https://github.com/git-for-windows/git/issues/4125

---
config: introduce an Operating System-specific includeIf condition

I was about to write up guidelines how to write this patch, but it turned out that it was much faster to write the patch instead.

Changes since v1:

* The documentation now avoids mentioning uname -s and clarifies what it means by offering examples.
* Replaced a double space in the test case with a single one.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1429%2Fdscho%2Finclude-if-os-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1429/dscho/include-if-os-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1429

Range-diff vs v1:

1: a7eb4a9d438 ! 1: 45231533883 config: introduce an Operating System-specific includeIf condition

     @@ Documentation/config.txt: As for the naming of this keyword, it is for forwards
       
      +`os`::
      +	The data that follows this keyword is taken as the name of an
     -+	Operating System; If it matches the output of `uname -s`, the
     -+	include condition is met.
     ++	Operating System, e.g. `Linux` or `Windows`; If it matches the
     ++	current Operating System, the include condition is met.
      +
       A few more notes on matching via `gitdir` and `gitdir/i`:
       
     @@ t/t1309-early-config.sh: test_expect_success 'onbranch config outside of git rep
      +		uname_s="$(uname -s)"
      +	fi &&
      +	test_config "includeIf.os:not-$uname_s.path" xyz &&
     -+	test 0 = "$(git  config x.y)" &&
     ++	test 0 = "$(git config x.y)" &&
      +	test_config "includeIf.os:$uname_s.path" xyz &&
      +	test z = "$(git config x.y)"
      +'
 Documentation/config.txt |  5 +++++
 config.c                 | 11 +++++++++++
 t/t1309-early-config.sh  | 16 ++++++++++++++++
 3 files changed, 32 insertions(+)
Documentation/config.txt +5 -0
index e376d547ce0..b90bcd8ecfe 100644
@@ -186,6 +186,11 @@ As for the naming of this keyword, it is for forwards compatibiliy with
 a naming scheme that supports more variable-based include conditions,
 but currently Git only supports the exact keyword described above.
 
+`os`::
+	The data that follows this keyword is taken as the name of an
+	Operating System, e.g. `Linux` or `Windows`; If it matches the
+	current Operating System, the include condition is met.
+
 A few more notes on matching via `gitdir` and `gitdir/i`:
 
  * Symlinks in `$GIT_DIR` are not resolved before matching.
config.c +11 -0
index 9b0e9c93285..9ab311ae99b 100644
@@ -394,6 +394,15 @@ static int include_by_remote_url(struct config_include_data *inc,
 					     inc->remote_urls);
 }
 
+static int include_by_os(const char *cond, size_t cond_len)
+{
+	struct utsname uname_info;
+
+	return !uname(&uname_info) &&
+		!strncasecmp(uname_info.sysname, cond, cond_len) &&
+		!uname_info.sysname[cond_len];
+}
+
 static int include_condition_is_true(struct config_include_data *inc,
 				     const char *cond, size_t cond_len)
 {
@@ -408,6 +417,8 @@ static int include_condition_is_true(struct config_include_data *inc,
 	else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,
 				   &cond_len))
 		return include_by_remote_url(inc, cond, cond_len);
+	else if (skip_prefix_mem(cond, cond_len, "os:", &cond, &cond_len))
+		return include_by_os(cond, cond_len);
 
 	/* unknown conditionals are always false */
 	return 0;
t/t1309-early-config.sh +16 -0
index 537435b90ae..b36afe1a528 100755
@@ -100,4 +100,20 @@ test_expect_success 'onbranch config outside of git repo' '
 	nongit git help
 '
 
+test_expect_success '[includeIf "os:..."]' '
+	test_config x.y 0 &&
+	echo "[x] y = z" >.git/xyz &&
+
+	if test_have_prereq MINGW
+	then
+		uname_s=Windows
+	else
+		uname_s="$(uname -s)"
+	fi &&
+	test_config "includeIf.os:not-$uname_s.path" xyz &&
+	test 0 = "$(git config x.y)" &&
+	test_config "includeIf.os:$uname_s.path" xyz &&
+	test z = "$(git config x.y)"
+'
+
 test_done

base-commit: e4a4b31577c7419497ac30cebe30d755b97752c5

Signature · 1 line
gitgitgadget
#5 lore raw
Quoted 3 lines · Johannes Schindelin via GitGitGadget

It is relatively common for users to maintain identical ~/.gitconfig files across all of their setups, using the includeIf construct liberally to adjust the settings to the respective setup as needed.

This seems like a reasonable thing to have in general, but I wonder if you have an example of how people use this. Mostly I am wondering:

- is it sometimes a misuse, where users _think_ that the OS is correlated with some feature of Git. And they would be better off with some flag like "does the current platform support fsmonitor".

- for cases where it really is "uname -s" the best differentiator? Or would they commonly want to lump FreeBSD and Linux into the same category, or to tell the difference between Debian versus Fedora?

-Peff

#25 lore raw
In reply to Johannes Schindelin via GitGitGadget

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 16 lines · writes:

From: Johannes Schindelin <[email protected]>

It is relatively common for users to maintain identical ~/.gitconfig files across all of their setups, using the includeIf construct liberally to adjust the settings to the respective setup as needed.

In case of Operating System-specific adjustments, Git currently offers no support to the users and they typically use a work-around like this:

[includeIf "gitdir:/home/"]
path = ~/.gitconfig-linux
[includeIf "gitdir:/Users/"]
path = ~/.gitconfig-mac
[includeIf "gitdir:C:"]
path = ~/.gitconfig-windows

Quoted 6 lines

However, this is fragile, as it would not even allow to discern between Operating Systems that happen to host their home directories in /home/, such as Linux and the BSDs.

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

As I am not confident enough that we made the best choice that would last forever with the initial attempt when we picked "uname -s" as the way to switch on "OS", I wouldn't call it "OS". Perhaps

	[includeIf "uname-s:Linux"] path = ...

would be what I would pick. Other than that, the feature makes quite a lot of sense.

#8 lore raw
In reply to Johannes Schindelin via GitGitGadget

Documentation/config.txt As for the naming of this keyword, it is for forwards compatibiliy with · line 194

Quoted 8 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

+os::

Documentation/config.txt +4 -0
+	The data that follows this keyword is taken as the name of an
+	Operating System, e.g. `Linux` or `Windows`; If it matches the
+	current Operating System, the include condition is met.
+
 A few more notes on matching via `gitdir` and `gitdir/i`:

The reste of the "includeif" use glob matching and "/i" for icase. IOW this is how this new feature would fit in:

	|--------+--------+----------+----------+------------------+----|
	|        | gitdir | gitdir/i | onbranch | hasconfig:remote | os |
	|--------+--------+----------+----------+------------------+----|
	| icase? | N      | Y        | N        | N                | Y  |
	| glob?  | Y      | Y        | Y        | Y                | N  |
	| path?  | Y      | Y        | Y        | Y                | N  |
	|--------+--------+----------+----------+------------------+----|

I think at least flipping that "glob" to "Y" so you could match e.g. "*BSD" would be useful, and easier to explain in context, rather than why the rest use wildmatch() and this doesn't.

For matching the uname the case doesn't really matter, but for consistency of the interface I think making it case-sensitive or adding an "os/i" would make sense. I.e. let's consistently use "/i" if & when something's case-insensitive.

Quoted 5 lines
t/t1309-early-config.sh +5 -0
+test_expect_success '[includeIf "os:..."]' '
+	test_config x.y 0 &&
+	echo "[x] y = z" >.git/xyz &&
+
+	if test_have_prereq MINGW

t/t1309-early-config.sh test_expect_success 'onbranch config outside of git repo' ' · line 117

Quoted 10 lines
t/t1309-early-config.sh +10 -0
+	then
+		uname_s=Windows
+	else
+		uname_s="$(uname -s)"
+	fi &&
+	test_config "includeIf.os:not-$uname_s.path" xyz &&
+	test 0 = "$(git config x.y)" &&
+	test_config "includeIf.os:$uname_s.path" xyz &&
+	test z = "$(git config x.y)"
+'

As I pointed out in the v1, this still:

* Hides segfaults in "git config", let's check the exit code.
* Doesn't test the "icase" semantics you're introducing. Let's do that if it's intentional.

#9 lore raw
Quoted 23 lines · Ævar Arnfjörð Bjarmason

Documentation/config.txt As for the naming of this keyword, it is for forwards compatibiliy with · line 194

Quoted 8 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

+os::

Documentation/config.txt +4 -0
+	The data that follows this keyword is taken as the name of an
+	Operating System, e.g. `Linux` or `Windows`; If it matches the
+	current Operating System, the include condition is met.
+
  A few more notes on matching via `gitdir` and `gitdir/i`:

The reste of the "includeif" use glob matching and "/i" for icase. IOW this is how this new feature would fit in:

	|--------+--------+----------+----------+------------------+----|
	|        | gitdir | gitdir/i | onbranch | hasconfig:remote | os |
	|--------+--------+----------+----------+------------------+----|
	| icase? | N      | Y        | N        | N                | Y  |
	| glob?  | Y      | Y        | Y        | Y                | N  |
	| path?  | Y      | Y        | Y        | Y                | N  |
	|--------+--------+----------+----------+------------------+----|
Quoted 3 lines

I think at least flipping that "glob" to "Y" so you could match e.g. "*BSD" would be useful, and easier to explain in context, rather than why the rest use wildmatch() and this doesn't.

Globbing could be useful for the BSDs.

One other thing I thought of is will users know "Darwin" means MacOS?

Quoted 4 lines

For matching the uname the case doesn't really matter, but for consistency of the interface I think making it case-sensitive or adding an "os/i" would make sense. I.e. let's consistently use "/i" if & when something's case-insensitive.

All the other items listed in your table such as branch names are case sensitive. The os name is not so it is of no benefit at all to the user to match it case sensitively. Let's consistently test case sensitive keys cases sensitively and case insensitive keys case insensitively.

Best Wishes

Phillip

Quoted 21 lines
Quoted 5 lines
t/t1309-early-config.sh +5 -0
+test_expect_success '[includeIf "os:..."]' '
+	test_config x.y 0 &&
+	echo "[x] y = z" >.git/xyz &&
+
+	if test_have_prereq MINGW

t/t1309-early-config.sh test_expect_success 'onbranch config outside of git repo' ' · line 117

Quoted 10 lines
t/t1309-early-config.sh +10 -0
+	then
+		uname_s=Windows
+	else
+		uname_s="$(uname -s)"
+	fi &&
+	test_config "includeIf.os:not-$uname_s.path" xyz &&
+	test 0 = "$(git config x.y)" &&
+	test_config "includeIf.os:$uname_s.path" xyz &&
+	test z = "$(git config x.y)"
+'

As I pointed out in the v1, this still:

* Hides segfaults in "git config", let's check the exit code.
* Doesn't test the "icase" semantics you're introducing. Let's do that if it's intentional.

#13 lore raw
In reply to Johannes Schindelin via GitGitGadget

Hi Dscho,

Le 2022-11-21 à 14:19, Johannes Schindelin via GitGitGadget a écrit :

Quoted 7 lines

From: Johannes Schindelin <[email protected]>

It is relatively common for users to maintain identical ~/.gitconfig files across all of their setups, using the includeIf construct liberally to adjust the settings to the respective setup as needed.

In case of Operating System-specific adjustments,

Here, as well as in the commit title, the rest of the message, and the changes to the doc in the patch, I would downcase "operating system".
It's a common word that I don't think should be capitalized (in contrast to proper OS names like Windows and Linux).

Cheers,
Philippe.

#10 lore raw
In reply to Phillip Wood
Quoted 2 lines · Phillip Wood

All the other items listed in your table such as branch names are case sensitive. The os name is not so it is of no benefit at all to the

You keep saying that you consider the OS name is case insensitive, but I doubt that is the case, not in the sense that MacOS and macOS are two different operating systems, but in the sense that OS publishers have a single preferred way to spell their ware (which is shown in "uname -s" output), and we should respect that.

#14 lore raw
In reply to Johannes Schindelin via GitGitGadget

Hi Dscho,

Quoted 16 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

It is relatively common for users to maintain identical ~/.gitconfig files across all of their setups, using the includeIf construct liberally to adjust the settings to the respective setup as needed.

In case of Operating System-specific adjustments, Git currently offers no support to the users and they typically use a work-around like this:

[includeIf "gitdir:/home/"]
path = ~/.gitconfig-linux
[includeIf "gitdir:/Users/"]
path = ~/.gitconfig-mac
[includeIf "gitdir:C:"]
path = ~/.gitconfig-windows

Quoted 6 lines

However, this is fragile, as it would not even allow to discern between Operating Systems that happen to host their home directories in /home/, such as Linux and the BSDs.

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

This uname -s doesn't work well on Git-for-Windows (GfW) / Windows because GfW has its own internal compatibility code to spoof the result. Internally GfW sets it to "Windows" (see
https://github.com/git/git/blob/master/compat/mingw.c#L3084-L3095).

If I ask for uname -s on the GfW bash, for me it returns MINGW64_NT-10.0-19045, both on the normal GfW install, and the GfW-SDK.

If I (as dumb user) try the CMD window prompt it's 'uname' is not recognized as an internal or external command, operable program or batch file.

The Windows PowerShell also doesn't recognise the uname command.

My WSL reports Linux, though I haven't played with that for a while (do all *nix variants report that?).

Thus we'll need some way of assisting the users in determining the internal system name that their local Git will find. It maybe that the man page just needs to be explicit about using "Windows" for the Git-for-Windows implementation.

Or less helpful, maybe a git-uname command to disambiguate any other systems with a compat::uname() variant.

Or just drop the mentions of "<uname-s>" in this commit message and rename it 'sysname' to match the field of the struct utsname?

Quoted 55 lines

This addresses https://github.com/git-for-windows/git/issues/4125

---
config: introduce an Operating System-specific includeIf condition

I was about to write up guidelines how to write this patch, but it turned out that it was much faster to write the patch instead.

Changes since v1:

* The documentation now avoids mentioning uname -s and clarifies what it means by offering examples.
* Replaced a double space in the test case with a single one.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1429%2Fdscho%2Finclude-if-os-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1429/dscho/include-if-os-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1429

Range-diff vs v1:

1: a7eb4a9d438 ! 1: 45231533883 config: introduce an Operating System-specific includeIf condition

     @@ Documentation/config.txt: As for the naming of this keyword, it is for forwards
       
      +`os`::
      +	The data that follows this keyword is taken as the name of an
     -+	Operating System; If it matches the output of `uname -s`, the
     -+	include condition is met.
     ++	Operating System, e.g. `Linux` or `Windows`; If it matches the
     ++	current Operating System, the include condition is met.
      +
       A few more notes on matching via `gitdir` and `gitdir/i`:
       
     @@ t/t1309-early-config.sh: test_expect_success 'onbranch config outside of git rep
      +		uname_s="$(uname -s)"
      +	fi &&
      +	test_config "includeIf.os:not-$uname_s.path" xyz &&
     -+	test 0 = "$(git  config x.y)" &&
     ++	test 0 = "$(git config x.y)" &&
      +	test_config "includeIf.os:$uname_s.path" xyz &&
      +	test z = "$(git config x.y)"
      +'
 Documentation/config.txt |  5 +++++
 config.c                 | 11 +++++++++++
 t/t1309-early-config.sh  | 16 ++++++++++++++++
 3 files changed, 32 insertions(+)
Documentation/config.txt +0 -0
index e376d547ce0..b90bcd8ecfe 100644

Documentation/config.txt As for the naming of this keyword, it is for forwards compatibiliy with · line 192

Quoted 7 lines
Documentation/config.txt +4 -0
@@ -186,6 +186,11 @@ As for the naming of this keyword, it is for forwards compatibiliy with
 a naming scheme that supports more variable-based include conditions,
 but currently Git only supports the exact keyword described above.
 
+`os`::
+	The data that follows this keyword is taken as the name of an
+	Operating System, e.g. `Linux` or `Windows`; If it matches the
+	current Operating System

Is 'matches' the appropriate way to indicate that we compare just the characters from the data string and ignore any trailing chars in the uname.sysname field?

Quoted 26 lines

, the include condition is met.

Documentation/config.txt +1 -0
+
 A few more notes on matching via `gitdir` and `gitdir/i`:
 
  * Symlinks in `$GIT_DIR` are not resolved before matching.
config.c +9 -0
index 9b0e9c93285..9ab311ae99b 100644
@@ -394,6 +394,15 @@ static int include_by_remote_url(struct config_include_data *inc,
 					     inc->remote_urls);
 }
 
+static int include_by_os(const char *cond, size_t cond_len)
+{
+	struct utsname uname_info;
+
+	return !uname(&uname_info) &&
+		!strncasecmp(uname_info.sysname, cond, cond_len) &&
+		!uname_info.sysname[cond_len];
+}
+
 static int include_condition_is_true(struct config_include_data *inc,
 				     const char *cond, size_t cond_len)
 {

config.c static int include_condition_is_true(struct config_include_data *inc, · line 421

Quoted 5 lines
config.c +2 -0
@@ -408,6 +417,8 @@ static int include_condition_is_true(struct config_include_data *inc,
 	else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,
 				   &cond_len))
 		return include_by_remote_url(inc, cond, cond_len);
+	else if (skip_prefix_mem(cond, cond_len, "os:", &cond, &cond_len))
+		return include_by_os(cond, cond_len);

(as above) We compare only on the basis of the few/many characters in the config file so, IIUC, we could use Win, or Lin as the os:
string. Should this be noted in the man text? I'm thinking of users who may be confused by having to change Win10 to Windows, but are happy to shorten to Win.

Quoted 8 lines
config.c +0 -0
 	/* unknown conditionals are always false */
 	return 0;
t/t1309-early-config.sh +0 -0
index 537435b90ae..b36afe1a528 100755

t/t1309-early-config.sh test_expect_success 'onbranch config outside of git repo' ' · line 109

Quoted 10 lines
t/t1309-early-config.sh +7 -0
@@ -100,4 +100,20 @@ test_expect_success 'onbranch config outside of git repo' '
 	nongit git help
 '
 
+test_expect_success '[includeIf "os:..."]' '
+	test_config x.y 0 &&
+	echo "[x] y = z" >.git/xyz &&
+
+	if test_have_prereq MINGW
+	then
+		uname_s=Windows

This (correctly) copies/follows the compat code
(https://github.com/git/git/blob/master/compat/mingw.c#L3088), but isn't what a GfW user sees if uname-s is run in their bash. Maybe change uname_s to sysname, as noted above.

Quoted 11 lines
t/t1309-early-config.sh +9 -0
+	else
+		uname_s="$(uname -s)"
+	fi &&
+	test_config "includeIf.os:not-$uname_s.path" xyz &&
+	test 0 = "$(git config x.y)" &&
+	test_config "includeIf.os:$uname_s.path" xyz &&
+	test z = "$(git config x.y)"
+'
+
 test_done
Quoted 1 line

base-commit: e4a4b31577c7419497ac30cebe30d755b97752c5

--
Philip

#6 lore raw
In reply to Jeff King
Quoted 6 lines · Jeff King
Quoted 3 lines · Johannes Schindelin via GitGitGadget

It is relatively common for users to maintain identical ~/.gitconfig files across all of their setups, using the includeIf construct liberally to adjust the settings to the respective setup as needed.

Quoted 6 lines

This seems like a reasonable thing to have in general, but I wonder if you have an example of how people use this. Mostly I am wondering:

- is it sometimes a misuse, where users _think_ that the OS is correlated with some feature of Git. And they would be better off with some flag like "does the current platform support fsmonitor".

A possible use-case is setting credential.helper based on OS, let's say libsecret on Linux, and osxkeychain on macOS. Of course, users can have their own helper on specific OS.

Quoted 6 lines

- for cases where it really is "uname -s" the best differentiator? Or would they commonly want to lump FreeBSD and Linux into the same category, or to tell the difference between Debian versus Fedora?

-Peff

Signature · 1 line
Danh
#11 lore raw
In reply to Junio C Hamano

Hi Junio

Welcome back, I hope you enjoyed your time away from the list.

Quoted 10 lines · Junio C Hamano
Quoted 2 lines · Phillip Wood

All the other items listed in your table such as branch names are case sensitive. The os name is not so it is of no benefit at all to the

You keep saying that you consider the OS name is case insensitive, but I doubt that is the case, not in the sense that MacOS and macOS are two different operating systems, but in the sense that OS publishers have a single preferred way to spell their ware (which is shown in "uname -s" output), and we should respect that.

I can see that we would want to respect the preferred spelling in our documentation but it seems a bit mean to penalize users who write

[IncludeIf "os:windows"]

rather than

[IncludeIf "os:Windows"]

Best Wishes

Phillip

#12 lore raw
Quoted 8 lines · Phillip Wood

I can see that we would want to respect the preferred spelling in our documentation but it seems a bit mean to penalize users who write

[IncludeIf "os:windows"]

rather than

[IncludeIf "os:Windows"]

I do not think "uname-s/i:windows" is out of question. I am saying that the default should be case sensitive for consistency with others.

Also, as I said already, I do not think we should squat on a good name "os" with this "uname -s" feature that may not be a good differenciator for two OSes for some cases (e.g. telling Debian and Fedora apart was a good example raised upthread already).

#7 lore raw
In reply to Đoàn Trần Công Danh
Quoted 10 lines · Đoàn Trần Công Danh
Quoted 6 lines

This seems like a reasonable thing to have in general, but I wonder if you have an example of how people use this. Mostly I am wondering:

- is it sometimes a misuse, where users _think_ that the OS is correlated with some feature of Git. And they would be better off with some flag like "does the current platform support fsmonitor".

A possible use-case is setting credential.helper based on OS, let's say libsecret on Linux, and osxkeychain on macOS. Of course, users can have their own helper on specific OS.

Thanks, that's a very nice concrete example. I agree that's a pretty reasonable use of this feature, given the lack of other selection mechanisms. I do wonder if folks might run into annoyances when they want to use libsecret on Linux _and_ FreeBSD or similar. But this feature is definitely better than the status quo, and is not very much code to implement or support.

-Peff

#15 lore raw
In reply to Philip Oakley
Quoted 8 lines · Philip Oakley
Quoted 2 lines

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

This uname -s doesn't work well on Git-for-Windows (GfW) / Windows because GfW has its own internal compatibility code to spoof the result.
...
Or just drop the mentions of "<uname-s>" in this commit message and rename it 'sysname' to match the field of the struct utsname?

FWIW I do not mind "sysname". It is much better to say

[includeIf "sysname:Linux"] path = ...

than "os:Linux", as "sysname" informs us the granularity used to identify the system better than "os".

#16 lore raw
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

The discussion about https://github.com/gitgitgadget/git/pull/1429 seems to have stalled on several points. I'll try to summarise; let's see if we can move forward.

(I am the reporter of https://github.com/git-for-windows/git/issues/4125, which led to this PR. I am vested in making progress here.)

1. name of the setting (os vs uname-s vs sysname)
* dscho@ suggested os; Phillip and Philip suggested uname-s and sysname, respectively
* I vote for os; I'm afraid perfect is the enemy of good here as
* man uname says -s gives "the name of the operating system implementation"; no other uname switch comes closer to whatever concept "OS" represents
* this is also correct on Windows (the "Windows" string) - see below
* I find it extremely unlikely a future unforeseen git feature would have a better use for includeIf os (in parallel with includeIf sysname), i.e. I don't worry that we're squatting on a good name for a poor use-case
2. casing (use of /i)
* dscho@ implemented case-insensitive comparison but without test coverage, documentation, and it's inconsistent with the other includeIf options that support the /i switch.
* I propose that we compare case-sensitively because
* no user can reasonably complain about this if the documentation is clear; the OS names are definitive and stable and it's not a big deal getting the case right for "Linux"
* without the case insensitivity being documented, the users who [discover the insensitivity and] rely on it are risking breakage; plus the git maintainers are exposing themselves to the effects of Hyrum's law
(https://xkcd.com/1172) - it's a disservice for both sides
* this still allows us to add support for /i later (should a use-case emerge)
* it is consistent with the other settings
* it requires less code (incl. tests) and shorter documentation
3. handling Windows (MinGW, WSL)
* As implemented currently, includeIf "os:Windows" would work in git-for-Windows. I think that's desirable, and no-one suggested otherwise.
* In contrast, Philip points out includeIf "os:Linux" would be the way to match on WSL. Is that an issue? Do we want WSL to match "os:Windows" or "os:WSL"? As a Windows user, when I switch to WSL I do expect a "proper" Linux experience (unlike when I run "Git bash" on Windows, which is more like a port of utilities, but still Windows). I think this treating WLS as Linux is OK-ish, and we may get away with not discerning WSL. Thoughts?
4. documentation (w.r.t. the details in 1. - 3.)
* We should document all of 1. - 3. I'm happy to give it a go if we can reach consensus.
* Specifically, the documentation should mention that the OS string equals "Windows" in Git-for-Windows, and $(uname -s) otherwise; it should list examples, incl. "Linux" and "Darwin"; it should mention the case sensitivity.
5. tests (potential segfaults)
* Johannes points out the tests hide segfaults. I haven't looked at this closely but hopefully Johannes's suggestion ("use test_cmp or test_cmp_config") is a clear enough pointer. I can try to fix this.
6. what's the use-case?
* As the reporter of https://github.com/git-for-windows/git/issues/4125,
here are my use-cases, i.e. settings that I currently set conditionally per OS (using includeIf gitdir):
* different difftool.path, mergetool.path per OS (e.g. paths containing C:\Program Files\...\...exe vs Unix file paths)
* different merge.tool per OS (I have a BeyondCompare license for Linux only)
* different core.autocrlf: true on Windows, input otherwise
* core.whitespace set to cr-at-eol on Windows
* core.editor set to gvim on Windows
* Note all of the use-cases above would cope with WSL reporting "Linux", except of merge.tool.

I hope this revives the discussion; I know it's been a while but I would appreciate your input. If possible, please refer to the numbered points (1 - 6) for clarity.

I'm happy to iterate on dscho@'s PR if we can reach consensus.

Quoted 21 lines · Junio C Hamano
Quoted 8 lines · Philip Oakley
Quoted 2 lines

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

This uname -s doesn't work well on Git-for-Windows (GfW) / Windows because GfW has its own internal compatibility code to spoof the result.
...
Or just drop the mentions of "<uname-s>" in this commit message and rename it 'sysname' to match the field of the struct utsname?

FWIW I do not mind "sysname". It is much better to say

[includeIf "sysname:Linux"] path = ...

than "os:Linux", as "sysname" informs us the granularity used to identify the system better than "os".

#17 lore raw
Quoted 11 lines · Samuel Ferencik
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

The discussion about https://github.com/gitgitgadget/git/pull/1429 seems to have stalled on several points. I'll try to summarise; let's see if we can move forward.

(I am the reporter of https://github.com/git-for-windows/git/issues/4125, which led to this PR. I am vested in making progress here.)

1. name of the setting (os vs uname-s vs sysname)

I do not think it is a good idea to squat on too generic a name like 'os', especially when there are multiple layers people will care about. But I think the original thread discussed this to death, and I do not see a point bringing it up again as the first bullet point.

Quoted 1 line

2. casing (use of /i)

My preference is to do this case sensitively (in other words, start stupid) and if somebody wants to use "/i", add it later after the dust settles.

Quoted 1 line

3. handling Windows (MinGW, WSL)

This comes back to the reason why "os" is a horrible choice. Is WSL a Windows? Is WSL a Linux? The same question can be asked for Cygwin.

The answer depends on which layer you care about. The underlying kernel and system may be Windows, and some characteristics of the underlying system may seep through the abstraction, but these systems aim to give user experience of something like GNU/Linux.

And this is not limited to Windows. There may be similar issue for systems like PacBSD. Is it a Linux? Is it a BSD?

Quoted 1 line

6. what's the use-case?

I think that this is the most important question to ask, and from here, we'd see how #3 above should be resolved (I suspect that you may want to have at least two layers to allow WSL to be grouped together with MinGW and Cygwin at one level, and at the same time allow it to be grouped together with Ubuntu at a different level). And after we figure that out, we'll have a clear and intuitive answer to #1.

#18 lore raw
Quoted 12 lines · Junio C Hamano
Quoted 10 lines · Samuel Ferencik
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

The discussion about https://github.com/gitgitgadget/git/pull/1429 seems to have stalled on several points. I'll try to summarise; let's see if we can move forward.

(I am the reporter of https://github.com/git-for-windows/git/issues/4125, which led to this PR. I am vested in making progress here.)

Quoted 6 lines
Quoted 1 line

1. name of the setting (os vs uname-s vs sysname)

I do not think it is a good idea to squat on too generic a name like 'os', especially when there are multiple layers people will care about. But I think the original thread discussed this to death, and I do not see a point bringing it up again as the first bullet point.

"platform" is the term I've seen to be less OS-centric.

Signature · 1 line
Felipe Contreras
#19 lore raw
In reply to Junio C Hamano

Hi Junio,

Quoted 12 lines · Junio C Hamano
Quoted 10 lines · Samuel Ferencik
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

The discussion about https://github.com/gitgitgadget/git/pull/1429 seems to have stalled on several points. I'll try to summarise; let's see if we can move forward.

(I am the reporter of https://github.com/git-for-windows/git/issues/4125, which led to this PR. I am vested in making progress here.)

Quoted 6 lines
Quoted 1 line

1. name of the setting (os vs uname-s vs sysname)

I do not think it is a good idea to squat on too generic a name like 'os', especially when there are multiple layers people will care about. But I think the original thread discussed this to death, and I do not see a point bringing it up again as the first bullet point.

Given what you said about "Operating System", i.e. that both "Ubuntu" and "Linux" should be able to match at the same time, I kind of concur, but in the other direction: rather than forcing the current patch series to use a less intuitive (i.e. user-unfriendlier) name than os, I would want to modify the patch series so that it _can_ match "Ubuntu" and "Linux".

Quoted 5 lines
Quoted 1 line

2. casing (use of /i)

My preference is to do this case sensitively (in other words, start stupid) and if somebody wants to use "/i", add it later after the dust settles.

I strongly disagree with this. This feature is meant for Git users, who I must assume based on my experience would expect the value to be case-insensitive. I.e. they would expect both linux and Linux to match. Let's not make this feature harder to use than necessary!

Quoted 4 lines
Quoted 1 line

3. handling Windows (MinGW, WSL)

This comes back to the reason why "os" is a horrible choice. Is WSL a Windows? Is WSL a Linux? The same question can be asked for Cygwin.

These questions actually have pretty obvious answers, with the exception of WSL1 (which nobody should use anymore): WSL is a Linux, Cygwin is not an Operating System by itself but runs on Windows. But of course that's not helpful to help configure Git specifically in a Cygwin setup.

Quoted 1 line

The answer depends on which layer you care about.

Yes, this is the crucial bit.

Quoted 10 lines

The underlying kernel and system may be Windows, and some characteristics of the underlying system may seep through the abstraction, but these systems aim to give user experience of something like GNU/Linux.

And this is not limited to Windows. There may be similar issue for systems like PacBSD. Is it a Linux? Is it a BSD?

Quoted 1 line

6. what's the use-case?

Quoted 7 lines

I think that this is the most important question to ask, and from here, we'd see how #3 above should be resolved (I suspect that you may want to have at least two layers to allow WSL to be grouped together with MinGW and Cygwin at one level, and at the same time allow it to be grouped together with Ubuntu at a different level). And after we figure that out, we'll have a clear and intuitive answer to #1.

This is probably the most valuable feedback in this entire thread: What is the problem we're trying to solve here?

The original report (which this patch tries to address) asks for a way to have a user-wide ("global") Git configuration that can be shared across machines and that allows for adapting to the various environments. The rationale is motivated well e.g. in
https://medium.com/doing-things-right/platform-specific-gitconfigs-and-the-wonderful-includeif-7376cd44994d
where platform-specific credential managers, editors, diff highlighters that work only in certain setups, and work vs personal environments are mentioned.

So as long as Git offers ways to discern between the mentioned environments by including environment-specific configuration files, we solve the problem.

Bonus points if we can do that without getting ever deeper into a pretty contentious discussion about naming.

The strategy chosen in above-mentioned article uses the presence of certain directories as tell-tales for the Operating System in which Git is called: Linux, macOS or Windows. Concretely, it suggests this:

[includeIf "gitdir:/Users"]
path = ~/.gitconfig-macos
[includeIf "gitdir:C:"]
path = ~/.gitconfig-windows
[includeIf "gitdir:/home"]
path = ~/.gitconfig-linux

Now, the presence of directories like /home/ might work well to discern Linux from macOS, but this is not the correct way to identify Linux in general (a /home/ directory exists in many Unices, too). And it only works when the _gitdir_ is in those directories, too. That's why I thought that Git could do better.

In many cases, though, the presence of directories is probably "good enough" to address the need described in above-mentioned article.

What triggered me to write this here patch was the report that those /home/ and /Users paths in the Git config ran into the warning that Git for Windows no longer treats paths starting with a slash as relative to the runtime prefix. This warning was introduced when the %(prefix)/ feature was upstreamed, superseding Git for Windows' original handling of paths starting with a slash. The warning was introduced in November '21 (virtually together with Git for Windows v2.34.0):
https://github.com/git-for-windows/git/commit/28fdfd8a41836f49666c65e82d92de9befea2e69

So while I still think that something like includeIf.os:<name> would make for a better way to address the concern in question, I realize that the path of least resistance is simply to drop the now-deprecated feature from Git for Windows (including the warning that was the reason for the original report): https://github.com/git-for-windows/git/pull/4389

This still leaves Git in the somewhat unsatisfying state where there is no better way to discern between Operating Systems than to work around by detecting the presence of certain directories. But I do not see any viable way to reach consensus about the includeIf.os:<name> patch, so I'll leave it at that.

Ciao,
Johannes

#20 lore raw

Note: I'm going to mix two things here (maybe not the best idea) and change the order.

Quoted 11 lines · Johannes Schindelin

This is probably the most valuable feedback in this entire thread: What is the problem we're trying to solve here?

The original report (which this patch tries to address) asks for a way to have a user-wide ("global") Git configuration that can be shared across machines and that allows for adapting to the various environments. The rationale is motivated well e.g. in
https://medium.com/doing-things-right/platform-specific-gitconfigs-and-the-wonderful-includeif-7376cd44994d
where platform-specific credential managers, editors, diff highlighters that work only in certain setups, and work vs personal environments are mentioned.

Why not allow use of environment variables? Perhaps a simple:

git config include.env.USER_VAR

and/or:

git config include.ifexists.env.DIR

(feel free to invent better names!) or similar. The user can then

export DIR=whatever

in some outside-of-Git setup.

On a separate note:

Quoted 4 lines

... This feature is meant for Git users, who I
must assume based on my experience would expect the value to be case-insensitive. I.e. they would expect both linux and Linux to match.

I'm not at all sure about this: we already see a lot of confusion from people who don't understand why, if Git is case-sensitive about branch names (which it is), Git isn't case-sensitive about branch names *sometimes* on Windows and macOS.

(In any case, using an env var sidesteps this question.)

Chris

#21 lore raw

[resending my previous response, which I had sent only to the PR, not the mailing list; composed before dscho@'s last email]

Quoted 5 lines
Quoted 1 line

2. casing (use of /i)

My preference is to do this case sensitively (in other words, start stupid) and if somebody wants to use "/i", add it later after the dust settles.

Fantastic.

Quoted 10 lines
Quoted 4 lines

6. what's the use-case?

* Note all of the use-cases above would cope with WSL reporting "Linux", except of merge.tool.

I think that this is the most important question to ask, and from here, we'd see how #3 above should be resolved (I suspect that you may want to have at least two layers to allow WSL to be grouped together with MinGW and Cygwin at one level, and at the same time allow it to be grouped together with Ubuntu at a different level).

Actually, I take that back: I can install the Linux version of BeyondCompare into WSL, use my license, and I'm fine with WSL reporting that it's Linux. (This is just to correct my previous claim. More below.)

Quoted 6 lines
Quoted 1 line

3. handling Windows (MinGW, WSL)

The answer depends on which layer you care about. The underlying kernel and system may be Windows, and some characteristics of the underlying system may seep through the abstraction, but these systems aim to give user experience of something like GNU/Linux.

Fair point. I think we only care about the top-most layer (the one nearest to the user).

The "seeping through" aspect means things often aren't clear-cut, but I also think we can make practical decisions. The closer the top layer approximates an OS, the more we can say it *is* that OS without compromising correctness. For example, a Linux container on Windows should report (uname) it's a Linux, and includeIf should go by this. So should WSL2, I think, because it provides a Linux kernel. Maybe there is a use-case for git config (includeIf) to behave differently in WSL because the host OS is Windows, but I'm not aware of such a use-case. In contrast, "Git bash" and Cygwin report something other than "Linux" (MINGW64_NT-<version>, CYGWIN_NT-<version>) because they are not Linuxes, and that's also fine. Interestingly, though, they don't report the host OS (Windows) either.

So I propose that we limit ourselves to the top-most layer. Can we come up with a name (os or another) that would capture this concept?

- Felipe proposed platform. I'm afraid this may be confused with the hardware platform (as reported by uname -m).
- Phillip proposed uname-s. It's self-documenting in a way, but it's also wrong on Windows and describes the tool rather than the concept.
- Philip proposed sysname. It's slightly better but still very much a pointer to utsname.sysname.
- dscho@ proposed os. I like it for its obviousness. The issues with the name are marginal (not bigger than with any other name) and can be sufficiently addressed by good documentation.

If we can agree on the name, I can help fix up the documentation, the tests, and remove the case insensitivity. Thoughts?

#22 lore raw
In reply to Johannes Schindelin
Quoted 15 lines · Johannes Schindelin
Quoted 13 lines · Junio C Hamano
Quoted 11 lines · Samuel Ferencik
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Let's introduce a new condition: os:<uname-s> where <uname-s> is the system name, i.e. the output of uname -s.

The discussion about https://github.com/gitgitgadget/git/pull/1429
seems to have stalled on several points. I'll try to summarise; let's see if we can move forward.

(I am the reporter of
https://github.com/git-for-windows/git/issues/4125, which led to this PR. I am vested in making progress here.)

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

1. name of the setting (os vs uname-s vs sysname)

I do not think it is a good idea to squat on too generic a name like 'os', especially when there are multiple layers people will care about. But I think the original thread discussed this to death, and I do not see a point bringing it up again as the first bullet point.

Given what you said about "Operating System", i.e. that both "Ubuntu" and

"Linux"

Quoted 1 line

should be able to match at the same time, I kind of concur, but in the

other direction:

Quoted 1 line

rather than forcing the current patch series to use a less intuitive (i.e.

user-

Quoted 1 line

unfriendlier) name than os, I would want to modify the patch series so

that it _can_

Quoted 9 lines

match "Ubuntu" and "Linux".

Quoted 5 lines
Quoted 1 line

2. casing (use of /i)

My preference is to do this case sensitively (in other words, start stupid) and if somebody wants to use "/i", add it later after the dust settles.

I strongly disagree with this. This feature is meant for Git users, who I

must assume

Quoted 1 line

based on my experience would expect the value to be case-insensitive. I.e.

they

Quoted 1 line

would expect both linux and Linux to match. Let's not make this feature

harder to

Quoted 8 lines

use than necessary!

Quoted 4 lines
Quoted 1 line

3. handling Windows (MinGW, WSL)

This comes back to the reason why "os" is a horrible choice. Is WSL a Windows? Is WSL a Linux? The same question can be asked for Cygwin.

These questions actually have pretty obvious answers, with the exception of

WSL1

Quoted 1 line

(which nobody should use anymore): WSL is a Linux, Cygwin is not an

Operating

Quoted 1 line

System by itself but runs on Windows. But of course that's not helpful to

help

Quoted 24 lines

configure Git specifically in a Cygwin setup.

Quoted 1 line

The answer depends on which layer you care about.

Yes, this is the crucial bit.

Quoted 10 lines

The underlying kernel and system may be Windows, and some characteristics of the underlying system may seep through the abstraction, but these systems aim to give user experience of something like GNU/Linux.

And this is not limited to Windows. There may be similar issue for systems like PacBSD. Is it a Linux? Is it a BSD?

Quoted 1 line

6. what's the use-case?

Quoted 7 lines

I think that this is the most important question to ask, and from here, we'd see how #3 above should be resolved (I suspect that you may want to have at least two layers to allow WSL to be grouped together with MinGW and Cygwin at one level, and at the same time allow it to be grouped together with Ubuntu at a different level).
And after we figure that out, we'll have a clear and intuitive answer to #1.

Quoted 1 line

This is probably the most valuable feedback in this entire thread: What is

the problem

Quoted 3 lines

we're trying to solve here?

The original report (which this patch tries to address) asks for a way to

have a user-

Quoted 1 line

wide ("global") Git configuration that can be shared across machines and

that allows

Quoted 1 line

for adapting to the various environments. The rationale is motivated well

e.g. in

Quoted 3 lines

https://medium.com/doing-things-right/platform-specific-gitconfigs-and-the-
wonderful-includeif-7376cd44994d
where platform-specific credential managers, editors, diff highlighters

that work only

Quoted 3 lines

in certain setups, and work vs personal environments are mentioned.

So as long as Git offers ways to discern between the mentioned environments

by

Quoted 1 line

including environment-specific configuration files, we solve the problem.

I would suggest using match of uname arguments. But there are variants. The OS release should also be included here as something like NONSTOP_KERNEL is not a sufficient answer. We should have at the very least, or encode the includeif string accordingly:

uname -r = the release n (e.g., J06)
uname -n = the node name (e.g., hpitug)
uname -s = the OS (e.g., NONSTOP_KERNEL

We use these in config.mak.uname (except for -n).

Regards,
Randall

#23 lore raw
In reply to Johannes Schindelin
Quoted 10 lines · Johannes Schindelin
Quoted 5 lines
Quoted 1 line

2. casing (use of /i)

My preference is to do this case sensitively (in other words, start stupid) and if somebody wants to use "/i", add it later after the dust settles.

I strongly disagree with this. This feature is meant for Git users, who I must assume based on my experience would expect the value to be case-insensitive. I.e. they would expect both linux and Linux to match. Let's not make this feature harder to use than necessary!

[jc: Read below with 'os' replaced with 'uname-s' or any of your favorite. This message does not take any position on that part of the discussion.]

I am OK with the above position, if we make sure that all other includeIf conditions are compared case insensitively, and if we make sure there is no existing "/i" includeIf conditions. Then those who want to differentiate can later add "/casesensitive" option.

But I do not want to see a system where some of the conditions are compared case insensitively while some other conditions are compared case sensitively. The end-users will then be forced to remember "the condition 'os' can be spelled in any case permutation, but the condition 'xyzzy' needs to be spelled in the right case". It would not be obvious to end users when they need to use "/i" variant in such a system.

Unlike 'gitdir' whose value is arbitrarily chosen by the users and the projects (where folks use both FooBar and foobar and want them to mean different things), the vocabulary of "os" is limited and I agree with you that it is very likely for any user to expect that any case permutations of "linux" would mean the same thing. But spelling "windows" and have it match even when the official name of the system may be "Windows" should be the choice made by the end user, and the "/i" suffix in "os/i" is a way for them to express it.

You might be able to talk me into adding only "os/i" added without adding "os", though. I do not see much point in doing so, other than that we can say "we do not take any position on what case permutation is the right and official way to spell the name of each system".

Thanks.

#24 lore raw
In reply to Johannes Schindelin
Quoted 7 lines · Johannes Schindelin

The original report (which this patch tries to address) asks for a way to have a user-wide ("global") Git configuration that can be shared across machines and that allows for adapting to the various environments.
...
So as long as Git offers ways to discern between the mentioned environments by including environment-specific configuration files, we solve the problem.

Perhaps

[includeIf "ifExists:/path/to/foo-credential-manager.exe"]
path = /path/to/config/needed/for/using/foo-credential-manager

is being called for? "os" being "LiNuX" does not tell much about the environment differences the end users would care about, like what desktop environment is in use, which leads to the availability and default choice of GUI tools, to help them auto-configure.