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
This commit is contained in:
Junio C Hamano
2017-03-17 13:50:26 -07:00
7 changed files with 446 additions and 10 deletions

43
dir.c
View File

@ -9,6 +9,7 @@
*/
#include "cache.h"
#include "dir.h"
#include "attr.h"
#include "refs.h"
#include "wildmatch.h"
#include "pathspec.h"
@ -134,7 +135,8 @@ static size_t common_prefix_len(const struct pathspec *pathspec)
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 @@ int within_depth(const char *name, int namelen,
#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 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
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 @@ static int do_match_pathspec(const struct pathspec *ps,
PATHSPEC_LITERAL |
PATHSPEC_GLOB |
PATHSPEC_ICASE |
PATHSPEC_EXCLUDE);
PATHSPEC_EXCLUDE |
PATHSPEC_ATTR);
if (!ps->nr) {
if (!ps->recursive ||
@ -1361,7 +1397,8 @@ static int simplify_away(const char *path, int pathlen,
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];