@@ -288,9 +288,24 @@ int match_pathspec_depth(const struct pathspec *ps,
288288 return retval ;
289289}
290290
291+ /*
292+ * Return the length of the "simple" part of a path match limiter.
293+ */
294+ static int simple_length (const char * match )
295+ {
296+ int len = -1 ;
297+
298+ for (;;) {
299+ unsigned char c = * match ++ ;
300+ len ++ ;
301+ if (c == '\0' || is_glob_special (c ))
302+ return len ;
303+ }
304+ }
305+
291306static int no_wildcard (const char * string )
292307{
293- return string [strcspn (string , "*?[{\\" )] == '\0' ;
308+ return string [simple_length (string )] == '\0' ;
294309}
295310
296311void add_exclude (const char * string , const char * base ,
@@ -326,8 +341,7 @@ void add_exclude(const char *string, const char *base,
326341 x -> flags = flags ;
327342 if (!strchr (string , '/' ))
328343 x -> flags |= EXC_FLAG_NODIR ;
329- if (no_wildcard (string ))
330- x -> flags |= EXC_FLAG_NOWILDCARD ;
344+ x -> nowildcardlen = simple_length (string );
331345 if (* string == '*' && no_wildcard (string + 1 ))
332346 x -> flags |= EXC_FLAG_ENDSWITH ;
333347 ALLOC_GROW (which -> excludes , which -> nr + 1 , which -> alloc );
@@ -498,57 +512,69 @@ int excluded_from_list(const char *pathname,
498512{
499513 int i ;
500514
501- if (el -> nr ) {
502- for (i = el -> nr - 1 ; 0 <= i ; i -- ) {
503- struct exclude * x = el -> excludes [i ];
504- const char * exclude = x -> pattern ;
505- int to_exclude = x -> to_exclude ;
506-
507- if (x -> flags & EXC_FLAG_MUSTBEDIR ) {
508- if (* dtype == DT_UNKNOWN )
509- * dtype = get_dtype (NULL , pathname , pathlen );
510- if (* dtype != DT_DIR )
511- continue ;
512- }
515+ if (!el -> nr )
516+ return -1 ; /* undefined */
513517
514- if (x -> flags & EXC_FLAG_NODIR ) {
515- /* match basename */
516- if (x -> flags & EXC_FLAG_NOWILDCARD ) {
517- if (!strcmp_icase (exclude , basename ))
518- return to_exclude ;
519- } else if (x -> flags & EXC_FLAG_ENDSWITH ) {
520- if (x -> patternlen - 1 <= pathlen &&
521- !strcmp_icase (exclude + 1 , pathname + pathlen - x -> patternlen + 1 ))
522- return to_exclude ;
523- } else {
524- if (fnmatch_icase (exclude , basename , 0 ) == 0 )
525- return to_exclude ;
526- }
527- }
528- else {
529- /* match with FNM_PATHNAME:
530- * exclude has base (baselen long) implicitly
531- * in front of it.
532- */
533- int baselen = x -> baselen ;
534- if (* exclude == '/' )
535- exclude ++ ;
536-
537- if (pathlen < baselen ||
538- (baselen && pathname [baselen - 1 ] != '/' ) ||
539- strncmp_icase (pathname , x -> base , baselen ))
540- continue ;
541-
542- if (x -> flags & EXC_FLAG_NOWILDCARD ) {
543- if (!strcmp_icase (exclude , pathname + baselen ))
544- return to_exclude ;
545- } else {
546- if (fnmatch_icase (exclude , pathname + baselen ,
547- FNM_PATHNAME ) == 0 )
548- return to_exclude ;
549- }
518+ for (i = el -> nr - 1 ; 0 <= i ; i -- ) {
519+ struct exclude * x = el -> excludes [i ];
520+ const char * name , * exclude = x -> pattern ;
521+ int to_exclude = x -> to_exclude ;
522+ int namelen , prefix = x -> nowildcardlen ;
523+
524+ if (x -> flags & EXC_FLAG_MUSTBEDIR ) {
525+ if (* dtype == DT_UNKNOWN )
526+ * dtype = get_dtype (NULL , pathname , pathlen );
527+ if (* dtype != DT_DIR )
528+ continue ;
529+ }
530+
531+ if (x -> flags & EXC_FLAG_NODIR ) {
532+ /* match basename */
533+ if (prefix == x -> patternlen ) {
534+ if (!strcmp_icase (exclude , basename ))
535+ return to_exclude ;
536+ } else if (x -> flags & EXC_FLAG_ENDSWITH ) {
537+ if (x -> patternlen - 1 <= pathlen &&
538+ !strcmp_icase (exclude + 1 , pathname + pathlen - x -> patternlen + 1 ))
539+ return to_exclude ;
540+ } else {
541+ if (fnmatch_icase (exclude , basename , 0 ) == 0 )
542+ return to_exclude ;
550543 }
544+ continue ;
545+ }
546+
547+ /* match with FNM_PATHNAME:
548+ * exclude has base (baselen long) implicitly in front of it.
549+ */
550+ if (* exclude == '/' ) {
551+ exclude ++ ;
552+ prefix -- ;
551553 }
554+
555+ if (pathlen < x -> baselen ||
556+ (x -> baselen && pathname [x -> baselen - 1 ] != '/' ) ||
557+ strncmp_icase (pathname , x -> base , x -> baselen ))
558+ continue ;
559+
560+ namelen = x -> baselen ? pathlen - x -> baselen : pathlen ;
561+ name = pathname + pathlen - namelen ;
562+
563+ /* if the non-wildcard part is longer than the
564+ remaining pathname, surely it cannot match */
565+ if (prefix > namelen )
566+ continue ;
567+
568+ if (prefix ) {
569+ if (strncmp_icase (exclude , name , prefix ))
570+ continue ;
571+ exclude += prefix ;
572+ name += prefix ;
573+ namelen -= prefix ;
574+ }
575+
576+ if (!namelen || !fnmatch_icase (exclude , name , FNM_PATHNAME ))
577+ return to_exclude ;
552578 }
553579 return -1 ; /* undecided */
554580}
@@ -1055,21 +1081,6 @@ static int cmp_name(const void *p1, const void *p2)
10551081 e2 -> name , e2 -> len );
10561082}
10571083
1058- /*
1059- * Return the length of the "simple" part of a path match limiter.
1060- */
1061- static int simple_length (const char * match )
1062- {
1063- int len = -1 ;
1064-
1065- for (;;) {
1066- unsigned char c = * match ++ ;
1067- len ++ ;
1068- if (c == '\0' || is_glob_special (c ))
1069- return len ;
1070- }
1071- }
1072-
10731084static struct path_simplify * create_simplify (const char * * pathspec )
10741085{
10751086 int nr , alloc = 0 ;
0 commit comments