From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Jeff King" <peff@peff.net>, "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 2/3] exclude: do strcmp as much as possible before fnmatch
Date: Sat, 26 May 2012 19:31:13 +0700 [thread overview]
Message-ID: <1338035474-4346-3-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1338035474-4346-1-git-send-email-pclouds@gmail.com>
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>
---
dir.c | 41 +++++++++++++++++++++++++++--------------
dir.h | 2 +-
2 files changed, 28 insertions(+), 15 deletions(-)
diff --git a/dir.c b/dir.c
index 8535cf2..50d744f 100644
--- a/dir.c
+++ b/dir.c
@@ -295,9 +295,11 @@ int match_pathspec_depth(const struct pathspec *ps,
return retval;
}
+const char *wildcards = "*?[{\\";
+
static int no_wildcard(const char *string)
{
- return string[strcspn(string, "*?[{\\")] == '\0';
+ return string[strcspn(string, wildcards)] == '\0';
}
void add_exclude(const char *string, const char *base,
@@ -336,8 +338,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 = strcspn(string, wildcards);
if (*string == '*' && no_wildcard(string+1))
x->flags |= EXC_FLAG_ENDSWITH;
ALLOC_GROW(which->excludes, which->nr + 1, which->alloc);
@@ -513,8 +514,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)
@@ -525,7 +527,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) {
@@ -539,26 +541,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 */
}
diff --git a/dir.h b/dir.h
index 58b6fc7..39fc145 100644
--- a/dir.h
+++ b/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;
--
1.7.10.2.549.g9354186
next prev parent reply other threads:[~2012-05-26 12:35 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-26 12:31 [PATCH WIP 0/3] top-level gitignore considered less harmful Nguyễn Thái Ngọc Duy
2012-05-26 12:31 ` [PATCH 1/3] Unindent excluded_from_list() Nguyễn Thái Ngọc Duy
2012-05-26 12:31 ` Nguyễn Thái Ngọc Duy [this message]
2012-05-27 6:51 ` [PATCH 2/3] exclude: do strcmp as much as possible before fnmatch Junio C Hamano
2012-05-27 12:06 ` Nguyen Thai Ngoc Duy
2012-05-27 18:14 ` Junio C Hamano
2012-05-28 1:03 ` Nguyen Thai Ngoc Duy
2012-05-28 5:02 ` Junio C Hamano
2012-05-29 18:03 ` Junio C Hamano
2012-05-29 18:21 ` Thiago Farina
2012-05-26 12:31 ` [PATCH 3/3] exclude: reduce computation cost on checking dirname in patterns Nguyễn Thái Ngọc Duy
2012-05-26 13:25 ` [PATCH WIP 0/3] top-level gitignore considered less harmful Nguyen Thai Ngoc Duy
2012-05-26 21:45 ` Jeff King
2012-05-27 3:45 ` Nguyen Thai Ngoc Duy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1338035474-4346-3-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
--cc=peff@peff.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).