Skip to content

Commit cf1a114

Browse files
committed
config_file: do not include trailing '/' for "gitdir" conditionals
When evaluating "gitdir:" and "gitdir/i:" conditionals, we currently compare the given pattern with the value of `git_repository_path`. Thing is though that `git_repository_path` returns the gitdir path with trailing '/', while we actually need to match against the gitdir without it. Fix this issue by stripping the trailing '/' previous to matching. Add various tests to ensure we get this right.
1 parent 5d987f7 commit cf1a114

File tree

2 files changed

+37
-28
lines changed

2 files changed

+37
-28
lines changed

src/config_file.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ static int do_match_gitdir(
701701
const char *condition,
702702
bool case_insensitive)
703703
{
704-
git_buf pattern = GIT_BUF_INIT;
704+
git_buf pattern = GIT_BUF_INIT, gitdir = GIT_BUF_INIT;
705705
int error, fnmatch_flags;
706706

707707
if (condition[0] == '.' && git_path_is_dirsep(condition[1])) {
@@ -722,17 +722,24 @@ static int do_match_gitdir(
722722
goto out;
723723
}
724724

725+
if ((error = git_repository_item_path(&gitdir, repo, GIT_REPOSITORY_ITEM_GITDIR)) < 0)
726+
goto out;
727+
728+
if (git_path_is_dirsep(gitdir.ptr[gitdir.size - 1]))
729+
git_buf_truncate(&gitdir, gitdir.size - 1);
730+
725731
fnmatch_flags = FNM_PATHNAME|FNM_LEADING_DIR;
726732
if (case_insensitive)
727733
fnmatch_flags |= FNM_IGNORECASE;
728734

729-
if ((error = p_fnmatch(pattern.ptr, git_repository_path(repo), fnmatch_flags)) < 0)
735+
if ((error = p_fnmatch(pattern.ptr, gitdir.ptr, fnmatch_flags)) < 0)
730736
goto out;
731737

732738
*matches = (error == 0);
733739

734740
out:
735741
git_buf_dispose(&pattern);
742+
git_buf_dispose(&gitdir);
736743
return error;
737744
}
738745

tests/config/conditionals.c

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,53 +47,55 @@ static void assert_condition_includes(const char *keyword, const char *path, boo
4747
git_config_free(cfg);
4848
}
4949

50+
static char *sandbox_path(git_buf *buf, const char *suffix)
51+
{
52+
char *path = p_realpath(clar_sandbox_path(), NULL);
53+
cl_assert(path);
54+
cl_git_pass(git_buf_attach(buf, path, 0));
55+
cl_git_pass(git_buf_joinpath(buf, buf->ptr, suffix));
56+
return buf->ptr;
57+
}
58+
5059
void test_config_conditionals__gitdir(void)
5160
{
5261
git_buf path = GIT_BUF_INIT;
53-
char *sandbox_path;
5462

5563
assert_condition_includes("gitdir", ROOT_PREFIX "/", true);
56-
assert_condition_includes("gitdir", "empty_standard_repo", true);
64+
assert_condition_includes("gitdir", "empty_stand", false);
65+
assert_condition_includes("gitdir", "empty_stand/", false);
66+
assert_condition_includes("gitdir", "empty_stand/.git", false);
67+
assert_condition_includes("gitdir", "empty_stand/.git/", false);
68+
assert_condition_includes("gitdir", "empty_stand*/", true);
69+
assert_condition_includes("gitdir", "empty_stand*/.git", true);
70+
assert_condition_includes("gitdir", "empty_stand*/.git/", false);
5771
assert_condition_includes("gitdir", "empty_standard_repo/", true);
58-
assert_condition_includes("gitdir", "./", true);
72+
assert_condition_includes("gitdir", "empty_standard_repo/.git", true);
73+
assert_condition_includes("gitdir", "empty_standard_repo/.git/", false);
74+
75+
assert_condition_includes("gitdir", "./", false);
5976

6077
assert_condition_includes("gitdir", ROOT_PREFIX "/nonexistent", false);
6178
assert_condition_includes("gitdir", ROOT_PREFIX "/empty_standard_repo", false);
62-
assert_condition_includes("gitdir", "empty_stand", false);
6379
assert_condition_includes("gitdir", "~/empty_standard_repo", false);
6480

65-
sandbox_path = p_realpath(clar_sandbox_path(), NULL);
81+
assert_condition_includes("gitdir", sandbox_path(&path, "/"), true);
82+
assert_condition_includes("gitdir", sandbox_path(&path, "/**"), true);
6683

67-
git_buf_joinpath(&path, sandbox_path, "/");
68-
assert_condition_includes("gitdir", path.ptr, true);
84+
assert_condition_includes("gitdir", sandbox_path(&path, "empty_standard_repo/"), true);
85+
assert_condition_includes("gitdir", sandbox_path(&path, "empty_standard_repo/"), true);
86+
assert_condition_includes("gitdir", sandbox_path(&path, "Empty_Standard_Repo"), false);
87+
assert_condition_includes("gitdir", sandbox_path(&path, "Empty_Standard_Repo/"), false);
6988

70-
git_buf_joinpath(&path, sandbox_path, "/*");
71-
assert_condition_includes("gitdir", path.ptr, true);
72-
73-
git_buf_joinpath(&path, sandbox_path, "empty_standard_repo");
74-
assert_condition_includes("gitdir", path.ptr, true);
75-
76-
git_buf_joinpath(&path, sandbox_path, "Empty_Standard_Repo");
77-
assert_condition_includes("gitdir", path.ptr, false);
78-
79-
git__free(sandbox_path);
8089
git_buf_dispose(&path);
8190
}
8291

8392
void test_config_conditionals__gitdir_i(void)
8493
{
8594
git_buf path = GIT_BUF_INIT;
86-
char *sandbox_path;
87-
88-
sandbox_path = p_realpath(clar_sandbox_path(), NULL);
89-
90-
git_buf_joinpath(&path, sandbox_path, "empty_standard_repo");
91-
assert_condition_includes("gitdir/i", path.ptr, true);
9295

93-
git_buf_joinpath(&path, sandbox_path, "EMPTY_STANDARD_REPO");
94-
assert_condition_includes("gitdir/i", path.ptr, true);
96+
assert_condition_includes("gitdir/i", sandbox_path(&path, "empty_standard_repo/"), true);
97+
assert_condition_includes("gitdir/i", sandbox_path(&path, "EMPTY_STANDARD_REPO/"), true);
9598

96-
git__free(sandbox_path);
9799
git_buf_dispose(&path);
98100
}
99101

0 commit comments

Comments
 (0)