]>
Commit | Line | Data |
---|---|---|
4d6be03b JK |
1 | #!/bin/sh |
2 | ||
5c72261c EN |
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 | ||
4d6be03b JK |
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 | | |
32 | git hash-object -w -t tree --stdin | |
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 | ||
5c72261c EN |
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 | |
4d6be03b | 79 | { |
8125a58b | 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" | |
4d6be03b JK |
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' ' | |
5c72261c | 92 | # See NOTICE at top of file. |
4d6be03b | 93 | git diff-tree -M -r --no-abbrev one two >actual && |
350410f6 | 94 | test_must_be_empty actual |
4d6be03b JK |
95 | ' |
96 | ||
5c72261c EN |
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 | ||
ac14de13 EN |
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 | ||
4d6be03b | 189 | test_done |