Skip to content

Commit 8c72236

Browse files
pcloudsgitster
authored andcommitted
Revert "dir.c: don't exclude whole dir prematurely if neg pattern may match"
This reverts commit 57534ee. The feature added in that commit requires that patterns behave the same way from anywhere. But some patterns can behave differently depending on current "working" directory. The conditions to catch and avoid these patterns are too loose. The untracked listing[1] and sparse-checkout selection[2] can become incorrect as a result. [1] http://article.gmane.org/gmane.comp.version-control.git/283520 [2] http://article.gmane.org/gmane.comp.version-control.git/283532 Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 57534ee commit 8c72236

File tree

3 files changed

+5
-117
lines changed

3 files changed

+5
-117
lines changed

Documentation/gitignore.txt

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,12 @@ PATTERN FORMAT
8282

8383
- An optional prefix "`!`" which negates the pattern; any
8484
matching file excluded by a previous pattern will become
85-
included again.
85+
included again. It is not possible to re-include a file if a parent
86+
directory of that file is excluded. Git doesn't list excluded
87+
directories for performance reasons, so any patterns on contained
88+
files have no effect, no matter where they are defined.
8689
Put a backslash ("`\`") in front of the first "`!`" for patterns
8790
that begin with a literal "`!`", for example, "`\!important!.txt`".
88-
It is possible to re-include a file if a parent directory of that
89-
file is excluded if certain conditions are met. See section NOTES
90-
for detail.
9191

9292
- If the pattern ends with a slash, it is removed for the
9393
purpose of the following description, but it would only find
@@ -141,21 +141,6 @@ not tracked by Git remain untracked.
141141
To stop tracking a file that is currently tracked, use
142142
'git rm --cached'.
143143

144-
To re-include files or directories when their parent directory is
145-
excluded, the following conditions must be met:
146-
147-
- The rules to exclude a directory and re-include a subset back must
148-
be in the same .gitignore file.
149-
150-
- The directory part in the re-include rules must be literal (i.e. no
151-
wildcards)
152-
153-
- The rules to exclude the parent directory must not end with a
154-
trailing slash.
155-
156-
- The rules to exclude the parent directory must have at least one
157-
slash.
158-
159144
EXAMPLES
160145
--------
161146

dir.c

Lines changed: 1 addition & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -733,74 +733,13 @@ int match_pathname(const char *pathname, int pathlen,
733733
*/
734734
if (!patternlen && !namelen)
735735
return 1;
736-
/*
737-
* This can happen when we ignore some exclude rules
738-
* on directories in other to see if negative rules
739-
* may match. E.g.
740-
*
741-
* /abc
742-
* !/abc/def/ghi
743-
*
744-
* The pattern of interest is "/abc". On the first
745-
* try, we should match path "abc" with this pattern
746-
* in the "if" statement right above, but the caller
747-
* ignores it.
748-
*
749-
* On the second try with paths within "abc",
750-
* e.g. "abc/xyz", we come here and try to match it
751-
* with "/abc".
752-
*/
753-
if (!patternlen && namelen && *name == '/')
754-
return 1;
755736
}
756737

757738
return fnmatch_icase_mem(pattern, patternlen,
758739
name, namelen,
759740
WM_PATHNAME) == 0;
760741
}
761742

762-
/*
763-
* Return non-zero if pathname is a directory and an ancestor of the
764-
* literal path in a (negative) pattern. This is used to keep
765-
* descending in "foo" and "foo/bar" when the pattern is
766-
* "!foo/bar/.gitignore". "foo/notbar" will not be descended however.
767-
*/
768-
static int match_neg_path(const char *pathname, int pathlen, int *dtype,
769-
const char *base, int baselen,
770-
const char *pattern, int prefix, int patternlen,
771-
int flags)
772-
{
773-
assert((flags & EXC_FLAG_NEGATIVE) && !(flags & EXC_FLAG_NODIR));
774-
775-
if (*dtype == DT_UNKNOWN)
776-
*dtype = get_dtype(NULL, pathname, pathlen);
777-
if (*dtype != DT_DIR)
778-
return 0;
779-
780-
if (*pattern == '/') {
781-
pattern++;
782-
patternlen--;
783-
prefix--;
784-
}
785-
786-
if (baselen) {
787-
if (((pathlen < baselen && base[pathlen] == '/') ||
788-
pathlen == baselen) &&
789-
!strncmp_icase(pathname, base, pathlen))
790-
return 1;
791-
pathname += baselen + 1;
792-
pathlen -= baselen + 1;
793-
}
794-
795-
796-
if (prefix &&
797-
((pathlen < prefix && pattern[pathlen] == '/') &&
798-
!strncmp_icase(pathname, pattern, pathlen)))
799-
return 1;
800-
801-
return 0;
802-
}
803-
804743
/*
805744
* Scan the given exclude list in reverse to see whether pathname
806745
* should be ignored. The first match (i.e. the last on the list), if
@@ -814,7 +753,7 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
814753
struct exclude_list *el)
815754
{
816755
struct exclude *exc = NULL; /* undecided */
817-
int i, matched_negative_path = 0;
756+
int i;
818757

819758
if (!el->nr)
820759
return NULL; /* undefined */
@@ -849,18 +788,7 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
849788
exc = x;
850789
break;
851790
}
852-
853-
if ((x->flags & EXC_FLAG_NEGATIVE) && !matched_negative_path &&
854-
match_neg_path(pathname, pathlen, dtype, x->base,
855-
x->baselen ? x->baselen - 1 : 0,
856-
exclude, prefix, x->patternlen, x->flags))
857-
matched_negative_path = 1;
858791
}
859-
if (exc &&
860-
!(exc->flags & EXC_FLAG_NEGATIVE) &&
861-
!(exc->flags & EXC_FLAG_NODIR) &&
862-
matched_negative_path)
863-
exc = NULL;
864792
return exc;
865793
}
866794

t/t3001-ls-files-others-exclude.sh

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -305,29 +305,4 @@ test_expect_success 'ls-files with "**" patterns and no slashes' '
305305
test_cmp expect actual
306306
'
307307

308-
test_expect_success 'negative patterns' '
309-
git init reinclude &&
310-
(
311-
cd reinclude &&
312-
cat >.gitignore <<-\EOF &&
313-
/fooo
314-
/foo
315-
!foo/bar/bar
316-
EOF
317-
mkdir fooo &&
318-
cat >fooo/.gitignore <<-\EOF &&
319-
!/*
320-
EOF
321-
mkdir -p foo/bar &&
322-
touch abc foo/def foo/bar/ghi foo/bar/bar &&
323-
git ls-files -o --exclude-standard >../actual &&
324-
cat >../expected <<-\EOF &&
325-
.gitignore
326-
abc
327-
foo/bar/bar
328-
EOF
329-
test_cmp ../expected ../actual
330-
)
331-
'
332-
333308
test_done

0 commit comments

Comments
 (0)