From: Junio C Hamano Date: Fri, 17 Mar 2017 20:50:26 +0000 (-0700) Subject: Merge branch 'bw/attr-pathspec' X-Git-Tag: v2.13.0-rc0~105 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/f6c64c648ade843b44d517b2de41b8b882f112c0?ds=inline;hp=-c Merge branch 'bw/attr-pathspec' The pathspec mechanism learned to further limit the paths that match the pattern to those that have specified attributes attached via the gitattributes mechanism. * bw/attr-pathspec: pathspec: allow escaped query values pathspec: allow querying for attributes --- f6c64c648ade843b44d517b2de41b8b882f112c0 diff --combined dir.c index aeeb5ce104,2fe7acbcf2..837ff965a4 --- a/dir.c +++ b/dir.c @@@ -9,6 -9,7 +9,7 @@@ */ #include "cache.h" #include "dir.h" + #include "attr.h" #include "refs.h" #include "wildmatch.h" #include "pathspec.h" @@@ -134,7 -135,8 +135,8 @@@ static size_t common_prefix_len(const s PATHSPEC_LITERAL | PATHSPEC_GLOB | PATHSPEC_ICASE | - PATHSPEC_EXCLUDE); + PATHSPEC_EXCLUDE | + PATHSPEC_ATTR); for (n = 0; n < pathspec->nr; n++) { size_t i = 0, len = 0, item_len; @@@ -209,6 -211,36 +211,36 @@@ int within_depth(const char *name, int #define DO_MATCH_DIRECTORY (1<<1) #define DO_MATCH_SUBMODULE (1<<2) + static int match_attrs(const char *name, int namelen, + const struct pathspec_item *item) + { + int i; + + git_check_attr(name, item->attr_check); + for (i = 0; i < item->attr_match_nr; i++) { + const char *value; + int matched; + enum attr_match_mode match_mode; + + value = item->attr_check->items[i].value; + match_mode = item->attr_match[i].match_mode; + + if (ATTR_TRUE(value)) + matched = (match_mode == MATCH_SET); + else if (ATTR_FALSE(value)) + matched = (match_mode == MATCH_UNSET); + else if (ATTR_UNSET(value)) + matched = (match_mode == MATCH_UNSPECIFIED); + else + matched = (match_mode == MATCH_VALUE && + !strcmp(item->attr_match[i].value, value)); + if (!matched) + return 0; + } + + return 1; + } + /* * Does 'match' match the given name? * A match is found if @@@ -261,6 -293,9 +293,9 @@@ static int match_pathspec_item(const st strncmp(item->match, name - prefix, item->prefix)) return 0; + if (item->attr_match_nr && !match_attrs(name, namelen, item)) + return 0; + /* If the match was just the prefix, we matched */ if (!*match) return MATCHED_RECURSIVELY; @@@ -339,7 -374,8 +374,8 @@@ static int do_match_pathspec(const stru PATHSPEC_LITERAL | PATHSPEC_GLOB | PATHSPEC_ICASE | - PATHSPEC_EXCLUDE); + PATHSPEC_EXCLUDE | + PATHSPEC_ATTR); if (!ps->nr) { if (!ps->recursive || @@@ -1361,7 -1397,8 +1397,8 @@@ static int simplify_away(const char *pa PATHSPEC_LITERAL | PATHSPEC_GLOB | PATHSPEC_ICASE | - PATHSPEC_EXCLUDE); + PATHSPEC_EXCLUDE | + PATHSPEC_ATTR); for (i = 0; i < pathspec->nr; i++) { const struct pathspec_item *item = &pathspec->items[i]; @@@ -2730,8 -2767,8 +2767,8 @@@ void connect_work_tree_and_git_dir(cons { struct strbuf file_name = STRBUF_INIT; struct strbuf rel_path = STRBUF_INIT; - char *git_dir = real_pathdup(git_dir_); - char *work_tree = real_pathdup(work_tree_); + char *git_dir = real_pathdup(git_dir_, 1); + char *work_tree = real_pathdup(work_tree_, 1); /* Update gitfile */ strbuf_addf(&file_name, "%s/.git", work_tree);