Skip to content

Commit 68bdfd7

Browse files
committed
Merge commit 'f9f6e2c' into nd/attr-match-optim-more
* commit 'f9f6e2c': exclude: do strcmp as much as possible before fnmatch dir.c: get rid of the wildcard symbol set in no_wildcard() Unindent excluded_from_list()
2 parents 4742d13 + f9f6e2c commit 68bdfd7

File tree

2 files changed

+78
-67
lines changed

2 files changed

+78
-67
lines changed

dir.c

Lines changed: 77 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
291306
static int no_wildcard(const char *string)
292307
{
293-
return string[strcspn(string, "*?[{\\")] == '\0';
308+
return string[simple_length(string)] == '\0';
294309
}
295310

296311
void 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-
10731084
static struct path_simplify *create_simplify(const char **pathspec)
10741085
{
10751086
int nr, alloc = 0;

dir.h

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

1111
#define EXC_FLAG_NODIR 1
12-
#define EXC_FLAG_NOWILDCARD 2
1312
#define EXC_FLAG_ENDSWITH 4
1413
#define EXC_FLAG_MUSTBEDIR 8
1514

@@ -19,6 +18,7 @@ struct exclude_list {
1918
struct exclude {
2019
const char *pattern;
2120
int patternlen;
21+
int nowildcardlen;
2222
const char *base;
2323
int baselen;
2424
int to_exclude;

0 commit comments

Comments
 (0)