@@ -53,6 +53,8 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
5353 int check_only , const struct path_simplify * simplify );
5454static int get_dtype (struct dirent * de , const char * path , int len );
5555
56+ static struct trace_key trace_exclude = TRACE_KEY_INIT (EXCLUDE );
57+
5658/* helper string functions with support for the ignore_case flag */
5759int strcmp_icase (const char * a , const char * b )
5860{
@@ -519,6 +521,7 @@ void add_exclude(const char *string, const char *base,
519521 x -> baselen = baselen ;
520522 x -> flags = flags ;
521523 x -> srcpos = srcpos ;
524+ string_list_init (& x -> sticky_paths , 1 );
522525 ALLOC_GROW (el -> excludes , el -> nr + 1 , el -> alloc );
523526 el -> excludes [el -> nr ++ ] = x ;
524527 x -> el = el ;
@@ -559,8 +562,10 @@ void clear_exclude_list(struct exclude_list *el)
559562{
560563 int i ;
561564
562- for (i = 0 ; i < el -> nr ; i ++ )
565+ for (i = 0 ; i < el -> nr ; i ++ ) {
566+ string_list_clear (& el -> excludes [i ]-> sticky_paths , 0 );
563567 free (el -> excludes [i ]);
568+ }
564569 free (el -> excludes );
565570 free (el -> filebuf );
566571
@@ -878,7 +883,7 @@ int match_pathname(const char *pathname, int pathlen,
878883 * then our prefix match is all we need; we
879884 * do not need to call fnmatch at all.
880885 */
881- if (!patternlen && !namelen )
886+ if (!patternlen && ( !namelen || * name == '/' ) )
882887 return 1 ;
883888 }
884889
@@ -887,6 +892,113 @@ int match_pathname(const char *pathname, int pathlen,
887892 WM_PATHNAME ) == 0 ;
888893}
889894
895+ static void add_sticky (struct exclude * exc , const char * pathname , int pathlen )
896+ {
897+ struct strbuf sb = STRBUF_INIT ;
898+ int i ;
899+
900+ for (i = exc -> sticky_paths .nr - 1 ; i >= 0 ; i -- ) {
901+ const char * sticky = exc -> sticky_paths .items [i ].string ;
902+ int len = strlen (sticky );
903+
904+ if (pathlen < len && sticky [pathlen ] == '/' &&
905+ !strncmp (pathname , sticky , pathlen ))
906+ return ;
907+ }
908+
909+ strbuf_add (& sb , pathname , pathlen );
910+ string_list_append_nodup (& exc -> sticky_paths , strbuf_detach (& sb , NULL ));
911+ }
912+
913+ static int match_sticky (struct exclude * exc , const char * pathname , int pathlen , int dtype )
914+ {
915+ int i ;
916+
917+ for (i = exc -> sticky_paths .nr - 1 ; i >= 0 ; i -- ) {
918+ const char * sticky = exc -> sticky_paths .items [i ].string ;
919+ int len = strlen (sticky );
920+
921+ if (pathlen == len && dtype == DT_DIR &&
922+ !strncmp (pathname , sticky , len ))
923+ return 1 ;
924+
925+ if (pathlen > len && pathname [len ] == '/' &&
926+ !strncmp (pathname , sticky , len ))
927+ return 1 ;
928+ }
929+
930+ return 0 ;
931+ }
932+
933+ static inline int different_decisions (const struct exclude * a ,
934+ const struct exclude * b )
935+ {
936+ return (a -> flags & EXC_FLAG_NEGATIVE ) != (b -> flags & EXC_FLAG_NEGATIVE );
937+ }
938+
939+ /*
940+ * Return non-zero if pathname is a directory and an ancestor of the
941+ * literal path in a pattern.
942+ */
943+ static int match_directory_part (const char * pathname , int pathlen ,
944+ int * dtype , struct exclude * x )
945+ {
946+ const char * base = x -> base ;
947+ int baselen = x -> baselen ? x -> baselen - 1 : 0 ;
948+ const char * pattern = x -> pattern ;
949+ int prefix = x -> nowildcardlen ;
950+ int patternlen = x -> patternlen ;
951+
952+ if (* dtype == DT_UNKNOWN )
953+ * dtype = get_dtype (NULL , pathname , pathlen );
954+ if (* dtype != DT_DIR )
955+ return 0 ;
956+
957+ if (* pattern == '/' ) {
958+ pattern ++ ;
959+ patternlen -- ;
960+ prefix -- ;
961+ }
962+
963+ if (baselen ) {
964+ if (((pathlen < baselen && base [pathlen ] == '/' ) ||
965+ pathlen == baselen ) &&
966+ !strncmp_icase (pathname , base , pathlen ))
967+ return 1 ;
968+ pathname += baselen + 1 ;
969+ pathlen -= baselen + 1 ;
970+ }
971+
972+
973+ if (prefix &&
974+ (((pathlen < prefix && pattern [pathlen ] == '/' ) ||
975+ pathlen == prefix ) &&
976+ !strncmp_icase (pathname , pattern , pathlen )))
977+ return 1 ;
978+
979+ return 0 ;
980+ }
981+
982+ static struct exclude * should_descend (const char * pathname , int pathlen ,
983+ int * dtype , struct exclude_list * el ,
984+ struct exclude * exc )
985+ {
986+ int i ;
987+
988+ for (i = el -> nr - 1 ; 0 <= i ; i -- ) {
989+ struct exclude * x = el -> excludes [i ];
990+
991+ if (x == exc )
992+ break ;
993+
994+ if (!(x -> flags & EXC_FLAG_NODIR ) &&
995+ different_decisions (x , exc ) &&
996+ match_directory_part (pathname , pathlen , dtype , x ))
997+ return x ;
998+ }
999+ return NULL ;
1000+ }
1001+
8901002/*
8911003 * Scan the given exclude list in reverse to see whether pathname
8921004 * should be ignored. The first match (i.e. the last on the list), if
@@ -900,16 +1012,32 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
9001012 struct exclude_list * el )
9011013{
9021014 struct exclude * exc = NULL ; /* undecided */
903- int i ;
1015+ int i , maybe_descend = 0 ;
9041016
9051017 if (!el -> nr )
9061018 return NULL ; /* undefined */
9071019
1020+ trace_printf_key (& trace_exclude , "exclude: from %s\n" , el -> src );
1021+
9081022 for (i = el -> nr - 1 ; 0 <= i ; i -- ) {
9091023 struct exclude * x = el -> excludes [i ];
9101024 const char * exclude = x -> pattern ;
9111025 int prefix = x -> nowildcardlen ;
9121026
1027+ if (!maybe_descend && i < el -> nr - 1 &&
1028+ different_decisions (x , el -> excludes [i + 1 ]))
1029+ maybe_descend = 1 ;
1030+
1031+ if (x -> sticky_paths .nr ) {
1032+ if (* dtype == DT_UNKNOWN )
1033+ * dtype = get_dtype (NULL , pathname , pathlen );
1034+ if (match_sticky (x , pathname , pathlen , * dtype )) {
1035+ exc = x ;
1036+ break ;
1037+ }
1038+ continue ;
1039+ }
1040+
9131041 if (x -> flags & EXC_FLAG_MUSTBEDIR ) {
9141042 if (* dtype == DT_UNKNOWN )
9151043 * dtype = get_dtype (NULL , pathname , pathlen );
@@ -936,6 +1064,45 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
9361064 break ;
9371065 }
9381066 }
1067+
1068+ if (!exc ) {
1069+ trace_printf_key (& trace_exclude , "exclude: %.*s => n/a\n" ,
1070+ pathlen , pathname );
1071+ return NULL ;
1072+ }
1073+
1074+ /*
1075+ * We have found a matching pattern "exc" that may exclude whole
1076+ * directory. We also found that there may be a pattern that matches
1077+ * something inside the directory and reincludes stuff.
1078+ *
1079+ * Go through the patterns again, find that pattern and double check.
1080+ * If it's true, return "undecided" and keep descending in. "exc" is
1081+ * marked sticky so that it continues to match inside the directory.
1082+ */
1083+ if (!(exc -> flags & EXC_FLAG_NEGATIVE ) && maybe_descend ) {
1084+ struct exclude * x ;
1085+
1086+ if (* dtype == DT_UNKNOWN )
1087+ * dtype = get_dtype (NULL , pathname , pathlen );
1088+
1089+ if (* dtype == DT_DIR &&
1090+ (x = should_descend (pathname , pathlen , dtype , el , exc ))) {
1091+ add_sticky (exc , pathname , pathlen );
1092+ trace_printf_key (& trace_exclude ,
1093+ "exclude: %.*s vs %s at line %d => %s,"
1094+ " forced open by %s at line %d => n/a\n" ,
1095+ pathlen , pathname , exc -> pattern , exc -> srcpos ,
1096+ exc -> flags & EXC_FLAG_NEGATIVE ? "no" : "yes" ,
1097+ x -> pattern , x -> srcpos );
1098+ return NULL ;
1099+ }
1100+ }
1101+
1102+ trace_printf_key (& trace_exclude , "exclude: %.*s vs %s at line %d => %s%s\n" ,
1103+ pathlen , pathname , exc -> pattern , exc -> srcpos ,
1104+ exc -> flags & EXC_FLAG_NEGATIVE ? "no" : "yes" ,
1105+ exc -> sticky_paths .nr ? " (stuck)" : "" );
9391106 return exc ;
9401107}
9411108
@@ -1683,9 +1850,13 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
16831850 struct cached_dir cdir ;
16841851 enum path_treatment state , subdir_state , dir_state = path_none ;
16851852 struct strbuf path = STRBUF_INIT ;
1853+ static int level = 0 ;
16861854
16871855 strbuf_add (& path , base , baselen );
16881856
1857+ trace_printf_key (& trace_exclude , "exclude: [%d] enter '%.*s'\n" ,
1858+ level ++ , baselen , base );
1859+
16891860 if (open_cached_dir (& cdir , dir , untracked , & path , check_only ))
16901861 goto out ;
16911862
@@ -1749,6 +1920,8 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
17491920 }
17501921 close_cached_dir (& cdir );
17511922 out :
1923+ trace_printf_key (& trace_exclude , "exclude: [%d] leave '%.*s'\n" ,
1924+ -- level , baselen , base );
17521925 strbuf_release (& path );
17531926
17541927 return dir_state ;
@@ -1985,6 +2158,25 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
19852158 return root ;
19862159}
19872160
2161+ static void clear_sticky (struct dir_struct * dir )
2162+ {
2163+ struct exclude_list_group * g ;
2164+ struct exclude_list * el ;
2165+ struct exclude * x ;
2166+ int i , j , k ;
2167+
2168+ for (i = EXC_CMDL ; i <= EXC_FILE ; i ++ ) {
2169+ g = & dir -> exclude_list_group [i ];
2170+ for (j = g -> nr - 1 ; j >= 0 ; j -- ) {
2171+ el = & g -> el [j ];
2172+ for (k = el -> nr - 1 ; 0 <= k ; k -- ) {
2173+ x = el -> excludes [k ];
2174+ string_list_clear (& x -> sticky_paths , 0 );
2175+ }
2176+ }
2177+ }
2178+ }
2179+
19882180int read_directory (struct dir_struct * dir , const char * path , int len , const struct pathspec * pathspec )
19892181{
19902182 struct path_simplify * simplify ;
@@ -2005,6 +2197,12 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru
20052197 if (has_symlink_leading_path (path , len ))
20062198 return dir -> nr ;
20072199
2200+ /*
2201+ * Stay on the safe side. if read_directory() has run once on
2202+ * "dir", some sticky flag may have been left. Clear them all.
2203+ */
2204+ clear_sticky (dir );
2205+
20082206 /*
20092207 * exclude patterns are treated like positive ones in
20102208 * create_simplify. Usually exclude patterns should be a
0 commit comments