pathspec: add match_pathspec_depth()
match_pathspec_depth() is a clone of match_pathspec() except that it can take depth limit. Computation is a bit lighter compared to match_pathspec() because it's usually precomputed and stored in struct pathspec. In long term, match_pathspec() and match_one() should be removed in favor of this function. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
f1a2ddbbc2
commit
61cf282045
89
dir.c
89
dir.c
@ -199,6 +199,95 @@ int match_pathspec(const char **pathspec, const char *name, int namelen,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does 'match' match 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_pathspec_item(const struct pathspec_item *item, int prefix,
|
||||||
|
const char *name, int namelen)
|
||||||
|
{
|
||||||
|
/* name/namelen has prefix cut off by caller */
|
||||||
|
const char *match = item->match + prefix;
|
||||||
|
int matchlen = item->len - prefix;
|
||||||
|
|
||||||
|
/* If the match was just the prefix, we matched */
|
||||||
|
if (!*match)
|
||||||
|
return MATCHED_RECURSIVELY;
|
||||||
|
|
||||||
|
if (matchlen <= namelen && !strncmp(match, name, matchlen)) {
|
||||||
|
if (matchlen == namelen)
|
||||||
|
return MATCHED_EXACTLY;
|
||||||
|
|
||||||
|
if (match[matchlen-1] == '/' || name[matchlen] == '/')
|
||||||
|
return MATCHED_RECURSIVELY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->has_wildcard && !fnmatch(match, name, 0))
|
||||||
|
return MATCHED_FNMATCH;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_depth(const struct pathspec *ps,
|
||||||
|
const char *name, int namelen,
|
||||||
|
int prefix, char *seen)
|
||||||
|
{
|
||||||
|
int i, retval = 0;
|
||||||
|
|
||||||
|
if (!ps->nr) {
|
||||||
|
if (!ps->recursive || ps->max_depth == -1)
|
||||||
|
return MATCHED_RECURSIVELY;
|
||||||
|
|
||||||
|
if (within_depth(name, namelen, 0, ps->max_depth))
|
||||||
|
return MATCHED_EXACTLY;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
name += prefix;
|
||||||
|
namelen -= prefix;
|
||||||
|
|
||||||
|
for (i = ps->nr - 1; i >= 0; i--) {
|
||||||
|
int how;
|
||||||
|
if (seen && seen[i] == MATCHED_EXACTLY)
|
||||||
|
continue;
|
||||||
|
how = match_pathspec_item(ps->items+i, prefix, name, namelen);
|
||||||
|
if (ps->recursive && ps->max_depth != -1 &&
|
||||||
|
how && how != MATCHED_FNMATCH) {
|
||||||
|
int len = ps->items[i].len;
|
||||||
|
if (name[len] == '/')
|
||||||
|
len++;
|
||||||
|
if (within_depth(name+len, namelen-len, 0, ps->max_depth))
|
||||||
|
how = MATCHED_EXACTLY;
|
||||||
|
else
|
||||||
|
how = 0;
|
||||||
|
}
|
||||||
|
if (how) {
|
||||||
|
if (retval < how)
|
||||||
|
retval = how;
|
||||||
|
if (seen && seen[i] < how)
|
||||||
|
seen[i] = how;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
static int no_wildcard(const char *string)
|
static int no_wildcard(const char *string)
|
||||||
{
|
{
|
||||||
return string[strcspn(string, "*?[{\\")] == '\0';
|
return string[strcspn(string, "*?[{\\")] == '\0';
|
||||||
|
3
dir.h
3
dir.h
@ -65,6 +65,9 @@ struct dir_struct {
|
|||||||
#define MATCHED_FNMATCH 2
|
#define MATCHED_FNMATCH 2
|
||||||
#define MATCHED_EXACTLY 3
|
#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 match_pathspec_depth(const struct pathspec *pathspec,
|
||||||
|
const char *name, int namelen,
|
||||||
|
int prefix, char *seen);
|
||||||
extern int within_depth(const char *name, int namelen, int depth, int max_depth);
|
extern int within_depth(const char *name, int namelen, int depth, int max_depth);
|
||||||
|
|
||||||
extern int fill_directory(struct dir_struct *dir, const char **pathspec);
|
extern int fill_directory(struct dir_struct *dir, const char **pathspec);
|
||||||
|
Loading…
Reference in New Issue
Block a user