Merge branch 'js/fsck-name-object'
[git] / t / t3034-merge-recursive-rename-options.sh
1 #!/bin/sh
2
3 test_description='merge-recursive rename options
4
5 Test rename detection by examining rename/delete conflicts.
6
7 * (HEAD -> rename) rename
8 | * (master) delete
9 |/
10 * base
11
12 git diff --name-status base master
13 D       0-old
14 D       1-old
15 D       2-old
16 D       3-old
17
18 git diff --name-status -M01 base rename
19 R025    0-old   0-new
20 R050    1-old   1-new
21 R075    2-old   2-new
22 R100    3-old   3-new
23
24 Actual similarity indices are parsed from diff output. We rely on the fact that
25 they are rounded down (see, e.g., Documentation/diff-generate-patch.txt, which
26 mentions this in a different context).
27 '
28
29 . ./test-lib.sh
30
31 get_expected_stages () {
32         git checkout rename -- $1-new &&
33         git ls-files --stage $1-new >expected-stages-undetected-$1 &&
34         sed "s/ 0       / 2     /" <expected-stages-undetected-$1 \
35                 >expected-stages-detected-$1 &&
36         git read-tree -u --reset HEAD
37 }
38
39 rename_detected () {
40         git ls-files --stage $1-old $1-new >stages-actual-$1 &&
41         test_cmp expected-stages-detected-$1 stages-actual-$1
42 }
43
44 rename_undetected () {
45         git ls-files --stage $1-old $1-new >stages-actual-$1 &&
46         test_cmp expected-stages-undetected-$1 stages-actual-$1
47 }
48
49 check_common () {
50         git ls-files --stage >stages-actual &&
51         test_line_count = 4 stages-actual
52 }
53
54 check_threshold_0 () {
55         check_common &&
56         rename_detected 0 &&
57         rename_detected 1 &&
58         rename_detected 2 &&
59         rename_detected 3
60 }
61
62 check_threshold_1 () {
63         check_common &&
64         rename_undetected 0 &&
65         rename_detected 1 &&
66         rename_detected 2 &&
67         rename_detected 3
68 }
69
70 check_threshold_2 () {
71         check_common &&
72         rename_undetected 0 &&
73         rename_undetected 1 &&
74         rename_detected 2 &&
75         rename_detected 3
76 }
77
78 check_exact_renames () {
79         check_common &&
80         rename_undetected 0 &&
81         rename_undetected 1 &&
82         rename_undetected 2 &&
83         rename_detected 3
84 }
85
86 check_no_renames () {
87         check_common &&
88         rename_undetected 0 &&
89         rename_undetected 1 &&
90         rename_undetected 2 &&
91         rename_undetected 3
92 }
93
94 test_expect_success 'setup repo' '
95         cat <<-\EOF >3-old &&
96         33a
97         33b
98         33c
99         33d
100         EOF
101         sed s/33/22/ <3-old >2-old &&
102         sed s/33/11/ <3-old >1-old &&
103         sed s/33/00/ <3-old >0-old &&
104         git add [0-3]-old &&
105         git commit -m base &&
106         git rm [0-3]-old &&
107         git commit -m delete &&
108         git checkout -b rename HEAD^ &&
109         cp 3-old 3-new &&
110         sed 1,1s/./x/ <2-old >2-new &&
111         sed 1,2s/./x/ <1-old >1-new &&
112         sed 1,3s/./x/ <0-old >0-new &&
113         git add [0-3]-new &&
114         git rm [0-3]-old &&
115         git commit -m rename &&
116         get_expected_stages 0 &&
117         get_expected_stages 1 &&
118         get_expected_stages 2 &&
119         get_expected_stages 3 &&
120         check_50="false" &&
121         tail="HEAD^ -- HEAD master"
122 '
123
124 test_expect_success 'setup thresholds' '
125         git diff --name-status -M01 HEAD^ HEAD >diff-output &&
126         test_debug "cat diff-output" &&
127         test_line_count = 4 diff-output &&
128         grep "R[0-9][0-9][0-9]  \([0-3]\)-old   \1-new" diff-output \
129                 >grep-output &&
130         test_cmp diff-output grep-output &&
131         th0=$(sed -n "s/R\(...\)        0-old   0-new/\1/p" <diff-output) &&
132         th1=$(sed -n "s/R\(...\)        1-old   1-new/\1/p" <diff-output) &&
133         th2=$(sed -n "s/R\(...\)        2-old   2-new/\1/p" <diff-output) &&
134         th3=$(sed -n "s/R\(...\)        3-old   3-new/\1/p" <diff-output) &&
135         test "$th0" -lt "$th1" &&
136         test "$th1" -lt "$th2" &&
137         test "$th2" -lt "$th3" &&
138         test "$th3" = 100 &&
139         if test 50 -le "$th0"
140         then
141                 check_50=check_threshold_0
142         elif test 50 -le "$th1"
143         then
144                 check_50=check_threshold_1
145         elif test 50 -le "$th2"
146         then
147                 check_50=check_threshold_2
148         fi &&
149         th0="$th0%" &&
150         th1="$th1%" &&
151         th2="$th2%" &&
152         th3="$th3%"
153 '
154
155 test_expect_success 'assumption for tests: rename detection with diff' '
156         git diff --name-status -M$th0 --diff-filter=R HEAD^ HEAD \
157                 >diff-output-0 &&
158         git diff --name-status -M$th1 --diff-filter=R HEAD^ HEAD \
159                 >diff-output-1 &&
160         git diff --name-status -M$th2 --diff-filter=R HEAD^ HEAD \
161                 >diff-output-2 &&
162         git diff --name-status -M100% --diff-filter=R HEAD^ HEAD \
163                 >diff-output-3 &&
164         test_line_count = 4 diff-output-0 &&
165         test_line_count = 3 diff-output-1 &&
166         test_line_count = 2 diff-output-2 &&
167         test_line_count = 1 diff-output-3
168 '
169
170 test_expect_success 'default similarity threshold is 50%' '
171         git read-tree --reset -u HEAD &&
172         test_must_fail git merge-recursive $tail &&
173         $check_50
174 '
175
176 test_expect_success 'low rename threshold' '
177         git read-tree --reset -u HEAD &&
178         test_must_fail git merge-recursive --find-renames=$th0 $tail &&
179         check_threshold_0
180 '
181
182 test_expect_success 'medium rename threshold' '
183         git read-tree --reset -u HEAD &&
184         test_must_fail git merge-recursive --find-renames=$th1 $tail &&
185         check_threshold_1
186 '
187
188 test_expect_success 'high rename threshold' '
189         git read-tree --reset -u HEAD &&
190         test_must_fail git merge-recursive --find-renames=$th2 $tail &&
191         check_threshold_2
192 '
193
194 test_expect_success 'exact renames only' '
195         git read-tree --reset -u HEAD &&
196         test_must_fail git merge-recursive --find-renames=100% $tail &&
197         check_exact_renames
198 '
199
200 test_expect_success 'rename threshold is truncated' '
201         git read-tree --reset -u HEAD &&
202         test_must_fail git merge-recursive --find-renames=200% $tail &&
203         check_exact_renames
204 '
205
206 test_expect_success 'disabled rename detection' '
207         git read-tree --reset -u HEAD &&
208         git merge-recursive --no-renames $tail &&
209         check_no_renames
210 '
211
212 test_expect_success 'last wins in --find-renames=<m> --find-renames=<n>' '
213         git read-tree --reset -u HEAD &&
214         test_must_fail git merge-recursive \
215                 --find-renames=$th0 --find-renames=$th2 $tail &&
216         check_threshold_2
217 '
218
219 test_expect_success '--find-renames resets threshold' '
220         git read-tree --reset -u HEAD &&
221         test_must_fail git merge-recursive \
222                 --find-renames=$th0 --find-renames $tail &&
223         $check_50
224 '
225
226 test_expect_success 'last wins in --no-renames --find-renames' '
227         git read-tree --reset -u HEAD &&
228         test_must_fail git merge-recursive --no-renames --find-renames $tail &&
229         $check_50
230 '
231
232 test_expect_success 'last wins in --find-renames --no-renames' '
233         git read-tree --reset -u HEAD &&
234         git merge-recursive --find-renames --no-renames $tail &&
235         check_no_renames
236 '
237
238 test_expect_success 'assumption for further tests: trivial merge succeeds' '
239         git read-tree --reset -u HEAD &&
240         git merge-recursive HEAD -- HEAD HEAD &&
241         git diff --quiet --cached &&
242         git merge-recursive --find-renames=$th0 HEAD -- HEAD HEAD &&
243         git diff --quiet --cached &&
244         git merge-recursive --find-renames=$th2 HEAD -- HEAD HEAD &&
245         git diff --quiet --cached &&
246         git merge-recursive --find-renames=100% HEAD -- HEAD HEAD &&
247         git diff --quiet --cached &&
248         git merge-recursive --no-renames HEAD -- HEAD HEAD &&
249         git diff --quiet --cached
250 '
251
252 test_expect_success '--find-renames rejects negative argument' '
253         git read-tree --reset -u HEAD &&
254         test_must_fail git merge-recursive --find-renames=-25 \
255                 HEAD -- HEAD HEAD &&
256         git diff --quiet --cached
257 '
258
259 test_expect_success '--find-renames rejects non-numbers' '
260         git read-tree --reset -u HEAD &&
261         test_must_fail git merge-recursive --find-renames=0xf \
262                 HEAD -- HEAD HEAD &&
263         git diff --quiet --cached
264 '
265
266 test_expect_success 'rename-threshold=<n> is a synonym for find-renames=<n>' '
267         git read-tree --reset -u HEAD &&
268         test_must_fail git merge-recursive --rename-threshold=$th0 $tail &&
269         check_threshold_0
270 '
271
272 test_expect_success 'last wins in --no-renames --rename-threshold=<n>' '
273         git read-tree --reset -u HEAD &&
274         test_must_fail git merge-recursive --no-renames --rename-threshold=$th0 $tail &&
275         check_threshold_0
276 '
277
278 test_expect_success 'last wins in --rename-threshold=<n> --no-renames' '
279         git read-tree --reset -u HEAD &&
280         git merge-recursive --rename-threshold=$th0 --no-renames $tail &&
281         check_no_renames
282 '
283
284 test_expect_success '--rename-threshold=<n> rejects negative argument' '
285         git read-tree --reset -u HEAD &&
286         test_must_fail git merge-recursive --rename-threshold=-25 \
287                 HEAD -- HEAD HEAD &&
288         git diff --quiet --cached
289 '
290
291 test_expect_success '--rename-threshold=<n> rejects non-numbers' '
292         git read-tree --reset -u HEAD &&
293         test_must_fail git merge-recursive --rename-threshold=0xf \
294                 HEAD -- HEAD HEAD &&
295         git diff --quiet --cached
296 '
297
298 test_expect_success 'last wins in --rename-threshold=<m> --find-renames=<n>' '
299         git read-tree --reset -u HEAD &&
300         test_must_fail git merge-recursive \
301                 --rename-threshold=$th0 --find-renames=$th2 $tail &&
302         check_threshold_2
303 '
304
305 test_expect_success 'last wins in --find-renames=<m> --rename-threshold=<n>' '
306         git read-tree --reset -u HEAD &&
307         test_must_fail git merge-recursive \
308                 --find-renames=$th2 --rename-threshold=$th0 $tail &&
309         check_threshold_0
310 '
311
312 test_done