Revert "Merge branch 'nd/exclusion-regression-fix'"
This reverts commit 5e57f9c3dfe7dd44a1b56bb5b3327d7a1356ec7c, reversing changes made to e79112d21024beb997951381db21a70b087d459d. We will be postponing nd/exclusion-regression-fix topic to later cycle.
Junio C Hamano committed
Mar 18, 2016 at 11:06 UTC
5cee349370bd2dce48d0d653ab4ce99bb79a3415
7 files changed
+12
-378
Documentation/git-check-ignore.txt
-1
@@ -114,7 +114,6 @@ SEE ALSO
114
linkgit:gitignore[5]
115
linkgit:gitconfig[5]
116
linkgit:git-ls-files[1]
117
-GIT_TRACE_EXCLUDE in linkgit:git[1]
117
118
GIT
119
---
Documentation/git.txt
-5
@@ -1069,11 +1069,6 @@ of clones and fetches.
1069
cloning of shallow repositories.
1070
See 'GIT_TRACE' for available trace output options.
1071
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
-
1072
'GIT_LITERAL_PATHSPECS'::
1073
Setting this variable to `1` will cause Git to treat all
1074
pathspecs literally, rather than as glob patterns. For example,
Documentation/gitignore.txt
+4
-13
@@ -82,12 +82,12 @@ PATTERN FORMAT
82
83
- An optional prefix "`!`" which negates the pattern; any
84
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.
89
Put a backslash ("`\`") in front of the first "`!`" for patterns
90
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.
91
92
- If the pattern ends with a slash, it is removed for the
93
purpose of the following description, but it would only find
@@ -141,15 +141,6 @@ not tracked by Git remain untracked.
141
To stop tracking a file that is currently tracked, use
142
'git rm --cached'.
143
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
-
144
EXAMPLES
145
--------
146
dir.c
+3
-201
@@ -53,8 +53,6 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
53
int check_only, const struct path_simplify *simplify);
54
static int get_dtype(struct dirent *de, const char *path, int len);
55
56
-static struct trace_key trace_exclude = TRACE_KEY_INIT(EXCLUDE);
57
-
56
/* helper string functions with support for the ignore_case flag */
57
int strcmp_icase(const char *a, const char *b)
58
{
@@ -516,7 +514,6 @@ void add_exclude(const char *string, const char *base,
514
x->baselen = baselen;
515
x->flags = flags;
516
x->srcpos = srcpos;
519
- string_list_init(&x->sticky_paths, 1);
517
ALLOC_GROW(el->excludes, el->nr + 1, el->alloc);
518
el->excludes[el->nr++] = x;
519
x->el = el;
@@ -557,10 +554,8 @@ void clear_exclude_list(struct exclude_list *el)
554
{
555
int i;
556
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++)
558
free(el->excludes[i]);
563
- }
559
free(el->excludes);
560
free(el->filebuf);
561
@@ -875,7 +870,7 @@ int match_pathname(const char *pathname, int pathlen,
870
* then our prefix match is all we need; we
871
* do not need to call fnmatch at all.
872
*/
878
- if (!patternlen && (!namelen || *name == '/'))
873
+ if (!patternlen && !namelen)
874
return 1;
875
}
876
@@ -884,113 +879,6 @@ int match_pathname(const char *pathname, int pathlen,
879
WM_PATHNAME) == 0;
880
}
881
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
-
882
/*
883
* Scan the given exclude list in reverse to see whether pathname
884
* 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,
892
struct exclude_list *el)
893
{
894
struct exclude *exc = NULL; /* undecided */
1007
- int i, maybe_descend = 0;
895
+ int i;
896
897
if (!el->nr)
898
return NULL; /* undefined */
899
1012
- trace_printf_key(&trace_exclude, "exclude: from %s\n", el->src);
1013
-
900
for (i = el->nr - 1; 0 <= i; i--) {
901
struct exclude *x = el->excludes[i];
902
const char *exclude = x->pattern;
903
int prefix = x->nowildcardlen;
904
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
-
905
if (x->flags & EXC_FLAG_MUSTBEDIR) {
906
if (*dtype == DT_UNKNOWN)
907
*dtype = get_dtype(NULL, pathname, pathlen);
@@ -1056,45 +928,6 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
928
break;
929
}
930
}
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)" : "");
931
return exc;
932
}
933
@@ -1840,13 +1673,9 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
1673
struct cached_dir cdir;
1674
enum path_treatment state, subdir_state, dir_state = path_none;
1675
struct strbuf path = STRBUF_INIT;
1843
- static int level = 0;
1676
1677
strbuf_add(&path, base, baselen);
1678
1847
- trace_printf_key(&trace_exclude, "exclude: [%d] enter '%.*s'\n",
1848
- level++, baselen, base);
1849
-
1679
if (open_cached_dir(&cdir, dir, untracked, &path, check_only))
1680
goto out;
1681
@@ -1910,8 +1739,6 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
1739
}
1740
close_cached_dir(&cdir);
1741
out:
1913
- trace_printf_key(&trace_exclude, "exclude: [%d] leave '%.*s'\n",
1914
- --level, baselen, base);
1742
strbuf_release(&path);
1743
1744
return dir_state;
@@ -2148,25 +1975,6 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
1975
return root;
1976
}
1977
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
-
1978
int read_directory(struct dir_struct *dir, const char *path, int len, const struct pathspec *pathspec)
1979
{
1980
struct path_simplify *simplify;
@@ -2187,12 +1995,6 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru
1995
if (has_symlink_leading_path(path, len))
1996
return dir->nr;
1997
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
-
1998
/*
1999
* exclude patterns are treated like positive ones in
2000
* create_simplify. Usually exclude patterns should be a
dir.h
-3
@@ -4,7 +4,6 @@
4
/* See Documentation/technical/api-directory-listing.txt */
5
6
#include "strbuf.h"
7
-#include "string-list.h"
7
8
struct dir_entry {
9
unsigned int len;
@@ -35,8 +34,6 @@ struct exclude {
34
* and from -1 decrementing for patterns from CLI args.
35
*/
36
int srcpos;
38
-
39
- struct string_list sticky_paths;
37
};
38
39
/*
t/t3001-ls-files-others-exclude.sh
+5
-2
@@ -175,10 +175,13 @@ test_expect_success 'negated exclude matches can override previous ones' '
175
grep "^a.1" output
176
'
177
178
-test_expect_success 'excluded directory does not override content patterns' '
178
+test_expect_success 'excluded directory overrides content patterns' '
179
180
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
185
'
186
187
test_expect_success 'negated directory doesn'\''t affect content patterns' '
t/t3007-ls-files-other-negative.sh
deleted
-153
@@ -1,153 +0,0 @@
1
-#!/bin/sh
2
-
3
-test_description='test re-include patterns'
4
-
5
-. ./test-lib.sh
6
-
7
-test_expect_success 'setup' '
8
- mkdir -p fooo foo/bar tmp &&
9
- touch abc foo/def foo/bar/ghi foo/bar/bar
10
-'
11
-
12
-test_expect_success 'no match, do not enter subdir and waste cycles' '
13
- cat >.gitignore <<-\EOF &&
14
- /tmp
15
- /foo
16
- !fooo/bar/bar
17
- EOF
18
- GIT_TRACE_EXCLUDE="$(pwd)/tmp/trace" git ls-files -o --exclude-standard >tmp/actual &&
19
- ! grep "enter .foo/.\$" tmp/trace &&
20
- cat >tmp/expected <<-\EOF &&
21
- .gitignore
22
- abc
23
- EOF
24
- test_cmp tmp/expected tmp/actual
25
-'
26
-
27
-test_expect_success 'match, excluded by literal pathname pattern' '
28
- cat >.gitignore <<-\EOF &&
29
- /tmp
30
- /fooo
31
- /foo
32
- !foo/bar/bar
33
- EOF
34
- cat >fooo/.gitignore <<-\EOF &&
35
- !/*
36
- EOF git ls-files -o --exclude-standard >tmp/actual &&
37
- cat >tmp/expected <<-\EOF &&
38
- .gitignore
39
- abc
40
- foo/bar/bar
41
- EOF
42
- test_cmp tmp/expected tmp/actual
43
-'
44
-
45
-test_expect_success 'match, excluded by wildcard pathname pattern' '
46
- cat >.gitignore <<-\EOF &&
47
- /tmp
48
- /fooo
49
- /fo?
50
- !foo/bar/bar
51
- EOF
52
- git ls-files -o --exclude-standard >tmp/actual &&
53
- cat >tmp/expected <<-\EOF &&
54
- .gitignore
55
- abc
56
- foo/bar/bar
57
- EOF
58
- test_cmp tmp/expected tmp/actual
59
-'
60
-
61
-test_expect_success 'match, excluded by literal basename pattern' '
62
- cat >.gitignore <<-\EOF &&
63
- /tmp
64
- /fooo
65
- foo
66
- !foo/bar/bar
67
- EOF
68
- git ls-files -o --exclude-standard >tmp/actual &&
69
- cat >tmp/expected <<-\EOF &&
70
- .gitignore
71
- abc
72
- foo/bar/bar
73
- EOF
74
- test_cmp tmp/expected tmp/actual
75
-'
76
-
77
-test_expect_success 'match, excluded by wildcard basename pattern' '
78
- cat >.gitignore <<-\EOF &&
79
- /tmp
80
- /fooo
81
- fo?
82
- !foo/bar/bar
83
- EOF
84
- git ls-files -o --exclude-standard >tmp/actual &&
85
- cat >tmp/expected <<-\EOF &&
86
- .gitignore
87
- abc
88
- foo/bar/bar
89
- EOF
90
- test_cmp tmp/expected tmp/actual
91
-'
92
-
93
-test_expect_success 'match, excluded by literal mustbedir, basename pattern' '
94
- cat >.gitignore <<-\EOF &&
95
- /tmp
96
- /fooo
97
- foo/
98
- !foo/bar/bar
99
- EOF
100
- git ls-files -o --exclude-standard >tmp/actual &&
101
- cat >tmp/expected <<-\EOF &&
102
- .gitignore
103
- abc
104
- foo/bar/bar
105
- EOF
106
- test_cmp tmp/expected tmp/actual
107
-'
108
-
109
-test_expect_success 'match, excluded by literal mustbedir, pathname pattern' '
110
- cat >.gitignore <<-\EOF &&
111
- /tmp
112
- /fooo
113
- /foo/
114
- !foo/bar/bar
115
- EOF
116
- git ls-files -o --exclude-standard >tmp/actual &&
117
- cat >tmp/expected <<-\EOF &&
118
- .gitignore
119
- abc
120
- foo/bar/bar
121
- EOF
122
- test_cmp tmp/expected tmp/actual
123
-'
124
-
125
-test_expect_success 'prepare for nested negatives' '
126
- cat >.git/info/exclude <<-\EOF &&
127
- /.gitignore
128
- /tmp
129
- /foo
130
- /abc
131
- EOF
132
- git ls-files -o --exclude-standard >tmp/actual &&
133
- test_must_be_empty tmp/actual &&
134
- mkdir -p 1/2/3/4 &&
135
- touch 1/f 1/2/f 1/2/3/f 1/2/3/4/f
136
-'
137
-
138
-test_expect_success 'match, literal pathname, nested negatives' '
139
- cat >.gitignore <<-\EOF &&
140
- /1
141
- !1/2
142
- 1/2/3
143
- !1/2/3/4
144
- EOF
145
- git ls-files -o --exclude-standard >tmp/actual &&
146
- cat >tmp/expected <<-\EOF &&
147
- 1/2/3/4/f
148
- 1/2/f
149
- EOF
150
- test_cmp tmp/expected tmp/actual
151
-'
152
-
153
-test_done