config: add include directive
It can be useful to split your ~/.gitconfig across multiple
files. For example, you might have a "main" file which is
used on many machines, but a small set of per-machine
tweaks. Or you may want to make some of your config public
(e.g., clever aliases) while keeping other data back (e.g.,
your name or other identifying information). Or you may want
to include a number of config options in some subset of your
repos without copying and pasting (e.g., you want to
reference them from the .git/config of participating repos).
This patch introduces an include directive for config files.
It looks like:
[include]
path = /path/to/file
This is syntactically backwards-compatible with existing git
config parsers (i.e., they will see it as another config
entry and ignore it unless you are looking up include.path).
The implementation provides a "git_config_include" callback
which wraps regular config callbacks. Callers can pass it to
git_config_from_file, and it will transparently follow any
include directives, passing all of the discovered options to
the real callback.
Include directives are turned on automatically for "regular"
git config parsing. This includes calls to git_config, as
well as calls to the "git config" program that do not
specify a single file (e.g., using "-f", "--global", etc).
They are not turned on in other cases, including:
1. Parsing of other config-like files, like .gitmodules.
There isn't a real need, and I'd rather be conservative
and avoid unnecessary incompatibility or confusion.
2. Reading single files via "git config". This is for two
reasons:
a. backwards compatibility with scripts looking at
config-like files.
b. inspection of a specific file probably means you
care about just what's in that file, not a general
lookup for "do we have this value anywhere at
all". If that is not the case, the caller can
always specify "--includes".
3. Writing files via "git config"; we want to treat
include.* variables as literal items to be copied (or
modified), and not expand them. So "git config
--unset-all foo.bar" would operate _only_ on
.git/config, not any of its included files (just as it
also does not operate on ~/.gitconfig).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 10:54:04 +01:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='test config file include directives'
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
test_expect_success 'include file by absolute path' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path = \"$(pwd)/one\"" >.gitconfig &&
|
|
|
|
echo 1 >expect &&
|
|
|
|
git config test.one >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'include file by relative path' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path = one" >.gitconfig &&
|
|
|
|
echo 1 >expect &&
|
|
|
|
git config test.one >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'chained relative paths' '
|
|
|
|
mkdir subdir &&
|
|
|
|
echo "[test]three = 3" >subdir/three &&
|
|
|
|
echo "[include]path = three" >subdir/two &&
|
|
|
|
echo "[include]path = subdir/two" >.gitconfig &&
|
|
|
|
echo 3 >expect &&
|
|
|
|
git config test.three >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2012-04-25 14:00:36 +02:00
|
|
|
test_expect_success 'include paths get tilde-expansion' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path = ~/one" >.gitconfig &&
|
|
|
|
echo 1 >expect &&
|
|
|
|
git config test.one >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
config: add include directive
It can be useful to split your ~/.gitconfig across multiple
files. For example, you might have a "main" file which is
used on many machines, but a small set of per-machine
tweaks. Or you may want to make some of your config public
(e.g., clever aliases) while keeping other data back (e.g.,
your name or other identifying information). Or you may want
to include a number of config options in some subset of your
repos without copying and pasting (e.g., you want to
reference them from the .git/config of participating repos).
This patch introduces an include directive for config files.
It looks like:
[include]
path = /path/to/file
This is syntactically backwards-compatible with existing git
config parsers (i.e., they will see it as another config
entry and ignore it unless you are looking up include.path).
The implementation provides a "git_config_include" callback
which wraps regular config callbacks. Callers can pass it to
git_config_from_file, and it will transparently follow any
include directives, passing all of the discovered options to
the real callback.
Include directives are turned on automatically for "regular"
git config parsing. This includes calls to git_config, as
well as calls to the "git config" program that do not
specify a single file (e.g., using "-f", "--global", etc).
They are not turned on in other cases, including:
1. Parsing of other config-like files, like .gitmodules.
There isn't a real need, and I'd rather be conservative
and avoid unnecessary incompatibility or confusion.
2. Reading single files via "git config". This is for two
reasons:
a. backwards compatibility with scripts looking at
config-like files.
b. inspection of a specific file probably means you
care about just what's in that file, not a general
lookup for "do we have this value anywhere at
all". If that is not the case, the caller can
always specify "--includes".
3. Writing files via "git config"; we want to treat
include.* variables as literal items to be copied (or
modified), and not expand them. So "git config
--unset-all foo.bar" would operate _only_ on
.git/config, not any of its included files (just as it
also does not operate on ~/.gitconfig).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 10:54:04 +01:00
|
|
|
test_expect_success 'include options can still be examined' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path = one" >.gitconfig &&
|
|
|
|
echo one >expect &&
|
|
|
|
git config include.path >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'listing includes option and expansion' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path = one" >.gitconfig &&
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
include.path=one
|
|
|
|
test.one=1
|
|
|
|
EOF
|
|
|
|
git config --list >actual.full &&
|
|
|
|
grep -v ^core actual.full >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'single file lookup does not expand includes by default' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path = one" >.gitconfig &&
|
|
|
|
test_must_fail git config -f .gitconfig test.one &&
|
|
|
|
test_must_fail git config --global test.one &&
|
|
|
|
echo 1 >expect &&
|
|
|
|
git config --includes -f .gitconfig test.one >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'single file list does not expand includes by default' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path = one" >.gitconfig &&
|
|
|
|
echo "include.path=one" >expect &&
|
|
|
|
git config -f .gitconfig --list >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'writing config file does not expand includes' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path = one" >.gitconfig &&
|
|
|
|
git config test.two 2 &&
|
|
|
|
echo 2 >expect &&
|
|
|
|
git config --no-includes test.two >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
test_must_fail git config --no-includes test.one
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'config modification does not affect includes' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path = one" >.gitconfig &&
|
|
|
|
git config test.one 2 &&
|
|
|
|
echo 1 >expect &&
|
|
|
|
git config -f one test.one >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
1
|
|
|
|
2
|
|
|
|
EOF
|
|
|
|
git config --get-all test.one >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'missing include files are ignored' '
|
|
|
|
cat >.gitconfig <<-\EOF &&
|
config: add conditional include
Sometimes a set of repositories want to share configuration settings
among themselves that are distinct from other such sets of repositories.
A user may work on two projects, each of which have multiple
repositories, and use one user.email for one project while using another
for the other.
Setting $GIT_DIR/.config works, but if the penalty of forgetting to
update $GIT_DIR/.config is high (especially when you end up cloning
often), it may not be the best way to go. Having the settings in
~/.gitconfig, which would work for just one set of repositories, would
not well in such a situation. Having separate ${HOME}s may add more
problems than it solves.
Extend the include.path mechanism that lets a config file include
another config file, so that the inclusion can be done only when some
conditions hold. Then ~/.gitconfig can say "include config-project-A
only when working on project-A" for each project A the user works on.
In this patch, the only supported grouping is based on $GIT_DIR (in
absolute path), so you would need to group repositories by directory, or
something like that to take advantage of it.
We already have include.path for unconditional includes. This patch goes
with includeIf.<condition>.path to make it clearer that a condition is
required. The new config has the same backward compatibility approach as
include.path: older git versions that don't understand includeIf will
simply ignore them.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-01 12:26:31 +01:00
|
|
|
[include]path = non-existent
|
config: add include directive
It can be useful to split your ~/.gitconfig across multiple
files. For example, you might have a "main" file which is
used on many machines, but a small set of per-machine
tweaks. Or you may want to make some of your config public
(e.g., clever aliases) while keeping other data back (e.g.,
your name or other identifying information). Or you may want
to include a number of config options in some subset of your
repos without copying and pasting (e.g., you want to
reference them from the .git/config of participating repos).
This patch introduces an include directive for config files.
It looks like:
[include]
path = /path/to/file
This is syntactically backwards-compatible with existing git
config parsers (i.e., they will see it as another config
entry and ignore it unless you are looking up include.path).
The implementation provides a "git_config_include" callback
which wraps regular config callbacks. Callers can pass it to
git_config_from_file, and it will transparently follow any
include directives, passing all of the discovered options to
the real callback.
Include directives are turned on automatically for "regular"
git config parsing. This includes calls to git_config, as
well as calls to the "git config" program that do not
specify a single file (e.g., using "-f", "--global", etc).
They are not turned on in other cases, including:
1. Parsing of other config-like files, like .gitmodules.
There isn't a real need, and I'd rather be conservative
and avoid unnecessary incompatibility or confusion.
2. Reading single files via "git config". This is for two
reasons:
a. backwards compatibility with scripts looking at
config-like files.
b. inspection of a specific file probably means you
care about just what's in that file, not a general
lookup for "do we have this value anywhere at
all". If that is not the case, the caller can
always specify "--includes".
3. Writing files via "git config"; we want to treat
include.* variables as literal items to be copied (or
modified), and not expand them. So "git config
--unset-all foo.bar" would operate _only_ on
.git/config, not any of its included files (just as it
also does not operate on ~/.gitconfig).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 10:54:04 +01:00
|
|
|
[test]value = yes
|
|
|
|
EOF
|
|
|
|
echo yes >expect &&
|
|
|
|
git config test.value >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'absolute includes from command line work' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo 1 >expect &&
|
2014-02-18 23:58:55 +01:00
|
|
|
git -c include.path="$(pwd)/one" config test.one >actual &&
|
config: add include directive
It can be useful to split your ~/.gitconfig across multiple
files. For example, you might have a "main" file which is
used on many machines, but a small set of per-machine
tweaks. Or you may want to make some of your config public
(e.g., clever aliases) while keeping other data back (e.g.,
your name or other identifying information). Or you may want
to include a number of config options in some subset of your
repos without copying and pasting (e.g., you want to
reference them from the .git/config of participating repos).
This patch introduces an include directive for config files.
It looks like:
[include]
path = /path/to/file
This is syntactically backwards-compatible with existing git
config parsers (i.e., they will see it as another config
entry and ignore it unless you are looking up include.path).
The implementation provides a "git_config_include" callback
which wraps regular config callbacks. Callers can pass it to
git_config_from_file, and it will transparently follow any
include directives, passing all of the discovered options to
the real callback.
Include directives are turned on automatically for "regular"
git config parsing. This includes calls to git_config, as
well as calls to the "git config" program that do not
specify a single file (e.g., using "-f", "--global", etc).
They are not turned on in other cases, including:
1. Parsing of other config-like files, like .gitmodules.
There isn't a real need, and I'd rather be conservative
and avoid unnecessary incompatibility or confusion.
2. Reading single files via "git config". This is for two
reasons:
a. backwards compatibility with scripts looking at
config-like files.
b. inspection of a specific file probably means you
care about just what's in that file, not a general
lookup for "do we have this value anywhere at
all". If that is not the case, the caller can
always specify "--includes".
3. Writing files via "git config"; we want to treat
include.* variables as literal items to be copied (or
modified), and not expand them. So "git config
--unset-all foo.bar" would operate _only_ on
.git/config, not any of its included files (just as it
also does not operate on ~/.gitconfig).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 10:54:04 +01:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'relative includes from command line fail' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
test_must_fail git -c include.path=one config test.one
|
|
|
|
'
|
|
|
|
|
2014-02-18 23:58:52 +01:00
|
|
|
test_expect_success 'absolute includes from blobs work' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path=$(pwd)/one" >blob &&
|
|
|
|
blob=$(git hash-object -w blob) &&
|
|
|
|
echo 1 >expect &&
|
|
|
|
git config --blob=$blob test.one >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'relative includes from blobs fail' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path=one" >blob &&
|
|
|
|
blob=$(git hash-object -w blob) &&
|
|
|
|
test_must_fail git config --blob=$blob test.one
|
|
|
|
'
|
|
|
|
|
2014-02-18 23:58:55 +01:00
|
|
|
test_expect_success 'absolute includes from stdin work' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo 1 >expect &&
|
|
|
|
echo "[include]path=\"$(pwd)/one\"" |
|
|
|
|
git config --file - test.one >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'relative includes from stdin line fail' '
|
|
|
|
echo "[test]one = 1" >one &&
|
|
|
|
echo "[include]path=one" |
|
|
|
|
test_must_fail git config --file - test.one
|
|
|
|
'
|
|
|
|
|
config: add conditional include
Sometimes a set of repositories want to share configuration settings
among themselves that are distinct from other such sets of repositories.
A user may work on two projects, each of which have multiple
repositories, and use one user.email for one project while using another
for the other.
Setting $GIT_DIR/.config works, but if the penalty of forgetting to
update $GIT_DIR/.config is high (especially when you end up cloning
often), it may not be the best way to go. Having the settings in
~/.gitconfig, which would work for just one set of repositories, would
not well in such a situation. Having separate ${HOME}s may add more
problems than it solves.
Extend the include.path mechanism that lets a config file include
another config file, so that the inclusion can be done only when some
conditions hold. Then ~/.gitconfig can say "include config-project-A
only when working on project-A" for each project A the user works on.
In this patch, the only supported grouping is based on $GIT_DIR (in
absolute path), so you would need to group repositories by directory, or
something like that to take advantage of it.
We already have include.path for unconditional includes. This patch goes
with includeIf.<condition>.path to make it clearer that a condition is
required. The new config has the same backward compatibility approach as
include.path: older git versions that don't understand includeIf will
simply ignore them.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-01 12:26:31 +01:00
|
|
|
test_expect_success 'conditional include, both unanchored' '
|
|
|
|
git init foo &&
|
|
|
|
(
|
|
|
|
cd foo &&
|
|
|
|
echo "[includeIf \"gitdir:foo/\"]path=bar" >>.git/config &&
|
|
|
|
echo "[test]one=1" >.git/bar &&
|
|
|
|
echo 1 >expect &&
|
|
|
|
git config test.one >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'conditional include, $HOME expansion' '
|
|
|
|
(
|
|
|
|
cd foo &&
|
|
|
|
echo "[includeIf \"gitdir:~/foo/\"]path=bar2" >>.git/config &&
|
|
|
|
echo "[test]two=2" >.git/bar2 &&
|
|
|
|
echo 2 >expect &&
|
|
|
|
git config test.two >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'conditional include, full pattern' '
|
|
|
|
(
|
|
|
|
cd foo &&
|
|
|
|
echo "[includeIf \"gitdir:**/foo/**\"]path=bar3" >>.git/config &&
|
|
|
|
echo "[test]three=3" >.git/bar3 &&
|
|
|
|
echo 3 >expect &&
|
|
|
|
git config test.three >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'conditional include, relative path' '
|
|
|
|
echo "[includeIf \"gitdir:./foo/.git\"]path=bar4" >>.gitconfig &&
|
|
|
|
echo "[test]four=4" >bar4 &&
|
|
|
|
(
|
|
|
|
cd foo &&
|
|
|
|
echo 4 >expect &&
|
|
|
|
git config test.four >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'conditional include, both unanchored, icase' '
|
|
|
|
(
|
|
|
|
cd foo &&
|
|
|
|
echo "[includeIf \"gitdir/i:FOO/\"]path=bar5" >>.git/config &&
|
|
|
|
echo "[test]five=5" >.git/bar5 &&
|
|
|
|
echo 5 >expect &&
|
|
|
|
git config test.five >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
config: add include directive
It can be useful to split your ~/.gitconfig across multiple
files. For example, you might have a "main" file which is
used on many machines, but a small set of per-machine
tweaks. Or you may want to make some of your config public
(e.g., clever aliases) while keeping other data back (e.g.,
your name or other identifying information). Or you may want
to include a number of config options in some subset of your
repos without copying and pasting (e.g., you want to
reference them from the .git/config of participating repos).
This patch introduces an include directive for config files.
It looks like:
[include]
path = /path/to/file
This is syntactically backwards-compatible with existing git
config parsers (i.e., they will see it as another config
entry and ignore it unless you are looking up include.path).
The implementation provides a "git_config_include" callback
which wraps regular config callbacks. Callers can pass it to
git_config_from_file, and it will transparently follow any
include directives, passing all of the discovered options to
the real callback.
Include directives are turned on automatically for "regular"
git config parsing. This includes calls to git_config, as
well as calls to the "git config" program that do not
specify a single file (e.g., using "-f", "--global", etc).
They are not turned on in other cases, including:
1. Parsing of other config-like files, like .gitmodules.
There isn't a real need, and I'd rather be conservative
and avoid unnecessary incompatibility or confusion.
2. Reading single files via "git config". This is for two
reasons:
a. backwards compatibility with scripts looking at
config-like files.
b. inspection of a specific file probably means you
care about just what's in that file, not a general
lookup for "do we have this value anywhere at
all". If that is not the case, the caller can
always specify "--includes".
3. Writing files via "git config"; we want to treat
include.* variables as literal items to be copied (or
modified), and not expand them. So "git config
--unset-all foo.bar" would operate _only_ on
.git/config, not any of its included files (just as it
also does not operate on ~/.gitconfig).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 10:54:04 +01:00
|
|
|
test_expect_success 'include cycles are detected' '
|
|
|
|
cat >.gitconfig <<-\EOF &&
|
|
|
|
[test]value = gitconfig
|
|
|
|
[include]path = cycle
|
|
|
|
EOF
|
|
|
|
cat >cycle <<-\EOF &&
|
|
|
|
[test]value = cycle
|
|
|
|
[include]path = .gitconfig
|
|
|
|
EOF
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
gitconfig
|
|
|
|
cycle
|
|
|
|
EOF
|
|
|
|
test_must_fail git config --get-all test.value 2>stderr &&
|
|
|
|
grep "exceeded maximum include depth" stderr
|
|
|
|
'
|
|
|
|
|
|
|
|
test_done
|