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