提交 68492fc7 编写于 作者: L Lars Knoll 提交者: Junio C Hamano

Speedup scanning for excluded files.

Try to avoid a lot of work scanning for excluded files,
by caching some more information when setting up the exclusion
data structure.

Speeds up 'git runstatus' on a repository containing the Qt sources by 30% and
reduces the amount of instructions executed (as measured by valgrind) by a
factor of 2.
Signed-off-by: NJunio C Hamano <gitster@pobox.com>
上级 79f3368d
...@@ -118,14 +118,32 @@ int match_pathspec(const char **pathspec, const char *name, int namelen, int pre ...@@ -118,14 +118,32 @@ int match_pathspec(const char **pathspec, const char *name, int namelen, int pre
return retval; return retval;
} }
static int no_wildcard(const char *string)
{
return string[strcspn(string, "*?[{")] == '\0';
}
void add_exclude(const char *string, const char *base, void add_exclude(const char *string, const char *base,
int baselen, struct exclude_list *which) int baselen, struct exclude_list *which)
{ {
struct exclude *x = xmalloc(sizeof (*x)); struct exclude *x = xmalloc(sizeof (*x));
x->to_exclude = 1;
if (*string == '!') {
x->to_exclude = 0;
string++;
}
x->pattern = string; x->pattern = string;
x->patternlen = strlen(string);
x->base = base; x->base = base;
x->baselen = baselen; x->baselen = baselen;
x->flags = 0;
if (!strchr(string, '/'))
x->flags |= EXC_FLAG_NODIR;
if (no_wildcard(string))
x->flags |= EXC_FLAG_NOWILDCARD;
if (*string == '*' && no_wildcard(string+1))
x->flags |= EXC_FLAG_ENDSWITH;
if (which->nr == which->alloc) { if (which->nr == which->alloc) {
which->alloc = alloc_nr(which->alloc); which->alloc = alloc_nr(which->alloc);
which->excludes = xrealloc(which->excludes, which->excludes = xrealloc(which->excludes,
...@@ -209,7 +227,7 @@ void pop_exclude_per_directory(struct dir_struct *dir, int stk) ...@@ -209,7 +227,7 @@ void pop_exclude_per_directory(struct dir_struct *dir, int stk)
* Return 1 for exclude, 0 for include and -1 for undecided. * Return 1 for exclude, 0 for include and -1 for undecided.
*/ */
static int excluded_1(const char *pathname, static int excluded_1(const char *pathname,
int pathlen, int pathlen, const char *basename,
struct exclude_list *el) struct exclude_list *el)
{ {
int i; int i;
...@@ -218,19 +236,21 @@ static int excluded_1(const char *pathname, ...@@ -218,19 +236,21 @@ static int excluded_1(const char *pathname,
for (i = el->nr - 1; 0 <= i; i--) { for (i = el->nr - 1; 0 <= i; i--) {
struct exclude *x = el->excludes[i]; struct exclude *x = el->excludes[i];
const char *exclude = x->pattern; const char *exclude = x->pattern;
int to_exclude = 1; int to_exclude = x->to_exclude;
if (*exclude == '!') { if (x->flags & EXC_FLAG_NODIR) {
to_exclude = 0;
exclude++;
}
if (!strchr(exclude, '/')) {
/* match basename */ /* match basename */
const char *basename = strrchr(pathname, '/'); if (x->flags & EXC_FLAG_NOWILDCARD) {
basename = (basename) ? basename+1 : pathname; if (!strcmp(exclude, basename))
if (fnmatch(exclude, basename, 0) == 0) return to_exclude;
return to_exclude; } else if (x->flags & EXC_FLAG_ENDSWITH) {
if (x->patternlen - 1 <= pathlen &&
!strcmp(exclude + 1, pathname + pathlen - x->patternlen + 1))
return to_exclude;
} else {
if (fnmatch(exclude, basename, 0) == 0)
return to_exclude;
}
} }
else { else {
/* match with FNM_PATHNAME: /* match with FNM_PATHNAME:
...@@ -246,9 +266,14 @@ static int excluded_1(const char *pathname, ...@@ -246,9 +266,14 @@ static int excluded_1(const char *pathname,
strncmp(pathname, x->base, baselen)) strncmp(pathname, x->base, baselen))
continue; continue;
if (fnmatch(exclude, pathname+baselen, if (x->flags & EXC_FLAG_NOWILDCARD) {
FNM_PATHNAME) == 0) if (!strcmp(exclude, pathname + baselen))
return to_exclude; return to_exclude;
} else {
if (fnmatch(exclude, pathname+baselen,
FNM_PATHNAME) == 0)
return to_exclude;
}
} }
} }
} }
...@@ -259,9 +284,11 @@ int excluded(struct dir_struct *dir, const char *pathname) ...@@ -259,9 +284,11 @@ int excluded(struct dir_struct *dir, const char *pathname)
{ {
int pathlen = strlen(pathname); int pathlen = strlen(pathname);
int st; int st;
const char *basename = strrchr(pathname, '/');
basename = (basename) ? basename+1 : pathname;
for (st = EXC_CMDL; st <= EXC_FILE; st++) { for (st = EXC_CMDL; st <= EXC_FILE; st++) {
switch (excluded_1(pathname, pathlen, &dir->exclude_list[st])) { switch (excluded_1(pathname, pathlen, basename, &dir->exclude_list[st])) {
case 0: case 0:
return 0; return 0;
case 1: case 1:
......
...@@ -17,13 +17,20 @@ struct dir_entry { ...@@ -17,13 +17,20 @@ struct dir_entry {
char name[FLEX_ARRAY]; /* more */ char name[FLEX_ARRAY]; /* more */
}; };
#define EXC_FLAG_NODIR 1
#define EXC_FLAG_NOWILDCARD 2
#define EXC_FLAG_ENDSWITH 4
struct exclude_list { struct exclude_list {
int nr; int nr;
int alloc; int alloc;
struct exclude { struct exclude {
const char *pattern; const char *pattern;
int patternlen;
const char *base; const char *base;
int baselen; int baselen;
int to_exclude;
int flags;
} **excludes; } **excludes;
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册