@ -40,6 +40,18 @@ int common_prefix(const char **pathspec)
return prefix;
return prefix;
}
}
/*
* Does 'match' matches the given name?
* A match is found if
*
* (1) the 'match' string is leading directory of 'name', or
* (2) the 'match' string is a wildcard and matches 'name', or
* (3) the 'match' string is exactly the same as 'name'.
*
* and the return value tells which case it was.
*
* It returns 0 when there is no match.
*/
static int match_one(const char *match, const char *name, int namelen)
static int match_one(const char *match, const char *name, int namelen)
{
{
int matchlen;
int matchlen;
@ -47,27 +59,30 @@ static int match_one(const char *match, const char *name, int namelen)
/* If the match was just the prefix, we matched */
/* If the match was just the prefix, we matched */
matchlen = strlen(match);
matchlen = strlen(match);
if (!matchlen)
if (!matchlen)
return 1;
return MATCHED_RECURSIVELY;
/*
/*
* If we don't match the matchstring exactly,
* If we don't match the matchstring exactly,
* we need to match by fnmatch
* we need to match by fnmatch
*/
*/
if (strncmp(match, name, matchlen))
if (strncmp(match, name, matchlen))
return !fnmatch(match, name, 0);
return !fnmatch(match, name, 0) ? MATCHED_FNMATCH : 0;
/*
if (!name[matchlen])
* If we did match the string exactly, we still
return MATCHED_EXACTLY;
* need to make sure that it happened on a path
if (match[matchlen-1] == '/' || name[matchlen] == '/')
* component boundary (ie either the last character
return MATCHED_RECURSIVELY;
* of the match was '/', or the next character of
return 0;
* the name was '/' or the terminating NUL.
*/
return match[matchlen-1] == '/' ||
name[matchlen] == '/' ||
!name[matchlen];
}
}
/*
* Given a name and a list of pathspecs, see if the name matches
* any of the pathspecs. The caller is also interested in seeing
* all pathspec matches some names it calls this function with
* (otherwise the user could have mistyped the unmatched pathspec),
* and a mark is left in seen[] array for pathspec element that
* actually matched anything.
*/
int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen)
int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen)
{
{
int retval;
int retval;
@ -77,12 +92,16 @@ int match_pathspec(const char **pathspec, const char *name, int namelen, int pre
namelen -= prefix;
namelen -= prefix;
for (retval = 0; (match = *pathspec++) != NULL; seen++) {
for (retval = 0; (match = *pathspec++) != NULL; seen++) {
if (retval & *seen)
int how;
if (retval && *seen == MATCHED_EXACTLY)
continue;
continue;
match += prefix;
match += prefix;
if (match_one(match, name, namelen)) {
how = match_one(match, name, namelen);
retval = 1;
if (how) {
*seen = 1;
if (retval < how)
retval = how;
if (*seen < how)
*seen = how;
}
}
}
}
return retval;
return retval;