{"thread":{"id":"32065","subject":"[PATCH/RFC] attr: allow pattern escape using backslash","startedAt":"2012-11-11T10:32:22Z","lastAt":"2012-11-11T10:32:22Z","messageCount":1,"participants":["Nguyễn Thái Ngọc Duy"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"202807","messageId":"20121111103222.GA6029@lanh","threadId":"32065","inReplyTo":null,"subject":"[PATCH/RFC] attr: allow pattern escape using backslash","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2012-11-11T10:32:22Z","receivedAt":"2012-11-11T10:32:22Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":".gitattributes pattern syntax is supposed to be the same as .gitignore\n(except a few things that do not make sense in attr context, but\nthat's a different issue). .gitignore uses fnmatch() as the matching\nmachinery and \"\\\" is accepted as an escape code. In theory the pattern\n'foo\\ bar' should match path 'foo bar' in .gitignore. Granted, no one\nwould write 'foo\\ bar' in .gitignore when 'foo bar' should\nsuffice.\n\nRegardless, 'foo\\ bar attr' does not (but should) attach \"attr\" to\npath \"foo bar\" because pattern/attr parse code does not understand\nbackslash escape. It parses the line as path 'foo\\' and attributes\n'bar' and 'attr'. This patch teaches attr code to recognize the\nbackslash in patterns (not macro names) and pass 'foo\\ bar' down to\nfnmatch().\n\nThis changes the attr behavior. \"foo\\ attr\", if exists in the field,\nwould match nothing because path \"foo\\\" is invalid in UNIX and is a\ndirectory in Windows, which we do not accept attaching attributes\nto. With this patch, that line becomes invalid and is rejected. So\nit's not really bad (i.e. no silent changes in behavior).\n\nOther subtle behavioral changes may happen. Still, I think we should\ndo this as it seems like a correct thing to do.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n It was posted [1] during rc cycles (I think) and initial feedback\n from Junio was \"not utterly wrong\". I still think this is worth\n doing, hence this resend for discussion.\n\n [1] http://thread.gmane.org/gmane.comp.version-control.git/207135\n\n attr.c                | 12 +++++++++++-\n t/t0003-attributes.sh |  5 +++++\n 2 files changed, 16 insertions(+), 1 deletion(-)\n\ndiff --git a/attr.c b/attr.c\nindex 887a9ae..173d51d 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -221,8 +221,18 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,\n \t\t\treturn NULL;\n \t\t}\n \t}\n-\telse\n+\telse {\n \t\tis_macro = 0;\n+\t\tnamelen = 0;\n+\t\twhile (name[namelen] != '\\0' &&\n+\t\t       !strchr(blank, name[namelen])) {\n+\t\t\tif (name[namelen] == '\\\\' &&\n+\t\t\t    name[namelen + 1] != '\\0')\n+\t\t\t\tnamelen += 2;\n+\t\t\telse\n+\t\t\t\tnamelen++;\n+\t\t}\n+\t}\n \n \tstates = name + namelen;\n \tstates += strspn(states, blank);\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex febc45c..16b419e 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -24,6 +24,7 @@ test_expect_success 'setup' '\n \t\techo \"offon -test test\"\n \t\techo \"no notest\"\n \t\techo \"A/e/F test=A/e/F\"\n+\t\techo \"A\\\\ b test=space\"\n \t) >.gitattributes &&\n \t(\n \t\techo \"g test=a/g\" &&\n@@ -196,6 +197,10 @@ test_expect_success 'root subdir attribute test' '\n \tattr_check subdir/a/i unspecified\n '\n \n+test_expect_success 'quoting in pattern' '\n+\tattr_check \"A b\" space\n+'\n+\n test_expect_success 'setup bare' '\n \tgit clone --bare . bare.git &&\n \tcd bare.git\n-- \n1.7.12.1.406.g6ab07c4\n"}]}