previous discussion: https://public-inbox.org/git/20161028185502.8789-1-sbeller@xxxxxxxxxx/ Changes since v2: * dropped one patch (that exposes git_attr_counted, nobody uses it throughout the series ) * added pathspec guarding and added a test with git-add to see if it works. * squashed "SQUASH" commits. * changed test for multithreaded tests as git-status makes use of pathspec code that doesn't support this new magic yet. interdiff to currently queued at the bottom of this email. v2 was: previous discussion at https://public-inbox.org/git/20161022233225.8883-1-sbeller@xxxxxxxxxx This implements the discarded series': jc/attr jc/attr-more sb/pathspec-label sb/submodule-default-paths This includes * The fixes for windows * Junios latest suggestion to use git_attr_check_initv instead of alloc/append. * I implemented the thread safe attr API in patch 27 (attr: convert to new threadsafe API) * patch 28 (attr: keep attr stack for each check) makes it actually possible to run in a multithreaded environment. * I added a test for the multithreaded when it is introduced in patch 32 (pathspec: allow querying for attributes) as well as a test to disallow multiple "attr"s in a pathspec. Thanks, Stefan Junio C Hamano (23): commit.c: use strchrnul() to scan for one line attr.c: use strchrnul() to scan for one line attr.c: update a stale comment on "struct match_attr" attr.c: explain the lack of attr-name syntax check in parse_attr() attr.c: complete a sentence in a comment attr.c: mark where #if DEBUG ends more clearly attr.c: simplify macroexpand_one() attr.c: tighten constness around "git_attr" structure attr.c: plug small leak in parse_attr_line() attr: rename function and struct related to checking attributes attr: (re)introduce git_check_attr() and struct git_attr_check attr: convert git_all_attrs() to use "struct git_attr_check" attr: convert git_check_attrs() callers to use the new API attr: retire git_check_attrs() API attr: add counted string version of git_check_attr() attr: expose validity check for attribute names attr.c: add push_stack() helper attr.c: pass struct git_attr_check down the callchain attr.c: rename a local variable check attr.c: correct ugly hack for git_all_attrs() attr.c: introduce empty_attr_check_elems() attr.c: always pass check[] to collect_some_attrs() attr.c: outline the future plans by heavily commenting Nguyễn Thái Ngọc Duy (1): attr: support quoting pathname patterns in C style Stefan Beller (11): attr: make git_check_attr_counted static attr: convert to new threadsafe API attr: keep attr stack for each check Documentation: fix a typo pathspec: move long magic parsing out of prefix_pathspec pathspec: move prefix check out of the inner loop pathspec: allow querying for attributes pathspec: allow escaped query values submodule update: add `--init-default-path` switch clone: add --init-submodule=<pathspec> switch completion: clone can initialize specific submodules Documentation/config.txt | 5 + Documentation/git-clone.txt | 23 +- Documentation/git-submodule.txt | 17 +- Documentation/gitattributes.txt | 10 +- Documentation/glossary-content.txt | 20 + Documentation/technical/api-gitattributes.txt | 140 ++++--- archive.c | 25 +- attr.c | 517 ++++++++++++++++++-------- attr.h | 71 ++-- builtin/check-attr.c | 74 ++-- builtin/clone.c | 36 +- builtin/pack-objects.c | 27 +- commit.c | 3 +- common-main.c | 2 + contrib/completion/git-completion.bash | 1 + convert.c | 46 ++- dir.c | 41 +- git-submodule.sh | 21 +- hashmap.h | 2 + ll-merge.c | 35 +- pathspec.c | 228 ++++++++++-- pathspec.h | 19 +- t/t0003-attributes.sh | 26 ++ t/t6134-pathspec-with-labels.sh | 201 ++++++++++ t/t7400-submodule-basic.sh | 134 +++++++ userdiff.c | 21 +- ws.c | 19 +- 27 files changed, 1354 insertions(+), 410 deletions(-) create mode 100755 t/t6134-pathspec-with-labels.sh -- interdiff to current origin/sb/attr: diff --git a/attr.c b/attr.c index cf15e76..979bd3c 100644 --- a/attr.c +++ b/attr.c @@ -135,7 +135,7 @@ static void report_invalid_attr(const char *name, size_t len, strbuf_release(&err); } -struct git_attr *git_attr_counted(const char *name, size_t len) +static struct git_attr *git_attr_internal(const char *name, int len) { unsigned hval = hash_name(name, len); unsigned pos = hval % HASHSIZE; @@ -171,7 +171,7 @@ struct git_attr *git_attr_counted(const char *name, size_t len) struct git_attr *git_attr(const char *name) { - return git_attr_counted(name, strlen(name)); + return git_attr_internal(name, strlen(name)); } /* What does a matched pattern decide? */ @@ -259,7 +259,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp, else { e->setto = xmemdupz(equals + 1, ep - equals - 1); } - e->attr = git_attr_counted(cp, len); + e->attr = git_attr_internal(cp, len); } return ep + strspn(ep, blank); } @@ -320,7 +320,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src, sizeof(struct attr_state) * num_attr + (is_macro ? 0 : namelen + 1)); if (is_macro) { - res->u.attr = git_attr_counted(name, namelen); + res->u.attr = git_attr_internal(name, namelen); res->u.attr->maybe_macro = 1; } else { char *p = (char *)&(res->state[num_attr]); diff --git a/attr.h b/attr.h index e7534da..ab381ae 100644 --- a/attr.h +++ b/attr.h @@ -2,7 +2,7 @@ #define ATTR_H /* - * Must be called on platforms that do not support static initialisation + * Must be called on platforms that do not support static initialization * of mutexes. */ extern void attr_start(void); diff --git a/dir.c b/dir.c index 3ec9117..c56d2ee 100644 --- a/dir.c +++ b/dir.c @@ -140,7 +140,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; @@ -349,7 +350,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 || diff --git a/pathspec.c b/pathspec.c index 8ea5dcb..d702803 100644 --- a/pathspec.c +++ b/pathspec.c @@ -232,6 +232,7 @@ static void eat_long_magic(struct pathspec_item *item, const char *elt, char *attr_body = xmemdupz(body, len - strlen("attr:")); parse_pathspec_attr_match(item, attr_body); free(attr_body); + *magic |= PATHSPEC_ATTR; continue; } diff --git a/pathspec.h b/pathspec.h index ebef4bf..c2d046d 100644 --- a/pathspec.h +++ b/pathspec.h @@ -8,13 +8,15 @@ #define PATHSPEC_GLOB (1<<3) #define PATHSPEC_ICASE (1<<4) #define PATHSPEC_EXCLUDE (1<<5) +#define PATHSPEC_ATTR (1<<6) #define PATHSPEC_ALL_MAGIC \ (PATHSPEC_FROMTOP | \ PATHSPEC_MAXDEPTH | \ PATHSPEC_LITERAL | \ PATHSPEC_GLOB | \ PATHSPEC_ICASE | \ - PATHSPEC_EXCLUDE) + PATHSPEC_EXCLUDE | \ + PATHSPEC_ATTR) #define PATHSPEC_ONESTAR 1 /* the pathspec pattern satisfies GFNM_ONESTAR */ diff --git a/t/t6134-pathspec-with-labels.sh b/t/t6134-pathspec-with-labels.sh index 3d03e0a..5aafc0c 100755 --- a/t/t6134-pathspec-with-labels.sh +++ b/t/t6134-pathspec-with-labels.sh @@ -160,7 +160,23 @@ test_expect_success 'fail on multiple attr specifiers in one pathspec item' ' ' test_expect_success 'checking attributes in a multithreaded process' ' - git status ":(attr:labelB)" + cat <<-EOF >expect && + fileA:A + EOF + echo A >fileA && + echo A >fileB && + git grep A -- ":(attr:labelA)" >actual && + test_cmp expect actual +' + +test_expect_success 'fail if attr magic is used places not implemented' ' + # The main purpose of this test is to check that we actually fail + # when you attempt to use attr magic in commands that do not implement + # attr magic. This test does not advocate git-add to stay that way, + # though, but git-add is convenient as it has its own internal pathspec + # parsing. + test_must_fail git add ":(attr:labelB)" 2>actual && + test_i18ngrep "unsupported magic" actual ' test_expect_success 'abort on giving invalid label on the command line' ' -- 2.10.1.469.g00a8914