{"thread":{"id":"16035","subject":"[PATCH/RFC] Introduce a built-in attribute \"text\"","startedAt":"2008-10-24T13:55:47Z","lastAt":"2008-10-25T06:51:06Z","messageCount":2,"participants":["Michael J Gruber","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"93855","messageId":"1224856547-30533-1-git-send-email-git@drmicha.warpmail.net","threadId":"16035","inReplyTo":null,"subject":"[PATCH/RFC] Introduce a built-in attribute \"text\"","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2008-10-24T13:55:47Z","receivedAt":"2008-10-24T13:55:47Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"\"text is the opposite of \"binary\": It sets the attributes \"crlf\" and\n\"diff\". It is needed because attribute macros can't be negated,\nand some users may want to force git into treating certain files as\ntext which are not recognized by the internal logic.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\nThis gives the user the chance to mess up completely (given an\n\"appropriate\" setting of autocrlf), but I still think it's a good idea\nto have that \"-binary\" built-in. attributes aren't used by noobs anyways.\nIn many cases, \"diff\" might be preferred over \"text\". Should I add a warning\nto the doc?\n\nMichael\n\n Documentation/gitattributes.txt |    4 +++-\n attr.c                          |    1 +\n 2 files changed, 4 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\nindex 2694559..2a00f8c 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -510,7 +510,9 @@ the same time.  The system knows a built-in attribute macro, `binary`:\n which is equivalent to the above.  Note that the attribute macros can only\n be \"Set\" (see the above example that sets \"binary\" macro as if it were an\n ordinary attribute --- setting it in turn unsets \"crlf\" and \"diff\").\n-\n+Therefore, there is also a built-in attribute macro `text` which allows\n+you to mark certain files as text which git does not recognize automatically.\n+It is equivalent to setting `crlf diff`.\n \n DEFINING ATTRIBUTE MACROS\n -------------------------\ndiff --git a/attr.c b/attr.c\nindex 17f6a4d..63e2837 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -283,6 +283,7 @@ static void free_attr_elem(struct attr_stack *e)\n \n static const char *builtin_attr[] = {\n \t\"[attr]binary -diff -crlf\",\n+\t\"[attr]text diff crlf\",\n \tNULL,\n };\n \n-- \n1.6.0.3.514.g2f91b\n"},{"id":"93912","messageId":"7vwsfx9nhh.fsf@gitster.siamese.dyndns.org","threadId":"16035","inReplyTo":"1224856547-30533-1-git-send-email-git@drmicha.warpmail.net","subject":"Re* [PATCH/RFC] Introduce a built-in attribute \"text\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-10-25T06:51:06Z","receivedAt":"2008-10-25T06:51:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> \"text is the opposite of \"binary\": It sets the attributes \"crlf\" and\n> \"diff\". It is needed because attribute macros can't be negated,\n\nIf the reason for this patch is really (and only) because macros cannot be\nnegated, perhaps we should be allowing to negate them?  That is, given:\n\n\t[attr] binary = -diff -crlf\n        *.bar !binary\n\nyou would set diff and crlf to TRUE for b.bar, because the normal action\nis to set them to FALSE.\n\nIf the original attribute macro expands to anything but setting other\nattributes to TRUE or FALSE (i.e. to a string value, or reseting to\nUNSPECIFIED), or if a related attribute is not the exact opposite, you\ncannot simply negate, but need to introduce a new attribute like your\npatch does.  For example, it is conceivable you might instead want to\ndefine:\n\n\t[attr] text = diff\n\ni.e. without \"crlf\" bit.\n\nSince what you want to do here is merely to negate what is already there,\nit might make more sense to simply bite the bullet and give the attribute\nmechanism the ability to negate an attribute macro.\n\nThis is of course untested (you can tell that by noticing that it does not\ncome with patch to the test scripts) nor undocumented, but it looks\nobvious enough ;-).  Originally we silently ignored attempts to negate or\nto reset an attribute macro.  We now allow you to negate an attribute\nmacro, and the definition of \"negating\" is:\n\n - negation of setting to TRUE is setting to FALSE.\n - negation of setting to FALSE is setting to TRUE.\n - negation of anything else is itself.\n\nThe third one is arbitrary and people may want to come up with a different\nbehaviour (with solid argument explaining why that behaviour is more\nsensible).\n\n attr.c |   34 +++++++++++++++++++++++++++++-----\n 1 files changed, 29 insertions(+), 5 deletions(-)\n\ndiff --git c/attr.c w/attr.c\nindex 17f6a4d..0021cec 100644\n--- c/attr.c\n+++ w/attr.c\n@@ -558,7 +558,24 @@ static int path_matches(const char *pathname, int pathlen,\n \treturn fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0;\n }\n \n-static int fill_one(const char *what, struct match_attr *a, int rem)\n+static const char *attr_negate(const char *value)\n+{\n+\tif (value == ATTR__TRUE)\n+\t\treturn ATTR__FALSE;\n+\telse if (value == ATTR__FALSE)\n+\t\treturn ATTR__TRUE;\n+\telse\n+\t\t/*\n+\t\t * NEEDSWORK: here we define negation of setting\n+\t\t * to anything but TRUE and FALSE is itself.  We\n+\t\t * may want to instead say it is not touching the\n+\t\t * attribute, in which case you could simply return\n+\t\t * NULL from here.\n+\t\t */\n+\t\treturn value;\n+}\n+\n+static int fill_one(const char *what, struct match_attr *a, int rem, int negated)\n {\n \tstruct git_attr_check *check = check_all_attr;\n \tint i;\n@@ -569,6 +586,11 @@ static int fill_one(const char *what, struct match_attr *a, int rem)\n \t\tconst char *v = a->state[i].setto;\n \n \t\tif (*n == ATTR__UNKNOWN) {\n+\t\t\tif (negated) {\n+\t\t\t\tv = attr_negate(v);\n+\t\t\t\tif (!v)\n+\t\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tdebug_set(what, a->u.pattern, attr, v);\n \t\t\t*n = v;\n \t\t\trem--;\n@@ -588,7 +610,7 @@ static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)\n \t\t\tcontinue;\n \t\tif (path_matches(path, pathlen,\n \t\t\t\t a->u.pattern, base, strlen(base)))\n-\t\t\trem = fill_one(\"fill\", a, rem);\n+\t\t\trem = fill_one(\"fill\", a, rem, 0);\n \t}\n \treturn rem;\n }\n@@ -602,9 +624,11 @@ static int macroexpand(struct attr_stack *stk, int rem)\n \t\tstruct match_attr *a = stk->attrs[i];\n \t\tif (!a->is_macro)\n \t\t\tcontinue;\n-\t\tif (check[a->u.attr->attr_nr].value != ATTR__TRUE)\n-\t\t\tcontinue;\n-\t\trem = fill_one(\"expand\", a, rem);\n+\t\tif (check[a->u.attr->attr_nr].value == ATTR__TRUE)\n+\t\t\trem = fill_one(\"expand\", a, rem, 0);\n+\t\telse if (check[a->u.attr->attr_nr].value == ATTR__FALSE)\n+\t\t\trem = fill_one(\"expand\", a, rem, 1);\n+\t\t\t\n \t}\n \treturn rem;\n }\n"}]}