Skip to content

Commit 5cee349

Browse files
committed
Revert "Merge branch 'nd/exclusion-regression-fix'"
This reverts commit 5e57f9c, reversing changes made to e79112d. We will be postponing nd/exclusion-regression-fix topic to later cycle.
1 parent 8ad3cb0 commit 5cee349

File tree

7 files changed

+12
-378
lines changed

7 files changed

+12
-378
lines changed

Documentation/git-check-ignore.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ SEE ALSO
114114
linkgit:gitignore[5]
115115
linkgit:gitconfig[5]
116116
linkgit:git-ls-files[1]
117-
GIT_TRACE_EXCLUDE in linkgit:git[1]
118117

119118
GIT
120119
---

Documentation/git.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,11 +1069,6 @@ of clones and fetches.
10691069
cloning of shallow repositories.
10701070
See 'GIT_TRACE' for available trace output options.
10711071

1072-
'GIT_TRACE_EXCLUDE'::
1073-
Enables trace messages that can help debugging .gitignore
1074-
processing. See 'GIT_TRACE' for available trace output
1075-
options.
1076-
10771072
'GIT_LITERAL_PATHSPECS'::
10781073
Setting this variable to `1` will cause Git to treat all
10791074
pathspecs literally, rather than as glob patterns. For example,

Documentation/gitignore.txt

Lines changed: 4 additions & 13 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,15 +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-
153144
EXAMPLES
154145
--------
155146

dir.c

Lines changed: 3 additions & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
5353
int check_only, const struct path_simplify *simplify);
5454
static int get_dtype(struct dirent *de, const char *path, int len);
5555

56-
static struct trace_key trace_exclude = TRACE_KEY_INIT(EXCLUDE);
57-
5856
/* helper string functions with support for the ignore_case flag */
5957
int strcmp_icase(const char *a, const char *b)
6058
{
@@ -516,7 +514,6 @@ void add_exclude(const char *string, const char *base,
516514
x->baselen = baselen;
517515
x->flags = flags;
518516
x->srcpos = srcpos;
519-
string_list_init(&x->sticky_paths, 1);
520517
ALLOC_GROW(el->excludes, el->nr + 1, el->alloc);
521518
el->excludes[el->nr++] = x;
522519
x->el = el;
@@ -557,10 +554,8 @@ void clear_exclude_list(struct exclude_list *el)
557554
{
558555
int i;
559556

560-
for (i = 0; i < el->nr; i++) {
561-
string_list_clear(&el->excludes[i]->sticky_paths, 0);
557+
for (i = 0; i < el->nr; i++)
562558
free(el->excludes[i]);
563-
}
564559
free(el->excludes);
565560
free(el->filebuf);
566561

@@ -875,7 +870,7 @@ int match_pathname(const char *pathname, int pathlen,
875870
* then our prefix match is all we need; we
876871
* do not need to call fnmatch at all.
877872
*/
878-
if (!patternlen && (!namelen || *name == '/'))
873+
if (!patternlen && !namelen)
879874
return 1;
880875
}
881876

@@ -884,113 +879,6 @@ int match_pathname(const char *pathname, int pathlen,
884879
WM_PATHNAME) == 0;
885880
}
886881

887-
static void add_sticky(struct exclude *exc, const char *pathname, int pathlen)
888-
{
889-
struct strbuf sb = STRBUF_INIT;
890-
int i;
891-
892-
for (i = exc->sticky_paths.nr - 1; i >= 0; i--) {
893-
const char *sticky = exc->sticky_paths.items[i].string;
894-
int len = strlen(sticky);
895-
896-
if (pathlen < len && sticky[pathlen] == '/' &&
897-
!strncmp(pathname, sticky, pathlen))
898-
return;
899-
}
900-
901-
strbuf_add(&sb, pathname, pathlen);
902-
string_list_append_nodup(&exc->sticky_paths, strbuf_detach(&sb, NULL));
903-
}
904-
905-
static int match_sticky(struct exclude *exc, const char *pathname, int pathlen, int dtype)
906-
{
907-
int i;
908-
909-
for (i = exc->sticky_paths.nr - 1; i >= 0; i--) {
910-
const char *sticky = exc->sticky_paths.items[i].string;
911-
int len = strlen(sticky);
912-
913-
if (pathlen == len && dtype == DT_DIR &&
914-
!strncmp(pathname, sticky, len))
915-
return 1;
916-
917-
if (pathlen > len && pathname[len] == '/' &&
918-
!strncmp(pathname, sticky, len))
919-
return 1;
920-
}
921-
922-
return 0;
923-
}
924-
925-
static inline int different_decisions(const struct exclude *a,
926-
const struct exclude *b)
927-
{
928-
return (a->flags & EXC_FLAG_NEGATIVE) != (b->flags & EXC_FLAG_NEGATIVE);
929-
}
930-
931-
/*
932-
* Return non-zero if pathname is a directory and an ancestor of the
933-
* literal path in a pattern.
934-
*/
935-
static int match_directory_part(const char *pathname, int pathlen,
936-
int *dtype, struct exclude *x)
937-
{
938-
const char *base = x->base;
939-
int baselen = x->baselen ? x->baselen - 1 : 0;
940-
const char *pattern = x->pattern;
941-
int prefix = x->nowildcardlen;
942-
int patternlen = x->patternlen;
943-
944-
if (*dtype == DT_UNKNOWN)
945-
*dtype = get_dtype(NULL, pathname, pathlen);
946-
if (*dtype != DT_DIR)
947-
return 0;
948-
949-
if (*pattern == '/') {
950-
pattern++;
951-
patternlen--;
952-
prefix--;
953-
}
954-
955-
if (baselen) {
956-
if (((pathlen < baselen && base[pathlen] == '/') ||
957-
pathlen == baselen) &&
958-
!strncmp_icase(pathname, base, pathlen))
959-
return 1;
960-
pathname += baselen + 1;
961-
pathlen -= baselen + 1;
962-
}
963-
964-
965-
if (prefix &&
966-
(((pathlen < prefix && pattern[pathlen] == '/') ||
967-
pathlen == prefix) &&
968-
!strncmp_icase(pathname, pattern, pathlen)))
969-
return 1;
970-
971-
return 0;
972-
}
973-
974-
static struct exclude *should_descend(const char *pathname, int pathlen,
975-
int *dtype, struct exclude_list *el,
976-
struct exclude *exc)
977-
{
978-
int i;
979-
980-
for (i = el->nr - 1; 0 <= i; i--) {
981-
struct exclude *x = el->excludes[i];
982-
983-
if (x == exc)
984-
break;
985-
986-
if (!(x->flags & EXC_FLAG_NODIR) &&
987-
different_decisions(x, exc) &&
988-
match_directory_part(pathname, pathlen, dtype, x))
989-
return x;
990-
}
991-
return NULL;
992-
}
993-
994882
/*
995883
* Scan the given exclude list in reverse to see whether pathname
996884
* should be ignored. The first match (i.e. the last on the list), if
@@ -1004,32 +892,16 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
1004892
struct exclude_list *el)
1005893
{
1006894
struct exclude *exc = NULL; /* undecided */
1007-
int i, maybe_descend = 0;
895+
int i;
1008896

1009897
if (!el->nr)
1010898
return NULL; /* undefined */
1011899

1012-
trace_printf_key(&trace_exclude, "exclude: from %s\n", el->src);
1013-
1014900
for (i = el->nr - 1; 0 <= i; i--) {
1015901
struct exclude *x = el->excludes[i];
1016902
const char *exclude = x->pattern;
1017903
int prefix = x->nowildcardlen;
1018904

1019-
if (!maybe_descend && i < el->nr - 1 &&
1020-
different_decisions(x, el->excludes[i+1]))
1021-
maybe_descend = 1;
1022-
1023-
if (x->sticky_paths.nr) {
1024-
if (*dtype == DT_UNKNOWN)
1025-
*dtype = get_dtype(NULL, pathname, pathlen);
1026-
if (match_sticky(x, pathname, pathlen, *dtype)) {
1027-
exc = x;
1028-
break;
1029-
}
1030-
continue;
1031-
}
1032-
1033905
if (x->flags & EXC_FLAG_MUSTBEDIR) {
1034906
if (*dtype == DT_UNKNOWN)
1035907
*dtype = get_dtype(NULL, pathname, pathlen);
@@ -1056,45 +928,6 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
1056928
break;
1057929
}
1058930
}
1059-
1060-
if (!exc) {
1061-
trace_printf_key(&trace_exclude, "exclude: %.*s => n/a\n",
1062-
pathlen, pathname);
1063-
return NULL;
1064-
}
1065-
1066-
/*
1067-
* We have found a matching pattern "exc" that may exclude whole
1068-
* directory. We also found that there may be a pattern that matches
1069-
* something inside the directory and reincludes stuff.
1070-
*
1071-
* Go through the patterns again, find that pattern and double check.
1072-
* If it's true, return "undecided" and keep descending in. "exc" is
1073-
* marked sticky so that it continues to match inside the directory.
1074-
*/
1075-
if (!(exc->flags & EXC_FLAG_NEGATIVE) && maybe_descend) {
1076-
struct exclude *x;
1077-
1078-
if (*dtype == DT_UNKNOWN)
1079-
*dtype = get_dtype(NULL, pathname, pathlen);
1080-
1081-
if (*dtype == DT_DIR &&
1082-
(x = should_descend(pathname, pathlen, dtype, el, exc))) {
1083-
add_sticky(exc, pathname, pathlen);
1084-
trace_printf_key(&trace_exclude,
1085-
"exclude: %.*s vs %s at line %d => %s,"
1086-
" forced open by %s at line %d => n/a\n",
1087-
pathlen, pathname, exc->pattern, exc->srcpos,
1088-
exc->flags & EXC_FLAG_NEGATIVE ? "no" : "yes",
1089-
x->pattern, x->srcpos);
1090-
return NULL;
1091-
}
1092-
}
1093-
1094-
trace_printf_key(&trace_exclude, "exclude: %.*s vs %s at line %d => %s%s\n",
1095-
pathlen, pathname, exc->pattern, exc->srcpos,
1096-
exc->flags & EXC_FLAG_NEGATIVE ? "no" : "yes",
1097-
exc->sticky_paths.nr ? " (stuck)" : "");
1098931
return exc;
1099932
}
1100933

@@ -1840,13 +1673,9 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
18401673
struct cached_dir cdir;
18411674
enum path_treatment state, subdir_state, dir_state = path_none;
18421675
struct strbuf path = STRBUF_INIT;
1843-
static int level = 0;
18441676

18451677
strbuf_add(&path, base, baselen);
18461678

1847-
trace_printf_key(&trace_exclude, "exclude: [%d] enter '%.*s'\n",
1848-
level++, baselen, base);
1849-
18501679
if (open_cached_dir(&cdir, dir, untracked, &path, check_only))
18511680
goto out;
18521681

@@ -1910,8 +1739,6 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
19101739
}
19111740
close_cached_dir(&cdir);
19121741
out:
1913-
trace_printf_key(&trace_exclude, "exclude: [%d] leave '%.*s'\n",
1914-
--level, baselen, base);
19151742
strbuf_release(&path);
19161743

19171744
return dir_state;
@@ -2148,25 +1975,6 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
21481975
return root;
21491976
}
21501977

2151-
static void clear_sticky(struct dir_struct *dir)
2152-
{
2153-
struct exclude_list_group *g;
2154-
struct exclude_list *el;
2155-
struct exclude *x;
2156-
int i, j, k;
2157-
2158-
for (i = EXC_CMDL; i <= EXC_FILE; i++) {
2159-
g = &dir->exclude_list_group[i];
2160-
for (j = g->nr - 1; j >= 0; j--) {
2161-
el = &g->el[j];
2162-
for (k = el->nr - 1; 0 <= k; k--) {
2163-
x = el->excludes[k];
2164-
string_list_clear(&x->sticky_paths, 0);
2165-
}
2166-
}
2167-
}
2168-
}
2169-
21701978
int read_directory(struct dir_struct *dir, const char *path, int len, const struct pathspec *pathspec)
21711979
{
21721980
struct path_simplify *simplify;
@@ -2187,12 +1995,6 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru
21871995
if (has_symlink_leading_path(path, len))
21881996
return dir->nr;
21891997

2190-
/*
2191-
* Stay on the safe side. if read_directory() has run once on
2192-
* "dir", some sticky flag may have been left. Clear them all.
2193-
*/
2194-
clear_sticky(dir);
2195-
21961998
/*
21971999
* exclude patterns are treated like positive ones in
21982000
* create_simplify. Usually exclude patterns should be a

dir.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
/* See Documentation/technical/api-directory-listing.txt */
55

66
#include "strbuf.h"
7-
#include "string-list.h"
87

98
struct dir_entry {
109
unsigned int len;
@@ -35,8 +34,6 @@ struct exclude {
3534
* and from -1 decrementing for patterns from CLI args.
3635
*/
3736
int srcpos;
38-
39-
struct string_list sticky_paths;
4037
};
4138

4239
/*

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,13 @@ test_expect_success 'negated exclude matches can override previous ones' '
175175
grep "^a.1" output
176176
'
177177

178-
test_expect_success 'excluded directory does not override content patterns' '
178+
test_expect_success 'excluded directory overrides content patterns' '
179179
180180
git ls-files --others --exclude="one" --exclude="!one/a.1" >output &&
181-
grep "^one/a.1" output
181+
if grep "^one/a.1" output
182+
then
183+
false
184+
fi
182185
'
183186

184187
test_expect_success 'negated directory doesn'\''t affect content patterns' '

0 commit comments

Comments
 (0)