Skip to content

Commit 9d117e2

Browse files
committed
ignore: treat paths with trailing "/" as directories
The function `git_ignore_path_is_ignored` is there to test the ignore status of paths that need not necessarily exist inside of a repository. This has the implication that for a given path, we cannot always decide whether it references a directory or a file, and we need to distinguish those cases because ignore rules may treat those differently. E.g. given the following gitignore file: * !/**/ we'd only want to unignore directories, while keeping files ignored. But still, calling `git_ignore_path_is_ignored("dir/")` will say that this directory is ignored because it treats "dir/" as a file path. As said, the `is_ignored` function cannot always decide whether the given path is a file or directory, and thus it may produce wrong results in some cases. While this is unfixable in the general case, we can do better when we are being passed a path name with a trailing path separator (e.g. "dir/") and always treat them as directories.
1 parent aeea1c4 commit 9d117e2

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

src/ignore.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,9 @@ int git_ignore_path_is_ignored(
534534
memset(&path, 0, sizeof(path));
535535
memset(&ignores, 0, sizeof(ignores));
536536

537-
if (git_repository_is_bare(repo))
537+
if (!git__suffixcmp(pathname, "/"))
538+
dir_flag = GIT_DIR_FLAG_TRUE;
539+
else if (git_repository_is_bare(repo))
538540
dir_flag = GIT_DIR_FLAG_FALSE;
539541

540542
if ((error = git_attr_path__init(&path, pathname, workdir, dir_flag)) < 0 ||

tests/attr/ignore.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,19 @@ void test_attr_ignore__ignored_subdirfiles_with_negations(void)
397397
assert_is_ignored(true, "dir/sub1/c.test");
398398
}
399399

400+
void test_attr_ignore__negative_directory_rules_only_match_directories(void)
401+
{
402+
cl_git_rewritefile(
403+
"attr/.gitignore",
404+
"*\n"
405+
"!/**/\n"
406+
"!*.keep\n"
407+
"!.gitignore\n"
408+
);
409+
410+
assert_is_ignored(true, "src");
411+
assert_is_ignored(true, "src/A");
412+
assert_is_ignored(false, "src/");
413+
assert_is_ignored(false, "src/A.keep");
414+
assert_is_ignored(false, ".gitignore");
415+
}

0 commit comments

Comments
 (0)