Commit 5811e3ba490ed57dd73714ff4cf26cfa355c19f4

Patrick Steinhardt 2019-06-13T19:16:32

config_file: use `wildmatch` to evaluate conditionals We currently use `p_fnmatch` to compute whether a given "gitdir:" or "gitdir/i:" conditional matches the current configuration file path. As git.git has moved to use `wildmatch` instead of `p_fnmatch` throughout its complete codebase, we evaluate conditionals inconsistently with git.git in some special cases. Convert `p_fnmatch` to use `wildmatch`. The `FNM_LEADINGDIR` flag cannot be translated to `wildmatch`, but in fact git.git doesn't use it here either. And in fact, dropping it while we go increases compatibility with git.git.

diff --git a/src/config_file.c b/src/config_file.c
index 4fb8327..27b9cc5 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -18,7 +18,7 @@
 #include "array.h"
 #include "config_parse.h"
 #include "config_entries.h"
-#include "fnmatch.h"
+#include "wildmatch.h"
 
 #include <ctype.h>
 #include <sys/types.h>
@@ -702,7 +702,7 @@ static int do_match_gitdir(
 	bool case_insensitive)
 {
 	git_buf pattern = GIT_BUF_INIT, gitdir = GIT_BUF_INIT;
-	int error, fnmatch_flags;
+	int error;
 
 	if (condition[0] == '.' && git_path_is_dirsep(condition[1])) {
 		git_path_dirname_r(&pattern, cfg_file);
@@ -728,15 +728,8 @@ static int do_match_gitdir(
 	if (git_path_is_dirsep(gitdir.ptr[gitdir.size - 1]))
 		git_buf_truncate(&gitdir, gitdir.size - 1);
 
-	fnmatch_flags = FNM_PATHNAME|FNM_LEADING_DIR;
-	if (case_insensitive)
-		fnmatch_flags |= FNM_IGNORECASE;
-
-	if ((error = p_fnmatch(pattern.ptr, gitdir.ptr, fnmatch_flags)) < 0)
-		goto out;
-
-	*matches = (error == 0);
-
+	*matches = wildmatch(pattern.ptr, gitdir.ptr,
+			     WM_PATHNAME | (case_insensitive ? WM_CASEFOLD : 0)) == WM_MATCH;
 out:
 	git_buf_dispose(&pattern);
 	git_buf_dispose(&gitdir);
diff --git a/tests/config/conditionals.c b/tests/config/conditionals.c
index 4c25728..8b9c0e6 100644
--- a/tests/config/conditionals.c
+++ b/tests/config/conditionals.c
@@ -68,6 +68,7 @@ void test_config_conditionals__gitdir(void)
 	assert_condition_includes("gitdir", "empty_stand*/", true);
 	assert_condition_includes("gitdir", "empty_stand*/.git", true);
 	assert_condition_includes("gitdir", "empty_stand*/.git/", false);
+	assert_condition_includes("gitdir", "empty_standard_repo", false);
 	assert_condition_includes("gitdir", "empty_standard_repo/", true);
 	assert_condition_includes("gitdir", "empty_standard_repo/.git", true);
 	assert_condition_includes("gitdir", "empty_standard_repo/.git/", false);
@@ -79,8 +80,10 @@ void test_config_conditionals__gitdir(void)
 	assert_condition_includes("gitdir", "~/empty_standard_repo", false);
 
 	assert_condition_includes("gitdir", sandbox_path(&path, "/"), true);
+	assert_condition_includes("gitdir", sandbox_path(&path, "/*"), false);
 	assert_condition_includes("gitdir", sandbox_path(&path, "/**"), true);
 
+	assert_condition_includes("gitdir", sandbox_path(&path, "empty_standard_repo"), false);
 	assert_condition_includes("gitdir", sandbox_path(&path, "empty_standard_repo/"), true);
 	assert_condition_includes("gitdir", sandbox_path(&path, "empty_standard_repo/"), true);
 	assert_condition_includes("gitdir", sandbox_path(&path, "Empty_Standard_Repo"), false);