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:
Junio C Hamano 2017-05-30 11:16:43 +09:00
commit b784d0be5d
3 changed files with 49 additions and 0 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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