Skip to content

Commit

Permalink
config: introduce an Operating System-specific includeIf condition
Browse files Browse the repository at this point in the history
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 git-for-windows#4125

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Nov 21, 2022
1 parent e4a4b31 commit 4523153
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Documentation/config.txt
Expand Up @@ -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.
Expand Down
11 changes: 11 additions & 0 deletions config.c
Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions t/t1309-early-config.sh
Expand Up @@ -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

0 comments on commit 4523153

Please sign in to comment.