bisect: fix exiting when checkout failed in bisect_start()
[git/git.git] / git-bisect.sh
CommitLineData
8cc6a083 1#!/bin/sh
d025524d 2
243a60fb
CC
3USAGE='[help|start|bad|good|skip|next|reset|visualize|replay|log|run]'
4LONG_USAGE='git bisect help
6021be86 5 print this long help message.
4796e823 6git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...]
6021be86 7 reset bisect state and start bisection.
38a47fd6 8git bisect bad [<rev>]
6021be86 9 mark <rev> a known-bad revision.
38a47fd6 10git bisect good [<rev>...]
6021be86 11 mark <rev>... known-good revisions.
5413812f 12git bisect skip [(<rev>|<range>)...]
6021be86 13 mark <rev>... untestable revisions.
38a47fd6 14git bisect next
6021be86 15 find next bisection to test and check it out.
6b87ce23 16git bisect reset [<commit>]
6021be86 17 finish bisection search and go back to commit.
38a47fd6 18git bisect visualize
6021be86 19 show bisect status in gitk.
38a47fd6 20git bisect replay <logfile>
6021be86 21 replay bisection log.
38a47fd6 22git bisect log
6021be86 23 show bisect log.
38a47fd6 24git bisect run <cmd>...
6021be86 25 use <cmd>... to automatically bisect.
243a60fb
CC
26
27Please use "git help bisect" to get the full man page.'
d025524d 28
8f321a39 29OPTIONS_SPEC=
ae2b0f15 30. git-sh-setup
dcf9c2e5 31. git-sh-i18n
8cc6a083 32
ce32660e
JS
33_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
34_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
35
4796e823
JS
36bisect_head()
37{
38 if test -f "$GIT_DIR/BISECT_HEAD"
39 then
40 echo BISECT_HEAD
41 else
42 echo HEAD
43 fi
44}
45
8cc6a083 46bisect_autostart() {
823ea121 47 test -s "$GIT_DIR/BISECT_START" || {
ddd7a7c2
ÆAB
48 (
49 gettext "You need to start by \"git bisect start\"" &&
50 echo
51 ) >&2
8cc6a083
LT
52 if test -t 0
53 then
04de0996
ÆAB
54 # TRANSLATORS: Make sure to include [Y] and [n] in your
55 # translation. The program will only accept English input
56 # at this point.
6021be86 57 gettext "Do you want me to do it for you [Y/n]? " >&2
8cc6a083
LT
58 read yesno
59 case "$yesno" in
60 [Nn]*)
61 exit ;;
62 esac
63 bisect_start
64 else
65 exit 1
66 fi
67 }
68}
69
70bisect_start() {
4764f464
JS
71 #
72 # Check for one bad and then some good revisions.
73 #
74 has_double_dash=0
75 for arg; do
6021be86 76 case "$arg" in --) has_double_dash=1; break ;; esac
4764f464
JS
77 done
78 orig_args=$(git rev-parse --sq-quote "$@")
79 bad_seen=0
80 eval=''
24c51280
JS
81 if test "z$(git rev-parse --is-bare-repository)" != zfalse
82 then
83 mode=--no-checkout
84 else
85 mode=''
86 fi
4764f464 87 while [ $# -gt 0 ]; do
6021be86
JS
88 arg="$1"
89 case "$arg" in
90 --)
91 shift
92 break
4764f464 93 ;;
6021be86
JS
94 --no-checkout)
95 mode=--no-checkout
96 shift ;;
97 --*)
98 die "$(eval_gettext "unrecognised option: '\$arg'")" ;;
99 *)
100 rev=$(git rev-parse -q --verify "$arg^{commit}") || {
43b8ff4b
JH
101 test $has_double_dash -eq 1 &&
102 die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
103 break
6021be86
JS
104 }
105 case $bad_seen in
106 0) state='bad' ; bad_seen=1 ;;
107 *) state='good' ;;
108 esac
109 eval="$eval bisect_write '$state' '$rev' 'nolog' &&"
110 shift
111 ;;
4764f464 112 esac
4764f464
JS
113 done
114
8cc6a083 115 #
634f2464 116 # Verify HEAD.
8cc6a083 117 #
48949a18 118 head=$(GIT_DIR="$GIT_DIR" git symbolic-ref -q HEAD) ||
ce32660e 119 head=$(GIT_DIR="$GIT_DIR" git rev-parse --verify HEAD) ||
9570fc1e 120 die "$(gettext "Bad HEAD - I need a HEAD")"
634f2464 121
ee831f7d 122 #
634f2464 123 # Check if we are bisecting.
ee831f7d 124 #
d3e54c88 125 start_head=''
634f2464
CC
126 if test -s "$GIT_DIR/BISECT_START"
127 then
128 # Reset to the rev from where we started.
9d0cd91c 129 start_head=$(cat "$GIT_DIR/BISECT_START")
4796e823
JS
130 if test "z$mode" != "z--no-checkout"
131 then
1acf1171
CC
132 git checkout "$start_head" -- ||
133 die "$(eval_gettext "Checking out '\$start_head' failed. Try 'git bisect reset <validbranch>'.")"
4796e823 134 fi
634f2464
CC
135 else
136 # Get rev from where we start.
137 case "$head" in
138 refs/heads/*|$_x40)
139 # This error message should only be triggered by
140 # cogito usage, and cogito users should understand
141 # it relates to cg-seek.
142 [ -s "$GIT_DIR/head-name" ] &&
9570fc1e 143 die "$(gettext "won't bisect on seeked tree")"
634f2464
CC
144 start_head="${head#refs/heads/}"
145 ;;
146 *)
9570fc1e 147 die "$(gettext "Bad HEAD - strange symbolic ref")"
634f2464
CC
148 ;;
149 esac
150 fi
8cc6a083
LT
151
152 #
634f2464 153 # Get rid of any old bisect state.
8cc6a083 154 #
823ea121 155 bisect_clean_state || exit
38a47fd6 156
ba963de8
CC
157 #
158 # Change state.
159 # In case of mistaken revs or checkout error, or signals received,
160 # "bisect_auto_next" below may exit or misbehave.
161 # We have to trap this to be able to clean up using
162 # "bisect_clean_state".
163 #
164 trap 'bisect_clean_state' 0
165 trap 'exit 255' 1 2 3 15
166
167 #
168 # Write new start state.
169 #
4796e823
JS
170 echo "$start_head" >"$GIT_DIR/BISECT_START" && {
171 test "z$mode" != "z--no-checkout" ||
172 git update-ref --no-deref BISECT_HEAD "$start_head"
173 } &&
de52f5a8 174 git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
6ba7acff 175 eval "$eval true" &&
6c98c054 176 echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
ba963de8
CC
177 #
178 # Check if we can proceed to the next bisect state.
179 #
38a47fd6 180 bisect_auto_next
ba963de8
CC
181
182 trap '-' 0
8cc6a083
LT
183}
184
55624f9a
CC
185bisect_write() {
186 state="$1"
187 rev="$2"
737c74ee 188 nolog="$3"
55624f9a
CC
189 case "$state" in
190 bad) tag="$state" ;;
191 good|skip) tag="$state"-"$rev" ;;
15eaa049 192 *) die "$(eval_gettext "Bad bisect_write argument: \$state")" ;;
55624f9a 193 esac
ba963de8 194 git update-ref "refs/bisect/$tag" "$rev" || exit
f454cdc4 195 echo "# $state: $(git show-branch $rev)" >>"$GIT_DIR/BISECT_LOG"
6c98c054 196 test -n "$nolog" || echo "git bisect $state $rev" >>"$GIT_DIR/BISECT_LOG"
55624f9a
CC
197}
198
c9c4e2d5
CC
199is_expected_rev() {
200 test -f "$GIT_DIR/BISECT_EXPECTED_REV" &&
201 test "$1" = $(cat "$GIT_DIR/BISECT_EXPECTED_REV")
202}
203
c9c4e2d5
CC
204check_expected_revs() {
205 for _rev in "$@"; do
eef12a9a
JS
206 if ! is_expected_rev "$_rev"
207 then
c9c4e2d5
CC
208 rm -f "$GIT_DIR/BISECT_ANCESTORS_OK"
209 rm -f "$GIT_DIR/BISECT_EXPECTED_REV"
210 return
211 fi
212 done
213}
214
ee2314f5 215bisect_skip() {
6021be86 216 all=''
ee2314f5
CC
217 for arg in "$@"
218 do
6021be86
JS
219 case "$arg" in
220 *..*)
221 revs=$(git rev-list "$arg") || die "$(eval_gettext "Bad rev input: \$arg")" ;;
222 *)
223 revs=$(git rev-parse --sq-quote "$arg") ;;
224 esac
225 all="$all $revs"
226 done
227 eval bisect_state 'skip' $all
ee2314f5
CC
228}
229
155fc795 230bisect_state() {
8cc6a083 231 bisect_autostart
155fc795
CC
232 state=$1
233 case "$#,$state" in
234 0,*)
9570fc1e 235 die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;;
155fc795 236 1,bad|1,good|1,skip)
4796e823
JS
237 rev=$(git rev-parse --verify $(bisect_head)) ||
238 die "$(gettext "Bad rev input: $(bisect_head)")"
c9c4e2d5
CC
239 bisect_write "$state" "$rev"
240 check_expected_revs "$rev" ;;
e3389075 241 2,bad|*,good|*,skip)
155fc795 242 shift
d3e54c88 243 eval=''
e3389075 244 for rev in "$@"
155fc795 245 do
a179a303 246 sha=$(git rev-parse --verify "$rev^{commit}") ||
15eaa049 247 die "$(eval_gettext "Bad rev input: \$rev")"
d3e54c88
CC
248 eval="$eval bisect_write '$state' '$sha'; "
249 done
c9c4e2d5
CC
250 eval "$eval"
251 check_expected_revs "$@" ;;
e3389075 252 *,bad)
9570fc1e 253 die "$(gettext "'git bisect bad' can take only one argument.")" ;;
cc9f24d0
JH
254 *)
255 usage ;;
8cc6a083 256 esac
97e1c51e
CC
257 bisect_auto_next
258}
259
8cc6a083 260bisect_next_check() {
0a5280a9
JH
261 missing_good= missing_bad=
262 git show-ref -q --verify refs/bisect/bad || missing_bad=t
263 test -n "$(git for-each-ref "refs/bisect/good-*")" || missing_good=t
6fecf191 264
0a5280a9
JH
265 case "$missing_good,$missing_bad,$1" in
266 ,,*)
267 : have both good and bad - ok
268 ;;
269 *,)
270 # do not have both but not asked to fail - just report.
271 false
272 ;;
273 t,,good)
274 # have bad but not good. we could bisect although
275 # this is less optimum.
ddd7a7c2
ÆAB
276 (
277 gettext "Warning: bisecting only with a bad commit." &&
278 echo
279 ) >&2
0a5280a9
JH
280 if test -t 0
281 then
04de0996
ÆAB
282 # TRANSLATORS: Make sure to include [Y] and [n] in your
283 # translation. The program will only accept English input
284 # at this point.
285 gettext "Are you sure [Y/n]? " >&2
e5d3afd7
FM
286 read yesno
287 case "$yesno" in [Nn]*) exit 1 ;; esac
0a5280a9
JH
288 fi
289 : bisect without good...
290 ;;
8cc6a083 291 *)
be508d3a
ÆAB
292
293 if test -s "$GIT_DIR/BISECT_START"
294 then
295 (
296 gettext "You need to give me at least one good and one bad revisions.
297(You can use \"git bisect bad\" and \"git bisect good\" for that.)" &&
298 echo
299 ) >&2
300 else
301 (
302 gettext "You need to start by \"git bisect start\".
303You then need to give me at least one good and one bad revisions.
304(You can use \"git bisect bad\" and \"git bisect good\" for that.)" &&
305 echo
306 ) >&2
307 fi
0a5280a9 308 exit 1 ;;
8cc6a083
LT
309 esac
310}
311
312bisect_auto_next() {
434d036f 313 bisect_next_check && bisect_next || :
8cc6a083
LT
314}
315
316bisect_next() {
8fe26f44 317 case "$#" in 0) ;; *) usage ;; esac
8cc6a083 318 bisect_autostart
0a5280a9
JH
319 bisect_next_check good
320
0871984d 321 # Perform all bisection computation, display and checkout
4796e823 322 git bisect--helper --next-all $(test -f "$GIT_DIR/BISECT_HEAD" && echo --no-checkout)
5a1d31c7 323 res=$?
0a5280a9 324
6021be86 325 # Check if we should exit because bisection is finished
5a1d31c7 326 test $res -eq 10 && exit 0
0a5280a9 327
5a1d31c7
CC
328 # Check for an error in the bisection process
329 test $res -ne 0 && exit $res
330
331 return 0
8cc6a083
LT
332}
333
cc9f24d0
JH
334bisect_visualize() {
335 bisect_next_check fail
235997c9
JH
336
337 if test $# = 0
338 then
c4e4644e 339 if test -n "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" &&
43b8ff4b 340 type gitk >/dev/null 2>&1
eef12a9a 341 then
c4e4644e
JK
342 set gitk
343 else
344 set git log
345 fi
235997c9
JH
346 else
347 case "$1" in
348 git*|tig) ;;
349 -*) set git log "$@" ;;
350 *) set git "$@" ;;
351 esac
352 fi
353
fc13aa3d 354 eval '"$@"' --bisect -- $(cat "$GIT_DIR/BISECT_NAMES")
cc9f24d0
JH
355}
356
8cc6a083 357bisect_reset() {
823ea121 358 test -s "$GIT_DIR/BISECT_START" || {
d0238a88 359 gettext "We are not bisecting."; echo
fce0499f
CC
360 return
361 }
8cc6a083 362 case "$#" in
823ea121 363 0) branch=$(cat "$GIT_DIR/BISECT_START") ;;
7d0c2d6f 364 1) git rev-parse --quiet --verify "$1^{commit}" > /dev/null || {
6021be86
JS
365 invalid="$1"
366 die "$(eval_gettext "'\$invalid' is not a valid commit")"
367 }
368 branch="$1" ;;
8fe26f44 369 *)
6021be86 370 usage ;;
8cc6a083 371 esac
43b8ff4b
JH
372
373 if ! test -f "$GIT_DIR/BISECT_HEAD" && ! git checkout "$branch" --
4796e823 374 then
43b8ff4b 375 die "$(eval_gettext "Could not check out original HEAD '\$branch'.
15eaa049 376Try 'git bisect reset <commit>'.")"
3bb8cf88 377 fi
4796e823 378 bisect_clean_state
e204de28
JH
379}
380
38a47fd6 381bisect_clean_state() {
947a604b 382 # There may be some refs packed during bisection.
634f2464 383 git for-each-ref --format='%(refname) %(objectname)' refs/bisect/\* |
947a604b
CC
384 while read ref hash
385 do
823ea121 386 git update-ref -d $ref $hash || exit
947a604b 387 done
c9c4e2d5
CC
388 rm -f "$GIT_DIR/BISECT_EXPECTED_REV" &&
389 rm -f "$GIT_DIR/BISECT_ANCESTORS_OK" &&
823ea121
CC
390 rm -f "$GIT_DIR/BISECT_LOG" &&
391 rm -f "$GIT_DIR/BISECT_NAMES" &&
392 rm -f "$GIT_DIR/BISECT_RUN" &&
9d0cd91c 393 # Cleanup head-name if it got left by an old version of git-bisect
823ea121 394 rm -f "$GIT_DIR/head-name" &&
4796e823
JS
395 git update-ref -d --no-deref BISECT_HEAD &&
396 # clean up BISECT_START last
823ea121 397 rm -f "$GIT_DIR/BISECT_START"
38a47fd6
CC
398}
399
e204de28 400bisect_replay () {
55a9fc80
ÆAB
401 file="$1"
402 test "$#" -eq 1 || die "$(gettext "No logfile given")"
403 test -r "$file" || die "$(eval_gettext "cannot read \$file for replaying")"
e204de28 404 bisect_reset
6c98c054 405 while read git bisect command rev
e204de28 406 do
6c98c054 407 test "$git $bisect" = "git bisect" -o "$git" = "git-bisect" || continue
eef12a9a
JS
408 if test "$git" = "git-bisect"
409 then
6c98c054
MV
410 rev="$command"
411 command="$bisect"
412 fi
e204de28
JH
413 case "$command" in
414 start)
e9a45d75 415 cmd="bisect_start $rev"
737c74ee
CC
416 eval "$cmd" ;;
417 good|bad|skip)
418 bisect_write "$command" "$rev" ;;
e204de28 419 *)
9570fc1e 420 die "$(gettext "?? what are you talking about?")" ;;
e204de28 421 esac
55a9fc80 422 done <"$file"
e204de28 423 bisect_auto_next
8cc6a083
LT
424}
425
a17c4101 426bisect_run () {
6021be86
JS
427 bisect_next_check fail
428
429 while true
430 do
431 command="$@"
432 eval_gettext "running \$command"; echo
433 "$@"
434 res=$?
435
436 # Check for really bad run error.
eef12a9a
JS
437 if [ $res -lt 0 -o $res -ge 128 ]
438 then
6021be86
JS
439 (
440 eval_gettext "bisect run failed:
09209255 441exit code \$res from '\$command' is < 0 or >= 128" &&
6021be86
JS
442 echo
443 ) >&2
444 exit $res
445 fi
446
447 # Find current state depending on run success or failure.
448 # A special exit code of 125 means cannot test.
eef12a9a
JS
449 if [ $res -eq 125 ]
450 then
6021be86 451 state='skip'
eef12a9a
JS
452 elif [ $res -gt 0 ]
453 then
6021be86
JS
454 state='bad'
455 else
456 state='good'
457 fi
458
459 # We have to use a subshell because "bisect_state" can exit.
460 ( bisect_state $state > "$GIT_DIR/BISECT_RUN" )
461 res=$?
462
463 cat "$GIT_DIR/BISECT_RUN"
464
465 if sane_grep "first bad commit could be any of" "$GIT_DIR/BISECT_RUN" \
eef12a9a
JS
466 > /dev/null
467 then
6021be86
JS
468 (
469 gettext "bisect run cannot continue any more" &&
470 echo
471 ) >&2
472 exit $res
473 fi
474
eef12a9a
JS
475 if [ $res -ne 0 ]
476 then
6021be86
JS
477 (
478 eval_gettext "bisect run failed:
c6649c92 479'bisect_state \$state' exited with error code \$res" &&
6021be86
JS
480 echo
481 ) >&2
482 exit $res
483 fi
a17c4101 484
eef12a9a
JS
485 if sane_grep "is the first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null
486 then
6021be86
JS
487 gettext "bisect run success"; echo
488 exit 0;
489 fi
a17c4101 490
6021be86 491 done
a17c4101
CC
492}
493
412ff738 494bisect_log () {
9570fc1e 495 test -s "$GIT_DIR/BISECT_LOG" || die "$(gettext "We are not bisecting.")"
412ff738
SG
496 cat "$GIT_DIR/BISECT_LOG"
497}
a17c4101 498
8cc6a083
LT
499case "$#" in
5000)
6021be86 501 usage ;;
8cc6a083 502*)
6021be86
JS
503 cmd="$1"
504 shift
505 case "$cmd" in
506 help)
507 git bisect -h ;;
508 start)
509 bisect_start "$@" ;;
510 bad|good)
511 bisect_state "$cmd" "$@" ;;
512 skip)
513 bisect_skip "$@" ;;
514 next)
515 # Not sure we want "next" at the UI level anymore.
516 bisect_next "$@" ;;
517 visualize|view)
518 bisect_visualize "$@" ;;
519 reset)
520 bisect_reset "$@" ;;
521 replay)
522 bisect_replay "$@" ;;
523 log)
524 bisect_log ;;
525 run)
526 bisect_run "$@" ;;
527 *)
528 usage ;;
529 esac
8cc6a083 530esac