Merge branch 'ab/conditional-config-with-symlinks'
The recently introduced "[includeIf "gitdir:$dir"] path=..." mechansim has further been taught to take symlinks into account. The directory "$dir" specified in "gitdir:$dir" may be a symlink to a real location, not something that $(getcwd) may return. In such a case, a realpath of "$dir" is compared with the real path of the current repository to determine if the contents from the named path should be included. * ab/conditional-config-with-symlinks: config: match both symlink & realpath versions in IncludeIf.gitdir:*
This commit is contained in:
commit
b784d0be5d
@ -145,6 +145,16 @@ A few more notes on matching via `gitdir` and `gitdir/i`:
|
||||
|
||||
* Symlinks in `$GIT_DIR` are not resolved before matching.
|
||||
|
||||
* Both the symlink & realpath versions of paths will be matched
|
||||
outside of `$GIT_DIR`. E.g. if ~/git is a symlink to
|
||||
/mnt/storage/git, both `gitdir:~/git` and `gitdir:/mnt/storage/git`
|
||||
will match.
|
||||
+
|
||||
This was not the case in the initial release of this feature in
|
||||
v2.13.0, which only matched the realpath version. Configuration that
|
||||
wants to be compatible with the initial release of this feature needs
|
||||
to either specify only the realpath version, or both versions.
|
||||
|
||||
* Note that "../" is not special and will match literally, which is
|
||||
unlikely what you want.
|
||||
|
||||
|
16
config.c
16
config.c
@ -214,6 +214,7 @@ static int include_by_gitdir(const struct config_options *opts,
|
||||
struct strbuf pattern = STRBUF_INIT;
|
||||
int ret = 0, prefix;
|
||||
const char *git_dir;
|
||||
int already_tried_absolute = 0;
|
||||
|
||||
if (opts->git_dir)
|
||||
git_dir = opts->git_dir;
|
||||
@ -226,6 +227,7 @@ static int include_by_gitdir(const struct config_options *opts,
|
||||
strbuf_add(&pattern, cond, cond_len);
|
||||
prefix = prepare_include_condition_pattern(&pattern);
|
||||
|
||||
again:
|
||||
if (prefix < 0)
|
||||
goto done;
|
||||
|
||||
@ -245,6 +247,20 @@ static int include_by_gitdir(const struct config_options *opts,
|
||||
ret = !wildmatch(pattern.buf + prefix, text.buf + prefix,
|
||||
icase ? WM_CASEFOLD : 0, NULL);
|
||||
|
||||
if (!ret && !already_tried_absolute) {
|
||||
/*
|
||||
* We've tried e.g. matching gitdir:~/work, but if
|
||||
* ~/work is a symlink to /mnt/storage/work
|
||||
* strbuf_realpath() will expand it, so the rule won't
|
||||
* match. Let's match against a
|
||||
* strbuf_add_absolute_path() version of the path,
|
||||
* which'll do the right thing
|
||||
*/
|
||||
strbuf_reset(&text);
|
||||
strbuf_add_absolute_path(&text, git_dir);
|
||||
already_tried_absolute = 1;
|
||||
goto again;
|
||||
}
|
||||
done:
|
||||
strbuf_release(&pattern);
|
||||
strbuf_release(&text);
|
||||
|
@ -273,6 +273,29 @@ test_expect_success SYMLINKS 'conditional include, relative path with symlinks'
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'conditional include, gitdir matching symlink' '
|
||||
ln -s foo bar &&
|
||||
(
|
||||
cd bar &&
|
||||
echo "[includeIf \"gitdir:bar/\"]path=bar7" >>.git/config &&
|
||||
echo "[test]seven=7" >.git/bar7 &&
|
||||
echo 7 >expect &&
|
||||
git config test.seven >actual &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'conditional include, gitdir matching symlink, icase' '
|
||||
(
|
||||
cd bar &&
|
||||
echo "[includeIf \"gitdir/i:BAR/\"]path=bar8" >>.git/config &&
|
||||
echo "[test]eight=8" >.git/bar8 &&
|
||||
echo 8 >expect &&
|
||||
git config test.eight >actual &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'include cycles are detected' '
|
||||
cat >.gitconfig <<-\EOF &&
|
||||
[test]value = gitconfig
|
||||
|
Loading…
Reference in New Issue
Block a user