match_pathspec() -- return how well the spec matched
This updates the return value from match_pathspec() so that the caller can tell cases between exact match, leading pathname match (i.e. file "foo/bar" matches a pathspec "foo"), or filename glob match. This can be used to prevent "rm dir" from removing "dir/file" without explicitly asking for recursive behaviour with -r flag, for example. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
d4ada4876d
commit
e813d50e35
51
dir.c
51
dir.c
@ -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;
|
||||||
|
4
dir.h
4
dir.h
@ -40,6 +40,10 @@ struct dir_struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern int common_prefix(const char **pathspec);
|
extern int common_prefix(const char **pathspec);
|
||||||
|
|
||||||
|
#define MATCHED_RECURSIVELY 1
|
||||||
|
#define MATCHED_FNMATCH 2
|
||||||
|
#define MATCHED_EXACTLY 3
|
||||||
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
|
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
|
||||||
|
|
||||||
extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen);
|
extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen);
|
||||||
|
Loading…
Reference in New Issue
Block a user