Skip to content

Commit a2e2c04

Browse files
committed
Merge branch 'nd/conditional-config-include'
$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()
2 parents 4c01f67 + 86f9515 commit a2e2c04

File tree

8 files changed

+73
-14
lines changed

8 files changed

+73
-14
lines changed

builtin/commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1404,7 +1404,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
14041404

14051405
static const char *implicit_ident_advice(void)
14061406
{
1407-
char *user_config = expand_user_path("~/.gitconfig");
1407+
char *user_config = expand_user_path("~/.gitconfig", 0);
14081408
char *xdg_config = xdg_config_home("config");
14091409
int config_exists = file_exists(user_config) || file_exists(xdg_config);
14101410

builtin/config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
502502
}
503503

504504
if (use_global_config) {
505-
char *user_config = expand_user_path("~/.gitconfig");
505+
char *user_config = expand_user_path("~/.gitconfig", 0);
506506
char *xdg_config = xdg_config_home("config");
507507

508508
if (!user_config)

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,7 @@ typedef int create_file_fn(const char *path, void *cb);
11641164
int raceproof_create_file(const char *path, create_file_fn fn, void *cb);
11651165

11661166
int mkdir_in_gitdir(const char *path);
1167-
extern char *expand_user_path(const char *path);
1167+
extern char *expand_user_path(const char *path, int real_home);
11681168
const char *enter_repo(const char *path, int strict);
11691169
static inline int is_absolute_path(const char *path)
11701170
{

config.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ static int handle_path_include(const char *path, struct config_include_data *inc
135135
if (!path)
136136
return config_error_nonbool("include.path");
137137

138-
expanded = expand_user_path(path);
138+
expanded = expand_user_path(path, 0);
139139
if (!expanded)
140140
return error("could not expand include path '%s'", path);
141141
path = expanded;
@@ -177,7 +177,7 @@ static int prepare_include_condition_pattern(struct strbuf *pat)
177177
char *expanded;
178178
int prefix = 0;
179179

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

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

216-
strbuf_add_absolute_path(&text, get_git_dir());
216+
strbuf_realpath(&text, get_git_dir(), 1);
217217
strbuf_add(&pattern, cond, cond_len);
218218
prefix = prepare_include_condition_pattern(&pattern);
219219

@@ -965,7 +965,7 @@ int git_config_pathname(const char **dest, const char *var, const char *value)
965965
{
966966
if (!value)
967967
return config_error_nonbool(var);
968-
*dest = expand_user_path(value);
968+
*dest = expand_user_path(value, 0);
969969
if (!*dest)
970970
die(_("failed to expand user dir in: '%s'"), value);
971971
return 0;
@@ -1515,7 +1515,7 @@ static int do_git_config_sequence(config_fn_t fn, void *data)
15151515
{
15161516
int ret = 0;
15171517
char *xdg_config = xdg_config_home("config");
1518-
char *user_config = expand_user_path("~/.gitconfig");
1518+
char *user_config = expand_user_path("~/.gitconfig", 0);
15191519
char *repo_config = have_git_dir() ? git_pathdup("config") : NULL;
15201520

15211521
current_parsing_scope = CONFIG_SCOPE_SYSTEM;

credential-cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ static char *get_socket_path(void)
8787
{
8888
struct stat sb;
8989
char *old_dir, *socket;
90-
old_dir = expand_user_path("~/.git-credential-cache");
90+
old_dir = expand_user_path("~/.git-credential-cache", 0);
9191
if (old_dir && !stat(old_dir, &sb) && S_ISDIR(sb.st_mode))
9292
socket = xstrfmt("%s/socket", old_dir);
9393
else

credential-store.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ int cmd_main(int argc, const char **argv)
168168
if (file) {
169169
string_list_append(&fns, file);
170170
} else {
171-
if ((file = expand_user_path("~/.git-credentials")))
171+
if ((file = expand_user_path("~/.git-credentials", 0)))
172172
string_list_append_nodup(&fns, file);
173173
file = xdg_config_home("credentials");
174174
if (file)

path.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -617,8 +617,10 @@ static struct passwd *getpw_str(const char *username, size_t len)
617617
* Return a string with ~ and ~user expanded via getpw*. If buf != NULL,
618618
* then it is a newly allocated string. Returns NULL on getpw failure or
619619
* if path is NULL.
620+
*
621+
* If real_home is true, real_path($HOME) is used in the expansion.
620622
*/
621-
char *expand_user_path(const char *path)
623+
char *expand_user_path(const char *path, int real_home)
622624
{
623625
struct strbuf user_path = STRBUF_INIT;
624626
const char *to_copy = path;
@@ -633,7 +635,10 @@ char *expand_user_path(const char *path)
633635
const char *home = getenv("HOME");
634636
if (!home)
635637
goto return_null;
636-
strbuf_addstr(&user_path, home);
638+
if (real_home)
639+
strbuf_addstr(&user_path, real_path(home));
640+
else
641+
strbuf_addstr(&user_path, home);
637642
#ifdef GIT_WINDOWS_NATIVE
638643
convert_slashes(user_path.buf);
639644
#endif
@@ -702,7 +707,7 @@ const char *enter_repo(const char *path, int strict)
702707
strbuf_add(&validated_path, path, len);
703708

704709
if (used_path.buf[0] == '~') {
705-
char *newpath = expand_user_path(used_path.buf);
710+
char *newpath = expand_user_path(used_path.buf, 0);
706711
if (!newpath)
707712
return NULL;
708713
strbuf_attach(&used_path, newpath, strlen(newpath),

t/t1305-config-include.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
test_description='test config file include directives'
44
. ./test-lib.sh
55

6+
# Force setup_explicit_git_dir() to run until the end. This is needed
7+
# by some tests to make sure real_path() is called on $GIT_DIR. The
8+
# caller needs to make sure git commands are run from a subdirectory
9+
# though or real_path() will not be called.
10+
force_setup_explicit_git_dir() {
11+
GIT_DIR="$(pwd)/.git"
12+
GIT_WORK_TREE="$(pwd)"
13+
export GIT_DIR GIT_WORK_TREE
14+
}
15+
616
test_expect_success 'include file by absolute path' '
717
echo "[test]one = 1" >one &&
818
echo "[include]path = \"$(pwd)/one\"" >.gitconfig &&
@@ -208,6 +218,50 @@ test_expect_success 'conditional include, both unanchored, icase' '
208218
)
209219
'
210220

221+
test_expect_success SYMLINKS 'conditional include, set up symlinked $HOME' '
222+
mkdir real-home &&
223+
ln -s real-home home &&
224+
(
225+
HOME="$TRASH_DIRECTORY/home" &&
226+
export HOME &&
227+
cd "$HOME" &&
228+
229+
git init foo &&
230+
cd foo &&
231+
mkdir sub
232+
)
233+
'
234+
235+
test_expect_success SYMLINKS 'conditional include, $HOME expansion with symlinks' '
236+
(
237+
HOME="$TRASH_DIRECTORY/home" &&
238+
export HOME &&
239+
cd "$HOME"/foo &&
240+
241+
echo "[includeIf \"gitdir:~/foo/\"]path=bar2" >>.git/config &&
242+
echo "[test]two=2" >.git/bar2 &&
243+
echo 2 >expect &&
244+
force_setup_explicit_git_dir &&
245+
git -C sub config test.two >actual &&
246+
test_cmp expect actual
247+
)
248+
'
249+
250+
test_expect_success SYMLINKS 'conditional include, relative path with symlinks' '
251+
echo "[includeIf \"gitdir:./foo/.git\"]path=bar4" >home/.gitconfig &&
252+
echo "[test]four=4" >home/bar4 &&
253+
(
254+
HOME="$TRASH_DIRECTORY/home" &&
255+
export HOME &&
256+
cd "$HOME"/foo &&
257+
258+
echo 4 >expect &&
259+
force_setup_explicit_git_dir &&
260+
git -C sub config test.four >actual &&
261+
test_cmp expect actual
262+
)
263+
'
264+
211265
test_expect_success 'include cycles are detected' '
212266
cat >.gitconfig <<-\EOF &&
213267
[test]value = gitconfig

0 commit comments

Comments
 (0)