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