Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- I really like the mnemonic ^ but it's regex. ":^Documentation" looks nicer than ":~Documentation". Do we plan on supporting regex in pathspec too? We should mention these magic in a less obscure document. Glossary is mostly for developer discussions. git-diff may be a good place because it's one of the two frequently used commands (the other one is grep) that benefit magic the most (with a short reference from git.txt) Documentation/glossary-content.txt | 8 +++--- cache.h | 1 + dir.c | 2 + setup.c | 1 + tree-walk.c | 37 +++++++++++++++++++++++++++++++++-- 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index 3595b58..9a2765d 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -319,12 +319,12 @@ top `/`;; The magic word `top` (mnemonic: `/`) makes the pattern match from the root of the working tree, even when you are running the command from inside a subdirectory. + +exclude `~`;; + The magic word `exclude` (mnemonic: `~`) excludes paths that + match the pattern. -- + -Currently only the slash `/` is recognized as the "magic signature", -but it is envisioned that we will support more types of magic in later -versions of git. -+ A pathspec with only a colon means "there is no pathspec". This form should not be combined with other pathspec. diff --git a/cache.h b/cache.h index 719d4a3..75fe589 100644 --- a/cache.h +++ b/cache.h @@ -541,6 +541,7 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct */ #define PATHSPEC_FROMTOP (1<<0) #define PATHSPEC_NOGLOB (1<<1) +#define PATHSPEC_NEGATE (1<<2) struct pathspec { const char **raw; /* get_pathspec() result, not freed by free_pathspec() */ diff --git a/dir.c b/dir.c index d38af0f..46dd35f 100644 --- a/dir.c +++ b/dir.c @@ -1305,6 +1305,8 @@ int parse_pathspec(struct pathspec *pathspec, const char *prefix, pitem->magic |= PATHSPEC_NOGLOB; else pathspec->magic &= ~PATHSPEC_NOGLOB; + if (pitem->magic & PATHSPEC_NEGATE) + pathspec->magic |= PATHSPEC_NEGATE; pitem++; dst++; } diff --git a/setup.c b/setup.c index b074210..42beb9b 100644 --- a/setup.c +++ b/setup.c @@ -111,6 +111,7 @@ static struct pathspec_magic { const char *name; } pathspec_magic[] = { { PATHSPEC_FROMTOP, '/', "top" }, + { PATHSPEC_NEGATE, '~', "exclude" }, }; /* diff --git a/tree-walk.c b/tree-walk.c index db07fd6..936b5da 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -580,15 +580,17 @@ static int match_dir_prefix(const char *base, int baselen, * - zero for no * - negative for "no, and no subsequent entries will be either" */ -int tree_entry_interesting(const struct name_entry *entry, - struct strbuf *base, int base_offset, - const struct pathspec *ps) +static int tree_entry_interesting_1(const struct name_entry *entry, + struct strbuf *base, int base_offset, + const struct pathspec *ps, int negative_magic) { int i; int pathlen, baselen = base->len - base_offset; int never_interesting = ps->magic & PATHSPEC_NOGLOB ? -1 : 0; + int has_effective_pathspec = 0; if (!ps->nr) { +no_pathspec: if (!ps->recursive || ps->max_depth == -1) return 2; return !!within_depth(base->buf + base_offset, baselen, @@ -604,6 +606,12 @@ int tree_entry_interesting(const struct name_entry *entry, const char *base_str = base->buf + base_offset; int matchlen = item->len; + if ((!negative_magic && !(item->magic & PATHSPEC_NEGATE)) || + ( negative_magic && (item->magic & PATHSPEC_NEGATE))) + has_effective_pathspec = 1; + else + continue; + if (baselen >= matchlen) { /* If it doesn't match, move along... */ if (!match_dir_prefix(base_str, baselen, match, matchlen)) @@ -663,5 +671,28 @@ match_wildcards: if (ps->recursive && S_ISDIR(entry->mode)) return 1; } + + /* the same effect with ps->nr == 0 */ + if (!has_effective_pathspec) + goto no_pathspec; + return never_interesting; /* No matches */ } + +int tree_entry_interesting(const struct name_entry *entry, + struct strbuf *base, int base_offset, + const struct pathspec *ps) +{ + int next_ret, ret; + + ret = tree_entry_interesting_1(entry, base, base_offset, ps, 0); + if (ps->magic & PATHSPEC_NEGATE) { + next_ret = tree_entry_interesting_1(entry, base, base_offset, ps, 1); + switch (next_ret) { + case 2: ret = -1; break; + case 1: ret = 0; break; + default: break; + } + } + return ret; +} -- 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