Merge branch 'nd/cache-tree-ita'
authorJunio C Hamano <gitster@pobox.com>
Mon, 25 Jul 2016 21:13:44 +0000 (14:13 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 25 Jul 2016 21:13:44 +0000 (14:13 -0700)
"git add -N dir/file && git write-tree" produced an incorrect tree
when there are other paths in the same directory that sorts after
"file".

* nd/cache-tree-ita:
cache-tree: do not generate empty trees as a result of all i-t-a subentries
cache-tree.c: fix i-t-a entry skipping directory updates sometimes
test-lib.sh: introduce and use $EMPTY_BLOB
test-lib.sh: introduce and use $EMPTY_TREE

15 files changed:
cache-tree.c
t/t0000-basic.sh
t/t1011-read-tree-sparse-checkout.sh
t/t1100-commit-tree-options.sh
t/t1700-split-index.sh
t/t2203-add-intent.sh
t/t3102-ls-tree-wildcards.sh
t/t4010-diff-pathspec.sh
t/t4054-diff-bogus-tree.sh
t/t5504-fetch-receive-strict.sh
t/t7011-skip-worktree-reading.sh
t/t7012-skip-worktree-writing.sh
t/t7063-status-untracked-cache.sh
t/t7508-status.sh
t/test-lib.sh
index ddf0cc9f9aa51f577b0d1a764ebc3e0a318fe1ba..f28b1f45a49b842c2f7a372b0c0c595bebc56b5d 100644 (file)
@@ -319,12 +319,13 @@ static int update_one(struct cache_tree *it,
        i = 0;
        while (i < entries) {
                const struct cache_entry *ce = cache[i];
-               struct cache_tree_sub *sub;
+               struct cache_tree_sub *sub = NULL;
                const char *path, *slash;
                int pathlen, entlen;
                const unsigned char *sha1;
                unsigned mode;
                int expected_missing = 0;
+               int contains_ita = 0;
 
                path = ce->name;
                pathlen = ce_namelen(ce);
@@ -341,7 +342,8 @@ static int update_one(struct cache_tree *it,
                        i += sub->count;
                        sha1 = sub->cache_tree->sha1;
                        mode = S_IFDIR;
-                       if (sub->cache_tree->entry_count < 0) {
+                       contains_ita = sub->cache_tree->entry_count < 0;
+                       if (contains_ita) {
                                to_invalidate = 1;
                                expected_missing = 1;
                        }
@@ -375,11 +377,17 @@ static int update_one(struct cache_tree *it,
                 * they are not part of generated trees. Invalidate up
                 * to root to force cache-tree users to read elsewhere.
                 */
-               if (ce_intent_to_add(ce)) {
+               if (!sub && ce_intent_to_add(ce)) {
                        to_invalidate = 1;
                        continue;
                }
 
+               /*
+                * "sub" can be an empty tree if all subentries are i-t-a.
+                */
+               if (contains_ita && !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))
+                       continue;
+
                strbuf_grow(&buffer, entlen + 100);
                strbuf_addf(&buffer, "%o %.*s%c", mode, entlen, path + baselen, '\0');
                strbuf_add(&buffer, sha1, 20);
index 60811a3a7ca56f995ecda5944121127e2a330bc0..1aa5093f36ea61a75cb11de5a65ed11b2b3b4e65 100755 (executable)
@@ -834,7 +834,7 @@ test_expect_success 'git write-tree should be able to write an empty tree' '
 '
 
 test_expect_success 'validate object ID of a known tree' '
-       test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904
+       test "$tree" = $EMPTY_TREE
 '
 
 # Various types of objects
index e5fa235d3a988bee620479e40574ad54c403f33a..c167f606ca7b8c1628ac8d00507d50f032278730 100755 (executable)
@@ -15,11 +15,11 @@ test_description='sparse checkout tests
 . "$TEST_DIRECTORY"/lib-read-tree.sh
 
 test_expect_success 'setup' '
-       cat >expected <<-\EOF &&
+       cat >expected <<-EOF &&
        100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0       init.t
-       100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       sub/added
-       100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       sub/addedtoo
-       100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       subsub/added
+       100644 $EMPTY_BLOB 0    sub/added
+       100644 $EMPTY_BLOB 0    sub/addedtoo
+       100644 $EMPTY_BLOB 0    subsub/added
        EOF
        cat >expected.swt <<-\EOF &&
        H init.t
index b7e9b4fc5b365897d80501d1c49d70ad47740acc..ae66ba5babf347f12f2c4cb213b0de72ea980da2 100755 (executable)
@@ -15,7 +15,7 @@ Also make sure that command line parser understands the normal
 . ./test-lib.sh
 
 cat >expected <<EOF
-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904
+tree $EMPTY_TREE
 author Author Name <author@email> 1117148400 +0000
 committer Committer Name <committer@email> 1117150200 +0000
 
index 8aef49f23624305a62047da4bc2fd66e6a03b0e5..292a0720fccb0becca47fad2945634cbffeb89d6 100755 (executable)
@@ -33,14 +33,14 @@ test_expect_success 'add one file' '
        git update-index --add one &&
        git ls-files --stage >ls-files.actual &&
        cat >ls-files.expect <<EOF &&
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      one
+100644 $EMPTY_BLOB 0   one
 EOF
        test_cmp ls-files.expect ls-files.actual &&
 
        test-dump-split-index .git/index | sed "/^own/d" >actual &&
        cat >expect <<EOF &&
 base $base
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      one
+100644 $EMPTY_BLOB 0   one
 replacements:
 deletions:
 EOF
@@ -51,7 +51,7 @@ test_expect_success 'disable split index' '
        git update-index --no-split-index &&
        git ls-files --stage >ls-files.actual &&
        cat >ls-files.expect <<EOF &&
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      one
+100644 $EMPTY_BLOB 0   one
 EOF
        test_cmp ls-files.expect ls-files.actual &&
 
@@ -67,7 +67,7 @@ test_expect_success 'enable split index again, "one" now belongs to base index"'
        git update-index --split-index &&
        git ls-files --stage >ls-files.actual &&
        cat >ls-files.expect <<EOF &&
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      one
+100644 $EMPTY_BLOB 0   one
 EOF
        test_cmp ls-files.expect ls-files.actual &&
 
@@ -105,7 +105,7 @@ test_expect_success 'add another file, which stays index' '
        git ls-files --stage >ls-files.actual &&
        cat >ls-files.expect <<EOF &&
 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0      one
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      two
+100644 $EMPTY_BLOB 0   two
 EOF
        test_cmp ls-files.expect ls-files.actual &&
 
@@ -113,7 +113,7 @@ EOF
        q_to_tab >expect <<EOF &&
 $BASE
 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      two
+100644 $EMPTY_BLOB 0   two
 replacements: 0
 deletions:
 EOF
@@ -159,14 +159,14 @@ test_expect_success 'add original file back' '
        git update-index --add one &&
        git ls-files --stage >ls-files.actual &&
        cat >ls-files.expect <<EOF &&
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      one
+100644 $EMPTY_BLOB 0   one
 EOF
        test_cmp ls-files.expect ls-files.actual &&
 
        test-dump-split-index .git/index | sed "/^own/d" >actual &&
        cat >expect <<EOF &&
 $BASE
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      one
+100644 $EMPTY_BLOB 0   one
 replacements:
 deletions: 0
 EOF
@@ -178,8 +178,8 @@ test_expect_success 'add new file' '
        git update-index --add two &&
        git ls-files --stage >actual &&
        cat >expect <<EOF &&
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      one
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      two
+100644 $EMPTY_BLOB 0   one
+100644 $EMPTY_BLOB 0   two
 EOF
        test_cmp expect actual
 '
@@ -188,8 +188,8 @@ test_expect_success 'unify index, two files remain' '
        git update-index --no-split-index &&
        git ls-files --stage >ls-files.actual &&
        cat >ls-files.expect <<EOF &&
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      one
-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0      two
+100644 $EMPTY_BLOB 0   one
+100644 $EMPTY_BLOB 0   two
 EOF
        test_cmp ls-files.expect ls-files.actual &&
 
index 2a4a749b4fa3b07963a18b645d29ef774c01bbd1..8f22c43e245cb6fb68449a64ba45222e187f56a9 100755 (executable)
@@ -82,5 +82,36 @@ test_expect_success 'cache-tree invalidates i-t-a paths' '
        test_cmp expect actual
 '
 
+test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' '
+       git init ita-in-dir &&
+       (
+               cd ita-in-dir &&
+               mkdir 2 &&
+               for f in 1 2/1 2/2 3
+               do
+                       echo "$f" >"$f"
+               done &&
+               git add 1 2/2 3 &&
+               git add -N 2/1 &&
+               git commit -m committed &&
+               git ls-tree -r HEAD >actual &&
+               grep 2/2 actual
+       )
+'
+
+test_expect_success 'cache-tree does skip dir that becomes empty' '
+       rm -fr ita-in-dir &&
+       git init ita-in-dir &&
+       (
+               cd ita-in-dir &&
+               mkdir -p 1/2/3 &&
+               echo 4 >1/2/3/4 &&
+               git add -N 1/2/3/4 &&
+               git write-tree >actual &&
+               echo $EMPTY_TREE >expected &&
+               test_cmp expected actual
+       )
+'
+
 test_done
 
index 4d4b02e760d322586eb496d72d0fd6c6b6946a02..e804377f1cbf4f2c82c1aae3d902014d634a2cdc 100755 (executable)
@@ -12,16 +12,16 @@ test_expect_success 'setup' '
 '
 
 test_expect_success 'ls-tree a[a] matches literally' '
-       cat >expect <<-\EOF &&
-       100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    a[a]/three
+       cat >expect <<-EOF &&
+       100644 blob $EMPTY_BLOB a[a]/three
        EOF
        git ls-tree -r HEAD "a[a]" >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'ls-tree outside prefix' '
-       cat >expect <<-\EOF &&
-       100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    ../a[a]/three
+       cat >expect <<-EOF &&
+       100644 blob $EMPTY_BLOB ../a[a]/three
        EOF
        ( cd aa && git ls-tree -r HEAD "../a[a]"; ) >actual &&
        test_cmp expect actual
index 43c488b545e6acc02bab9d496e33c37b99f49c7a..35b35a81c8ce38b3fe29f33412d2e7c9ff1bf68d 100755 (executable)
@@ -78,8 +78,6 @@ test_expect_success 'diff-tree pathspec' '
        test_cmp expected current
 '
 
-EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904
-
 test_expect_success 'diff-tree with wildcard shows dir also matches' '
        git diff-tree --name-only $EMPTY_TREE $tree -- "f*" >result &&
        echo file0 >expected &&
index 1d6efab3c53f673298c4e1911fd1cb4756be59f6..18f42c5fff9a6e3ccb56f9e3122c6c0469ad81a9 100755 (executable)
@@ -3,8 +3,6 @@
 test_description='test diff with a bogus tree containing the null sha1'
 . ./test-lib.sh
 
-empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904
-
 test_expect_success 'create bogus tree' '
        bogus_tree=$(
                printf "100644 fooQQQQQQQQQQQQQQQQQQQQQ" |
@@ -22,13 +20,13 @@ test_expect_success 'create tree with matching file' '
 
 test_expect_success 'raw diff shows null sha1 (addition)' '
        echo ":000000 100644 $_z40 $_z40 A      foo" >expect &&
-       git diff-tree $empty_tree $bogus_tree >actual &&
+       git diff-tree $EMPTY_TREE $bogus_tree >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'raw diff shows null sha1 (removal)' '
        echo ":100644 000000 $_z40 $_z40 D      foo" >expect &&
-       git diff-tree $bogus_tree $empty_tree >actual &&
+       git diff-tree $bogus_tree $EMPTY_TREE >actual &&
        test_cmp expect actual
 '
 
@@ -57,11 +55,11 @@ test_expect_success 'raw diff shows null sha1 (index)' '
 '
 
 test_expect_success 'patch fails due to bogus sha1 (addition)' '
-       test_must_fail git diff-tree -p $empty_tree $bogus_tree
+       test_must_fail git diff-tree -p $EMPTY_TREE $bogus_tree
 '
 
 test_expect_success 'patch fails due to bogus sha1 (removal)' '
-       test_must_fail git diff-tree -p $bogus_tree $empty_tree
+       test_must_fail git diff-tree -p $bogus_tree $EMPTY_TREE
 '
 
 test_expect_success 'patch fails due to bogus sha1 (modification)' '
index 44f3d5fb284e9848180df9ed9cfbc44a91762277..9b19cff729381b3a8f81f113a5407ac9f9d97cda 100755 (executable)
@@ -115,8 +115,8 @@ test_expect_success 'push with transfer.fsckobjects' '
        test_cmp exp act
 '
 
-cat >bogus-commit <<\EOF
-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904
+cat >bogus-commit <<EOF
+tree $EMPTY_TREE
 author Bugs Bunny 1234567890 +0000
 committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000
 
index 88d60c1ce2933141c0800a76fdebca9037803258..84f41451ec4e34b6438313545ca886fbef75f34d 100755 (executable)
@@ -23,17 +23,15 @@ S sub/1
 H sub/2
 EOF
 
-NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
-
 setup_absent() {
        test -f 1 && rm 1
        git update-index --remove 1 &&
-       git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
+       git update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 &&
        git update-index --skip-worktree 1
 }
 
 test_absent() {
-       echo "100644 $NULL_SHA1 0       1" > expected &&
+       echo "100644 $EMPTY_BLOB 0      1" > expected &&
        git ls-files --stage 1 > result &&
        test_cmp expected result &&
        test ! -f 1
@@ -42,12 +40,12 @@ test_absent() {
 setup_dirty() {
        git update-index --force-remove 1 &&
        echo dirty > 1 &&
-       git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
+       git update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 &&
        git update-index --skip-worktree 1
 }
 
 test_dirty() {
-       echo "100644 $NULL_SHA1 0       1" > expected &&
+       echo "100644 $EMPTY_BLOB 0      1" > expected &&
        git ls-files --stage 1 > result &&
        test_cmp expected result &&
        echo dirty > expected
@@ -120,7 +118,7 @@ test_expect_success 'grep with skip-worktree file' '
        test "$(git grep --no-ext-grep test)" = "1:test"
 '
 
-echo ":000000 100644 $_z40 $NULL_SHA1 A        1" > expected
+echo ":000000 100644 $_z40 $EMPTY_BLOB A       1" > expected
 test_expect_success 'diff-index does not examine skip-worktree absent entries' '
        setup_absent &&
        git diff-index HEAD -- 1 > result &&
index 9ceaa4049f960f20ca37d58e58e9e6c4e9ff4398..9d1abe50eff6772673df545d3e6715d4d2e6f2db 100755 (executable)
@@ -53,17 +53,15 @@ test_expect_success 'read-tree removes worktree, dirty case' '
        git update-index --no-skip-worktree added
 '
 
-NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
-
 setup_absent() {
        test -f 1 && rm 1
        git update-index --remove 1 &&
-       git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
+       git update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 &&
        git update-index --skip-worktree 1
 }
 
 test_absent() {
-       echo "100644 $NULL_SHA1 0       1" > expected &&
+       echo "100644 $EMPTY_BLOB 0      1" > expected &&
        git ls-files --stage 1 > result &&
        test_cmp expected result &&
        test ! -f 1
@@ -72,12 +70,12 @@ test_absent() {
 setup_dirty() {
        git update-index --force-remove 1 &&
        echo dirty > 1 &&
-       git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
+       git update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 &&
        git update-index --skip-worktree 1
 }
 
 test_dirty() {
-       echo "100644 $NULL_SHA1 0       1" > expected &&
+       echo "100644 $EMPTY_BLOB 0      1" > expected &&
        git ls-files --stage 1 > result &&
        test_cmp expected result &&
        echo dirty > expected
index 38b3890532ddfdef1f110e37aefe404596752703..c23a21cb74d56426a9948c0a37db512b093eaa57 100755 (executable)
@@ -53,7 +53,7 @@ A  two
 EOF
 
 cat >../dump.expect <<EOF &&
-info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
+info/exclude $EMPTY_BLOB
 core.excludesfile 0000000000000000000000000000000000000000
 exclude_per_dir .gitignore
 flags 00000006
@@ -137,7 +137,7 @@ EOF
 test_expect_success 'verify untracked cache dump' '
        test-dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
-info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
+info/exclude $EMPTY_BLOB
 core.excludesfile 0000000000000000000000000000000000000000
 exclude_per_dir .gitignore
 flags 00000006
@@ -184,7 +184,7 @@ EOF
 test_expect_success 'verify untracked cache dump' '
        test-dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
-info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
+info/exclude $EMPTY_BLOB
 core.excludesfile 0000000000000000000000000000000000000000
 exclude_per_dir .gitignore
 flags 00000006
index b3bdd162aaaf0fed0be9f62feab6aeb4b7019dbe..fb00e6d9b07f4cc6f478bb532749403017599400 100755 (executable)
@@ -803,7 +803,7 @@ EOF
 '
 
 cat >expect <<EOF
-:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M     dir1/modified
+:100644 100644 $EMPTY_BLOB 0000000000000000000000000000000000000000 M  dir1/modified
 EOF
 test_expect_success 'status refreshes the index' '
        touch dir2/added &&
index 3f8b98b2c54e1afdb0da42fe3de9fa5ab3f59df3..d731d66e3673f0e9d990007dd690c14d84eae783 100644 (file)
@@ -162,6 +162,9 @@ _x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05"
 # Zero SHA-1
 _z40=0000000000000000000000000000000000000000
 
+EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+EMPTY_BLOB=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
+
 # Line feed
 LF='
 '
@@ -170,7 +173,7 @@ LF='
 # when case-folding filenames
 u200c=$(printf '\342\200\214')
 
-export _x05 _x40 _z40 LF u200c
+export _x05 _x40 _z40 LF u200c EMPTY_TREE EMPTY_BLOB
 
 # Each test should start with something like this, after copyright notices:
 #