Jeff King | 4d6be03 | 2015-02-26 20:42:27 -0500 | [diff] [blame] | 1 | #!/bin/sh |
| 2 | |
Elijah Newren | 5c72261 | 2020-12-11 09:08:44 +0000 | [diff] [blame] | 3 | # NOTICE: |
| 4 | # This testsuite does a number of diffs and checks that the output match. |
| 5 | # However, it is a "garbage in, garbage out" situation; the trees have |
| 6 | # duplicate entries for individual paths, and it results in diffs that do |
| 7 | # not make much sense. As such, it is not clear that the diffs are |
| 8 | # "correct". The primary purpose of these tests was to verify that |
| 9 | # diff-tree does not segfault, but there is perhaps some value in ensuring |
| 10 | # that the diff output isn't wildly unreasonable. |
| 11 | |
Jeff King | 4d6be03 | 2015-02-26 20:42:27 -0500 | [diff] [blame] | 12 | test_description='test tree diff when trees have duplicate entries' |
| 13 | . ./test-lib.sh |
| 14 | |
| 15 | # make_tree_entry <mode> <mode> <sha1> |
| 16 | # |
| 17 | # We have to rely on perl here because not all printfs understand |
| 18 | # hex escapes (only octal), and xxd is not portable. |
| 19 | make_tree_entry () { |
| 20 | printf '%s %s\0' "$1" "$2" && |
| 21 | perl -e 'print chr(hex($_)) for ($ARGV[0] =~ /../g)' "$3" |
| 22 | } |
| 23 | |
| 24 | # Like git-mktree, but without all of the pesky sanity checking. |
| 25 | # Arguments come in groups of three, each group specifying a single |
| 26 | # tree entry (see make_tree_entry above). |
| 27 | make_tree () { |
| 28 | while test $# -gt 2; do |
| 29 | make_tree_entry "$1" "$2" "$3" |
| 30 | shift; shift; shift |
| 31 | done | |
Jeff King | 34959d8 | 2023-01-18 15:41:56 -0500 | [diff] [blame] | 32 | git hash-object --literally -w -t tree --stdin |
Jeff King | 4d6be03 | 2015-02-26 20:42:27 -0500 | [diff] [blame] | 33 | } |
| 34 | |
| 35 | # this is kind of a convoluted setup, but matches |
| 36 | # a real-world case. Each tree contains four entries |
| 37 | # for the given path, one with one sha1, and three with |
| 38 | # the other. The first tree has them split across |
| 39 | # two subtrees (which are themselves duplicate entries in |
| 40 | # the root tree), and the second has them all in a single subtree. |
| 41 | test_expect_success 'create trees with duplicate entries' ' |
| 42 | blob_one=$(echo one | git hash-object -w --stdin) && |
| 43 | blob_two=$(echo two | git hash-object -w --stdin) && |
| 44 | inner_one_a=$(make_tree \ |
| 45 | 100644 inner $blob_one |
| 46 | ) && |
| 47 | inner_one_b=$(make_tree \ |
| 48 | 100644 inner $blob_two \ |
| 49 | 100644 inner $blob_two \ |
| 50 | 100644 inner $blob_two |
| 51 | ) && |
| 52 | outer_one=$(make_tree \ |
| 53 | 040000 outer $inner_one_a \ |
| 54 | 040000 outer $inner_one_b |
| 55 | ) && |
| 56 | inner_two=$(make_tree \ |
| 57 | 100644 inner $blob_one \ |
| 58 | 100644 inner $blob_two \ |
| 59 | 100644 inner $blob_two \ |
| 60 | 100644 inner $blob_two |
| 61 | ) && |
| 62 | outer_two=$(make_tree \ |
| 63 | 040000 outer $inner_two |
| 64 | ) && |
| 65 | git tag one $outer_one && |
| 66 | git tag two $outer_two |
| 67 | ' |
| 68 | |
Elijah Newren | 5c72261 | 2020-12-11 09:08:44 +0000 | [diff] [blame] | 69 | test_expect_success 'create tree without duplicate entries' ' |
| 70 | blob_one=$(echo one | git hash-object -w --stdin) && |
| 71 | outer_three=$(make_tree \ |
| 72 | 100644 renamed $blob_one |
| 73 | ) && |
| 74 | git tag three $outer_three |
| 75 | ' |
| 76 | |
| 77 | test_expect_success 'diff-tree between duplicate trees' ' |
| 78 | # See NOTICE at top of file |
Jeff King | 4d6be03 | 2015-02-26 20:42:27 -0500 | [diff] [blame] | 79 | { |
brian m. carlson | 8125a58 | 2018-05-13 02:24:13 +0000 | [diff] [blame] | 80 | printf ":000000 100644 $ZERO_OID $blob_two A\touter/inner\n" && |
| 81 | printf ":000000 100644 $ZERO_OID $blob_two A\touter/inner\n" && |
| 82 | printf ":000000 100644 $ZERO_OID $blob_two A\touter/inner\n" && |
| 83 | printf ":100644 000000 $blob_two $ZERO_OID D\touter/inner\n" && |
| 84 | printf ":100644 000000 $blob_two $ZERO_OID D\touter/inner\n" && |
| 85 | printf ":100644 000000 $blob_two $ZERO_OID D\touter/inner\n" |
Jeff King | 4d6be03 | 2015-02-26 20:42:27 -0500 | [diff] [blame] | 86 | } >expect && |
| 87 | git diff-tree -r --no-abbrev one two >actual && |
| 88 | test_cmp expect actual |
| 89 | ' |
| 90 | |
| 91 | test_expect_success 'diff-tree with renames' ' |
Elijah Newren | 5c72261 | 2020-12-11 09:08:44 +0000 | [diff] [blame] | 92 | # See NOTICE at top of file. |
Jeff King | 4d6be03 | 2015-02-26 20:42:27 -0500 | [diff] [blame] | 93 | git diff-tree -M -r --no-abbrev one two >actual && |
Elijah Newren | 350410f | 2020-12-29 20:05:28 +0000 | [diff] [blame] | 94 | test_must_be_empty actual |
Jeff King | 4d6be03 | 2015-02-26 20:42:27 -0500 | [diff] [blame] | 95 | ' |
| 96 | |
Elijah Newren | 5c72261 | 2020-12-11 09:08:44 +0000 | [diff] [blame] | 97 | test_expect_success 'diff-tree FROM duplicate tree' ' |
| 98 | # See NOTICE at top of file. |
| 99 | { |
| 100 | printf ":100644 000000 $blob_one $ZERO_OID D\touter/inner\n" && |
| 101 | printf ":100644 000000 $blob_two $ZERO_OID D\touter/inner\n" && |
| 102 | printf ":100644 000000 $blob_two $ZERO_OID D\touter/inner\n" && |
| 103 | printf ":100644 000000 $blob_two $ZERO_OID D\touter/inner\n" && |
| 104 | printf ":000000 100644 $ZERO_OID $blob_one A\trenamed\n" |
| 105 | } >expect && |
| 106 | git diff-tree -r --no-abbrev one three >actual && |
| 107 | test_cmp expect actual |
| 108 | ' |
| 109 | |
| 110 | test_expect_success 'diff-tree FROM duplicate tree, with renames' ' |
| 111 | # See NOTICE at top of file. |
| 112 | { |
| 113 | printf ":100644 000000 $blob_two $ZERO_OID D\touter/inner\n" && |
| 114 | printf ":100644 000000 $blob_two $ZERO_OID D\touter/inner\n" && |
| 115 | printf ":100644 000000 $blob_two $ZERO_OID D\touter/inner\n" && |
| 116 | printf ":100644 100644 $blob_one $blob_one R100\touter/inner\trenamed\n" |
| 117 | } >expect && |
| 118 | git diff-tree -M -r --no-abbrev one three >actual && |
| 119 | test_cmp expect actual |
| 120 | ' |
| 121 | |
Elijah Newren | ac14de1 | 2020-12-11 09:08:45 +0000 | [diff] [blame] | 122 | test_expect_success 'create a few commits' ' |
| 123 | git commit-tree -m "Duplicate Entries" two^{tree} >commit_id && |
| 124 | git branch base $(cat commit_id) && |
| 125 | |
| 126 | git commit-tree -p $(cat commit_id) -m "Just one" three^{tree} >up && |
| 127 | git branch update $(cat up) && |
| 128 | |
| 129 | git commit-tree -p $(cat up) -m "Back to weird" two^{tree} >final && |
| 130 | git branch final $(cat final) && |
| 131 | |
| 132 | rm commit_id up final |
| 133 | ' |
| 134 | |
| 135 | test_expect_failure 'git read-tree does not segfault' ' |
| 136 | test_when_finished rm .git/index.lock && |
| 137 | test_might_fail git read-tree --reset base |
| 138 | ' |
| 139 | |
| 140 | test_expect_failure 'reset --hard does not segfault' ' |
| 141 | test_when_finished rm .git/index.lock && |
| 142 | git checkout base && |
| 143 | test_might_fail git reset --hard |
| 144 | ' |
| 145 | |
| 146 | test_expect_failure 'git diff HEAD does not segfault' ' |
| 147 | git checkout base && |
| 148 | GIT_TEST_CHECK_CACHE_TREE=false && |
| 149 | git reset --hard && |
| 150 | test_might_fail git diff HEAD |
| 151 | ' |
| 152 | |
| 153 | test_expect_failure 'can switch to another branch when status is empty' ' |
| 154 | git clean -ffdqx && |
| 155 | git status --porcelain -uno >actual && |
| 156 | test_must_be_empty actual && |
| 157 | git checkout update |
| 158 | ' |
| 159 | |
| 160 | test_expect_success 'forcibly switch to another branch, verify status empty' ' |
| 161 | git checkout -f update && |
| 162 | git status --porcelain -uno >actual && |
| 163 | test_must_be_empty actual |
| 164 | ' |
| 165 | |
| 166 | test_expect_success 'fast-forward from non-duplicate entries to duplicate' ' |
| 167 | git merge final |
| 168 | ' |
| 169 | |
| 170 | test_expect_failure 'clean status, switch branches, status still clean' ' |
| 171 | git status --porcelain -uno >actual && |
| 172 | test_must_be_empty actual && |
| 173 | git checkout base && |
| 174 | git status --porcelain -uno >actual && |
| 175 | test_must_be_empty actual |
| 176 | ' |
| 177 | |
| 178 | test_expect_success 'switch to base branch and force status to be clean' ' |
| 179 | git checkout base && |
| 180 | GIT_TEST_CHECK_CACHE_TREE=false git reset --hard && |
| 181 | git status --porcelain -uno >actual && |
| 182 | test_must_be_empty actual |
| 183 | ' |
| 184 | |
| 185 | test_expect_failure 'fast-forward from duplicate entries to non-duplicate' ' |
| 186 | git merge update |
| 187 | ' |
| 188 | |
Jeff King | 4d6be03 | 2015-02-26 20:42:27 -0500 | [diff] [blame] | 189 | test_done |