243
bisect_next_check && bisect_next || :
244
}
245
246
-eval_rev_list() {
247
- _eval="$1"
248
-
249
- eval $_eval
250
- res=$?
251
-
252
- if [ $res -ne 0 ]; then
253
- echo >&2 "'git rev-list --bisect-vars' failed:"
254
- echo >&2 "maybe you mistake good and bad revs?"
255
- exit $res
256
- fi
257
-
258
- return $res
259
-}
260
-
246
filter_skipped() {
247
_eval="$1"
248
_skip="$2"
249
250
if [ -z "$_skip" ]; then
266
- eval_rev_list "$_eval"
251
+ eval "$_eval"
252
return
253
fi
254
255
# Let's parse the output of:
256
# "git rev-list --bisect-vars --bisect-all ..."
272
- eval_rev_list "$_eval" | while read hash line
257
+ eval "$_eval" | while read hash line
258
do
259
case "$VARS,$FOUND,$TRIED,$hash" in
260
# We display some vars.
317
fi
318
}
319
320
+bisect_checkout() {
321
+ _rev="$1"
322
+ _msg="$2"
323
+ echo "Bisecting: $_msg"
324
+ git checkout -q "$_rev" || exit
325
+ git show-branch "$_rev"
326
+}
327
+
328
+is_among() {
329
+ _rev="$1"
330
+ _list="$2"
331
+ case "$_list" in *$_rev*) return 0 ;; esac
332
+ return 1
333
+}
334
+
335
+is_testing_merge_base() {
336
+ grep "^testing $1$" "$GIT_DIR/BISECT_MERGE_BASES" >/dev/null 2>&1
337
+}
338
+
339
+mark_testing_merge_base() {
340
+ echo "testing $1" >> "$GIT_DIR/BISECT_MERGE_BASES"
341
+}
342
+
343
+handle_bad_merge_base() {
344
+ _badmb="$1"
345
+ _good="$2"
346
+ if is_testing_merge_base "$_badmb"; then
347
+ cat >&2 <<EOF
348
+The merge base $_badmb is bad.
349
+This means the bug has been fixed between $_badmb and [$_good].
350
+EOF
351
+ exit 3
352
+ else
353
+ cat >&2 <<EOF
354
+Some good revs are not ancestor of the bad rev.
355
+git bisect cannot work properly in this case.
356
+Maybe you mistake good and bad revs?
357
+EOF
358
+ exit 1
359
+ fi
360
+}
361
+
362
+handle_skipped_merge_base() {
363
+ _mb="$1"
364
+ _bad="$2"
365
+ _good="$3"
366
+ cat >&2 <<EOF
367
+Warning: the merge base between $_bad and [$_good] must be skipped.
368
+So we cannot be sure the first bad commit is between $_mb and $_bad.
369
+We continue anyway.
370
+EOF
371
+}
372
+
373
+check_merge_bases() {
374
+ _bad="$1"
375
+ _good="$2"
376
+ _skip="$3"
377
+ for _mb in $(git merge-base --all $_bad $_good)
378
+ do
379
+ if is_among "$_mb" "$_good"; then
380
+ continue
381
+ elif test "$_mb" = "$_bad"; then
382
+ handle_bad_merge_base "$_bad" "$_good"
383
+ elif is_among "$_mb" "$_skip"; then
384
+ handle_skipped_merge_base "$_mb" "$_bad" "$_good"
385
+ else
386
+ mark_testing_merge_base "$_mb"
387
+ bisect_checkout "$_mb" "a merge base must be tested"
388
+ checkout_done=1
389
+ return
390
+ fi
391
+ done
392
+}
393
+
394
+check_good_are_ancestors_of_bad() {
395
+ _bad="$1"
396
+ _good=$(echo $2 | sed -e 's/\^//g')
397
+ _skip="$3"
398
+
399
+ # Bisecting with no good rev is ok
400
+ test -z "$_good" && return
401
+
402
+ _side=$(git rev-list $_good ^$_bad)
403
+ if test -n "$_side"; then
404
+ check_merge_bases "$_bad" "$_good" "$_skip"
405
+ fi
406
+}
407
+
408
bisect_next() {
409
case "$#" in 0) ;; *) usage ;; esac
410
bisect_autostart
411
bisect_next_check good
412
413
+ # Get bad, good and skipped revs
414
+ bad=$(git rev-parse --verify refs/bisect/bad) &&
415
+ good=$(git for-each-ref --format='^%(objectname)' \
416
+ "refs/bisect/good-*" | tr '\012' ' ') &&
417
skip=$(git for-each-ref --format='%(objectname)' \
341
- "refs/bisect/skip-*" | tr '\012' ' ') || exit
418
+ "refs/bisect/skip-*" | tr '\012' ' ') &&
419
420
+ # Maybe some merge bases must be tested first
421
+ check_good_are_ancestors_of_bad "$bad" "$good" "$skip" || exit
422
+ test "$checkout_done" -eq "1" && checkout_done='' && return
423
+
424
+ # Get bisection information
425
BISECT_OPT=''
426
test -n "$skip" && BISECT_OPT='--bisect-all'
345
-
346
- bad=$(git rev-parse --verify refs/bisect/bad) &&
347
- good=$(git for-each-ref --format='^%(objectname)' \
348
- "refs/bisect/good-*" | tr '\012' ' ') &&
427
eval="git rev-list --bisect-vars $BISECT_OPT $good $bad --" &&
428
eval="$eval $(cat "$GIT_DIR/BISECT_NAMES")" &&
429
eval=$(filter_skipped "$eval" "$skip") &&
444
# commit is also a "skip" commit (see above).
445
exit_if_skipped_commits "$bisect_rev"
446
369
- echo "Bisecting: $bisect_nr revisions left to test after this"
370
- git checkout -q "$bisect_rev" || exit
371
- git show-branch "$bisect_rev"
447
+ bisect_checkout "$bisect_rev" "$bisect_nr revisions left to test after this"
448
}
449
450
bisect_visualize() {
491
do
492
git update-ref -d $ref $hash || exit
493
done
494
+ rm -f "$GIT_DIR/BISECT_MERGE_BASES" &&
495
rm -f "$GIT_DIR/BISECT_LOG" &&
496
rm -f "$GIT_DIR/BISECT_NAMES" &&
497
rm -f "$GIT_DIR/BISECT_RUN" &&