unpack-trees: rename 'is_excluded_from_list()'

The first consumer of pattern-matching filenames was the
.gitignore feature. In that context, storing a list of patterns
as a 'struct exclude_list'  makes sense. However, the
sparse-checkout feature then adopted these structures and methods,
but with the opposite meaning: these patterns match the files
that should be included!

Now that this library is renamed to use 'struct pattern_list'
and 'struct pattern', we can now rename the method used by
the sparse-checkout feature to determine which paths should
appear in the working directory.

The method is_excluded_from_list() is only used by the
sparse-checkout logic in unpack-trees and list-objects-filter.
The confusing part is that it returned 1 for "excluded" (i.e.
it matches the list of exclusions) but that really manes that
the path matched the list of patterns for _inclusion_ in the
working directory.

Rename the method to be path_matches_pattern_list() and have
it return an explicit 'enum pattern_match_result'. Here, the
values MATCHED = 1, UNMATCHED = 0, and UNDECIDED = -1 agree
with the previous integer values. This shift allows future
consumers to better understand what the retur values mean,
and provides more type checking for handling those values.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Derrick Stolee 2019-09-03 11:04:58 -07:00 committed by Junio C Hamano
parent 65edd96aec
commit 468ce99b77
4 changed files with 72 additions and 42 deletions

25
dir.c
View file

@ -1072,19 +1072,28 @@ static struct path_pattern *last_matching_pattern_from_list(const char *pathname
} }
/* /*
* Scan the list and let the last match determine the fate. * Scan the list of patterns to determine if the ordered list
* Return 1 for exclude, 0 for include and -1 for undecided. * 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, enum pattern_match_result path_matches_pattern_list(
int pathlen, const char *basename, int *dtype, const char *pathname, int pathlen,
struct pattern_list *pl, struct index_state *istate) const char *basename, int *dtype,
struct pattern_list *pl,
struct index_state *istate)
{ {
struct path_pattern *pattern; struct path_pattern *pattern;
pattern = last_matching_pattern_from_list(pathname, pathlen, basename, pattern = last_matching_pattern_from_list(pathname, pathlen, basename,
dtype, pl, istate); dtype, pl, istate);
if (pattern) if (pattern) {
return pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1; if (pattern->flags & PATTERN_FLAG_NEGATIVE)
return -1; /* undecided */ return NOT_MATCHED;
else
return MATCHED;
}
return UNDECIDED;
} }
static struct path_pattern *last_matching_pattern_from_lists( static struct path_pattern *last_matching_pattern_from_lists(

21
dir.h
View file

@ -230,10 +230,23 @@ int read_directory(struct dir_struct *, struct index_state *istate,
const char *path, int len, const char *path, int len,
const struct pathspec *pathspec); const struct pathspec *pathspec);
int is_excluded_from_list(const char *pathname, int pathlen, enum pattern_match_result {
const char *basename, int *dtype, UNDECIDED = -1,
struct pattern_list *pl, NOT_MATCHED = 0,
struct index_state *istate); 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 dir_entry *dir_add_ignored(struct dir_struct *dir,
struct index_state *istate, struct index_state *istate,
const char *pathname, int len); const char *pathname, int len);

View file

@ -328,12 +328,12 @@ static void filter_blobs_limit__init(
*/ */
struct frame { 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 * should be inherited as we recurse into directories based
* upon pattern matching of the directory itself or of a * upon pattern matching of the directory itself or of a
* containing directory. * containing directory.
*/ */
int defval; enum pattern_match_result default_match;
/* /*
* 1 if the directory (recursively) contains any provisionally * 1 if the directory (recursively) contains any provisionally
@ -363,8 +363,9 @@ static enum list_objects_filter_result filter_sparse(
void *filter_data_) void *filter_data_)
{ {
struct filter_sparse_data *filter_data = filter_data_; struct filter_sparse_data *filter_data = filter_data_;
int val, dtype; int dtype;
struct frame *frame; struct frame *frame;
enum pattern_match_result match;
switch (filter_situation) { switch (filter_situation) {
default: default:
@ -373,15 +374,15 @@ static enum list_objects_filter_result filter_sparse(
case LOFS_BEGIN_TREE: case LOFS_BEGIN_TREE:
assert(obj->type == OBJ_TREE); assert(obj->type == OBJ_TREE);
dtype = DT_DIR; dtype = DT_DIR;
val = is_excluded_from_list(pathname, strlen(pathname), match = path_matches_pattern_list(pathname, strlen(pathname),
filename, &dtype, &filter_data->pl, filename, &dtype, &filter_data->pl,
r->index); r->index);
if (val < 0) if (match == UNDECIDED)
val = filter_data->array_frame[filter_data->nr - 1].defval; match = filter_data->array_frame[filter_data->nr - 1].default_match;
ALLOC_GROW(filter_data->array_frame, filter_data->nr + 1, ALLOC_GROW(filter_data->array_frame, filter_data->nr + 1,
filter_data->alloc); 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->array_frame[filter_data->nr].child_prov_omit = 0;
filter_data->nr++; filter_data->nr++;
@ -435,12 +436,12 @@ static enum list_objects_filter_result filter_sparse(
frame = &filter_data->array_frame[filter_data->nr - 1]; frame = &filter_data->array_frame[filter_data->nr - 1];
dtype = DT_REG; dtype = DT_REG;
val = is_excluded_from_list(pathname, strlen(pathname), match = path_matches_pattern_list(pathname, strlen(pathname),
filename, &dtype, &filter_data->pl, filename, &dtype, &filter_data->pl,
r->index); r->index);
if (val < 0) if (match == UNDECIDED)
val = frame->defval; match = frame->default_match;
if (val > 0) { if (match == MATCHED) {
if (omits) if (omits)
oidset_remove(omits, &obj->oid); oidset_remove(omits, &obj->oid);
return LOFR_MARK_SEEN | LOFR_DO_SHOW; return LOFR_MARK_SEEN | LOFR_DO_SHOW;
@ -487,7 +488,7 @@ static void filter_sparse_oid__init(
die("could not load filter specification"); die("could not load filter specification");
ALLOC_GROW(d->array_frame, d->nr + 1, d->alloc); 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->array_frame[d->nr].child_prov_omit = 0;
d->nr++; d->nr++;

View file

@ -1265,7 +1265,8 @@ static int clear_ce_flags_1(struct index_state *istate,
struct cache_entry **cache, int nr, struct cache_entry **cache, int nr,
struct strbuf *prefix, struct strbuf *prefix,
int select_mask, int clear_mask, int select_mask, int clear_mask,
struct pattern_list *pl, int defval); struct pattern_list *pl,
enum pattern_match_result default_match);
/* Whole directory matching */ /* Whole directory matching */
static int clear_ce_flags_dir(struct index_state *istate, static int clear_ce_flags_dir(struct index_state *istate,
@ -1273,19 +1274,21 @@ static int clear_ce_flags_dir(struct index_state *istate,
struct strbuf *prefix, struct strbuf *prefix,
char *basename, char *basename,
int select_mask, int clear_mask, int select_mask, int clear_mask,
struct pattern_list *pl, int defval) struct pattern_list *pl,
enum pattern_match_result default_match)
{ {
struct cache_entry **cache_end; struct cache_entry **cache_end;
int dtype = DT_DIR; int dtype = DT_DIR;
int ret = is_excluded_from_list(prefix->buf, prefix->len,
basename, &dtype, pl, istate);
int rc; int rc;
enum pattern_match_result ret;
ret = path_matches_pattern_list(prefix->buf, prefix->len,
basename, &dtype, pl, istate);
strbuf_addch(prefix, '/'); strbuf_addch(prefix, '/');
/* If undecided, use matching result of parent dir in defval */ /* If undecided, use matching result of parent dir in defval */
if (ret < 0) if (ret == UNDECIDED)
ret = defval; ret = default_match;
for (cache_end = cache; cache_end != cache + nr; cache_end++) { for (cache_end = cache; cache_end != cache + nr; cache_end++) {
struct cache_entry *ce = *cache_end; struct cache_entry *ce = *cache_end;
@ -1298,7 +1301,7 @@ static int clear_ce_flags_dir(struct index_state *istate,
* with ret (iow, we know in advance the incl/excl * with ret (iow, we know in advance the incl/excl
* decision for the entire directory), clear flag here without * decision for the entire directory), clear flag here without
* calling clear_ce_flags_1(). That function will call * 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, rc = clear_ce_flags_1(istate, cache, cache_end - cache,
prefix, prefix,
@ -1327,7 +1330,8 @@ static int clear_ce_flags_1(struct index_state *istate,
struct cache_entry **cache, int nr, struct cache_entry **cache, int nr,
struct strbuf *prefix, struct strbuf *prefix,
int select_mask, int clear_mask, int select_mask, int clear_mask,
struct pattern_list *pl, int defval) struct pattern_list *pl,
enum pattern_match_result default_match)
{ {
struct cache_entry **cache_end = cache + nr; struct cache_entry **cache_end = cache + nr;
@ -1338,7 +1342,8 @@ static int clear_ce_flags_1(struct index_state *istate,
while(cache != cache_end) { while(cache != cache_end) {
struct cache_entry *ce = *cache; struct cache_entry *ce = *cache;
const char *name, *slash; const char *name, *slash;
int len, dtype, ret; int len, dtype;
enum pattern_match_result ret;
if (select_mask && !(ce->ce_flags & select_mask)) { if (select_mask && !(ce->ce_flags & select_mask)) {
cache++; cache++;
@ -1362,7 +1367,7 @@ static int clear_ce_flags_1(struct index_state *istate,
prefix, prefix,
prefix->buf + prefix->len - len, prefix->buf + prefix->len - len,
select_mask, clear_mask, select_mask, clear_mask,
pl, defval); pl, default_match);
/* clear_c_f_dir eats a whole dir already? */ /* clear_c_f_dir eats a whole dir already? */
if (processed) { if (processed) {
@ -1374,18 +1379,20 @@ static int clear_ce_flags_1(struct index_state *istate,
strbuf_addch(prefix, '/'); strbuf_addch(prefix, '/');
cache += clear_ce_flags_1(istate, cache, cache_end - cache, cache += clear_ce_flags_1(istate, cache, cache_end - cache,
prefix, prefix,
select_mask, clear_mask, pl, defval); select_mask, clear_mask, pl,
default_match);
strbuf_setlen(prefix, prefix->len - len - 1); strbuf_setlen(prefix, prefix->len - len - 1);
continue; continue;
} }
/* Non-directory */ /* Non-directory */
dtype = ce_to_dtype(ce); dtype = ce_to_dtype(ce);
ret = is_excluded_from_list(ce->name, ce_namelen(ce), ret = path_matches_pattern_list(ce->name,
name, &dtype, pl, istate); ce_namelen(ce),
if (ret < 0) name, &dtype, pl, istate);
ret = defval; if (ret == UNDECIDED)
if (ret > 0) ret = default_match;
if (ret == MATCHED)
ce->ce_flags &= ~clear_mask; ce->ce_flags &= ~clear_mask;
cache++; cache++;
} }