From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 4/4] exclude/attr: share full pathname matching code
Date: Sun, 14 Oct 2012 18:55:42 +0700 [thread overview]
Message-ID: <1350215742-20761-5-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1350215742-20761-1-git-send-email-pclouds@gmail.com>
match_pathname's declaration in dir.h does not have any description to
discourage the use of this function elsewhere as this function is
highly tied to how excluded_from_list and path_matches work.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
attr.c | 35 +++------------------------
dir.c | 85 +++++++++++++++++++++++++++++++++++++++++-------------------------
dir.h | 3 +++
3 files changed, 59 insertions(+), 64 deletions(-)
diff --git a/attr.c b/attr.c
index a28ce0d..2fc6353 100644
--- a/attr.c
+++ b/attr.c
@@ -659,8 +659,6 @@ static int path_matches(const char *pathname, int pathlen,
{
const char *pattern = pat->pattern;
int prefix = pat->nowildcardlen;
- const char *name;
- int namelen;
if (pat->flags & EXC_FLAG_NODIR) {
return match_basename(basename,
@@ -668,36 +666,9 @@ static int path_matches(const char *pathname, int pathlen,
pattern, prefix,
pat->patternlen, pat->flags);
}
- /*
- * match with FNM_PATHNAME; the pattern has base implicitly
- * in front of it.
- */
- if (*pattern == '/') {
- pattern++;
- prefix--;
- }
-
- /*
- * note: unlike excluded_from_list, baselen here does not
- * count the trailing slash, and base[] does not end with
- * a trailing slash, either.
- */
- if (pathlen < baselen + 1 ||
- (baselen && pathname[baselen] != '/') ||
- strncmp_icase(pathname, base, baselen))
- return 0;
-
- namelen = baselen ? pathlen - baselen - 1 : pathlen;
- name = pathname + pathlen - namelen;
-
- /*
- * if the non-wildcard part is longer than the remaining
- * pathname, surely it cannot match.
- */
- if (!namelen || prefix > namelen)
- return 0;
-
- return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
+ return match_pathname(pathname, pathlen,
+ base, baselen,
+ pattern, prefix, pat->patternlen, pat->flags);
}
static int macroexpand_one(int attr_nr, int rem);
diff --git a/dir.c b/dir.c
index 42c42cd..ee8e711 100644
--- a/dir.c
+++ b/dir.c
@@ -549,6 +549,53 @@ int match_basename(const char *basename, int basenamelen,
return 0;
}
+int match_pathname(const char *pathname, int pathlen,
+ const char *base, int baselen,
+ const char *pattern, int prefix, int patternlen,
+ int flags)
+{
+ const char *name;
+ int namelen;
+
+ /*
+ * match with FNM_PATHNAME; the pattern has base implicitly
+ * in front of it.
+ */
+ if (*pattern == '/') {
+ pattern++;
+ prefix--;
+ }
+
+ /*
+ * baselen does not count the trailing slash. base[] may or
+ * may not end with a trailing slash though.
+ */
+ if (pathlen < baselen + 1 ||
+ (baselen && pathname[baselen] != '/') ||
+ strncmp_icase(pathname, base, baselen))
+ return 0;
+
+ namelen = baselen ? pathlen - baselen - 1 : pathlen;
+ name = pathname + pathlen - namelen;
+
+ if (prefix) {
+ /*
+ * if the non-wildcard part is longer than the
+ * remaining pathname, surely it cannot match.
+ */
+ if (prefix > namelen)
+ return 0;
+
+ if (strncmp_icase(pattern, name, prefix))
+ return 0;
+ pattern += prefix;
+ name += prefix;
+ namelen -= prefix;
+ }
+
+ return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
+}
+
/* Scan the list and let the last match determine the fate.
* Return 1 for exclude, 0 for include and -1 for undecided.
*/
@@ -563,9 +610,9 @@ int excluded_from_list(const char *pathname,
for (i = el->nr - 1; 0 <= i; i--) {
struct exclude *x = el->excludes[i];
- const char *name, *exclude = x->pattern;
+ const char *exclude = x->pattern;
int to_exclude = x->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
- int namelen, prefix = x->nowildcardlen;
+ int prefix = x->nowildcardlen;
if (x->flags & EXC_FLAG_MUSTBEDIR) {
if (*dtype == DT_UNKNOWN)
@@ -583,36 +630,10 @@ int excluded_from_list(const char *pathname,
continue;
}
- /* match with FNM_PATHNAME:
- * exclude has base (baselen long) implicitly in front of it.
- */
- if (*exclude == '/') {
- exclude++;
- prefix--;
- }
-
- if (pathlen < x->baselen ||
- (x->baselen && pathname[x->baselen-1] != '/') ||
- strncmp_icase(pathname, x->base, x->baselen))
- continue;
-
- 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 (!fnmatch_icase(exclude, name, FNM_PATHNAME))
+ assert(x->baselen == 0 || x->base[x->baselen - 1] == '/');
+ if (match_pathname(pathname, pathlen,
+ x->base, x->baselen ? x->baselen - 1 : 0,
+ exclude, prefix, x->patternlen, x->flags))
return to_exclude;
}
return -1; /* undecided */
diff --git a/dir.h b/dir.h
index d416c5a..11d054a 100644
--- a/dir.h
+++ b/dir.h
@@ -80,6 +80,9 @@ extern int excluded_from_list(const char *pathname, int pathlen, const char *bas
int *dtype, struct exclude_list *el);
extern int match_basename(const char *, int,
const char *, int, int, int);
+extern int match_pathname(const char *, int,
+ const char *, int,
+ const char *, int, int, int);
struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len);
/*
--
1.8.0.rc2.11.g2b79d01
prev parent reply other threads:[~2012-10-14 11:56 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-14 11:55 [PATCH 0/4] nd/attr-match-optim-more updates Nguyễn Thái Ngọc Duy
2012-10-14 11:55 ` [PATCH 1/4] exclude: stricten a length check in EXC_FLAG_ENDSWITH case Nguyễn Thái Ngọc Duy
2012-10-14 11:55 ` [PATCH 2/4] exclude: fix a bug in prefix compare optimization Nguyễn Thái Ngọc Duy
2012-10-14 11:55 ` [PATCH 3/4] exclude/attr: share basename matching code Nguyễn Thái Ngọc Duy
2012-10-14 18:09 ` Junio C Hamano
2012-10-14 11:55 ` Nguyễn Thái Ngọc Duy [this message]
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=1350215742-20761-5-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/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).