mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-05 20:33:41 +00:00
status: fix handling of filenames with special prefixes
Fix libgit2/libgit2sharp#379
This commit is contained in:
parent
2d2260da41
commit
2e40a60e84
@ -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 */
|
||||
@ -609,6 +635,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,
|
||||
|
@ -49,7 +49,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;
|
||||
|
@ -78,7 +78,7 @@ int git_pathspec_init(
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user