mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
Merge branch 'ds/include-exclude'
The internal code originally invented for ".gitignore" processing got reshuffled and renamed to make it less tied to "excluding" and stress more that it is about "matching", as it has been reused for things like sparse checkout specification that want to check if a path is "included". * ds/include-exclude: unpack-trees: rename 'is_excluded_from_list()' treewide: rename 'exclude' methods to 'pattern' treewide: rename 'EXCL_FLAG_' to 'PATTERN_FLAG_' treewide: rename 'struct exclude_list' to 'struct pattern_list' treewide: rename 'struct exclude' to 'struct path_pattern'
This commit is contained in:
commit
9755f70fe6
|
@ -10,7 +10,7 @@ Fixes since v2.7
|
|||
setting GIT_WORK_TREE environment themselves.
|
||||
|
||||
* The "exclude_list" structure has the usual "alloc, nr" pair of
|
||||
fields to be used by ALLOC_GROW(), but clear_exclude_list() forgot
|
||||
fields to be used by ALLOC_GROW(), but clear_pattern_list() forgot
|
||||
to reset 'alloc' to 0 when it cleared 'nr' to discard the managed
|
||||
array.
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ notes for details).
|
|||
setting GIT_WORK_TREE environment themselves.
|
||||
|
||||
* The "exclude_list" structure has the usual "alloc, nr" pair of
|
||||
fields to be used by ALLOC_GROW(), but clear_exclude_list() forgot
|
||||
fields to be used by ALLOC_GROW(), but clear_pattern_list() forgot
|
||||
to reset 'alloc' to 0 when it cleared 'nr' to discard the managed
|
||||
array.
|
||||
|
||||
|
|
|
@ -111,11 +111,11 @@ marked. If you to exclude files, make sure you have loaded index first.
|
|||
* Prepare `struct dir_struct dir` and clear it with `memset(&dir, 0,
|
||||
sizeof(dir))`.
|
||||
|
||||
* To add single exclude pattern, call `add_exclude_list()` and then
|
||||
`add_exclude()`.
|
||||
* To add single exclude pattern, call `add_pattern_list()` and then
|
||||
`add_pattern()`.
|
||||
|
||||
* To add patterns from a file (e.g. `.git/info/exclude`), call
|
||||
`add_excludes_from_file()` , and/or set `dir.exclude_per_dir`. A
|
||||
`add_patterns_from_file()` , and/or set `dir.exclude_per_dir`. A
|
||||
short-hand function `setup_standard_excludes()` can be used to set
|
||||
up the standard set of exclude settings.
|
||||
|
||||
|
|
10
attr.c
10
attr.c
|
@ -259,7 +259,7 @@ struct pattern {
|
|||
const char *pattern;
|
||||
int patternlen;
|
||||
int nowildcardlen;
|
||||
unsigned flags; /* EXC_FLAG_* */
|
||||
unsigned flags; /* PATTERN_FLAG_* */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -400,11 +400,11 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
|
|||
char *p = (char *)&(res->state[num_attr]);
|
||||
memcpy(p, name, namelen);
|
||||
res->u.pat.pattern = p;
|
||||
parse_exclude_pattern(&res->u.pat.pattern,
|
||||
parse_path_pattern(&res->u.pat.pattern,
|
||||
&res->u.pat.patternlen,
|
||||
&res->u.pat.flags,
|
||||
&res->u.pat.nowildcardlen);
|
||||
if (res->u.pat.flags & EXC_FLAG_NEGATIVE) {
|
||||
if (res->u.pat.flags & PATTERN_FLAG_NEGATIVE) {
|
||||
warning(_("Negative patterns are ignored in git attributes\n"
|
||||
"Use '\\!' for literal leading exclamation."));
|
||||
goto fail_return;
|
||||
|
@ -991,10 +991,10 @@ static int path_matches(const char *pathname, int pathlen,
|
|||
int prefix = pat->nowildcardlen;
|
||||
int isdir = (pathlen && pathname[pathlen - 1] == '/');
|
||||
|
||||
if ((pat->flags & EXC_FLAG_MUSTBEDIR) && !isdir)
|
||||
if ((pat->flags & PATTERN_FLAG_MUSTBEDIR) && !isdir)
|
||||
return 0;
|
||||
|
||||
if (pat->flags & EXC_FLAG_NODIR) {
|
||||
if (pat->flags & PATTERN_FLAG_NODIR) {
|
||||
return match_basename(pathname + basename_offset,
|
||||
pathlen - basename_offset - isdir,
|
||||
pattern, prefix,
|
||||
|
|
|
@ -32,19 +32,19 @@ static const struct option check_ignore_options[] = {
|
|||
OPT_END()
|
||||
};
|
||||
|
||||
static void output_exclude(const char *path, struct exclude *exclude)
|
||||
static void output_pattern(const char *path, struct path_pattern *pattern)
|
||||
{
|
||||
char *bang = (exclude && exclude->flags & EXC_FLAG_NEGATIVE) ? "!" : "";
|
||||
char *slash = (exclude && exclude->flags & EXC_FLAG_MUSTBEDIR) ? "/" : "";
|
||||
char *bang = (pattern && pattern->flags & PATTERN_FLAG_NEGATIVE) ? "!" : "";
|
||||
char *slash = (pattern && pattern->flags & PATTERN_FLAG_MUSTBEDIR) ? "/" : "";
|
||||
if (!nul_term_line) {
|
||||
if (!verbose) {
|
||||
write_name_quoted(path, stdout, '\n');
|
||||
} else {
|
||||
if (exclude) {
|
||||
quote_c_style(exclude->el->src, NULL, stdout, 0);
|
||||
if (pattern) {
|
||||
quote_c_style(pattern->pl->src, NULL, stdout, 0);
|
||||
printf(":%d:%s%s%s\t",
|
||||
exclude->srcpos,
|
||||
bang, exclude->pattern, slash);
|
||||
pattern->srcpos,
|
||||
bang, pattern->pattern, slash);
|
||||
}
|
||||
else {
|
||||
printf("::\t");
|
||||
|
@ -56,11 +56,11 @@ static void output_exclude(const char *path, struct exclude *exclude)
|
|||
if (!verbose) {
|
||||
printf("%s%c", path, '\0');
|
||||
} else {
|
||||
if (exclude)
|
||||
if (pattern)
|
||||
printf("%s%c%d%c%s%s%s%c%s%c",
|
||||
exclude->el->src, '\0',
|
||||
exclude->srcpos, '\0',
|
||||
bang, exclude->pattern, slash, '\0',
|
||||
pattern->pl->src, '\0',
|
||||
pattern->srcpos, '\0',
|
||||
bang, pattern->pattern, slash, '\0',
|
||||
path, '\0');
|
||||
else
|
||||
printf("%c%c%c%s%c", '\0', '\0', '\0', path, '\0');
|
||||
|
@ -74,7 +74,7 @@ static int check_ignore(struct dir_struct *dir,
|
|||
const char *full_path;
|
||||
char *seen;
|
||||
int num_ignored = 0, i;
|
||||
struct exclude *exclude;
|
||||
struct path_pattern *pattern;
|
||||
struct pathspec pathspec;
|
||||
|
||||
if (!argc) {
|
||||
|
@ -103,15 +103,15 @@ static int check_ignore(struct dir_struct *dir,
|
|||
seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
|
||||
for (i = 0; i < pathspec.nr; i++) {
|
||||
full_path = pathspec.items[i].match;
|
||||
exclude = NULL;
|
||||
pattern = NULL;
|
||||
if (!seen[i]) {
|
||||
int dtype = DT_UNKNOWN;
|
||||
exclude = last_exclude_matching(dir, &the_index,
|
||||
pattern = last_matching_pattern(dir, &the_index,
|
||||
full_path, &dtype);
|
||||
}
|
||||
if (!quiet && (exclude || show_non_matching))
|
||||
output_exclude(pathspec.items[i].original, exclude);
|
||||
if (exclude)
|
||||
if (!quiet && (pattern || show_non_matching))
|
||||
output_pattern(pathspec.items[i].original, pattern);
|
||||
if (pattern)
|
||||
num_ignored++;
|
||||
}
|
||||
free(seen);
|
||||
|
|
|
@ -648,7 +648,7 @@ static int filter_by_patterns_cmd(void)
|
|||
struct strbuf confirm = STRBUF_INIT;
|
||||
struct strbuf **ignore_list;
|
||||
struct string_list_item *item;
|
||||
struct exclude_list *el;
|
||||
struct pattern_list *pl;
|
||||
int changed = -1, i;
|
||||
|
||||
for (;;) {
|
||||
|
@ -671,7 +671,7 @@ static int filter_by_patterns_cmd(void)
|
|||
break;
|
||||
|
||||
memset(&dir, 0, sizeof(dir));
|
||||
el = add_exclude_list(&dir, EXC_CMDL, "manual exclude");
|
||||
pl = add_pattern_list(&dir, EXC_CMDL, "manual exclude");
|
||||
ignore_list = strbuf_split_max(&confirm, ' ', 0);
|
||||
|
||||
for (i = 0; ignore_list[i]; i++) {
|
||||
|
@ -679,7 +679,7 @@ static int filter_by_patterns_cmd(void)
|
|||
if (!ignore_list[i]->len)
|
||||
continue;
|
||||
|
||||
add_exclude(ignore_list[i]->buf, "", 0, el, -(i+1));
|
||||
add_pattern(ignore_list[i]->buf, "", 0, pl, -(i+1));
|
||||
}
|
||||
|
||||
changed = 0;
|
||||
|
@ -901,7 +901,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
|||
struct pathspec pathspec;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct string_list exclude_list = STRING_LIST_INIT_NODUP;
|
||||
struct exclude_list *el;
|
||||
struct pattern_list *pl;
|
||||
struct string_list_item *item;
|
||||
const char *qname;
|
||||
struct option options[] = {
|
||||
|
@ -958,9 +958,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
|||
if (!ignored)
|
||||
setup_standard_excludes(&dir);
|
||||
|
||||
el = add_exclude_list(&dir, EXC_CMDL, "--exclude option");
|
||||
pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option");
|
||||
for (i = 0; i < exclude_list.nr; i++)
|
||||
add_exclude(exclude_list.items[i].string, "", 0, el, -(i+1));
|
||||
add_pattern(exclude_list.items[i].string, "", 0, pl, -(i+1));
|
||||
|
||||
parse_pathspec(&pathspec, 0,
|
||||
PATHSPEC_PREFER_CWD,
|
||||
|
|
|
@ -492,7 +492,7 @@ static int option_parse_exclude_from(const struct option *opt,
|
|||
BUG_ON_OPT_NEG(unset);
|
||||
|
||||
exc_given = 1;
|
||||
add_excludes_from_file(dir, arg);
|
||||
add_patterns_from_file(dir, arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -516,7 +516,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
|
|||
int require_work_tree = 0, show_tag = 0, i;
|
||||
const char *max_prefix;
|
||||
struct dir_struct dir;
|
||||
struct exclude_list *el;
|
||||
struct pattern_list *pl;
|
||||
struct string_list exclude_list = STRING_LIST_INIT_NODUP;
|
||||
struct option builtin_ls_files_options[] = {
|
||||
/* Think twice before adding "--nul" synonym to this */
|
||||
|
@ -594,9 +594,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
|
|||
|
||||
argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
|
||||
ls_files_usage, 0);
|
||||
el = add_exclude_list(&dir, EXC_CMDL, "--exclude option");
|
||||
pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option");
|
||||
for (i = 0; i < exclude_list.nr; i++) {
|
||||
add_exclude(exclude_list.items[i].string, "", 0, el, --exclude_args);
|
||||
add_pattern(exclude_list.items[i].string, "", 0, pl, --exclude_args);
|
||||
}
|
||||
if (show_tag || show_valid_bit || show_fsmonitor_bit) {
|
||||
tag_cached = "H ";
|
||||
|
|
282
dir.c
282
dir.c
|
@ -561,7 +561,7 @@ int no_wildcard(const char *string)
|
|||
return string[simple_length(string)] == '\0';
|
||||
}
|
||||
|
||||
void parse_exclude_pattern(const char **pattern,
|
||||
void parse_path_pattern(const char **pattern,
|
||||
int *patternlen,
|
||||
unsigned *flags,
|
||||
int *nowildcardlen)
|
||||
|
@ -571,20 +571,20 @@ void parse_exclude_pattern(const char **pattern,
|
|||
|
||||
*flags = 0;
|
||||
if (*p == '!') {
|
||||
*flags |= EXC_FLAG_NEGATIVE;
|
||||
*flags |= PATTERN_FLAG_NEGATIVE;
|
||||
p++;
|
||||
}
|
||||
len = strlen(p);
|
||||
if (len && p[len - 1] == '/') {
|
||||
len--;
|
||||
*flags |= EXC_FLAG_MUSTBEDIR;
|
||||
*flags |= PATTERN_FLAG_MUSTBEDIR;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
if (p[i] == '/')
|
||||
break;
|
||||
}
|
||||
if (i == len)
|
||||
*flags |= EXC_FLAG_NODIR;
|
||||
*flags |= PATTERN_FLAG_NODIR;
|
||||
*nowildcardlen = simple_length(p);
|
||||
/*
|
||||
* we should have excluded the trailing slash from 'p' too,
|
||||
|
@ -594,35 +594,35 @@ void parse_exclude_pattern(const char **pattern,
|
|||
if (*nowildcardlen > len)
|
||||
*nowildcardlen = len;
|
||||
if (*p == '*' && no_wildcard(p + 1))
|
||||
*flags |= EXC_FLAG_ENDSWITH;
|
||||
*flags |= PATTERN_FLAG_ENDSWITH;
|
||||
*pattern = p;
|
||||
*patternlen = len;
|
||||
}
|
||||
|
||||
void add_exclude(const char *string, const char *base,
|
||||
int baselen, struct exclude_list *el, int srcpos)
|
||||
void add_pattern(const char *string, const char *base,
|
||||
int baselen, struct pattern_list *pl, int srcpos)
|
||||
{
|
||||
struct exclude *x;
|
||||
struct path_pattern *pattern;
|
||||
int patternlen;
|
||||
unsigned flags;
|
||||
int nowildcardlen;
|
||||
|
||||
parse_exclude_pattern(&string, &patternlen, &flags, &nowildcardlen);
|
||||
if (flags & EXC_FLAG_MUSTBEDIR) {
|
||||
FLEXPTR_ALLOC_MEM(x, pattern, string, patternlen);
|
||||
parse_path_pattern(&string, &patternlen, &flags, &nowildcardlen);
|
||||
if (flags & PATTERN_FLAG_MUSTBEDIR) {
|
||||
FLEXPTR_ALLOC_MEM(pattern, pattern, string, patternlen);
|
||||
} else {
|
||||
x = xmalloc(sizeof(*x));
|
||||
x->pattern = string;
|
||||
pattern = xmalloc(sizeof(*pattern));
|
||||
pattern->pattern = string;
|
||||
}
|
||||
x->patternlen = patternlen;
|
||||
x->nowildcardlen = nowildcardlen;
|
||||
x->base = base;
|
||||
x->baselen = baselen;
|
||||
x->flags = flags;
|
||||
x->srcpos = srcpos;
|
||||
ALLOC_GROW(el->excludes, el->nr + 1, el->alloc);
|
||||
el->excludes[el->nr++] = x;
|
||||
x->el = el;
|
||||
pattern->patternlen = patternlen;
|
||||
pattern->nowildcardlen = nowildcardlen;
|
||||
pattern->base = base;
|
||||
pattern->baselen = baselen;
|
||||
pattern->flags = flags;
|
||||
pattern->srcpos = srcpos;
|
||||
ALLOC_GROW(pl->patterns, pl->nr + 1, pl->alloc);
|
||||
pl->patterns[pl->nr++] = pattern;
|
||||
pattern->pl = pl;
|
||||
}
|
||||
|
||||
static int read_skip_worktree_file_from_index(const struct index_state *istate,
|
||||
|
@ -643,19 +643,19 @@ static int read_skip_worktree_file_from_index(const struct index_state *istate,
|
|||
}
|
||||
|
||||
/*
|
||||
* Frees memory within el which was allocated for exclude patterns and
|
||||
* the file buffer. Does not free el itself.
|
||||
* Frees memory within pl which was allocated for exclude patterns and
|
||||
* the file buffer. Does not free pl itself.
|
||||
*/
|
||||
void clear_exclude_list(struct exclude_list *el)
|
||||
void clear_pattern_list(struct pattern_list *pl)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < el->nr; i++)
|
||||
free(el->excludes[i]);
|
||||
free(el->excludes);
|
||||
free(el->filebuf);
|
||||
for (i = 0; i < pl->nr; i++)
|
||||
free(pl->patterns[i]);
|
||||
free(pl->patterns);
|
||||
free(pl->filebuf);
|
||||
|
||||
memset(el, 0, sizeof(*el));
|
||||
memset(pl, 0, sizeof(*pl));
|
||||
}
|
||||
|
||||
static void trim_trailing_spaces(char *buf)
|
||||
|
@ -762,21 +762,21 @@ static void invalidate_directory(struct untracked_cache *uc,
|
|||
dir->dirs[i]->recurse = 0;
|
||||
}
|
||||
|
||||
static int add_excludes_from_buffer(char *buf, size_t size,
|
||||
static int add_patterns_from_buffer(char *buf, size_t size,
|
||||
const char *base, int baselen,
|
||||
struct exclude_list *el);
|
||||
struct pattern_list *pl);
|
||||
|
||||
/*
|
||||
* Given a file with name "fname", read it (either from disk, or from
|
||||
* an index if 'istate' is non-null), parse it and store the
|
||||
* exclude rules in "el".
|
||||
* exclude rules in "pl".
|
||||
*
|
||||
* If "ss" is not NULL, compute SHA-1 of the exclude file and fill
|
||||
* stat data from disk (only valid if add_excludes returns zero). If
|
||||
* stat data from disk (only valid if add_patterns returns zero). If
|
||||
* ss_valid is non-zero, "ss" must contain good value as input.
|
||||
*/
|
||||
static int add_excludes(const char *fname, const char *base, int baselen,
|
||||
struct exclude_list *el, struct index_state *istate,
|
||||
static int add_patterns(const char *fname, const char *base, int baselen,
|
||||
struct pattern_list *pl, struct index_state *istate,
|
||||
struct oid_stat *oid_stat)
|
||||
{
|
||||
struct stat st;
|
||||
|
@ -837,21 +837,21 @@ static int add_excludes(const char *fname, const char *base, int baselen,
|
|||
}
|
||||
}
|
||||
|
||||
add_excludes_from_buffer(buf, size, base, baselen, el);
|
||||
add_patterns_from_buffer(buf, size, base, baselen, pl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_excludes_from_buffer(char *buf, size_t size,
|
||||
static int add_patterns_from_buffer(char *buf, size_t size,
|
||||
const char *base, int baselen,
|
||||
struct exclude_list *el)
|
||||
struct pattern_list *pl)
|
||||
{
|
||||
int i, lineno = 1;
|
||||
char *entry;
|
||||
|
||||
el->filebuf = buf;
|
||||
pl->filebuf = buf;
|
||||
|
||||
if (skip_utf8_bom(&buf, size))
|
||||
size -= buf - el->filebuf;
|
||||
size -= buf - pl->filebuf;
|
||||
|
||||
entry = buf;
|
||||
|
||||
|
@ -860,7 +860,7 @@ static int add_excludes_from_buffer(char *buf, size_t size,
|
|||
if (entry != buf + i && entry[0] != '#') {
|
||||
buf[i - (i && buf[i-1] == '\r')] = 0;
|
||||
trim_trailing_spaces(entry);
|
||||
add_exclude(entry, base, baselen, el, lineno);
|
||||
add_pattern(entry, base, baselen, pl, lineno);
|
||||
}
|
||||
lineno++;
|
||||
entry = buf + i + 1;
|
||||
|
@ -869,17 +869,17 @@ static int add_excludes_from_buffer(char *buf, size_t size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int add_excludes_from_file_to_list(const char *fname, const char *base,
|
||||
int baselen, struct exclude_list *el,
|
||||
int add_patterns_from_file_to_list(const char *fname, const char *base,
|
||||
int baselen, struct pattern_list *pl,
|
||||
struct index_state *istate)
|
||||
{
|
||||
return add_excludes(fname, base, baselen, el, istate, NULL);
|
||||
return add_patterns(fname, base, baselen, pl, istate, NULL);
|
||||
}
|
||||
|
||||
int add_excludes_from_blob_to_list(
|
||||
int add_patterns_from_blob_to_list(
|
||||
struct object_id *oid,
|
||||
const char *base, int baselen,
|
||||
struct exclude_list *el)
|
||||
struct pattern_list *pl)
|
||||
{
|
||||
char *buf;
|
||||
size_t size;
|
||||
|
@ -889,31 +889,31 @@ int add_excludes_from_blob_to_list(
|
|||
if (r != 1)
|
||||
return r;
|
||||
|
||||
add_excludes_from_buffer(buf, size, base, baselen, el);
|
||||
add_patterns_from_buffer(buf, size, base, baselen, pl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct exclude_list *add_exclude_list(struct dir_struct *dir,
|
||||
struct pattern_list *add_pattern_list(struct dir_struct *dir,
|
||||
int group_type, const char *src)
|
||||
{
|
||||
struct exclude_list *el;
|
||||
struct pattern_list *pl;
|
||||
struct exclude_list_group *group;
|
||||
|
||||
group = &dir->exclude_list_group[group_type];
|
||||
ALLOC_GROW(group->el, group->nr + 1, group->alloc);
|
||||
el = &group->el[group->nr++];
|
||||
memset(el, 0, sizeof(*el));
|
||||
el->src = src;
|
||||
return el;
|
||||
ALLOC_GROW(group->pl, group->nr + 1, group->alloc);
|
||||
pl = &group->pl[group->nr++];
|
||||
memset(pl, 0, sizeof(*pl));
|
||||
pl->src = src;
|
||||
return pl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to set up core.excludesfile and .git/info/exclude lists.
|
||||
*/
|
||||
static void add_excludes_from_file_1(struct dir_struct *dir, const char *fname,
|
||||
static void add_patterns_from_file_1(struct dir_struct *dir, const char *fname,
|
||||
struct oid_stat *oid_stat)
|
||||
{
|
||||
struct exclude_list *el;
|
||||
struct pattern_list *pl;
|
||||
/*
|
||||
* catch setup_standard_excludes() that's called before
|
||||
* dir->untracked is assigned. That function behaves
|
||||
|
@ -921,15 +921,15 @@ static void add_excludes_from_file_1(struct dir_struct *dir, const char *fname,
|
|||
*/
|
||||
if (!dir->untracked)
|
||||
dir->unmanaged_exclude_files++;
|
||||
el = add_exclude_list(dir, EXC_FILE, fname);
|
||||
if (add_excludes(fname, "", 0, el, NULL, oid_stat) < 0)
|
||||
pl = add_pattern_list(dir, EXC_FILE, fname);
|
||||
if (add_patterns(fname, "", 0, pl, NULL, oid_stat) < 0)
|
||||
die(_("cannot use %s as an exclude file"), fname);
|
||||
}
|
||||
|
||||
void add_excludes_from_file(struct dir_struct *dir, const char *fname)
|
||||
void add_patterns_from_file(struct dir_struct *dir, const char *fname)
|
||||
{
|
||||
dir->unmanaged_exclude_files++; /* see validate_untracked_cache() */
|
||||
add_excludes_from_file_1(dir, fname, NULL);
|
||||
add_patterns_from_file_1(dir, fname, NULL);
|
||||
}
|
||||
|
||||
int match_basename(const char *basename, int basenamelen,
|
||||
|
@ -940,7 +940,7 @@ int match_basename(const char *basename, int basenamelen,
|
|||
if (patternlen == basenamelen &&
|
||||
!fspathncmp(pattern, basename, basenamelen))
|
||||
return 1;
|
||||
} else if (flags & EXC_FLAG_ENDSWITH) {
|
||||
} else if (flags & PATTERN_FLAG_ENDSWITH) {
|
||||
/* "*literal" matching against "fooliteral" */
|
||||
if (patternlen - 1 <= basenamelen &&
|
||||
!fspathncmp(pattern + 1,
|
||||
|
@ -1021,85 +1021,97 @@ int match_pathname(const char *pathname, int pathlen,
|
|||
* any, determines the fate. Returns the exclude_list element which
|
||||
* matched, or NULL for undecided.
|
||||
*/
|
||||
static struct exclude *last_exclude_matching_from_list(const char *pathname,
|
||||
static struct path_pattern *last_matching_pattern_from_list(const char *pathname,
|
||||
int pathlen,
|
||||
const char *basename,
|
||||
int *dtype,
|
||||
struct exclude_list *el,
|
||||
struct pattern_list *pl,
|
||||
struct index_state *istate)
|
||||
{
|
||||
struct exclude *exc = NULL; /* undecided */
|
||||
struct path_pattern *res = NULL; /* undecided */
|
||||
int i;
|
||||
|
||||
if (!el->nr)
|
||||
if (!pl->nr)
|
||||
return NULL; /* undefined */
|
||||
|
||||
for (i = el->nr - 1; 0 <= i; i--) {
|
||||
struct exclude *x = el->excludes[i];
|
||||
const char *exclude = x->pattern;
|
||||
int prefix = x->nowildcardlen;
|
||||
for (i = pl->nr - 1; 0 <= i; i--) {
|
||||
struct path_pattern *pattern = pl->patterns[i];
|
||||
const char *exclude = pattern->pattern;
|
||||
int prefix = pattern->nowildcardlen;
|
||||
|
||||
if (x->flags & EXC_FLAG_MUSTBEDIR) {
|
||||
if (pattern->flags & PATTERN_FLAG_MUSTBEDIR) {
|
||||
if (*dtype == DT_UNKNOWN)
|
||||
*dtype = get_dtype(NULL, istate, pathname, pathlen);
|
||||
if (*dtype != DT_DIR)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (x->flags & EXC_FLAG_NODIR) {
|
||||
if (pattern->flags & PATTERN_FLAG_NODIR) {
|
||||
if (match_basename(basename,
|
||||
pathlen - (basename - pathname),
|
||||
exclude, prefix, x->patternlen,
|
||||
x->flags)) {
|
||||
exc = x;
|
||||
exclude, prefix, pattern->patternlen,
|
||||
pattern->flags)) {
|
||||
res = pattern;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(x->baselen == 0 || x->base[x->baselen - 1] == '/');
|
||||
assert(pattern->baselen == 0 ||
|
||||
pattern->base[pattern->baselen - 1] == '/');
|
||||
if (match_pathname(pathname, pathlen,
|
||||
x->base, x->baselen ? x->baselen - 1 : 0,
|
||||
exclude, prefix, x->patternlen, x->flags)) {
|
||||
exc = x;
|
||||
pattern->base,
|
||||
pattern->baselen ? pattern->baselen - 1 : 0,
|
||||
exclude, prefix, pattern->patternlen,
|
||||
pattern->flags)) {
|
||||
res = pattern;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return exc;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the list and let the last match determine the fate.
|
||||
* Return 1 for exclude, 0 for include and -1 for undecided.
|
||||
* Scan the list of patterns to determine if the ordered list
|
||||
* of patterns matches on 'pathname'.
|
||||
*
|
||||
* Return 1 for a match, 0 for not matched and -1 for undecided.
|
||||
*/
|
||||
int is_excluded_from_list(const char *pathname,
|
||||
int pathlen, const char *basename, int *dtype,
|
||||
struct exclude_list *el, struct index_state *istate)
|
||||
enum pattern_match_result path_matches_pattern_list(
|
||||
const char *pathname, int pathlen,
|
||||
const char *basename, int *dtype,
|
||||
struct pattern_list *pl,
|
||||
struct index_state *istate)
|
||||
{
|
||||
struct exclude *exclude;
|
||||
exclude = last_exclude_matching_from_list(pathname, pathlen, basename,
|
||||
dtype, el, istate);
|
||||
if (exclude)
|
||||
return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
|
||||
return -1; /* undecided */
|
||||
struct path_pattern *pattern;
|
||||
pattern = last_matching_pattern_from_list(pathname, pathlen, basename,
|
||||
dtype, pl, istate);
|
||||
if (pattern) {
|
||||
if (pattern->flags & PATTERN_FLAG_NEGATIVE)
|
||||
return NOT_MATCHED;
|
||||
else
|
||||
return MATCHED;
|
||||
}
|
||||
|
||||
return UNDECIDED;
|
||||
}
|
||||
|
||||
static struct exclude *last_exclude_matching_from_lists(struct dir_struct *dir,
|
||||
struct index_state *istate,
|
||||
const char *pathname, int pathlen, const char *basename,
|
||||
int *dtype_p)
|
||||
static struct path_pattern *last_matching_pattern_from_lists(
|
||||
struct dir_struct *dir, struct index_state *istate,
|
||||
const char *pathname, int pathlen,
|
||||
const char *basename, int *dtype_p)
|
||||
{
|
||||
int i, j;
|
||||
struct exclude_list_group *group;
|
||||
struct exclude *exclude;
|
||||
struct path_pattern *pattern;
|
||||
for (i = EXC_CMDL; i <= EXC_FILE; i++) {
|
||||
group = &dir->exclude_list_group[i];
|
||||
for (j = group->nr - 1; j >= 0; j--) {
|
||||
exclude = last_exclude_matching_from_list(
|
||||
pattern = last_matching_pattern_from_list(
|
||||
pathname, pathlen, basename, dtype_p,
|
||||
&group->el[j], istate);
|
||||
if (exclude)
|
||||
return exclude;
|
||||
&group->pl[j], istate);
|
||||
if (pattern)
|
||||
return pattern;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
@ -1114,7 +1126,7 @@ static void prep_exclude(struct dir_struct *dir,
|
|||
const char *base, int baselen)
|
||||
{
|
||||
struct exclude_list_group *group;
|
||||
struct exclude_list *el;
|
||||
struct pattern_list *pl;
|
||||
struct exclude_stack *stk = NULL;
|
||||
struct untracked_cache_dir *untracked;
|
||||
int current;
|
||||
|
@ -1130,17 +1142,17 @@ static void prep_exclude(struct dir_struct *dir,
|
|||
if (stk->baselen <= baselen &&
|
||||
!strncmp(dir->basebuf.buf, base, stk->baselen))
|
||||
break;
|
||||
el = &group->el[dir->exclude_stack->exclude_ix];
|
||||
pl = &group->pl[dir->exclude_stack->exclude_ix];
|
||||
dir->exclude_stack = stk->prev;
|
||||
dir->exclude = NULL;
|
||||
free((char *)el->src); /* see strbuf_detach() below */
|
||||
clear_exclude_list(el);
|
||||
dir->pattern = NULL;
|
||||
free((char *)pl->src); /* see strbuf_detach() below */
|
||||
clear_pattern_list(pl);
|
||||
free(stk);
|
||||
group->nr--;
|
||||
}
|
||||
|
||||
/* Skip traversing into sub directories if the parent is excluded */
|
||||
if (dir->exclude)
|
||||
if (dir->pattern)
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -1181,7 +1193,7 @@ static void prep_exclude(struct dir_struct *dir,
|
|||
stk->baselen = cp - base;
|
||||
stk->exclude_ix = group->nr;
|
||||
stk->ucd = untracked;
|
||||
el = add_exclude_list(dir, EXC_DIRS, NULL);
|
||||
pl = add_pattern_list(dir, EXC_DIRS, NULL);
|
||||
strbuf_add(&dir->basebuf, base + current, stk->baselen - current);
|
||||
assert(stk->baselen == dir->basebuf.len);
|
||||
|
||||
|
@ -1189,15 +1201,15 @@ static void prep_exclude(struct dir_struct *dir,
|
|||
if (stk->baselen) {
|
||||
int dt = DT_DIR;
|
||||
dir->basebuf.buf[stk->baselen - 1] = 0;
|
||||
dir->exclude = last_exclude_matching_from_lists(dir,
|
||||
dir->pattern = last_matching_pattern_from_lists(dir,
|
||||
istate,
|
||||
dir->basebuf.buf, stk->baselen - 1,
|
||||
dir->basebuf.buf + current, &dt);
|
||||
dir->basebuf.buf[stk->baselen - 1] = '/';
|
||||
if (dir->exclude &&
|
||||
dir->exclude->flags & EXC_FLAG_NEGATIVE)
|
||||
dir->exclude = NULL;
|
||||
if (dir->exclude) {
|
||||
if (dir->pattern &&
|
||||
dir->pattern->flags & PATTERN_FLAG_NEGATIVE)
|
||||
dir->pattern = NULL;
|
||||
if (dir->pattern) {
|
||||
dir->exclude_stack = stk;
|
||||
return;
|
||||
}
|
||||
|
@ -1223,30 +1235,30 @@ static void prep_exclude(struct dir_struct *dir,
|
|||
/*
|
||||
* dir->basebuf gets reused by the traversal, but we
|
||||
* need fname to remain unchanged to ensure the src
|
||||
* member of each struct exclude correctly
|
||||
* member of each struct path_pattern correctly
|
||||
* back-references its source file. Other invocations
|
||||
* of add_exclude_list provide stable strings, so we
|
||||
* of add_pattern_list provide stable strings, so we
|
||||
* strbuf_detach() and free() here in the caller.
|
||||
*/
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
strbuf_addbuf(&sb, &dir->basebuf);
|
||||
strbuf_addstr(&sb, dir->exclude_per_dir);
|
||||
el->src = strbuf_detach(&sb, NULL);
|
||||
add_excludes(el->src, el->src, stk->baselen, el, istate,
|
||||
pl->src = strbuf_detach(&sb, NULL);
|
||||
add_patterns(pl->src, pl->src, stk->baselen, pl, istate,
|
||||
untracked ? &oid_stat : NULL);
|
||||
}
|
||||
/*
|
||||
* NEEDSWORK: when untracked cache is enabled, prep_exclude()
|
||||
* will first be called in valid_cached_dir() then maybe many
|
||||
* times more in last_exclude_matching(). When the cache is
|
||||
* used, last_exclude_matching() will not be called and
|
||||
* times more in last_matching_pattern(). When the cache is
|
||||
* used, last_matching_pattern() will not be called and
|
||||
* reading .gitignore content will be a waste.
|
||||
*
|
||||
* So when it's called by valid_cached_dir() and we can get
|
||||
* .gitignore SHA-1 from the index (i.e. .gitignore is not
|
||||
* modified on work tree), we could delay reading the
|
||||
* .gitignore content until we absolutely need it in
|
||||
* last_exclude_matching(). Be careful about ignore rule
|
||||
* last_matching_pattern(). Be careful about ignore rule
|
||||
* order, though, if you do that.
|
||||
*/
|
||||
if (untracked &&
|
||||
|
@ -1266,7 +1278,7 @@ static void prep_exclude(struct dir_struct *dir,
|
|||
* Returns the exclude_list element which matched, or NULL for
|
||||
* undecided.
|
||||
*/
|
||||
struct exclude *last_exclude_matching(struct dir_struct *dir,
|
||||
struct path_pattern *last_matching_pattern(struct dir_struct *dir,
|
||||
struct index_state *istate,
|
||||
const char *pathname,
|
||||
int *dtype_p)
|
||||
|
@ -1277,10 +1289,10 @@ struct exclude *last_exclude_matching(struct dir_struct *dir,
|
|||
|
||||
prep_exclude(dir, istate, pathname, basename-pathname);
|
||||
|
||||
if (dir->exclude)
|
||||
return dir->exclude;
|
||||
if (dir->pattern)
|
||||
return dir->pattern;
|
||||
|
||||
return last_exclude_matching_from_lists(dir, istate, pathname, pathlen,
|
||||
return last_matching_pattern_from_lists(dir, istate, pathname, pathlen,
|
||||
basename, dtype_p);
|
||||
}
|
||||
|
||||
|
@ -1292,10 +1304,10 @@ struct exclude *last_exclude_matching(struct dir_struct *dir,
|
|||
int is_excluded(struct dir_struct *dir, struct index_state *istate,
|
||||
const char *pathname, int *dtype_p)
|
||||
{
|
||||
struct exclude *exclude =
|
||||
last_exclude_matching(dir, istate, pathname, dtype_p);
|
||||
if (exclude)
|
||||
return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
|
||||
struct path_pattern *pattern =
|
||||
last_matching_pattern(dir, istate, pathname, dtype_p);
|
||||
if (pattern)
|
||||
return pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1808,7 +1820,7 @@ static int valid_cached_dir(struct dir_struct *dir,
|
|||
|
||||
/*
|
||||
* prep_exclude will be called eventually on this directory,
|
||||
* but it's called much later in last_exclude_matching(). We
|
||||
* but it's called much later in last_matching_pattern(). We
|
||||
* need it now to determine the validity of the cache for this
|
||||
* path. The next calls will be nearly no-op, the way
|
||||
* prep_exclude() is designed.
|
||||
|
@ -2488,14 +2500,14 @@ void setup_standard_excludes(struct dir_struct *dir)
|
|||
if (!excludes_file)
|
||||
excludes_file = xdg_config_home("ignore");
|
||||
if (excludes_file && !access_or_warn(excludes_file, R_OK, 0))
|
||||
add_excludes_from_file_1(dir, excludes_file,
|
||||
add_patterns_from_file_1(dir, excludes_file,
|
||||
dir->untracked ? &dir->ss_excludes_file : NULL);
|
||||
|
||||
/* per repository user preference */
|
||||
if (startup_info->have_repository) {
|
||||
const char *path = git_path_info_exclude();
|
||||
if (!access_or_warn(path, R_OK, 0))
|
||||
add_excludes_from_file_1(dir, path,
|
||||
add_patterns_from_file_1(dir, path,
|
||||
dir->untracked ? &dir->ss_info_exclude : NULL);
|
||||
}
|
||||
}
|
||||
|
@ -2527,18 +2539,18 @@ void clear_directory(struct dir_struct *dir)
|
|||
{
|
||||
int i, j;
|
||||
struct exclude_list_group *group;
|
||||
struct exclude_list *el;
|
||||
struct pattern_list *pl;
|
||||
struct exclude_stack *stk;
|
||||
|
||||
for (i = EXC_CMDL; i <= EXC_FILE; i++) {
|
||||
group = &dir->exclude_list_group[i];
|
||||
for (j = 0; j < group->nr; j++) {
|
||||
el = &group->el[j];
|
||||
pl = &group->pl[j];
|
||||
if (i == EXC_DIRS)
|
||||
free((char *)el->src);
|
||||
clear_exclude_list(el);
|
||||
free((char *)pl->src);
|
||||
clear_pattern_list(pl);
|
||||
}
|
||||
free(group->el);
|
||||
free(group->pl);
|
||||
}
|
||||
|
||||
stk = dir->exclude_stack;
|
||||
|
|
63
dir.h
63
dir.h
|
@ -11,24 +11,24 @@ struct dir_entry {
|
|||
char name[FLEX_ARRAY]; /* more */
|
||||
};
|
||||
|
||||
#define EXC_FLAG_NODIR 1
|
||||
#define EXC_FLAG_ENDSWITH 4
|
||||
#define EXC_FLAG_MUSTBEDIR 8
|
||||
#define EXC_FLAG_NEGATIVE 16
|
||||
#define PATTERN_FLAG_NODIR 1
|
||||
#define PATTERN_FLAG_ENDSWITH 4
|
||||
#define PATTERN_FLAG_MUSTBEDIR 8
|
||||
#define PATTERN_FLAG_NEGATIVE 16
|
||||
|
||||
struct exclude {
|
||||
struct path_pattern {
|
||||
/*
|
||||
* This allows callers of last_exclude_matching() etc.
|
||||
* This allows callers of last_matching_pattern() etc.
|
||||
* to determine the origin of the matching pattern.
|
||||
*/
|
||||
struct exclude_list *el;
|
||||
struct pattern_list *pl;
|
||||
|
||||
const char *pattern;
|
||||
int patternlen;
|
||||
int nowildcardlen;
|
||||
const char *base;
|
||||
int baselen;
|
||||
unsigned flags; /* EXC_FLAG_* */
|
||||
unsigned flags; /* PATTERN_FLAG_* */
|
||||
|
||||
/*
|
||||
* Counting starts from 1 for line numbers in ignore files,
|
||||
|
@ -44,7 +44,7 @@ struct exclude {
|
|||
* can also be used to represent the list of --exclude values passed
|
||||
* via CLI args.
|
||||
*/
|
||||
struct exclude_list {
|
||||
struct pattern_list {
|
||||
int nr;
|
||||
int alloc;
|
||||
|
||||
|
@ -54,7 +54,7 @@ struct exclude_list {
|
|||
/* origin of list, e.g. path to filename, or descriptive string */
|
||||
const char *src;
|
||||
|
||||
struct exclude **excludes;
|
||||
struct path_pattern **patterns;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -72,7 +72,7 @@ struct exclude_stack {
|
|||
|
||||
struct exclude_list_group {
|
||||
int nr, alloc;
|
||||
struct exclude_list *el;
|
||||
struct pattern_list *pl;
|
||||
};
|
||||
|
||||
struct oid_stat {
|
||||
|
@ -191,7 +191,7 @@ struct dir_struct {
|
|||
* matching exclude struct if the directory is excluded.
|
||||
*/
|
||||
struct exclude_stack *exclude_stack;
|
||||
struct exclude *exclude;
|
||||
struct path_pattern *pattern;
|
||||
struct strbuf basebuf;
|
||||
|
||||
/* Enable untracked file cache if set */
|
||||
|
@ -230,9 +230,22 @@ int read_directory(struct dir_struct *, struct index_state *istate,
|
|||
const char *path, int len,
|
||||
const struct pathspec *pathspec);
|
||||
|
||||
int is_excluded_from_list(const char *pathname, int pathlen,
|
||||
enum pattern_match_result {
|
||||
UNDECIDED = -1,
|
||||
NOT_MATCHED = 0,
|
||||
MATCHED = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* Scan the list of patterns to determine if the ordered list
|
||||
* of patterns matches on 'pathname'.
|
||||
*
|
||||
* Return 1 for a match, 0 for not matched and -1 for undecided.
|
||||
*/
|
||||
enum pattern_match_result path_matches_pattern_list(const char *pathname,
|
||||
int pathlen,
|
||||
const char *basename, int *dtype,
|
||||
struct exclude_list *el,
|
||||
struct pattern_list *pl,
|
||||
struct index_state *istate);
|
||||
struct dir_entry *dir_add_ignored(struct dir_struct *dir,
|
||||
struct index_state *istate,
|
||||
|
@ -248,7 +261,7 @@ int match_pathname(const char *, int,
|
|||
const char *, int,
|
||||
const char *, int, int, unsigned);
|
||||
|
||||
struct exclude *last_exclude_matching(struct dir_struct *dir,
|
||||
struct path_pattern *last_matching_pattern(struct dir_struct *dir,
|
||||
struct index_state *istate,
|
||||
const char *name, int *dtype);
|
||||
|
||||
|
@ -256,18 +269,18 @@ int is_excluded(struct dir_struct *dir,
|
|||
struct index_state *istate,
|
||||
const char *name, int *dtype);
|
||||
|
||||
struct exclude_list *add_exclude_list(struct dir_struct *dir,
|
||||
struct pattern_list *add_pattern_list(struct dir_struct *dir,
|
||||
int group_type, const char *src);
|
||||
int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
|
||||
struct exclude_list *el, struct index_state *istate);
|
||||
void add_excludes_from_file(struct dir_struct *, const char *fname);
|
||||
int add_excludes_from_blob_to_list(struct object_id *oid,
|
||||
int add_patterns_from_file_to_list(const char *fname, const char *base, int baselen,
|
||||
struct pattern_list *pl, struct index_state *istate);
|
||||
void add_patterns_from_file(struct dir_struct *, const char *fname);
|
||||
int add_patterns_from_blob_to_list(struct object_id *oid,
|
||||
const char *base, int baselen,
|
||||
struct exclude_list *el);
|
||||
void parse_exclude_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen);
|
||||
void add_exclude(const char *string, const char *base,
|
||||
int baselen, struct exclude_list *el, int srcpos);
|
||||
void clear_exclude_list(struct exclude_list *el);
|
||||
struct pattern_list *pl);
|
||||
void parse_path_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen);
|
||||
void add_pattern(const char *string, const char *base,
|
||||
int baselen, struct pattern_list *pl, int srcpos);
|
||||
void clear_pattern_list(struct pattern_list *pl);
|
||||
void clear_directory(struct dir_struct *dir);
|
||||
|
||||
int repo_file_exists(struct repository *repo, const char *path);
|
||||
|
|
|
@ -328,12 +328,12 @@ static void filter_blobs_limit__init(
|
|||
*/
|
||||
struct frame {
|
||||
/*
|
||||
* defval is the usual default include/exclude value that
|
||||
* default_match is the usual default include/exclude value that
|
||||
* should be inherited as we recurse into directories based
|
||||
* upon pattern matching of the directory itself or of a
|
||||
* containing directory.
|
||||
*/
|
||||
int defval;
|
||||
enum pattern_match_result default_match;
|
||||
|
||||
/*
|
||||
* 1 if the directory (recursively) contains any provisionally
|
||||
|
@ -347,7 +347,7 @@ struct frame {
|
|||
};
|
||||
|
||||
struct filter_sparse_data {
|
||||
struct exclude_list el;
|
||||
struct pattern_list pl;
|
||||
|
||||
size_t nr, alloc;
|
||||
struct frame *array_frame;
|
||||
|
@ -363,8 +363,9 @@ static enum list_objects_filter_result filter_sparse(
|
|||
void *filter_data_)
|
||||
{
|
||||
struct filter_sparse_data *filter_data = filter_data_;
|
||||
int val, dtype;
|
||||
int dtype;
|
||||
struct frame *frame;
|
||||
enum pattern_match_result match;
|
||||
|
||||
switch (filter_situation) {
|
||||
default:
|
||||
|
@ -373,15 +374,15 @@ static enum list_objects_filter_result filter_sparse(
|
|||
case LOFS_BEGIN_TREE:
|
||||
assert(obj->type == OBJ_TREE);
|
||||
dtype = DT_DIR;
|
||||
val = is_excluded_from_list(pathname, strlen(pathname),
|
||||
filename, &dtype, &filter_data->el,
|
||||
match = path_matches_pattern_list(pathname, strlen(pathname),
|
||||
filename, &dtype, &filter_data->pl,
|
||||
r->index);
|
||||
if (val < 0)
|
||||
val = filter_data->array_frame[filter_data->nr - 1].defval;
|
||||
if (match == UNDECIDED)
|
||||
match = filter_data->array_frame[filter_data->nr - 1].default_match;
|
||||
|
||||
ALLOC_GROW(filter_data->array_frame, filter_data->nr + 1,
|
||||
filter_data->alloc);
|
||||
filter_data->array_frame[filter_data->nr].defval = val;
|
||||
filter_data->array_frame[filter_data->nr].default_match = match;
|
||||
filter_data->array_frame[filter_data->nr].child_prov_omit = 0;
|
||||
filter_data->nr++;
|
||||
|
||||
|
@ -435,12 +436,12 @@ static enum list_objects_filter_result filter_sparse(
|
|||
frame = &filter_data->array_frame[filter_data->nr - 1];
|
||||
|
||||
dtype = DT_REG;
|
||||
val = is_excluded_from_list(pathname, strlen(pathname),
|
||||
filename, &dtype, &filter_data->el,
|
||||
match = path_matches_pattern_list(pathname, strlen(pathname),
|
||||
filename, &dtype, &filter_data->pl,
|
||||
r->index);
|
||||
if (val < 0)
|
||||
val = frame->defval;
|
||||
if (val > 0) {
|
||||
if (match == UNDECIDED)
|
||||
match = frame->default_match;
|
||||
if (match == MATCHED) {
|
||||
if (omits)
|
||||
oidset_remove(omits, &obj->oid);
|
||||
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
|
||||
|
@ -482,12 +483,12 @@ static void filter_sparse_oid__init(
|
|||
struct filter *filter)
|
||||
{
|
||||
struct filter_sparse_data *d = xcalloc(1, sizeof(*d));
|
||||
if (add_excludes_from_blob_to_list(filter_options->sparse_oid_value,
|
||||
NULL, 0, &d->el) < 0)
|
||||
if (add_patterns_from_blob_to_list(filter_options->sparse_oid_value,
|
||||
NULL, 0, &d->pl) < 0)
|
||||
die("could not load filter specification");
|
||||
|
||||
ALLOC_GROW(d->array_frame, d->nr + 1, d->alloc);
|
||||
d->array_frame[d->nr].defval = 0; /* default to include */
|
||||
d->array_frame[d->nr].default_match = 0; /* default to include */
|
||||
d->array_frame[d->nr].child_prov_omit = 0;
|
||||
d->nr++;
|
||||
|
||||
|
|
|
@ -1269,7 +1269,8 @@ static int clear_ce_flags_1(struct index_state *istate,
|
|||
struct cache_entry **cache, int nr,
|
||||
struct strbuf *prefix,
|
||||
int select_mask, int clear_mask,
|
||||
struct exclude_list *el, int defval);
|
||||
struct pattern_list *pl,
|
||||
enum pattern_match_result default_match);
|
||||
|
||||
/* Whole directory matching */
|
||||
static int clear_ce_flags_dir(struct index_state *istate,
|
||||
|
@ -1277,19 +1278,21 @@ static int clear_ce_flags_dir(struct index_state *istate,
|
|||
struct strbuf *prefix,
|
||||
char *basename,
|
||||
int select_mask, int clear_mask,
|
||||
struct exclude_list *el, int defval)
|
||||
struct pattern_list *pl,
|
||||
enum pattern_match_result default_match)
|
||||
{
|
||||
struct cache_entry **cache_end;
|
||||
int dtype = DT_DIR;
|
||||
int ret = is_excluded_from_list(prefix->buf, prefix->len,
|
||||
basename, &dtype, el, istate);
|
||||
int rc;
|
||||
enum pattern_match_result ret;
|
||||
ret = path_matches_pattern_list(prefix->buf, prefix->len,
|
||||
basename, &dtype, pl, istate);
|
||||
|
||||
strbuf_addch(prefix, '/');
|
||||
|
||||
/* If undecided, use matching result of parent dir in defval */
|
||||
if (ret < 0)
|
||||
ret = defval;
|
||||
if (ret == UNDECIDED)
|
||||
ret = default_match;
|
||||
|
||||
for (cache_end = cache; cache_end != cache + nr; cache_end++) {
|
||||
struct cache_entry *ce = *cache_end;
|
||||
|
@ -1298,23 +1301,23 @@ static int clear_ce_flags_dir(struct index_state *istate,
|
|||
}
|
||||
|
||||
/*
|
||||
* TODO: check el, if there are no patterns that may conflict
|
||||
* TODO: check pl, if there are no patterns that may conflict
|
||||
* with ret (iow, we know in advance the incl/excl
|
||||
* decision for the entire directory), clear flag here without
|
||||
* calling clear_ce_flags_1(). That function will call
|
||||
* the expensive is_excluded_from_list() on every entry.
|
||||
* the expensive path_matches_pattern_list() on every entry.
|
||||
*/
|
||||
rc = clear_ce_flags_1(istate, cache, cache_end - cache,
|
||||
prefix,
|
||||
select_mask, clear_mask,
|
||||
el, ret);
|
||||
pl, ret);
|
||||
strbuf_setlen(prefix, prefix->len - 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Traverse the index, find every entry that matches according to
|
||||
* o->el. Do "ce_flags &= ~clear_mask" on those entries. Return the
|
||||
* o->pl. Do "ce_flags &= ~clear_mask" on those entries. Return the
|
||||
* number of traversed entries.
|
||||
*
|
||||
* If select_mask is non-zero, only entries whose ce_flags has on of
|
||||
|
@ -1331,7 +1334,8 @@ static int clear_ce_flags_1(struct index_state *istate,
|
|||
struct cache_entry **cache, int nr,
|
||||
struct strbuf *prefix,
|
||||
int select_mask, int clear_mask,
|
||||
struct exclude_list *el, int defval)
|
||||
struct pattern_list *pl,
|
||||
enum pattern_match_result default_match)
|
||||
{
|
||||
struct cache_entry **cache_end = cache + nr;
|
||||
|
||||
|
@ -1342,7 +1346,8 @@ static int clear_ce_flags_1(struct index_state *istate,
|
|||
while(cache != cache_end) {
|
||||
struct cache_entry *ce = *cache;
|
||||
const char *name, *slash;
|
||||
int len, dtype, ret;
|
||||
int len, dtype;
|
||||
enum pattern_match_result ret;
|
||||
|
||||
if (select_mask && !(ce->ce_flags & select_mask)) {
|
||||
cache++;
|
||||
|
@ -1366,7 +1371,7 @@ static int clear_ce_flags_1(struct index_state *istate,
|
|||
prefix,
|
||||
prefix->buf + prefix->len - len,
|
||||
select_mask, clear_mask,
|
||||
el, defval);
|
||||
pl, default_match);
|
||||
|
||||
/* clear_c_f_dir eats a whole dir already? */
|
||||
if (processed) {
|
||||
|
@ -1378,18 +1383,20 @@ static int clear_ce_flags_1(struct index_state *istate,
|
|||
strbuf_addch(prefix, '/');
|
||||
cache += clear_ce_flags_1(istate, cache, cache_end - cache,
|
||||
prefix,
|
||||
select_mask, clear_mask, el, defval);
|
||||
select_mask, clear_mask, pl,
|
||||
default_match);
|
||||
strbuf_setlen(prefix, prefix->len - len - 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Non-directory */
|
||||
dtype = ce_to_dtype(ce);
|
||||
ret = is_excluded_from_list(ce->name, ce_namelen(ce),
|
||||
name, &dtype, el, istate);
|
||||
if (ret < 0)
|
||||
ret = defval;
|
||||
if (ret > 0)
|
||||
ret = path_matches_pattern_list(ce->name,
|
||||
ce_namelen(ce),
|
||||
name, &dtype, pl, istate);
|
||||
if (ret == UNDECIDED)
|
||||
ret = default_match;
|
||||
if (ret == MATCHED)
|
||||
ce->ce_flags &= ~clear_mask;
|
||||
cache++;
|
||||
}
|
||||
|
@ -1398,7 +1405,7 @@ static int clear_ce_flags_1(struct index_state *istate,
|
|||
|
||||
static int clear_ce_flags(struct index_state *istate,
|
||||
int select_mask, int clear_mask,
|
||||
struct exclude_list *el)
|
||||
struct pattern_list *pl)
|
||||
{
|
||||
static struct strbuf prefix = STRBUF_INIT;
|
||||
|
||||
|
@ -1409,13 +1416,13 @@ static int clear_ce_flags(struct index_state *istate,
|
|||
istate->cache_nr,
|
||||
&prefix,
|
||||
select_mask, clear_mask,
|
||||
el, 0);
|
||||
pl, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set/Clear CE_NEW_SKIP_WORKTREE according to $GIT_DIR/info/sparse-checkout
|
||||
*/
|
||||
static void mark_new_skip_worktree(struct exclude_list *el,
|
||||
static void mark_new_skip_worktree(struct pattern_list *pl,
|
||||
struct index_state *istate,
|
||||
int select_flag, int skip_wt_flag)
|
||||
{
|
||||
|
@ -1441,7 +1448,7 @@ static void mark_new_skip_worktree(struct exclude_list *el,
|
|||
* 2. Widen worktree according to sparse-checkout file.
|
||||
* Matched entries will have skip_wt_flag cleared (i.e. "in")
|
||||
*/
|
||||
clear_ce_flags(istate, select_flag, skip_wt_flag, el);
|
||||
clear_ce_flags(istate, select_flag, skip_wt_flag, pl);
|
||||
}
|
||||
|
||||
static int verify_absent(const struct cache_entry *,
|
||||
|
@ -1457,21 +1464,21 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
|
|||
{
|
||||
int i, ret;
|
||||
static struct cache_entry *dfc;
|
||||
struct exclude_list el;
|
||||
struct pattern_list pl;
|
||||
|
||||
if (len > MAX_UNPACK_TREES)
|
||||
die("unpack_trees takes at most %d trees", MAX_UNPACK_TREES);
|
||||
|
||||
trace_performance_enter();
|
||||
memset(&el, 0, sizeof(el));
|
||||
memset(&pl, 0, sizeof(pl));
|
||||
if (!core_apply_sparse_checkout || !o->update)
|
||||
o->skip_sparse_checkout = 1;
|
||||
if (!o->skip_sparse_checkout) {
|
||||
char *sparse = git_pathdup("info/sparse-checkout");
|
||||
if (add_excludes_from_file_to_list(sparse, "", 0, &el, NULL) < 0)
|
||||
if (add_patterns_from_file_to_list(sparse, "", 0, &pl, NULL) < 0)
|
||||
o->skip_sparse_checkout = 1;
|
||||
else
|
||||
o->el = ⪙
|
||||
o->pl = &pl;
|
||||
free(sparse);
|
||||
}
|
||||
|
||||
|
@ -1502,7 +1509,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
|
|||
* Sparse checkout loop #1: set NEW_SKIP_WORKTREE on existing entries
|
||||
*/
|
||||
if (!o->skip_sparse_checkout)
|
||||
mark_new_skip_worktree(o->el, o->src_index, 0, CE_NEW_SKIP_WORKTREE);
|
||||
mark_new_skip_worktree(o->pl, o->src_index, 0, CE_NEW_SKIP_WORKTREE);
|
||||
|
||||
if (!dfc)
|
||||
dfc = xcalloc(1, cache_entry_size(0));
|
||||
|
@ -1567,7 +1574,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
|
|||
* If the will have NEW_SKIP_WORKTREE, also set CE_SKIP_WORKTREE
|
||||
* so apply_sparse_checkout() won't attempt to remove it from worktree
|
||||
*/
|
||||
mark_new_skip_worktree(o->el, &o->result, CE_ADDED, CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE);
|
||||
mark_new_skip_worktree(o->pl, &o->result, CE_ADDED, CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE);
|
||||
|
||||
ret = 0;
|
||||
for (i = 0; i < o->result.cache_nr; i++) {
|
||||
|
@ -1635,7 +1642,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
|
|||
|
||||
done:
|
||||
trace_performance_leave("unpack_trees");
|
||||
clear_exclude_list(&el);
|
||||
clear_pattern_list(&pl);
|
||||
return ret;
|
||||
|
||||
return_failed:
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
struct cache_entry;
|
||||
struct unpack_trees_options;
|
||||
struct exclude_list;
|
||||
struct pattern_list;
|
||||
|
||||
typedef int (*merge_fn_t)(const struct cache_entry * const *src,
|
||||
struct unpack_trees_options *options);
|
||||
|
@ -83,7 +83,7 @@ struct unpack_trees_options {
|
|||
struct index_state *src_index;
|
||||
struct index_state result;
|
||||
|
||||
struct exclude_list *el; /* for internal use */
|
||||
struct pattern_list *pl; /* for internal use */
|
||||
};
|
||||
|
||||
int unpack_trees(unsigned n, struct tree_desc *t,
|
||||
|
|
Loading…
Reference in a new issue