Skip to content

Commit

Permalink
Merge branch 'nd/conditional-config-include'
Browse files Browse the repository at this point in the history
$GIT_DIR may in some cases be normalized with all symlinks resolved
while "gitdir" path expansion in the pattern does not receive the
same treatment, leading to incorrect mismatch.  This has been fixed.

* nd/conditional-config-include:
  config: resolve symlinks in conditional include's patterns
  path.c: and an option to call real_path() in expand_user_path()
  • Loading branch information
gitster committed Apr 24, 2017
2 parents 4c01f67 + 86f9515 commit a2e2c04
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 14 deletions.
2 changes: 1 addition & 1 deletion builtin/commit.c
Expand Up @@ -1404,7 +1404,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)

static const char *implicit_ident_advice(void)
{
char *user_config = expand_user_path("~/.gitconfig");
char *user_config = expand_user_path("~/.gitconfig", 0);
char *xdg_config = xdg_config_home("config");
int config_exists = file_exists(user_config) || file_exists(xdg_config);

Expand Down
2 changes: 1 addition & 1 deletion builtin/config.c
Expand Up @@ -502,7 +502,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
}

if (use_global_config) {
char *user_config = expand_user_path("~/.gitconfig");
char *user_config = expand_user_path("~/.gitconfig", 0);
char *xdg_config = xdg_config_home("config");

if (!user_config)
Expand Down
2 changes: 1 addition & 1 deletion cache.h
Expand Up @@ -1164,7 +1164,7 @@ typedef int create_file_fn(const char *path, void *cb);
int raceproof_create_file(const char *path, create_file_fn fn, void *cb);

int mkdir_in_gitdir(const char *path);
extern char *expand_user_path(const char *path);
extern char *expand_user_path(const char *path, int real_home);
const char *enter_repo(const char *path, int strict);
static inline int is_absolute_path(const char *path)
{
Expand Down
12 changes: 6 additions & 6 deletions config.c
Expand Up @@ -135,7 +135,7 @@ static int handle_path_include(const char *path, struct config_include_data *inc
if (!path)
return config_error_nonbool("include.path");

expanded = expand_user_path(path);
expanded = expand_user_path(path, 0);
if (!expanded)
return error("could not expand include path '%s'", path);
path = expanded;
Expand Down Expand Up @@ -177,7 +177,7 @@ static int prepare_include_condition_pattern(struct strbuf *pat)
char *expanded;
int prefix = 0;

expanded = expand_user_path(pat->buf);
expanded = expand_user_path(pat->buf, 1);
if (expanded) {
strbuf_reset(pat);
strbuf_addstr(pat, expanded);
Expand All @@ -191,7 +191,7 @@ static int prepare_include_condition_pattern(struct strbuf *pat)
return error(_("relative config include "
"conditionals must come from files"));

strbuf_add_absolute_path(&path, cf->path);
strbuf_realpath(&path, cf->path, 1);
slash = find_last_dir_sep(path.buf);
if (!slash)
die("BUG: how is this possible?");
Expand All @@ -213,7 +213,7 @@ static int include_by_gitdir(const char *cond, size_t cond_len, int icase)
struct strbuf pattern = STRBUF_INIT;
int ret = 0, prefix;

strbuf_add_absolute_path(&text, get_git_dir());
strbuf_realpath(&text, get_git_dir(), 1);
strbuf_add(&pattern, cond, cond_len);
prefix = prepare_include_condition_pattern(&pattern);

Expand Down Expand Up @@ -965,7 +965,7 @@ int git_config_pathname(const char **dest, const char *var, const char *value)
{
if (!value)
return config_error_nonbool(var);
*dest = expand_user_path(value);
*dest = expand_user_path(value, 0);
if (!*dest)
die(_("failed to expand user dir in: '%s'"), value);
return 0;
Expand Down Expand Up @@ -1515,7 +1515,7 @@ static int do_git_config_sequence(config_fn_t fn, void *data)
{
int ret = 0;
char *xdg_config = xdg_config_home("config");
char *user_config = expand_user_path("~/.gitconfig");
char *user_config = expand_user_path("~/.gitconfig", 0);
char *repo_config = have_git_dir() ? git_pathdup("config") : NULL;

current_parsing_scope = CONFIG_SCOPE_SYSTEM;
Expand Down
2 changes: 1 addition & 1 deletion credential-cache.c
Expand Up @@ -87,7 +87,7 @@ static char *get_socket_path(void)
{
struct stat sb;
char *old_dir, *socket;
old_dir = expand_user_path("~/.git-credential-cache");
old_dir = expand_user_path("~/.git-credential-cache", 0);
if (old_dir && !stat(old_dir, &sb) && S_ISDIR(sb.st_mode))
socket = xstrfmt("%s/socket", old_dir);
else
Expand Down
2 changes: 1 addition & 1 deletion credential-store.c
Expand Up @@ -168,7 +168,7 @@ int cmd_main(int argc, const char **argv)
if (file) {
string_list_append(&fns, file);
} else {
if ((file = expand_user_path("~/.git-credentials")))
if ((file = expand_user_path("~/.git-credentials", 0)))
string_list_append_nodup(&fns, file);
file = xdg_config_home("credentials");
if (file)
Expand Down
11 changes: 8 additions & 3 deletions path.c
Expand Up @@ -617,8 +617,10 @@ static struct passwd *getpw_str(const char *username, size_t len)
* Return a string with ~ and ~user expanded via getpw*. If buf != NULL,
* then it is a newly allocated string. Returns NULL on getpw failure or
* if path is NULL.
*
* If real_home is true, real_path($HOME) is used in the expansion.
*/
char *expand_user_path(const char *path)
char *expand_user_path(const char *path, int real_home)
{
struct strbuf user_path = STRBUF_INIT;
const char *to_copy = path;
Expand All @@ -633,7 +635,10 @@ char *expand_user_path(const char *path)
const char *home = getenv("HOME");
if (!home)
goto return_null;
strbuf_addstr(&user_path, home);
if (real_home)
strbuf_addstr(&user_path, real_path(home));
else
strbuf_addstr(&user_path, home);
#ifdef GIT_WINDOWS_NATIVE
convert_slashes(user_path.buf);
#endif
Expand Down Expand Up @@ -702,7 +707,7 @@ const char *enter_repo(const char *path, int strict)
strbuf_add(&validated_path, path, len);

if (used_path.buf[0] == '~') {
char *newpath = expand_user_path(used_path.buf);
char *newpath = expand_user_path(used_path.buf, 0);
if (!newpath)
return NULL;
strbuf_attach(&used_path, newpath, strlen(newpath),
Expand Down
54 changes: 54 additions & 0 deletions t/t1305-config-include.sh
Expand Up @@ -3,6 +3,16 @@
test_description='test config file include directives'
. ./test-lib.sh

# Force setup_explicit_git_dir() to run until the end. This is needed
# by some tests to make sure real_path() is called on $GIT_DIR. The
# caller needs to make sure git commands are run from a subdirectory
# though or real_path() will not be called.
force_setup_explicit_git_dir() {
GIT_DIR="$(pwd)/.git"
GIT_WORK_TREE="$(pwd)"
export GIT_DIR GIT_WORK_TREE
}

test_expect_success 'include file by absolute path' '
echo "[test]one = 1" >one &&
echo "[include]path = \"$(pwd)/one\"" >.gitconfig &&
Expand Down Expand Up @@ -208,6 +218,50 @@ test_expect_success 'conditional include, both unanchored, icase' '
)
'

test_expect_success SYMLINKS 'conditional include, set up symlinked $HOME' '
mkdir real-home &&
ln -s real-home home &&
(
HOME="$TRASH_DIRECTORY/home" &&
export HOME &&
cd "$HOME" &&
git init foo &&
cd foo &&
mkdir sub
)
'

test_expect_success SYMLINKS 'conditional include, $HOME expansion with symlinks' '
(
HOME="$TRASH_DIRECTORY/home" &&
export HOME &&
cd "$HOME"/foo &&
echo "[includeIf \"gitdir:~/foo/\"]path=bar2" >>.git/config &&
echo "[test]two=2" >.git/bar2 &&
echo 2 >expect &&
force_setup_explicit_git_dir &&
git -C sub config test.two >actual &&
test_cmp expect actual
)
'

test_expect_success SYMLINKS 'conditional include, relative path with symlinks' '
echo "[includeIf \"gitdir:./foo/.git\"]path=bar4" >home/.gitconfig &&
echo "[test]four=4" >home/bar4 &&
(
HOME="$TRASH_DIRECTORY/home" &&
export HOME &&
cd "$HOME"/foo &&
echo 4 >expect &&
force_setup_explicit_git_dir &&
git -C sub config test.four >actual &&
test_cmp expect actual
)
'

test_expect_success 'include cycles are detected' '
cat >.gitconfig <<-\EOF &&
[test]value = gitconfig
Expand Down

0 comments on commit a2e2c04

Please sign in to comment.