@@ -288,9 +288,24 @@ int match_pathspec_depth(const struct pathspec *ps,
288
288
return retval ;
289
289
}
290
290
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
+
291
306
static int no_wildcard (const char * string )
292
307
{
293
- return string [strcspn (string , "*?[{\\" )] == '\0' ;
308
+ return string [simple_length (string )] == '\0' ;
294
309
}
295
310
296
311
void add_exclude (const char * string , const char * base ,
@@ -326,8 +341,7 @@ void add_exclude(const char *string, const char *base,
326
341
x -> flags = flags ;
327
342
if (!strchr (string , '/' ))
328
343
x -> flags |= EXC_FLAG_NODIR ;
329
- if (no_wildcard (string ))
330
- x -> flags |= EXC_FLAG_NOWILDCARD ;
344
+ x -> nowildcardlen = simple_length (string );
331
345
if (* string == '*' && no_wildcard (string + 1 ))
332
346
x -> flags |= EXC_FLAG_ENDSWITH ;
333
347
ALLOC_GROW (which -> excludes , which -> nr + 1 , which -> alloc );
@@ -498,57 +512,69 @@ int excluded_from_list(const char *pathname,
498
512
{
499
513
int i ;
500
514
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 */
513
517
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 ;
550
543
}
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 -- ;
551
553
}
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 ;
552
578
}
553
579
return -1 ; /* undecided */
554
580
}
@@ -1055,21 +1081,6 @@ static int cmp_name(const void *p1, const void *p2)
1055
1081
e2 -> name , e2 -> len );
1056
1082
}
1057
1083
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
-
1073
1084
static struct path_simplify * create_simplify (const char * * pathspec )
1074
1085
{
1075
1086
int nr , alloc = 0 ;
0 commit comments