Merge branch 'jk/no-common'
[git] / t / t6030-bisect-porcelain.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Christian Couder
4 #
5 test_description='Tests git bisect functionality'
6
7 exec </dev/null
8
9 . ./test-lib.sh
10
11 add_line_into_file()
12 {
13     _line=$1
14     _file=$2
15
16     if [ -f "$_file" ]; then
17         echo "$_line" >> $_file || return $?
18         MSG="Add <$_line> into <$_file>."
19     else
20         echo "$_line" > $_file || return $?
21         git add $_file || return $?
22         MSG="Create file <$_file> with <$_line> inside."
23     fi
24
25     test_tick
26     git commit --quiet -m "$MSG" $_file
27 }
28
29 HASH1=
30 HASH2=
31 HASH3=
32 HASH4=
33
34 test_expect_success 'set up basic repo with 1 file (hello) and 4 commits' '
35      add_line_into_file "1: Hello World" hello &&
36      HASH1=$(git rev-parse --verify HEAD) &&
37      add_line_into_file "2: A new day for git" hello &&
38      HASH2=$(git rev-parse --verify HEAD) &&
39      add_line_into_file "3: Another new day for git" hello &&
40      HASH3=$(git rev-parse --verify HEAD) &&
41      add_line_into_file "4: Ciao for now" hello &&
42      HASH4=$(git rev-parse --verify HEAD)
43 '
44
45 test_expect_success 'bisect starts with only one bad' '
46         git bisect reset &&
47         git bisect start &&
48         git bisect bad $HASH4 &&
49         git bisect next
50 '
51
52 test_expect_success 'bisect does not start with only one good' '
53         git bisect reset &&
54         git bisect start &&
55         git bisect good $HASH1 &&
56         test_must_fail git bisect next
57 '
58
59 test_expect_success 'bisect start with one bad and good' '
60         git bisect reset &&
61         git bisect start &&
62         git bisect good $HASH1 &&
63         git bisect bad $HASH4 &&
64         git bisect next
65 '
66
67 test_expect_success 'bisect fails if given any junk instead of revs' '
68         git bisect reset &&
69         test_must_fail git bisect start foo $HASH1 -- &&
70         test_must_fail git bisect start $HASH4 $HASH1 bar -- &&
71         test -z "$(git for-each-ref "refs/bisect/*")" &&
72         test -z "$(ls .git/BISECT_* 2>/dev/null)" &&
73         git bisect start &&
74         test_must_fail git bisect good foo $HASH1 &&
75         test_must_fail git bisect good $HASH1 bar &&
76         test_must_fail git bisect bad frotz &&
77         test_must_fail git bisect bad $HASH3 $HASH4 &&
78         test_must_fail git bisect skip bar $HASH3 &&
79         test_must_fail git bisect skip $HASH1 foo &&
80         test -z "$(git for-each-ref "refs/bisect/*")" &&
81         git bisect good $HASH1 &&
82         git bisect bad $HASH4
83 '
84
85 test_expect_success 'bisect start without -- takes unknown arg as pathspec' '
86         git bisect reset &&
87         git bisect start foo bar &&
88         grep foo ".git/BISECT_NAMES" &&
89         grep bar ".git/BISECT_NAMES"
90 '
91
92 test_expect_success 'bisect reset: back in the master branch' '
93         git bisect reset &&
94         echo "* master" > branch.expect &&
95         git branch > branch.output &&
96         cmp branch.expect branch.output
97 '
98
99 test_expect_success 'bisect reset: back in another branch' '
100         git checkout -b other &&
101         git bisect start &&
102         git bisect good $HASH1 &&
103         git bisect bad $HASH3 &&
104         git bisect reset &&
105         echo "  master" > branch.expect &&
106         echo "* other" >> branch.expect &&
107         git branch > branch.output &&
108         cmp branch.expect branch.output
109 '
110
111 test_expect_success 'bisect reset when not bisecting' '
112         git bisect reset &&
113         git branch > branch.output &&
114         cmp branch.expect branch.output
115 '
116
117 test_expect_success 'bisect reset removes packed refs' '
118         git bisect reset &&
119         git bisect start &&
120         git bisect good $HASH1 &&
121         git bisect bad $HASH3 &&
122         git pack-refs --all --prune &&
123         git bisect next &&
124         git bisect reset &&
125         test -z "$(git for-each-ref "refs/bisect/*")" &&
126         test -z "$(git for-each-ref "refs/heads/bisect")"
127 '
128
129 test_expect_success 'bisect reset removes bisect state after --no-checkout' '
130         git bisect reset &&
131         git bisect start --no-checkout &&
132         git bisect good $HASH1 &&
133         git bisect bad $HASH3 &&
134         git bisect next &&
135         git bisect reset &&
136         test -z "$(git for-each-ref "refs/bisect/*")" &&
137         test -z "$(git for-each-ref "refs/heads/bisect")" &&
138         test -z "$(git for-each-ref "BISECT_HEAD")"
139 '
140
141 test_expect_success 'bisect start: back in good branch' '
142         git branch > branch.output &&
143         grep "* other" branch.output > /dev/null &&
144         git bisect start $HASH4 $HASH1 -- &&
145         git bisect good &&
146         git bisect start $HASH4 $HASH1 -- &&
147         git bisect bad &&
148         git bisect reset &&
149         git branch > branch.output &&
150         grep "* other" branch.output > /dev/null
151 '
152
153 test_expect_success 'bisect start: no ".git/BISECT_START" created if junk rev' '
154         git bisect reset &&
155         test_must_fail git bisect start $HASH4 foo -- &&
156         git branch > branch.output &&
157         grep "* other" branch.output > /dev/null &&
158         test_path_is_missing .git/BISECT_START
159 '
160
161 test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if junk rev' '
162         git bisect start $HASH4 $HASH1 -- &&
163         git bisect good &&
164         cp .git/BISECT_START saved &&
165         test_must_fail git bisect start $HASH4 foo -- &&
166         git branch > branch.output &&
167         test_i18ngrep "* (no branch, bisect started on other)" branch.output > /dev/null &&
168         test_cmp saved .git/BISECT_START
169 '
170 test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' '
171         git bisect start $HASH4 $HASH1 -- &&
172         git bisect good &&
173         test_must_fail git bisect start $HASH1 $HASH4 -- &&
174         git branch > branch.output &&
175         grep "* other" branch.output > /dev/null &&
176         test_path_is_missing .git/BISECT_START
177 '
178
179 test_expect_success 'bisect start: no ".git/BISECT_START" if checkout error' '
180         echo "temp stuff" > hello &&
181         test_must_fail git bisect start $HASH4 $HASH1 -- &&
182         git branch &&
183         git branch > branch.output &&
184         grep "* other" branch.output > /dev/null &&
185         test_path_is_missing .git/BISECT_START &&
186         test -z "$(git for-each-ref "refs/bisect/*")" &&
187         git checkout HEAD hello
188 '
189
190 # $HASH1 is good, $HASH4 is bad, we skip $HASH3
191 # but $HASH2 is bad,
192 # so we should find $HASH2 as the first bad commit
193 test_expect_success 'bisect skip: successful result' '
194         test_when_finished git bisect reset &&
195         git bisect reset &&
196         git bisect start $HASH4 $HASH1 &&
197         git bisect skip &&
198         git bisect bad > my_bisect_log.txt &&
199         grep "$HASH2 is the first bad commit" my_bisect_log.txt
200 '
201
202 # $HASH1 is good, $HASH4 is bad, we skip $HASH3 and $HASH2
203 # so we should not be able to tell the first bad commit
204 # among $HASH2, $HASH3 and $HASH4
205 test_expect_success 'bisect skip: cannot tell between 3 commits' '
206         test_when_finished git bisect reset &&
207         git bisect start $HASH4 $HASH1 &&
208         git bisect skip &&
209         test_expect_code 2 git bisect skip >my_bisect_log.txt &&
210         grep "first bad commit could be any of" my_bisect_log.txt &&
211         ! grep $HASH1 my_bisect_log.txt &&
212         grep $HASH2 my_bisect_log.txt &&
213         grep $HASH3 my_bisect_log.txt &&
214         grep $HASH4 my_bisect_log.txt
215 '
216
217 # $HASH1 is good, $HASH4 is bad, we skip $HASH3
218 # but $HASH2 is good,
219 # so we should not be able to tell the first bad commit
220 # among $HASH3 and $HASH4
221 test_expect_success 'bisect skip: cannot tell between 2 commits' '
222         test_when_finished git bisect reset &&
223         git bisect start $HASH4 $HASH1 &&
224         git bisect skip &&
225         test_expect_code 2 git bisect good >my_bisect_log.txt &&
226         grep "first bad commit could be any of" my_bisect_log.txt &&
227         ! grep $HASH1 my_bisect_log.txt &&
228         ! grep $HASH2 my_bisect_log.txt &&
229         grep $HASH3 my_bisect_log.txt &&
230         grep $HASH4 my_bisect_log.txt
231 '
232
233 # $HASH1 is good, $HASH4 is both skipped and bad, we skip $HASH3
234 # and $HASH2 is good,
235 # so we should not be able to tell the first bad commit
236 # among $HASH3 and $HASH4
237 test_expect_success 'bisect skip: with commit both bad and skipped' '
238         test_when_finished git bisect reset &&
239         git bisect start &&
240         git bisect skip &&
241         git bisect bad &&
242         git bisect good $HASH1 &&
243         git bisect skip &&
244         test_expect_code 2 git bisect good >my_bisect_log.txt &&
245         grep "first bad commit could be any of" my_bisect_log.txt &&
246         ! grep $HASH1 my_bisect_log.txt &&
247         ! grep $HASH2 my_bisect_log.txt &&
248         grep $HASH3 my_bisect_log.txt &&
249         grep $HASH4 my_bisect_log.txt
250 '
251
252 # We want to automatically find the commit that
253 # added "Another" into hello.
254 test_expect_success '"git bisect run" simple case' '
255         write_script test_script.sh <<-\EOF &&
256         ! grep Another hello >/dev/null
257         EOF
258         git bisect start &&
259         git bisect good $HASH1 &&
260         git bisect bad $HASH4 &&
261         git bisect run ./test_script.sh >my_bisect_log.txt &&
262         grep "$HASH3 is the first bad commit" my_bisect_log.txt &&
263         git bisect reset
264 '
265
266 # We want to automatically find the commit that
267 # added "Ciao" into hello.
268 test_expect_success '"git bisect run" with more complex "git bisect start"' '
269         write_script test_script.sh <<-\EOF &&
270         ! grep Ciao hello >/dev/null
271         EOF
272         git bisect start $HASH4 $HASH1 &&
273         git bisect run ./test_script.sh >my_bisect_log.txt &&
274         grep "$HASH4 is the first bad commit" my_bisect_log.txt &&
275         git bisect reset
276 '
277
278 # $HASH1 is good, $HASH5 is bad, we skip $HASH3
279 # but $HASH4 is good,
280 # so we should find $HASH5 as the first bad commit
281 HASH5=
282 test_expect_success 'bisect skip: add line and then a new test' '
283         add_line_into_file "5: Another new line." hello &&
284         HASH5=$(git rev-parse --verify HEAD) &&
285         git bisect start $HASH5 $HASH1 &&
286         git bisect skip &&
287         git bisect good > my_bisect_log.txt &&
288         grep "$HASH5 is the first bad commit" my_bisect_log.txt &&
289         git bisect log > log_to_replay.txt &&
290         git bisect reset
291 '
292
293 test_expect_success 'bisect skip and bisect replay' '
294         git bisect replay log_to_replay.txt > my_bisect_log.txt &&
295         grep "$HASH5 is the first bad commit" my_bisect_log.txt &&
296         git bisect reset
297 '
298
299 HASH6=
300 test_expect_success 'bisect run & skip: cannot tell between 2' '
301         add_line_into_file "6: Yet a line." hello &&
302         HASH6=$(git rev-parse --verify HEAD) &&
303         write_script test_script.sh <<-\EOF &&
304         sed -ne \$p hello | grep Ciao >/dev/null && exit 125
305         ! grep line hello >/dev/null
306         EOF
307         git bisect start $HASH6 $HASH1 &&
308         test_expect_code 2 git bisect run ./test_script.sh >my_bisect_log.txt &&
309         grep "first bad commit could be any of" my_bisect_log.txt &&
310         ! grep $HASH3 my_bisect_log.txt &&
311         ! grep $HASH6 my_bisect_log.txt &&
312         grep $HASH4 my_bisect_log.txt &&
313         grep $HASH5 my_bisect_log.txt
314 '
315
316 HASH7=
317 test_expect_success 'bisect run & skip: find first bad' '
318         git bisect reset &&
319         add_line_into_file "7: Should be the last line." hello &&
320         HASH7=$(git rev-parse --verify HEAD) &&
321         write_script test_script.sh <<-\EOF &&
322         sed -ne \$p hello | grep Ciao >/dev/null && exit 125
323         sed -ne \$p hello | grep day >/dev/null && exit 125
324         ! grep Yet hello >/dev/null
325         EOF
326         git bisect start $HASH7 $HASH1 &&
327         git bisect run ./test_script.sh >my_bisect_log.txt &&
328         grep "$HASH6 is the first bad commit" my_bisect_log.txt
329 '
330
331 test_expect_success 'bisect skip only one range' '
332         git bisect reset &&
333         git bisect start $HASH7 $HASH1 &&
334         git bisect skip $HASH1..$HASH5 &&
335         test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
336         test_must_fail git bisect bad > my_bisect_log.txt &&
337         grep "first bad commit could be any of" my_bisect_log.txt
338 '
339
340 test_expect_success 'bisect skip many ranges' '
341         git bisect start $HASH7 $HASH1 &&
342         test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
343         git bisect skip $HASH2 $HASH2.. ..$HASH5 &&
344         test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
345         test_must_fail git bisect bad > my_bisect_log.txt &&
346         grep "first bad commit could be any of" my_bisect_log.txt
347 '
348
349 test_expect_success 'bisect starting with a detached HEAD' '
350         git bisect reset &&
351         git checkout master^ &&
352         HEAD=$(git rev-parse --verify HEAD) &&
353         git bisect start &&
354         test $HEAD = $(cat .git/BISECT_START) &&
355         git bisect reset &&
356         test $HEAD = $(git rev-parse --verify HEAD)
357 '
358
359 test_expect_success 'bisect errors out if bad and good are mistaken' '
360         git bisect reset &&
361         test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error &&
362         test_i18ngrep "mistook good and bad" rev_list_error &&
363         git bisect reset
364 '
365
366 test_expect_success 'bisect does not create a "bisect" branch' '
367         git bisect reset &&
368         git bisect start $HASH7 $HASH1 &&
369         git branch bisect &&
370         rev_hash4=$(git rev-parse --verify HEAD) &&
371         test "$rev_hash4" = "$HASH4" &&
372         git branch -D bisect &&
373         git bisect good &&
374         git branch bisect &&
375         rev_hash6=$(git rev-parse --verify HEAD) &&
376         test "$rev_hash6" = "$HASH6" &&
377         git bisect good > my_bisect_log.txt &&
378         grep "$HASH7 is the first bad commit" my_bisect_log.txt &&
379         git bisect reset &&
380         rev_hash6=$(git rev-parse --verify bisect) &&
381         test "$rev_hash6" = "$HASH6" &&
382         git branch -D bisect
383 '
384
385 # This creates a "side" branch to test "siblings" cases.
386 #
387 # H1-H2-H3-H4-H5-H6-H7  <--other
388 #            \
389 #             S5-S6-S7  <--side
390 #
391 test_expect_success 'side branch creation' '
392         git bisect reset &&
393         git checkout -b side $HASH4 &&
394         add_line_into_file "5(side): first line on a side branch" hello2 &&
395         SIDE_HASH5=$(git rev-parse --verify HEAD) &&
396         add_line_into_file "6(side): second line on a side branch" hello2 &&
397         SIDE_HASH6=$(git rev-parse --verify HEAD) &&
398         add_line_into_file "7(side): third line on a side branch" hello2 &&
399         SIDE_HASH7=$(git rev-parse --verify HEAD)
400 '
401
402 test_expect_success 'good merge base when good and bad are siblings' '
403         git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
404         test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
405         grep $HASH4 my_bisect_log.txt &&
406         git bisect good > my_bisect_log.txt &&
407         ! grep "merge base must be tested" my_bisect_log.txt &&
408         grep $HASH6 my_bisect_log.txt &&
409         git bisect reset
410 '
411 test_expect_success 'skipped merge base when good and bad are siblings' '
412         git bisect start "$SIDE_HASH7" "$HASH7" > my_bisect_log.txt &&
413         test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
414         grep $HASH4 my_bisect_log.txt &&
415         git bisect skip > my_bisect_log.txt 2>&1 &&
416         grep "warning" my_bisect_log.txt &&
417         grep $SIDE_HASH6 my_bisect_log.txt &&
418         git bisect reset
419 '
420
421 test_expect_success 'bad merge base when good and bad are siblings' '
422         git bisect start "$HASH7" HEAD > my_bisect_log.txt &&
423         test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
424         grep $HASH4 my_bisect_log.txt &&
425         test_must_fail git bisect bad > my_bisect_log.txt 2>&1 &&
426         test_i18ngrep "merge base $HASH4 is bad" my_bisect_log.txt &&
427         test_i18ngrep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt &&
428         git bisect reset
429 '
430
431 # This creates a few more commits (A and B) to test "siblings" cases
432 # when a good and a bad rev have many merge bases.
433 #
434 # We should have the following:
435 #
436 # H1-H2-H3-H4-H5-H6-H7
437 #            \  \     \
438 #             S5-A     \
439 #              \        \
440 #               S6-S7----B
441 #
442 # And there A and B have 2 merge bases (S5 and H5) that should be
443 # reported by "git merge-base --all A B".
444 #
445 test_expect_success 'many merge bases creation' '
446         git checkout "$SIDE_HASH5" &&
447         git merge -m "merge HASH5 and SIDE_HASH5" "$HASH5" &&
448         A_HASH=$(git rev-parse --verify HEAD) &&
449         git checkout side &&
450         git merge -m "merge HASH7 and SIDE_HASH7" "$HASH7" &&
451         B_HASH=$(git rev-parse --verify HEAD) &&
452         git merge-base --all "$A_HASH" "$B_HASH" > merge_bases.txt &&
453         test_line_count = 2 merge_bases.txt &&
454         grep "$HASH5" merge_bases.txt &&
455         grep "$SIDE_HASH5" merge_bases.txt
456 '
457
458 # We want to automatically find the merge that
459 # added "line" into hello.
460 test_expect_success '"git bisect run --first-parent" simple case' '
461         git rev-list --first-parent $B_HASH ^$HASH4 >first_parent_chain.txt &&
462         write_script test_script.sh <<-\EOF &&
463         grep $(git rev-parse HEAD) first_parent_chain.txt || exit -1
464         ! grep line hello >/dev/null
465         EOF
466         git bisect start --first-parent &&
467         test_path_is_file ".git/BISECT_FIRST_PARENT" &&
468         git bisect good $HASH4 &&
469         git bisect bad $B_HASH &&
470         git bisect run ./test_script.sh >my_bisect_log.txt &&
471         grep "$B_HASH is the first bad commit" my_bisect_log.txt &&
472         git bisect reset &&
473         test_path_is_missing .git/BISECT_FIRST_PARENT
474 '
475
476 test_expect_success 'good merge bases when good and bad are siblings' '
477         git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt &&
478         test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
479         git bisect good > my_bisect_log2.txt &&
480         test_i18ngrep "merge base must be tested" my_bisect_log2.txt &&
481         {
482                 {
483                         grep "$SIDE_HASH5" my_bisect_log.txt &&
484                         grep "$HASH5" my_bisect_log2.txt
485                 } || {
486                         grep "$SIDE_HASH5" my_bisect_log2.txt &&
487                         grep "$HASH5" my_bisect_log.txt
488                 }
489         } &&
490         git bisect reset
491 '
492
493 test_expect_success 'optimized merge base checks' '
494         git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
495         test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
496         grep "$HASH4" my_bisect_log.txt &&
497         git bisect good > my_bisect_log2.txt &&
498         test -f ".git/BISECT_ANCESTORS_OK" &&
499         test "$HASH6" = $(git rev-parse --verify HEAD) &&
500         git bisect bad &&
501         git bisect good "$A_HASH" > my_bisect_log4.txt &&
502         test_i18ngrep "merge base must be tested" my_bisect_log4.txt &&
503         test_path_is_missing ".git/BISECT_ANCESTORS_OK"
504 '
505
506 # This creates another side branch called "parallel" with some files
507 # in some directories, to test bisecting with paths.
508 #
509 # We should have the following:
510 #
511 #    P1-P2-P3-P4-P5-P6-P7
512 #   /        /        /
513 # H1-H2-H3-H4-H5-H6-H7
514 #            \  \     \
515 #             S5-A     \
516 #              \        \
517 #               S6-S7----B
518 #
519 test_expect_success '"parallel" side branch creation' '
520         git bisect reset &&
521         git checkout -b parallel $HASH1 &&
522         mkdir dir1 dir2 &&
523         add_line_into_file "1(para): line 1 on parallel branch" dir1/file1 &&
524         PARA_HASH1=$(git rev-parse --verify HEAD) &&
525         add_line_into_file "2(para): line 2 on parallel branch" dir2/file2 &&
526         PARA_HASH2=$(git rev-parse --verify HEAD) &&
527         add_line_into_file "3(para): line 3 on parallel branch" dir2/file3 &&
528         PARA_HASH3=$(git rev-parse --verify HEAD) &&
529         git merge -m "merge HASH4 and PARA_HASH3" "$HASH4" &&
530         PARA_HASH4=$(git rev-parse --verify HEAD) &&
531         add_line_into_file "5(para): add line on parallel branch" dir1/file1 &&
532         PARA_HASH5=$(git rev-parse --verify HEAD) &&
533         add_line_into_file "6(para): add line on parallel branch" dir2/file2 &&
534         PARA_HASH6=$(git rev-parse --verify HEAD) &&
535         git merge -m "merge HASH7 and PARA_HASH6" "$HASH7" &&
536         PARA_HASH7=$(git rev-parse --verify HEAD)
537 '
538
539 test_expect_success 'restricting bisection on one dir' '
540         git bisect reset &&
541         git bisect start HEAD $HASH1 -- dir1 &&
542         para1=$(git rev-parse --verify HEAD) &&
543         test "$para1" = "$PARA_HASH1" &&
544         git bisect bad > my_bisect_log.txt &&
545         grep "$PARA_HASH1 is the first bad commit" my_bisect_log.txt
546 '
547
548 test_expect_success 'restricting bisection on one dir and a file' '
549         git bisect reset &&
550         git bisect start HEAD $HASH1 -- dir1 hello &&
551         para4=$(git rev-parse --verify HEAD) &&
552         test "$para4" = "$PARA_HASH4" &&
553         git bisect bad &&
554         hash3=$(git rev-parse --verify HEAD) &&
555         test "$hash3" = "$HASH3" &&
556         git bisect good &&
557         hash4=$(git rev-parse --verify HEAD) &&
558         test "$hash4" = "$HASH4" &&
559         git bisect good &&
560         para1=$(git rev-parse --verify HEAD) &&
561         test "$para1" = "$PARA_HASH1" &&
562         git bisect good > my_bisect_log.txt &&
563         grep "$PARA_HASH4 is the first bad commit" my_bisect_log.txt
564 '
565
566 test_expect_success 'skipping away from skipped commit' '
567         git bisect start $PARA_HASH7 $HASH1 &&
568         para4=$(git rev-parse --verify HEAD) &&
569         test "$para4" = "$PARA_HASH4" &&
570         git bisect skip &&
571         hash7=$(git rev-parse --verify HEAD) &&
572         test "$hash7" = "$HASH7" &&
573         git bisect skip &&
574         para3=$(git rev-parse --verify HEAD) &&
575         test "$para3" = "$PARA_HASH3"
576 '
577
578 test_expect_success 'erroring out when using bad path parameters' '
579         test_must_fail git bisect start $PARA_HASH7 $HASH1 -- foobar 2> error.txt &&
580         test_i18ngrep "bad path parameters" error.txt
581 '
582
583 test_expect_success 'test bisection on bare repo - --no-checkout specified' '
584         git clone --bare . bare.nocheckout &&
585         (
586                 cd bare.nocheckout &&
587                 git bisect start --no-checkout &&
588                 git bisect good $HASH1 &&
589                 git bisect bad $HASH4 &&
590                 git bisect run eval \
591                         "test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \
592                         >../nocheckout.log
593         ) &&
594         grep "$HASH3 is the first bad commit" nocheckout.log
595 '
596
597
598 test_expect_success 'test bisection on bare repo - --no-checkout defaulted' '
599         git clone --bare . bare.defaulted &&
600         (
601                 cd bare.defaulted &&
602                 git bisect start &&
603                 git bisect good $HASH1 &&
604                 git bisect bad $HASH4 &&
605                 git bisect run eval \
606                         "test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \
607                         >../defaulted.log
608         ) &&
609         grep "$HASH3 is the first bad commit" defaulted.log
610 '
611
612 #
613 # This creates a broken branch which cannot be checked out because
614 # the tree created has been deleted.
615 #
616 # H1-H2-H3-H4-H5-H6-H7  <--other
617 #            \
618 #             S5-S6'-S7'-S8'-S9  <--broken
619 #
620 # Commits marked with ' have a missing tree.
621 #
622 test_expect_success 'broken branch creation' '
623         git bisect reset &&
624         git checkout -b broken $HASH4 &&
625         git tag BROKEN_HASH4 $HASH4 &&
626         add_line_into_file "5(broken): first line on a broken branch" hello2 &&
627         git tag BROKEN_HASH5 &&
628         mkdir missing &&
629         :> missing/MISSING &&
630         git add missing/MISSING &&
631         git commit -m "6(broken): Added file that will be deleted" &&
632         git tag BROKEN_HASH6 &&
633         deleted=$(git rev-parse --verify HEAD:missing) &&
634         add_line_into_file "7(broken): second line on a broken branch" hello2 &&
635         git tag BROKEN_HASH7 &&
636         add_line_into_file "8(broken): third line on a broken branch" hello2 &&
637         git tag BROKEN_HASH8 &&
638         git rm missing/MISSING &&
639         git commit -m "9(broken): Remove missing file" &&
640         git tag BROKEN_HASH9 &&
641         rm .git/objects/$(test_oid_to_path $deleted)
642 '
643
644 echo "" > expected.ok
645 cat > expected.missing-tree.default <<EOF
646 fatal: unable to read tree $deleted
647 EOF
648
649 test_expect_success 'bisect fails if tree is broken on start commit' '
650         git bisect reset &&
651         test_must_fail git bisect start BROKEN_HASH7 BROKEN_HASH4 2>error.txt &&
652         test_cmp expected.missing-tree.default error.txt
653 '
654
655 test_expect_success 'bisect fails if tree is broken on trial commit' '
656         git bisect reset &&
657         test_must_fail git bisect start BROKEN_HASH9 BROKEN_HASH4 2>error.txt &&
658         git reset --hard broken &&
659         git checkout broken &&
660         test_cmp expected.missing-tree.default error.txt
661 '
662
663 check_same()
664 {
665         echo "Checking $1 is the same as $2" &&
666         test_cmp_rev "$1" "$2"
667 }
668
669 test_expect_success 'bisect: --no-checkout - start commit bad' '
670         git bisect reset &&
671         git bisect start BROKEN_HASH7 BROKEN_HASH4 --no-checkout &&
672         check_same BROKEN_HASH6 BISECT_HEAD &&
673         git bisect reset
674 '
675
676 test_expect_success 'bisect: --no-checkout - trial commit bad' '
677         git bisect reset &&
678         git bisect start broken BROKEN_HASH4 --no-checkout &&
679         check_same BROKEN_HASH6 BISECT_HEAD &&
680         git bisect reset
681 '
682
683 test_expect_success 'bisect: --no-checkout - target before breakage' '
684         git bisect reset &&
685         git bisect start broken BROKEN_HASH4 --no-checkout &&
686         check_same BROKEN_HASH6 BISECT_HEAD &&
687         git bisect bad BISECT_HEAD &&
688         check_same BROKEN_HASH5 BISECT_HEAD &&
689         git bisect bad BISECT_HEAD &&
690         check_same BROKEN_HASH5 bisect/bad &&
691         git bisect reset
692 '
693
694 test_expect_success 'bisect: --no-checkout - target in breakage' '
695         git bisect reset &&
696         git bisect start broken BROKEN_HASH4 --no-checkout &&
697         check_same BROKEN_HASH6 BISECT_HEAD &&
698         git bisect bad BISECT_HEAD &&
699         check_same BROKEN_HASH5 BISECT_HEAD &&
700         test_must_fail git bisect good BISECT_HEAD &&
701         check_same BROKEN_HASH6 bisect/bad &&
702         git bisect reset
703 '
704
705 test_expect_success 'bisect: --no-checkout - target after breakage' '
706         git bisect reset &&
707         git bisect start broken BROKEN_HASH4 --no-checkout &&
708         check_same BROKEN_HASH6 BISECT_HEAD &&
709         git bisect good BISECT_HEAD &&
710         check_same BROKEN_HASH8 BISECT_HEAD &&
711         test_must_fail git bisect good BISECT_HEAD &&
712         check_same BROKEN_HASH9 bisect/bad &&
713         git bisect reset
714 '
715
716 test_expect_success 'bisect: demonstrate identification of damage boundary' "
717         git bisect reset &&
718         git checkout broken &&
719         git bisect start broken master --no-checkout &&
720         test_must_fail git bisect run \"\$SHELL_PATH\" -c '
721                 GOOD=\$(git for-each-ref \"--format=%(objectname)\" refs/bisect/good-*) &&
722                 git rev-list --objects BISECT_HEAD --not \$GOOD >tmp.\$\$ &&
723                 git pack-objects --stdout >/dev/null < tmp.\$\$
724                 rc=\$?
725                 rm -f tmp.\$\$
726                 test \$rc = 0' &&
727         check_same BROKEN_HASH6 bisect/bad &&
728         git bisect reset
729 "
730
731 cat > expected.bisect-log <<EOF
732 # bad: [$HASH4] Add <4: Ciao for now> into <hello>.
733 # good: [$HASH2] Add <2: A new day for git> into <hello>.
734 git bisect start '$HASH4' '$HASH2'
735 # good: [$HASH3] Add <3: Another new day for git> into <hello>.
736 git bisect good $HASH3
737 # first bad commit: [$HASH4] Add <4: Ciao for now> into <hello>.
738 EOF
739
740 test_expect_success 'bisect log: successful result' '
741         git bisect reset &&
742         git bisect start $HASH4 $HASH2 &&
743         git bisect good &&
744         git bisect log >bisect-log.txt &&
745         test_cmp expected.bisect-log bisect-log.txt &&
746         git bisect reset
747 '
748
749 cat > expected.bisect-skip-log <<EOF
750 # bad: [$HASH4] Add <4: Ciao for now> into <hello>.
751 # good: [$HASH2] Add <2: A new day for git> into <hello>.
752 git bisect start '$HASH4' '$HASH2'
753 # skip: [$HASH3] Add <3: Another new day for git> into <hello>.
754 git bisect skip $HASH3
755 # only skipped commits left to test
756 # possible first bad commit: [$HASH4] Add <4: Ciao for now> into <hello>.
757 # possible first bad commit: [$HASH3] Add <3: Another new day for git> into <hello>.
758 EOF
759
760 test_expect_success 'bisect log: only skip commits left' '
761         git bisect reset &&
762         git bisect start $HASH4 $HASH2 &&
763         test_must_fail git bisect skip &&
764         git bisect log >bisect-skip-log.txt &&
765         test_cmp expected.bisect-skip-log bisect-skip-log.txt &&
766         git bisect reset
767 '
768
769 test_expect_success '"git bisect bad HEAD" behaves as "git bisect bad"' '
770         git checkout parallel &&
771         git bisect start HEAD $HASH1 &&
772         git bisect good HEAD &&
773         git bisect bad HEAD &&
774         test "$HASH6" = $(git rev-parse --verify HEAD) &&
775         git bisect reset
776 '
777
778 test_expect_success 'bisect starts with only one new' '
779         git bisect reset &&
780         git bisect start &&
781         git bisect new $HASH4 &&
782         git bisect next
783 '
784
785 test_expect_success 'bisect does not start with only one old' '
786         git bisect reset &&
787         git bisect start &&
788         git bisect old $HASH1 &&
789         test_must_fail git bisect next
790 '
791
792 test_expect_success 'bisect start with one new and old' '
793         git bisect reset &&
794         git bisect start &&
795         git bisect old $HASH1 &&
796         git bisect new $HASH4 &&
797         git bisect new &&
798         git bisect new >bisect_result &&
799         grep "$HASH2 is the first new commit" bisect_result &&
800         git bisect log >log_to_replay.txt &&
801         git bisect reset
802 '
803
804 test_expect_success 'bisect replay with old and new' '
805         git bisect replay log_to_replay.txt >bisect_result &&
806         grep "$HASH2 is the first new commit" bisect_result &&
807         git bisect reset
808 '
809
810 test_expect_success 'bisect replay with CRLF log' '
811         append_cr <log_to_replay.txt >log_to_replay_crlf.txt &&
812         git bisect replay log_to_replay_crlf.txt >bisect_result_crlf &&
813         grep "$HASH2 is the first new commit" bisect_result_crlf &&
814         git bisect reset
815 '
816
817 test_expect_success 'bisect cannot mix old/new and good/bad' '
818         git bisect start &&
819         git bisect bad $HASH4 &&
820         test_must_fail git bisect old $HASH1
821 '
822
823 test_expect_success 'bisect terms needs 0 or 1 argument' '
824         git bisect reset &&
825         test_must_fail git bisect terms only-one &&
826         test_must_fail git bisect terms 1 2 &&
827         test_must_fail git bisect terms 2>actual &&
828         echo "error: no terms defined" >expected &&
829         test_i18ncmp expected actual
830 '
831
832 test_expect_success 'bisect terms shows good/bad after start' '
833         git bisect reset &&
834         git bisect start HEAD $HASH1 &&
835         git bisect terms --term-good >actual &&
836         echo good >expected &&
837         test_cmp expected actual &&
838         git bisect terms --term-bad >actual &&
839         echo bad >expected &&
840         test_cmp expected actual
841 '
842
843 test_expect_success 'bisect start with one term1 and term2' '
844         git bisect reset &&
845         git bisect start --term-old term2 --term-new term1 &&
846         git bisect term2 $HASH1 &&
847         git bisect term1 $HASH4 &&
848         git bisect term1 &&
849         git bisect term1 >bisect_result &&
850         grep "$HASH2 is the first term1 commit" bisect_result &&
851         git bisect log >log_to_replay.txt &&
852         git bisect reset
853 '
854
855 test_expect_success 'bisect replay with term1 and term2' '
856         git bisect replay log_to_replay.txt >bisect_result &&
857         grep "$HASH2 is the first term1 commit" bisect_result &&
858         git bisect reset
859 '
860
861 test_expect_success 'bisect start term1 term2' '
862         git bisect reset &&
863         git bisect start --term-new term1 --term-old term2 $HASH4 $HASH1 &&
864         git bisect term1 &&
865         git bisect term1 >bisect_result &&
866         grep "$HASH2 is the first term1 commit" bisect_result &&
867         git bisect log >log_to_replay.txt &&
868         git bisect reset
869 '
870
871 test_expect_success 'bisect cannot mix terms' '
872         git bisect reset &&
873         git bisect start --term-good term1 --term-bad term2 $HASH4 $HASH1 &&
874         test_must_fail git bisect a &&
875         test_must_fail git bisect b &&
876         test_must_fail git bisect bad &&
877         test_must_fail git bisect good &&
878         test_must_fail git bisect new &&
879         test_must_fail git bisect old
880 '
881
882 test_expect_success 'bisect terms rejects invalid terms' '
883         git bisect reset &&
884         test_must_fail git bisect start --term-good &&
885         test_must_fail git bisect start --term-good invalid..term &&
886         test_must_fail git bisect start --term-bad &&
887         test_must_fail git bisect terms --term-bad invalid..term &&
888         test_must_fail git bisect terms --term-good bad &&
889         test_must_fail git bisect terms --term-good old &&
890         test_must_fail git bisect terms --term-good skip &&
891         test_must_fail git bisect terms --term-good reset &&
892         test_path_is_missing .git/BISECT_TERMS
893 '
894
895 test_expect_success 'bisect start --term-* does store terms' '
896         git bisect reset &&
897         git bisect start --term-bad=one --term-good=two &&
898         git bisect terms >actual &&
899         cat <<-EOF >expected &&
900         Your current terms are two for the old state
901         and one for the new state.
902         EOF
903         test_i18ncmp expected actual &&
904         git bisect terms --term-bad >actual &&
905         echo one >expected &&
906         test_cmp expected actual &&
907         git bisect terms --term-good >actual &&
908         echo two >expected &&
909         test_cmp expected actual
910 '
911
912 test_expect_success 'bisect start takes options and revs in any order' '
913         git bisect reset &&
914         git bisect start --term-good one $HASH4 \
915                 --term-good two --term-bad bad-term \
916                 $HASH1 --term-good three -- &&
917         (git bisect terms --term-bad && git bisect terms --term-good) >actual &&
918         printf "%s\n%s\n" bad-term three >expected &&
919         test_cmp expected actual
920 '
921
922 test_expect_success 'git bisect reset cleans bisection state properly' '
923         git bisect reset &&
924         git bisect start &&
925         git bisect good $HASH1 &&
926         git bisect bad $HASH4 &&
927         git bisect reset &&
928         test -z "$(git for-each-ref "refs/bisect/*")" &&
929         test_path_is_missing "$GIT_DIR/BISECT_EXPECTED_REV" &&
930         test_path_is_missing "$GIT_DIR/BISECT_ANCESTORS_OK" &&
931         test_path_is_missing "$GIT_DIR/BISECT_LOG" &&
932         test_path_is_missing "$GIT_DIR/BISECT_RUN" &&
933         test_path_is_missing "$GIT_DIR/BISECT_TERMS" &&
934         test_path_is_missing "$GIT_DIR/head-name" &&
935         test_path_is_missing "$GIT_DIR/BISECT_HEAD" &&
936         test_path_is_missing "$GIT_DIR/BISECT_START"
937 '
938
939 test_done