{"thread":{"id":"28017","subject":"[PATCH v3 00/23] Add --all option to git-check-attr","startedAt":"2011-08-04T04:36:10Z","lastAt":"2011-08-04T04:36:33Z","messageCount":24,"participants":["Michael Haggerty"],"isPatch":true,"patchVersion":3,"patchTotal":23},"messages":[{"id":"172854","messageId":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":null,"subject":"[PATCH v3 00/23] Add --all option to git-check-attr","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:10Z","receivedAt":"2011-08-04T04:36:10Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"This re-roll differs in the following ways from v2:\n\n* The following series of refactoring patches were inserted:\n\n      Teach prepare_attr_stack() to figure out dirlen itself\n      Extract a function collect_all_attrs()\n      Remove redundant call to bootstrap_attr_stack()\n      Remove redundant check\n\n  This change, in turn, simplifies patch\n\n      Allow querying all attributes on a file\n\n* The new API function is named git_all_attrs() instead of\n  git_allattrs().\n\n* Additionally, git_checkattr() is renamed to git_check_attr() at the\n  suggestion of Junio.\n\n* The renaming of struct git_attr_check to git_attr_value is no longer\n  part of the patch series.\n\nThanks to Junio for the great feedback.  I believe that I have\naddressed all of your comments.\n\nMichael Haggerty (23):\n  doc: Add a link from gitattributes(5) to git-check-attr(1)\n  doc: Correct git_attr() calls in example code\n  Remove anachronism from comment\n  Disallow the empty string as an attribute name\n  git-check-attr: Add missing \"&&\"\n  git-check-attr: Add tests of command-line parsing\n  Provide access to the name attribute of git_attr\n  git-check-attr: Use git_attr_name()\n  Teach prepare_attr_stack() to figure out dirlen itself\n  Extract a function collect_all_attrs()\n  Remove redundant call to bootstrap_attr_stack()\n  Remove redundant check\n  Allow querying all attributes on a file\n  git-check-attr: Extract a function output_attr()\n  git-check-attr: Introduce a new variable\n  git-check-attr: Extract a function error_with_usage()\n  git-check-attr: Handle each error separately\n  git-check-attr: Process command-line args more systematically\n  git-check-attr: Error out if no pathnames are specified\n  git-check-attr: Add an --all option to show all attributes\n  git-check-attr: Drive two tests using the same raw data\n  git-check-attr: Fix command-line handling to match docs\n  Rename git_checkattr() to git_check_attr()\n\n Documentation/git-check-attr.txt              |   23 ++++-\n Documentation/gitattributes.txt               |    3 +\n Documentation/technical/api-gitattributes.txt |   63 +++++++++-----\n archive.c                                     |    2 +-\n attr.c                                        |   79 ++++++++++++----\n attr.h                                        |   20 ++++-\n builtin/check-attr.c                          |  121 +++++++++++++++++--------\n builtin/pack-objects.c                        |    2 +-\n convert.c                                     |    2 +-\n ll-merge.c                                    |    4 +-\n t/t0003-attributes.sh                         |   61 +++++++++----\n userdiff.c                                    |    2 +-\n ws.c                                          |    2 +-\n 13 files changed, 272 insertions(+), 112 deletions(-)\n\n-- \n1.7.6.8.gd2879\n"},{"id":"172862","messageId":"1312432593-9841-2-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 01/23] doc: Add a link from gitattributes(5) to git-check-attr(1)","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:11Z","receivedAt":"2011-08-04T04:36:11Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n Documentation/gitattributes.txt |    3 +++\n 1 files changed, 3 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\nindex 2bbe76b..25e46ae 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -955,6 +955,9 @@ frotz\tunspecified\n ----------------------------------------------------------------\n \n \n+SEE ALSO\n+--------\n+linkgit:git-check-attr[1].\n \n GIT\n ---\n-- \n1.7.6.8.gd2879\n"},{"id":"172855","messageId":"1312432593-9841-3-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 02/23] doc: Correct git_attr() calls in example code","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:12Z","receivedAt":"2011-08-04T04:36:12Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"Commit 7fb0eaa2 (2010-01-17) changed git_attr() to take a string\ninstead of a string and a length.  Update the documentation\naccordingly.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n Documentation/technical/api-gitattributes.txt |   10 +++++-----\n 1 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt\nindex 9d97eaa..916720f 100644\n--- a/Documentation/technical/api-gitattributes.txt\n+++ b/Documentation/technical/api-gitattributes.txt\n@@ -11,9 +11,9 @@ Data Structure\n `struct git_attr`::\n \n \tAn attribute is an opaque object that is identified by its name.\n-\tPass the name and its length to `git_attr()` function to obtain\n-\tthe object of this type.  The internal representation of this\n-\tstructure is of no interest to the calling programs.\n+\tPass the name to `git_attr()` function to obtain the object of\n+\tthis type.  The internal representation of this structure is\n+\tof no interest to the calling programs.\n \n `struct git_attr_check`::\n \n@@ -72,8 +72,8 @@ static void setup_check(void)\n {\n \tif (check[0].attr)\n \t\treturn; /* already done */\n-\tcheck[0].attr = git_attr(\"crlf\", 4);\n-\tcheck[1].attr = git_attr(\"ident\", 5);\n+\tcheck[0].attr = git_attr(\"crlf\");\n+\tcheck[1].attr = git_attr(\"ident\");\n }\n ------------\n \n-- \n1.7.6.8.gd2879\n"},{"id":"172856","messageId":"1312432593-9841-4-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 03/23] Remove anachronism from comment","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:13Z","receivedAt":"2011-08-04T04:36:13Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"Setting attributes to arbitrary values (\"attribute=value\") is now\nsupported, so it is no longer necessary for this comment to justify\nprohibiting '=' in an attribute name.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n attr.c |    6 ++----\n 1 files changed, 2 insertions(+), 4 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex f6b3f7e..4a1244f 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -50,10 +50,8 @@ static unsigned hash_name(const char *name, int namelen)\n static int invalid_attr_name(const char *name, int namelen)\n {\n \t/*\n-\t * Attribute name cannot begin with '-' and from\n-\t * [-A-Za-z0-9_.].  We'd specifically exclude '=' for now,\n-\t * as we might later want to allow non-binary value for\n-\t * attributes, e.g. \"*.svg\tmerge=special-merge-program-for-svg\"\n+\t * Attribute name cannot begin with '-' and must consist of\n+\t * characters from [-A-Za-z0-9_.].\n \t */\n \tif (*name == '-')\n \t\treturn -1;\n-- \n1.7.6.8.gd2879\n"},{"id":"172859","messageId":"1312432593-9841-5-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 04/23] Disallow the empty string as an attribute name","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:14Z","receivedAt":"2011-08-04T04:36:14Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"Previously, it was possible to have a line like \"file.txt =foo\" in a\n.gitattribute file, after which an invocation like \"git check-attr ''\n-- file.txt\" would succeed.  This patch disallows both constructs.\n\nPlease note that any existing .gitattributes file that tries to set an\nempty attribute will now trigger the error message \"error: : not a\nvalid attribute name\" whereas previously the nonsense was allowed\nthrough.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n attr.c                |    2 +-\n t/t0003-attributes.sh |    6 ++++++\n 2 files changed, 7 insertions(+), 1 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 4a1244f..b1d1d6d 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -53,7 +53,7 @@ static int invalid_attr_name(const char *name, int namelen)\n \t * Attribute name cannot begin with '-' and must consist of\n \t * characters from [-A-Za-z0-9_.].\n \t */\n-\tif (*name == '-')\n+\tif (namelen <= 0 || *name == '-')\n \t\treturn -1;\n \twhile (namelen--) {\n \t\tchar ch = *name++;\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex ebbc755..8c76b79 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -42,6 +42,12 @@ test_expect_success 'setup' '\n \n '\n \n+test_expect_success 'command line checks' '\n+\n+\ttest_must_fail git check-attr \"\" -- f\n+\n+'\n+\n test_expect_success 'attribute test' '\n \n \tattr_check f f &&\n-- \n1.7.6.8.gd2879\n"},{"id":"172857","messageId":"1312432593-9841-6-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 05/23] git-check-attr: Add missing \"&&\"","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:15Z","receivedAt":"2011-08-04T04:36:15Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n t/t0003-attributes.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex 8c76b79..dae76b3 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -35,7 +35,7 @@ test_expect_success 'setup' '\n \t\techo \"h test=a/b/h\" &&\n \t\techo \"d/* test=a/b/d/*\"\n \t\techo \"d/yes notest\"\n-\t) >a/b/.gitattributes\n+\t) >a/b/.gitattributes &&\n \t(\n \t\techo \"global test=global\"\n \t) >\"$HOME\"/global-gitattributes\n-- \n1.7.6.8.gd2879\n"},{"id":"172863","messageId":"1312432593-9841-7-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 06/23] git-check-attr: Add tests of command-line parsing","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:16Z","receivedAt":"2011-08-04T04:36:16Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n t/t0003-attributes.sh |    7 +++++++\n 1 files changed, 7 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex dae76b3..f1debeb 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -44,6 +44,13 @@ test_expect_success 'setup' '\n \n test_expect_success 'command line checks' '\n \n+\ttest_must_fail git check-attr &&\n+\ttest_must_fail git check-attr -- &&\n+\ttest_must_fail git check-attr -- f &&\n+\techo \"f\" | test_must_fail git check-attr --stdin &&\n+\techo \"f\" | test_must_fail git check-attr --stdin -- f &&\n+\techo \"f\" | test_must_fail git check-attr --stdin test -- f &&\n+\techo \"f\" | test_must_fail git check-attr --stdin test f &&\n \ttest_must_fail git check-attr \"\" -- f\n \n '\n-- \n1.7.6.8.gd2879\n"},{"id":"172858","messageId":"1312432593-9841-8-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 07/23] Provide access to the name attribute of git_attr","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:17Z","receivedAt":"2011-08-04T04:36:17Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"It will be present in any likely future reimplementation, and its\navailability simplifies other code.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n Documentation/technical/api-gitattributes.txt |    3 ++-\n attr.c                                        |    5 +++++\n attr.h                                        |    7 +++++++\n 3 files changed, 14 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt\nindex 916720f..ab3a84d 100644\n--- a/Documentation/technical/api-gitattributes.txt\n+++ b/Documentation/technical/api-gitattributes.txt\n@@ -13,7 +13,8 @@ Data Structure\n \tAn attribute is an opaque object that is identified by its name.\n \tPass the name to `git_attr()` function to obtain the object of\n \tthis type.  The internal representation of this structure is\n-\tof no interest to the calling programs.\n+\tof no interest to the calling programs.  The name of the\n+\tattribute can be retrieved by calling `git_attr_name()`.\n \n `struct git_attr_check`::\n \ndiff --git a/attr.c b/attr.c\nindex b1d1d6d..bfa1f43 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -36,6 +36,11 @@ static int attr_nr;\n static struct git_attr_check *check_all_attr;\n static struct git_attr *(git_attr_hash[HASHSIZE]);\n \n+char *git_attr_name(struct git_attr *attr)\n+{\n+\treturn attr->name;\n+}\n+\n static unsigned hash_name(const char *name, int namelen)\n {\n \tunsigned val = 0, c;\ndiff --git a/attr.h b/attr.h\nindex 8b3f19b..d4f875a 100644\n--- a/attr.h\n+++ b/attr.h\n@@ -29,6 +29,13 @@ struct git_attr_check {\n \tconst char *value;\n };\n \n+/*\n+ * Return the name of the attribute represented by the argument.  The\n+ * return value is a pointer to a null-delimited string that is part\n+ * of the internal data structure; it should not be modified or freed.\n+ */\n+char *git_attr_name(struct git_attr *);\n+\n int git_checkattr(const char *path, int, struct git_attr_check *);\n \n enum git_attr_direction {\n-- \n1.7.6.8.gd2879\n"},{"id":"172861","messageId":"1312432593-9841-9-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 08/23] git-check-attr: Use git_attr_name()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:18Z","receivedAt":"2011-08-04T04:36:18Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/check-attr.c |   13 ++++++-------\n 1 files changed, 6 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex 3016d29..5f04126 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -21,7 +21,7 @@ static const struct option check_attr_options[] = {\n };\n \n static void check_attr(int cnt, struct git_attr_check *check,\n-\tconst char** name, const char *file)\n+\tconst char *file)\n {\n \tint j;\n \tif (git_checkattr(file, cnt, check))\n@@ -37,12 +37,11 @@ static void check_attr(int cnt, struct git_attr_check *check,\n \t\t\tvalue = \"unspecified\";\n \n \t\tquote_c_style(file, NULL, stdout, 0);\n-\t\tprintf(\": %s: %s\\n\", name[j], value);\n+\t\tprintf(\": %s: %s\\n\", git_attr_name(check[j].attr), value);\n \t}\n }\n \n-static void check_attr_stdin_paths(int cnt, struct git_attr_check *check,\n-\tconst char** name)\n+static void check_attr_stdin_paths(int cnt, struct git_attr_check *check)\n {\n \tstruct strbuf buf, nbuf;\n \tint line_termination = null_term_line ? 0 : '\\n';\n@@ -56,7 +55,7 @@ static void check_attr_stdin_paths(int cnt, struct git_attr_check *check,\n \t\t\t\tdie(\"line is badly quoted\");\n \t\t\tstrbuf_swap(&buf, &nbuf);\n \t\t}\n-\t\tcheck_attr(cnt, check, name, buf.buf);\n+\t\tcheck_attr(cnt, check, buf.buf);\n \t\tmaybe_flush_or_die(stdout, \"attribute to stdout\");\n \t}\n \tstrbuf_release(&buf);\n@@ -113,10 +112,10 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (stdin_paths)\n-\t\tcheck_attr_stdin_paths(cnt, check, argv);\n+\t\tcheck_attr_stdin_paths(cnt, check);\n \telse {\n \t\tfor (i = doubledash; i < argc; i++)\n-\t\t\tcheck_attr(cnt, check, argv, argv[i]);\n+\t\t\tcheck_attr(cnt, check, argv[i]);\n \t\tmaybe_flush_or_die(stdout, \"attribute to stdout\");\n \t}\n \treturn 0;\n-- \n1.7.6.8.gd2879\n"},{"id":"172860","messageId":"1312432593-9841-10-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 09/23] Teach prepare_attr_stack() to figure out dirlen itself","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:19Z","receivedAt":"2011-08-04T04:36:19Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n attr.c |   21 +++++++++++----------\n 1 files changed, 11 insertions(+), 10 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex bfa1f43..7f0f390 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -535,11 +535,18 @@ static void bootstrap_attr_stack(void)\n \t}\n }\n \n-static void prepare_attr_stack(const char *path, int dirlen)\n+static void prepare_attr_stack(const char *path)\n {\n \tstruct attr_stack *elem, *info;\n-\tint len;\n+\tint dirlen, len;\n \tstruct strbuf pathbuf;\n+\tconst char *cp;\n+\n+\tcp = strrchr(path, '/');\n+\tif (!cp)\n+\t\tdirlen = 0;\n+\telse\n+\t\tdirlen = cp - path;\n \n \tstrbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));\n \n@@ -709,20 +716,14 @@ static int macroexpand_one(int attr_nr, int rem)\n int git_checkattr(const char *path, int num, struct git_attr_check *check)\n {\n \tstruct attr_stack *stk;\n-\tconst char *cp;\n-\tint dirlen, pathlen, i, rem;\n+\tint pathlen, i, rem;\n \n \tbootstrap_attr_stack();\n \tfor (i = 0; i < attr_nr; i++)\n \t\tcheck_all_attr[i].value = ATTR__UNKNOWN;\n \n \tpathlen = strlen(path);\n-\tcp = strrchr(path, '/');\n-\tif (!cp)\n-\t\tdirlen = 0;\n-\telse\n-\t\tdirlen = cp - path;\n-\tprepare_attr_stack(path, dirlen);\n+\tprepare_attr_stack(path);\n \trem = attr_nr;\n \tfor (stk = attr_stack; 0 < rem && stk; stk = stk->prev)\n \t\trem = fill(path, pathlen, stk, rem);\n-- \n1.7.6.8.gd2879\n"},{"id":"172877","messageId":"1312432593-9841-11-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 10/23] Extract a function collect_all_attrs()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:20Z","receivedAt":"2011-08-04T04:36:20Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n attr.c |   17 ++++++++++++++---\n 1 files changed, 14 insertions(+), 3 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 7f0f390..bc589f0 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -713,20 +713,31 @@ static int macroexpand_one(int attr_nr, int rem)\n \treturn rem;\n }\n \n-int git_checkattr(const char *path, int num, struct git_attr_check *check)\n+/*\n+ * Collect all attributes for path into the array pointed to by\n+ * check_all_attr.\n+ */\n+static void collect_all_attrs(const char *path)\n {\n \tstruct attr_stack *stk;\n-\tint pathlen, i, rem;\n+\tint i, pathlen, rem;\n \n \tbootstrap_attr_stack();\n+\tprepare_attr_stack(path);\n \tfor (i = 0; i < attr_nr; i++)\n \t\tcheck_all_attr[i].value = ATTR__UNKNOWN;\n \n \tpathlen = strlen(path);\n-\tprepare_attr_stack(path);\n \trem = attr_nr;\n \tfor (stk = attr_stack; 0 < rem && stk; stk = stk->prev)\n \t\trem = fill(path, pathlen, stk, rem);\n+}\n+\n+int git_checkattr(const char *path, int num, struct git_attr_check *check)\n+{\n+\tint i;\n+\n+\tcollect_all_attrs(path);\n \n \tfor (i = 0; i < num; i++) {\n \t\tconst char *value = check_all_attr[check[i].attr->attr_nr].value;\n-- \n1.7.6.8.gd2879\n"},{"id":"172875","messageId":"1312432593-9841-12-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 11/23] Remove redundant call to bootstrap_attr_stack()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:21Z","receivedAt":"2011-08-04T04:36:21Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"prepare_attr_stack() does the same thing.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n attr.c |    1 -\n 1 files changed, 0 insertions(+), 1 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex bc589f0..b8ce158 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -722,7 +722,6 @@ static void collect_all_attrs(const char *path)\n \tstruct attr_stack *stk;\n \tint i, pathlen, rem;\n \n-\tbootstrap_attr_stack();\n \tprepare_attr_stack(path);\n \tfor (i = 0; i < attr_nr; i++)\n \t\tcheck_all_attr[i].value = ATTR__UNKNOWN;\n-- \n1.7.6.8.gd2879\n"},{"id":"172864","messageId":"1312432593-9841-13-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 12/23] Remove redundant check","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:22Z","receivedAt":"2011-08-04T04:36:22Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"bootstrap_attr_stack() also checks whether attr_stack is already set.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n attr.c |    3 +--\n 1 files changed, 1 insertions(+), 2 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex b8ce158..ab30c81 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -565,8 +565,7 @@ static void prepare_attr_stack(const char *path)\n \t * .gitattributes in deeper directories to shallower ones,\n \t * and finally use the built-in set as the default.\n \t */\n-\tif (!attr_stack)\n-\t\tbootstrap_attr_stack();\n+\tbootstrap_attr_stack();\n \n \t/*\n \t * Pop the \"info\" one that is always at the top of the stack.\n-- \n1.7.6.8.gd2879\n"},{"id":"172872","messageId":"1312432593-9841-14-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 13/23] Allow querying all attributes on a file","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:23Z","receivedAt":"2011-08-04T04:36:23Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"Add a function, git_all_attrs(), that reports on all attributes that\nare set on a path.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n Documentation/technical/api-gitattributes.txt |   46 +++++++++++++++++-------\n attr.c                                        |   28 +++++++++++++++\n attr.h                                        |    9 +++++\n 3 files changed, 69 insertions(+), 14 deletions(-)\n\ndiff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt\nindex ab3a84d..3bd2f57 100644\n--- a/Documentation/technical/api-gitattributes.txt\n+++ b/Documentation/technical/api-gitattributes.txt\n@@ -22,19 +22,6 @@ Data Structure\n \tto `git_checkattr()` function, and receives the results.\n \n \n-Calling Sequence\n-----------------\n-\n-* Prepare an array of `struct git_attr_check` to define the list of\n-  attributes you would want to check.  To populate this array, you would\n-  need to define necessary attributes by calling `git_attr()` function.\n-\n-* Call git_checkattr() to check the attributes for the path.\n-\n-* Inspect `git_attr_check` structure to see how each of the attribute in\n-  the array is defined for the path.\n-\n-\n Attribute Values\n ----------------\n \n@@ -58,6 +45,19 @@ If none of the above returns true, `.value` member points at a string\n value of the attribute for the path.\n \n \n+Querying Specific Attributes\n+----------------------------\n+\n+* Prepare an array of `struct git_attr_check` to define the list of\n+  attributes you would want to check.  To populate this array, you would\n+  need to define necessary attributes by calling `git_attr()` function.\n+\n+* Call `git_checkattr()` to check the attributes for the path.\n+\n+* Inspect `git_attr_check` structure to see how each of the attribute in\n+  the array is defined for the path.\n+\n+\n Example\n -------\n \n@@ -109,4 +109,22 @@ static void setup_check(void)\n \t}\n ------------\n \n-(JC)\n+\n+Querying All Attributes\n+-----------------------\n+\n+To get the values of all attributes associated with a file:\n+\n+* Call `git_all_attrs()`, which returns an array of `git_attr_check`\n+  structures.\n+\n+* Iterate over the `git_attr_check` array to examine the attribute\n+  names and values.  The name of the attribute described by a\n+  `git_attr_check` object can be retrieved via\n+  `git_attr_name(check[i].attr)`.  (Please note that no items will be\n+  returned for unset attributes, so `ATTR_UNSET()` will return false\n+  for all returned `git_array_check` objects.)\n+\n+* Free the `git_array_check` array.\n+\n+\ndiff --git a/attr.c b/attr.c\nindex ab30c81..658112e 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -747,6 +747,34 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)\n \treturn 0;\n }\n \n+int git_all_attrs(const char *path, int *num, struct git_attr_check **check)\n+{\n+\tint i, count, j;\n+\n+\tcollect_all_attrs(path);\n+\n+\t/* Count the number of attributes that are set. */\n+\tcount = 0;\n+\tfor (i = 0; i < attr_nr; i++) {\n+\t\tconst char *value = check_all_attr[i].value;\n+\t\tif (value != ATTR__UNSET && value != ATTR__UNKNOWN)\n+\t\t\t++count;\n+\t}\n+\t*num = count;\n+\t*check = xmalloc(sizeof(**check) * count);\n+\tj = 0;\n+\tfor (i = 0; i < attr_nr; i++) {\n+\t\tconst char *value = check_all_attr[i].value;\n+\t\tif (value != ATTR__UNSET && value != ATTR__UNKNOWN) {\n+\t\t\t(*check)[j].attr = check_all_attr[i].attr;\n+\t\t\t(*check)[j].value = value;\n+\t\t\t++j;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)\n {\n \tenum git_attr_direction old = direction;\ndiff --git a/attr.h b/attr.h\nindex d4f875a..9e22893 100644\n--- a/attr.h\n+++ b/attr.h\n@@ -38,6 +38,15 @@ char *git_attr_name(struct git_attr *);\n \n int git_checkattr(const char *path, int, struct git_attr_check *);\n \n+/*\n+ * Retrieve all attributes that apply to the specified path.  *num\n+ * will be set the the number of attributes on the path; **check will\n+ * be set to point at a newly-allocated array of git_attr_check\n+ * objects describing the attributes and their values.  *check must be\n+ * free()ed by the caller.\n+ */\n+int git_all_attrs(const char *path, int *num, struct git_attr_check **check);\n+\n enum git_attr_direction {\n \tGIT_ATTR_CHECKIN,\n \tGIT_ATTR_CHECKOUT,\n-- \n1.7.6.8.gd2879\n"},{"id":"172876","messageId":"1312432593-9841-15-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 14/23] git-check-attr: Extract a function output_attr()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:24Z","receivedAt":"2011-08-04T04:36:24Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/check-attr.c |   12 +++++++++---\n 1 files changed, 9 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex 5f04126..384c5a6 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -20,12 +20,10 @@ static const struct option check_attr_options[] = {\n \tOPT_END()\n };\n \n-static void check_attr(int cnt, struct git_attr_check *check,\n+static void output_attr(int cnt, struct git_attr_check *check,\n \tconst char *file)\n {\n \tint j;\n-\tif (git_checkattr(file, cnt, check))\n-\t\tdie(\"git_checkattr died\");\n \tfor (j = 0; j < cnt; j++) {\n \t\tconst char *value = check[j].value;\n \n@@ -41,6 +39,14 @@ static void check_attr(int cnt, struct git_attr_check *check,\n \t}\n }\n \n+static void check_attr(int cnt, struct git_attr_check *check,\n+\tconst char *file)\n+{\n+\tif (git_checkattr(file, cnt, check))\n+\t\tdie(\"git_checkattr died\");\n+\toutput_attr(cnt, check, file);\n+}\n+\n static void check_attr_stdin_paths(int cnt, struct git_attr_check *check)\n {\n \tstruct strbuf buf, nbuf;\n-- \n1.7.6.8.gd2879\n"},{"id":"172865","messageId":"1312432593-9841-16-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 15/23] git-check-attr: Introduce a new variable","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:25Z","receivedAt":"2011-08-04T04:36:25Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"Avoid reusing variable \"doubledash\" to mean something other than the\nexpected \"position of a double-dash, if any\".\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/check-attr.c |   13 +++++++------\n 1 files changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex 384c5a6..c527078 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -71,7 +71,7 @@ static void check_attr_stdin_paths(int cnt, struct git_attr_check *check)\n int cmd_check_attr(int argc, const char **argv, const char *prefix)\n {\n \tstruct git_attr_check *check;\n-\tint cnt, i, doubledash;\n+\tint cnt, i, doubledash, filei;\n \tconst char *errstr = NULL;\n \n \targc = parse_options(argc, argv, prefix, check_attr_options,\n@@ -92,14 +92,15 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \t/* If there is no double dash, we handle only one attribute */\n \tif (doubledash < 0) {\n \t\tcnt = 1;\n-\t\tdoubledash = 0;\n-\t} else\n+\t\tfilei = 1;\n+\t} else {\n \t\tcnt = doubledash;\n-\tdoubledash++;\n+\t\tfilei = doubledash + 1;\n+\t}\n \n \tif (cnt <= 0)\n \t\terrstr = \"No attribute specified\";\n-\telse if (stdin_paths && doubledash < argc)\n+\telse if (stdin_paths && filei < argc)\n \t\terrstr = \"Can't specify files with --stdin\";\n \tif (errstr) {\n \t\terror(\"%s\", errstr);\n@@ -120,7 +121,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \tif (stdin_paths)\n \t\tcheck_attr_stdin_paths(cnt, check);\n \telse {\n-\t\tfor (i = doubledash; i < argc; i++)\n+\t\tfor (i = filei; i < argc; i++)\n \t\t\tcheck_attr(cnt, check, argv[i]);\n \t\tmaybe_flush_or_die(stdout, \"attribute to stdout\");\n \t}\n-- \n1.7.6.8.gd2879\n"},{"id":"172866","messageId":"1312432593-9841-17-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 16/23] git-check-attr: Extract a function error_with_usage()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:26Z","receivedAt":"2011-08-04T04:36:26Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/check-attr.c |    9 +++++++--\n 1 files changed, 7 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex c527078..d004222 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -68,6 +68,12 @@ static void check_attr_stdin_paths(int cnt, struct git_attr_check *check)\n \tstrbuf_release(&nbuf);\n }\n \n+static NORETURN void error_with_usage(const char *msg)\n+{\n+\terror(\"%s\", msg);\n+\tusage_with_options(check_attr_usage, check_attr_options);\n+}\n+\n int cmd_check_attr(int argc, const char **argv, const char *prefix)\n {\n \tstruct git_attr_check *check;\n@@ -103,8 +109,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \telse if (stdin_paths && filei < argc)\n \t\terrstr = \"Can't specify files with --stdin\";\n \tif (errstr) {\n-\t\terror(\"%s\", errstr);\n-\t\tusage_with_options(check_attr_usage, check_attr_options);\n+\t\terror_with_usage(errstr);\n \t}\n \n \tcheck = xcalloc(cnt, sizeof(*check));\n-- \n1.7.6.8.gd2879\n"},{"id":"172867","messageId":"1312432593-9841-18-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 17/23] git-check-attr: Handle each error separately","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:27Z","receivedAt":"2011-08-04T04:36:27Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"This will make the code easier to refactor.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/check-attr.c |   11 ++++-------\n 1 files changed, 4 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex d004222..de3fef7 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -78,7 +78,6 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n {\n \tstruct git_attr_check *check;\n \tint cnt, i, doubledash, filei;\n-\tconst char *errstr = NULL;\n \n \targc = parse_options(argc, argv, prefix, check_attr_options,\n \t\t\t     check_attr_usage, PARSE_OPT_KEEP_DASHDASH);\n@@ -105,12 +104,10 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (cnt <= 0)\n-\t\terrstr = \"No attribute specified\";\n-\telse if (stdin_paths && filei < argc)\n-\t\terrstr = \"Can't specify files with --stdin\";\n-\tif (errstr) {\n-\t\terror_with_usage(errstr);\n-\t}\n+\t\terror_with_usage(\"No attribute specified\");\n+\n+\tif (stdin_paths && filei < argc)\n+\t\terror_with_usage(\"Can't specify files with --stdin\");\n \n \tcheck = xcalloc(cnt, sizeof(*check));\n \tfor (i = 0; i < cnt; i++) {\n-- \n1.7.6.8.gd2879\n"},{"id":"172868","messageId":"1312432593-9841-19-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 18/23] git-check-attr: Process command-line args more systematically","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:28Z","receivedAt":"2011-08-04T04:36:28Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/check-attr.c |   19 ++++++++++++-------\n 1 files changed, 12 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex de3fef7..e9b827f 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -81,8 +81,6 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \n \targc = parse_options(argc, argv, prefix, check_attr_options,\n \t\t\t     check_attr_usage, PARSE_OPT_KEEP_DASHDASH);\n-\tif (!argc)\n-\t\tusage_with_options(check_attr_usage, check_attr_options);\n \n \tif (read_cache() < 0) {\n \t\tdie(\"invalid cache\");\n@@ -94,8 +92,17 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \t\t\tdoubledash = i;\n \t}\n \n-\t/* If there is no double dash, we handle only one attribute */\n-\tif (doubledash < 0) {\n+\t/* Check attribute argument(s): */\n+\tif (doubledash == 0) {\n+\t\terror_with_usage(\"No attribute specified\");\n+\t} else if (doubledash < 0) {\n+\t\t/*\n+\t\t * There is no double dash; treat the first\n+\t\t * argument as an attribute.\n+\t\t */\n+\t\tif (!argc)\n+\t\t\terror_with_usage(\"No attribute specified\");\n+\n \t\tcnt = 1;\n \t\tfilei = 1;\n \t} else {\n@@ -103,9 +110,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \t\tfilei = doubledash + 1;\n \t}\n \n-\tif (cnt <= 0)\n-\t\terror_with_usage(\"No attribute specified\");\n-\n+\t/* Check file argument(s): */\n \tif (stdin_paths && filei < argc)\n \t\terror_with_usage(\"Can't specify files with --stdin\");\n \n-- \n1.7.6.8.gd2879\n"},{"id":"172871","messageId":"1312432593-9841-20-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 19/23] git-check-attr: Error out if no pathnames are specified","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:29Z","receivedAt":"2011-08-04T04:36:29Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"If no pathnames are passed as command-line arguments and the --stdin\noption is not specified, fail with the error message \"No file\nspecified\".  Add tests of this behavior.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/check-attr.c  |    9 +++++++--\n t/t0003-attributes.sh |    2 ++\n 2 files changed, 9 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex e9b827f..6cf6421 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -111,8 +111,13 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \t}\n \n \t/* Check file argument(s): */\n-\tif (stdin_paths && filei < argc)\n-\t\terror_with_usage(\"Can't specify files with --stdin\");\n+\tif (stdin_paths) {\n+\t\tif (filei < argc)\n+\t\t\terror_with_usage(\"Can't specify files with --stdin\");\n+\t} else {\n+\t\tif (filei >= argc)\n+\t\t\terror_with_usage(\"No file specified\");\n+\t}\n \n \tcheck = xcalloc(cnt, sizeof(*check));\n \tfor (i = 0; i < cnt; i++) {\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex f1debeb..2254005 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -46,6 +46,8 @@ test_expect_success 'command line checks' '\n \n \ttest_must_fail git check-attr &&\n \ttest_must_fail git check-attr -- &&\n+\ttest_must_fail git check-attr test &&\n+\ttest_must_fail git check-attr test -- &&\n \ttest_must_fail git check-attr -- f &&\n \techo \"f\" | test_must_fail git check-attr --stdin &&\n \techo \"f\" | test_must_fail git check-attr --stdin -- f &&\n-- \n1.7.6.8.gd2879\n"},{"id":"172870","messageId":"1312432593-9841-21-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 20/23] git-check-attr: Add an --all option to show all attributes","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:30Z","receivedAt":"2011-08-04T04:36:30Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"Add new usage patterns\n\n    git check-attr [-a | --all] [--] pathname...\n    git check-attr --stdin [-a | --all] < <list-of-paths>\n\nwhich display all attributes associated with the specified file(s).\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n Documentation/git-check-attr.txt |   16 ++++++++++-\n builtin/check-attr.c             |   52 ++++++++++++++++++++++++++-----------\n t/t0003-attributes.sh            |   24 +++++++++++++++++\n 3 files changed, 74 insertions(+), 18 deletions(-)\n\ndiff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt\nindex 30eca6c..798e5d5 100644\n--- a/Documentation/git-check-attr.txt\n+++ b/Documentation/git-check-attr.txt\n@@ -9,8 +9,8 @@ git-check-attr - Display gitattributes information\n SYNOPSIS\n --------\n [verse]\n-'git check-attr' attr... [--] pathname...\n-'git check-attr' --stdin [-z] attr... < <list-of-paths>\n+'git check-attr' [-a | --all | attr...] [--] pathname...\n+'git check-attr' --stdin [-z] [-a | --all | attr...] < <list-of-paths>\n \n DESCRIPTION\n -----------\n@@ -19,6 +19,11 @@ For every pathname, this command will list if each attribute is 'unspecified',\n \n OPTIONS\n -------\n+-a, --all::\n+\tList all attributes that are associated with the specified\n+\tpaths.  If this option is used, then 'unspecified' attributes\n+\twill not be included in the output.\n+\n --stdin::\n \tRead file names from stdin instead of from the command-line.\n \n@@ -69,6 +74,13 @@ org/example/MyClass.java: diff: java\n org/example/MyClass.java: myAttr: set\n ---------------\n \n+* Listing all attributes for a file:\n+---------------\n+$ git check-attr --all -- org/example/MyClass.java\n+org/example/MyClass.java: diff: java\n+org/example/MyClass.java: myAttr: set\n+---------------\n+\n * Listing an attribute for multiple files:\n ---------------\n $ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex 6cf6421..b0d2ebc 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -4,16 +4,18 @@\n #include \"quote.h\"\n #include \"parse-options.h\"\n \n+static int all_attrs;\n static int stdin_paths;\n static const char * const check_attr_usage[] = {\n-\"git check-attr attr... [--] pathname...\",\n-\"git check-attr --stdin attr... < <list-of-paths>\",\n+\"git check-attr [-a | --all | attr...] [--] pathname...\",\n+\"git check-attr --stdin [-a | --all | attr...] < <list-of-paths>\",\n NULL\n };\n \n static int null_term_line;\n \n static const struct option check_attr_options[] = {\n+\tOPT_BOOLEAN('a', \"all\", &all_attrs, \"report all attributes set on file\"),\n \tOPT_BOOLEAN(0 , \"stdin\", &stdin_paths, \"read file names from stdin\"),\n \tOPT_BOOLEAN('z', NULL, &null_term_line,\n \t\t\"input paths are terminated by a null character\"),\n@@ -42,9 +44,16 @@ static void output_attr(int cnt, struct git_attr_check *check,\n static void check_attr(int cnt, struct git_attr_check *check,\n \tconst char *file)\n {\n-\tif (git_checkattr(file, cnt, check))\n-\t\tdie(\"git_checkattr died\");\n-\toutput_attr(cnt, check, file);\n+\tif (check != NULL) {\n+\t\tif (git_checkattr(file, cnt, check))\n+\t\t\tdie(\"git_checkattr died\");\n+\t\toutput_attr(cnt, check, file);\n+\t} else {\n+\t\tif (git_all_attrs(file, &cnt, &check))\n+\t\t\tdie(\"git_all_attrs died\");\n+\t\toutput_attr(cnt, check, file);\n+\t\tfree(check);\n+\t}\n }\n \n static void check_attr_stdin_paths(int cnt, struct git_attr_check *check)\n@@ -92,8 +101,14 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \t\t\tdoubledash = i;\n \t}\n \n-\t/* Check attribute argument(s): */\n-\tif (doubledash == 0) {\n+\t/* Process --all and/or attribute arguments: */\n+\tif (all_attrs) {\n+\t\tif (doubledash >= 1)\n+\t\t\terror_with_usage(\"Attributes and --all both specified\");\n+\n+\t\tcnt = 0;\n+\t\tfilei = doubledash + 1;\n+\t} else if (doubledash == 0) {\n \t\terror_with_usage(\"No attribute specified\");\n \t} else if (doubledash < 0) {\n \t\t/*\n@@ -119,15 +134,20 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \t\t\terror_with_usage(\"No file specified\");\n \t}\n \n-\tcheck = xcalloc(cnt, sizeof(*check));\n-\tfor (i = 0; i < cnt; i++) {\n-\t\tconst char *name;\n-\t\tstruct git_attr *a;\n-\t\tname = argv[i];\n-\t\ta = git_attr(name);\n-\t\tif (!a)\n-\t\t\treturn error(\"%s: not a valid attribute name\", name);\n-\t\tcheck[i].attr = a;\n+\tif (all_attrs) {\n+\t\tcheck = NULL;\n+\t} else {\n+\t\tcheck = xcalloc(cnt, sizeof(*check));\n+\t\tfor (i = 0; i < cnt; i++) {\n+\t\t\tconst char *name;\n+\t\t\tstruct git_attr *a;\n+\t\t\tname = argv[i];\n+\t\t\ta = git_attr(name);\n+\t\t\tif (!a)\n+\t\t\t\treturn error(\"%s: not a valid attribute name\",\n+\t\t\t\t\tname);\n+\t\t\tcheck[i].attr = a;\n+\t\t}\n \t}\n \n \tif (stdin_paths)\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex 2254005..8892ba3 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -107,6 +107,30 @@ EOF\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'attribute test: --all option' '\n+\n+\tcat <<EOF > all &&\n+f: test: f\n+a/f: test: f\n+a/c/f: test: f\n+a/g: test: a/g\n+a/b/g: test: a/b/g\n+b/g: test: unspecified\n+a/b/h: test: a/b/h\n+a/b/d/g: test: a/b/d/*\n+onoff: test: unset\n+offon: test: set\n+no: notest: set\n+a/b/d/no: test: a/b/d/*\n+a/b/d/no: notest: set\n+a/b/d/yes: notest: set\n+EOF\n+\n+\tgrep -v unspecified < all | sort > expect &&\n+\tsed -e \"s/:.*//\" < all | uniq | git check-attr --stdin --all | sort > actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'root subdir attribute test' '\n \n \tattr_check a/i a/i &&\n-- \n1.7.6.8.gd2879\n"},{"id":"172869","messageId":"1312432593-9841-22-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 21/23] git-check-attr: Drive two tests using the same raw data","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:31Z","receivedAt":"2011-08-04T04:36:31Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n t/t0003-attributes.sh |   59 +++++++++++++++++++-----------------------------\n 1 files changed, 23 insertions(+), 36 deletions(-)\n\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex 8892ba3..a49f8a9 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -38,7 +38,25 @@ test_expect_success 'setup' '\n \t) >a/b/.gitattributes &&\n \t(\n \t\techo \"global test=global\"\n-\t) >\"$HOME\"/global-gitattributes\n+\t) >\"$HOME\"/global-gitattributes &&\n+\tcat <<EOF >expect-all\n+f: test: f\n+a/f: test: f\n+a/c/f: test: f\n+a/g: test: a/g\n+a/b/g: test: a/b/g\n+b/g: test: unspecified\n+a/b/h: test: a/b/h\n+a/b/d/g: test: a/b/d/*\n+onoff: test: unset\n+offon: test: set\n+no: notest: set\n+no: test: unspecified\n+a/b/d/no: notest: set\n+a/b/d/no: test: a/b/d/*\n+a/b/d/yes: notest: set\n+a/b/d/yes: test: unspecified\n+EOF\n \n '\n \n@@ -87,47 +105,16 @@ test_expect_success 'core.attributesfile' '\n \n test_expect_success 'attribute test: read paths from stdin' '\n \n-\tcat <<EOF > expect &&\n-f: test: f\n-a/f: test: f\n-a/c/f: test: f\n-a/g: test: a/g\n-a/b/g: test: a/b/g\n-b/g: test: unspecified\n-a/b/h: test: a/b/h\n-a/b/d/g: test: a/b/d/*\n-onoff: test: unset\n-offon: test: set\n-no: test: unspecified\n-a/b/d/no: test: a/b/d/*\n-a/b/d/yes: test: unspecified\n-EOF\n-\n+\tgrep -v notest < expect-all > expect &&\n \tsed -e \"s/:.*//\" < expect | git check-attr --stdin test > actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'attribute test: --all option' '\n \n-\tcat <<EOF > all &&\n-f: test: f\n-a/f: test: f\n-a/c/f: test: f\n-a/g: test: a/g\n-a/b/g: test: a/b/g\n-b/g: test: unspecified\n-a/b/h: test: a/b/h\n-a/b/d/g: test: a/b/d/*\n-onoff: test: unset\n-offon: test: set\n-no: notest: set\n-a/b/d/no: test: a/b/d/*\n-a/b/d/no: notest: set\n-a/b/d/yes: notest: set\n-EOF\n-\n-\tgrep -v unspecified < all | sort > expect &&\n-\tsed -e \"s/:.*//\" < all | uniq | git check-attr --stdin --all | sort > actual &&\n+\tgrep -v unspecified < expect-all | sort > expect &&\n+\tsed -e \"s/:.*//\" < expect-all | uniq |\n+\t\tgit check-attr --stdin --all | sort > actual &&\n \ttest_cmp expect actual\n '\n \n-- \n1.7.6.8.gd2879\n"},{"id":"172873","messageId":"1312432593-9841-23-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 22/23] git-check-attr: Fix command-line handling to match docs","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:32Z","receivedAt":"2011-08-04T04:36:32Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"According to the git-check-attr synopsis, if the '--stdin' option is\nused then no pathnames are expected on the command line.  Change the\nbehavior to match this description; namely, if '--stdin' is used but\nnot '--', then treat all command-line arguments as attribute names.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n Documentation/git-check-attr.txt |    7 +++++--\n builtin/check-attr.c             |   15 +++++++++------\n t/t0003-attributes.sh            |    1 -\n 3 files changed, 14 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt\nindex 798e5d5..1f7312a 100644\n--- a/Documentation/git-check-attr.txt\n+++ b/Documentation/git-check-attr.txt\n@@ -33,8 +33,11 @@ OPTIONS\n \n \\--::\n \tInterpret all preceding arguments as attributes and all following\n-\targuments as path names. If not supplied, only the first argument will\n-\tbe treated as an attribute.\n+\targuments as path names.\n+\n+If none of `--stdin`, `--all`, or `--` is used, the first argument\n+will be treated as an attribute and the rest of the arguments as\n+pathnames.\n \n OUTPUT\n ------\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex b0d2ebc..f20772a 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -111,15 +111,18 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \t} else if (doubledash == 0) {\n \t\terror_with_usage(\"No attribute specified\");\n \t} else if (doubledash < 0) {\n-\t\t/*\n-\t\t * There is no double dash; treat the first\n-\t\t * argument as an attribute.\n-\t\t */\n \t\tif (!argc)\n \t\t\terror_with_usage(\"No attribute specified\");\n \n-\t\tcnt = 1;\n-\t\tfilei = 1;\n+\t\tif (stdin_paths) {\n+\t\t\t/* Treat all arguments as attribute names. */\n+\t\t\tcnt = argc;\n+\t\t\tfilei = argc;\n+\t\t} else {\n+\t\t\t/* Treat exactly one argument as an attribute name. */\n+\t\t\tcnt = 1;\n+\t\t\tfilei = 1;\n+\t\t}\n \t} else {\n \t\tcnt = doubledash;\n \t\tfilei = doubledash + 1;\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex a49f8a9..5acb2d5 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -70,7 +70,6 @@ test_expect_success 'command line checks' '\n \techo \"f\" | test_must_fail git check-attr --stdin &&\n \techo \"f\" | test_must_fail git check-attr --stdin -- f &&\n \techo \"f\" | test_must_fail git check-attr --stdin test -- f &&\n-\techo \"f\" | test_must_fail git check-attr --stdin test f &&\n \ttest_must_fail git check-attr \"\" -- f\n \n '\n-- \n1.7.6.8.gd2879\n"},{"id":"172874","messageId":"1312432593-9841-24-git-send-email-mhagger@alum.mit.edu","threadId":"28017","inReplyTo":"1312432593-9841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v3 23/23] Rename git_checkattr() to git_check_attr()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-08-04T04:36:33Z","receivedAt":"2011-08-04T04:36:33Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"Suggested by: Junio Hamano <gitster@pobox.com>\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n Documentation/technical/api-gitattributes.txt |    8 ++++----\n archive.c                                     |    2 +-\n attr.c                                        |    2 +-\n attr.h                                        |    4 ++--\n builtin/check-attr.c                          |    4 ++--\n builtin/pack-objects.c                        |    2 +-\n convert.c                                     |    2 +-\n ll-merge.c                                    |    4 ++--\n userdiff.c                                    |    2 +-\n ws.c                                          |    2 +-\n 10 files changed, 16 insertions(+), 16 deletions(-)\n\ndiff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt\nindex 3bd2f57..5a1403f 100644\n--- a/Documentation/technical/api-gitattributes.txt\n+++ b/Documentation/technical/api-gitattributes.txt\n@@ -19,7 +19,7 @@ Data Structure\n `struct git_attr_check`::\n \n \tThis structure represents a set of attributes to check in a call\n-\tto `git_checkattr()` function, and receives the results.\n+\tto `git_check_attr()` function, and receives the results.\n \n \n Attribute Values\n@@ -52,7 +52,7 @@ Querying Specific Attributes\n   attributes you would want to check.  To populate this array, you would\n   need to define necessary attributes by calling `git_attr()` function.\n \n-* Call `git_checkattr()` to check the attributes for the path.\n+* Call `git_check_attr()` to check the attributes for the path.\n \n * Inspect `git_attr_check` structure to see how each of the attribute in\n   the array is defined for the path.\n@@ -78,13 +78,13 @@ static void setup_check(void)\n }\n ------------\n \n-. Call `git_checkattr()` with the prepared array of `struct git_attr_check`:\n+. Call `git_check_attr()` with the prepared array of `struct git_attr_check`:\n \n ------------\n \tconst char *path;\n \n \tsetup_check();\n-\tgit_checkattr(path, ARRAY_SIZE(check), check);\n+\tgit_check_attr(path, ARRAY_SIZE(check), check);\n ------------\n \n . Act on `.value` member of the result, left in `check[]`:\ndiff --git a/archive.c b/archive.c\nindex 2a7a28e..3fd7f47 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -123,7 +123,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,\n \tpath_without_prefix = path.buf + args->baselen;\n \n \tsetup_archive_check(check);\n-\tif (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) {\n+\tif (!git_check_attr(path_without_prefix, ARRAY_SIZE(check), check)) {\n \t\tif (ATTR_TRUE(check[0].value))\n \t\t\treturn 0;\n \t\tconvert = ATTR_TRUE(check[1].value);\ndiff --git a/attr.c b/attr.c\nindex 658112e..da29c8e 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -731,7 +731,7 @@ static void collect_all_attrs(const char *path)\n \t\trem = fill(path, pathlen, stk, rem);\n }\n \n-int git_checkattr(const char *path, int num, struct git_attr_check *check)\n+int git_check_attr(const char *path, int num, struct git_attr_check *check)\n {\n \tint i;\n \ndiff --git a/attr.h b/attr.h\nindex 9e22893..eb8ca0d 100644\n--- a/attr.h\n+++ b/attr.h\n@@ -20,7 +20,7 @@ extern const char git_attr__false[];\n #define ATTR_UNSET(v) ((v) == NULL)\n \n /*\n- * Send one or more git_attr_check to git_checkattr(), and\n+ * Send one or more git_attr_check to git_check_attr(), and\n  * each 'value' member tells what its value is.\n  * Unset one is returned as NULL.\n  */\n@@ -36,7 +36,7 @@ struct git_attr_check {\n  */\n char *git_attr_name(struct git_attr *);\n \n-int git_checkattr(const char *path, int, struct git_attr_check *);\n+int git_check_attr(const char *path, int, struct git_attr_check *);\n \n /*\n  * Retrieve all attributes that apply to the specified path.  *num\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex f20772a..6b16368 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -45,8 +45,8 @@ static void check_attr(int cnt, struct git_attr_check *check,\n \tconst char *file)\n {\n \tif (check != NULL) {\n-\t\tif (git_checkattr(file, cnt, check))\n-\t\t\tdie(\"git_checkattr died\");\n+\t\tif (git_check_attr(file, cnt, check))\n+\t\t\tdie(\"git_check_attr died\");\n \t\toutput_attr(cnt, check, file);\n \t} else {\n \t\tif (git_all_attrs(file, &cnt, &check))\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 84e6daf..ac8bed8 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -634,7 +634,7 @@ static int no_try_delta(const char *path)\n \tstruct git_attr_check check[1];\n \n \tsetup_delta_attr_check(check);\n-\tif (git_checkattr(path, ARRAY_SIZE(check), check))\n+\tif (git_check_attr(path, ARRAY_SIZE(check), check))\n \t\treturn 0;\n \tif (ATTR_FALSE(check->value))\n \t\treturn 1;\ndiff --git a/convert.c b/convert.c\nindex 85939c2..416bf83 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -727,7 +727,7 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)\n \t\tgit_config(read_convert_config, NULL);\n \t}\n \n-\tif (!git_checkattr(path, NUM_CONV_ATTRS, ccheck)) {\n+\tif (!git_check_attr(path, NUM_CONV_ATTRS, ccheck)) {\n \t\tca->crlf_action = git_path_check_crlf(path, ccheck + 4);\n \t\tif (ca->crlf_action == CRLF_GUESS)\n \t\t\tca->crlf_action = git_path_check_crlf(path, ccheck + 0);\ndiff --git a/ll-merge.c b/ll-merge.c\nindex 6ce512e..da59738 100644\n--- a/ll-merge.c\n+++ b/ll-merge.c\n@@ -330,7 +330,7 @@ static int git_path_check_merge(const char *path, struct git_attr_check check[2]\n \t\tcheck[0].attr = git_attr(\"merge\");\n \t\tcheck[1].attr = git_attr(\"conflict-marker-size\");\n \t}\n-\treturn git_checkattr(path, 2, check);\n+\treturn git_check_attr(path, 2, check);\n }\n \n static void normalize_file(mmfile_t *mm, const char *path)\n@@ -387,7 +387,7 @@ int ll_merge_marker_size(const char *path)\n \n \tif (!check.attr)\n \t\tcheck.attr = git_attr(\"conflict-marker-size\");\n-\tif (!git_checkattr(path, 1, &check) && check.value) {\n+\tif (!git_check_attr(path, 1, &check) && check.value) {\n \t\tmarker_size = atoi(check.value);\n \t\tif (marker_size <= 0)\n \t\t\tmarker_size = DEFAULT_CONFLICT_MARKER_SIZE;\ndiff --git a/userdiff.c b/userdiff.c\nindex 01d3a8b..bf553ad 100644\n--- a/userdiff.c\n+++ b/userdiff.c\n@@ -270,7 +270,7 @@ struct userdiff_driver *userdiff_find_by_path(const char *path)\n \n \tif (!path)\n \t\treturn NULL;\n-\tif (git_checkattr(path, 1, &check))\n+\tif (git_check_attr(path, 1, &check))\n \t\treturn NULL;\n \n \tif (ATTR_TRUE(check.value))\ndiff --git a/ws.c b/ws.c\nindex 9fb9b14..b498d75 100644\n--- a/ws.c\n+++ b/ws.c\n@@ -88,7 +88,7 @@ unsigned whitespace_rule(const char *pathname)\n \tstruct git_attr_check attr_whitespace_rule;\n \n \tsetup_whitespace_attr_check(&attr_whitespace_rule);\n-\tif (!git_checkattr(pathname, 1, &attr_whitespace_rule)) {\n+\tif (!git_check_attr(pathname, 1, &attr_whitespace_rule)) {\n \t\tconst char *value;\n \n \t\tvalue = attr_whitespace_rule.value;\n-- \n1.7.6.8.gd2879\n"}]}