Commit 5c54e216 by Carlos Martín Nieto

ignore: consider files with a CR in their names

We currently consider CR to start the end of the line, but that means
that we miss cases with CR CR LF which can be used with git to match
files whose names have CR at the end of their names.

The fix from the patch comes from Russell's comment in the issue.

This fixes #2536.
parent 4bb87087
......@@ -543,7 +543,7 @@ int git_attr_fnmatch__parse(
for (scan = pattern; *scan != '\0'; ++scan) {
/* scan until (non-escaped) white space */
if (git__isspace(*scan) && *(scan - 1) != '\\') {
if (!allow_space || (*scan != ' ' && *scan != '\t'))
if (!allow_space || (*scan != ' ' && *scan != '\t' && *scan != '\r'))
break;
}
......@@ -564,6 +564,15 @@ int git_attr_fnmatch__parse(
if ((spec->length = scan - pattern) == 0)
return GIT_ENOTFOUND;
/*
* Remove one trailing \r in case this is a CRLF delimited
* file, in the case of Icon\r\r\n, we still leave the first
* \r there to match against.
*/
if (pattern[spec->length - 1] == '\r')
if (--spec->length == 0)
return GIT_ENOTFOUND;
if (pattern[spec->length - 1] == '/') {
spec->length--;
spec->flags = spec->flags | GIT_ATTR_FNMATCH_DIRECTORY;
......
......@@ -883,3 +883,35 @@ void test_status_ignore__negative_ignores_without_trailing_slash_inside_ignores(
cl_assert(found_parent_child2_file);
}
void test_status_ignore__filename_with_cr(void)
{
int ignored;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_mkfile("empty_standard_repo/.gitignore", "Icon\r\r\n");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r"));
cl_assert_equal_i(1, ignored);
cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\n");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn"));
cl_assert_equal_i(1, ignored);
cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\r\n");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn"));
cl_assert_equal_i(1, ignored);
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn\r"));
cl_assert_equal_i(0, ignored);
cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\r\r\n");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn\r"));
cl_assert_equal_i(1, ignored);
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r"));
cl_assert_equal_i(0, ignored);
cl_git_mkfile("empty_standard_repo/.gitignore", "Icon\r\n");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r"));
cl_assert_equal_i(0, ignored);
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon"));
cl_assert_equal_i(1, ignored);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment