mirror of
https://github.com/git/git
synced 2024-08-27 03:29:21 +00:00
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 <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
fcd631ed84
commit
f9f6e2ce26
37
dir.c
37
dir.c
|
@ -341,8 +341,7 @@ void add_exclude(const char *string, const char *base,
|
|||
x->flags = flags;
|
||||
if (!strchr(string, '/'))
|
||||
x->flags |= EXC_FLAG_NODIR;
|
||||
if (no_wildcard(string))
|
||||
x->flags |= EXC_FLAG_NOWILDCARD;
|
||||
x->nowildcardlen = simple_length(string);
|
||||
if (*string == '*' && no_wildcard(string+1))
|
||||
x->flags |= EXC_FLAG_ENDSWITH;
|
||||
ALLOC_GROW(which->excludes, which->nr + 1, which->alloc);
|
||||
|
@ -518,8 +517,9 @@ int excluded_from_list(const char *pathname,
|
|||
|
||||
for (i = el->nr - 1; 0 <= i; i--) {
|
||||
struct exclude *x = el->excludes[i];
|
||||
const char *exclude = x->pattern;
|
||||
const char *name, *exclude = x->pattern;
|
||||
int to_exclude = x->to_exclude;
|
||||
int namelen, prefix = x->nowildcardlen;
|
||||
|
||||
if (x->flags & EXC_FLAG_MUSTBEDIR) {
|
||||
if (*dtype == DT_UNKNOWN)
|
||||
|
@ -530,7 +530,7 @@ int excluded_from_list(const char *pathname,
|
|||
|
||||
if (x->flags & EXC_FLAG_NODIR) {
|
||||
/* match basename */
|
||||
if (x->flags & EXC_FLAG_NOWILDCARD) {
|
||||
if (prefix == x->patternlen) {
|
||||
if (!strcmp_icase(exclude, basename))
|
||||
return to_exclude;
|
||||
} else if (x->flags & EXC_FLAG_ENDSWITH) {
|
||||
|
@ -544,26 +544,37 @@ int excluded_from_list(const char *pathname,
|
|||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* match with FNM_PATHNAME:
|
||||
* exclude has base (baselen long) implicitly in front of it.
|
||||
*/
|
||||
if (*exclude == '/')
|
||||
if (*exclude == '/') {
|
||||
exclude++;
|
||||
prefix--;
|
||||
}
|
||||
|
||||
if (pathlen < x->baselen ||
|
||||
(x->baselen && pathname[x->baselen-1] != '/') ||
|
||||
strncmp_icase(pathname, x->base, x->baselen))
|
||||
continue;
|
||||
|
||||
if (x->flags & EXC_FLAG_NOWILDCARD) {
|
||||
if (!strcmp_icase(exclude, pathname + x->baselen))
|
||||
return to_exclude;
|
||||
} else {
|
||||
if (fnmatch_icase(exclude, pathname+x->baselen,
|
||||
FNM_PATHNAME) == 0)
|
||||
return to_exclude;
|
||||
namelen = x->baselen ? pathlen - x->baselen : pathlen;
|
||||
name = pathname + pathlen - namelen;
|
||||
|
||||
/* if the non-wildcard part is longer than the
|
||||
remaining pathname, surely it cannot match */
|
||||
if (prefix > namelen)
|
||||
continue;
|
||||
|
||||
if (prefix) {
|
||||
if (strncmp_icase(exclude, name, prefix))
|
||||
continue;
|
||||
exclude += prefix;
|
||||
name += prefix;
|
||||
namelen -= prefix;
|
||||
}
|
||||
|
||||
if (!namelen || !fnmatch_icase(exclude, name, FNM_PATHNAME))
|
||||
return to_exclude;
|
||||
}
|
||||
return -1; /* undecided */
|
||||
}
|
||||
|
|
2
dir.h
2
dir.h
|
@ -7,7 +7,6 @@ struct dir_entry {
|
|||
};
|
||||
|
||||
#define EXC_FLAG_NODIR 1
|
||||
#define EXC_FLAG_NOWILDCARD 2
|
||||
#define EXC_FLAG_ENDSWITH 4
|
||||
#define EXC_FLAG_MUSTBEDIR 8
|
||||
|
||||
|
@ -17,6 +16,7 @@ struct exclude_list {
|
|||
struct exclude {
|
||||
const char *pattern;
|
||||
int patternlen;
|
||||
int nowildcardlen;
|
||||
const char *base;
|
||||
int baselen;
|
||||
int to_exclude;
|
||||
|
|
Loading…
Reference in a new issue