{"thread":{"id":"18890","subject":"[PATCH 0/5] archive attribute series","startedAt":"2009-04-16T02:28:32Z","lastAt":"2009-04-17T22:18:10Z","messageCount":19,"participants":["Junio C Hamano","Jeff King","Jakub Narebski","Nguyen Thai Ngoc Duy","René Scharfe"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"111407","messageId":"1239848917-14399-1-git-send-email-gitster@pobox.com","threadId":"18890","inReplyTo":null,"subject":"[PATCH 0/5] archive attribute series","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-04-16T02:28:32Z","receivedAt":"2009-04-16T02:28:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Here is my attempt to consolidate the fix-ups on Duy's git-archive\nenhancements.\n\nI haven't decided if this should go to 1.6.3; it is a sensible change but\nit *is* a change in behaviour that could be seen as incompatible.\n\nJunio C Hamano (1):\n  unpack-trees: do not muck with attributes when we are not checking\n    out\n\nNguyá»n ThÃ¡i Ngá»c Duy (2):\n  attr: add GIT_ATTR_INDEX \"direction\"\n  archive: do not read .gitattributes in working directory\n\nRenÃ© Scharfe (2):\n  archive tests: do not use .gitattributes in working directory\n  archive test: test new --fix-attributes feature\n\n Documentation/git-archive.txt |    5 ++-\n archive.c                     |   22 ++++++++++++++\n archive.h                     |    1 +\n attr.c                        |   12 ++++++--\n attr.h                        |    3 +-\n builtin-tar-tree.c            |    8 +++++\n t/t5000-tar-tree.sh           |    9 +++--\n t/t5001-archive-attr.sh       |   62 +++++++++++++++++++++++++++++++++++++++++\n unpack-trees.c                |    6 ++-\n 9 files changed, 117 insertions(+), 11 deletions(-)\n create mode 100755 t/t5001-archive-attr.sh\n"},{"id":"111411","messageId":"1239848917-14399-2-git-send-email-gitster@pobox.com","threadId":"18890","inReplyTo":"1239848917-14399-1-git-send-email-gitster@pobox.com","subject":"[PATCH 1/5] archive tests: do not use .gitattributes in working directory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-04-16T02:28:33Z","receivedAt":"2009-04-16T02:28:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: René Scharfe <rene.scharfe@lsrfire.ath.cx>\n\nWe are interested in using archive mostly from a bare repository, so it\nshould not add .gitattributes to the work tree.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t5000-tar-tree.sh |    9 +++++----\n 1 files changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh\nindex 7641e0d..abb41b0 100755\n--- a/t/t5000-tar-tree.sh\n+++ b/t/t5000-tar-tree.sh\n@@ -50,7 +50,7 @@ test_expect_success \\\n test_expect_success \\\n     'add ignored file' \\\n     'echo ignore me >a/ignored &&\n-     echo ignored export-ignore >.gitattributes'\n+     echo ignored export-ignore >.git/info/attributes'\n \n test_expect_success \\\n     'add files to repository' \\\n@@ -64,7 +64,7 @@ test_expect_success \\\n test_expect_success \\\n     'create bare clone' \\\n     'git clone --bare . bare.git &&\n-     cp .gitattributes bare.git/info/attributes'\n+     cp .git/info/attributes bare.git/info/attributes'\n \n test_expect_success \\\n     'remove ignored file' \\\n@@ -139,10 +139,11 @@ test_expect_success \\\n \n test_expect_success \\\n     'create archives with substfiles' \\\n-    'echo \"substfile?\" export-subst >a/.gitattributes &&\n+    'cp .git/info/attributes .git/info/attributes.before &&\n+     echo \"substfile?\" export-subst >>.git/info/attributes &&\n      git archive HEAD >f.tar &&\n      git archive --prefix=prefix/ HEAD >g.tar &&\n-     rm a/.gitattributes'\n+     mv .git/info/attributes.before .git/info/attributes'\n \n test_expect_success \\\n     'extract substfiles' \\\n-- \n1.6.3.rc0.6.g08087\n"},{"id":"111410","messageId":"1239848917-14399-3-git-send-email-gitster@pobox.com","threadId":"18890","inReplyTo":"1239848917-14399-2-git-send-email-gitster@pobox.com","subject":"[PATCH 2/5] attr: add GIT_ATTR_INDEX \"direction\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-04-16T02:28:34Z","receivedAt":"2009-04-16T02:28:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n\nThis instructs attr mechanism, not to look into working .gitattributes\nat all. Needed by tools that does not handle working directory, such\nas \"git archive\".\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n attr.c |   12 +++++++++---\n attr.h |    3 ++-\n 2 files changed, 11 insertions(+), 4 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 43259e5..626eadb 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -405,7 +405,7 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)\n \t\tif (!res)\n \t\t\tres = read_attr_from_file(path, macro_ok);\n \t}\n-\telse {\n+\telse if (direction == GIT_ATTR_CHECKIN) {\n \t\tres = read_attr_from_file(path, macro_ok);\n \t\tif (!res)\n \t\t\t/*\n@@ -415,6 +415,8 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)\n \t\t\t */\n \t\t\tres = read_attr_from_index(path, macro_ok);\n \t}\n+\telse\n+\t\tres = read_attr_from_index(path, macro_ok);\n \tif (!res)\n \t\tres = xcalloc(1, sizeof(*res));\n \treturn res;\n@@ -466,7 +468,7 @@ static void bootstrap_attr_stack(void)\n \t\telem->prev = attr_stack;\n \t\tattr_stack = elem;\n \n-\t\tif (!is_bare_repository()) {\n+\t\tif (!is_bare_repository() || direction == GIT_ATTR_INDEX) {\n \t\t\telem = read_attr(GITATTRIBUTES_FILE, 1);\n \t\t\telem->origin = strdup(\"\");\n \t\t\telem->prev = attr_stack;\n@@ -533,7 +535,7 @@ static void prepare_attr_stack(const char *path, int dirlen)\n \t/*\n \t * Read from parent directories and push them down\n \t */\n-\tif (!is_bare_repository()) {\n+\tif (!is_bare_repository() || direction == GIT_ATTR_INDEX) {\n \t\twhile (1) {\n \t\t\tchar *cp;\n \n@@ -674,6 +676,10 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)\n void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)\n {\n \tenum git_attr_direction old = direction;\n+\n+\tif (is_bare_repository() && new != GIT_ATTR_INDEX)\n+\t\tdie(\"BUG: non-INDEX att direction in a bare repo\");\n+\n \tdirection = new;\n \tif (new != old)\n \t\tdrop_attr_stack();\ndiff --git a/attr.h b/attr.h\nindex 3a2f4ec..69b5767 100644\n--- a/attr.h\n+++ b/attr.h\n@@ -33,7 +33,8 @@ int git_checkattr(const char *path, int, struct git_attr_check *);\n \n enum git_attr_direction {\n \tGIT_ATTR_CHECKIN,\n-\tGIT_ATTR_CHECKOUT\n+\tGIT_ATTR_CHECKOUT,\n+\tGIT_ATTR_INDEX,\n };\n void git_attr_set_direction(enum git_attr_direction, struct index_state *);\n \n-- \n1.6.3.rc0.6.g08087\n"},{"id":"111409","messageId":"1239848917-14399-4-git-send-email-gitster@pobox.com","threadId":"18890","inReplyTo":"1239848917-14399-3-git-send-email-gitster@pobox.com","subject":"[PATCH 3/5] unpack-trees: do not muck with attributes when we are not checking out","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-04-16T02:28:35Z","receivedAt":"2009-04-16T02:28:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Signed-off-by: Junio C Hamano <gitster@pobox.com>\n---\n unpack-trees.c |    6 ++++--\n 1 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 6847c2d..e4eb8fa 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -87,7 +87,8 @@ static int check_updates(struct unpack_trees_options *o)\n \t\tcnt = 0;\n \t}\n \n-\tgit_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);\n+\tif (o->update)\n+\t\tgit_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);\n \tfor (i = 0; i < index->cache_nr; i++) {\n \t\tstruct cache_entry *ce = index->cache[i];\n \n@@ -112,7 +113,8 @@ static int check_updates(struct unpack_trees_options *o)\n \t\t}\n \t}\n \tstop_progress(&progress);\n-\tgit_attr_set_direction(GIT_ATTR_CHECKIN, NULL);\n+\tif (o->update)\n+\t\tgit_attr_set_direction(GIT_ATTR_CHECKIN, NULL);\n \treturn errs != 0;\n }\n \n-- \n1.6.3.rc0.6.g08087\n"},{"id":"111412","messageId":"1239848917-14399-5-git-send-email-gitster@pobox.com","threadId":"18890","inReplyTo":"1239848917-14399-4-git-send-email-gitster@pobox.com","subject":"[PATCH 4/5] archive: do not read .gitattributes in working directory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-04-16T02:28:36Z","receivedAt":"2009-04-16T02:28:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n\nThe old behaviour still remains with --fix-attributes, and it is always on\nfor the legacy \"git tar-tree\".\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/git-archive.txt |    5 ++++-\n archive.c                     |   22 ++++++++++++++++++++++\n archive.h                     |    1 +\n builtin-tar-tree.c            |    8 ++++++++\n 4 files changed, 35 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt\nindex c1adf59..fd882bf 100644\n--- a/Documentation/git-archive.txt\n+++ b/Documentation/git-archive.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n --------\n [verse]\n 'git archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]\n-\t      [--output=<file>]\n+\t      [--output=<file>] [--fix-attributes]\n \t      [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>\n \t      [path...]\n \n@@ -51,6 +51,9 @@ OPTIONS\n --output=<file>::\n \tWrite the archive to <file> instead of stdout.\n \n+--fix-attributes::\n+\tLook for attributes in .gitattributes in working directory too.\n+\n <extra>::\n \tThis can be any options that the archiver backend understands.\n \tSee next section.\ndiff --git a/archive.c b/archive.c\nindex 96b62d4..0ce628b 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -4,6 +4,7 @@\n #include \"attr.h\"\n #include \"archive.h\"\n #include \"parse-options.h\"\n+#include \"unpack-trees.h\"\n \n static char const * const archive_usage[] = {\n \t\"git archive [options] <tree-ish> [path...]\",\n@@ -150,6 +151,8 @@ int write_archive_entries(struct archiver_args *args,\n \t\twrite_archive_entry_fn_t write_entry)\n {\n \tstruct archiver_context context;\n+\tstruct unpack_trees_options opts;\n+\tstruct tree_desc t;\n \tint err;\n \n \tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n@@ -168,6 +171,22 @@ int write_archive_entries(struct archiver_args *args,\n \tcontext.args = args;\n \tcontext.write_entry = write_entry;\n \n+\t/*\n+\t * Setup index and instruct attr to read index only\n+\t */\n+\tif (!args->worktree_attributes) {\n+\t\tmemset(&opts, 0, sizeof(opts));\n+\t\topts.index_only = 1;\n+\t\topts.head_idx = -1;\n+\t\topts.src_index = &the_index;\n+\t\topts.dst_index = &the_index;\n+\t\topts.fn = oneway_merge;\n+\t\tinit_tree_desc(&t, args->tree->buffer, args->tree->size);\n+\t\tif (unpack_trees(1, &t, &opts))\n+\t\t\treturn -1;\n+\t\tgit_attr_set_direction(GIT_ATTR_INDEX, &the_index);\n+\t}\n+\n \terr =  read_tree_recursive(args->tree, args->base, args->baselen, 0,\n \t\t\targs->pathspec, write_archive_entry, &context);\n \tif (err == READ_TREE_RECURSIVE)\n@@ -258,6 +277,7 @@ static int parse_archive_args(int argc, const char **argv,\n \tint verbose = 0;\n \tint i;\n \tint list = 0;\n+\tint worktree_attributes = 0;\n \tstruct option opts[] = {\n \t\tOPT_GROUP(\"\"),\n \t\tOPT_STRING(0, \"format\", &format, \"fmt\", \"archive format\"),\n@@ -265,6 +285,7 @@ static int parse_archive_args(int argc, const char **argv,\n \t\t\t\"prepend prefix to each pathname in the archive\"),\n \t\tOPT_STRING(0, \"output\", &output, \"file\",\n \t\t\t\"write the archive to this file\"),\n+\t\tOPT_BOOLEAN(0, \"fix-attributes\", &worktree_attributes, \"read .gitattributes in working directory\"),\n \t\tOPT__VERBOSE(&verbose),\n \t\tOPT__COMPR('0', &compression_level, \"store only\", 0),\n \t\tOPT__COMPR('1', &compression_level, \"compress faster\", 1),\n@@ -324,6 +345,7 @@ static int parse_archive_args(int argc, const char **argv,\n \targs->verbose = verbose;\n \targs->base = base;\n \targs->baselen = strlen(base);\n+\targs->worktree_attributes = worktree_attributes;\n \n \treturn argc;\n }\ndiff --git a/archive.h b/archive.h\nindex 0b15b35..038ac35 100644\n--- a/archive.h\n+++ b/archive.h\n@@ -10,6 +10,7 @@ struct archiver_args {\n \ttime_t time;\n \tconst char **pathspec;\n \tunsigned int verbose : 1;\n+\tunsigned int worktree_attributes : 1;\n \tint compression_level;\n };\n \ndiff --git a/builtin-tar-tree.c b/builtin-tar-tree.c\nindex 0713bca..760ea9d 100644\n--- a/builtin-tar-tree.c\n+++ b/builtin-tar-tree.c\n@@ -36,6 +36,14 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix)\n \t\targv++;\n \t\targc--;\n \t}\n+\tif (2 <= argc && !strcmp(argv[1], \"--fix-attributes\")) {\n+\t\targv++;\n+\t\targc--;\n+\t}\n+\n+\t/* tar-tree defaults to fix-attributes as before */\n+\tnargv[nargc++] = \"--fix-attributes\";\n+\n \tswitch (argc) {\n \tdefault:\n \t\tusage(tar_tree_usage);\n-- \n1.6.3.rc0.6.g08087\n"},{"id":"111408","messageId":"1239848917-14399-6-git-send-email-gitster@pobox.com","threadId":"18890","inReplyTo":"1239848917-14399-5-git-send-email-gitster@pobox.com","subject":"[PATCH 5/5] archive test: test new --fix-attributes feature","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-04-16T02:28:37Z","receivedAt":"2009-04-16T02:28:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: René Scharfe <rene.scharfe@lsrfire.ath.cx>\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t5001-archive-attr.sh |   62 +++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 62 insertions(+), 0 deletions(-)\n create mode 100755 t/t5001-archive-attr.sh\n\ndiff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh\nnew file mode 100755\nindex 0000000..b754f21\n--- /dev/null\n+++ b/t/t5001-archive-attr.sh\n@@ -0,0 +1,62 @@\n+#!/bin/sh\n+\n+test_description='git archive attribute tests'\n+\n+. ./test-lib.sh\n+\n+SUBSTFORMAT=%H%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+\techo ignored by tree >ignored-by-tree &&\n+\techo ignored-by-tree export-ignore >.gitattributes &&\n+\tgit add ignored-by-tree .gitattributes &&\n+\n+\techo ignored by worktree >ignored-by-worktree &&\n+\techo ignored-by-worktree export-ignore >.gitattributes &&\n+\tgit add ignored-by-worktree &&\n+\n+\tprintf \"A\\$Format:%s\\$O\" \"$SUBSTFORMAT\" >nosubstfile &&\n+\tprintf \"A\\$Format:%s\\$O\" \"$SUBSTFORMAT\" >substfile1 &&\n+\tprintf \"A not substituted O\" >substfile2 &&\n+\techo \"substfile?\" export-subst >>.git/info/attributes &&\n+\tgit add nosubstfile substfile1 substfile2 &&\n+\n+\tgit commit -m.\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_success 'git archive with worktree attributes' '\n+\tgit archive --fix-attributes HEAD >worktree.tar &&\n+\t(mkdir worktree && cd worktree && \"$TAR\" xf -) <worktree.tar\n+'\n+\n+test_expect_success 'export-ignore' '\n+\ttest ! -e archive/ignored &&\n+\ttest ! -e archive/ignored-by-tree &&\n+\ttest   -e archive/ignored-by-worktree &&\n+\ttest ! -e worktree/ignored &&\n+\ttest   -e worktree/ignored-by-tree &&\n+\ttest ! -e worktree/ignored-by-worktree\n+'\n+\n+test_expect_success 'export-subst' '\n+\tgit log \"--pretty=format:A${SUBSTFORMAT}O\" HEAD >substfile1.expected &&\n+\ttest_cmp nosubstfile archive/nosubstfile &&\n+\ttest_cmp substfile1.expected archive/substfile1 &&\n+\ttest_cmp substfile2 archive/substfile2\n+'\n+\n+test_expect_success 'git tar-tree vs. git archive with worktree attributes' '\n+\tgit tar-tree HEAD >tar-tree.tar &&\n+\ttest_cmp worktree.tar tar-tree.tar\n+'\n+\n+test_done\n-- \n1.6.3.rc0.6.g08087\n"},{"id":"111417","messageId":"7vhc0pnpn3.fsf@gitster.siamese.dyndns.org","threadId":"18890","inReplyTo":"1239848917-14399-5-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 4/5] archive: do not read .gitattributes in working directory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-04-16T05:17:36Z","receivedAt":"2009-04-16T05:17:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c\n> index 0713bca..760ea9d 100644\n> --- a/builtin-tar-tree.c\n> +++ b/builtin-tar-tree.c\n> @@ -36,6 +36,14 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix)\n>  \t\targv++;\n>  \t\targc--;\n>  \t}\n> +\tif (2 <= argc && !strcmp(argv[1], \"--fix-attributes\")) {\n> +\t\targv++;\n> +\t\targc--;\n> +\t}\n> +\n> +\t/* tar-tree defaults to fix-attributes as before */\n> +\tnargv[nargc++] = \"--fix-attributes\";\n> +\n>  \tswitch (argc) {\n>  \tdefault:\n>  \t\tusage(tar_tree_usage);\n\nI screwed up this part; nargv[] array needs to be enlarged by one element\nbecause of this change.  It resulted in a funny breakage in tests that\ntriggered only when run from the toplevel of the tree but did not surface\nwhen the individual test was done from t/ directory, which my final\ntesting on the k.org machine caught, and that is why I still haven't\nmanaged to push the result out for tonight.\n"},{"id":"111424","messageId":"20090416070626.GB20071@coredump.intra.peff.net","threadId":"18890","inReplyTo":"7vhc0pnpn3.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 4/5] archive: do not read .gitattributes in working directory","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-04-16T07:06:26Z","receivedAt":"2009-04-16T07:06:26Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Apr 15, 2009 at 10:17:36PM -0700, Junio C Hamano wrote:\n\n> > +\t/* tar-tree defaults to fix-attributes as before */\n> > +\tnargv[nargc++] = \"--fix-attributes\";\n> > +\n> >  \tswitch (argc) {\n> >  \tdefault:\n> >  \t\tusage(tar_tree_usage);\n> \n> I screwed up this part; nargv[] array needs to be enlarged by one element\n> because of this change.  It resulted in a funny breakage in tests that\n> triggered only when run from the toplevel of the tree but did not surface\n> when the individual test was done from t/ directory, which my final\n> testing on the k.org machine caught, and that is why I still haven't\n> managed to push the result out for tonight.\n\nFWIW, running t5000 with --valgrind does catch it. I'll try to run the\nfull test suite with valgrind on the last -rc before 1.6.3 to catch any\nhidden issues which have cropped up during this cycle (I can do it\nearlier, too, but it is a real pain to run the whole thing, so I want to\njust wait until the last minute).\n\n-Peff\n"},{"id":"111427","messageId":"gs6mo9$nc6$1@ger.gmane.org","threadId":"18890","inReplyTo":"1239848917-14399-5-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 4/5] archive: do not read .gitattributes in working directory","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-04-16T07:29:12Z","receivedAt":"2009-04-16T07:29:12Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n\n> The old behaviour still remains with --fix-attributes, and it is always on\n> for the legacy \"git tar-tree\".\n\nI thought that we agreed on '--worktree-attributes' being better name,\ndidn't we?\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"111439","messageId":"fcaeb9bf0904160350m14dce828oe88bda6562d98f48@mail.gmail.com","threadId":"18890","inReplyTo":"1239848917-14399-5-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 4/5] archive: do not read .gitattributes in working directory","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2009-04-16T10:50:05Z","receivedAt":"2009-04-16T10:50:05Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Sorry I got distracted by Vista+x11 stuff and had not work on this.\n\n2009/4/16 Junio C Hamano <gitster@pobox.com>:\n> @@ -168,6 +171,22 @@ int write_archive_entries(struct archiver_args *args,\n>        context.args = args;\n>        context.write_entry = write_entry;\n>\n> +       /*\n> +        * Setup index and instruct attr to read index only\n> +        */\n> +       if (!args->worktree_attributes) {\n> +               memset(&opts, 0, sizeof(opts));\n> +               opts.index_only = 1;\n> +               opts.head_idx = -1;\n> +               opts.src_index = &the_index;\n> +               opts.dst_index = &the_index;\n> +               opts.fn = oneway_merge;\n> +               init_tree_desc(&t, args->tree->buffer, args->tree->size);\n> +               if (unpack_trees(1, &t, &opts))\n> +                       return -1;\n> +               git_attr_set_direction(GIT_ATTR_INDEX, &the_index);\n> +       }\n> +\n>        err =  read_tree_recursive(args->tree, args->base, args->baselen, 0,\n>                        args->pathspec, write_archive_entry, &context);\n>        if (err == READ_TREE_RECURSIVE)\n\nSquash the attached patch on top of this patch (I have yet to install\nmutt), we may avoid a few possible lstat()s during unpack_trees(),\nalso less memory allocation.\n\nI was thinking about loading .gitattributes inside write_archive_entry\ntoo, to avoid calling read_tree_recursive twice, but it requires\n.gitattributes to be traversed first. Won't work if there are files\n.abc, .def...\n\nIf read_tree_recusive() expose its tree to read_tree_fn_t, we can then\nlook ahead and load .gitattributes, but that requires changing\nread_tree_fn_t interface. I'll see if it's feasible to make a\ncustomized read_tree_recusive() just for archive.c\n\nOh and a feature request (not really because I don't use it myself):\nsupport submodules in \"git archive\", anyone?\n\n> @@ -36,6 +36,14 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix)\n>                argv++;\n>                argc--;\n>        }\n> +       if (2 <= argc && !strcmp(argv[1], \"--fix-attributes\")) {\n> +               argv++;\n> +               argc--;\n> +       }\n\nDoes this part needed? Gotta fix tar_tree_usage and git-tar-tree.txt\ntoo. I'd vote remove it.\n-- \nDuy\n\n\ndiff --git a/archive.c b/archive.c\nindex 0ce628b..f79d005 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -147,12 +147,34 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,\n \treturn err;\n }\n \n+static int read_gitattr_to_index(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)\n+{\n+\tstruct cache_entry *ce;\n+\tunsigned int size;\n+\tint len;\n+\tstatic int gitattr_len = 0;\n+\n+\tif (S_ISDIR(mode))\n+\t\treturn READ_TREE_RECURSIVE;\n+\n+\tlen = strlen(pathname);\n+\tif (!gitattr_len)\n+\t\tgitattr_len = strlen(GITATTRIBUTES_FILE);\n+\tif (len < gitattr_len || strcmp(pathname+len-gitattr_len, GITATTRIBUTES_FILE))\n+\t\treturn 0;\n+\tsize = cache_entry_size(len);\n+\tce = xcalloc(1, size);\n+\tce->ce_mode = create_ce_mode(mode);\n+\tce->ce_flags = create_ce_flags(len, stage);\n+\tmemcpy(ce->name, pathname, len+1);\n+\thashcpy(ce->sha1, sha1);\n+\treturn add_cache_entry(ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_SKIP_DFCHECK);\n+}\n+\n int write_archive_entries(struct archiver_args *args,\n \t\twrite_archive_entry_fn_t write_entry)\n {\n \tstruct archiver_context context;\n-\tstruct unpack_trees_options opts;\n-\tstruct tree_desc t;\n \tint err;\n \n \tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n@@ -170,20 +192,8 @@ int write_archive_entries(struct archiver_args *args,\n \n \tcontext.args = args;\n \tcontext.write_entry = write_entry;\n-\n-\t/*\n-\t * Setup index and instruct attr to read index only\n-\t */\n \tif (!args->worktree_attributes) {\n-\t\tmemset(&opts, 0, sizeof(opts));\n-\t\topts.index_only = 1;\n-\t\topts.head_idx = -1;\n-\t\topts.src_index = &the_index;\n-\t\topts.dst_index = &the_index;\n-\t\topts.fn = oneway_merge;\n-\t\tinit_tree_desc(&t, args->tree->buffer, args->tree->size);\n-\t\tif (unpack_trees(1, &t, &opts))\n-\t\t\treturn -1;\n+\t\tread_tree_recursive(args->tree, NULL, 0, 0, NULL, read_gitattr_to_index, NULL);\n \t\tgit_attr_set_direction(GIT_ATTR_INDEX, &the_index);\n \t}\n \n"},{"id":"111443","messageId":"fcaeb9bf0904160538w4a826c57r40e9cf1c52b0b6ff@mail.gmail.com","threadId":"18890","inReplyTo":"fcaeb9bf0904160350m14dce828oe88bda6562d98f48@mail.gmail.com","subject":"Re: [PATCH 4/5] archive: do not read .gitattributes in working directory","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2009-04-16T12:38:46Z","receivedAt":"2009-04-16T12:38:46Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Apr 16, 2009 at 8:50 PM, Nguyen Thai Ngoc Duy <pclouds@gmail.com> wrote:\n> I was thinking about loading .gitattributes inside write_archive_entry\n> too, to avoid calling read_tree_recursive twice, but it requires\n> .gitattributes to be traversed first. Won't work if there are files\n> .abc, .def...\n>\n> If read_tree_recusive() expose its tree to read_tree_fn_t, we can then\n> look ahead and load .gitattributes, but that requires changing\n> read_tree_fn_t interface. I'll see if it's feasible to make a\n> customized read_tree_recusive() just for archive.c\n\nHere it is (again on top of your patch). Need to read directories\ntwice, but not as bad as read_tree_recursive() twice.\n-- \nDuy\n\n\ndiff --git a/archive.c b/archive.c\nindex 0ce628b..8df53a8 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -97,6 +97,43 @@ struct archiver_context {\n \twrite_archive_entry_fn_t write_entry;\n };\n \n+static int read_gitattr_to_index(struct tree *tree, const char *base, int baselen, struct archiver_args *args)\n+{\n+\tstruct tree_desc desc;\n+\tstruct name_entry entry;\n+\tstruct cache_entry *ce;\n+\tunsigned int size;\n+\tint pathlen;\n+\n+\tif (parse_tree(tree))\n+\t\treturn -1;\n+\n+\tinit_tree_desc(&desc, tree->buffer, tree->size);\n+\n+\twhile (tree_entry(&desc, &entry)) {\n+\t\tif (S_ISDIR(entry.mode) || S_ISGITLINK(entry.mode))\n+\t\t\tcontinue;\n+\t\tif (strcmp(entry.path, GITATTRIBUTES_FILE))\n+\t\t\tcontinue;\n+\t\tpathlen = tree_entry_len(entry.path, entry.sha1);\n+\t\tbaselen -= args->baselen; /* remove user prefix */\n+\t\tif (baselen)\n+\t\t\tbaselen++; /* slash */\n+\t\tsize = cache_entry_size(baselen + pathlen);\n+\t\tce = xcalloc(1, size);\n+\t\tce->ce_mode = create_ce_mode(entry.mode);\n+\t\tce->ce_flags = create_ce_flags(baselen + pathlen, 0);\n+\t\tif (baselen) {\n+\t\t\tmemcpy(ce->name, base + args->baselen, baselen-1);\n+\t\t\tce->name[baselen-1] = '/';\n+\t\t}\n+\t\tmemcpy(ce->name + baselen, entry.path, pathlen + 1);\n+\t\thashcpy(ce->sha1, entry.sha1);\n+\t\treturn add_cache_entry(ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_SKIP_DFCHECK);\n+\t}\n+\treturn 0;\n+}\n+\n static int write_archive_entry(const unsigned char *sha1, const char *base,\n \t\tint baselen, const char *filename, unsigned mode, int stage,\n \t\tvoid *context)\n@@ -119,11 +156,25 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,\n \tstrbuf_addstr(&path, filename);\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-\t\tif (ATTR_TRUE(check[0].value))\n-\t\t\treturn 0;\n-\t\tconvert = ATTR_TRUE(check[1].value);\n+\tif (S_ISDIR(mode)) {\n+\t\t/*\n+\t\t * we want to read .gitattributes before any entry is processed\n+\t\t * so every time we get a directory entry, we look ahead to see\n+\t\t * if there is .gitattributes and load it\n+\t\t *\n+\t\t * later when the directory is processed, .gitattributes is\n+\t\t * already ready in index for git_checkattr()\n+\t\t */\n+\t\tif (!args->worktree_attributes)\n+\t\t\tread_gitattr_to_index(lookup_tree(sha1), base, baselen, args);\n+\t}\n+\telse {\n+\t\tsetup_archive_check(check);\n+\t\tif (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) {\n+\t\t\tif (ATTR_TRUE(check[0].value))\n+\t\t\t\treturn 0;\n+\t\t\tconvert = ATTR_TRUE(check[1].value);\n+\t\t}\n \t}\n \n \tif (S_ISDIR(mode) || S_ISGITLINK(mode)) {\n@@ -151,8 +202,6 @@ int write_archive_entries(struct archiver_args *args,\n \t\twrite_archive_entry_fn_t write_entry)\n {\n \tstruct archiver_context context;\n-\tstruct unpack_trees_options opts;\n-\tstruct tree_desc t;\n \tint err;\n \n \tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n@@ -171,19 +220,9 @@ int write_archive_entries(struct archiver_args *args,\n \tcontext.args = args;\n \tcontext.write_entry = write_entry;\n \n-\t/*\n-\t * Setup index and instruct attr to read index only\n-\t */\n \tif (!args->worktree_attributes) {\n-\t\tmemset(&opts, 0, sizeof(opts));\n-\t\topts.index_only = 1;\n-\t\topts.head_idx = -1;\n-\t\topts.src_index = &the_index;\n-\t\topts.dst_index = &the_index;\n-\t\topts.fn = oneway_merge;\n-\t\tinit_tree_desc(&t, args->tree->buffer, args->tree->size);\n-\t\tif (unpack_trees(1, &t, &opts))\n-\t\t\treturn -1;\n+\t\t/* read .gitattributes at root if any */\n+\t\tread_gitattr_to_index(args->tree, args->base, args->baselen, args);\n \t\tgit_attr_set_direction(GIT_ATTR_INDEX, &the_index);\n \t}\n \n@@ -209,13 +248,23 @@ static const struct archiver *lookup_archiver(const char *name)\n }\n \n static void parse_pathspec_arg(const char **pathspec,\n-\t\tstruct archiver_args *ar_args)\n+\t\tstruct archiver_args *ar_args,\n+\t\tconst char *prefix)\n {\n-\tar_args->pathspec = get_pathspec(ar_args->base, pathspec);\n+\tstruct strbuf s = STRBUF_INIT;\n+\tif (ar_args->base)\n+\t\tstrbuf_addstr(&s, ar_args->base);\n+\tif (prefix)\n+\t\tstrbuf_addstr(&s, prefix);\n+\tar_args->pathspec = get_pathspec(s.len ? s.buf : NULL, pathspec);\n+\t/*\n+\t * s.buf must never be freed because\n+\t * get_pathspec does not duplicate it\n+\t */\n }\n \n static void parse_treeish_arg(const char **argv,\n-\t\tstruct archiver_args *ar_args, const char *prefix)\n+\t\tstruct archiver_args *ar_args)\n {\n \tconst char *name = argv[0];\n \tconst unsigned char *commit_sha1;\n@@ -240,18 +289,6 @@ static void parse_treeish_arg(const char **argv,\n \tif (tree == NULL)\n \t\tdie(\"not a tree object\");\n \n-\tif (prefix) {\n-\t\tunsigned char tree_sha1[20];\n-\t\tunsigned int mode;\n-\t\tint err;\n-\n-\t\terr = get_tree_entry(tree->object.sha1, prefix,\n-\t\t\t\t     tree_sha1, &mode);\n-\t\tif (err || !S_ISDIR(mode))\n-\t\t\tdie(\"current working directory is untracked\");\n-\n-\t\ttree = parse_tree_indirect(tree_sha1);\n-\t}\n \tar_args->tree = tree;\n \tar_args->commit_sha1 = commit_sha1;\n \tar_args->commit = commit;\n@@ -360,8 +397,8 @@ int write_archive(int argc, const char **argv, const char *prefix,\n \tif (setup_prefix && prefix == NULL)\n \t\tprefix = setup_git_directory();\n \n-\tparse_treeish_arg(argv, &args, prefix);\n-\tparse_pathspec_arg(argv + 1, &args);\n+\tparse_treeish_arg(argv, &args);\n+\tparse_pathspec_arg(argv + 1, &args, prefix);\n \n \tgit_config(git_default_config, NULL);\n \n"},{"id":"111531","messageId":"49E8DDD5.4080008@lsrfire.ath.cx","threadId":"18890","inReplyTo":"1239848917-14399-2-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 1/5] archive tests: do not use .gitattributes in working directory","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-04-17T19:51:49Z","receivedAt":"2009-04-17T19:51:49Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Thanks for wrapping this series up.  You can add a\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n\nto the this patch, if you like.\n\nRené\n"},{"id":"111532","messageId":"49E8DE50.5000908@lsrfire.ath.cx","threadId":"18890","inReplyTo":"1239848917-14399-6-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 5/5] archive test: test new --fix-attributes feature","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-04-17T19:53:52Z","receivedAt":"2009-04-17T19:53:52Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Could you please squash in the following, which adds test cases for bare repos\nand gives every export-ignore file existence test its own test case?  And also\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n\n?\n\n t/t5001-archive-attr.sh |   46 ++++++++++++++++++++++++++++++++++++++--------\n 1 files changed, 38 insertions(+), 8 deletions(-)\n\ndiff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh\nindex b754f21..dd93c3f 100755\n--- a/t/t5001-archive-attr.sh\n+++ b/t/t5001-archive-attr.sh\n@@ -6,6 +6,14 @@ test_description='git archive attribute tests'\n \n SUBSTFORMAT=%H%n\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@@ -25,7 +33,10 @@ test_expect_success 'setup' '\n \techo \"substfile?\" export-subst >>.git/info/attributes &&\n \tgit add nosubstfile substfile1 substfile2 &&\n \n-\tgit commit -m.\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@@ -33,20 +44,34 @@ test_expect_success 'git archive' '\n \t(mkdir archive && cd archive && \"$TAR\" xf -) <archive.tar\n '\n \n+test_expect_missing\tarchive/ignored\n+test_expect_missing\tarchive/ignored-by-tree\n+test_expect_exists\tarchive/ignored-by-worktree\n+\n test_expect_success 'git archive with worktree attributes' '\n \tgit archive --fix-attributes HEAD >worktree.tar &&\n \t(mkdir worktree && cd worktree && \"$TAR\" xf -) <worktree.tar\n '\n \n-test_expect_success 'export-ignore' '\n-\ttest ! -e archive/ignored &&\n-\ttest ! -e archive/ignored-by-tree &&\n-\ttest   -e archive/ignored-by-worktree &&\n-\ttest ! -e worktree/ignored &&\n-\ttest   -e worktree/ignored-by-tree &&\n-\ttest ! -e worktree/ignored-by-worktree\n+test_expect_missing\tworktree/ignored\n+test_expect_exists\tworktree/ignored-by-tree\n+test_expect_missing\tworktree/ignored-by-worktree\n+\n+test_expect_success 'git archive vs. bare' '\n+\t(cd bare && git archive HEAD) >bare-archive.tar &&\n+\ttest_cmp archive.tar bare-archive.tar\n+'\n+\n+test_expect_success 'git archive with worktree attributes, bare' '\n+\t(cd bare && git archive --fix-attributes HEAD) >bare-worktree.tar &&\n+\t(mkdir bare-worktree && cd bare-worktree && \"$TAR\" xf -\n+\t) <bare-worktree.tar\n '\n \n+test_expect_missing\tbare-worktree/ignored\n+test_expect_exists\tbare-worktree/ignored-by-tree\n+test_expect_exists\tbare-worktree/ignored-by-worktree\n+\n test_expect_success 'export-subst' '\n \tgit log \"--pretty=format:A${SUBSTFORMAT}O\" HEAD >substfile1.expected &&\n \ttest_cmp nosubstfile archive/nosubstfile &&\n@@ -59,4 +84,9 @@ test_expect_success 'git tar-tree vs. git archive with worktree attributes' '\n \ttest_cmp worktree.tar tar-tree.tar\n '\n \n+test_expect_success 'git tar-tree vs. git archive with worktree attrs, bare' '\n+\t(cd bare && git tar-tree HEAD) >bare-tar-tree.tar &&\n+\ttest_cmp bare-worktree.tar bare-tar-tree.tar\n+'\n+\n test_done\n"},{"id":"111534","messageId":"49E8E7A0.5020707@lsrfire.ath.cx","threadId":"18890","inReplyTo":"1239848917-14399-3-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 2/5] attr: add GIT_ATTR_INDEX \"direction\"","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-04-17T20:33:36Z","receivedAt":"2009-04-17T20:33:36Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Junio C Hamano schrieb:\n> @@ -674,6 +676,10 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)\n>  void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)\n>  {\n>  \tenum git_attr_direction old = direction;\n> +\n> +\tif (is_bare_repository() && new != GIT_ATTR_INDEX)\n> +\t\tdie(\"BUG: non-INDEX att direction in a bare repo\");\n\nIt's just a message that is probably never shown, but \"[...] attr\ndirection [...]\" (with r) would still look better.\n\nRené\n"},{"id":"111541","messageId":"49E9000D.1050808@lsrfire.ath.cx","threadId":"18890","inReplyTo":"1239848917-14399-1-git-send-email-gitster@pobox.com","subject":"[PATCH v2 1/5] archive tests: do not use .gitattributes in working directory","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-04-17T22:17:49Z","receivedAt":"2009-04-17T22:17:49Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"We are interested in using archive mostly from a bare repository, so it\nshould not add .gitattributes to the work tree.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t5000-tar-tree.sh |    9 +++++----\n 1 files changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh\nindex 7641e0d..abb41b0 100755\n--- a/t/t5000-tar-tree.sh\n+++ b/t/t5000-tar-tree.sh\n@@ -50,7 +50,7 @@ test_expect_success \\\n test_expect_success \\\n     'add ignored file' \\\n     'echo ignore me >a/ignored &&\n-     echo ignored export-ignore >.gitattributes'\n+     echo ignored export-ignore >.git/info/attributes'\n \n test_expect_success \\\n     'add files to repository' \\\n@@ -64,7 +64,7 @@ test_expect_success \\\n test_expect_success \\\n     'create bare clone' \\\n     'git clone --bare . bare.git &&\n-     cp .gitattributes bare.git/info/attributes'\n+     cp .git/info/attributes bare.git/info/attributes'\n \n test_expect_success \\\n     'remove ignored file' \\\n@@ -139,10 +139,11 @@ test_expect_success \\\n \n test_expect_success \\\n     'create archives with substfiles' \\\n-    'echo \"substfile?\" export-subst >a/.gitattributes &&\n+    'cp .git/info/attributes .git/info/attributes.before &&\n+     echo \"substfile?\" export-subst >>.git/info/attributes &&\n      git archive HEAD >f.tar &&\n      git archive --prefix=prefix/ HEAD >g.tar &&\n-     rm a/.gitattributes'\n+     mv .git/info/attributes.before .git/info/attributes'\n \n test_expect_success \\\n     'extract substfiles' \\\n-- \n1.6.3.rc0\n"},{"id":"111542","messageId":"49E90016.7060204@lsrfire.ath.cx","threadId":"18890","inReplyTo":"1239848917-14399-1-git-send-email-gitster@pobox.com","subject":"[PATCH v2 2/5] attr: add GIT_ATTR_INDEX \"direction\"","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-04-17T22:17:58Z","receivedAt":"2009-04-17T22:17:58Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"From: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n\nThis instructs attr mechanism, not to look into working .gitattributes\nat all. Needed by tools that does not handle working directory, such\nas \"git archive\".\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n attr.c |   12 +++++++++---\n attr.h |    3 ++-\n 2 files changed, 11 insertions(+), 4 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 43259e5..f1ca4f5 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -405,7 +405,7 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)\n \t\tif (!res)\n \t\t\tres = read_attr_from_file(path, macro_ok);\n \t}\n-\telse {\n+\telse if (direction == GIT_ATTR_CHECKIN) {\n \t\tres = read_attr_from_file(path, macro_ok);\n \t\tif (!res)\n \t\t\t/*\n@@ -415,6 +415,8 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)\n \t\t\t */\n \t\t\tres = read_attr_from_index(path, macro_ok);\n \t}\n+\telse\n+\t\tres = read_attr_from_index(path, macro_ok);\n \tif (!res)\n \t\tres = xcalloc(1, sizeof(*res));\n \treturn res;\n@@ -466,7 +468,7 @@ static void bootstrap_attr_stack(void)\n \t\telem->prev = attr_stack;\n \t\tattr_stack = elem;\n \n-\t\tif (!is_bare_repository()) {\n+\t\tif (!is_bare_repository() || direction == GIT_ATTR_INDEX) {\n \t\t\telem = read_attr(GITATTRIBUTES_FILE, 1);\n \t\t\telem->origin = strdup(\"\");\n \t\t\telem->prev = attr_stack;\n@@ -533,7 +535,7 @@ static void prepare_attr_stack(const char *path, int dirlen)\n \t/*\n \t * Read from parent directories and push them down\n \t */\n-\tif (!is_bare_repository()) {\n+\tif (!is_bare_repository() || direction == GIT_ATTR_INDEX) {\n \t\twhile (1) {\n \t\t\tchar *cp;\n \n@@ -674,6 +676,10 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)\n void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)\n {\n \tenum git_attr_direction old = direction;\n+\n+\tif (is_bare_repository() && new != GIT_ATTR_INDEX)\n+\t\tdie(\"BUG: non-INDEX attr direction in a bare repo\");\n+\n \tdirection = new;\n \tif (new != old)\n \t\tdrop_attr_stack();\ndiff --git a/attr.h b/attr.h\nindex 3a2f4ec..69b5767 100644\n--- a/attr.h\n+++ b/attr.h\n@@ -33,7 +33,8 @@ int git_checkattr(const char *path, int, struct git_attr_check *);\n \n enum git_attr_direction {\n \tGIT_ATTR_CHECKIN,\n-\tGIT_ATTR_CHECKOUT\n+\tGIT_ATTR_CHECKOUT,\n+\tGIT_ATTR_INDEX,\n };\n void git_attr_set_direction(enum git_attr_direction, struct index_state *);\n \n-- \n1.6.3.rc0\n"},{"id":"111543","messageId":"49E90019.9030606@lsrfire.ath.cx","threadId":"18890","inReplyTo":"1239848917-14399-1-git-send-email-gitster@pobox.com","subject":"[PATCH v2 3/5] unpack-trees: do not muck with attributes when we are not checking out","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-04-17T22:18:01Z","receivedAt":"2009-04-17T22:18:01Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"From: Junio C Hamano <gitster@pobox.com>\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n unpack-trees.c |    6 ++++--\n 1 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 6847c2d..e4eb8fa 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -87,7 +87,8 @@ static int check_updates(struct unpack_trees_options *o)\n \t\tcnt = 0;\n \t}\n \n-\tgit_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);\n+\tif (o->update)\n+\t\tgit_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);\n \tfor (i = 0; i < index->cache_nr; i++) {\n \t\tstruct cache_entry *ce = index->cache[i];\n \n@@ -112,7 +113,8 @@ static int check_updates(struct unpack_trees_options *o)\n \t\t}\n \t}\n \tstop_progress(&progress);\n-\tgit_attr_set_direction(GIT_ATTR_CHECKIN, NULL);\n+\tif (o->update)\n+\t\tgit_attr_set_direction(GIT_ATTR_CHECKIN, NULL);\n \treturn errs != 0;\n }\n \n-- \n1.6.3.rc0\n"},{"id":"111545","messageId":"49E9001D.9020209@lsrfire.ath.cx","threadId":"18890","inReplyTo":"1239848917-14399-1-git-send-email-gitster@pobox.com","subject":"[PATCH v2 4/5] archive: do not read .gitattributes in working directory","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-04-17T22:18:05Z","receivedAt":"2009-04-17T22:18:05Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"From: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n\nThe old behaviour still remains with --worktree-attributes, and it is\nalways on for the legacy \"git tar-tree\".\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\nChanges:\n\n   s/--fix-attributes/--worktree-attributes/g\n\n   Don't make tar-tree silently ignore --worktree-attributes; its\n   behaviour should not be changed any more.\n\n Documentation/git-archive.txt |    5 ++++-\n archive.c                     |   23 +++++++++++++++++++++++\n archive.h                     |    1 +\n builtin-tar-tree.c            |    9 ++++++++-\n 4 files changed, 36 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt\nindex c1adf59..bc132c8 100644\n--- a/Documentation/git-archive.txt\n+++ b/Documentation/git-archive.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n --------\n [verse]\n 'git archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]\n-\t      [--output=<file>]\n+\t      [--output=<file>] [--worktree-attributes]\n \t      [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>\n \t      [path...]\n \n@@ -51,6 +51,9 @@ OPTIONS\n --output=<file>::\n \tWrite the archive to <file> instead of stdout.\n \n+--worktree-attributes::\n+\tLook for attributes in .gitattributes in working directory too.\n+\n <extra>::\n \tThis can be any options that the archiver backend understands.\n \tSee next section.\ndiff --git a/archive.c b/archive.c\nindex 96b62d4..b2b90d3 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -4,6 +4,7 @@\n #include \"attr.h\"\n #include \"archive.h\"\n #include \"parse-options.h\"\n+#include \"unpack-trees.h\"\n \n static char const * const archive_usage[] = {\n \t\"git archive [options] <tree-ish> [path...]\",\n@@ -150,6 +151,8 @@ int write_archive_entries(struct archiver_args *args,\n \t\twrite_archive_entry_fn_t write_entry)\n {\n \tstruct archiver_context context;\n+\tstruct unpack_trees_options opts;\n+\tstruct tree_desc t;\n \tint err;\n \n \tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n@@ -168,6 +171,22 @@ int write_archive_entries(struct archiver_args *args,\n \tcontext.args = args;\n \tcontext.write_entry = write_entry;\n \n+\t/*\n+\t * Setup index and instruct attr to read index only\n+\t */\n+\tif (!args->worktree_attributes) {\n+\t\tmemset(&opts, 0, sizeof(opts));\n+\t\topts.index_only = 1;\n+\t\topts.head_idx = -1;\n+\t\topts.src_index = &the_index;\n+\t\topts.dst_index = &the_index;\n+\t\topts.fn = oneway_merge;\n+\t\tinit_tree_desc(&t, args->tree->buffer, args->tree->size);\n+\t\tif (unpack_trees(1, &t, &opts))\n+\t\t\treturn -1;\n+\t\tgit_attr_set_direction(GIT_ATTR_INDEX, &the_index);\n+\t}\n+\n \terr =  read_tree_recursive(args->tree, args->base, args->baselen, 0,\n \t\t\targs->pathspec, write_archive_entry, &context);\n \tif (err == READ_TREE_RECURSIVE)\n@@ -258,6 +277,7 @@ static int parse_archive_args(int argc, const char **argv,\n \tint verbose = 0;\n \tint i;\n \tint list = 0;\n+\tint worktree_attributes = 0;\n \tstruct option opts[] = {\n \t\tOPT_GROUP(\"\"),\n \t\tOPT_STRING(0, \"format\", &format, \"fmt\", \"archive format\"),\n@@ -265,6 +285,8 @@ static int parse_archive_args(int argc, const char **argv,\n \t\t\t\"prepend prefix to each pathname in the archive\"),\n \t\tOPT_STRING(0, \"output\", &output, \"file\",\n \t\t\t\"write the archive to this file\"),\n+\t\tOPT_BOOLEAN(0, \"worktree-attributes\", &worktree_attributes,\n+\t\t\t\"read .gitattributes in working directory\"),\n \t\tOPT__VERBOSE(&verbose),\n \t\tOPT__COMPR('0', &compression_level, \"store only\", 0),\n \t\tOPT__COMPR('1', &compression_level, \"compress faster\", 1),\n@@ -324,6 +346,7 @@ static int parse_archive_args(int argc, const char **argv,\n \targs->verbose = verbose;\n \targs->base = base;\n \targs->baselen = strlen(base);\n+\targs->worktree_attributes = worktree_attributes;\n \n \treturn argc;\n }\ndiff --git a/archive.h b/archive.h\nindex 0b15b35..038ac35 100644\n--- a/archive.h\n+++ b/archive.h\n@@ -10,6 +10,7 @@ struct archiver_args {\n \ttime_t time;\n \tconst char **pathspec;\n \tunsigned int verbose : 1;\n+\tunsigned int worktree_attributes : 1;\n \tint compression_level;\n };\n \ndiff --git a/builtin-tar-tree.c b/builtin-tar-tree.c\nindex 0713bca..1a5a2ed 100644\n--- a/builtin-tar-tree.c\n+++ b/builtin-tar-tree.c\n@@ -24,7 +24,7 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix)\n \t * \tgit archive --format-tar --prefix=basedir tree-ish\n \t */\n \tint i;\n-\tconst char **nargv = xcalloc(sizeof(*nargv), argc + 2);\n+\tconst char **nargv = xcalloc(sizeof(*nargv), argc + 3);\n \tchar *basedir_arg;\n \tint nargc = 0;\n \n@@ -36,6 +36,13 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix)\n \t\targv++;\n \t\targc--;\n \t}\n+\n+\t/*\n+\t * Because it's just a compatibility wrapper, tar-tree supports only\n+\t * the old behaviour of reading attributes from the work tree.\n+\t */\n+\tnargv[nargc++] = \"--worktree-attributes\";\n+\n \tswitch (argc) {\n \tdefault:\n \t\tusage(tar_tree_usage);\n-- \n1.6.3.rc0\n"},{"id":"111544","messageId":"49E90022.20700@lsrfire.ath.cx","threadId":"18890","inReplyTo":"1239848917-14399-1-git-send-email-gitster@pobox.com","subject":"[PATCH v2 5/5] archive test: attributes","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-04-17T22:18:10Z","receivedAt":"2009-04-17T22:18:10Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add a test script for all archive attributes and their handling in\nnormal and bare repositories.  export-ignore and export-subst are\ntested, as well as the effect of the option --worktree-attributes.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\nAny attribute related tests in t5000 can eventually be removed if\nthere is an equivalent test in t5001 -- and there should be.\n\n t/t5001-archive-attr.sh |   91 +++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 91 insertions(+), 0 deletions(-)\n create mode 100755 t/t5001-archive-attr.sh\n\ndiff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh\nnew file mode 100755\nindex 0000000..426b319\n--- /dev/null\n+++ b/t/t5001-archive-attr.sh\n@@ -0,0 +1,91 @@\n+#!/bin/sh\n+\n+test_description='git archive attribute tests'\n+\n+. ./test-lib.sh\n+\n+SUBSTFORMAT=%H%n\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+\techo ignored by tree >ignored-by-tree &&\n+\techo ignored-by-tree export-ignore >.gitattributes &&\n+\tgit add ignored-by-tree .gitattributes &&\n+\n+\techo ignored by worktree >ignored-by-worktree &&\n+\techo ignored-by-worktree export-ignore >.gitattributes &&\n+\tgit add ignored-by-worktree &&\n+\n+\tprintf \"A\\$Format:%s\\$O\" \"$SUBSTFORMAT\" >nosubstfile &&\n+\tprintf \"A\\$Format:%s\\$O\" \"$SUBSTFORMAT\" >substfile1 &&\n+\tprintf \"A not substituted O\" >substfile2 &&\n+\techo \"substfile?\" export-subst >>.git/info/attributes &&\n+\tgit add nosubstfile substfile1 substfile2 &&\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/ignored-by-tree\n+test_expect_exists\tarchive/ignored-by-worktree\n+\n+test_expect_success 'git archive with worktree attributes' '\n+\tgit archive --worktree-attributes HEAD >worktree.tar &&\n+\t(mkdir worktree && cd worktree && \"$TAR\" xf -) <worktree.tar\n+'\n+\n+test_expect_missing\tworktree/ignored\n+test_expect_exists\tworktree/ignored-by-tree\n+test_expect_missing\tworktree/ignored-by-worktree\n+\n+test_expect_success 'git archive vs. bare' '\n+\t(cd bare && git archive HEAD) >bare-archive.tar &&\n+\ttest_cmp archive.tar bare-archive.tar\n+'\n+\n+test_expect_success 'git archive with worktree attributes, bare' '\n+\t(cd bare && git archive --worktree-attributes HEAD) >bare-worktree.tar &&\n+\t(mkdir bare-worktree && cd bare-worktree && \"$TAR\" xf -) <bare-worktree.tar\n+'\n+\n+test_expect_missing\tbare-worktree/ignored\n+test_expect_exists\tbare-worktree/ignored-by-tree\n+test_expect_exists\tbare-worktree/ignored-by-worktree\n+\n+test_expect_success 'export-subst' '\n+\tgit log \"--pretty=format:A${SUBSTFORMAT}O\" HEAD >substfile1.expected &&\n+\ttest_cmp nosubstfile archive/nosubstfile &&\n+\ttest_cmp substfile1.expected archive/substfile1 &&\n+\ttest_cmp substfile2 archive/substfile2\n+'\n+\n+test_expect_success 'git tar-tree vs. git archive with worktree attributes' '\n+\tgit tar-tree HEAD >tar-tree.tar &&\n+\ttest_cmp worktree.tar tar-tree.tar\n+'\n+\n+test_expect_success 'git tar-tree vs. git archive with worktree attrs, bare' '\n+\t(cd bare && git tar-tree HEAD) >bare-tar-tree.tar &&\n+\ttest_cmp bare-worktree.tar bare-tar-tree.tar\n+'\n+\n+test_done\n-- \n1.6.3.rc0\n"}]}