summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <junkio@cox.net>2006-05-02 17:27:07 -0700
committerLibravatar Junio C Hamano <junkio@cox.net>2006-05-02 17:30:07 -0700
commit1e3d90e0135274ad89cd8ee0722e2dd043ec0052 (patch)
tree302b1811381fab29a1591de70e632663742ea1d2
parentbuiltin-grep: support -w (--word-regexp). (diff)
downloadtgif-1e3d90e0135274ad89cd8ee0722e2dd043ec0052.tar.xz
builtin-grep: tighten path wildcard vs tree traversal.
The earlier code descended into Documentation/technical when given "Documentation/how*" as the pattern, which was too loose. Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r--builtin-grep.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/builtin-grep.c b/builtin-grep.c
index 09e3677824..2124fa62e8 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -26,7 +26,7 @@ static int pathspec_matches(const char **paths, const char *name)
for (i = 0; paths[i]; i++) {
const char *match = paths[i];
int matchlen = strlen(match);
- const char *slash, *cp;
+ const char *cp, *meta;
if ((matchlen <= namelen) &&
!strncmp(name, match, matchlen) &&
@@ -38,38 +38,43 @@ static int pathspec_matches(const char **paths, const char *name)
if (name[namelen-1] != '/')
continue;
- /* We are being asked if the name directory is worth
+ /* We are being asked if the directory ("name") is worth
* descending into.
*
* Find the longest leading directory name that does
* not have metacharacter in the pathspec; the name
* we are looking at must overlap with that directory.
*/
- for (cp = match, slash = NULL; cp - match < matchlen; cp++) {
+ for (cp = match, meta = NULL; cp - match < matchlen; cp++) {
char ch = *cp;
- if (ch == '/')
- slash = cp;
- if (ch == '*' || ch == '[')
+ if (ch == '*' || ch == '[' || ch == '?') {
+ meta = cp;
break;
+ }
}
- if (!slash)
- slash = match; /* toplevel */
- else
- slash++;
- if (namelen <= slash - match) {
+ if (!meta)
+ meta = cp; /* fully literal */
+
+ if (namelen <= meta - match) {
/* Looking at "Documentation/" and
* the pattern says "Documentation/howto/", or
- * "Documentation/diff*.txt".
+ * "Documentation/diff*.txt". The name we
+ * have should match prefix.
*/
if (!memcmp(match, name, namelen))
return 1;
+ continue;
}
- else {
+
+ if (meta - match < namelen) {
/* Looking at "Documentation/howto/" and
- * the pattern says "Documentation/h*".
+ * the pattern says "Documentation/h*";
+ * match up to "Do.../h"; this avoids descending
+ * into "Documentation/technical/".
*/
- if (!memcmp(match, name, slash - match))
+ if (!memcmp(match, name, meta - match))
return 1;
+ continue;
}
}
return 0;