git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 2/2] config: resolve symlinks in conditional include's patterns

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Apr 5, 2017, 10:24 UTC
Message-ID
<20170405102439.14797-2-pclouds@gmail.com>
In-Reply-To
<20170405102439.14797-1-pclouds@gmail.com>

$GIT_DIR returned by get_git_dir() is normalized, with all symlinks resolved (see setup_work_tree function). In order to match paths (or patterns) against $GIT_DIR char-by-char, they have to be normalized too. There is a note in config.txt about this, that the user need to resolve symlinks by themselves if needed.

The problem is, we allow certain path expansion, '~/' and './', for convenience and can't ask the user to resolve symlinks in these expansions. Make sure the expanded paths have all symlinks resolved.

PS. The strbuf_realpath(&text, get_git_dir(), 1) is still needed because get_git_dir() may return relative path.

Noticed-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Tests are added in v2.
 config.c                  |  6 +++---
 t/t1305-config-include.sh | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/config.c b/config.c
index f036c721e6..d5ba848b65 100644
--- a/config.c
+++ b/config.c
@@ -177,7 +177,7 @@ static int prepare_include_condition_pattern(struct strbuf *pat)
 	char *expanded;
 	int prefix = 0;
 
-	expanded = expand_user_path(pat->buf, 0);
+	expanded = expand_user_path(pat->buf, 1);
 	if (expanded) {
 		strbuf_reset(pat);
 		strbuf_addstr(pat, expanded);
@@ -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?");
@@ -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);
 
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index e833939320..8fbc7a029f 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -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 &&
@@ -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
-- 
2.11.0.157.gd943d85
Previous: Nguyễn Thái Ngọc Duy
Message 11 of 11 in “t1503 broken ?”
  1. Torsten BögershausenMar 25, 2017
  2. Duy NguyenMar 25, 2017
  3. Duy NguyenMar 25, 2017
  4. Duy NguyenMar 25, 2017
  5. Torsten BögershausenMar 25, 2017
  6. 1/2 path.c: and an option to call real_path() in expand_user_path()Nguyễn Thái Ngọc Duy, Mar 30, 2017
  7. 2/2 config: resolve symlinks in conditional include's patternsNguyễn Thái Ngọc Duy, Mar 30, 2017
  8. Junio C HamanoMar 30, 2017
  9. Duy NguyenApr 4, 2017
  10. 1/2 path.c: and an option to call real_path() in expand_user_path()Nguyễn Thái Ngọc Duy, Apr 5, 2017
  11. 2/2 config: resolve symlinks in conditional include's patternsNguyễn Thái Ngọc Duy, Apr 5, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.