Merge branch 'jc/test-lazy-prereq' (early part)
[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 || return 1
56
57         if git bisect next
58         then
59                 echo Oops, should have failed.
60                 false
61         else
62                 :
63         fi
64 '
65
66 test_expect_success 'bisect start with one bad and good' '
67         git bisect reset &&
68         git bisect start &&
69         git bisect good $HASH1 &&
70         git bisect bad $HASH4 &&
71         git bisect next
72 '
73
74 test_expect_success 'bisect fails if given any junk instead of revs' '
75         git bisect reset &&
76         test_must_fail git bisect start foo $HASH1 -- &&
77         test_must_fail git bisect start $HASH4 $HASH1 bar -- &&
78         test -z "$(git for-each-ref "refs/bisect/*")" &&
79         test -z "$(ls .git/BISECT_* 2>/dev/null)" &&
80         git bisect start &&
81         test_must_fail git bisect good foo $HASH1 &&
82         test_must_fail git bisect good $HASH1 bar &&
83         test_must_fail git bisect bad frotz &&
84         test_must_fail git bisect bad $HASH3 $HASH4 &&
85         test_must_fail git bisect skip bar $HASH3 &&
86         test_must_fail git bisect skip $HASH1 foo &&
87         test -z "$(git for-each-ref "refs/bisect/*")" &&
88         git bisect good $HASH1 &&
89         git bisect bad $HASH4
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_must_fail test -e .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_must_fail test -e .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_must_fail test -e .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         git bisect reset &&
195         git bisect start $HASH4 $HASH1 &&
196         git bisect skip &&
197         git bisect bad > my_bisect_log.txt &&
198         grep "$HASH2 is the first bad commit" my_bisect_log.txt &&
199         git bisect reset
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         git bisect start $HASH4 $HASH1 &&
207         git bisect skip || return 1
208
209         if git bisect skip > my_bisect_log.txt
210         then
211                 echo Oops, should have failed.
212                 false
213         else
214                 test $? -eq 2 &&
215                 grep "first bad commit could be any of" my_bisect_log.txt &&
216                 ! grep $HASH1 my_bisect_log.txt &&
217                 grep $HASH2 my_bisect_log.txt &&
218                 grep $HASH3 my_bisect_log.txt &&
219                 grep $HASH4 my_bisect_log.txt &&
220                 git bisect reset
221         fi
222 '
223
224 # $HASH1 is good, $HASH4 is bad, we skip $HASH3
225 # but $HASH2 is good,
226 # so we should not be able to tell the first bad commit
227 # among $HASH3 and $HASH4
228 test_expect_success 'bisect skip: cannot tell between 2 commits' '
229         git bisect start $HASH4 $HASH1 &&
230         git bisect skip || return 1
231
232         if git bisect good > my_bisect_log.txt
233         then
234                 echo Oops, should have failed.
235                 false
236         else
237                 test $? -eq 2 &&
238                 grep "first bad commit could be any of" my_bisect_log.txt &&
239                 ! grep $HASH1 my_bisect_log.txt &&
240                 ! grep $HASH2 my_bisect_log.txt &&
241                 grep $HASH3 my_bisect_log.txt &&
242                 grep $HASH4 my_bisect_log.txt &&
243                 git bisect reset
244         fi
245 '
246
247 # $HASH1 is good, $HASH4 is both skipped and bad, we skip $HASH3
248 # and $HASH2 is good,
249 # so we should not be able to tell the first bad commit
250 # among $HASH3 and $HASH4
251 test_expect_success 'bisect skip: with commit both bad and skipped' '
252         git bisect start &&
253         git bisect skip &&
254         git bisect bad &&
255         git bisect good $HASH1 &&
256         git bisect skip &&
257         if git bisect good > my_bisect_log.txt
258         then
259                 echo Oops, should have failed.
260                 false
261         else
262                 test $? -eq 2 &&
263                 grep "first bad commit could be any of" my_bisect_log.txt &&
264                 ! grep $HASH1 my_bisect_log.txt &&
265                 ! grep $HASH2 my_bisect_log.txt &&
266                 grep $HASH3 my_bisect_log.txt &&
267                 grep $HASH4 my_bisect_log.txt &&
268                 git bisect reset
269         fi
270 '
271
272 # We want to automatically find the commit that
273 # introduced "Another" into hello.
274 test_expect_success \
275     '"git bisect run" simple case' \
276     'echo "#"\!"/bin/sh" > test_script.sh &&
277      echo "grep Another hello > /dev/null" >> test_script.sh &&
278      echo "test \$? -ne 0" >> test_script.sh &&
279      chmod +x test_script.sh &&
280      git bisect start &&
281      git bisect good $HASH1 &&
282      git bisect bad $HASH4 &&
283      git bisect run ./test_script.sh > my_bisect_log.txt &&
284      grep "$HASH3 is the first bad commit" my_bisect_log.txt &&
285      git bisect reset'
286
287 # We want to automatically find the commit that
288 # introduced "Ciao" into hello.
289 test_expect_success \
290     '"git bisect run" with more complex "git bisect start"' \
291     'echo "#"\!"/bin/sh" > test_script.sh &&
292      echo "grep Ciao hello > /dev/null" >> test_script.sh &&
293      echo "test \$? -ne 0" >> test_script.sh &&
294      chmod +x test_script.sh &&
295      git bisect start $HASH4 $HASH1 &&
296      git bisect run ./test_script.sh > my_bisect_log.txt &&
297      grep "$HASH4 is the first bad commit" my_bisect_log.txt &&
298      git bisect reset'
299
300 # $HASH1 is good, $HASH5 is bad, we skip $HASH3
301 # but $HASH4 is good,
302 # so we should find $HASH5 as the first bad commit
303 HASH5=
304 test_expect_success 'bisect skip: add line and then a new test' '
305         add_line_into_file "5: Another new line." hello &&
306         HASH5=$(git rev-parse --verify HEAD) &&
307         git bisect start $HASH5 $HASH1 &&
308         git bisect skip &&
309         git bisect good > my_bisect_log.txt &&
310         grep "$HASH5 is the first bad commit" my_bisect_log.txt &&
311         git bisect log > log_to_replay.txt &&
312         git bisect reset
313 '
314
315 test_expect_success 'bisect skip and bisect replay' '
316         git bisect replay log_to_replay.txt > my_bisect_log.txt &&
317         grep "$HASH5 is the first bad commit" my_bisect_log.txt &&
318         git bisect reset
319 '
320
321 HASH6=
322 test_expect_success 'bisect run & skip: cannot tell between 2' '
323         add_line_into_file "6: Yet a line." hello &&
324         HASH6=$(git rev-parse --verify HEAD) &&
325         echo "#"\!"/bin/sh" > test_script.sh &&
326         echo "sed -ne \\\$p hello | grep Ciao > /dev/null && exit 125" >> test_script.sh &&
327         echo "grep line hello > /dev/null" >> test_script.sh &&
328         echo "test \$? -ne 0" >> test_script.sh &&
329         chmod +x test_script.sh &&
330         git bisect start $HASH6 $HASH1 &&
331         if git bisect run ./test_script.sh > my_bisect_log.txt
332         then
333                 echo Oops, should have failed.
334                 false
335         else
336                 test $? -eq 2 &&
337                 grep "first bad commit could be any of" my_bisect_log.txt &&
338                 ! grep $HASH3 my_bisect_log.txt &&
339                 ! grep $HASH6 my_bisect_log.txt &&
340                 grep $HASH4 my_bisect_log.txt &&
341                 grep $HASH5 my_bisect_log.txt
342         fi
343 '
344
345 HASH7=
346 test_expect_success 'bisect run & skip: find first bad' '
347         git bisect reset &&
348         add_line_into_file "7: Should be the last line." hello &&
349         HASH7=$(git rev-parse --verify HEAD) &&
350         echo "#"\!"/bin/sh" > test_script.sh &&
351         echo "sed -ne \\\$p hello | grep Ciao > /dev/null && exit 125" >> test_script.sh &&
352         echo "sed -ne \\\$p hello | grep day > /dev/null && exit 125" >> test_script.sh &&
353         echo "grep Yet hello > /dev/null" >> test_script.sh &&
354         echo "test \$? -ne 0" >> test_script.sh &&
355         chmod +x test_script.sh &&
356         git bisect start $HASH7 $HASH1 &&
357         git bisect run ./test_script.sh > my_bisect_log.txt &&
358         grep "$HASH6 is the first bad commit" my_bisect_log.txt
359 '
360
361 test_expect_success 'bisect skip only one range' '
362         git bisect reset &&
363         git bisect start $HASH7 $HASH1 &&
364         git bisect skip $HASH1..$HASH5 &&
365         test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
366         test_must_fail git bisect bad > my_bisect_log.txt &&
367         grep "first bad commit could be any of" my_bisect_log.txt
368 '
369
370 test_expect_success 'bisect skip many ranges' '
371         git bisect start $HASH7 $HASH1 &&
372         test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
373         git bisect skip $HASH2 $HASH2.. ..$HASH5 &&
374         test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
375         test_must_fail git bisect bad > my_bisect_log.txt &&
376         grep "first bad commit could be any of" my_bisect_log.txt
377 '
378
379 test_expect_success 'bisect starting with a detached HEAD' '
380         git bisect reset &&
381         git checkout master^ &&
382         HEAD=$(git rev-parse --verify HEAD) &&
383         git bisect start &&
384         test $HEAD = $(cat .git/BISECT_START) &&
385         git bisect reset &&
386         test $HEAD = $(git rev-parse --verify HEAD)
387 '
388
389 test_expect_success 'bisect errors out if bad and good are mistaken' '
390         git bisect reset &&
391         test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error &&
392         grep "mistake good and bad" rev_list_error &&
393         git bisect reset
394 '
395
396 test_expect_success 'bisect does not create a "bisect" branch' '
397         git bisect reset &&
398         git bisect start $HASH7 $HASH1 &&
399         git branch bisect &&
400         rev_hash4=$(git rev-parse --verify HEAD) &&
401         test "$rev_hash4" = "$HASH4" &&
402         git branch -D bisect &&
403         git bisect good &&
404         git branch bisect &&
405         rev_hash6=$(git rev-parse --verify HEAD) &&
406         test "$rev_hash6" = "$HASH6" &&
407         git bisect good > my_bisect_log.txt &&
408         grep "$HASH7 is the first bad commit" my_bisect_log.txt &&
409         git bisect reset &&
410         rev_hash6=$(git rev-parse --verify bisect) &&
411         test "$rev_hash6" = "$HASH6" &&
412         git branch -D bisect
413 '
414
415 # This creates a "side" branch to test "siblings" cases.
416 #
417 # H1-H2-H3-H4-H5-H6-H7  <--other
418 #            \
419 #             S5-S6-S7  <--side
420 #
421 test_expect_success 'side branch creation' '
422         git bisect reset &&
423         git checkout -b side $HASH4 &&
424         add_line_into_file "5(side): first line on a side branch" hello2 &&
425         SIDE_HASH5=$(git rev-parse --verify HEAD) &&
426         add_line_into_file "6(side): second line on a side branch" hello2 &&
427         SIDE_HASH6=$(git rev-parse --verify HEAD) &&
428         add_line_into_file "7(side): third line on a side branch" hello2 &&
429         SIDE_HASH7=$(git rev-parse --verify HEAD)
430 '
431
432 test_expect_success 'good merge base when good and bad are siblings' '
433         git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
434         grep "merge base must be tested" my_bisect_log.txt &&
435         grep $HASH4 my_bisect_log.txt &&
436         git bisect good > my_bisect_log.txt &&
437         test_must_fail grep "merge base must be tested" my_bisect_log.txt &&
438         grep $HASH6 my_bisect_log.txt &&
439         git bisect reset
440 '
441 test_expect_success 'skipped merge base when good and bad are siblings' '
442         git bisect start "$SIDE_HASH7" "$HASH7" > my_bisect_log.txt &&
443         grep "merge base must be tested" my_bisect_log.txt &&
444         grep $HASH4 my_bisect_log.txt &&
445         git bisect skip > my_bisect_log.txt 2>&1 &&
446         grep "warning" my_bisect_log.txt &&
447         grep $SIDE_HASH6 my_bisect_log.txt &&
448         git bisect reset
449 '
450
451 test_expect_success 'bad merge base when good and bad are siblings' '
452         git bisect start "$HASH7" HEAD > my_bisect_log.txt &&
453         grep "merge base must be tested" my_bisect_log.txt &&
454         grep $HASH4 my_bisect_log.txt &&
455         test_must_fail git bisect bad > my_bisect_log.txt 2>&1 &&
456         grep "merge base $HASH4 is bad" my_bisect_log.txt &&
457         grep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt &&
458         git bisect reset
459 '
460
461 # This creates a few more commits (A and B) to test "siblings" cases
462 # when a good and a bad rev have many merge bases.
463 #
464 # We should have the following:
465 #
466 # H1-H2-H3-H4-H5-H6-H7
467 #            \  \     \
468 #             S5-A     \
469 #              \        \
470 #               S6-S7----B
471 #
472 # And there A and B have 2 merge bases (S5 and H5) that should be
473 # reported by "git merge-base --all A B".
474 #
475 test_expect_success 'many merge bases creation' '
476         git checkout "$SIDE_HASH5" &&
477         git merge -m "merge HASH5 and SIDE_HASH5" "$HASH5" &&
478         A_HASH=$(git rev-parse --verify HEAD) &&
479         git checkout side &&
480         git merge -m "merge HASH7 and SIDE_HASH7" "$HASH7" &&
481         B_HASH=$(git rev-parse --verify HEAD) &&
482         git merge-base --all "$A_HASH" "$B_HASH" > merge_bases.txt &&
483         test_line_count = 2 merge_bases.txt &&
484         grep "$HASH5" merge_bases.txt &&
485         grep "$SIDE_HASH5" merge_bases.txt
486 '
487
488 test_expect_success 'good merge bases when good and bad are siblings' '
489         git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt &&
490         grep "merge base must be tested" my_bisect_log.txt &&
491         git bisect good > my_bisect_log2.txt &&
492         grep "merge base must be tested" my_bisect_log2.txt &&
493         {
494                 {
495                         grep "$SIDE_HASH5" my_bisect_log.txt &&
496                         grep "$HASH5" my_bisect_log2.txt
497                 } || {
498                         grep "$SIDE_HASH5" my_bisect_log2.txt &&
499                         grep "$HASH5" my_bisect_log.txt
500                 }
501         } &&
502         git bisect reset
503 '
504
505 test_expect_success 'optimized merge base checks' '
506         git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
507         grep "merge base must be tested" my_bisect_log.txt &&
508         grep "$HASH4" my_bisect_log.txt &&
509         git bisect good > my_bisect_log2.txt &&
510         test -f ".git/BISECT_ANCESTORS_OK" &&
511         test "$HASH6" = $(git rev-parse --verify HEAD) &&
512         git bisect bad > my_bisect_log3.txt &&
513         git bisect good "$A_HASH" > my_bisect_log4.txt &&
514         grep "merge base must be tested" my_bisect_log4.txt &&
515         test_must_fail test -f ".git/BISECT_ANCESTORS_OK"
516 '
517
518 # This creates another side branch called "parallel" with some files
519 # in some directories, to test bisecting with paths.
520 #
521 # We should have the following:
522 #
523 #    P1-P2-P3-P4-P5-P6-P7
524 #   /        /        /
525 # H1-H2-H3-H4-H5-H6-H7
526 #            \  \     \
527 #             S5-A     \
528 #              \        \
529 #               S6-S7----B
530 #
531 test_expect_success '"parallel" side branch creation' '
532         git bisect reset &&
533         git checkout -b parallel $HASH1 &&
534         mkdir dir1 dir2 &&
535         add_line_into_file "1(para): line 1 on parallel branch" dir1/file1 &&
536         PARA_HASH1=$(git rev-parse --verify HEAD) &&
537         add_line_into_file "2(para): line 2 on parallel branch" dir2/file2 &&
538         PARA_HASH2=$(git rev-parse --verify HEAD) &&
539         add_line_into_file "3(para): line 3 on parallel branch" dir2/file3 &&
540         PARA_HASH3=$(git rev-parse --verify HEAD) &&
541         git merge -m "merge HASH4 and PARA_HASH3" "$HASH4" &&
542         PARA_HASH4=$(git rev-parse --verify HEAD) &&
543         add_line_into_file "5(para): add line on parallel branch" dir1/file1 &&
544         PARA_HASH5=$(git rev-parse --verify HEAD) &&
545         add_line_into_file "6(para): add line on parallel branch" dir2/file2 &&
546         PARA_HASH6=$(git rev-parse --verify HEAD) &&
547         git merge -m "merge HASH7 and PARA_HASH6" "$HASH7" &&
548         PARA_HASH7=$(git rev-parse --verify HEAD)
549 '
550
551 test_expect_success 'restricting bisection on one dir' '
552         git bisect reset &&
553         git bisect start HEAD $HASH1 -- dir1 &&
554         para1=$(git rev-parse --verify HEAD) &&
555         test "$para1" = "$PARA_HASH1" &&
556         git bisect bad > my_bisect_log.txt &&
557         grep "$PARA_HASH1 is the first bad commit" my_bisect_log.txt
558 '
559
560 test_expect_success 'restricting bisection on one dir and a file' '
561         git bisect reset &&
562         git bisect start HEAD $HASH1 -- dir1 hello &&
563         para4=$(git rev-parse --verify HEAD) &&
564         test "$para4" = "$PARA_HASH4" &&
565         git bisect bad &&
566         hash3=$(git rev-parse --verify HEAD) &&
567         test "$hash3" = "$HASH3" &&
568         git bisect good &&
569         hash4=$(git rev-parse --verify HEAD) &&
570         test "$hash4" = "$HASH4" &&
571         git bisect good &&
572         para1=$(git rev-parse --verify HEAD) &&
573         test "$para1" = "$PARA_HASH1" &&
574         git bisect good > my_bisect_log.txt &&
575         grep "$PARA_HASH4 is the first bad commit" my_bisect_log.txt
576 '
577
578 test_expect_success 'skipping away from skipped commit' '
579         git bisect start $PARA_HASH7 $HASH1 &&
580         para4=$(git rev-parse --verify HEAD) &&
581         test "$para4" = "$PARA_HASH4" &&
582         git bisect skip &&
583         hash7=$(git rev-parse --verify HEAD) &&
584         test "$hash7" = "$HASH7" &&
585         git bisect skip &&
586         para3=$(git rev-parse --verify HEAD) &&
587         test "$para3" = "$PARA_HASH3"
588 '
589
590 test_expect_success 'erroring out when using bad path parameters' '
591         test_must_fail git bisect start $PARA_HASH7 $HASH1 -- foobar 2> error.txt &&
592         grep "bad path parameters" error.txt
593 '
594
595 test_expect_success 'test bisection on bare repo - --no-checkout specified' '
596         git clone --bare . bare.nocheckout &&
597         (
598                 cd bare.nocheckout &&
599                 git bisect start --no-checkout &&
600                 git bisect good $HASH1 &&
601                 git bisect bad $HASH4 &&
602                 git bisect run eval \
603                         "test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \
604                         >../nocheckout.log &&
605                 git bisect reset
606         ) &&
607         grep "$HASH3 is the first bad commit" nocheckout.log
608 '
609
610
611 test_expect_success 'test bisection on bare repo - --no-checkout defaulted' '
612         git clone --bare . bare.defaulted &&
613         (
614                 cd bare.defaulted &&
615                 git bisect start &&
616                 git bisect good $HASH1 &&
617                 git bisect bad $HASH4 &&
618                 git bisect run eval \
619                         "test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \
620                         >../defaulted.log &&
621                 git bisect reset
622         ) &&
623         grep "$HASH3 is the first bad commit" defaulted.log
624 '
625
626 #
627 # This creates a broken branch which cannot be checked out because
628 # the tree created has been deleted.
629 #
630 # H1-H2-H3-H4-H5-H6-H7  <--other
631 #            \
632 #             S5-S6'-S7'-S8'-S9  <--broken
633 #
634 # Commits marked with ' have a missing tree.
635 #
636 test_expect_success 'broken branch creation' '
637         git bisect reset &&
638         git checkout -b broken $HASH4 &&
639         git tag BROKEN_HASH4 $HASH4 &&
640         add_line_into_file "5(broken): first line on a broken branch" hello2 &&
641         git tag BROKEN_HASH5 &&
642         mkdir missing &&
643         :> missing/MISSING &&
644         git add missing/MISSING &&
645         git commit -m "6(broken): Added file that will be deleted"
646         git tag BROKEN_HASH6 &&
647         add_line_into_file "7(broken): second line on a broken branch" hello2 &&
648         git tag BROKEN_HASH7 &&
649         add_line_into_file "8(broken): third line on a broken branch" hello2 &&
650         git tag BROKEN_HASH8 &&
651         git rm missing/MISSING &&
652         git commit -m "9(broken): Remove missing file"
653         git tag BROKEN_HASH9 &&
654         rm .git/objects/39/f7e61a724187ab767d2e08442d9b6b9dab587d
655 '
656
657 echo "" > expected.ok
658 cat > expected.missing-tree.default <<EOF
659 fatal: unable to read tree 39f7e61a724187ab767d2e08442d9b6b9dab587d
660 EOF
661
662 test_expect_success 'bisect fails if tree is broken on start commit' '
663         git bisect reset &&
664         test_must_fail git bisect start BROKEN_HASH7 BROKEN_HASH4 2>error.txt &&
665         test_cmp expected.missing-tree.default error.txt
666 '
667
668 test_expect_success 'bisect fails if tree is broken on trial commit' '
669         git bisect reset &&
670         test_must_fail git bisect start BROKEN_HASH9 BROKEN_HASH4 2>error.txt &&
671         git reset --hard broken &&
672         git checkout broken &&
673         test_cmp expected.missing-tree.default error.txt
674 '
675
676 check_same()
677 {
678         echo "Checking $1 is the same as $2" &&
679         test_cmp_rev "$1" "$2"
680 }
681
682 test_expect_success 'bisect: --no-checkout - start commit bad' '
683         git bisect reset &&
684         git bisect start BROKEN_HASH7 BROKEN_HASH4 --no-checkout &&
685         check_same BROKEN_HASH6 BISECT_HEAD &&
686         git bisect reset
687 '
688
689 test_expect_success 'bisect: --no-checkout - trial commit bad' '
690         git bisect reset &&
691         git bisect start broken BROKEN_HASH4 --no-checkout &&
692         check_same BROKEN_HASH6 BISECT_HEAD &&
693         git bisect reset
694 '
695
696 test_expect_success 'bisect: --no-checkout - target before breakage' '
697         git bisect reset &&
698         git bisect start broken BROKEN_HASH4 --no-checkout &&
699         check_same BROKEN_HASH6 BISECT_HEAD &&
700         git bisect bad BISECT_HEAD &&
701         check_same BROKEN_HASH5 BISECT_HEAD &&
702         git bisect bad BISECT_HEAD &&
703         check_same BROKEN_HASH5 bisect/bad &&
704         git bisect reset
705 '
706
707 test_expect_success 'bisect: --no-checkout - target in breakage' '
708         git bisect reset &&
709         git bisect start broken BROKEN_HASH4 --no-checkout &&
710         check_same BROKEN_HASH6 BISECT_HEAD &&
711         git bisect bad BISECT_HEAD &&
712         check_same BROKEN_HASH5 BISECT_HEAD &&
713         git bisect good BISECT_HEAD &&
714         check_same BROKEN_HASH6 bisect/bad &&
715         git bisect reset
716 '
717
718 test_expect_success 'bisect: --no-checkout - target after breakage' '
719         git bisect reset &&
720         git bisect start broken BROKEN_HASH4 --no-checkout &&
721         check_same BROKEN_HASH6 BISECT_HEAD &&
722         git bisect good BISECT_HEAD &&
723         check_same BROKEN_HASH8 BISECT_HEAD &&
724         git bisect good BISECT_HEAD &&
725         check_same BROKEN_HASH9 bisect/bad &&
726         git bisect reset
727 '
728
729 test_expect_success 'bisect: demonstrate identification of damage boundary' "
730         git bisect reset &&
731         git checkout broken &&
732         git bisect start broken master --no-checkout &&
733         git bisect run \"\$SHELL_PATH\" -c '
734                 GOOD=\$(git for-each-ref \"--format=%(objectname)\" refs/bisect/good-*) &&
735                 git rev-list --objects BISECT_HEAD --not \$GOOD >tmp.\$\$ &&
736                 git pack-objects --stdout >/dev/null < tmp.\$\$
737                 rc=\$?
738                 rm -f tmp.\$\$
739                 test \$rc = 0' &&
740         check_same BROKEN_HASH6 bisect/bad &&
741         git bisect reset
742 "
743
744 cat > expected.bisect-log <<EOF
745 # bad: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>.
746 # good: [7b7f204a749c3125d5224ed61ea2ae1187ad046f] Add <2: A new day for git> into <hello>.
747 git bisect start '32a594a3fdac2d57cf6d02987e30eec68511498c' '7b7f204a749c3125d5224ed61ea2ae1187ad046f'
748 # good: [3de952f2416b6084f557ec417709eac740c6818c] Add <3: Another new day for git> into <hello>.
749 git bisect good 3de952f2416b6084f557ec417709eac740c6818c
750 # first bad commit: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>.
751 EOF
752
753 test_expect_success 'bisect log: successfull result' '
754         git bisect reset &&
755         git bisect start $HASH4 $HASH2 &&
756         git bisect good &&
757         git bisect log >bisect-log.txt &&
758         test_cmp expected.bisect-log bisect-log.txt &&
759         git bisect reset
760 '
761
762 cat > expected.bisect-skip-log <<EOF
763 # bad: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>.
764 # good: [7b7f204a749c3125d5224ed61ea2ae1187ad046f] Add <2: A new day for git> into <hello>.
765 git bisect start '32a594a3fdac2d57cf6d02987e30eec68511498c' '7b7f204a749c3125d5224ed61ea2ae1187ad046f'
766 # skip: [3de952f2416b6084f557ec417709eac740c6818c] Add <3: Another new day for git> into <hello>.
767 git bisect skip 3de952f2416b6084f557ec417709eac740c6818c
768 # only skipped commits left to test
769 # possible first bad commit: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>.
770 # possible first bad commit: [3de952f2416b6084f557ec417709eac740c6818c] Add <3: Another new day for git> into <hello>.
771 EOF
772
773 test_expect_success 'bisect log: only skip commits left' '
774         git bisect reset &&
775         git bisect start $HASH4 $HASH2 &&
776         test_must_fail git bisect skip &&
777         git bisect log >bisect-skip-log.txt &&
778         test_cmp expected.bisect-skip-log bisect-skip-log.txt &&
779         git bisect reset
780 '
781
782 test_done