Commit 33d532dc by Russell Belfer

Merge pull request #1462 from yorah/fix/libgit2sharp-issue-379

status: fix handling of filenames with special prefixes
parents 7f7ebe13 2e40a60e
......@@ -85,7 +85,7 @@ int git_attr_file__parse_buffer(
}
/* parse the next "pattern attr attr attr" line */
if (!(error = git_attr_fnmatch__parse(
if (!(error = git_attr_fnmatch__parse_gitattr_format(
&rule->match, attrs->pool, context, &scan)) &&
!(error = git_attr_assignment__parse(
repo, attrs->pool, &rule->assigns, &scan)))
......@@ -337,23 +337,16 @@ void git_attr_path__free(git_attr_path *info)
* GIT_ENOTFOUND if the fnmatch does not require matching, or
* another error code there was an actual problem.
*/
int git_attr_fnmatch__parse(
int git_attr_fnmatch__parse_gitattr_format(
git_attr_fnmatch *spec,
git_pool *pool,
const char *source,
const char **base)
{
const char *pattern, *scan;
int slash_count, allow_space;
const char *pattern;
assert(spec && base && *base);
if (parse_optimized_patterns(spec, pool, *base))
return 0;
spec->flags = (spec->flags & GIT_ATTR_FNMATCH_ALLOWSPACE);
allow_space = (spec->flags != 0);
pattern = *base;
while (git__isspace(*pattern)) pattern++;
......@@ -375,6 +368,39 @@ int git_attr_fnmatch__parse(
pattern++;
}
if (git_attr_fnmatch__parse_shellglob_format(spec, pool,
source, &pattern) < 0)
return -1;
*base = pattern;
return 0;
}
/*
* Fills a spec for the purpose of pure pathspec matching, not
* related to a gitattribute file parsing.
*
* This will return 0 if the spec was filled out, or
* another error code there was an actual problem.
*/
int git_attr_fnmatch__parse_shellglob_format(
git_attr_fnmatch *spec,
git_pool *pool,
const char *source,
const char **base)
{
const char *pattern, *scan;
int slash_count, allow_space;
assert(spec && base && *base);
if (parse_optimized_patterns(spec, pool, *base))
return 0;
allow_space = (spec->flags & GIT_ATTR_FNMATCH_ALLOWSPACE) != 0;
pattern = *base;
slash_count = 0;
for (scan = pattern; *scan != '\0'; ++scan) {
/* scan until (non-escaped) white space */
......@@ -610,6 +636,7 @@ static void git_attr_rule__clear(git_attr_rule *rule)
/* match.pattern is stored in a git_pool, so no need to free */
rule->match.pattern = NULL;
rule->match.length = 0;
rule->match.flags = 0;
}
void git_attr_rule__free(git_attr_rule *rule)
......
......@@ -115,7 +115,13 @@ extern uint32_t git_attr_file__name_hash(const char *name);
* other utilities
*/
extern int git_attr_fnmatch__parse(
extern int git_attr_fnmatch__parse_gitattr_format(
git_attr_fnmatch *spec,
git_pool *pool,
const char *source,
const char **base);
extern int git_attr_fnmatch__parse_shellglob_format(
git_attr_fnmatch *spec,
git_pool *pool,
const char *source,
......
......@@ -39,7 +39,7 @@ static int parse_ignore_file(
match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE;
if (!(error = git_attr_fnmatch__parse(
if (!(error = git_attr_fnmatch__parse_gitattr_format(
match, ignores->pool, context, &scan)))
{
match->flags |= GIT_ATTR_FNMATCH_IGNORE;
......
......@@ -85,7 +85,7 @@ int git_pathspec__vinit(
match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE;
ret = git_attr_fnmatch__parse(match, strpool, NULL, &pattern);
ret = git_attr_fnmatch__parse_shellglob_format(match, strpool, NULL, &pattern);
if (ret == GIT_ENOTFOUND) {
git__free(match);
continue;
......
......@@ -459,3 +459,37 @@ void test_status_ignore__automatically_ignore_bad_files(void)
cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c"));
cl_assert(!ignored);
}
void test_status_ignore__filenames_with_special_prefixes_do_not_interfere_with_status_retrieval(void)
{
status_entry_single st;
char *test_cases[] = {
"!file",
"#blah",
"[blah]",
"[attr]",
"[attr]blah",
NULL
};
int i;
for (i = 0; *(test_cases + i) != NULL; i++) {
git_buf file = GIT_BUF_INIT;
char *file_name = *(test_cases + i);
git_repository *repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_pass(git_buf_joinpath(&file, "empty_standard_repo", file_name));
cl_git_mkfile(git_buf_cstr(&file), "Please don't ignore me!");
memset(&st, 0, sizeof(st));
cl_git_pass(git_status_foreach(repo, cb_status__single, &st));
cl_assert(st.count == 1);
cl_assert(st.status == GIT_STATUS_WT_NEW);
cl_git_pass(git_status_file(&st.status, repo, file_name));
cl_assert(st.status == GIT_STATUS_WT_NEW);
cl_git_sandbox_cleanup();
git_buf_free(&file);
}
}
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