Skip to content

Commit f9f6e2c

Browse files
pcloudsgitster
authored andcommitted
exclude: do strcmp as much as possible before fnmatch
this also avoids calling fnmatch() if the non-wildcard prefix is longer than basename Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fcd631e commit f9f6e2c

File tree

2 files changed

+25
-14
lines changed

2 files changed

+25
-14
lines changed

dir.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,7 @@ void add_exclude(const char *string, const char *base,
341341
x->flags = flags;
342342
if (!strchr(string, '/'))
343343
x->flags |= EXC_FLAG_NODIR;
344-
if (no_wildcard(string))
345-
x->flags |= EXC_FLAG_NOWILDCARD;
344+
x->nowildcardlen = simple_length(string);
346345
if (*string == '*' && no_wildcard(string+1))
347346
x->flags |= EXC_FLAG_ENDSWITH;
348347
ALLOC_GROW(which->excludes, which->nr + 1, which->alloc);
@@ -518,8 +517,9 @@ int excluded_from_list(const char *pathname,
518517

519518
for (i = el->nr - 1; 0 <= i; i--) {
520519
struct exclude *x = el->excludes[i];
521-
const char *exclude = x->pattern;
520+
const char *name, *exclude = x->pattern;
522521
int to_exclude = x->to_exclude;
522+
int namelen, prefix = x->nowildcardlen;
523523

524524
if (x->flags & EXC_FLAG_MUSTBEDIR) {
525525
if (*dtype == DT_UNKNOWN)
@@ -530,7 +530,7 @@ int excluded_from_list(const char *pathname,
530530

531531
if (x->flags & EXC_FLAG_NODIR) {
532532
/* match basename */
533-
if (x->flags & EXC_FLAG_NOWILDCARD) {
533+
if (prefix == x->patternlen) {
534534
if (!strcmp_icase(exclude, basename))
535535
return to_exclude;
536536
} else if (x->flags & EXC_FLAG_ENDSWITH) {
@@ -544,26 +544,37 @@ int excluded_from_list(const char *pathname,
544544
continue;
545545
}
546546

547-
548547
/* match with FNM_PATHNAME:
549548
* exclude has base (baselen long) implicitly in front of it.
550549
*/
551-
if (*exclude == '/')
550+
if (*exclude == '/') {
552551
exclude++;
552+
prefix--;
553+
}
553554

554555
if (pathlen < x->baselen ||
555556
(x->baselen && pathname[x->baselen-1] != '/') ||
556557
strncmp_icase(pathname, x->base, x->baselen))
557558
continue;
558559

559-
if (x->flags & EXC_FLAG_NOWILDCARD) {
560-
if (!strcmp_icase(exclude, pathname + x->baselen))
561-
return to_exclude;
562-
} else {
563-
if (fnmatch_icase(exclude, pathname+x->baselen,
564-
FNM_PATHNAME) == 0)
565-
return to_exclude;
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;
566574
}
575+
576+
if (!namelen || !fnmatch_icase(exclude, name, FNM_PATHNAME))
577+
return to_exclude;
567578
}
568579
return -1; /* undecided */
569580
}

dir.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ struct dir_entry {
77
};
88

99
#define EXC_FLAG_NODIR 1
10-
#define EXC_FLAG_NOWILDCARD 2
1110
#define EXC_FLAG_ENDSWITH 4
1211
#define EXC_FLAG_MUSTBEDIR 8
1312

@@ -17,6 +16,7 @@ struct exclude_list {
1716
struct exclude {
1817
const char *pattern;
1918
int patternlen;
19+
int nowildcardlen;
2020
const char *base;
2121
int baselen;
2222
int to_exclude;

0 commit comments

Comments
 (0)