mirror of
https://github.com/git/git.git
synced 2025-04-01 05:09:22 +00:00
tree_entry_interesting(): refactor into separate smaller functions
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
48932677d6
commit
58c4d66619
170
tree-walk.c
170
tree-walk.c
@ -456,6 +456,90 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int match_entry(const struct name_entry *entry, int pathlen,
|
||||||
|
const char *match, int matchlen,
|
||||||
|
int *never_interesting)
|
||||||
|
{
|
||||||
|
int m = -1; /* signals that we haven't called strncmp() */
|
||||||
|
|
||||||
|
if (*never_interesting) {
|
||||||
|
/*
|
||||||
|
* We have not seen any match that sorts later
|
||||||
|
* than the current path.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does match sort strictly earlier than path
|
||||||
|
* with their common parts?
|
||||||
|
*/
|
||||||
|
m = strncmp(match, entry->path,
|
||||||
|
(matchlen < pathlen) ? matchlen : pathlen);
|
||||||
|
if (m < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we come here even once, that means there is at
|
||||||
|
* least one pathspec that would sort equal to or
|
||||||
|
* later than the path we are currently looking at.
|
||||||
|
* In other words, if we have never reached this point
|
||||||
|
* after iterating all pathspecs, it means all
|
||||||
|
* pathspecs are either outside of base, or inside the
|
||||||
|
* base but sorts strictly earlier than the current
|
||||||
|
* one. In either case, they will never match the
|
||||||
|
* subsequent entries. In such a case, we initialized
|
||||||
|
* the variable to -1 and that is what will be
|
||||||
|
* returned, allowing the caller to terminate early.
|
||||||
|
*/
|
||||||
|
*never_interesting = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathlen > matchlen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (matchlen > pathlen) {
|
||||||
|
if (match[pathlen] != '/')
|
||||||
|
return 0;
|
||||||
|
if (!S_ISDIR(entry->mode))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m == -1)
|
||||||
|
/*
|
||||||
|
* we cheated and did not do strncmp(), so we do
|
||||||
|
* that here.
|
||||||
|
*/
|
||||||
|
m = strncmp(match, entry->path, pathlen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If common part matched earlier then it is a hit,
|
||||||
|
* because we rejected the case where path is not a
|
||||||
|
* leading directory and is shorter than match.
|
||||||
|
*/
|
||||||
|
if (!m)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int match_dir_prefix(const char *base, int baselen,
|
||||||
|
const char *match, int matchlen)
|
||||||
|
{
|
||||||
|
if (strncmp(base, match, matchlen))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the base is a subdirectory of a path which
|
||||||
|
* was specified, all of them are interesting.
|
||||||
|
*/
|
||||||
|
if (!matchlen ||
|
||||||
|
base[matchlen] == '/' ||
|
||||||
|
match[matchlen - 1] == '/')
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Just a random prefix match */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is a tree entry interesting given the pathspec we have?
|
* Is a tree entry interesting given the pathspec we have?
|
||||||
*
|
*
|
||||||
@ -468,13 +552,12 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch
|
|||||||
* - negative for "no, and no subsequent entries will be either"
|
* - negative for "no, and no subsequent entries will be either"
|
||||||
*/
|
*/
|
||||||
int tree_entry_interesting(const struct name_entry *entry,
|
int tree_entry_interesting(const struct name_entry *entry,
|
||||||
const struct strbuf *base_buf,
|
const struct strbuf *base,
|
||||||
const struct pathspec *ps)
|
const struct pathspec *ps)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int pathlen, baselen = base_buf->len;
|
int pathlen, baselen = base->len;
|
||||||
int never_interesting = -1;
|
int never_interesting = -1;
|
||||||
const char *base = base_buf->buf;
|
|
||||||
|
|
||||||
if (!ps || !ps->nr)
|
if (!ps || !ps->nr)
|
||||||
return 2;
|
return 2;
|
||||||
@ -485,88 +568,21 @@ int tree_entry_interesting(const struct name_entry *entry,
|
|||||||
const struct pathspec_item *item = ps->items+i;
|
const struct pathspec_item *item = ps->items+i;
|
||||||
const char *match = item->match;
|
const char *match = item->match;
|
||||||
int matchlen = item->len;
|
int matchlen = item->len;
|
||||||
int m = -1; /* signals that we haven't called strncmp() */
|
|
||||||
|
|
||||||
if (baselen >= matchlen) {
|
if (baselen >= matchlen) {
|
||||||
/* If it doesn't match, move along... */
|
/* If it doesn't match, move along... */
|
||||||
if (strncmp(base, match, matchlen))
|
if (!match_dir_prefix(base->buf, baselen, match, matchlen))
|
||||||
continue;
|
continue;
|
||||||
|
return 2;
|
||||||
/*
|
|
||||||
* If the base is a subdirectory of a path which
|
|
||||||
* was specified, all of them are interesting.
|
|
||||||
*/
|
|
||||||
if (!matchlen ||
|
|
||||||
base[matchlen] == '/' ||
|
|
||||||
match[matchlen - 1] == '/')
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
/* Just a random prefix match */
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Does the base match? */
|
/* Does the base match? */
|
||||||
if (strncmp(base, match, baselen))
|
if (!strncmp(base->buf, match, baselen)) {
|
||||||
continue;
|
if (match_entry(entry, pathlen,
|
||||||
|
match + baselen, matchlen - baselen,
|
||||||
match += baselen;
|
&never_interesting))
|
||||||
matchlen -= baselen;
|
return 1;
|
||||||
|
|
||||||
if (never_interesting) {
|
|
||||||
/*
|
|
||||||
* We have not seen any match that sorts later
|
|
||||||
* than the current path.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Does match sort strictly earlier than path
|
|
||||||
* with their common parts?
|
|
||||||
*/
|
|
||||||
m = strncmp(match, entry->path,
|
|
||||||
(matchlen < pathlen) ? matchlen : pathlen);
|
|
||||||
if (m < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we come here even once, that means there is at
|
|
||||||
* least one pathspec that would sort equal to or
|
|
||||||
* later than the path we are currently looking at.
|
|
||||||
* In other words, if we have never reached this point
|
|
||||||
* after iterating all pathspecs, it means all
|
|
||||||
* pathspecs are either outside of base, or inside the
|
|
||||||
* base but sorts strictly earlier than the current
|
|
||||||
* one. In either case, they will never match the
|
|
||||||
* subsequent entries. In such a case, we initialized
|
|
||||||
* the variable to -1 and that is what will be
|
|
||||||
* returned, allowing the caller to terminate early.
|
|
||||||
*/
|
|
||||||
never_interesting = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pathlen > matchlen)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (matchlen > pathlen) {
|
|
||||||
if (match[pathlen] != '/')
|
|
||||||
continue;
|
|
||||||
if (!S_ISDIR(entry->mode))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m == -1)
|
|
||||||
/*
|
|
||||||
* we cheated and did not do strncmp(), so we do
|
|
||||||
* that here.
|
|
||||||
*/
|
|
||||||
m = strncmp(match, entry->path, pathlen);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If common part matched earlier then it is a hit,
|
|
||||||
* because we rejected the case where path is not a
|
|
||||||
* leading directory and is shorter than match.
|
|
||||||
*/
|
|
||||||
if (!m)
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
return never_interesting; /* No matches */
|
return never_interesting; /* No matches */
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user