Merge branch 'jc/grep' into next

* jc/grep:
  builtin-grep: tighten path wildcard vs tree traversal.
This commit is contained in:
Junio C Hamano 2006-05-02 22:04:16 -07:00
commit e0d7d6402d

View File

@ -26,7 +26,7 @@ static int pathspec_matches(const char **paths, const char *name)
for (i = 0; paths[i]; i++) { for (i = 0; paths[i]; i++) {
const char *match = paths[i]; const char *match = paths[i];
int matchlen = strlen(match); int matchlen = strlen(match);
const char *slash, *cp; const char *cp, *meta;
if ((matchlen <= namelen) && if ((matchlen <= namelen) &&
!strncmp(name, match, matchlen) && !strncmp(name, match, matchlen) &&
@ -38,38 +38,43 @@ static int pathspec_matches(const char **paths, const char *name)
if (name[namelen-1] != '/') if (name[namelen-1] != '/')
continue; continue;
/* We are being asked if the name directory is worth /* We are being asked if the directory ("name") is worth
* descending into. * descending into.
* *
* Find the longest leading directory name that does * Find the longest leading directory name that does
* not have metacharacter in the pathspec; the name * not have metacharacter in the pathspec; the name
* we are looking at must overlap with that directory. * 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; char ch = *cp;
if (ch == '/') if (ch == '*' || ch == '[' || ch == '?') {
slash = cp; meta = cp;
if (ch == '*' || ch == '[')
break; break;
} }
if (!slash) }
slash = match; /* toplevel */ if (!meta)
else meta = cp; /* fully literal */
slash++;
if (namelen <= slash - match) { if (namelen <= meta - match) {
/* Looking at "Documentation/" and /* Looking at "Documentation/" and
* the pattern says "Documentation/howto/", or * the pattern says "Documentation/howto/", or
* "Documentation/diff*.txt". * "Documentation/diff*.txt". The name we
* have should match prefix.
*/ */
if (!memcmp(match, name, namelen)) if (!memcmp(match, name, namelen))
return 1; return 1;
continue;
} }
else {
if (meta - match < namelen) {
/* Looking at "Documentation/howto/" and /* 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; return 1;
continue;
} }
} }
return 0; return 0;