{"thread":{"id":"42772","subject":"Git doesn't always add files to a commit (amend)","startedAt":"2016-07-04T13:50:50Z","lastAt":"2016-07-18T20:48:54Z","messageCount":30,"participants":["Yuri Kanivetsky","Duy Nguyen","Nguyễn Thái Ngọc Duy","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"290787","messageId":"CAMhVC3Y9iT9X=JbB5tguXm8MRX4v2fDEqMwrMuDR6TD2+2+HLQ@mail.gmail.com","threadId":"42772","inReplyTo":null,"subject":"Git doesn't always add files to a commit (amend)","fromName":"Yuri Kanivetsky","fromEmail":"yuri.kanivetsky@gmail.com","sentAt":"2016-07-04T13:50:38Z","receivedAt":"2016-07-04T13:50:50Z","isPatch":false,"sender":{"key":"yuri.kanivetsky@gmail.com","avatar":"https://gravatar.com/avatar/e4d91cf41e555a0c340222a1898c6320f51ad5ab2f9638282cc2412abb450648?d=mp&s=160"},"body":"Hi,\n\nWhen intent to add a directory is made (`git add -N`), and then\ncontents of any but the first file is staged, `git commit -v --amend`\ndoesn't add it to the commit, see for yourself:\n\n    #!/usr/bin/env bash\n    set -eu\n    rm -rf 1\n    mkdir 1\n    cd 1\n    git init\n    echo 1 > 1 && git add 1 && git commit -m 1\n    mkdir 2\n    echo 2/1 > 2/1\n    echo 2/2 > 2/2\n    git add -N 2\n    # git add 2/1   # this file is added\n    git add 2/2   # as opposed to this one\n    git commit --amend -m 1\n    git --no-pager log -p\n    git reset\n    git --no-pager status\n\nI'm running git-2.9.0.\n\nRegards,\nYuri\n"},{"id":"290794","messageId":"20160704154848.GA6857@duynguyen","threadId":"42772","inReplyTo":"CAMhVC3Y9iT9X=JbB5tguXm8MRX4v2fDEqMwrMuDR6TD2+2+HLQ@mail.gmail.com","subject":"Re: Git doesn't always add files to a commit (amend)","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-04T15:48:49Z","receivedAt":"2016-07-04T15:48:58Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Jul 04, 2016 at 04:50:38PM +0300, Yuri Kanivetsky wrote:\n> Hi,\n> \n> When intent to add a directory is made (`git add -N`), and then\n> contents of any but the first file is staged, `git commit -v --amend`\n> doesn't add it to the commit\n\nOops, a bug since 2012. Thanks for the report. I know what's wrong and\nwill prepare a proper patch in a couple of hours.\n\n> , see for yourself:\n> \n>     #!/usr/bin/env bash\n>     set -eu\n>     rm -rf 1\n>     mkdir 1\n>     cd 1\n>     git init\n>     echo 1 > 1 && git add 1 && git commit -m 1\n>     mkdir 2\n>     echo 2/1 > 2/1\n>     echo 2/2 > 2/2\n>     git add -N 2\n>     # git add 2/1   # this file is added\n>     git add 2/2   # as opposed to this one\n>     git commit --amend -m 1\n>     git --no-pager log -p\n>     git reset\n>     git --no-pager status\n> \n> I'm running git-2.9.0.\n> \n> Regards,\n> Yuri\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n"},{"id":"290798","messageId":"20160704174807.6578-1-pclouds@gmail.com","threadId":"42772","inReplyTo":"CAMhVC3Y9iT9X=JbB5tguXm8MRX4v2fDEqMwrMuDR6TD2+2+HLQ@mail.gmail.com","subject":"[PATCH] cache-tree.c: fix i-t-a check skipping directory updates sometimes","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-04T17:48:07Z","receivedAt":"2016-07-04T17:52:47Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Commit 3cf773e (cache-tree: fix writing cache-tree when CE_REMOVE is\npresent - 2012-12-16) skips i-t-a entries when building trees objects\nfrom the index. Unfortunately it may skip too much.\n\nThe code in question checks if an entry is an i-t-a one, then no tree\nentry will be written. But it does not take into account that\ndirectories can also be written with the same code. Suppose we have\nthis in the index.\n\n    a-file\n    subdir/file1\n    subdir/file2\n    subdir/file3\n    the-last-file\n\nWe write an entry for a-file as normal and move on to subdir/file1,\nwhere we realize the entry name for this level is simply just\n\"subdir\", write down an entry for \"subdir\" then jump three items ahead\nto the-last-file.\n\nThat is what happens normally when the first file in subdir is not an\ni-t-a entry. If subdir/file1 is an i-t-a, because of the broken\ncondition in this code, we still think \"subdir\" is an i-t-a file and\nnot writing \"subdir\" down and jump to the-last-file. The result tree\nnow only has two items: a-file and the-last-file. subdir should be\nthere too (even though it only records two sub-entries, file2 and\nfile3).\n\nIf the i-t-a entry is subdir/file2 or subdir/file3, this is not a\nproblem because we jump over them anyway. Which may explain why the\nbug is hidden for nearly four years.\n\nFix it by making sure we only skip i-t-a entries when the entry in\nquestion is actual an index entry, not a directory.\n\nReported-by: Yuri Kanivetsky <yuri.kanivetsky@gmail.com>\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache-tree.c          |  4 ++--\n t/t2203-add-intent.sh | 13 +++++++++++++\n 2 files changed, 15 insertions(+), 2 deletions(-)\n\ndiff --git a/cache-tree.c b/cache-tree.c\nindex ddf0cc9..c2676e8 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -319,7 +319,7 @@ static int update_one(struct cache_tree *it,\n \ti = 0;\n \twhile (i < entries) {\n \t\tconst struct cache_entry *ce = cache[i];\n-\t\tstruct cache_tree_sub *sub;\n+\t\tstruct cache_tree_sub *sub = NULL;\n \t\tconst char *path, *slash;\n \t\tint pathlen, entlen;\n \t\tconst unsigned char *sha1;\n@@ -375,7 +375,7 @@ static int update_one(struct cache_tree *it,\n \t\t * they are not part of generated trees. Invalidate up\n \t\t * to root to force cache-tree users to read elsewhere.\n \t\t */\n-\t\tif (ce_intent_to_add(ce)) {\n+\t\tif (!sub && ce_intent_to_add(ce)) {\n \t\t\tto_invalidate = 1;\n \t\t\tcontinue;\n \t\t}\ndiff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\nindex 2a4a749..12d701c 100755\n--- a/t/t2203-add-intent.sh\n+++ b/t/t2203-add-intent.sh\n@@ -82,5 +82,18 @@ test_expect_success 'cache-tree invalidates i-t-a paths' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n+\tgit init ita-in-dir &&\n+\t(\n+\t\tcd ita-in-dir &&\n+\t\tmkdir 2 &&\n+\t\ttouch 1 2/1 2/2 3 &&\n+\t\tgit add 1 2/2 3 &&\n+\t\tgit add -N 2/1 &&\n+\t\tgit commit -m comitted &&\n+\t\tgit ls-tree -r HEAD | grep 2/2\n+\t)\n+'\n+\n test_done\n \n-- \n2.8.2.537.g0965dd9\n\n"},{"id":"290891","messageId":"xmqqd1mqu0g6.fsf@gitster.mtv.corp.google.com","threadId":"42772","inReplyTo":"20160704174807.6578-1-pclouds@gmail.com","subject":"Re: [PATCH] cache-tree.c: fix i-t-a check skipping directory updates sometimes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-06T17:43:21Z","receivedAt":"2016-07-06T17:43:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> Commit 3cf773e (cache-tree: fix writing cache-tree when CE_REMOVE is\n> present - 2012-12-16) skips i-t-a entries when building trees objects\n> from the index. Unfortunately it may skip too much.\n>\n> The code in question checks if an entry is an i-t-a one, then no tree\n> entry will be written. But it does not take into account that\n> directories can also be written with the same code. Suppose we have\n> this in the index.\n>\n>     a-file\n>     subdir/file1\n>     subdir/file2\n>     subdir/file3\n>     the-last-file\n>\n> We write an entry for a-file as normal and move on to subdir/file1,\n> where we realize the entry name for this level is simply just\n> \"subdir\", write down an entry for \"subdir\" then jump three items ahead\n> to the-last-file.\n>\n> That is what happens normally when the first file in subdir is not an\n> i-t-a entry. If subdir/file1 is an i-t-a, because of the broken\n> condition in this code, we still think \"subdir\" is an i-t-a file and\n> not writing \"subdir\" down and jump to the-last-file. The result tree\n> now only has two items: a-file and the-last-file. subdir should be\n> there too (even though it only records two sub-entries, file2 and\n> file3).\n>\n> If the i-t-a entry is subdir/file2 or subdir/file3, this is not a\n> problem because we jump over them anyway. Which may explain why the\n> bug is hidden for nearly four years.\n>\n> Fix it by making sure we only skip i-t-a entries when the entry in\n> question is actual an index entry, not a directory.\n\nAha.  Good catch.\n\nHowever, this makes me wonder if subdir has only files all of which\nare i-t-a.  The resulting top-level tree object should not record\nsubdir/ as an empty (sub)directory in that case.  I do not see where\nyou are ensuring it in the patch below, though.\n\n>\n> Reported-by: Yuri Kanivetsky <yuri.kanivetsky@gmail.com>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  cache-tree.c          |  4 ++--\n>  t/t2203-add-intent.sh | 13 +++++++++++++\n>  2 files changed, 15 insertions(+), 2 deletions(-)\n>\n> diff --git a/cache-tree.c b/cache-tree.c\n> index ddf0cc9..c2676e8 100644\n> --- a/cache-tree.c\n> +++ b/cache-tree.c\n> @@ -319,7 +319,7 @@ static int update_one(struct cache_tree *it,\n>  \ti = 0;\n>  \twhile (i < entries) {\n>  \t\tconst struct cache_entry *ce = cache[i];\n> -\t\tstruct cache_tree_sub *sub;\n> +\t\tstruct cache_tree_sub *sub = NULL;\n>  \t\tconst char *path, *slash;\n>  \t\tint pathlen, entlen;\n>  \t\tconst unsigned char *sha1;\n> @@ -375,7 +375,7 @@ static int update_one(struct cache_tree *it,\n>  \t\t * they are not part of generated trees. Invalidate up\n>  \t\t * to root to force cache-tree users to read elsewhere.\n>  \t\t */\n> -\t\tif (ce_intent_to_add(ce)) {\n> +\t\tif (!sub && ce_intent_to_add(ce)) {\n>  \t\t\tto_invalidate = 1;\n>  \t\t\tcontinue;\n>  \t\t}\n> diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\n> index 2a4a749..12d701c 100755\n> --- a/t/t2203-add-intent.sh\n> +++ b/t/t2203-add-intent.sh\n> @@ -82,5 +82,18 @@ test_expect_success 'cache-tree invalidates i-t-a paths' '\n>  \ttest_cmp expect actual\n>  '\n>  \n> +test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n> +\tgit init ita-in-dir &&\n> +\t(\n> +\t\tcd ita-in-dir &&\n> +\t\tmkdir 2 &&\n> +\t\ttouch 1 2/1 2/2 3 &&\n> +\t\tgit add 1 2/2 3 &&\n> +\t\tgit add -N 2/1 &&\n> +\t\tgit commit -m comitted &&\n> +\t\tgit ls-tree -r HEAD | grep 2/2\n> +\t)\n> +'\n> +\n>  test_done\n"},{"id":"290893","messageId":"xmqq8txetzwp.fsf@gitster.mtv.corp.google.com","threadId":"42772","inReplyTo":"xmqqd1mqu0g6.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] cache-tree.c: fix i-t-a check skipping directory updates sometimes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-06T17:55:02Z","receivedAt":"2016-07-06T17:55:14Z","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> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>\n>> Fix it by making sure we only skip i-t-a entries when the entry in\n>> question is actual an index entry, not a directory.\n>\n> Aha.  Good catch.\n>\n> However, this makes me wonder if subdir has only files all of which\n> are i-t-a.  The resulting top-level tree object should not record\n> subdir/ as an empty (sub)directory in that case.  I do not see where\n> you are ensuring it in the patch below, though.\n\nHere is a fix-up to the test part to avoid \"touch\" if we are not\ninterested in timestamp, and to avoid \"git\" command in the upstream\nof a pipe, plus an additional test to help further bugfix to make\nsure a directory that becomes empty with this culling is not\nincluded in the end result.\n\nThanks for looking into this topic.\n\n t/t2203-add-intent.sh | 28 +++++++++++++++++++++++++---\n 1 file changed, 25 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\nindex 12d701c..1fc8d3f 100755\n--- a/t/t2203-add-intent.sh\n+++ b/t/t2203-add-intent.sh\n@@ -87,11 +87,33 @@ test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n \t(\n \t\tcd ita-in-dir &&\n \t\tmkdir 2 &&\n-\t\ttouch 1 2/1 2/2 3 &&\n+\t\tfor f in 1 2/1 2/2 3\n+\t\tdo\n+\t\t\techo \"$f\" >\"$f\"\n+\t\tdone &&\n \t\tgit add 1 2/2 3 &&\n \t\tgit add -N 2/1 &&\n-\t\tgit commit -m comitted &&\n-\t\tgit ls-tree -r HEAD | grep 2/2\n+\t\tgit commit -m committed &&\n+\t\tgit ls-tree -r HEAD >actual &&\n+\t\tgrep 2/2 actual\n+\t)\n+'\n+\n+test_expect_success 'cache-tree does skip dir that becomes empty' '\n+\trm -fr ita-in-dir &&\n+\tgit init ita-in-dir &&\n+\t(\n+\t\tcd ita-in-dir &&\n+\t\tmkdir 2 &&\n+\t\tfor f in 1 2/1 2/2 3\n+\t\tdo\n+\t\t\techo \"$f\" >\"$f\"\n+\t\tdone &&\n+\t\tgit add 1 3 &&\n+\t\tgit add -N 2/1 &&\n+\t\tgit commit -m committed &&\n+\t\tgit ls-tree HEAD >actual &&\n+\t\t! grep 2 actual\n \t)\n '\n \n"},{"id":"290899","messageId":"20160706184829.31825-2-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160706184829.31825-1-pclouds@gmail.com","subject":"[PATCH v2 1/2] cache-tree.c: fix i-t-a entry skipping directory updates sometimes","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-06T18:48:28Z","receivedAt":"2016-07-06T18:49:10Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Commit 3cf773e (cache-tree: fix writing cache-tree when CE_REMOVE is\npresent - 2012-12-16) skips i-t-a entries when building trees objects\nfrom the index. Unfortunately it may skip too much.\n\nThe code in question checks if an entry is an i-t-a one, then no tree\nentry will be written. But it does not take into account that\ndirectories can also be written with the same code. Suppose we have\nthis in the index.\n\n    a-file\n    subdir/file1\n    subdir/file2\n    subdir/file3\n    the-last-file\n\nWe write an entry for a-file as normal and move on to subdir/file1,\nwhere we realize the entry name for this level is simply just\n\"subdir\", write down an entry for \"subdir\" then jump three items ahead\nto the-last-file.\n\nThat is what happens normally when the first file in subdir is not an\ni-t-a entry. If subdir/file1 is an i-t-a, because of the broken\ncondition in this code, we still think \"subdir\" is an i-t-a file and\nnot writing \"subdir\" down and jump to the-last-file. The result tree\nnow only has two items: a-file and the-last-file. subdir should be\nthere too (even though it only records two sub-entries, file2 and\nfile3).\n\nIf the i-t-a entry is subdir/file2 or subdir/file3, this is not a\nproblem because we jump over them anyway. Which may explain why the\nbug is hidden for nearly four years.\n\nFix it by making sure we only skip i-t-a entries when the entry in\nquestion is actual an index entry, not a directory.\n\nReported-by: Yuri Kanivetsky <yuri.kanivetsky@gmail.com>\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache-tree.c          |  4 ++--\n t/t2203-add-intent.sh | 17 +++++++++++++++++\n 2 files changed, 19 insertions(+), 2 deletions(-)\n\ndiff --git a/cache-tree.c b/cache-tree.c\nindex ddf0cc9..c2676e8 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -319,7 +319,7 @@ static int update_one(struct cache_tree *it,\n \ti = 0;\n \twhile (i < entries) {\n \t\tconst struct cache_entry *ce = cache[i];\n-\t\tstruct cache_tree_sub *sub;\n+\t\tstruct cache_tree_sub *sub = NULL;\n \t\tconst char *path, *slash;\n \t\tint pathlen, entlen;\n \t\tconst unsigned char *sha1;\n@@ -375,7 +375,7 @@ static int update_one(struct cache_tree *it,\n \t\t * they are not part of generated trees. Invalidate up\n \t\t * to root to force cache-tree users to read elsewhere.\n \t\t */\n-\t\tif (ce_intent_to_add(ce)) {\n+\t\tif (!sub && ce_intent_to_add(ce)) {\n \t\t\tto_invalidate = 1;\n \t\t\tcontinue;\n \t\t}\ndiff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\nindex 2a4a749..24aed2e 100755\n--- a/t/t2203-add-intent.sh\n+++ b/t/t2203-add-intent.sh\n@@ -82,5 +82,22 @@ test_expect_success 'cache-tree invalidates i-t-a paths' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n+\tgit init ita-in-dir &&\n+\t(\n+\t\tcd ita-in-dir &&\n+\t\tmkdir 2 &&\n+\t\tfor f in 1 2/1 2/2 3\n+\t\tdo\n+\t\t\techo \"$f\" >\"$f\"\n+\t\tdone &&\n+\t\tgit add 1 2/2 3 &&\n+\t\tgit add -N 2/1 &&\n+\t\tgit commit -m committed &&\n+\t\tgit ls-tree -r HEAD >actual &&\n+\t\tgrep 2/2 actual\n+\t)\n+'\n+\n test_done\n \n-- \n2.8.2.537.g0965dd9\n\n"},{"id":"290900","messageId":"20160706184829.31825-1-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160704174807.6578-1-pclouds@gmail.com","subject":"[PATCH v2 0/2] cache-tree building fix in the presence of ita entries","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-06T18:48:27Z","receivedAt":"2016-07-06T18:49:15Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"1/2 is the same as before with some test fixups from Junio.\n\n2/2 fixes the empty tree generation found by Junio. I split it out\nbecause the commit message in 1/2 is already long. And because it can\nhappen even without 1/2 (i.e. yet another bug :( though really hard to\nhappen).\n\nSuppose a/b/c contains all i-t-a entries. Without 1/2, we skip adding\n'c' to the tree object 'a/b' (by luck). But if 'a/b' has _nothing_\nelse but 'a/b/c' then again we will have an empty tree object, which\nshould not be added in 'a'. It's a cascading effect all the way up.\n\nNguyễn Thái Ngọc Duy (2):\n  cache-tree.c: fix i-t-a entry skipping directory updates sometimes\n  cache-tree: do not generate empty trees as a result of all i-t-a subentries\n\n cache-tree.c          | 20 ++++++++++++++++++--\n t/t2203-add-intent.sh | 29 +++++++++++++++++++++++++++++\n 2 files changed, 47 insertions(+), 2 deletions(-)\n\n-- \n2.8.2.537.g0965dd9\n\n"},{"id":"290901","messageId":"20160706184829.31825-3-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160706184829.31825-1-pclouds@gmail.com","subject":"[PATCH v2 2/2] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-06T18:48:29Z","receivedAt":"2016-07-06T18:49:18Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"If a subdirectory contains nothing but i-t-a entries, we generate an\nempty tree object and add it to its parent tree. Which is wrong. Such\na subdirectory should not be added. We ignore i-t-a files _and_\ndirectories.\n\nNote that this has a cascading effect. If subdir 'a/b/c' contains\nnothing but i-t-a entries, we ignore it. But then if 'a/b' contains\nonly (the non-existing) 'a/b/c', then we should ignore 'a/b' while\nbuilding 'a' too. And it goes all the way up to top directory.\n\nNoticed-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache-tree.c          | 16 ++++++++++++++++\n t/t2203-add-intent.sh | 12 ++++++++++++\n 2 files changed, 28 insertions(+)\n\ndiff --git a/cache-tree.c b/cache-tree.c\nindex c2676e8..75e73d7 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -380,6 +380,13 @@ static int update_one(struct cache_tree *it,\n \t\t\tcontinue;\n \t\t}\n \n+\t\t/*\n+\t\t * \"sub\" can be an empty tree if all subentries are i-t-a.\n+\t\t */\n+\t\tif (sub && sub->cache_tree->entry_count < 0 &&\n+\t\t    !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))\n+\t\t\tcontinue;\n+\n \t\tstrbuf_grow(&buffer, entlen + 100);\n \t\tstrbuf_addf(&buffer, \"%o %.*s%c\", mode, entlen, path + baselen, '\\0');\n \t\tstrbuf_add(&buffer, sha1, 20);\n@@ -426,6 +433,15 @@ int cache_tree_update(struct index_state *istate, int flags)\n \ti = update_one(it, cache, entries, \"\", 0, &skip, flags);\n \tif (i < 0)\n \t\treturn i;\n+\t/*\n+\t * Top dir can become empty if all entries are i-t-a (even\n+\t * from subdirs). Note that we do allow to create an empty\n+\t * tree from an empty index. Only error when an empty tree is\n+\t * a result of the i-t-a thing.\n+\t */\n+\tif (it->entry_count < 0 &&\n+\t    !hashcmp(it->sha1, EMPTY_TREE_SHA1_BIN))\n+\t\treturn error(_(\"cannot build a tree from just intent-to-add entries\"));\n \tistate->cache_changed |= CACHE_TREE_CHANGED;\n \treturn 0;\n }\ndiff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\nindex 24aed2e..a19f06b 100755\n--- a/t/t2203-add-intent.sh\n+++ b/t/t2203-add-intent.sh\n@@ -99,5 +99,17 @@ test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n \t)\n '\n \n+test_expect_success 'cache-tree does skip dir that becomes empty' '\n+\trm -fr ita-in-dir &&\n+\tgit init ita-in-dir &&\n+\t(\n+\t\tcd ita-in-dir &&\n+\t\tmkdir -p 1/2/3 &&\n+\t\techo 4 >1/2/3/4 &&\n+\t\tgit add -N 1/2/3/4 &&\n+\t\ttest_must_fail git commit -m committed\n+\t)\n+'\n+\n test_done\n \n-- \n2.8.2.537.g0965dd9\n\n"},{"id":"290906","messageId":"xmqqeg76sh44.fsf@gitster.mtv.corp.google.com","threadId":"42772","inReplyTo":"20160706184829.31825-3-pclouds@gmail.com","subject":"Re: [PATCH v2 2/2] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-06T19:26:19Z","receivedAt":"2016-07-06T19:26:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> @@ -426,6 +433,15 @@ int cache_tree_update(struct index_state *istate, int flags)\n>  \ti = update_one(it, cache, entries, \"\", 0, &skip, flags);\n>  \tif (i < 0)\n>  \t\treturn i;\n> +\t/*\n> +\t * Top dir can become empty if all entries are i-t-a (even\n> +\t * from subdirs). Note that we do allow to create an empty\n> +\t * tree from an empty index. Only error when an empty tree is\n> +\t * a result of the i-t-a thing.\n> +\t */\n> +\tif (it->entry_count < 0 &&\n> +\t    !hashcmp(it->sha1, EMPTY_TREE_SHA1_BIN))\n> +\t\treturn error(_(\"cannot build a tree from just intent-to-add entries\"));\n\nThe test would not let you tell between the two possible ways the\nlast step \"git commit\" fails.\n\nDid it fail due to the protection this change adds (i.e. you should\nbe checking if \"git write-tree\" fails if that is the case we want to\ncover), or did it fail because you recorded an empty tree as the\nroot commit without giving the --allow-empty option?\n\nIn any case, I am not sure about the logic in the comment, either.\n\"git commit --allow-empty\" should be able to create a new commit\nwithout any files in it, no?\n\n>  \tistate->cache_changed |= CACHE_TREE_CHANGED;\n>  \treturn 0;\n>  }\n> diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\n> index 24aed2e..a19f06b 100755\n> --- a/t/t2203-add-intent.sh\n> +++ b/t/t2203-add-intent.sh\n> @@ -99,5 +99,17 @@ test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n>  \t)\n>  '\n>  \n> +test_expect_success 'cache-tree does skip dir that becomes empty' '\n> +\trm -fr ita-in-dir &&\n> +\tgit init ita-in-dir &&\n> +\t(\n> +\t\tcd ita-in-dir &&\n> +\t\tmkdir -p 1/2/3 &&\n> +\t\techo 4 >1/2/3/4 &&\n> +\t\tgit add -N 1/2/3/4 &&\n> +\t\ttest_must_fail git commit -m committed\n> +\t)\n> +'\n> +\n>  test_done\n"},{"id":"290968","messageId":"20160707171237.GA31445@duynguyen","threadId":"42772","inReplyTo":"xmqqeg76sh44.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v2 2/2] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-07T17:12:37Z","receivedAt":"2016-07-07T18:13:12Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Jul 06, 2016 at 12:26:19PM -0700, Junio C Hamano wrote:\n> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n> \n> > @@ -426,6 +433,15 @@ int cache_tree_update(struct index_state *istate, int flags)\n> >  \ti = update_one(it, cache, entries, \"\", 0, &skip, flags);\n> >  \tif (i < 0)\n> >  \t\treturn i;\n> > +\t/*\n> > +\t * Top dir can become empty if all entries are i-t-a (even\n> > +\t * from subdirs). Note that we do allow to create an empty\n> > +\t * tree from an empty index. Only error when an empty tree is\n> > +\t * a result of the i-t-a thing.\n> > +\t */\n> > +\tif (it->entry_count < 0 &&\n> > +\t    !hashcmp(it->sha1, EMPTY_TREE_SHA1_BIN))\n> > +\t\treturn error(_(\"cannot build a tree from just intent-to-add entries\"));\n> \n> The test would not let you tell between the two possible ways the\n> last step \"git commit\" fails.\n> \n> Did it fail due to the protection this change adds (i.e. you should\n> be checking if \"git write-tree\" fails if that is the case we want to\n> cover), or did it fail because you recorded an empty tree as the\n> root commit without giving the --allow-empty option?\n> \n> In any case, I am not sure about the logic in the comment, either.\n> \"git commit --allow-empty\" should be able to create a new commit\n> without any files in it, no?\n\nYou're right. If an empty index can produce an empty tree, then an\nindex full of i-t-a entries should also be able to produce an empty\ntree.\n\ngit-commit not failing when --allow-empty is not given is another\n(known) problem, where it miscounts the number of real index entries.\nIt's not right to \"fix\" it in here.\n\nI'll deal with that separately. Let's focus on cache-tree only this\ntime. So how about this on top?\n\n-- 8< --\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 75e73d7..2d50640 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -433,15 +433,6 @@ int cache_tree_update(struct index_state *istate, int flags)\n \ti = update_one(it, cache, entries, \"\", 0, &skip, flags);\n \tif (i < 0)\n \t\treturn i;\n-\t/*\n-\t * Top dir can become empty if all entries are i-t-a (even\n-\t * from subdirs). Note that we do allow to create an empty\n-\t * tree from an empty index. Only error when an empty tree is\n-\t * a result of the i-t-a thing.\n-\t */\n-\tif (it->entry_count < 0 &&\n-\t    !hashcmp(it->sha1, EMPTY_TREE_SHA1_BIN))\n-\t\treturn error(_(\"cannot build a tree from just intent-to-add entries\"));\n \tistate->cache_changed |= CACHE_TREE_CHANGED;\n \treturn 0;\n }\ndiff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\nindex a19f06b..1a01279 100755\n--- a/t/t2203-add-intent.sh\n+++ b/t/t2203-add-intent.sh\n@@ -104,10 +104,17 @@ test_expect_success 'cache-tree does skip dir that becomes empty' '\n \tgit init ita-in-dir &&\n \t(\n \t\tcd ita-in-dir &&\n+\t\techo ground >ground &&\n+\t\tgit add ground &&\n \t\tmkdir -p 1/2/3 &&\n \t\techo 4 >1/2/3/4 &&\n \t\tgit add -N 1/2/3/4 &&\n-\t\ttest_must_fail git commit -m committed\n+\t\tgit commit -m committed &&\n+\t\tgit ls-tree -r HEAD >actual &&\n+\t\tcat >expected <<\\EOF &&\n+100644 blob b649b43b0708f5604ac912f5a15f7da2bad51a1b\tground\n+EOF\n+\t\ttest_cmp expected actual\n \t)\n '\n \n-- 8< --\n\n> > +test_expect_success 'cache-tree does skip dir that becomes empty' '\n> > +\trm -fr ita-in-dir &&\n> > +\tgit init ita-in-dir &&\n> > +\t(\n> > +\t\tcd ita-in-dir &&\n> > +\t\tmkdir -p 1/2/3 &&\n> > +\t\techo 4 >1/2/3/4 &&\n> > +\t\tgit add -N 1/2/3/4 &&\n> > +\t\ttest_must_fail git commit -m committed\n> > +\t)\n> > +'\n> > +\n> >  test_done\n"},{"id":"290971","messageId":"xmqqmvltp9f9.fsf@gitster.mtv.corp.google.com","threadId":"42772","inReplyTo":"20160707171237.GA31445@duynguyen","subject":"Re: [PATCH v2 2/2] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-07T18:52:58Z","receivedAt":"2016-07-07T18:54:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> I'll deal with that separately. Let's focus on cache-tree only this\n> time. So how about this on top?\n\nI was hoping that you would limit the scope of the test to check if\nwrite-tree does the right thing.  i.e. not test \"git commit\", but\ntest \"git write-tree\".\n\n"},{"id":"291031","messageId":"20160708153930.GA19448@duynguyen","threadId":"42772","inReplyTo":"xmqqmvltp9f9.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v2 2/2] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-08T15:39:30Z","receivedAt":"2016-07-08T15:39:39Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Jul 07, 2016 at 11:52:58AM -0700, Junio C Hamano wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n> \n> > I'll deal with that separately. Let's focus on cache-tree only this\n> > time. So how about this on top?\n> \n> I was hoping that you would limit the scope of the test to check if\n> write-tree does the right thing.  i.e. not test \"git commit\", but\n> test \"git write-tree\".\n> \n\nYeah that's better. So the squash patch is something like this\n\n-- 8< --\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 75e73d7..2d50640 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -433,15 +433,6 @@ int cache_tree_update(struct index_state *istate, int flags)\n \ti = update_one(it, cache, entries, \"\", 0, &skip, flags);\n \tif (i < 0)\n \t\treturn i;\n-\t/*\n-\t * Top dir can become empty if all entries are i-t-a (even\n-\t * from subdirs). Note that we do allow to create an empty\n-\t * tree from an empty index. Only error when an empty tree is\n-\t * a result of the i-t-a thing.\n-\t */\n-\tif (it->entry_count < 0 &&\n-\t    !hashcmp(it->sha1, EMPTY_TREE_SHA1_BIN))\n-\t\treturn error(_(\"cannot build a tree from just intent-to-add entries\"));\n \tistate->cache_changed |= CACHE_TREE_CHANGED;\n \treturn 0;\n }\ndiff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\nindex a19f06b..80880b7 100755\n--- a/t/t2203-add-intent.sh\n+++ b/t/t2203-add-intent.sh\n@@ -107,7 +107,9 @@ test_expect_success 'cache-tree does skip dir that becomes empty' '\n \t\tmkdir -p 1/2/3 &&\n \t\techo 4 >1/2/3/4 &&\n \t\tgit add -N 1/2/3/4 &&\n-\t\ttest_must_fail git commit -m committed\n+\t\tgit write-tree >actual &&\n+\t\techo 4b825dc642cb6eb9a060e54bf8d69288fbee4904 >empty-tree &&\n+\t\ttest_cmp empty-tree actual\n \t)\n '\n \n-- 8< --\n--\nDuy\n"},{"id":"291032","messageId":"xmqqwpkwm8ho.fsf@gitster.mtv.corp.google.com","threadId":"42772","inReplyTo":"20160708153930.GA19448@duynguyen","subject":"Re: [PATCH v2 2/2] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-08T15:53:39Z","receivedAt":"2016-07-08T15:54:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> Yeah that's better. So the squash patch is something like this\n\nRather...\n\n> diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\n> index a19f06b..80880b7 100755\n> --- a/t/t2203-add-intent.sh\n> +++ b/t/t2203-add-intent.sh\n> @@ -107,7 +107,9 @@ test_expect_success 'cache-tree does skip dir that becomes empty' '\n>  \t\tmkdir -p 1/2/3 &&\n>  \t\techo 4 >1/2/3/4 &&\n>  \t\tgit add -N 1/2/3/4 &&\n> -\t\ttest_must_fail git commit -m committed\n> +\t\tgit write-tree >actual &&\n> +\t\techo 4b825dc642cb6eb9a060e54bf8d69288fbee4904 >empty-tree &&\n> +\t\ttest_cmp empty-tree actual\n\n\twritten=$(git write-tree) &&\n        git ls-tree \"$written\" >actual &&\n        ! grep 1 actual\n\nThat way, we have one less thing to worry about when the hash\nfunction changes in the future.  You may want to rename 1/2/3\nto something more readable (e.g. dir/2/3) and grep for \"dir\"\ninstead, though.\n\n"},{"id":"291036","messageId":"CACsJy8DkXuszC2f=TVzzXPKz2zvyRKFOVqXRoZGbwfo+oUMP7Q@mail.gmail.com","threadId":"42772","inReplyTo":"xmqqwpkwm8ho.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v2 2/2] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-08T16:36:20Z","receivedAt":"2016-07-08T16:38:11Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Fri, Jul 8, 2016 at 5:53 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n>\n>> Yeah that's better. So the squash patch is something like this\n>\n> Rather...\n>\n>> diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\n>> index a19f06b..80880b7 100755\n>> --- a/t/t2203-add-intent.sh\n>> +++ b/t/t2203-add-intent.sh\n>> @@ -107,7 +107,9 @@ test_expect_success 'cache-tree does skip dir that becomes empty' '\n>>               mkdir -p 1/2/3 &&\n>>               echo 4 >1/2/3/4 &&\n>>               git add -N 1/2/3/4 &&\n>> -             test_must_fail git commit -m committed\n>> +             git write-tree >actual &&\n>> +             echo 4b825dc642cb6eb9a060e54bf8d69288fbee4904 >empty-tree &&\n>> +             test_cmp empty-tree actual\n>\n>         written=$(git write-tree) &&\n>         git ls-tree \"$written\" >actual &&\n>         ! grep 1 actual\n>\n> That way, we have one less thing to worry about when the hash\n> function changes in the future.  You may want to rename 1/2/3\n> to something more readable (e.g. dir/2/3) and grep for \"dir\"\n> instead, though.\n\nI thought about that too, then did a grep which showed empty sha1 tree\nwas used elsewhere. And thought of sending a patch to define\n$EMPTY_SHA1 in test-lib-functions.sh or somewhere so we don't hard\ncode it everywhere, but I didn't. But yeah ls-tree works. The last\nline could be test_must_be_empty actual (a bit stricter than grep 1)\n-- \nDuy\n"},{"id":"291042","messageId":"xmqq60sgm4bs.fsf@gitster.mtv.corp.google.com","threadId":"42772","inReplyTo":"CACsJy8DkXuszC2f=TVzzXPKz2zvyRKFOVqXRoZGbwfo+oUMP7Q@mail.gmail.com","subject":"Re: [PATCH v2 2/2] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-08T17:23:35Z","receivedAt":"2016-07-08T17:23:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> I thought about that too, then did a grep which showed empty sha1 tree\n> was used elsewhere. And thought of sending a patch to define\n> $EMPTY_SHA1 in test-lib-functions.sh or somewhere so we don't hard\n> code it everywhere, but I didn't. But yeah ls-tree works. The last\n> line could be test_must_be_empty actual (a bit stricter than grep 1)\n\nI am OK if you moved $EMPTY_TREE from t4010 to test-lib.sh, added\n$EMPTY_BLOB next to it while at it, and remove their definition from\nt1501.\n\nt0000, t1100, t3404, t4054 and t5504 have references to 4b825dc64\nthat may want to be updated to use $EMPTY_TREE.\n\nt5308, t7011, and t7012 defines HI_SHA1 and NULL_SHA1, which may\nwant to be updated to use $EMPTY_BLOB.\n\nt/lib-pack.sh has one instance of 69de29bb2d1d that may want to be\nupdated to use $EMPTY_BLOB.\n"},{"id":"291086","messageId":"20160709052356.30570-1-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160706184829.31825-1-pclouds@gmail.com","subject":"[PATCH v3 0/4] cache-tree building fix in the presence of ita entries","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-09T05:23:52Z","receivedAt":"2016-07-09T05:24:29Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"v3 fixes 2/2 (which is 4/4 now), allowing cache-tree to generate an\nempty tree if the index contains nothing but i-t-a entries.\n\nSince empty tree SHA-1 is involved and we don't want to make it harder\nto move away from SHA-1 in future, 1/2 and 2/2 are added to keep SHA-1\nfor empty tree (and blob while we're at it) in one place.\n\nNote that I didn't make lib-pack.sh and t5308 use $_EMPTY_BLOB because\nthe actual SHA-1 characters matter (t5308) and I'm not so sure about\nvariable expansion in the case/esac block and not wanting to check all\nthe shells out there again (lib-pack.sh).\n\n\nNguyễn Thái Ngọc Duy (4):\n  test-lib.sh: introduce and use $_EMPTY_TREE\n  test-lib.sh: introduce and use $_EMPTY_BLOB\n  cache-tree.c: fix i-t-a entry skipping directory updates sometimes\n  cache-tree: do not generate empty trees as a result of all i-t-a subentries\n\n cache-tree.c                         | 11 +++++++++--\n t/t0000-basic.sh                     |  2 +-\n t/t1011-read-tree-sparse-checkout.sh |  8 ++++----\n t/t1100-commit-tree-options.sh       |  2 +-\n t/t1700-split-index.sh               | 24 ++++++++++++------------\n t/t2203-add-intent.sh                | 31 +++++++++++++++++++++++++++++++\n t/t3102-ls-tree-wildcards.sh         |  8 ++++----\n t/t4010-diff-pathspec.sh             |  6 ++----\n t/t4054-diff-bogus-tree.sh           | 10 ++++------\n t/t5504-fetch-receive-strict.sh      |  4 ++--\n t/t7011-skip-worktree-reading.sh     | 12 +++++-------\n t/t7012-skip-worktree-writing.sh     | 10 ++++------\n t/t7063-status-untracked-cache.sh    |  6 +++---\n t/t7508-status.sh                    |  2 +-\n t/test-lib.sh                        |  5 ++++-\n 15 files changed, 87 insertions(+), 54 deletions(-)\n\n-- \n2.8.2.537.g0965dd9\n\n"},{"id":"291087","messageId":"20160709052356.30570-3-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160709052356.30570-1-pclouds@gmail.com","subject":"[PATCH v3 2/4] test-lib.sh: introduce and use $_EMPTY_BLOB","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-09T05:23:54Z","receivedAt":"2016-07-09T05:24:33Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Similar to $_EMPTY_TREE this makes it easier to recognize this special\nSHA-1 and change hash later.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n t/t1011-read-tree-sparse-checkout.sh |  8 ++++----\n t/t1700-split-index.sh               | 24 ++++++++++++------------\n t/t3102-ls-tree-wildcards.sh         |  8 ++++----\n t/t7011-skip-worktree-reading.sh     | 12 +++++-------\n t/t7012-skip-worktree-writing.sh     | 10 ++++------\n t/t7063-status-untracked-cache.sh    |  6 +++---\n t/t7508-status.sh                    |  2 +-\n t/test-lib.sh                        |  3 ++-\n 8 files changed, 35 insertions(+), 38 deletions(-)\n\ndiff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh\nindex 0c74bee..21cfa2e 100755\n--- a/t/t1011-read-tree-sparse-checkout.sh\n+++ b/t/t1011-read-tree-sparse-checkout.sh\n@@ -15,11 +15,11 @@ test_description='sparse checkout tests\n . \"$TEST_DIRECTORY\"/lib-read-tree.sh\n \n test_expect_success 'setup' '\n-\tcat >expected <<-\\EOF &&\n+\tcat >expected <<-EOF &&\n \t100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0\tinit.t\n-\t100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tsub/added\n-\t100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tsub/addedtoo\n-\t100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tsubsub/added\n+\t100644 $_EMPTY_BLOB 0\tsub/added\n+\t100644 $_EMPTY_BLOB 0\tsub/addedtoo\n+\t100644 $_EMPTY_BLOB 0\tsubsub/added\n \tEOF\n \tcat >expected.swt <<-\\EOF &&\n \tH init.t\ndiff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh\nindex 8aef49f..305f210 100755\n--- a/t/t1700-split-index.sh\n+++ b/t/t1700-split-index.sh\n@@ -33,14 +33,14 @@ test_expect_success 'add one file' '\n \tgit update-index --add one &&\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $_EMPTY_BLOB 0\tone\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \n \ttest-dump-split-index .git/index | sed \"/^own/d\" >actual &&\n \tcat >expect <<EOF &&\n base $base\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $_EMPTY_BLOB 0\tone\n replacements:\n deletions:\n EOF\n@@ -51,7 +51,7 @@ test_expect_success 'disable split index' '\n \tgit update-index --no-split-index &&\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $_EMPTY_BLOB 0\tone\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \n@@ -67,7 +67,7 @@ test_expect_success 'enable split index again, \"one\" now belongs to base index\"'\n \tgit update-index --split-index &&\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $_EMPTY_BLOB 0\tone\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \n@@ -105,7 +105,7 @@ test_expect_success 'add another file, which stays index' '\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0\tone\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\ttwo\n+100644 $_EMPTY_BLOB 0\ttwo\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \n@@ -113,7 +113,7 @@ EOF\n \tq_to_tab >expect <<EOF &&\n $BASE\n 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\ttwo\n+100644 $_EMPTY_BLOB 0\ttwo\n replacements: 0\n deletions:\n EOF\n@@ -159,14 +159,14 @@ test_expect_success 'add original file back' '\n \tgit update-index --add one &&\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $_EMPTY_BLOB 0\tone\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \n \ttest-dump-split-index .git/index | sed \"/^own/d\" >actual &&\n \tcat >expect <<EOF &&\n $BASE\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $_EMPTY_BLOB 0\tone\n replacements:\n deletions: 0\n EOF\n@@ -178,8 +178,8 @@ test_expect_success 'add new file' '\n \tgit update-index --add two &&\n \tgit ls-files --stage >actual &&\n \tcat >expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\ttwo\n+100644 $_EMPTY_BLOB 0\tone\n+100644 $_EMPTY_BLOB 0\ttwo\n EOF\n \ttest_cmp expect actual\n '\n@@ -188,8 +188,8 @@ test_expect_success 'unify index, two files remain' '\n \tgit update-index --no-split-index &&\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\ttwo\n+100644 $_EMPTY_BLOB 0\tone\n+100644 $_EMPTY_BLOB 0\ttwo\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \ndiff --git a/t/t3102-ls-tree-wildcards.sh b/t/t3102-ls-tree-wildcards.sh\nindex 4d4b02e..5cf84fa 100755\n--- a/t/t3102-ls-tree-wildcards.sh\n+++ b/t/t3102-ls-tree-wildcards.sh\n@@ -12,16 +12,16 @@ test_expect_success 'setup' '\n '\n \n test_expect_success 'ls-tree a[a] matches literally' '\n-\tcat >expect <<-\\EOF &&\n-\t100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\ta[a]/three\n+\tcat >expect <<-EOF &&\n+\t100644 blob $_EMPTY_BLOB\ta[a]/three\n \tEOF\n \tgit ls-tree -r HEAD \"a[a]\" >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'ls-tree outside prefix' '\n-\tcat >expect <<-\\EOF &&\n-\t100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\t../a[a]/three\n+\tcat >expect <<-EOF &&\n+\t100644 blob $_EMPTY_BLOB\t../a[a]/three\n \tEOF\n \t( cd aa && git ls-tree -r HEAD \"../a[a]\"; ) >actual &&\n \ttest_cmp expect actual\ndiff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh\nindex 88d60c1..7fe0c9f 100755\n--- a/t/t7011-skip-worktree-reading.sh\n+++ b/t/t7011-skip-worktree-reading.sh\n@@ -23,17 +23,15 @@ S sub/1\n H sub/2\n EOF\n \n-NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n-\n setup_absent() {\n \ttest -f 1 && rm 1\n \tgit update-index --remove 1 &&\n-\tgit update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&\n+\tgit update-index --add --cacheinfo 100644 $_EMPTY_BLOB 1 &&\n \tgit update-index --skip-worktree 1\n }\n \n test_absent() {\n-\techo \"100644 $NULL_SHA1 0\t1\" > expected &&\n+\techo \"100644 $_EMPTY_BLOB 0\t1\" > expected &&\n \tgit ls-files --stage 1 > result &&\n \ttest_cmp expected result &&\n \ttest ! -f 1\n@@ -42,12 +40,12 @@ test_absent() {\n setup_dirty() {\n \tgit update-index --force-remove 1 &&\n \techo dirty > 1 &&\n-\tgit update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&\n+\tgit update-index --add --cacheinfo 100644 $_EMPTY_BLOB 1 &&\n \tgit update-index --skip-worktree 1\n }\n \n test_dirty() {\n-\techo \"100644 $NULL_SHA1 0\t1\" > expected &&\n+\techo \"100644 $_EMPTY_BLOB 0\t1\" > expected &&\n \tgit ls-files --stage 1 > result &&\n \ttest_cmp expected result &&\n \techo dirty > expected\n@@ -120,7 +118,7 @@ test_expect_success 'grep with skip-worktree file' '\n \ttest \"$(git grep --no-ext-grep test)\" = \"1:test\"\n '\n \n-echo \":000000 100644 $_z40 $NULL_SHA1 A\t1\" > expected\n+echo \":000000 100644 $_z40 $_EMPTY_BLOB A\t1\" > expected\n test_expect_success 'diff-index does not examine skip-worktree absent entries' '\n \tsetup_absent &&\n \tgit diff-index HEAD -- 1 > result &&\ndiff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh\nindex 9ceaa40..003e36f 100755\n--- a/t/t7012-skip-worktree-writing.sh\n+++ b/t/t7012-skip-worktree-writing.sh\n@@ -53,17 +53,15 @@ test_expect_success 'read-tree removes worktree, dirty case' '\n \tgit update-index --no-skip-worktree added\n '\n \n-NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n-\n setup_absent() {\n \ttest -f 1 && rm 1\n \tgit update-index --remove 1 &&\n-\tgit update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&\n+\tgit update-index --add --cacheinfo 100644 $_EMPTY_BLOB 1 &&\n \tgit update-index --skip-worktree 1\n }\n \n test_absent() {\n-\techo \"100644 $NULL_SHA1 0\t1\" > expected &&\n+\techo \"100644 $_EMPTY_BLOB 0\t1\" > expected &&\n \tgit ls-files --stage 1 > result &&\n \ttest_cmp expected result &&\n \ttest ! -f 1\n@@ -72,12 +70,12 @@ test_absent() {\n setup_dirty() {\n \tgit update-index --force-remove 1 &&\n \techo dirty > 1 &&\n-\tgit update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&\n+\tgit update-index --add --cacheinfo 100644 $_EMPTY_BLOB 1 &&\n \tgit update-index --skip-worktree 1\n }\n \n test_dirty() {\n-\techo \"100644 $NULL_SHA1 0\t1\" > expected &&\n+\techo \"100644 $_EMPTY_BLOB 0\t1\" > expected &&\n \tgit ls-files --stage 1 > result &&\n \ttest_cmp expected result &&\n \techo dirty > expected\ndiff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh\nindex a971884..8d23259 100755\n--- a/t/t7063-status-untracked-cache.sh\n+++ b/t/t7063-status-untracked-cache.sh\n@@ -53,7 +53,7 @@ A  two\n EOF\n \n cat >../dump.expect <<EOF &&\n-info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n+info/exclude $_EMPTY_BLOB\n core.excludesfile 0000000000000000000000000000000000000000\n exclude_per_dir .gitignore\n flags 00000006\n@@ -137,7 +137,7 @@ EOF\n test_expect_success 'verify untracked cache dump' '\n \ttest-dump-untracked-cache >../actual &&\n \tcat >../expect <<EOF &&\n-info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n+info/exclude $_EMPTY_BLOB\n core.excludesfile 0000000000000000000000000000000000000000\n exclude_per_dir .gitignore\n flags 00000006\n@@ -184,7 +184,7 @@ EOF\n test_expect_success 'verify untracked cache dump' '\n \ttest-dump-untracked-cache >../actual &&\n \tcat >../expect <<EOF &&\n-info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n+info/exclude $_EMPTY_BLOB\n core.excludesfile 0000000000000000000000000000000000000000\n exclude_per_dir .gitignore\n flags 00000006\ndiff --git a/t/t7508-status.sh b/t/t7508-status.sh\nindex c3ed7cb..2b534ec 100755\n--- a/t/t7508-status.sh\n+++ b/t/t7508-status.sh\n@@ -803,7 +803,7 @@ EOF\n '\n \n cat >expect <<EOF\n-:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M\tdir1/modified\n+:100644 100644 $_EMPTY_BLOB 0000000000000000000000000000000000000000 M\tdir1/modified\n EOF\n test_expect_success 'status refreshes the index' '\n \ttouch dir2/added &&\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 327caa5..e1785a2 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -163,6 +163,7 @@ _x40=\"$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05\"\n _z40=0000000000000000000000000000000000000000\n \n _EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+_EMPTY_BLOB=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n \n # Line feed\n LF='\n@@ -172,7 +173,7 @@ LF='\n # when case-folding filenames\n u200c=$(printf '\\342\\200\\214')\n \n-export _x05 _x40 _z40 LF u200c _EMPTY_TREE\n+export _x05 _x40 _z40 LF u200c _EMPTY_TREE _EMPTY_BLOB\n \n # Each test should start with something like this, after copyright notices:\n #\n-- \n2.8.2.537.g0965dd9\n\n"},{"id":"291088","messageId":"20160709052356.30570-4-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160709052356.30570-1-pclouds@gmail.com","subject":"[PATCH v3 3/4] cache-tree.c: fix i-t-a entry skipping directory updates sometimes","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-09T05:23:55Z","receivedAt":"2016-07-09T05:24:34Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Commit 3cf773e (cache-tree: fix writing cache-tree when CE_REMOVE is\npresent - 2012-12-16) skips i-t-a entries when building trees objects\nfrom the index. Unfortunately it may skip too much.\n\nThe code in question checks if an entry is an i-t-a one, then no tree\nentry will be written. But it does not take into account that\ndirectories can also be written with the same code. Suppose we have\nthis in the index.\n\n    a-file\n    subdir/file1\n    subdir/file2\n    subdir/file3\n    the-last-file\n\nWe write an entry for a-file as normal and move on to subdir/file1,\nwhere we realize the entry name for this level is simply just\n\"subdir\", write down an entry for \"subdir\" then jump three items ahead\nto the-last-file.\n\nThat is what happens normally when the first file in subdir is not an\ni-t-a entry. If subdir/file1 is an i-t-a, because of the broken\ncondition in this code, we still think \"subdir\" is an i-t-a file and\nnot writing \"subdir\" down and jump to the-last-file. The result tree\nnow only has two items: a-file and the-last-file. subdir should be\nthere too (even though it only records two sub-entries, file2 and\nfile3).\n\nIf the i-t-a entry is subdir/file2 or subdir/file3, this is not a\nproblem because we jump over them anyway. Which may explain why the\nbug is hidden for nearly four years.\n\nFix it by making sure we only skip i-t-a entries when the entry in\nquestion is actual an index entry, not a directory.\n\nReported-by: Yuri Kanivetsky <yuri.kanivetsky@gmail.com>\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache-tree.c          |  4 ++--\n t/t2203-add-intent.sh | 17 +++++++++++++++++\n 2 files changed, 19 insertions(+), 2 deletions(-)\n\ndiff --git a/cache-tree.c b/cache-tree.c\nindex ddf0cc9..c2676e8 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -319,7 +319,7 @@ static int update_one(struct cache_tree *it,\n \ti = 0;\n \twhile (i < entries) {\n \t\tconst struct cache_entry *ce = cache[i];\n-\t\tstruct cache_tree_sub *sub;\n+\t\tstruct cache_tree_sub *sub = NULL;\n \t\tconst char *path, *slash;\n \t\tint pathlen, entlen;\n \t\tconst unsigned char *sha1;\n@@ -375,7 +375,7 @@ static int update_one(struct cache_tree *it,\n \t\t * they are not part of generated trees. Invalidate up\n \t\t * to root to force cache-tree users to read elsewhere.\n \t\t */\n-\t\tif (ce_intent_to_add(ce)) {\n+\t\tif (!sub && ce_intent_to_add(ce)) {\n \t\t\tto_invalidate = 1;\n \t\t\tcontinue;\n \t\t}\ndiff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\nindex 2a4a749..24aed2e 100755\n--- a/t/t2203-add-intent.sh\n+++ b/t/t2203-add-intent.sh\n@@ -82,5 +82,22 @@ test_expect_success 'cache-tree invalidates i-t-a paths' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n+\tgit init ita-in-dir &&\n+\t(\n+\t\tcd ita-in-dir &&\n+\t\tmkdir 2 &&\n+\t\tfor f in 1 2/1 2/2 3\n+\t\tdo\n+\t\t\techo \"$f\" >\"$f\"\n+\t\tdone &&\n+\t\tgit add 1 2/2 3 &&\n+\t\tgit add -N 2/1 &&\n+\t\tgit commit -m committed &&\n+\t\tgit ls-tree -r HEAD >actual &&\n+\t\tgrep 2/2 actual\n+\t)\n+'\n+\n test_done\n \n-- \n2.8.2.537.g0965dd9\n\n"},{"id":"291089","messageId":"20160709052356.30570-5-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160709052356.30570-1-pclouds@gmail.com","subject":"[PATCH v3 4/4] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-09T05:23:56Z","receivedAt":"2016-07-09T05:24:36Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"If a subdirectory contains nothing but i-t-a entries, we generate an\nempty tree object and add it to its parent tree. Which is wrong. Such\na subdirectory should not be added.\n\nNote that this has a cascading effect. If subdir 'a/b/c' contains\nnothing but i-t-a entries, we ignore it. But then if 'a/b' contains\nonly (the non-existing) 'a/b/c', then we should ignore 'a/b' while\nbuilding 'a' too. And it goes all the way up to top directory.\n\nNoticed-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache-tree.c          |  7 +++++++\n t/t2203-add-intent.sh | 14 ++++++++++++++\n 2 files changed, 21 insertions(+)\n\ndiff --git a/cache-tree.c b/cache-tree.c\nindex c2676e8..2d50640 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -380,6 +380,13 @@ static int update_one(struct cache_tree *it,\n \t\t\tcontinue;\n \t\t}\n \n+\t\t/*\n+\t\t * \"sub\" can be an empty tree if subentries are i-t-a.\n+\t\t */\n+\t\tif (sub && sub->cache_tree->entry_count < 0 &&\n+\t\t    !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))\n+\t\t\tcontinue;\n+\n \t\tstrbuf_grow(&buffer, entlen + 100);\n \t\tstrbuf_addf(&buffer, \"%o %.*s%c\", mode, entlen, path + baselen, '\\0');\n \t\tstrbuf_add(&buffer, sha1, 20);\ndiff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\nindex 24aed2e..f4b2fac 100755\n--- a/t/t2203-add-intent.sh\n+++ b/t/t2203-add-intent.sh\n@@ -99,5 +99,19 @@ test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n \t)\n '\n \n+test_expect_success 'cache-tree does skip dir that becomes empty' '\n+\trm -fr ita-in-dir &&\n+\tgit init ita-in-dir &&\n+\t(\n+\t\tcd ita-in-dir &&\n+\t\tmkdir -p 1/2/3 &&\n+\t\techo 4 >1/2/3/4 &&\n+\t\tgit add -N 1/2/3/4 &&\n+\t\tgit write-tree >actual &&\n+\t\techo $_EMPTY_TREE >expected &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n test_done\n \n-- \n2.8.2.537.g0965dd9\n\n"},{"id":"291090","messageId":"20160709052356.30570-2-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160709052356.30570-1-pclouds@gmail.com","subject":"[PATCH v3 1/4] test-lib.sh: introduce and use $_EMPTY_TREE","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-09T05:23:53Z","receivedAt":"2016-07-09T05:24:41Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This is a special SHA1. Let's keep it at one place, easier to replace\nlater when the hash change comes, easier to recognize. Start with an\nunderscore to reduce the chances somebody may override it without\nrealizing it's predefined.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n t/t0000-basic.sh                |  2 +-\n t/t1100-commit-tree-options.sh  |  2 +-\n t/t4010-diff-pathspec.sh        |  6 ++----\n t/t4054-diff-bogus-tree.sh      | 10 ++++------\n t/t5504-fetch-receive-strict.sh |  4 ++--\n t/test-lib.sh                   |  4 +++-\n 6 files changed, 13 insertions(+), 15 deletions(-)\n\ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex 60811a3..48214e9 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -834,7 +834,7 @@ test_expect_success 'git write-tree should be able to write an empty tree' '\n '\n \n test_expect_success 'validate object ID of a known tree' '\n-\ttest \"$tree\" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+\ttest \"$tree\" = $_EMPTY_TREE\n '\n \n # Various types of objects\ndiff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh\nindex b7e9b4fc..2adb123 100755\n--- a/t/t1100-commit-tree-options.sh\n+++ b/t/t1100-commit-tree-options.sh\n@@ -15,7 +15,7 @@ Also make sure that command line parser understands the normal\n . ./test-lib.sh\n \n cat >expected <<EOF\n-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+tree $_EMPTY_TREE\n author Author Name <author@email> 1117148400 +0000\n committer Committer Name <committer@email> 1117150200 +0000\n \ndiff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh\nindex 43c488b..7c98912 100755\n--- a/t/t4010-diff-pathspec.sh\n+++ b/t/t4010-diff-pathspec.sh\n@@ -78,16 +78,14 @@ test_expect_success 'diff-tree pathspec' '\n \ttest_cmp expected current\n '\n \n-EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904\n-\n test_expect_success 'diff-tree with wildcard shows dir also matches' '\n-\tgit diff-tree --name-only $EMPTY_TREE $tree -- \"f*\" >result &&\n+\tgit diff-tree --name-only $_EMPTY_TREE $tree -- \"f*\" >result &&\n \techo file0 >expected &&\n \ttest_cmp expected result\n '\n \n test_expect_success 'diff-tree -r with wildcard' '\n-\tgit diff-tree -r --name-only $EMPTY_TREE $tree -- \"*file1\" >result &&\n+\tgit diff-tree -r --name-only $_EMPTY_TREE $tree -- \"*file1\" >result &&\n \techo path1/file1 >expected &&\n \ttest_cmp expected result\n '\ndiff --git a/t/t4054-diff-bogus-tree.sh b/t/t4054-diff-bogus-tree.sh\nindex 1d6efab..6b48512 100755\n--- a/t/t4054-diff-bogus-tree.sh\n+++ b/t/t4054-diff-bogus-tree.sh\n@@ -3,8 +3,6 @@\n test_description='test diff with a bogus tree containing the null sha1'\n . ./test-lib.sh\n \n-empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904\n-\n test_expect_success 'create bogus tree' '\n \tbogus_tree=$(\n \t\tprintf \"100644 fooQQQQQQQQQQQQQQQQQQQQQ\" |\n@@ -22,13 +20,13 @@ test_expect_success 'create tree with matching file' '\n \n test_expect_success 'raw diff shows null sha1 (addition)' '\n \techo \":000000 100644 $_z40 $_z40 A\tfoo\" >expect &&\n-\tgit diff-tree $empty_tree $bogus_tree >actual &&\n+\tgit diff-tree $_EMPTY_TREE $bogus_tree >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'raw diff shows null sha1 (removal)' '\n \techo \":100644 000000 $_z40 $_z40 D\tfoo\" >expect &&\n-\tgit diff-tree $bogus_tree $empty_tree >actual &&\n+\tgit diff-tree $bogus_tree $_EMPTY_TREE >actual &&\n \ttest_cmp expect actual\n '\n \n@@ -57,11 +55,11 @@ test_expect_success 'raw diff shows null sha1 (index)' '\n '\n \n test_expect_success 'patch fails due to bogus sha1 (addition)' '\n-\ttest_must_fail git diff-tree -p $empty_tree $bogus_tree\n+\ttest_must_fail git diff-tree -p $_EMPTY_TREE $bogus_tree\n '\n \n test_expect_success 'patch fails due to bogus sha1 (removal)' '\n-\ttest_must_fail git diff-tree -p $bogus_tree $empty_tree\n+\ttest_must_fail git diff-tree -p $bogus_tree $_EMPTY_TREE\n '\n \n test_expect_success 'patch fails due to bogus sha1 (modification)' '\ndiff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh\nindex 44f3d5f..39cc971 100755\n--- a/t/t5504-fetch-receive-strict.sh\n+++ b/t/t5504-fetch-receive-strict.sh\n@@ -115,8 +115,8 @@ test_expect_success 'push with transfer.fsckobjects' '\n \ttest_cmp exp act\n '\n \n-cat >bogus-commit <<\\EOF\n-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+cat >bogus-commit <<EOF\n+tree $_EMPTY_TREE\n author Bugs Bunny 1234567890 +0000\n committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000\n \ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 0055ebb..327caa5 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -162,6 +162,8 @@ _x40=\"$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05\"\n # Zero SHA-1\n _z40=0000000000000000000000000000000000000000\n \n+_EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+\n # Line feed\n LF='\n '\n@@ -170,7 +172,7 @@ LF='\n # when case-folding filenames\n u200c=$(printf '\\342\\200\\214')\n \n-export _x05 _x40 _z40 LF u200c\n+export _x05 _x40 _z40 LF u200c _EMPTY_TREE\n \n # Each test should start with something like this, after copyright notices:\n #\n-- \n2.8.2.537.g0965dd9\n\n"},{"id":"291303","messageId":"xmqq1t2y4mjy.fsf@gitster.mtv.corp.google.com","threadId":"42772","inReplyTo":"20160709052356.30570-2-pclouds@gmail.com","subject":"Re: [PATCH v3 1/4] test-lib.sh: introduce and use $_EMPTY_TREE","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-12T20:40:49Z","receivedAt":"2016-07-12T20:41:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> This is a special SHA1. Let's keep it at one place, easier to replace\n> later when the hash change comes, easier to recognize. Start with an\n> underscore to reduce the chances somebody may override it without\n> realizing it's predefined.\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  t/t0000-basic.sh                |  2 +-\n>  t/t1100-commit-tree-options.sh  |  2 +-\n>  t/t4010-diff-pathspec.sh        |  6 ++----\n>  t/t4054-diff-bogus-tree.sh      | 10 ++++------\n>  t/t5504-fetch-receive-strict.sh |  4 ++--\n>  t/test-lib.sh                   |  4 +++-\n>  6 files changed, 13 insertions(+), 15 deletions(-)\n>\n> diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\n> index 60811a3..48214e9 100755\n> --- a/t/t0000-basic.sh\n> +++ b/t/t0000-basic.sh\n> @@ -834,7 +834,7 @@ test_expect_success 'git write-tree should be able to write an empty tree' '\n>  '\n>  \n>  test_expect_success 'validate object ID of a known tree' '\n> -\ttest \"$tree\" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n> +\ttest \"$tree\" = $_EMPTY_TREE\n>  '\n\nI doubt the point of, and I'd rather not to see, the leading\nunderscore.  Are there existing uses of the name that want it to\nmean something different?\n"},{"id":"291304","messageId":"xmqqtwfu37ld.fsf@gitster.mtv.corp.google.com","threadId":"42772","inReplyTo":"20160709052356.30570-5-pclouds@gmail.com","subject":"Re: [PATCH v3 4/4] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-12T20:49:18Z","receivedAt":"2016-07-12T20:49:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> diff --git a/cache-tree.c b/cache-tree.c\n> index c2676e8..2d50640 100644\n> --- a/cache-tree.c\n> +++ b/cache-tree.c\n> @@ -380,6 +380,13 @@ static int update_one(struct cache_tree *it,\n>  \t\t\tcontinue;\n>  \t\t}\n>  \n> +\t\t/*\n> +\t\t * \"sub\" can be an empty tree if subentries are i-t-a.\n> +\t\t */\n> +\t\tif (sub && sub->cache_tree->entry_count < 0 &&\n> +\t\t    !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))\n> +\t\t\tcontinue;\n> +\n\nLooks sensible, except that it is unclear if it is correct to assume\nthat \"subentries are ita\" always equals to \"entry_count < 0\" here.\nI _think_ it is OK, as the function itself does use the latter as\nthe sign that it hit to_invalidate=1 case when it returns.\n\nThanks.\n\n>  \t\tstrbuf_grow(&buffer, entlen + 100);\n>  \t\tstrbuf_addf(&buffer, \"%o %.*s%c\", mode, entlen, path + baselen, '\\0');\n>  \t\tstrbuf_add(&buffer, sha1, 20);\n> diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\n> index 24aed2e..f4b2fac 100755\n> --- a/t/t2203-add-intent.sh\n> +++ b/t/t2203-add-intent.sh\n> @@ -99,5 +99,19 @@ test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n>  \t)\n>  '\n>  \n> +test_expect_success 'cache-tree does skip dir that becomes empty' '\n> +\trm -fr ita-in-dir &&\n> +\tgit init ita-in-dir &&\n> +\t(\n> +\t\tcd ita-in-dir &&\n> +\t\tmkdir -p 1/2/3 &&\n> +\t\techo 4 >1/2/3/4 &&\n> +\t\tgit add -N 1/2/3/4 &&\n> +\t\tgit write-tree >actual &&\n> +\t\techo $_EMPTY_TREE >expected &&\n> +\t\ttest_cmp expected actual\n> +\t)\n> +'\n> +\n>  test_done\n"},{"id":"291343","messageId":"CACsJy8AQLoe=61+iibfsYw-0ibVKF8zruymAFZqr8SwxX=JT2A@mail.gmail.com","threadId":"42772","inReplyTo":"xmqqtwfu37ld.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 4/4] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-13T14:59:43Z","receivedAt":"2016-07-13T15:03:05Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Jul 12, 2016 at 10:49 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>\n>> diff --git a/cache-tree.c b/cache-tree.c\n>> index c2676e8..2d50640 100644\n>> --- a/cache-tree.c\n>> +++ b/cache-tree.c\n>> @@ -380,6 +380,13 @@ static int update_one(struct cache_tree *it,\n>>                       continue;\n>>               }\n>>\n>> +             /*\n>> +              * \"sub\" can be an empty tree if subentries are i-t-a.\n>> +              */\n>> +             if (sub && sub->cache_tree->entry_count < 0 &&\n>> +                 !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))\n>> +                     continue;\n>> +\n>\n> Looks sensible, except that it is unclear if it is correct to assume\n> that \"subentries are ita\" always equals to \"entry_count < 0\" here.\n> I _think_ it is OK, as the function itself does use the latter as\n> the sign that it hit to_invalidate=1 case when it returns.\n\nI had the same concern and double checked it. If one day we have a new\nentry_count < 0 case that's not i-t-a, we'll need to refactor this\ncode a bit.\n-- \nDuy\n"},{"id":"291344","messageId":"CACsJy8B6faU6kaqSpNRZRxkrvM=W29acXkqVBdGq4gaqaDJRRA@mail.gmail.com","threadId":"42772","inReplyTo":"xmqq1t2y4mjy.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 1/4] test-lib.sh: introduce and use $_EMPTY_TREE","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-13T15:04:22Z","receivedAt":"2016-07-13T15:07:55Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Jul 12, 2016 at 10:40 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>\n>> This is a special SHA1. Let's keep it at one place, easier to replace\n>> later when the hash change comes, easier to recognize. Start with an\n>> underscore to reduce the chances somebody may override it without\n>> realizing it's predefined.\n>>\n>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n>> ---\n>>  t/t0000-basic.sh                |  2 +-\n>>  t/t1100-commit-tree-options.sh  |  2 +-\n>>  t/t4010-diff-pathspec.sh        |  6 ++----\n>>  t/t4054-diff-bogus-tree.sh      | 10 ++++------\n>>  t/t5504-fetch-receive-strict.sh |  4 ++--\n>>  t/test-lib.sh                   |  4 +++-\n>>  6 files changed, 13 insertions(+), 15 deletions(-)\n>>\n>> diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\n>> index 60811a3..48214e9 100755\n>> --- a/t/t0000-basic.sh\n>> +++ b/t/t0000-basic.sh\n>> @@ -834,7 +834,7 @@ test_expect_success 'git write-tree should be able to write an empty tree' '\n>>  '\n>>\n>>  test_expect_success 'validate object ID of a known tree' '\n>> -     test \"$tree\" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n>> +     test \"$tree\" = $_EMPTY_TREE\n>>  '\n>\n> I doubt the point of, and I'd rather not to see, the leading\n> underscore.  Are there existing uses of the name that want it to\n> mean something different?\n\nNo. There is EMPTY_TREE in use, but it's exactly what we expect. It's\nprobably still a good idea to separate \"global\" variables from\nper-file ones. But I don't feel strongly about this, so if a re-roll\nis required (or somebody votes for underscore removal, including you),\nI'll remove the underscore.\n-- \nDuy\n"},{"id":"291579","messageId":"20160716050627.9416-1-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160709052356.30570-1-pclouds@gmail.com","subject":"[PATCH v4 0/4] cache-tree building fix in the presence of ita entries","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-16T05:06:23Z","receivedAt":"2016-07-16T05:06:55Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"v4 removes the leading underscore from _EMPTY_BLOB and _EMPTY_TREE and\nupdates 4/4 slightly like this.\n\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 2d50640..f28b1f4 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -325,6 +325,7 @@ static int update_one(struct cache_tree *it,\n \t\tconst unsigned char *sha1;\n \t\tunsigned mode;\n \t\tint expected_missing = 0;\n+\t\tint contains_ita = 0;\n \n \t\tpath = ce->name;\n \t\tpathlen = ce_namelen(ce);\n@@ -341,7 +342,8 @@ static int update_one(struct cache_tree *it,\n \t\t\ti += sub->count;\n \t\t\tsha1 = sub->cache_tree->sha1;\n \t\t\tmode = S_IFDIR;\n-\t\t\tif (sub->cache_tree->entry_count < 0) {\n+\t\t\tcontains_ita = sub->cache_tree->entry_count < 0;\n+\t\t\tif (contains_ita) {\n \t\t\t\tto_invalidate = 1;\n \t\t\t\texpected_missing = 1;\n \t\t\t}\n@@ -381,10 +383,9 @@ static int update_one(struct cache_tree *it,\n \t\t}\n \n \t\t/*\n-\t\t * \"sub\" can be an empty tree if subentries are i-t-a.\n+\t\t * \"sub\" can be an empty tree if all subentries are i-t-a.\n \t\t */\n-\t\tif (sub && sub->cache_tree->entry_count < 0 &&\n-\t\t    !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))\n+\t\tif (contains_ita && !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))\n \t\t\tcontinue;\n \n \t\tstrbuf_grow(&buffer, entlen + 100);\n\nNguyễn Thái Ngọc Duy (4):\n  test-lib.sh: introduce and use $EMPTY_TREE\n  test-lib.sh: introduce and use $EMPTY_BLOB\n  cache-tree.c: fix i-t-a entry skipping directory updates sometimes\n  cache-tree: do not generate empty trees as a result of all i-t-a\n    subentries\n\n cache-tree.c                         | 14 +++++++++++---\n t/t0000-basic.sh                     |  2 +-\n t/t1011-read-tree-sparse-checkout.sh |  8 ++++----\n t/t1100-commit-tree-options.sh       |  2 +-\n t/t1700-split-index.sh               | 24 ++++++++++++------------\n t/t2203-add-intent.sh                | 31 +++++++++++++++++++++++++++++++\n t/t3102-ls-tree-wildcards.sh         |  8 ++++----\n t/t4010-diff-pathspec.sh             |  2 --\n t/t4054-diff-bogus-tree.sh           | 10 ++++------\n t/t5504-fetch-receive-strict.sh      |  4 ++--\n t/t7011-skip-worktree-reading.sh     | 12 +++++-------\n t/t7012-skip-worktree-writing.sh     | 10 ++++------\n t/t7063-status-untracked-cache.sh    |  6 +++---\n t/t7508-status.sh                    |  2 +-\n t/test-lib.sh                        |  5 ++++-\n 15 files changed, 87 insertions(+), 53 deletions(-)\n\n-- \n2.9.1.566.gbd532d4\n\n"},{"id":"291580","messageId":"20160716050627.9416-2-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160716050627.9416-1-pclouds@gmail.com","subject":"[PATCH v4 1/4] test-lib.sh: introduce and use $EMPTY_TREE","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-16T05:06:24Z","receivedAt":"2016-07-16T05:06:59Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This is a special SHA1. Let's keep it at one place, easier to replace\nlater when the hash change comes, easier to recognize.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n t/t0000-basic.sh                |  2 +-\n t/t1100-commit-tree-options.sh  |  2 +-\n t/t4010-diff-pathspec.sh        |  2 --\n t/t4054-diff-bogus-tree.sh      | 10 ++++------\n t/t5504-fetch-receive-strict.sh |  4 ++--\n t/test-lib.sh                   |  4 +++-\n 6 files changed, 11 insertions(+), 13 deletions(-)\n\ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex 60811a3..1aa5093 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -834,7 +834,7 @@ test_expect_success 'git write-tree should be able to write an empty tree' '\n '\n \n test_expect_success 'validate object ID of a known tree' '\n-\ttest \"$tree\" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+\ttest \"$tree\" = $EMPTY_TREE\n '\n \n # Various types of objects\ndiff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh\nindex b7e9b4fc..ae66ba5 100755\n--- a/t/t1100-commit-tree-options.sh\n+++ b/t/t1100-commit-tree-options.sh\n@@ -15,7 +15,7 @@ Also make sure that command line parser understands the normal\n . ./test-lib.sh\n \n cat >expected <<EOF\n-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+tree $EMPTY_TREE\n author Author Name <author@email> 1117148400 +0000\n committer Committer Name <committer@email> 1117150200 +0000\n \ndiff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh\nindex 43c488b..35b35a8 100755\n--- a/t/t4010-diff-pathspec.sh\n+++ b/t/t4010-diff-pathspec.sh\n@@ -78,8 +78,6 @@ test_expect_success 'diff-tree pathspec' '\n \ttest_cmp expected current\n '\n \n-EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904\n-\n test_expect_success 'diff-tree with wildcard shows dir also matches' '\n \tgit diff-tree --name-only $EMPTY_TREE $tree -- \"f*\" >result &&\n \techo file0 >expected &&\ndiff --git a/t/t4054-diff-bogus-tree.sh b/t/t4054-diff-bogus-tree.sh\nindex 1d6efab..18f42c5 100755\n--- a/t/t4054-diff-bogus-tree.sh\n+++ b/t/t4054-diff-bogus-tree.sh\n@@ -3,8 +3,6 @@\n test_description='test diff with a bogus tree containing the null sha1'\n . ./test-lib.sh\n \n-empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904\n-\n test_expect_success 'create bogus tree' '\n \tbogus_tree=$(\n \t\tprintf \"100644 fooQQQQQQQQQQQQQQQQQQQQQ\" |\n@@ -22,13 +20,13 @@ test_expect_success 'create tree with matching file' '\n \n test_expect_success 'raw diff shows null sha1 (addition)' '\n \techo \":000000 100644 $_z40 $_z40 A\tfoo\" >expect &&\n-\tgit diff-tree $empty_tree $bogus_tree >actual &&\n+\tgit diff-tree $EMPTY_TREE $bogus_tree >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'raw diff shows null sha1 (removal)' '\n \techo \":100644 000000 $_z40 $_z40 D\tfoo\" >expect &&\n-\tgit diff-tree $bogus_tree $empty_tree >actual &&\n+\tgit diff-tree $bogus_tree $EMPTY_TREE >actual &&\n \ttest_cmp expect actual\n '\n \n@@ -57,11 +55,11 @@ test_expect_success 'raw diff shows null sha1 (index)' '\n '\n \n test_expect_success 'patch fails due to bogus sha1 (addition)' '\n-\ttest_must_fail git diff-tree -p $empty_tree $bogus_tree\n+\ttest_must_fail git diff-tree -p $EMPTY_TREE $bogus_tree\n '\n \n test_expect_success 'patch fails due to bogus sha1 (removal)' '\n-\ttest_must_fail git diff-tree -p $bogus_tree $empty_tree\n+\ttest_must_fail git diff-tree -p $bogus_tree $EMPTY_TREE\n '\n \n test_expect_success 'patch fails due to bogus sha1 (modification)' '\ndiff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh\nindex 44f3d5f..9b19cff 100755\n--- a/t/t5504-fetch-receive-strict.sh\n+++ b/t/t5504-fetch-receive-strict.sh\n@@ -115,8 +115,8 @@ test_expect_success 'push with transfer.fsckobjects' '\n \ttest_cmp exp act\n '\n \n-cat >bogus-commit <<\\EOF\n-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+cat >bogus-commit <<EOF\n+tree $EMPTY_TREE\n author Bugs Bunny 1234567890 +0000\n committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000\n \ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 0055ebb..85f4c6d 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -162,6 +162,8 @@ _x40=\"$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05\"\n # Zero SHA-1\n _z40=0000000000000000000000000000000000000000\n \n+EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+\n # Line feed\n LF='\n '\n@@ -170,7 +172,7 @@ LF='\n # when case-folding filenames\n u200c=$(printf '\\342\\200\\214')\n \n-export _x05 _x40 _z40 LF u200c\n+export _x05 _x40 _z40 LF u200c EMPTY_TREE\n \n # Each test should start with something like this, after copyright notices:\n #\n-- \n2.9.1.566.gbd532d4\n\n"},{"id":"291581","messageId":"20160716050627.9416-4-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160716050627.9416-1-pclouds@gmail.com","subject":"[PATCH v4 3/4] cache-tree.c: fix i-t-a entry skipping directory updates sometimes","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-16T05:06:26Z","receivedAt":"2016-07-16T05:07:06Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Commit 3cf773e (cache-tree: fix writing cache-tree when CE_REMOVE is\npresent - 2012-12-16) skips i-t-a entries when building trees objects\nfrom the index. Unfortunately it may skip too much.\n\nThe code in question checks if an entry is an i-t-a one, then no tree\nentry will be written. But it does not take into account that\ndirectories can also be written with the same code. Suppose we have\nthis in the index.\n\n    a-file\n    subdir/file1\n    subdir/file2\n    subdir/file3\n    the-last-file\n\nWe write an entry for a-file as normal and move on to subdir/file1,\nwhere we realize the entry name for this level is simply just\n\"subdir\", write down an entry for \"subdir\" then jump three items ahead\nto the-last-file.\n\nThat is what happens normally when the first file in subdir is not an\ni-t-a entry. If subdir/file1 is an i-t-a, because of the broken\ncondition in this code, we still think \"subdir\" is an i-t-a file and\nnot writing \"subdir\" down and jump to the-last-file. The result tree\nnow only has two items: a-file and the-last-file. subdir should be\nthere too (even though it only records two sub-entries, file2 and\nfile3).\n\nIf the i-t-a entry is subdir/file2 or subdir/file3, this is not a\nproblem because we jump over them anyway. Which may explain why the\nbug is hidden for nearly four years.\n\nFix it by making sure we only skip i-t-a entries when the entry in\nquestion is actual an index entry, not a directory.\n\nReported-by: Yuri Kanivetsky <yuri.kanivetsky@gmail.com>\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n cache-tree.c          |  4 ++--\n t/t2203-add-intent.sh | 17 +++++++++++++++++\n 2 files changed, 19 insertions(+), 2 deletions(-)\n\ndiff --git a/cache-tree.c b/cache-tree.c\nindex ddf0cc9..c2676e8 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -319,7 +319,7 @@ static int update_one(struct cache_tree *it,\n \ti = 0;\n \twhile (i < entries) {\n \t\tconst struct cache_entry *ce = cache[i];\n-\t\tstruct cache_tree_sub *sub;\n+\t\tstruct cache_tree_sub *sub = NULL;\n \t\tconst char *path, *slash;\n \t\tint pathlen, entlen;\n \t\tconst unsigned char *sha1;\n@@ -375,7 +375,7 @@ static int update_one(struct cache_tree *it,\n \t\t * they are not part of generated trees. Invalidate up\n \t\t * to root to force cache-tree users to read elsewhere.\n \t\t */\n-\t\tif (ce_intent_to_add(ce)) {\n+\t\tif (!sub && ce_intent_to_add(ce)) {\n \t\t\tto_invalidate = 1;\n \t\t\tcontinue;\n \t\t}\ndiff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\nindex 2a4a749..24aed2e 100755\n--- a/t/t2203-add-intent.sh\n+++ b/t/t2203-add-intent.sh\n@@ -82,5 +82,22 @@ test_expect_success 'cache-tree invalidates i-t-a paths' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n+\tgit init ita-in-dir &&\n+\t(\n+\t\tcd ita-in-dir &&\n+\t\tmkdir 2 &&\n+\t\tfor f in 1 2/1 2/2 3\n+\t\tdo\n+\t\t\techo \"$f\" >\"$f\"\n+\t\tdone &&\n+\t\tgit add 1 2/2 3 &&\n+\t\tgit add -N 2/1 &&\n+\t\tgit commit -m committed &&\n+\t\tgit ls-tree -r HEAD >actual &&\n+\t\tgrep 2/2 actual\n+\t)\n+'\n+\n test_done\n \n-- \n2.9.1.566.gbd532d4\n\n"},{"id":"291582","messageId":"20160716050627.9416-5-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160716050627.9416-1-pclouds@gmail.com","subject":"[PATCH v4 4/4] cache-tree: do not generate empty trees as a result of all i-t-a subentries","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-16T05:06:27Z","receivedAt":"2016-07-16T05:07:10Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"If a subdirectory contains nothing but i-t-a entries, we generate an\nempty tree object and add it to its parent tree. Which is wrong. Such\na subdirectory should not be added.\n\nNote that this has a cascading effect. If subdir 'a/b/c' contains\nnothing but i-t-a entries, we ignore it. But then if 'a/b' contains\nonly (the non-existing) 'a/b/c', then we should ignore 'a/b' while\nbuilding 'a' too. And it goes all the way up to top directory.\n\nNoticed-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache-tree.c          | 10 +++++++++-\n t/t2203-add-intent.sh | 14 ++++++++++++++\n 2 files changed, 23 insertions(+), 1 deletion(-)\n\ndiff --git a/cache-tree.c b/cache-tree.c\nindex c2676e8..f28b1f4 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -325,6 +325,7 @@ static int update_one(struct cache_tree *it,\n \t\tconst unsigned char *sha1;\n \t\tunsigned mode;\n \t\tint expected_missing = 0;\n+\t\tint contains_ita = 0;\n \n \t\tpath = ce->name;\n \t\tpathlen = ce_namelen(ce);\n@@ -341,7 +342,8 @@ static int update_one(struct cache_tree *it,\n \t\t\ti += sub->count;\n \t\t\tsha1 = sub->cache_tree->sha1;\n \t\t\tmode = S_IFDIR;\n-\t\t\tif (sub->cache_tree->entry_count < 0) {\n+\t\t\tcontains_ita = sub->cache_tree->entry_count < 0;\n+\t\t\tif (contains_ita) {\n \t\t\t\tto_invalidate = 1;\n \t\t\t\texpected_missing = 1;\n \t\t\t}\n@@ -380,6 +382,12 @@ static int update_one(struct cache_tree *it,\n \t\t\tcontinue;\n \t\t}\n \n+\t\t/*\n+\t\t * \"sub\" can be an empty tree if all subentries are i-t-a.\n+\t\t */\n+\t\tif (contains_ita && !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))\n+\t\t\tcontinue;\n+\n \t\tstrbuf_grow(&buffer, entlen + 100);\n \t\tstrbuf_addf(&buffer, \"%o %.*s%c\", mode, entlen, path + baselen, '\\0');\n \t\tstrbuf_add(&buffer, sha1, 20);\ndiff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh\nindex 24aed2e..8f22c43 100755\n--- a/t/t2203-add-intent.sh\n+++ b/t/t2203-add-intent.sh\n@@ -99,5 +99,19 @@ test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '\n \t)\n '\n \n+test_expect_success 'cache-tree does skip dir that becomes empty' '\n+\trm -fr ita-in-dir &&\n+\tgit init ita-in-dir &&\n+\t(\n+\t\tcd ita-in-dir &&\n+\t\tmkdir -p 1/2/3 &&\n+\t\techo 4 >1/2/3/4 &&\n+\t\tgit add -N 1/2/3/4 &&\n+\t\tgit write-tree >actual &&\n+\t\techo $EMPTY_TREE >expected &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n test_done\n \n-- \n2.9.1.566.gbd532d4\n\n"},{"id":"291583","messageId":"20160716050627.9416-3-pclouds@gmail.com","threadId":"42772","inReplyTo":"20160716050627.9416-1-pclouds@gmail.com","subject":"[PATCH v4 2/4] test-lib.sh: introduce and use $EMPTY_BLOB","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-07-16T05:06:25Z","receivedAt":"2016-07-16T05:07:11Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Similar to $EMPTY_TREE this makes it easier to recognize this special\nSHA-1 and change hash later.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n t/t1011-read-tree-sparse-checkout.sh |  8 ++++----\n t/t1700-split-index.sh               | 24 ++++++++++++------------\n t/t3102-ls-tree-wildcards.sh         |  8 ++++----\n t/t7011-skip-worktree-reading.sh     | 12 +++++-------\n t/t7012-skip-worktree-writing.sh     | 10 ++++------\n t/t7063-status-untracked-cache.sh    |  6 +++---\n t/t7508-status.sh                    |  2 +-\n t/test-lib.sh                        |  3 ++-\n 8 files changed, 35 insertions(+), 38 deletions(-)\n\ndiff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh\nindex 0c74bee..2563d18 100755\n--- a/t/t1011-read-tree-sparse-checkout.sh\n+++ b/t/t1011-read-tree-sparse-checkout.sh\n@@ -15,11 +15,11 @@ test_description='sparse checkout tests\n . \"$TEST_DIRECTORY\"/lib-read-tree.sh\n \n test_expect_success 'setup' '\n-\tcat >expected <<-\\EOF &&\n+\tcat >expected <<-EOF &&\n \t100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0\tinit.t\n-\t100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tsub/added\n-\t100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tsub/addedtoo\n-\t100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tsubsub/added\n+\t100644 $EMPTY_BLOB 0\tsub/added\n+\t100644 $EMPTY_BLOB 0\tsub/addedtoo\n+\t100644 $EMPTY_BLOB 0\tsubsub/added\n \tEOF\n \tcat >expected.swt <<-\\EOF &&\n \tH init.t\ndiff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh\nindex 8aef49f..292a072 100755\n--- a/t/t1700-split-index.sh\n+++ b/t/t1700-split-index.sh\n@@ -33,14 +33,14 @@ test_expect_success 'add one file' '\n \tgit update-index --add one &&\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $EMPTY_BLOB 0\tone\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \n \ttest-dump-split-index .git/index | sed \"/^own/d\" >actual &&\n \tcat >expect <<EOF &&\n base $base\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $EMPTY_BLOB 0\tone\n replacements:\n deletions:\n EOF\n@@ -51,7 +51,7 @@ test_expect_success 'disable split index' '\n \tgit update-index --no-split-index &&\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $EMPTY_BLOB 0\tone\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \n@@ -67,7 +67,7 @@ test_expect_success 'enable split index again, \"one\" now belongs to base index\"'\n \tgit update-index --split-index &&\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $EMPTY_BLOB 0\tone\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \n@@ -105,7 +105,7 @@ test_expect_success 'add another file, which stays index' '\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0\tone\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\ttwo\n+100644 $EMPTY_BLOB 0\ttwo\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \n@@ -113,7 +113,7 @@ EOF\n \tq_to_tab >expect <<EOF &&\n $BASE\n 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\ttwo\n+100644 $EMPTY_BLOB 0\ttwo\n replacements: 0\n deletions:\n EOF\n@@ -159,14 +159,14 @@ test_expect_success 'add original file back' '\n \tgit update-index --add one &&\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $EMPTY_BLOB 0\tone\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \n \ttest-dump-split-index .git/index | sed \"/^own/d\" >actual &&\n \tcat >expect <<EOF &&\n $BASE\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n+100644 $EMPTY_BLOB 0\tone\n replacements:\n deletions: 0\n EOF\n@@ -178,8 +178,8 @@ test_expect_success 'add new file' '\n \tgit update-index --add two &&\n \tgit ls-files --stage >actual &&\n \tcat >expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\ttwo\n+100644 $EMPTY_BLOB 0\tone\n+100644 $EMPTY_BLOB 0\ttwo\n EOF\n \ttest_cmp expect actual\n '\n@@ -188,8 +188,8 @@ test_expect_success 'unify index, two files remain' '\n \tgit update-index --no-split-index &&\n \tgit ls-files --stage >ls-files.actual &&\n \tcat >ls-files.expect <<EOF &&\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tone\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\ttwo\n+100644 $EMPTY_BLOB 0\tone\n+100644 $EMPTY_BLOB 0\ttwo\n EOF\n \ttest_cmp ls-files.expect ls-files.actual &&\n \ndiff --git a/t/t3102-ls-tree-wildcards.sh b/t/t3102-ls-tree-wildcards.sh\nindex 4d4b02e..e804377 100755\n--- a/t/t3102-ls-tree-wildcards.sh\n+++ b/t/t3102-ls-tree-wildcards.sh\n@@ -12,16 +12,16 @@ test_expect_success 'setup' '\n '\n \n test_expect_success 'ls-tree a[a] matches literally' '\n-\tcat >expect <<-\\EOF &&\n-\t100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\ta[a]/three\n+\tcat >expect <<-EOF &&\n+\t100644 blob $EMPTY_BLOB\ta[a]/three\n \tEOF\n \tgit ls-tree -r HEAD \"a[a]\" >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'ls-tree outside prefix' '\n-\tcat >expect <<-\\EOF &&\n-\t100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\t../a[a]/three\n+\tcat >expect <<-EOF &&\n+\t100644 blob $EMPTY_BLOB\t../a[a]/three\n \tEOF\n \t( cd aa && git ls-tree -r HEAD \"../a[a]\"; ) >actual &&\n \ttest_cmp expect actual\ndiff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh\nindex 88d60c1..84f4145 100755\n--- a/t/t7011-skip-worktree-reading.sh\n+++ b/t/t7011-skip-worktree-reading.sh\n@@ -23,17 +23,15 @@ S sub/1\n H sub/2\n EOF\n \n-NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n-\n setup_absent() {\n \ttest -f 1 && rm 1\n \tgit update-index --remove 1 &&\n-\tgit update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&\n+\tgit update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 &&\n \tgit update-index --skip-worktree 1\n }\n \n test_absent() {\n-\techo \"100644 $NULL_SHA1 0\t1\" > expected &&\n+\techo \"100644 $EMPTY_BLOB 0\t1\" > expected &&\n \tgit ls-files --stage 1 > result &&\n \ttest_cmp expected result &&\n \ttest ! -f 1\n@@ -42,12 +40,12 @@ test_absent() {\n setup_dirty() {\n \tgit update-index --force-remove 1 &&\n \techo dirty > 1 &&\n-\tgit update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&\n+\tgit update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 &&\n \tgit update-index --skip-worktree 1\n }\n \n test_dirty() {\n-\techo \"100644 $NULL_SHA1 0\t1\" > expected &&\n+\techo \"100644 $EMPTY_BLOB 0\t1\" > expected &&\n \tgit ls-files --stage 1 > result &&\n \ttest_cmp expected result &&\n \techo dirty > expected\n@@ -120,7 +118,7 @@ test_expect_success 'grep with skip-worktree file' '\n \ttest \"$(git grep --no-ext-grep test)\" = \"1:test\"\n '\n \n-echo \":000000 100644 $_z40 $NULL_SHA1 A\t1\" > expected\n+echo \":000000 100644 $_z40 $EMPTY_BLOB A\t1\" > expected\n test_expect_success 'diff-index does not examine skip-worktree absent entries' '\n \tsetup_absent &&\n \tgit diff-index HEAD -- 1 > result &&\ndiff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh\nindex 9ceaa40..9d1abe5 100755\n--- a/t/t7012-skip-worktree-writing.sh\n+++ b/t/t7012-skip-worktree-writing.sh\n@@ -53,17 +53,15 @@ test_expect_success 'read-tree removes worktree, dirty case' '\n \tgit update-index --no-skip-worktree added\n '\n \n-NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n-\n setup_absent() {\n \ttest -f 1 && rm 1\n \tgit update-index --remove 1 &&\n-\tgit update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&\n+\tgit update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 &&\n \tgit update-index --skip-worktree 1\n }\n \n test_absent() {\n-\techo \"100644 $NULL_SHA1 0\t1\" > expected &&\n+\techo \"100644 $EMPTY_BLOB 0\t1\" > expected &&\n \tgit ls-files --stage 1 > result &&\n \ttest_cmp expected result &&\n \ttest ! -f 1\n@@ -72,12 +70,12 @@ test_absent() {\n setup_dirty() {\n \tgit update-index --force-remove 1 &&\n \techo dirty > 1 &&\n-\tgit update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&\n+\tgit update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 &&\n \tgit update-index --skip-worktree 1\n }\n \n test_dirty() {\n-\techo \"100644 $NULL_SHA1 0\t1\" > expected &&\n+\techo \"100644 $EMPTY_BLOB 0\t1\" > expected &&\n \tgit ls-files --stage 1 > result &&\n \ttest_cmp expected result &&\n \techo dirty > expected\ndiff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh\nindex a971884..a828a5f 100755\n--- a/t/t7063-status-untracked-cache.sh\n+++ b/t/t7063-status-untracked-cache.sh\n@@ -53,7 +53,7 @@ A  two\n EOF\n \n cat >../dump.expect <<EOF &&\n-info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n+info/exclude $EMPTY_BLOB\n core.excludesfile 0000000000000000000000000000000000000000\n exclude_per_dir .gitignore\n flags 00000006\n@@ -137,7 +137,7 @@ EOF\n test_expect_success 'verify untracked cache dump' '\n \ttest-dump-untracked-cache >../actual &&\n \tcat >../expect <<EOF &&\n-info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n+info/exclude $EMPTY_BLOB\n core.excludesfile 0000000000000000000000000000000000000000\n exclude_per_dir .gitignore\n flags 00000006\n@@ -184,7 +184,7 @@ EOF\n test_expect_success 'verify untracked cache dump' '\n \ttest-dump-untracked-cache >../actual &&\n \tcat >../expect <<EOF &&\n-info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n+info/exclude $EMPTY_BLOB\n core.excludesfile 0000000000000000000000000000000000000000\n exclude_per_dir .gitignore\n flags 00000006\ndiff --git a/t/t7508-status.sh b/t/t7508-status.sh\nindex c3ed7cb..a42aef8 100755\n--- a/t/t7508-status.sh\n+++ b/t/t7508-status.sh\n@@ -803,7 +803,7 @@ EOF\n '\n \n cat >expect <<EOF\n-:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M\tdir1/modified\n+:100644 100644 $EMPTY_BLOB 0000000000000000000000000000000000000000 M\tdir1/modified\n EOF\n test_expect_success 'status refreshes the index' '\n \ttouch dir2/added &&\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 85f4c6d..9f36091 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -163,6 +163,7 @@ _x40=\"$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05\"\n _z40=0000000000000000000000000000000000000000\n \n EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+EMPTY_BLOB=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n \n # Line feed\n LF='\n@@ -172,7 +173,7 @@ LF='\n # when case-folding filenames\n u200c=$(printf '\\342\\200\\214')\n \n-export _x05 _x40 _z40 LF u200c EMPTY_TREE\n+export _x05 _x40 _z40 LF u200c EMPTY_TREE EMPTY_BLOB\n \n # Each test should start with something like this, after copyright notices:\n #\n-- \n2.9.1.566.gbd532d4\n\n"},{"id":"291683","messageId":"xmqqbn1uiser.fsf@gitster.mtv.corp.google.com","threadId":"42772","inReplyTo":"20160716050627.9416-1-pclouds@gmail.com","subject":"Re: [PATCH v4 0/4] cache-tree building fix in the presence of ita entries","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-18T20:48:44Z","receivedAt":"2016-07-18T20:48:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> v4 removes the leading underscore from _EMPTY_BLOB and _EMPTY_TREE and\n> updates 4/4 slightly like this.\n>\n> diff --git a/cache-tree.c b/cache-tree.c\n> index 2d50640..f28b1f4 100644\n> --- a/cache-tree.c\n> +++ b/cache-tree.c\n> @@ -325,6 +325,7 @@ static int update_one(struct cache_tree *it,\n>  \t\tconst unsigned char *sha1;\n>  \t\tunsigned mode;\n>  \t\tint expected_missing = 0;\n> +\t\tint contains_ita = 0;\n>  \n>  \t\tpath = ce->name;\n>  \t\tpathlen = ce_namelen(ce);\n> @@ -341,7 +342,8 @@ static int update_one(struct cache_tree *it,\n>  \t\t\ti += sub->count;\n>  \t\t\tsha1 = sub->cache_tree->sha1;\n>  \t\t\tmode = S_IFDIR;\n> -\t\t\tif (sub->cache_tree->entry_count < 0) {\n> +\t\t\tcontains_ita = sub->cache_tree->entry_count < 0;\n> +\t\t\tif (contains_ita) {\n>  \t\t\t\tto_invalidate = 1;\n>  \t\t\t\texpected_missing = 1;\n>  \t\t\t}\n> @@ -381,10 +383,9 @@ static int update_one(struct cache_tree *it,\n>  \t\t}\n>  \n>  \t\t/*\n> -\t\t * \"sub\" can be an empty tree if subentries are i-t-a.\n> +\t\t * \"sub\" can be an empty tree if all subentries are i-t-a.\n>  \t\t */\n> -\t\tif (sub && sub->cache_tree->entry_count < 0 &&\n> -\t\t    !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))\n> +\t\tif (contains_ita && !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))\n>  \t\t\tcontinue;\n>  \n>  \t\tstrbuf_grow(&buffer, entlen + 100);\n\nThis makes quite a lot of sense; even though I do not think it would\nchange the behaviour within the context of current code, it\ndefinitely is easier to understand and prevents future mistakes.\n\nWill queue.\n\nThanks.\n"}]}