{"thread":{"id":"27928","subject":"[PATCH 07/19] Provide access to the name attribute of git_attr","startedAt":"2011-07-26T14:12:43Z","lastAt":"2011-07-28T04:31:07Z","messageCount":24,"participants":["Michael Haggerty","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":19},"messages":[{"id":"172066","messageId":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":null,"subject":"[PATCH 00/19] Add --all option to git-check-attr","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:43Z","receivedAt":"2011-07-26T14:12:43Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"Currently it is possible to inquire the values of particular\nattributes on particular files, using either the API function\ngit_checkattr() or the command \"git check-attr\".  But it is not\npossible to ask for *all* attributes that are associated with a\nparticular file.  This patch series adds that functionality:\n\n* A new API call git_allattr()\n\n* A new option \"git check-attr --all -- pathnames\"\n\nAlong the way, several small cleanups are made in the general\nneighborhood, including:\n\n* Disallow the empty string as an attribute name\n\n* Provide access to the name attribute of git_attr\n\n* Fail with an error message if no pathnames are provided on the\n  command line (and --stdin is not used)\n\n* If --stdin is used, interpret all command-line arguments as\n  attribute names\n\n* Rename struct git_attr_check to git_attr_value\n\nMost of the patches are hopefully self-explanatory; see the individual\npatch emails for discussion of changes that might potentially be\ncontroversial.\n\nMichael Haggerty (19):\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  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 struct git_attr_check to git_attr_value\n\n Documentation/git-check-attr.txt              |   23 ++++-\n Documentation/gitattributes.txt               |    3 +\n Documentation/technical/api-gitattributes.txt |   66 +++++++++-----\n archive.c                                     |    4 +-\n attr.c                                        |   61 +++++++++++--\n attr.h                                        |   24 ++++-\n builtin/check-attr.c                          |  123 ++++++++++++++++--------\n builtin/pack-objects.c                        |    4 +-\n convert.c                                     |   10 +-\n ll-merge.c                                    |    6 +-\n t/t0003-attributes.sh                         |   61 +++++++++----\n userdiff.c                                    |    2 +-\n ws.c                                          |    4 +-\n 13 files changed, 278 insertions(+), 113 deletions(-)\n\n-- \n1.7.6.8.gd2879\n"},{"id":"172065","messageId":"1311689582-3116-2-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 01/19] doc: Add a link from gitattributes(5) to git-check-attr(1)","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:44Z","receivedAt":"2011-07-26T14:12:44Z","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 412c55b..3d86434 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -952,6 +952,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":"172068","messageId":"1311689582-3116-3-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 02/19] doc: Correct git_attr() calls in example code","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:45Z","receivedAt":"2011-07-26T14:12:45Z","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":"172067","messageId":"1311689582-3116-4-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 03/19] Remove anachronism from comment","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:46Z","receivedAt":"2011-07-26T14:12:46Z","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":"172069","messageId":"1311689582-3116-5-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 04/19] Disallow the empty string as an attribute name","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:47Z","receivedAt":"2011-07-26T14:12:47Z","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\nCurrently it is possible to use the empty string as an attribute name.\nFor example, a .gitattributes file can have a line\n\n    file.txt =foo\n\nand git-check-attr can be invoked as\n\n    git check-attr '' -- file.txt\n\nIndeed, the above command invocation would report that attribute ''\nhas value 'foo' (though the output looks weird).\n\nI believe this behavior to be a bug, so this patch prohibits the empty\nstring as an attribute name.  Any attempt to use the empty string as\nan attribute name will now trigger the error message \"error: : not a\nvalid attribute name\"\n\nPlease note that it is conceivable that there are existing\nrepositories with .gitattributes files that set empty attributes.  If\nso, any attempt to read *any* attributes from a file in an affected\ndirectory will fail with the above error message.\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":"172064","messageId":"1311689582-3116-6-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 05/19] git-check-attr: Add missing \"&&\"","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:48Z","receivedAt":"2011-07-26T14:12:48Z","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":"172070","messageId":"1311689582-3116-7-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 06/19] git-check-attr: Add tests of command-line parsing","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:49Z","receivedAt":"2011-07-26T14:12:49Z","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":"172063","messageId":"1311689582-3116-8-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 07/19] Provide access to the name attribute of git_attr","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:50Z","receivedAt":"2011-07-26T14:12:50Z","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\nstruct git_attr is an opaque structure containing, among other things,\nthe name of the attribute that it represents.  This patch adds a\nfunction git_attr_name(struct git_attr *) that allows the name to be\nread from the structure.  This functionality will be convenient for\nlater patches.\n\nThis seems harmless to me.  It is hardly conceivable that the\nimplementation will change so dramatically that it becomes impossible\nto derive the attribute name from the git_attr.\n\nPlease check that the name that I chose for this function conforms to\ngit conventions.\n\n Documentation/technical/api-gitattributes.txt |    3 ++-\n attr.c                                        |    4 ++++\n attr.h                                        |    7 +++++++\n 3 files changed, 13 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..a261550 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -36,6 +36,10 @@ 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+\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":"172071","messageId":"1311689582-3116-9-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 08/19] git-check-attr: Use git_attr_name()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:51Z","receivedAt":"2011-07-26T14:12:51Z","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":"172072","messageId":"1311689582-3116-10-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 09/19] Allow querying all attributes on a file","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:52Z","receivedAt":"2011-07-26T14:12:52Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"Add a function, git_allattrs(), that reports on all attributes that\nare set on a path.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n\nPlease check that the function name conforms to git conventions.\n\n Documentation/technical/api-gitattributes.txt |   45 +++++++++++++++++-------\n attr.c                                        |   43 +++++++++++++++++++++++\n attr.h                                        |    9 +++++\n 3 files changed, 84 insertions(+), 13 deletions(-)\n\ndiff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt\nindex ab3a84d..640240e 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,23 @@ static void setup_check(void)\n \t}\n ------------\n \n+\n+Querying All Attributes\n+-----------------------\n+\n+To get the values of all attributes associated with a file:\n+\n+* Call `git_allattrs()`, 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+\n (JC)\ndiff --git a/attr.c b/attr.c\nindex a261550..976c830 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -736,6 +736,49 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)\n \treturn 0;\n }\n \n+int git_allattrs(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, count, j;\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+\trem = attr_nr;\n+\tfor (stk = attr_stack; 0 < rem && stk; stk = stk->prev)\n+\t\trem = fill(path, pathlen, stk, rem);\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_all_attr) * 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..83202f0 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_allattrs(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":"172073","messageId":"1311689582-3116-11-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 10/19] git-check-attr: Extract a function output_attr()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:53Z","receivedAt":"2011-07-26T14:12:53Z","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":"172074","messageId":"1311689582-3116-12-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 11/19] git-check-attr: Introduce a new variable","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:54Z","receivedAt":"2011-07-26T14:12:54Z","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":"172075","messageId":"1311689582-3116-13-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 12/19] git-check-attr: Extract a function error_with_usage()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:55Z","receivedAt":"2011-07-26T14:12:55Z","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":"172076","messageId":"1311689582-3116-14-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 13/19] git-check-attr: Handle each error separately","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:56Z","receivedAt":"2011-07-26T14:12:56Z","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":"172077","messageId":"1311689582-3116-15-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 14/19] git-check-attr: Process command-line args more systematically","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:57Z","receivedAt":"2011-07-26T14:12:57Z","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":"172080","messageId":"1311689582-3116-16-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 15/19] git-check-attr: Error out if no pathnames are specified","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:58Z","receivedAt":"2011-07-26T14:12:58Z","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\nThe documentation seems to require at least one pathname, and other\ngit commands seem to insist on pathname lists not being empty.  Add a\nsimilar test to git-check-attr.  If it is considered likely that\npeople depend on the current behavior, I have no problem with skipping\nthis patch.\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":"172082","messageId":"1311689582-3116-17-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 16/19] git-check-attr: Add an --all option to show all attributes","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:12:59Z","receivedAt":"2011-07-26T14:12:59Z","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 --all [--] pathname...\n    git check-attr --stdin --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\nOne non-obvious design choice is that if --all is specified but not\n'--', then all of the arguments are interpreted as pathnames.\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..3afa9b1 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' [--all | attr...] [--] pathname...\n+'git check-attr' --stdin [-z] [--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+--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..ecf420f 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 [--all | attr...] [--] pathname...\",\n+\"git check-attr --stdin [--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_allattrs(file, &cnt, &check))\n+\t\t\tdie(\"git_allattrs 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":"172078","messageId":"1311689582-3116-18-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 17/19] git-check-attr: Drive two tests using the same raw data","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:13:00Z","receivedAt":"2011-07-26T14:13:00Z","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":"172081","messageId":"1311689582-3116-19-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 18/19] git-check-attr: Fix command-line handling to match docs","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:13:01Z","receivedAt":"2011-07-26T14:13:01Z","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\nPreviously, such invocations either had exactly one argument (and\nfunctioned the same as with this patch), or they failed with the\nmessage \"Can't specify files with --stdin\".\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 3afa9b1..902d5ca 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 ecf420f..29613d4 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":"172079","messageId":"1311689582-3116-20-git-send-email-mhagger@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 19/19] Rename struct git_attr_check to git_attr_value","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-26T14:13:02Z","receivedAt":"2011-07-26T14:13:02Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"This described its purpose better, especially when used with\ngit_allattrs().\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n\nThis change makes the name of the structure more closely match its\nuses.  However, if git makes backwards-compatibility guarantees for\nits API, such a renaming might be prohibited.  If so, this patch can\nbe left off the series.\n\n Documentation/technical/api-gitattributes.txt |   20 ++++++++++----------\n archive.c                                     |    4 ++--\n attr.c                                        |    8 ++++----\n attr.h                                        |   12 ++++++------\n builtin/check-attr.c                          |    8 ++++----\n builtin/pack-objects.c                        |    4 ++--\n convert.c                                     |   10 +++++-----\n ll-merge.c                                    |    6 +++---\n userdiff.c                                    |    2 +-\n ws.c                                          |    4 ++--\n 10 files changed, 39 insertions(+), 39 deletions(-)\n\ndiff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt\nindex 640240e..c64969d 100644\n--- a/Documentation/technical/api-gitattributes.txt\n+++ b/Documentation/technical/api-gitattributes.txt\n@@ -16,7 +16,7 @@ Data Structure\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+`struct git_attr_value`::\n \n \tThis structure represents a set of attributes to check in a call\n \tto `git_checkattr()` function, and receives the results.\n@@ -27,7 +27,7 @@ Attribute Values\n \n An attribute for a path can be in one of four states: Set, Unset,\n Unspecified or set to a string, and `.value` member of `struct\n-git_attr_check` records it.  There are three macros to check these:\n+git_attr_value` records it.  There are three macros to check these:\n \n `ATTR_TRUE()`::\n \n@@ -48,13 +48,13 @@ value of the attribute for the path.\n Querying Specific Attributes\n ----------------------------\n \n-* Prepare an array of `struct git_attr_check` to define the list of\n+* Prepare an array of `struct git_attr_value` 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+* Inspect `git_attr_value` structure to see how each of the attribute in\n   the array is defined for the path.\n \n \n@@ -63,12 +63,12 @@ Example\n \n To see how attributes \"crlf\" and \"indent\" are set for different paths.\n \n-. Prepare an array of `struct git_attr_check` with two elements (because\n+. Prepare an array of `struct git_attr_value` with two elements (because\n   we are checking two attributes).  Initialize their `attr` member with\n   pointers to `struct git_attr` obtained by calling `git_attr()`:\n \n ------------\n-static struct git_attr_check check[2];\n+static struct git_attr_value check[2];\n static void setup_check(void)\n {\n \tif (check[0].attr)\n@@ -78,7 +78,7 @@ static void setup_check(void)\n }\n ------------\n \n-. Call `git_checkattr()` with the prepared array of `struct git_attr_check`:\n+. Call `git_checkattr()` with the prepared array of `struct git_attr_value`:\n \n ------------\n \tconst char *path;\n@@ -115,12 +115,12 @@ Querying All Attributes\n \n To get the values of all attributes associated with a file:\n \n-* Call `git_allattrs()`, which returns an array of `git_attr_check`\n+* Call `git_allattrs()`, which returns an array of `git_attr_value`\n   structures.\n \n-* Iterate over the `git_attr_check` array to examine the attribute\n+* Iterate over the `git_attr_value` 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_value` 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.)\ndiff --git a/archive.c b/archive.c\nindex 2a7a28e..9a180b6 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -81,7 +81,7 @@ static void *sha1_file_to_archive(const char *path, const unsigned char *sha1,\n \treturn buffer;\n }\n \n-static void setup_archive_check(struct git_attr_check *check)\n+static void setup_archive_check(struct git_attr_value *check)\n {\n \tstatic struct git_attr *attr_export_ignore;\n \tstatic struct git_attr *attr_export_subst;\n@@ -107,7 +107,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,\n \tstruct archiver_context *c = context;\n \tstruct archiver_args *args = c->args;\n \twrite_archive_entry_fn_t write_entry = c->write_entry;\n-\tstruct git_attr_check check[2];\n+\tstruct git_attr_value check[2];\n \tconst char *path_without_prefix;\n \tint convert = 0;\n \tint err;\ndiff --git a/attr.c b/attr.c\nindex 976c830..ec50ba5 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -33,7 +33,7 @@ struct git_attr {\n };\n static int attr_nr;\n \n-static struct git_attr_check *check_all_attr;\n+static struct git_attr_value *check_all_attr;\n static struct git_attr *(git_attr_hash[HASHSIZE]);\n \n char *git_attr_name(struct git_attr *attr) {\n@@ -645,7 +645,7 @@ static int macroexpand_one(int attr_nr, int rem);\n \n static int fill_one(const char *what, struct match_attr *a, int rem)\n {\n-\tstruct git_attr_check *check = check_all_attr;\n+\tstruct git_attr_value *check = check_all_attr;\n \tint i;\n \n \tfor (i = a->num_attr - 1; 0 < rem && 0 <= i; i--) {\n@@ -705,7 +705,7 @@ 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+int git_checkattr(const char *path, int num, struct git_attr_value *check)\n {\n \tstruct attr_stack *stk;\n \tconst char *cp;\n@@ -736,7 +736,7 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)\n \treturn 0;\n }\n \n-int git_allattrs(const char *path, int *num, struct git_attr_check **check)\n+int git_allattrs(const char *path, int *num, struct git_attr_value **check)\n {\n \tstruct attr_stack *stk;\n \tconst char *cp;\ndiff --git a/attr.h b/attr.h\nindex 83202f0..4dc4db0 100644\n--- a/attr.h\n+++ b/attr.h\n@@ -14,17 +14,17 @@ struct git_attr *git_attr(const char *);\n extern const char git_attr__true[];\n extern const char git_attr__false[];\n \n-/* For public to check git_attr_check results */\n+/* For public to check git_attr_value results */\n #define ATTR_TRUE(v) ((v) == git_attr__true)\n #define ATTR_FALSE(v) ((v) == 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_value to git_checkattr(), and\n  * each 'value' member tells what its value is.\n  * Unset one is returned as NULL.\n  */\n-struct git_attr_check {\n+struct git_attr_value {\n \tstruct git_attr *attr;\n \tconst char *value;\n };\n@@ -36,16 +36,16 @@ 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_checkattr(const char *path, int, struct git_attr_value *);\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+ * be set to point at a newly-allocated array of git_attr_value\n  * objects describing the attributes and their values.  *check must be\n  * free()ed by the caller.\n  */\n-int git_allattrs(const char *path, int *num, struct git_attr_check **check);\n+int git_allattrs(const char *path, int *num, struct git_attr_value **check);\n \n enum git_attr_direction {\n \tGIT_ATTR_CHECKIN,\ndiff --git a/builtin/check-attr.c b/builtin/check-attr.c\nindex 29613d4..cd00496 100644\n--- a/builtin/check-attr.c\n+++ b/builtin/check-attr.c\n@@ -22,7 +22,7 @@ static const struct option check_attr_options[] = {\n \tOPT_END()\n };\n \n-static void output_attr(int cnt, struct git_attr_check *check,\n+static void output_attr(int cnt, struct git_attr_value *check,\n \tconst char *file)\n {\n \tint j;\n@@ -41,7 +41,7 @@ static void output_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+static void check_attr(int cnt, struct git_attr_value *check,\n \tconst char *file)\n {\n \tif (check != NULL) {\n@@ -56,7 +56,7 @@ static void check_attr(int cnt, struct git_attr_check *check,\n \t}\n }\n \n-static void check_attr_stdin_paths(int cnt, struct git_attr_check *check)\n+static void check_attr_stdin_paths(int cnt, struct git_attr_value *check)\n {\n \tstruct strbuf buf, nbuf;\n \tint line_termination = null_term_line ? 0 : '\\n';\n@@ -85,7 +85,7 @@ static NORETURN void error_with_usage(const char *msg)\n \n int cmd_check_attr(int argc, const char **argv, const char *prefix)\n {\n-\tstruct git_attr_check *check;\n+\tstruct git_attr_value *check;\n \tint cnt, i, doubledash, filei;\n \n \targc = parse_options(argc, argv, prefix, check_attr_options,\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 84e6daf..a0becea 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -619,7 +619,7 @@ static unsigned name_hash(const char *name)\n \treturn hash;\n }\n \n-static void setup_delta_attr_check(struct git_attr_check *check)\n+static void setup_delta_attr_check(struct git_attr_value *check)\n {\n \tstatic struct git_attr *attr_delta;\n \n@@ -631,7 +631,7 @@ static void setup_delta_attr_check(struct git_attr_check *check)\n \n static int no_try_delta(const char *path)\n {\n-\tstruct git_attr_check check[1];\n+\tstruct git_attr_value check[1];\n \n \tsetup_delta_attr_check(check);\n \tif (git_checkattr(path, ARRAY_SIZE(check), check))\ndiff --git a/convert.c b/convert.c\nindex 85939c2..ab582f8 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -641,7 +641,7 @@ static int ident_to_worktree(const char *path, const char *src, size_t len,\n \treturn 1;\n }\n \n-static int git_path_check_crlf(const char *path, struct git_attr_check *check)\n+static int git_path_check_crlf(const char *path, struct git_attr_value *check)\n {\n \tconst char *value = check->value;\n \n@@ -658,7 +658,7 @@ static int git_path_check_crlf(const char *path, struct git_attr_check *check)\n \treturn CRLF_GUESS;\n }\n \n-static int git_path_check_eol(const char *path, struct git_attr_check *check)\n+static int git_path_check_eol(const char *path, struct git_attr_value *check)\n {\n \tconst char *value = check->value;\n \n@@ -672,7 +672,7 @@ static int git_path_check_eol(const char *path, struct git_attr_check *check)\n }\n \n static struct convert_driver *git_path_check_convert(const char *path,\n-\t\t\t\t\t     struct git_attr_check *check)\n+\t\t\t\t\t     struct git_attr_value *check)\n {\n \tconst char *value = check->value;\n \tstruct convert_driver *drv;\n@@ -685,7 +685,7 @@ static struct convert_driver *git_path_check_convert(const char *path,\n \treturn NULL;\n }\n \n-static int git_path_check_ident(const char *path, struct git_attr_check *check)\n+static int git_path_check_ident(const char *path, struct git_attr_value *check)\n {\n \tconst char *value = check->value;\n \n@@ -718,7 +718,7 @@ static const char *conv_attr_name[] = {\n static void convert_attrs(struct conv_attrs *ca, const char *path)\n {\n \tint i;\n-\tstatic struct git_attr_check ccheck[NUM_CONV_ATTRS];\n+\tstatic struct git_attr_value ccheck[NUM_CONV_ATTRS];\n \n \tif (!ccheck[0].attr) {\n \t\tfor (i = 0; i < NUM_CONV_ATTRS; i++)\ndiff --git a/ll-merge.c b/ll-merge.c\nindex 6ce512e..65f326e 100644\n--- a/ll-merge.c\n+++ b/ll-merge.c\n@@ -324,7 +324,7 @@ static const struct ll_merge_driver *find_ll_merge_driver(const char *merge_attr\n \treturn &ll_merge_drv[LL_TEXT_MERGE];\n }\n \n-static int git_path_check_merge(const char *path, struct git_attr_check check[2])\n+static int git_path_check_merge(const char *path, struct git_attr_value check[2])\n {\n \tif (!check[0].attr) {\n \t\tcheck[0].attr = git_attr(\"merge\");\n@@ -350,7 +350,7 @@ int ll_merge(mmbuffer_t *result_buf,\n \t     mmfile_t *theirs, const char *their_label,\n \t     const struct ll_merge_options *opts)\n {\n-\tstatic struct git_attr_check check[2];\n+\tstatic struct git_attr_value check[2];\n \tstatic const struct ll_merge_options default_opts;\n \tconst char *ll_driver_name = NULL;\n \tint marker_size = DEFAULT_CONFLICT_MARKER_SIZE;\n@@ -382,7 +382,7 @@ int ll_merge(mmbuffer_t *result_buf,\n \n int ll_merge_marker_size(const char *path)\n {\n-\tstatic struct git_attr_check check;\n+\tstatic struct git_attr_value check;\n \tint marker_size = DEFAULT_CONFLICT_MARKER_SIZE;\n \n \tif (!check.attr)\ndiff --git a/userdiff.c b/userdiff.c\nindex 01d3a8b..cde9537 100644\n--- a/userdiff.c\n+++ b/userdiff.c\n@@ -262,7 +262,7 @@ struct userdiff_driver *userdiff_find_by_name(const char *name) {\n struct userdiff_driver *userdiff_find_by_path(const char *path)\n {\n \tstatic struct git_attr *attr;\n-\tstruct git_attr_check check;\n+\tstruct git_attr_value check;\n \n \tif (!attr)\n \t\tattr = git_attr(\"diff\");\ndiff --git a/ws.c b/ws.c\nindex 9fb9b14..4a76ef8 100644\n--- a/ws.c\n+++ b/ws.c\n@@ -74,7 +74,7 @@ unsigned parse_whitespace_rule(const char *string)\n \treturn rule;\n }\n \n-static void setup_whitespace_attr_check(struct git_attr_check *check)\n+static void setup_whitespace_attr_check(struct git_attr_value *check)\n {\n \tstatic struct git_attr *attr_whitespace;\n \n@@ -85,7 +85,7 @@ static void setup_whitespace_attr_check(struct git_attr_check *check)\n \n unsigned whitespace_rule(const char *pathname)\n {\n-\tstruct git_attr_check attr_whitespace_rule;\n+\tstruct git_attr_value attr_whitespace_rule;\n \n \tsetup_whitespace_attr_check(&attr_whitespace_rule);\n \tif (!git_checkattr(pathname, 1, &attr_whitespace_rule)) {\n-- \n1.7.6.8.gd2879\n"},{"id":"172190","messageId":"7vr55bo47e.fsf@alter.siamese.dyndns.org","threadId":"27928","inReplyTo":"1311689582-3116-8-git-send-email-mhagger@alum.mit.edu","subject":"Re: [PATCH 07/19] Provide access to the name attribute of git_attr","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-07-27T20:02:38Z","receivedAt":"2011-07-27T20:02:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael Haggerty <mhagger@alum.mit.edu> writes:\n\n> It will be present in any likely future reimplementation, and its\n> availability simplifies other code.\n\nLooks good to me except for minor nits.\n\n> struct git_attr is an opaque structure containing, among other things,\n> the name of the attribute that it represents.  This patch adds a\n> function git_attr_name(struct git_attr *) that allows the name to be\n> read from the structure.  This functionality will be convenient for\n> later patches.\n>\n> This seems harmless to me.  It is hardly conceivable that the\n> implementation will change so dramatically that it becomes impossible\n> to derive the attribute name from the git_attr.\n\nThe original design of attribute API wanted to make sure that the callers\ndo not have to care what _other_ attributes are on the path, and defined\nonly \"if you have a specific name, you can ask if that is set\". Of course\nonce you start wanting to enumerate the attributes without knowing what\nattributes may exist in the world, you would need an API to grab all the\nattributes and then find out the name of each of them. So I think this is\nnot just harmless but is necessary.\n\n> diff --git a/attr.c b/attr.c\n> ...\n> +char *git_attr_name(struct git_attr *attr) {\n> +\treturn attr->name;\n> +}\n\n(Style)\n\n\tchar *git_attr_name(struct git_attr *attr)\n\t{\n\t\treturn attr->name;\n\t}\n\n> diff --git a/attr.h b/attr.h\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\nshould not be modified NOR freed?\n"},{"id":"172189","messageId":"7vlivjo479.fsf@alter.siamese.dyndns.org","threadId":"27928","inReplyTo":"1311689582-3116-5-git-send-email-mhagger@alum.mit.edu","subject":"Re: [PATCH 04/19] Disallow the empty string as an attribute name","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-07-27T20:20:36Z","receivedAt":"2011-07-27T20:20:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael Haggerty <mhagger@alum.mit.edu> writes:\n\n> 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\nGood. Very much appreciated.\n\n> Currently it is possible to use the empty string as an attribute name.\n\nYeah, even I wouldn't call it a regression to disallow this ;-).\n"},{"id":"172198","messageId":"4E30E52C.9060407@alum.mit.edu","threadId":"27928","inReplyTo":"7vr55bo47e.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 07/19] Provide access to the name attribute of git_attr","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-28T04:27:24Z","receivedAt":"2011-07-28T04:27:24Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 07/27/2011 10:02 PM, Junio C Hamano wrote:\n> Michael Haggerty <mhagger@alum.mit.edu> writes:\n>> diff --git a/attr.c b/attr.c\n>> ...\n>> +char *git_attr_name(struct git_attr *attr) {\n>> +\treturn attr->name;\n>> +}\n> \n> (Style)\n> \n> \tchar *git_attr_name(struct git_attr *attr)\n> \t{\n> \t\treturn attr->name;\n> \t}\n\nThanks.  I will include this in the next version of the patch series.\n\n>> diff --git a/attr.h b/attr.h\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> \n> should not be modified NOR freed?\n\nNo, usually \"nor\" is only used with \"neither\".  I'm confident that the\nwording that I used is correct [1].  Alternatively, one could write\n\"should be neither modified nor freed\".\n\nMichael\n\n[1] See, e.g., http://grammar.quickanddirtytips.com/when-to-use-nor.aspx\nsection \"When to Use “Or” Instead of “Nor”\".\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"172199","messageId":"4E30E60B.1060604@alum.mit.edu","threadId":"27928","inReplyTo":"1311689582-3116-17-git-send-email-mhagger@alum.mit.edu","subject":"Re: [PATCH 16/19] git-check-attr: Add an --all option to show all attributes","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-07-28T04:31:07Z","receivedAt":"2011-07-28T04:31:07Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 07/26/2011 04:12 PM, Michael Haggerty wrote:\n> Add new usage patterns\n> \n>     git check-attr --all [--] pathname...\n>     git check-attr --stdin --all < <list-of-paths>\n> \n> which display all attributes associated with the specified file(s).\n\nI realized that I also added the synonym \"-a\" but forgot to mention it\nin the docs or commit message.  I will fix this in the next version of\nthe patch series.\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"}]}