@@ -17,6 +17,7 @@ struct path_simplify {
1717static int read_directory_recursive (struct dir_struct * dir ,
1818 const char * path , const char * base , int baselen ,
1919 int check_only , const struct path_simplify * simplify );
20+ static int get_dtype (struct dirent * de , const char * path );
2021
2122int common_prefix (const char * * pathspec )
2223{
@@ -126,18 +127,34 @@ static int no_wildcard(const char *string)
126127void add_exclude (const char * string , const char * base ,
127128 int baselen , struct exclude_list * which )
128129{
129- struct exclude * x = xmalloc (sizeof (* x ));
130+ struct exclude * x ;
131+ size_t len ;
132+ int to_exclude = 1 ;
133+ int flags = 0 ;
130134
131- x -> to_exclude = 1 ;
132135 if (* string == '!' ) {
133- x -> to_exclude = 0 ;
136+ to_exclude = 0 ;
134137 string ++ ;
135138 }
136- x -> pattern = string ;
139+ len = strlen (string );
140+ if (len && string [len - 1 ] == '/' ) {
141+ char * s ;
142+ x = xmalloc (sizeof (* x ) + len );
143+ s = (char * )(x + 1 );
144+ memcpy (s , string , len - 1 );
145+ s [len - 1 ] = '\0' ;
146+ string = s ;
147+ x -> pattern = s ;
148+ flags = EXC_FLAG_MUSTBEDIR ;
149+ } else {
150+ x = xmalloc (sizeof (* x ));
151+ x -> pattern = string ;
152+ }
153+ x -> to_exclude = to_exclude ;
137154 x -> patternlen = strlen (string );
138155 x -> base = base ;
139156 x -> baselen = baselen ;
140- x -> flags = 0 ;
157+ x -> flags = flags ;
141158 if (!strchr (string , '/' ))
142159 x -> flags |= EXC_FLAG_NODIR ;
143160 if (no_wildcard (string ))
@@ -261,7 +278,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
261278 * Return 1 for exclude, 0 for include and -1 for undecided.
262279 */
263280static int excluded_1 (const char * pathname ,
264- int pathlen , const char * basename ,
281+ int pathlen , const char * basename , int * dtype ,
265282 struct exclude_list * el )
266283{
267284 int i ;
@@ -272,6 +289,13 @@ static int excluded_1(const char *pathname,
272289 const char * exclude = x -> pattern ;
273290 int to_exclude = x -> to_exclude ;
274291
292+ if (x -> flags & EXC_FLAG_MUSTBEDIR ) {
293+ if (* dtype == DT_UNKNOWN )
294+ * dtype = get_dtype (NULL , pathname );
295+ if (* dtype != DT_DIR )
296+ continue ;
297+ }
298+
275299 if (x -> flags & EXC_FLAG_NODIR ) {
276300 /* match basename */
277301 if (x -> flags & EXC_FLAG_NOWILDCARD ) {
@@ -314,7 +338,7 @@ static int excluded_1(const char *pathname,
314338 return -1 ; /* undecided */
315339}
316340
317- int excluded (struct dir_struct * dir , const char * pathname )
341+ int excluded (struct dir_struct * dir , const char * pathname , int * dtype_p )
318342{
319343 int pathlen = strlen (pathname );
320344 int st ;
@@ -323,7 +347,8 @@ int excluded(struct dir_struct *dir, const char *pathname)
323347
324348 prep_exclude (dir , pathname , basename - pathname );
325349 for (st = EXC_CMDL ; st <= EXC_FILE ; st ++ ) {
326- switch (excluded_1 (pathname , pathlen , basename , & dir -> exclude_list [st ])) {
350+ switch (excluded_1 (pathname , pathlen , basename ,
351+ dtype_p , & dir -> exclude_list [st ])) {
327352 case 0 :
328353 return 0 ;
329354 case 1 :
@@ -508,7 +533,7 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si
508533
509534static int get_dtype (struct dirent * de , const char * path )
510535{
511- int dtype = DTYPE (de );
536+ int dtype = de ? DTYPE (de ) : DT_UNKNOWN ;
512537 struct stat st ;
513538
514539 if (dtype != DT_UNKNOWN )
@@ -560,7 +585,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
560585 if (simplify_away (fullname , baselen + len , simplify ))
561586 continue ;
562587
563- exclude = excluded (dir , fullname );
588+ dtype = DTYPE (de );
589+ exclude = excluded (dir , fullname , & dtype );
564590 if (exclude && dir -> collect_ignored
565591 && in_pathspec (fullname , baselen + len , simplify ))
566592 dir_add_ignored (dir , fullname , baselen + len );
@@ -572,7 +598,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
572598 if (exclude && !dir -> show_ignored )
573599 continue ;
574600
575- dtype = get_dtype (de , fullname );
601+ if (dtype == DT_UNKNOWN )
602+ dtype = get_dtype (de , fullname );
576603
577604 /*
578605 * Do we want to see just the ignored files?
0 commit comments