From: Junio C Hamano Date: Wed, 20 Jan 2016 19:43:33 +0000 (-0800) Subject: Merge branch 'nd/exclusion-regression-fix' X-Git-Tag: v2.8.0-rc0~110 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/76b620d8166bf4cc7cadbc61f9927799ceea9162?hp=ceef512e797115ae581cfbfd220334e20f1c7b28 Merge branch 'nd/exclusion-regression-fix' The ignore mechanism saw a few regressions around untracked file listing and sparse checkout selection areas in 2.7.0; the change that is responsible for the regression has been reverted. * nd/exclusion-regression-fix: Revert "dir.c: don't exclude whole dir prematurely if neg pattern may match" --- diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt index 79a1948a0b..473623d631 100644 --- a/Documentation/gitignore.txt +++ b/Documentation/gitignore.txt @@ -82,12 +82,12 @@ PATTERN FORMAT - An optional prefix "`!`" which negates the pattern; any matching file excluded by a previous pattern will become - included again. + included again. It is not possible to re-include a file if a parent + directory of that file is excluded. Git doesn't list excluded + directories for performance reasons, so any patterns on contained + files have no effect, no matter where they are defined. Put a backslash ("`\`") in front of the first "`!`" for patterns that begin with a literal "`!`", for example, "`\!important!.txt`". - It is possible to re-include a file if a parent directory of that - file is excluded if certain conditions are met. See section NOTES - for detail. - If the pattern ends with a slash, it is removed for the purpose of the following description, but it would only find @@ -141,21 +141,6 @@ not tracked by Git remain untracked. To stop tracking a file that is currently tracked, use 'git rm --cached'. -To re-include files or directories when their parent directory is -excluded, the following conditions must be met: - - - The rules to exclude a directory and re-include a subset back must - be in the same .gitignore file. - - - The directory part in the re-include rules must be literal (i.e. no - wildcards) - - - The rules to exclude the parent directory must not end with a - trailing slash. - - - The rules to exclude the parent directory must have at least one - slash. - EXAMPLES -------- diff --git a/dir.c b/dir.c index b8b4576cd2..29aec12487 100644 --- a/dir.c +++ b/dir.c @@ -880,25 +880,6 @@ int match_pathname(const char *pathname, int pathlen, */ if (!patternlen && !namelen) return 1; - /* - * This can happen when we ignore some exclude rules - * on directories in other to see if negative rules - * may match. E.g. - * - * /abc - * !/abc/def/ghi - * - * The pattern of interest is "/abc". On the first - * try, we should match path "abc" with this pattern - * in the "if" statement right above, but the caller - * ignores it. - * - * On the second try with paths within "abc", - * e.g. "abc/xyz", we come here and try to match it - * with "/abc". - */ - if (!patternlen && namelen && *name == '/') - return 1; } return fnmatch_icase_mem(pattern, patternlen, @@ -906,48 +887,6 @@ int match_pathname(const char *pathname, int pathlen, WM_PATHNAME) == 0; } -/* - * Return non-zero if pathname is a directory and an ancestor of the - * literal path in a (negative) pattern. This is used to keep - * descending in "foo" and "foo/bar" when the pattern is - * "!foo/bar/.gitignore". "foo/notbar" will not be descended however. - */ -static int match_neg_path(const char *pathname, int pathlen, int *dtype, - const char *base, int baselen, - const char *pattern, int prefix, int patternlen, - int flags) -{ - assert((flags & EXC_FLAG_NEGATIVE) && !(flags & EXC_FLAG_NODIR)); - - if (*dtype == DT_UNKNOWN) - *dtype = get_dtype(NULL, pathname, pathlen); - if (*dtype != DT_DIR) - return 0; - - if (*pattern == '/') { - pattern++; - patternlen--; - prefix--; - } - - if (baselen) { - if (((pathlen < baselen && base[pathlen] == '/') || - pathlen == baselen) && - !strncmp_icase(pathname, base, pathlen)) - return 1; - pathname += baselen + 1; - pathlen -= baselen + 1; - } - - - if (prefix && - ((pathlen < prefix && pattern[pathlen] == '/') && - !strncmp_icase(pathname, pattern, pathlen))) - return 1; - - return 0; -} - /* * Scan the given exclude list in reverse to see whether pathname * should be ignored. The first match (i.e. the last on the list), if @@ -961,7 +900,7 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname, struct exclude_list *el) { struct exclude *exc = NULL; /* undecided */ - int i, matched_negative_path = 0; + int i; if (!el->nr) return NULL; /* undefined */ @@ -996,18 +935,7 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname, exc = x; break; } - - if ((x->flags & EXC_FLAG_NEGATIVE) && !matched_negative_path && - match_neg_path(pathname, pathlen, dtype, x->base, - x->baselen ? x->baselen - 1 : 0, - exclude, prefix, x->patternlen, x->flags)) - matched_negative_path = 1; - } - if (exc && - !(exc->flags & EXC_FLAG_NEGATIVE) && - !(exc->flags & EXC_FLAG_NODIR) && - matched_negative_path) - exc = NULL; + } return exc; } diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh index da257c020f..3fc484e8c3 100755 --- a/t/t3001-ls-files-others-exclude.sh +++ b/t/t3001-ls-files-others-exclude.sh @@ -305,29 +305,4 @@ test_expect_success 'ls-files with "**" patterns and no slashes' ' test_cmp expect actual ' -test_expect_success 'negative patterns' ' - git init reinclude && - ( - cd reinclude && - cat >.gitignore <<-\EOF && - /fooo - /foo - !foo/bar/bar - EOF - mkdir fooo && - cat >fooo/.gitignore <<-\EOF && - !/* - EOF - mkdir -p foo/bar && - touch abc foo/def foo/bar/ghi foo/bar/bar && - git ls-files -o --exclude-standard >../actual && - cat >../expected <<-\EOF && - .gitignore - abc - foo/bar/bar - EOF - test_cmp ../expected ../actual - ) -' - test_done