While the UI will be simple, where negative pathspecs are always appended in the end, this could should be able to handle a mixed set of negative and positive pathspecs (ie. overlapping must be handled correctly). Signed-off-by: Nguyán ThÃi Ngác Duy <pclouds@xxxxxxxxx> --- cache.h | 1 + tree-walk.c | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/cache.h b/cache.h index 08a9022..2189366 100644 --- a/cache.h +++ b/cache.h @@ -510,6 +510,7 @@ struct pathspec { const char *match; int len; int has_wildcard:1; + int to_exclude:1; } *items; }; diff --git a/tree-walk.c b/tree-walk.c index 322becc..acbee1b 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -560,6 +560,7 @@ int tree_entry_interesting(const struct name_entry *entry, int i; int pathlen, baselen = base->len - base_offset; int never_interesting = ps->has_wildcard ? 0 : -1; + int all_interesting_ok = !ps->recursive || ps->max_depth == -1; if (!ps->nr) { if (!ps->recursive || ps->max_depth == -1) @@ -569,6 +570,19 @@ int tree_entry_interesting(const struct name_entry *entry, ps->max_depth); } + /* + * TODO: add prepare_pathspec() to scan for pathspecs + * overlapped with negative ones. The ones that do not overlap + * can still return 2. + */ + for (i = 0; i < ps->nr; i++) { + const struct pathspec_item *item = ps->items+i; + if (item->to_exclude) { + all_interesting_ok = 0; + break; + } + } + pathlen = tree_entry_len(entry->path, entry->sha1); for (i = ps->nr - 1; i >= 0; i--) { @@ -578,17 +592,22 @@ int tree_entry_interesting(const struct name_entry *entry, int matchlen = item->len; if (baselen >= matchlen) { + int ret; + /* If it doesn't match, move along... */ if (!match_dir_prefix(base_str, baselen, match, matchlen)) goto match_wildcards; - if (!ps->recursive || ps->max_depth == -1) + if (all_interesting_ok) return 2; - return !!within_depth(base_str + matchlen + 1, - baselen - matchlen - 1, - !!S_ISDIR(entry->mode), - ps->max_depth); + ret = !!within_depth(base_str + matchlen + 1, + baselen - matchlen - 1, + !!S_ISDIR(entry->mode), + ps->max_depth); + if (item->to_exclude) + ret = !ret; + return ret; } /* Does the base match? */ @@ -596,18 +615,18 @@ int tree_entry_interesting(const struct name_entry *entry, if (match_entry(entry, pathlen, match + baselen, matchlen - baselen, &never_interesting)) - return 1; + return item->to_exclude ? 0 : 1; if (ps->items[i].has_wildcard) { if (!fnmatch(match + baselen, entry->path, 0)) - return 1; + return item->to_exclude ? 0 : 1; /* * Match all directories. We'll try to * match files later on. */ if (ps->recursive && S_ISDIR(entry->mode)) - return 1; + return item->to_exclude ? 0 : 1; } continue; @@ -626,7 +645,7 @@ match_wildcards: if (!fnmatch(match, base->buf + base_offset, 0)) { strbuf_setlen(base, base_offset + baselen); - return 1; + return item->to_exclude ? 0 : 1; } strbuf_setlen(base, base_offset + baselen); -- 1.7.3.1.256.g2539c.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html