@@ -308,42 +308,69 @@ static int no_wildcard(const char *string)
308308 return string [simple_length (string )] == '\0' ;
309309}
310310
311+ static void parse_exclude_pattern (const char * * pattern ,
312+ int * patternlen ,
313+ int * flags ,
314+ int * nowildcardlen )
315+ {
316+ const char * p = * pattern ;
317+ size_t i , len ;
318+
319+ * flags = 0 ;
320+ if (* p == '!' ) {
321+ * flags |= EXC_FLAG_NEGATIVE ;
322+ p ++ ;
323+ }
324+ len = strlen (p );
325+ if (len && p [len - 1 ] == '/' ) {
326+ len -- ;
327+ * flags |= EXC_FLAG_MUSTBEDIR ;
328+ }
329+ for (i = 0 ; i < len ; i ++ ) {
330+ if (p [i ] == '/' )
331+ break ;
332+ }
333+ if (i == len )
334+ * flags |= EXC_FLAG_NODIR ;
335+ * nowildcardlen = simple_length (p );
336+ /*
337+ * we should have excluded the trailing slash from 'p' too,
338+ * but that's one more allocation. Instead just make sure
339+ * nowildcardlen does not exceed real patternlen
340+ */
341+ if (* nowildcardlen > len )
342+ * nowildcardlen = len ;
343+ if (* p == '*' && no_wildcard (p + 1 ))
344+ * flags |= EXC_FLAG_ENDSWITH ;
345+ * pattern = p ;
346+ * patternlen = len ;
347+ }
348+
311349void add_exclude (const char * string , const char * base ,
312350 int baselen , struct exclude_list * which )
313351{
314352 struct exclude * x ;
315- size_t len ;
316- int to_exclude = 1 ;
317- int flags = 0 ;
353+ int patternlen ;
354+ int flags ;
355+ int nowildcardlen ;
318356
319- if (* string == '!' ) {
320- to_exclude = 0 ;
321- string ++ ;
322- }
323- len = strlen (string );
324- if (len && string [len - 1 ] == '/' ) {
357+ parse_exclude_pattern (& string , & patternlen , & flags , & nowildcardlen );
358+ if (flags & EXC_FLAG_MUSTBEDIR ) {
325359 char * s ;
326- x = xmalloc (sizeof (* x ) + len );
360+ x = xmalloc (sizeof (* x ) + patternlen + 1 );
327361 s = (char * )(x + 1 );
328- memcpy (s , string , len - 1 );
329- s [len - 1 ] = '\0' ;
330- string = s ;
362+ memcpy (s , string , patternlen );
363+ s [patternlen ] = '\0' ;
331364 x -> pattern = s ;
332- flags = EXC_FLAG_MUSTBEDIR ;
333365 } else {
334366 x = xmalloc (sizeof (* x ));
335367 x -> pattern = string ;
336368 }
337- x -> to_exclude = to_exclude ;
338- x -> patternlen = strlen ( string ) ;
369+ x -> patternlen = patternlen ;
370+ x -> nowildcardlen = nowildcardlen ;
339371 x -> base = base ;
340372 x -> baselen = baselen ;
341373 x -> flags = flags ;
342- if (!strchr (string , '/' ))
343- x -> flags |= EXC_FLAG_NODIR ;
344- x -> nowildcardlen = simple_length (string );
345- if (* string == '*' && no_wildcard (string + 1 ))
346- x -> flags |= EXC_FLAG_ENDSWITH ;
347374 ALLOC_GROW (which -> excludes , which -> nr + 1 , which -> alloc );
348375 which -> excludes [which -> nr ++ ] = x ;
349376}
@@ -584,7 +611,7 @@ int excluded_from_list(const char *pathname,
584611 for (i = el -> nr - 1 ; 0 <= i ; i -- ) {
585612 struct exclude * x = el -> excludes [i ];
586613 const char * exclude = x -> pattern ;
587- int to_exclude = x -> to_exclude ;
614+ int to_exclude = x -> flags & EXC_FLAG_NEGATIVE ? 0 : 1 ;
588615 int prefix = x -> nowildcardlen ;
589616
590617 if (x -> flags & EXC_FLAG_MUSTBEDIR ) {
0 commit comments