diff --git a/Documentation/RelNotes/2.7.1.txt b/Documentation/RelNotes/2.7.1.txt index 6553d69e33..6323feaf64 100644 --- a/Documentation/RelNotes/2.7.1.txt +++ b/Documentation/RelNotes/2.7.1.txt @@ -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. diff --git a/Documentation/RelNotes/2.8.0.txt b/Documentation/RelNotes/2.8.0.txt index 25079710fa..5fbe1b86ee 100644 --- a/Documentation/RelNotes/2.8.0.txt +++ b/Documentation/RelNotes/2.8.0.txt @@ -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. diff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt index 5abb8e8b1f..76b6e4f71b 100644 --- a/Documentation/technical/api-directory-listing.txt +++ b/Documentation/technical/api-directory-listing.txt @@ -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. diff --git a/attr.c b/attr.c index 93dc16b59c..d02d081e28 100644 --- a/attr.c +++ b/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, diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index 599097304b..5a4f92395f 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -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); diff --git a/builtin/clean.c b/builtin/clean.c index d5579da716..851beb7f0d 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -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, diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 670e8fb93c..f069a028ce 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -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 "; diff --git a/dir.c b/dir.c index d021c908e5..cab9c2a458 100644 --- a/dir.c +++ b/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; diff --git a/dir.h b/dir.h index 680079bbe3..608696c958 100644 --- a/dir.h +++ b/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,10 +230,23 @@ 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, - const char *basename, int *dtype, - struct exclude_list *el, - struct index_state *istate); +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 pattern_list *pl, + struct index_state *istate); struct dir_entry *dir_add_ignored(struct dir_struct *dir, struct index_state *istate, const char *pathname, int len); @@ -248,26 +261,26 @@ int match_pathname(const char *, int, const char *, int, const char *, int, int, unsigned); -struct exclude *last_exclude_matching(struct dir_struct *dir, - struct index_state *istate, - const char *name, int *dtype); +struct path_pattern *last_matching_pattern(struct dir_struct *dir, + struct index_state *istate, + const char *name, int *dtype); 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); diff --git a/list-objects-filter.c b/list-objects-filter.c index d664264d65..d624f1c898 100644 --- a/list-objects-filter.c +++ b/list-objects-filter.c @@ -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, - r->index); - if (val < 0) - val = filter_data->array_frame[filter_data->nr - 1].defval; + match = path_matches_pattern_list(pathname, strlen(pathname), + filename, &dtype, &filter_data->pl, + r->index); + 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++; diff --git a/unpack-trees.c b/unpack-trees.c index 9c25126aec..f0f56d40ac 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -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: diff --git a/unpack-trees.h b/unpack-trees.h index d344d7d296..f2eee0c7c5 100644 --- a/unpack-trees.h +++ b/unpack-trees.h @@ -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,