{"thread":{"id":"32411","subject":"[PATCH v2] Add directory pattern matching to attributes","startedAt":"2012-12-19T21:33:52Z","lastAt":"2012-12-19T22:58:19Z","messageCount":4,"participants":["Jean-Noël AVILA","Junio C Hamano"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"205215","messageId":"201212192233.53002.avila.jn@gmail.com","threadId":"32411","inReplyTo":null,"subject":"[PATCH v2] Add directory pattern matching to attributes","fromName":"Jean-Noël AVILA","fromEmail":"avila.jn@gmail.com","sentAt":"2012-12-19T21:33:52Z","receivedAt":"2012-12-19T21:33:52Z","isPatch":true,"sender":{"key":"jn.avila@free.fr","avatar":"https://avatars.githubusercontent.com/u/156172?v=4"},"body":"The manpage of gitattributes says: \"The rules how the pattern\nmatches paths are the same as in .gitignore files\" and the gitignore\npattern matching has a pattern ending with / for directory matching.\n\nThis rule is specifically relevant for the 'export-ignore' rule used\nfor git archive.\n\nSigned-off-by: Jean-Noel Avila <jn.avila@free.fr>\n---\nThis patch was not reviewed when I submitted it for the second time. Is there\nany pending work which prevents it from being merged?\n\n archive.c                       |    3 ++-\n attr.c                          |   32 ++++++++++++++++------\n t/t5002-archive-attr-pattern.sh |   57 +++++++++++++++++++++++++++++++++++++++\n 3 files changed, 83 insertions(+), 9 deletions(-)\n create mode 100644 t/t5002-archive-attr-pattern.sh\n\ndiff --git a/archive.c b/archive.c\nindex 4666404..93e00bb 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -120,6 +120,8 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,\n \tstrbuf_add(&path, args->base, args->baselen);\n \tstrbuf_add(&path, base, baselen);\n \tstrbuf_addstr(&path, filename);\n+\tif (S_ISDIR(mode) || S_ISGITLINK(mode))\n+\t\tstrbuf_addch(&path, '/');\n \tpath_without_prefix = path.buf + args->baselen;\n \n \tsetup_archive_check(check);\n@@ -130,7 +132,6 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,\n \t}\n \n \tif (S_ISDIR(mode) || S_ISGITLINK(mode)) {\n-\t\tstrbuf_addch(&path, '/');\n \t\tif (args->verbose)\n \t\t\tfprintf(stderr, \"%.*s\\n\", (int)path.len, path.buf);\n \t\terr = write_entry(args, sha1, path.buf, path.len, mode);\ndiff --git a/attr.c b/attr.c\nindex 097ae87..cdba88a 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -564,17 +564,31 @@ static void bootstrap_attr_stack(void)\n \tattr_stack = elem;\n }\n \n+static const char *find_basename(const char *path)\n+{\n+\tchar pathbuf[PATH_MAX];\n+\tint pathlen;\n+\tconst char *cp;\n+\n+\tpathlen =strlen(path);\n+\tif (path[pathlen-1] != '/') {\n+\t\tcp =strrchr(path, '/');\n+\t\treturn cp ? cp + 1: path;\n+\t} else {\n+\t\tstrncpy(pathbuf, path, pathlen);\n+\t\tpathbuf[pathlen-1] = '\\0';\n+\t\tcp =strrchr(pathbuf, '/');\n+\t\treturn cp ? path + (cp - pathbuf) + 1 : path;\n+\t}\n+}\n+\n static void prepare_attr_stack(const char *path)\n {\n \tstruct attr_stack *elem, *info;\n \tint dirlen, len;\n \tconst char *cp;\n \n-\tcp = strrchr(path, '/');\n-\tif (!cp)\n-\t\tdirlen = 0;\n-\telse\n-\t\tdirlen = cp - path;\n+\tdirlen = find_basename(path) - path;\n \n \t/*\n \t * At the bottom of the attribute stack is the built-in\n@@ -668,6 +682,10 @@ static int path_matches(const char *pathname, int pathlen,\n \tconst char *pattern = pat->pattern;\n \tint prefix = pat->nowildcardlen;\n \n+\tif ((pat->flags & EXC_FLAG_MUSTBEDIR) &&\n+\t    ((!pathlen) || (pathname[pathlen-1] != '/')))\n+\t\treturn 0;\n+\n \tif (pat->flags & EXC_FLAG_NODIR) {\n \t\treturn match_basename(basename,\n \t\t\t\t      pathlen - (basename - pathname),\n@@ -758,9 +776,7 @@ static void collect_all_attrs(const char *path)\n \tfor (i = 0; i < attr_nr; i++)\n \t\tcheck_all_attr[i].value = ATTR__UNKNOWN;\n \n-\tbasename = strrchr(path, '/');\n-\tbasename = basename ? basename + 1 : path;\n-\n+\tbasename = find_basename(path);\n \tpathlen = strlen(path);\n \trem = attr_nr;\n \tfor (stk = attr_stack; 0 < rem && stk; stk = stk->prev)\ndiff --git a/t/t5002-archive-attr-pattern.sh b/t/t5002-archive-attr-pattern.sh\nnew file mode 100644\nindex 0000000..0c847fb\n--- /dev/null\n+++ b/t/t5002-archive-attr-pattern.sh\n@@ -0,0 +1,57 @@\n+#!/bin/sh\n+\n+test_description='git archive attribute pattern tests'\n+\n+. ./test-lib.sh\n+\n+test_expect_exists() {\n+\ttest_expect_success \" $1 exists\" \"test -e $1\"\n+}\n+\n+test_expect_missing() {\n+\ttest_expect_success \" $1 does not exist\" \"test ! -e $1\"\n+}\n+\n+test_expect_success 'setup' '\n+\techo ignored >ignored &&\n+\techo ignored export-ignore >>.git/info/attributes &&\n+\tgit add ignored &&\n+\n+\tmkdir not-ignored-dir &&\n+\techo ignored-in-tree >not-ignored-dir/ignored &&\n+\techo not-ignored-in-tree >not-ignored-dir/ignored-only-if-dir &&\n+\tgit add not-ignored-dir &&\n+\n+\tmkdir ignored-only-if-dir &&\n+\techo ignored by ignored dir >ignored-only-if-dir/ignored-by-ignored-dir &&\n+\techo ignored-only-if-dir/ export-ignore >>.git/info/attributes &&\n+\tgit add ignored-only-if-dir &&\n+\n+\n+\tmkdir -p one-level-lower/two-levels-lower/ignored-only-if-dir &&\n+\techo ignored by ignored dir >one-level-lower/two-levels-lower/ignored-only-if-dir/ignored-by-ignored-dir &&\n+\tgit add one-level-lower &&\n+\n+\tgit commit -m. &&\n+\n+\tgit clone --bare . bare &&\n+\tcp .git/info/attributes bare/info/attributes\n+'\n+\n+test_expect_success 'git archive' '\n+\tgit archive HEAD >archive.tar &&\n+\t(mkdir archive && cd archive && \"$TAR\" xf -) <archive.tar\n+'\n+\n+test_expect_missing\tarchive/ignored\n+test_expect_missing\tarchive/not-ignored-dir/ignored\n+test_expect_exists\tarchive/not-ignored-dir/ignored-only-if-dir\n+test_expect_exists\tarchive/not-ignored-dir/\n+test_expect_missing\tarchive/ignored-only-if-dir/\n+test_expect_missing\tarchive/ignored-ony-if-dir/ignored-by-ignored-dir\n+test_expect_exists\tarchive/one-level-lower/\n+test_expect_missing\tarchive/one-level-lower/two-levels-lower/ignored-only-if-dir/\n+test_expect_missing\tarchive/one-level-lower/two-levels-lower/ignored-ony-if-dir/ignored-by-ignored-dir\n+\n+\n+test_done\n-- \n1.7.10.4\n"},{"id":"205217","messageId":"7vbodp90o4.fsf@alter.siamese.dyndns.org","threadId":"32411","inReplyTo":"201212192233.53002.avila.jn@gmail.com","subject":"Re: [PATCH v2] Add directory pattern matching to attributes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-12-19T21:44:59Z","receivedAt":"2012-12-19T21:44:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Jean-Noël AVILA\" <avila.jn@gmail.com> writes:\n\n> This patch was not reviewed when I submitted it for the second time.\n\nDid you miss this?\n\n    http://thread.gmane.org/gmane.comp.version-control.git/211214/focus=211470\n"},{"id":"205225","messageId":"201212192334.51085.avila.jn@gmail.com","threadId":"32411","inReplyTo":"7vbodp90o4.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] Add directory pattern matching to attributes","fromName":"Jean-Noël AVILA","fromEmail":"avila.jn@gmail.com","sentAt":"2012-12-19T22:34:50Z","receivedAt":"2012-12-19T22:34:50Z","isPatch":true,"sender":{"key":"jn.avila@free.fr","avatar":"https://avatars.githubusercontent.com/u/156172?v=4"},"body":"Le mercredi 19 décembre 2012 22:44:59, vous avez écrit :\n> \"Jean-Noël AVILA\" <avila.jn@gmail.com> writes:\n> > This patch was not reviewed when I submitted it for the second time.\n> \n> Did you miss this?\n> \n>    \n\nGrml, I did. Sorry for the noise.\n"},{"id":"205228","messageId":"7vr4ml7ipg.fsf@alter.siamese.dyndns.org","threadId":"32411","inReplyTo":"201212192334.51085.avila.jn@gmail.com","subject":"Re: [PATCH v2] Add directory pattern matching to attributes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-12-19T22:58:19Z","receivedAt":"2012-12-19T22:58:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Jean-Noël AVILA\" <avila.jn@gmail.com> writes:\n\n> Le mercredi 19 décembre 2012 22:44:59, vous avez écrit :\n>> \"Jean-Noël AVILA\" <avila.jn@gmail.com> writes:\n>> > This patch was not reviewed when I submitted it for the second time.\n>> \n>> Did you miss this?\n>>    \n>\n> Grml, I did. Sorry for the noise.\n\nThat's OK.  Your previous one, with the update suggested in the\nthread, has already been queued in 'next' and will be cooking\nthere throughout the pre-release feature freeze.\n"}]}