mirror of
https://github.com/git/git
synced 2024-09-13 05:14:36 +00:00
Merge branch 'nd/exclusion-regression-fix' into maint
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"
This commit is contained in:
commit
9496acc144
|
@ -82,12 +82,12 @@ PATTERN FORMAT
|
||||||
|
|
||||||
- An optional prefix "`!`" which negates the pattern; any
|
- An optional prefix "`!`" which negates the pattern; any
|
||||||
matching file excluded by a previous pattern will become
|
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
|
Put a backslash ("`\`") in front of the first "`!`" for patterns
|
||||||
that begin with a literal "`!`", for example, "`\!important!.txt`".
|
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
|
- If the pattern ends with a slash, it is removed for the
|
||||||
purpose of the following description, but it would only find
|
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
|
To stop tracking a file that is currently tracked, use
|
||||||
'git rm --cached'.
|
'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
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
|
74
dir.c
74
dir.c
|
@ -880,25 +880,6 @@ int match_pathname(const char *pathname, int pathlen,
|
||||||
*/
|
*/
|
||||||
if (!patternlen && !namelen)
|
if (!patternlen && !namelen)
|
||||||
return 1;
|
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,
|
return fnmatch_icase_mem(pattern, patternlen,
|
||||||
|
@ -906,48 +887,6 @@ int match_pathname(const char *pathname, int pathlen,
|
||||||
WM_PATHNAME) == 0;
|
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
|
* 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
|
* 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_list *el)
|
||||||
{
|
{
|
||||||
struct exclude *exc = NULL; /* undecided */
|
struct exclude *exc = NULL; /* undecided */
|
||||||
int i, matched_negative_path = 0;
|
int i;
|
||||||
|
|
||||||
if (!el->nr)
|
if (!el->nr)
|
||||||
return NULL; /* undefined */
|
return NULL; /* undefined */
|
||||||
|
@ -996,18 +935,7 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
|
||||||
exc = x;
|
exc = x;
|
||||||
break;
|
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;
|
return exc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -305,29 +305,4 @@ test_expect_success 'ls-files with "**" patterns and no slashes' '
|
||||||
test_cmp expect actual
|
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
|
test_done
|
||||||
|
|
Loading…
Reference in a new issue