diff --git a/git-bisect.sh b/git-bisect.sh index 97ac600873..b314d47704 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -243,33 +243,18 @@ bisect_auto_next() { bisect_next_check && bisect_next || : } -eval_rev_list() { - _eval="$1" - - eval $_eval - res=$? - - if [ $res -ne 0 ]; then - echo >&2 "'git rev-list --bisect-vars' failed:" - echo >&2 "maybe you mistake good and bad revs?" - exit $res - fi - - return $res -} - filter_skipped() { _eval="$1" _skip="$2" if [ -z "$_skip" ]; then - eval_rev_list "$_eval" + eval "$_eval" return fi # Let's parse the output of: # "git rev-list --bisect-vars --bisect-all ..." - eval_rev_list "$_eval" | while read hash line + eval "$_eval" | while read hash line do case "$VARS,$FOUND,$TRIED,$hash" in # We display some vars. @@ -332,20 +317,113 @@ exit_if_skipped_commits () { fi } +bisect_checkout() { + _rev="$1" + _msg="$2" + echo "Bisecting: $_msg" + git checkout -q "$_rev" || exit + git show-branch "$_rev" +} + +is_among() { + _rev="$1" + _list="$2" + case "$_list" in *$_rev*) return 0 ;; esac + return 1 +} + +is_testing_merge_base() { + grep "^testing $1$" "$GIT_DIR/BISECT_MERGE_BASES" >/dev/null 2>&1 +} + +mark_testing_merge_base() { + echo "testing $1" >> "$GIT_DIR/BISECT_MERGE_BASES" +} + +handle_bad_merge_base() { + _badmb="$1" + _good="$2" + if is_testing_merge_base "$_badmb"; then + cat >&2 <&2 <&2 < my_bisect_log.txt && + grep "merge base must be tested" my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + git bisect good > my_bisect_log.txt && + test_must_fail grep "merge base must be tested" my_bisect_log.txt && + grep $HASH6 my_bisect_log.txt && + git bisect reset +' +test_expect_success 'skipped merge base when good and bad are siblings' ' + git bisect start "$SIDE_HASH7" "$HASH7" > my_bisect_log.txt && + grep "merge base must be tested" my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + git bisect skip > my_bisect_log.txt 2>&1 && + grep "Warning" my_bisect_log.txt && + grep $SIDE_HASH6 my_bisect_log.txt && + git bisect reset +' + +test_expect_success 'bad merge base when good and bad are siblings' ' + git bisect start "$HASH7" HEAD > my_bisect_log.txt && + grep "merge base must be tested" my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + test_must_fail git bisect bad > my_bisect_log.txt 2>&1 && + grep "merge base $HASH4 is bad" my_bisect_log.txt && + grep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt && + git bisect reset +' + +# This creates a few more commits (A and B) to test "siblings" cases +# when a good and a bad rev have many merge bases. +# +# We should have the following: +# +# H1-H2-H3-H4-H5-H6-H7 +# \ \ \ +# S5-A \ +# \ \ +# S6-S7----B +# +# And there A and B have 2 merge bases (S5 and H5) that should be +# reported by "git merge-base --all A B". +# +test_expect_success 'many merge bases creation' ' + git checkout "$SIDE_HASH5" && + git merge -m "merge HASH5 and SIDE_HASH5" "$HASH5" && + A_HASH=$(git rev-parse --verify HEAD) && + git checkout side && + git merge -m "merge HASH7 and SIDE_HASH7" "$HASH7" && + B_HASH=$(git rev-parse --verify HEAD) && + git merge-base --all "$A_HASH" "$B_HASH" > merge_bases.txt && + test $(wc -l < merge_bases.txt) = "2" && + grep "$HASH5" merge_bases.txt && + grep "$SIDE_HASH5" merge_bases.txt +' + +test_expect_success 'good merge bases when good and bad are siblings' ' + git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt && + grep "merge base must be tested" my_bisect_log.txt && + git bisect good > my_bisect_log2.txt && + grep "merge base must be tested" my_bisect_log2.txt && + { + { + grep "$SIDE_HASH5" my_bisect_log.txt && + grep "$HASH5" my_bisect_log2.txt + } || { + grep "$SIDE_HASH5" my_bisect_log2.txt && + grep "$HASH5" my_bisect_log.txt + } + } && + git bisect reset +' + # # test_done