зеркало из https://github.com/microsoft/git.git
remove match_pathspec() in favor of match_pathspec_depth()
match_pathspec_depth was created to replace match_pathspec (see
61cf282
(pathspec: add match_pathspec_depth() - 2010-12-15). It took
more than two years, but the replacement finally happens :-)
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:
Родитель
9a08727443
Коммит
84b8b5d1fa
|
@ -195,23 +195,21 @@ int add_files_to_cache(const char *prefix,
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WARN_IMPLICIT_DOT (1u << 0)
|
#define WARN_IMPLICIT_DOT (1u << 0)
|
||||||
static char *prune_directory(struct dir_struct *dir, const char **pathspec,
|
static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec,
|
||||||
int prefix, unsigned flag)
|
int prefix, unsigned flag)
|
||||||
{
|
{
|
||||||
char *seen;
|
char *seen;
|
||||||
int i, specs;
|
int i;
|
||||||
struct dir_entry **src, **dst;
|
struct dir_entry **src, **dst;
|
||||||
|
|
||||||
for (specs = 0; pathspec[specs]; specs++)
|
seen = xcalloc(pathspec->nr, 1);
|
||||||
/* nothing */;
|
|
||||||
seen = xcalloc(specs, 1);
|
|
||||||
|
|
||||||
src = dst = dir->entries;
|
src = dst = dir->entries;
|
||||||
i = dir->nr;
|
i = dir->nr;
|
||||||
while (--i >= 0) {
|
while (--i >= 0) {
|
||||||
struct dir_entry *entry = *src++;
|
struct dir_entry *entry = *src++;
|
||||||
if (match_pathspec(pathspec, entry->name, entry->len,
|
if (match_pathspec_depth(pathspec, entry->name, entry->len,
|
||||||
prefix, seen))
|
prefix, seen))
|
||||||
*dst++ = entry;
|
*dst++ = entry;
|
||||||
else if (flag & WARN_IMPLICIT_DOT)
|
else if (flag & WARN_IMPLICIT_DOT)
|
||||||
/*
|
/*
|
||||||
|
@ -225,7 +223,7 @@ static char *prune_directory(struct dir_struct *dir, const char **pathspec,
|
||||||
warn_pathless_add();
|
warn_pathless_add();
|
||||||
}
|
}
|
||||||
dir->nr = dst - dir->entries;
|
dir->nr = dst - dir->entries;
|
||||||
add_pathspec_matches_against_index(pathspec, seen, specs);
|
add_pathspec_matches_against_index(pathspec, seen);
|
||||||
return seen;
|
return seen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,7 +521,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||||
/* This picks up the paths that are not tracked */
|
/* This picks up the paths that are not tracked */
|
||||||
baselen = fill_directory(&dir, implicit_dot ? &empty_pathspec : &pathspec);
|
baselen = fill_directory(&dir, implicit_dot ? &empty_pathspec : &pathspec);
|
||||||
if (pathspec.nr)
|
if (pathspec.nr)
|
||||||
seen = prune_directory(&dir, pathspec.raw, baselen,
|
seen = prune_directory(&dir, &pathspec, baselen,
|
||||||
implicit_dot ? WARN_IMPLICIT_DOT : 0);
|
implicit_dot ? WARN_IMPLICIT_DOT : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,23 +536,23 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!seen)
|
if (!seen)
|
||||||
seen = find_pathspecs_matching_against_index(pathspec.raw);
|
seen = find_pathspecs_matching_against_index(&pathspec);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* file_exists() assumes exact match
|
* file_exists() assumes exact match
|
||||||
*/
|
*/
|
||||||
GUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP);
|
GUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP);
|
||||||
|
|
||||||
for (i = 0; pathspec.raw[i]; i++) {
|
for (i = 0; i < pathspec.nr; i++) {
|
||||||
if (!seen[i] && pathspec.raw[i][0]
|
const char *path = pathspec.items[i].match;
|
||||||
&& !file_exists(pathspec.raw[i])) {
|
if (!seen[i] && !file_exists(path)) {
|
||||||
if (ignore_missing) {
|
if (ignore_missing) {
|
||||||
int dtype = DT_UNKNOWN;
|
int dtype = DT_UNKNOWN;
|
||||||
if (is_excluded(&dir, pathspec.raw[i], &dtype))
|
if (is_excluded(&dir, path, &dtype))
|
||||||
dir_add_ignored(&dir, pathspec.raw[i], strlen(pathspec.raw[i]));
|
dir_add_ignored(&dir, path, pathspec.items[i].len);
|
||||||
} else
|
} else
|
||||||
die(_("pathspec '%s' did not match any files"),
|
die(_("pathspec '%s' did not match any files"),
|
||||||
pathspec.raw[i]);
|
pathspec.items[i].original);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(seen);
|
free(seen);
|
||||||
|
|
|
@ -94,9 +94,9 @@ static int check_ignore(struct dir_struct *dir,
|
||||||
* should not be ignored, in order to be consistent with
|
* should not be ignored, in order to be consistent with
|
||||||
* 'git status', 'git add' etc.
|
* 'git status', 'git add' etc.
|
||||||
*/
|
*/
|
||||||
seen = find_pathspecs_matching_against_index(pathspec.raw);
|
seen = find_pathspecs_matching_against_index(&pathspec);
|
||||||
for (i = 0; i < pathspec.nr; i++) {
|
for (i = 0; i < pathspec.nr; i++) {
|
||||||
full_path = pathspec.raw[i];
|
full_path = pathspec.items[i].match;
|
||||||
exclude = NULL;
|
exclude = NULL;
|
||||||
if (!seen[i]) {
|
if (!seen[i]) {
|
||||||
exclude = last_exclude_matching(dir, full_path, &dtype);
|
exclude = last_exclude_matching(dir, full_path, &dtype);
|
||||||
|
|
107
dir.c
107
dir.c
|
@ -171,113 +171,6 @@ int within_depth(const char *name, int namelen,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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_one(const char *match, const char *name, int namelen)
|
|
||||||
{
|
|
||||||
int matchlen;
|
|
||||||
int literal = limit_pathspec_to_literal();
|
|
||||||
|
|
||||||
/* If the match was just the prefix, we matched */
|
|
||||||
if (!*match)
|
|
||||||
return MATCHED_RECURSIVELY;
|
|
||||||
|
|
||||||
if (ignore_case) {
|
|
||||||
for (;;) {
|
|
||||||
unsigned char c1 = tolower(*match);
|
|
||||||
unsigned char c2 = tolower(*name);
|
|
||||||
if (c1 == '\0' || (!literal && is_glob_special(c1)))
|
|
||||||
break;
|
|
||||||
if (c1 != c2)
|
|
||||||
return 0;
|
|
||||||
match++;
|
|
||||||
name++;
|
|
||||||
namelen--;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (;;) {
|
|
||||||
unsigned char c1 = *match;
|
|
||||||
unsigned char c2 = *name;
|
|
||||||
if (c1 == '\0' || (!literal && is_glob_special(c1)))
|
|
||||||
break;
|
|
||||||
if (c1 != c2)
|
|
||||||
return 0;
|
|
||||||
match++;
|
|
||||||
name++;
|
|
||||||
namelen--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we don't match the matchstring exactly,
|
|
||||||
* we need to match by fnmatch
|
|
||||||
*/
|
|
||||||
matchlen = strlen(match);
|
|
||||||
if (strncmp_icase(match, name, matchlen)) {
|
|
||||||
if (literal)
|
|
||||||
return 0;
|
|
||||||
return !fnmatch_icase(match, name, 0) ? MATCHED_FNMATCH : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (namelen == matchlen)
|
|
||||||
return MATCHED_EXACTLY;
|
|
||||||
if (match[matchlen-1] == '/' || name[matchlen] == '/')
|
|
||||||
return MATCHED_RECURSIVELY;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given a name and a list of pathspecs, returns the nature of the
|
|
||||||
* closest (i.e. most specific) match of the name to any of the
|
|
||||||
* pathspecs.
|
|
||||||
*
|
|
||||||
* The caller typically calls this multiple times with the same
|
|
||||||
* pathspec and seen[] array but with different name/namelen
|
|
||||||
* (e.g. entries from the index) and is interested in seeing if and
|
|
||||||
* how each pathspec matches all the names it calls this function
|
|
||||||
* with. A mark is left in the seen[] array for each pathspec element
|
|
||||||
* indicating the closest type of match that element achieved, so if
|
|
||||||
* seen[n] remains zero after multiple invocations, that means the nth
|
|
||||||
* pathspec did not match any names, which could indicate that the
|
|
||||||
* user mistyped the nth pathspec.
|
|
||||||
*/
|
|
||||||
int match_pathspec(const char **pathspec, const char *name, int namelen,
|
|
||||||
int prefix, char *seen)
|
|
||||||
{
|
|
||||||
int i, retval = 0;
|
|
||||||
|
|
||||||
if (!pathspec)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
name += prefix;
|
|
||||||
namelen -= prefix;
|
|
||||||
|
|
||||||
for (i = 0; pathspec[i] != NULL; i++) {
|
|
||||||
int how;
|
|
||||||
const char *match = pathspec[i] + prefix;
|
|
||||||
if (seen && seen[i] == MATCHED_EXACTLY)
|
|
||||||
continue;
|
|
||||||
how = match_one(match, name, namelen);
|
|
||||||
if (how) {
|
|
||||||
if (retval < how)
|
|
||||||
retval = how;
|
|
||||||
if (seen && seen[i] < how)
|
|
||||||
seen[i] = how;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Does 'match' match the given name?
|
* Does 'match' match the given name?
|
||||||
* A match is found if
|
* A match is found if
|
||||||
|
|
1
dir.h
1
dir.h
|
@ -131,7 +131,6 @@ struct dir_struct {
|
||||||
extern int simple_length(const char *match);
|
extern int simple_length(const char *match);
|
||||||
extern int no_wildcard(const char *string);
|
extern int no_wildcard(const char *string);
|
||||||
extern char *common_prefix(const struct pathspec *pathspec);
|
extern char *common_prefix(const struct pathspec *pathspec);
|
||||||
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,
|
extern int match_pathspec_depth(const struct pathspec *pathspec,
|
||||||
const char *name, int namelen,
|
const char *name, int namelen,
|
||||||
int prefix, char *seen);
|
int prefix, char *seen);
|
||||||
|
|
19
pathspec.c
19
pathspec.c
|
@ -15,8 +15,8 @@
|
||||||
* If seen[] has not already been written to, it may make sense
|
* If seen[] has not already been written to, it may make sense
|
||||||
* to use find_pathspecs_matching_against_index() instead.
|
* to use find_pathspecs_matching_against_index() instead.
|
||||||
*/
|
*/
|
||||||
void add_pathspec_matches_against_index(const char **pathspec,
|
void add_pathspec_matches_against_index(const struct pathspec *pathspec,
|
||||||
char *seen, int specs)
|
char *seen)
|
||||||
{
|
{
|
||||||
int num_unmatched = 0, i;
|
int num_unmatched = 0, i;
|
||||||
|
|
||||||
|
@ -26,14 +26,14 @@ void add_pathspec_matches_against_index(const char **pathspec,
|
||||||
* mistakenly think that the user gave a pathspec that did not match
|
* mistakenly think that the user gave a pathspec that did not match
|
||||||
* anything.
|
* anything.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < specs; i++)
|
for (i = 0; i < pathspec->nr; i++)
|
||||||
if (!seen[i])
|
if (!seen[i])
|
||||||
num_unmatched++;
|
num_unmatched++;
|
||||||
if (!num_unmatched)
|
if (!num_unmatched)
|
||||||
return;
|
return;
|
||||||
for (i = 0; i < active_nr; i++) {
|
for (i = 0; i < active_nr; i++) {
|
||||||
struct cache_entry *ce = active_cache[i];
|
struct cache_entry *ce = active_cache[i];
|
||||||
match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen);
|
match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, seen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,15 +45,10 @@ void add_pathspec_matches_against_index(const char **pathspec,
|
||||||
* nature of the "closest" (i.e. most specific) matches which each of the
|
* nature of the "closest" (i.e. most specific) matches which each of the
|
||||||
* given pathspecs achieves against all items in the index.
|
* given pathspecs achieves against all items in the index.
|
||||||
*/
|
*/
|
||||||
char *find_pathspecs_matching_against_index(const char **pathspec)
|
char *find_pathspecs_matching_against_index(const struct pathspec *pathspec)
|
||||||
{
|
{
|
||||||
char *seen;
|
char *seen = xcalloc(pathspec->nr, 1);
|
||||||
int i;
|
add_pathspec_matches_against_index(pathspec, seen);
|
||||||
|
|
||||||
for (i = 0; pathspec[i]; i++)
|
|
||||||
; /* just counting */
|
|
||||||
seen = xcalloc(i, 1);
|
|
||||||
add_pathspec_matches_against_index(pathspec, seen, i);
|
|
||||||
return seen;
|
return seen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,8 @@ extern void free_pathspec(struct pathspec *);
|
||||||
|
|
||||||
extern int limit_pathspec_to_literal(void);
|
extern int limit_pathspec_to_literal(void);
|
||||||
|
|
||||||
extern char *find_pathspecs_matching_against_index(const char **pathspec);
|
extern char *find_pathspecs_matching_against_index(const struct pathspec *pathspec);
|
||||||
extern void add_pathspec_matches_against_index(const char **pathspec, char *seen, int specs);
|
extern void add_pathspec_matches_against_index(const struct pathspec *pathspec, char *seen);
|
||||||
extern const char *check_path_for_gitlink(const char *path);
|
extern const char *check_path_for_gitlink(const char *path);
|
||||||
extern void die_if_path_beyond_symlink(const char *path, const char *prefix);
|
extern void die_if_path_beyond_symlink(const char *path, const char *prefix);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче