diff options
-rw-r--r-- | dir.c | 50 | ||||
-rwxr-xr-x | t/t6132-pathspec-exclude.sh | 33 |
2 files changed, 66 insertions, 17 deletions
@@ -364,7 +364,8 @@ static int match_pathspec_item(const struct index_state *istate, return MATCHED_FNMATCH; /* Perform checks to see if "name" is a leading string of the pathspec */ - if (flags & DO_MATCH_LEADING_PATHSPEC) { + if ( (flags & DO_MATCH_LEADING_PATHSPEC) && + !(flags & DO_MATCH_EXCLUDE)) { /* name is a literal prefix of the pathspec */ int offset = name[namelen-1] == '/' ? 1 : 0; if ((namelen < matchlen) && @@ -401,6 +402,10 @@ static int match_pathspec_item(const struct index_state *istate, } /* + * do_match_pathspec() is meant to ONLY be called by + * match_pathspec_with_flags(); calling it directly risks pathspecs + * like ':!unwanted_path' being ignored. + * * Given a name and a list of pathspecs, returns the nature of the * closest (i.e. most specific) match of the name to any of the * pathspecs. @@ -486,13 +491,12 @@ static int do_match_pathspec(const struct index_state *istate, return retval; } -int match_pathspec(const struct index_state *istate, - const struct pathspec *ps, - const char *name, int namelen, - int prefix, char *seen, int is_dir) +static int match_pathspec_with_flags(const struct index_state *istate, + const struct pathspec *ps, + const char *name, int namelen, + int prefix, char *seen, unsigned flags) { int positive, negative; - unsigned flags = is_dir ? DO_MATCH_DIRECTORY : 0; positive = do_match_pathspec(istate, ps, name, namelen, prefix, seen, flags); if (!(ps->magic & PATHSPEC_EXCLUDE) || !positive) @@ -503,6 +507,16 @@ int match_pathspec(const struct index_state *istate, return negative ? 0 : positive; } +int match_pathspec(const struct index_state *istate, + const struct pathspec *ps, + const char *name, int namelen, + int prefix, char *seen, int is_dir) +{ + unsigned flags = is_dir ? DO_MATCH_DIRECTORY : 0; + return match_pathspec_with_flags(istate, ps, name, namelen, + prefix, seen, flags); +} + /** * Check if a submodule is a superset of the pathspec */ @@ -511,11 +525,11 @@ int submodule_path_match(const struct index_state *istate, const char *submodule_name, char *seen) { - int matched = do_match_pathspec(istate, ps, submodule_name, - strlen(submodule_name), - 0, seen, - DO_MATCH_DIRECTORY | - DO_MATCH_LEADING_PATHSPEC); + int matched = match_pathspec_with_flags(istate, ps, submodule_name, + strlen(submodule_name), + 0, seen, + DO_MATCH_DIRECTORY | + DO_MATCH_LEADING_PATHSPEC); return matched; } @@ -1686,9 +1700,11 @@ static enum path_treatment treat_directory(struct dir_struct *dir, * for matching patterns. */ if (pathspec && !excluded) { - matches_how = do_match_pathspec(istate, pathspec, dirname, len, - 0 /* prefix */, NULL /* seen */, - DO_MATCH_LEADING_PATHSPEC); + matches_how = match_pathspec_with_flags(istate, pathspec, + dirname, len, + 0 /* prefix */, + NULL /* seen */, + DO_MATCH_LEADING_PATHSPEC); if (!matches_how) return path_none; } @@ -2120,9 +2136,9 @@ static enum path_treatment treat_path(struct dir_struct *dir, if (excluded) return path_excluded; if (pathspec && - !do_match_pathspec(istate, pathspec, path->buf, path->len, - 0 /* prefix */, NULL /* seen */, - 0 /* flags */)) + !match_pathspec(istate, pathspec, path->buf, path->len, + 0 /* prefix */, NULL /* seen */, + 0 /* is_dir */)) return path_none; return path_untracked; } diff --git a/t/t6132-pathspec-exclude.sh b/t/t6132-pathspec-exclude.sh index 2462b19ddd..30328b87f0 100755 --- a/t/t6132-pathspec-exclude.sh +++ b/t/t6132-pathspec-exclude.sh @@ -211,4 +211,37 @@ test_expect_success 't_e_i() exclude case #8' ' ) ' +test_expect_success 'grep --untracked PATTERN' ' + # This test is not an actual test of exclude patterns, rather it + # is here solely to ensure that if any tests are inserted, deleted, or + # changed above, that we still have untracked files with the expected + # contents for the NEXT two tests. + cat <<-\EOF >expect-grep && + actual + expect + sub/actual + sub/expect + EOF + git grep -l --untracked file -- >actual-grep && + test_cmp expect-grep actual-grep +' + +test_expect_success 'grep --untracked PATTERN :(exclude)DIR' ' + cat <<-\EOF >expect-grep && + actual + expect + EOF + git grep -l --untracked file -- ":(exclude)sub" >actual-grep && + test_cmp expect-grep actual-grep +' + +test_expect_success 'grep --untracked PATTERN :(exclude)*FILE' ' + cat <<-\EOF >expect-grep && + actual + sub/actual + EOF + git grep -l --untracked file -- ":(exclude)*expect" >actual-grep && + test_cmp expect-grep actual-grep +' + test_done |