Ticket #196: git-bisect.diff

File git-bisect.diff, 21.8 KB (added by dryeo, 5 years ago)

Diff between current git-bisect script and one from the bauxite git release.

  • git-bisect

    old new  
    1 #!/bin/sh
     1#!sh
    22
    3 USAGE='[help|start|bad|good|skip|next|reset|visualize|replay|log|run]'
     3USAGE='[help|start|bad|good|new|old|terms|skip|next|reset|visualize|replay|log|run]'
    44LONG_USAGE='git bisect help
    5         print this long help message.
    6 git bisect start [<bad> [<good>...]] [--] [<pathspec>...]
    7         reset bisect state and start bisection.
    8 git bisect bad [<rev>]
    9         mark <rev> a known-bad revision.
    10 git bisect good [<rev>...]
    11         mark <rev>... known-good revisions.
     5        print this long help message.
     6git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
     7                 [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...]
     8        reset bisect state and start bisection.
     9git bisect (bad|new) [<rev>]
     10        mark <rev> a known-bad revision/
     11                a revision after change in a given property.
     12git bisect (good|old) [<rev>...]
     13        mark <rev>... known-good revisions/
     14                revisions before change in a given property.
     15git bisect terms [--term-good | --term-bad]
     16        show the terms used for old and new commits (default: bad, good)
    1217git bisect skip [(<rev>|<range>)...]
    13         mark <rev>... untestable revisions.
     18        mark <rev>... untestable revisions.
    1419git bisect next
    15         find next bisection to test and check it out.
     20        find next bisection to test and check it out.
    1621git bisect reset [<commit>]
    17         finish bisection search and go back to commit.
     22        finish bisection search and go back to commit.
    1823git bisect visualize
    19         show bisect status in gitk.
     24        show bisect status in gitk.
    2025git bisect replay <logfile>
    21         replay bisection log.
     26        replay bisection log.
    2227git bisect log
    23         show bisect log.
     28        show bisect log.
    2429git bisect run <cmd>...
    25         use <cmd>... to automatically bisect.
     30        use <cmd>... to automatically bisect.
    2631
    2732Please use "git help bisect" to get the full man page.'
    2833
    2934OPTIONS_SPEC=
    3035. git-sh-setup
    31 require_work_tree
    3236
    3337_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
    3438_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
     39TERM_BAD=bad
     40TERM_GOOD=good
     41
     42bisect_head()
     43{
     44        if test -f "$GIT_DIR/BISECT_HEAD"
     45        then
     46                echo BISECT_HEAD
     47        else
     48                echo HEAD
     49        fi
     50}
    3551
    3652bisect_autostart() {
    3753        test -s "$GIT_DIR/BISECT_START" || {
    38                 echo >&2 'You need to start by "git bisect start"'
     54                gettextln "You need to start by \"git bisect start\"" >&2
    3955                if test -t 0
    4056                then
    41                         echo >&2 -n 'Do you want me to do it for you [Y/n]? '
     57                        # TRANSLATORS: Make sure to include [Y] and [n] in your
     58                        # translation. The program will only accept English input
     59                        # at this point.
     60                        gettext "Do you want me to do it for you [Y/n]? " >&2
    4261                        read yesno
    4362                        case "$yesno" in
    4463                        [Nn]*)
     
    5372
    5473bisect_start() {
    5574        #
     75        # Check for one bad and then some good revisions.
     76        #
     77        has_double_dash=0
     78        for arg; do
     79                case "$arg" in --) has_double_dash=1; break ;; esac
     80        done
     81        orig_args=$(git rev-parse --sq-quote "$@")
     82        bad_seen=0
     83        eval=''
     84        must_write_terms=0
     85        revs=''
     86        if test "z$(git rev-parse --is-bare-repository)" != zfalse
     87        then
     88                mode=--no-checkout
     89        else
     90                mode=''
     91        fi
     92        while [ $# -gt 0 ]; do
     93                arg="$1"
     94                case "$arg" in
     95                --)
     96                        shift
     97                        break
     98                ;;
     99                --no-checkout)
     100                        mode=--no-checkout
     101                        shift ;;
     102                --term-good|--term-old)
     103                        shift
     104                        must_write_terms=1
     105                        TERM_GOOD=$1
     106                        shift ;;
     107                --term-good=*|--term-old=*)
     108                        must_write_terms=1
     109                        TERM_GOOD=${1#*=}
     110                        shift ;;
     111                --term-bad|--term-new)
     112                        shift
     113                        must_write_terms=1
     114                        TERM_BAD=$1
     115                        shift ;;
     116                --term-bad=*|--term-new=*)
     117                        must_write_terms=1
     118                        TERM_BAD=${1#*=}
     119                        shift ;;
     120                --*)
     121                        die "$(eval_gettext "unrecognised option: '\$arg'")" ;;
     122                *)
     123                        rev=$(git rev-parse -q --verify "$arg^{commit}") || {
     124                                test $has_double_dash -eq 1 &&
     125                                die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
     126                                break
     127                        }
     128                        revs="$revs $rev"
     129                        shift
     130                        ;;
     131                esac
     132        done
     133
     134        for rev in $revs
     135        do
     136                # The user ran "git bisect start <sha1>
     137                # <sha1>", hence did not explicitly specify
     138                # the terms, but we are already starting to
     139                # set references named with the default terms,
     140                # and won't be able to change afterwards.
     141                must_write_terms=1
     142
     143                case $bad_seen in
     144                0) state=$TERM_BAD ; bad_seen=1 ;;
     145                *) state=$TERM_GOOD ;;
     146                esac
     147                eval="$eval bisect_write '$state' '$rev' 'nolog' &&"
     148        done
     149        #
    56150        # Verify HEAD.
    57151        #
    58152        head=$(GIT_DIR="$GIT_DIR" git symbolic-ref -q HEAD) ||
    59153        head=$(GIT_DIR="$GIT_DIR" git rev-parse --verify HEAD) ||
    60         die "Bad HEAD - I need a HEAD"
     154        die "$(gettext "Bad HEAD - I need a HEAD")"
    61155
    62156        #
    63157        # Check if we are bisecting.
     
    67161        then
    68162                # Reset to the rev from where we started.
    69163                start_head=$(cat "$GIT_DIR/BISECT_START")
    70                 git checkout "$start_head" -- || exit
     164                if test "z$mode" != "z--no-checkout"
     165                then
     166                        git checkout "$start_head" -- ||
     167                        die "$(eval_gettext "Checking out '\$start_head' failed. Try 'git bisect reset <valid-branch>'.")"
     168                fi
    71169        else
    72170                # Get rev from where we start.
    73171                case "$head" in
     
    76174                        # cogito usage, and cogito users should understand
    77175                        # it relates to cg-seek.
    78176                        [ -s "$GIT_DIR/head-name" ] &&
    79                                 die "won't bisect on seeked tree"
     177                                die "$(gettext "won't bisect on cg-seek'ed tree")"
    80178                        start_head="${head#refs/heads/}"
    81179                        ;;
    82180                *)
    83                         die "Bad HEAD - strange symbolic ref"
     181                        die "$(gettext "Bad HEAD - strange symbolic ref")"
    84182                        ;;
    85183                esac
    86184        fi
     
    91189        bisect_clean_state || exit
    92190
    93191        #
    94         # Check for one bad and then some good revisions.
    95         #
    96         has_double_dash=0
    97         for arg; do
    98             case "$arg" in --) has_double_dash=1; break ;; esac
    99         done
    100         orig_args=$(git rev-parse --sq-quote "$@")
    101         bad_seen=0
    102         eval=''
    103         while [ $# -gt 0 ]; do
    104             arg="$1"
    105             case "$arg" in
    106             --)
    107                 shift
    108                 break
    109                 ;;
    110             *)
    111                 rev=$(git rev-parse -q --verify "$arg^{commit}") || {
    112                     test $has_double_dash -eq 1 &&
    113                         die "'$arg' does not appear to be a valid revision"
    114                     break
    115                 }
    116                 case $bad_seen in
    117                 0) state='bad' ; bad_seen=1 ;;
    118                 *) state='good' ;;
    119                 esac
    120                 eval="$eval bisect_write '$state' '$rev' 'nolog'; "
    121                 shift
    122                 ;;
    123             esac
    124         done
    125 
    126         #
    127192        # Change state.
    128193        # In case of mistaken revs or checkout error, or signals received,
    129194        # "bisect_auto_next" below may exit or misbehave.
     
    136201        #
    137202        # Write new start state.
    138203        #
    139         echo "$start_head" >"$GIT_DIR/BISECT_START" &&
     204        echo "$start_head" >"$GIT_DIR/BISECT_START" && {
     205                test "z$mode" != "z--no-checkout" ||
     206                git update-ref --no-deref BISECT_HEAD "$start_head"
     207        } &&
    140208        git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
    141         eval "$eval" &&
     209        eval "$eval true" &&
     210        if test $must_write_terms -eq 1
     211        then
     212                write_terms "$TERM_BAD" "$TERM_GOOD"
     213        fi &&
    142214        echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
    143215        #
    144216        # Check if we can proceed to the next bisect state.
     
    153225        rev="$2"
    154226        nolog="$3"
    155227        case "$state" in
    156                 bad)            tag="$state" ;;
    157                 good|skip)      tag="$state"-"$rev" ;;
    158                 *)              die "Bad bisect_write argument: $state" ;;
     228                "$TERM_BAD")
     229                        tag="$state" ;;
     230                "$TERM_GOOD"|skip)
     231                        tag="$state"-"$rev" ;;
     232                *)
     233                        die "$(eval_gettext "Bad bisect_write argument: \$state")" ;;
    159234        esac
    160235        git update-ref "refs/bisect/$tag" "$rev" || exit
    161236        echo "# $state: $(git show-branch $rev)" >>"$GIT_DIR/BISECT_LOG"
     
    169244
    170245check_expected_revs() {
    171246        for _rev in "$@"; do
    172                 if ! is_expected_rev "$_rev"; then
     247                if ! is_expected_rev "$_rev"
     248                then
    173249                        rm -f "$GIT_DIR/BISECT_ANCESTORS_OK"
    174250                        rm -f "$GIT_DIR/BISECT_EXPECTED_REV"
    175251                        return
     
    178254}
    179255
    180256bisect_skip() {
    181         all=''
     257        all=''
    182258        for arg in "$@"
    183259        do
    184             case "$arg" in
    185             *..*)
    186                 revs=$(git rev-list "$arg") || die "Bad rev input: $arg" ;;
    187             *)
    188                 revs=$(git rev-parse --sq-quote "$arg") ;;
    189             esac
    190             all="$all $revs"
    191         done
    192         eval bisect_state 'skip' $all
     260                case "$arg" in
     261                *..*)
     262                        revs=$(git rev-list "$arg") || die "$(eval_gettext "Bad rev input: \$arg")" ;;
     263                *)
     264                        revs=$(git rev-parse --sq-quote "$arg") ;;
     265                esac
     266                all="$all $revs"
     267        done
     268        eval bisect_state 'skip' $all
    193269}
    194270
    195271bisect_state() {
    196272        bisect_autostart
    197273        state=$1
     274        check_and_set_terms $state
    198275        case "$#,$state" in
    199276        0,*)
    200277                die "Please call 'bisect_state' with at least one argument." ;;
    201         1,bad|1,good|1,skip)
    202                 rev=$(git rev-parse --verify HEAD) ||
    203                         die "Bad rev input: HEAD"
     278        1,"$TERM_BAD"|1,"$TERM_GOOD"|1,skip)
     279                bisected_head=$(bisect_head)
     280                rev=$(git rev-parse --verify "$bisected_head") ||
     281                        die "$(eval_gettext "Bad rev input: \$bisected_head")"
    204282                bisect_write "$state" "$rev"
    205283                check_expected_revs "$rev" ;;
    206         2,bad|*,good|*,skip)
     284        2,"$TERM_BAD"|*,"$TERM_GOOD"|*,skip)
    207285                shift
    208                 eval=''
     286                hash_list=''
    209287                for rev in "$@"
    210288                do
    211289                        sha=$(git rev-parse --verify "$rev^{commit}") ||
    212                                 die "Bad rev input: $rev"
    213                         eval="$eval bisect_write '$state' '$sha'; "
     290                                die "$(eval_gettext "Bad rev input: \$rev")"
     291                        hash_list="$hash_list $sha"
     292                done
     293                for rev in $hash_list
     294                do
     295                        bisect_write "$state" "$rev"
    214296                done
    215                 eval "$eval"
    216                 check_expected_revs "$@" ;;
    217         *,bad)
    218                 die "'git bisect bad' can take only one argument." ;;
     297                check_expected_revs $hash_list ;;
     298        *,"$TERM_BAD")
     299                die "$(eval_gettext "'git bisect \$TERM_BAD' can take only one argument.")" ;;
    219300        *)
    220301                usage ;;
    221302        esac
     
    224305
    225306bisect_next_check() {
    226307        missing_good= missing_bad=
    227         git show-ref -q --verify refs/bisect/bad || missing_bad=t
    228         test -n "$(git for-each-ref "refs/bisect/good-*")" || missing_good=t
     308        git show-ref -q --verify refs/bisect/$TERM_BAD || missing_bad=t
     309        test -n "$(git for-each-ref "refs/bisect/$TERM_GOOD-*")" || missing_good=t
    229310
    230311        case "$missing_good,$missing_bad,$1" in
    231312        ,,*)
    232                 : have both good and bad - ok
     313                : have both $TERM_GOOD and $TERM_BAD - ok
    233314                ;;
    234315        *,)
    235316                # do not have both but not asked to fail - just report.
    236317                false
    237318                ;;
    238         t,,good)
    239                 # have bad but not good.  we could bisect although
     319        t,,"$TERM_GOOD")
     320                # have bad (or new) but not good (or old).  we could bisect although
    240321                # this is less optimum.
    241                 echo >&2 'Warning: bisecting only with a bad commit.'
     322                eval_gettextln "Warning: bisecting only with a \$TERM_BAD commit." >&2
    242323                if test -t 0
    243324                then
    244                         printf >&2 'Are you sure [Y/n]? '
     325                        # TRANSLATORS: Make sure to include [Y] and [n] in your
     326                        # translation. The program will only accept English input
     327                        # at this point.
     328                        gettext "Are you sure [Y/n]? " >&2
    245329                        read yesno
    246330                        case "$yesno" in [Nn]*) exit 1 ;; esac
    247331                fi
    248                 : bisect without good...
     332                : bisect without $TERM_GOOD...
    249333                ;;
    250334        *)
    251                 THEN=''
    252                 test -s "$GIT_DIR/BISECT_START" || {
    253                         echo >&2 'You need to start by "git bisect start".'
    254                         THEN='then '
    255                 }
    256                 echo >&2 'You '$THEN'need to give me at least one good' \
    257                         'and one bad revisions.'
    258                 echo >&2 '(You can use "git bisect bad" and' \
    259                         '"git bisect good" for that.)'
     335                bad_syn=$(bisect_voc bad)
     336                good_syn=$(bisect_voc good)
     337                if test -s "$GIT_DIR/BISECT_START"
     338                then
     339
     340                        eval_gettextln "You need to give me at least one \$bad_syn and one \$good_syn revision.
     341(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
     342                else
     343                        eval_gettextln "You need to start by \"git bisect start\".
     344You then need to give me at least one \$good_syn and one \$bad_syn revision.
     345(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
     346                fi
    260347                exit 1 ;;
    261348        esac
    262349}
     
    268355bisect_next() {
    269356        case "$#" in 0) ;; *) usage ;; esac
    270357        bisect_autostart
    271         bisect_next_check good
     358        bisect_next_check $TERM_GOOD
    272359
    273360        # Perform all bisection computation, display and checkout
    274         git bisect--helper --next-all
     361        git bisect--helper --next-all $(test -f "$GIT_DIR/BISECT_HEAD" && echo --no-checkout)
    275362        res=$?
    276363
    277         # Check if we should exit because bisection is finished
    278         test $res -eq 10 && exit 0
     364        # Check if we should exit because bisection is finished
     365        if test $res -eq 10
     366        then
     367                bad_rev=$(git show-ref --hash --verify refs/bisect/$TERM_BAD)
     368                bad_commit=$(git show-branch $bad_rev)
     369                echo "# first $TERM_BAD commit: $bad_commit" >>"$GIT_DIR/BISECT_LOG"
     370                exit 0
     371        elif test $res -eq 2
     372        then
     373                echo "# only skipped commits left to test" >>"$GIT_DIR/BISECT_LOG"
     374                good_revs=$(git for-each-ref --format="%(objectname)" "refs/bisect/$TERM_GOOD-*")
     375                for skipped in $(git rev-list refs/bisect/$TERM_BAD --not $good_revs)
     376                do
     377                        skipped_commit=$(git show-branch $skipped)
     378                        echo "# possible first $TERM_BAD commit: $skipped_commit" >>"$GIT_DIR/BISECT_LOG"
     379                done
     380                exit $res
     381        fi
    279382
    280383        # Check for an error in the bisection process
    281384        test $res -ne 0 && exit $res
     
    288391
    289392        if test $# = 0
    290393        then
    291                 case "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" in
    292                 '')     set git log ;;
    293                 set*)   set gitk ;;
    294                 esac
     394                if test -n "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" &&
     395                        type gitk >/dev/null 2>&1
     396                then
     397                        set gitk
     398                else
     399                        set git log
     400                fi
    295401        else
    296402                case "$1" in
    297403                git*|tig) ;;
     
    305411
    306412bisect_reset() {
    307413        test -s "$GIT_DIR/BISECT_START" || {
    308                 echo "We are not bisecting."
     414                gettextln "We are not bisecting."
    309415                return
    310416        }
    311417        case "$#" in
    312418        0) branch=$(cat "$GIT_DIR/BISECT_START") ;;
    313         1) git rev-parse --quiet --verify "$1^{commit}" > /dev/null ||
    314                die "'$1' is not a valid commit"
    315            branch="$1" ;;
     419        1) git rev-parse --quiet --verify "$1^{commit}" >/dev/null || {
     420                        invalid="$1"
     421                        die "$(eval_gettext "'\$invalid' is not a valid commit")"
     422                }
     423                branch="$1" ;;
    316424        *)
    317             usage ;;
     425                usage ;;
    318426        esac
    319         git checkout "$branch" -- && bisect_clean_state
     427
     428        if ! test -f "$GIT_DIR/BISECT_HEAD" && ! git checkout "$branch" --
     429        then
     430                die "$(eval_gettext "Could not check out original HEAD '\$branch'.
     431Try 'git bisect reset <commit>'.")"
     432        fi
     433        bisect_clean_state
    320434}
    321435
    322436bisect_clean_state() {
     
    331445        rm -f "$GIT_DIR/BISECT_LOG" &&
    332446        rm -f "$GIT_DIR/BISECT_NAMES" &&
    333447        rm -f "$GIT_DIR/BISECT_RUN" &&
     448        rm -f "$GIT_DIR/BISECT_TERMS" &&
    334449        # Cleanup head-name if it got left by an old version of git-bisect
    335450        rm -f "$GIT_DIR/head-name" &&
    336 
     451        git update-ref -d --no-deref BISECT_HEAD &&
     452        # clean up BISECT_START last
    337453        rm -f "$GIT_DIR/BISECT_START"
    338454}
    339455
    340456bisect_replay () {
    341         test -r "$1" || die "cannot read $1 for replaying"
     457        file="$1"
     458        test "$#" -eq 1 || die "$(gettext "No logfile given")"
     459        test -r "$file" || die "$(eval_gettext "cannot read \$file for replaying")"
    342460        bisect_reset
    343461        while read git bisect command rev
    344462        do
    345                 test "$git $bisect" = "git bisect" -o "$git" = "git-bisect" || continue
    346                 if test "$git" = "git-bisect"; then
     463                test "$git $bisect" = "git bisect" || test "$git" = "git-bisect" || continue
     464                if test "$git" = "git-bisect"
     465                then
    347466                        rev="$command"
    348467                        command="$bisect"
    349468                fi
     469                get_terms
     470                check_and_set_terms "$command"
    350471                case "$command" in
    351472                start)
    352473                        cmd="bisect_start $rev"
    353474                        eval "$cmd" ;;
    354                 good|bad|skip)
     475                "$TERM_GOOD"|"$TERM_BAD"|skip)
    355476                        bisect_write "$command" "$rev" ;;
     477                terms)
     478                        bisect_terms $rev ;;
    356479                *)
    357                         die "?? what are you talking about?" ;;
     480                        die "$(gettext "?? what are you talking about?")" ;;
    358481                esac
    359         done <"$1"
     482        done <"$file"
    360483        bisect_auto_next
    361484}
    362485
    363486bisect_run () {
    364     bisect_next_check fail
     487        bisect_next_check fail
     488
     489        while true
     490        do
     491                command="$@"
     492                eval_gettextln "running \$command"
     493                "$@"
     494                res=$?
     495
     496                # Check for really bad run error.
     497                if [ $res -lt 0 -o $res -ge 128 ]
     498                then
     499                        eval_gettextln "bisect run failed:
     500exit code \$res from '\$command' is < 0 or >= 128" >&2
     501                        exit $res
     502                fi
     503
     504                # Find current state depending on run success or failure.
     505                # A special exit code of 125 means cannot test.
     506                if [ $res -eq 125 ]
     507                then
     508                        state='skip'
     509                elif [ $res -gt 0 ]
     510                then
     511                        state="$TERM_BAD"
     512                else
     513                        state="$TERM_GOOD"
     514                fi
     515
     516                # We have to use a subshell because "bisect_state" can exit.
     517                ( bisect_state $state >"$GIT_DIR/BISECT_RUN" )
     518                res=$?
     519
     520                cat "$GIT_DIR/BISECT_RUN"
     521
     522                if sane_grep "first $TERM_BAD commit could be any of" "$GIT_DIR/BISECT_RUN" \
     523                        >/dev/null
     524                then
     525                        gettextln "bisect run cannot continue any more" >&2
     526                        exit $res
     527                fi
     528
     529                if [ $res -ne 0 ]
     530                then
     531                        eval_gettextln "bisect run failed:
     532'bisect_state \$state' exited with error code \$res" >&2
     533                        exit $res
     534                fi
     535
     536                if sane_grep "is the first $TERM_BAD commit" "$GIT_DIR/BISECT_RUN" >/dev/null
     537                then
     538                        gettextln "bisect run success"
     539                        exit 0;
     540                fi
     541
     542        done
     543}
     544
     545bisect_log () {
     546        test -s "$GIT_DIR/BISECT_LOG" || die "$(gettext "We are not bisecting.")"
     547        cat "$GIT_DIR/BISECT_LOG"
     548}
     549
     550get_terms () {
     551        if test -s "$GIT_DIR/BISECT_TERMS"
     552        then
     553                {
     554                read TERM_BAD
     555                read TERM_GOOD
     556                } <"$GIT_DIR/BISECT_TERMS"
     557        fi
     558}
     559
     560write_terms () {
     561        TERM_BAD=$1
     562        TERM_GOOD=$2
     563        if test "$TERM_BAD" = "$TERM_GOOD"
     564        then
     565                die "$(gettext "please use two different terms")"
     566        fi
     567        check_term_format "$TERM_BAD" bad
     568        check_term_format "$TERM_GOOD" good
     569        printf '%s\n%s\n' "$TERM_BAD" "$TERM_GOOD" >"$GIT_DIR/BISECT_TERMS"
     570}
     571
     572check_term_format () {
     573        term=$1
     574        git check-ref-format refs/bisect/"$term" ||
     575        die "$(eval_gettext "'\$term' is not a valid term")"
     576        case "$term" in
     577        help|start|terms|skip|next|reset|visualize|replay|log|run)
     578                die "$(eval_gettext "can't use the builtin command '\$term' as a term")"
     579                ;;
     580        bad|new)
     581                if test "$2" != bad
     582                then
     583                        # In theory, nothing prevents swapping
     584                        # completely good and bad, but this situation
     585                        # could be confusing and hasn't been tested
     586                        # enough. Forbid it for now.
     587                        die "$(eval_gettext "can't change the meaning of term '\$term'")"
     588                fi
     589                ;;
     590        good|old)
     591                if test "$2" != good
     592                then
     593                        die "$(eval_gettext "can't change the meaning of term '\$term'")"
     594                fi
     595                ;;
     596        esac
     597}
    365598
    366     while true
    367     do
    368       echo "running $@"
    369       "$@"
    370       res=$?
    371 
    372       # Check for really bad run error.
    373       if [ $res -lt 0 -o $res -ge 128 ]; then
    374           echo >&2 "bisect run failed:"
    375           echo >&2 "exit code $res from '$@' is < 0 or >= 128"
    376           exit $res
    377       fi
    378 
    379       # Find current state depending on run success or failure.
    380       # A special exit code of 125 means cannot test.
    381       if [ $res -eq 125 ]; then
    382           state='skip'
    383       elif [ $res -gt 0 ]; then
    384           state='bad'
    385       else
    386           state='good'
    387       fi
    388 
    389       # We have to use a subshell because "bisect_state" can exit.
    390       ( bisect_state $state > "$GIT_DIR/BISECT_RUN" )
    391       res=$?
    392 
    393       cat "$GIT_DIR/BISECT_RUN"
    394 
    395       if sane_grep "first bad commit could be any of" "$GIT_DIR/BISECT_RUN" \
    396                 > /dev/null; then
    397           echo >&2 "bisect run cannot continue any more"
    398           exit $res
    399       fi
    400 
    401       if [ $res -ne 0 ]; then
    402           echo >&2 "bisect run failed:"
    403           echo >&2 "'bisect_state $state' exited with error code $res"
    404           exit $res
    405       fi
    406 
    407       if sane_grep "is the first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null; then
    408           echo "bisect run success"
    409           exit 0;
    410       fi
     599check_and_set_terms () {
     600        cmd="$1"
     601        case "$cmd" in
     602        skip|start|terms) ;;
     603        *)
     604                if test -s "$GIT_DIR/BISECT_TERMS" && test "$cmd" != "$TERM_BAD" && test "$cmd" != "$TERM_GOOD"
     605                then
     606                        die "$(eval_gettext "Invalid command: you're currently in a \$TERM_BAD/\$TERM_GOOD bisect.")"
     607                fi
     608                case "$cmd" in
     609                bad|good)
     610                        if ! test -s "$GIT_DIR/BISECT_TERMS"
     611                        then
     612                                write_terms bad good
     613                        fi
     614                        ;;
     615                new|old)
     616                        if ! test -s "$GIT_DIR/BISECT_TERMS"
     617                        then
     618                                write_terms new old
     619                        fi
     620                        ;;
     621                esac ;;
     622        esac
     623}
    411624
    412     done
     625bisect_voc () {
     626        case "$1" in
     627        bad) echo "bad|new" ;;
     628        good) echo "good|old" ;;
     629        esac
    413630}
    414631
     632bisect_terms () {
     633        get_terms
     634        if ! test -s "$GIT_DIR/BISECT_TERMS"
     635        then
     636                die "$(gettext "no terms defined")"
     637        fi
     638        case "$#" in
     639        0)
     640                gettextln "Your current terms are $TERM_GOOD for the old state
     641and $TERM_BAD for the new state."
     642                ;;
     643        1)
     644                arg=$1
     645                case "$arg" in
     646                        --term-good|--term-old)
     647                                printf '%s\n' "$TERM_GOOD"
     648                                ;;
     649                        --term-bad|--term-new)
     650                                printf '%s\n' "$TERM_BAD"
     651                                ;;
     652                        *)
     653                                die "$(eval_gettext "invalid argument \$arg for 'git bisect terms'.
     654Supported options are: --term-good|--term-old and --term-bad|--term-new.")"
     655                                ;;
     656                esac
     657                ;;
     658        *)
     659                usage ;;
     660        esac
     661}
    415662
    416663case "$#" in
    4176640)
    418     usage ;;
     665        usage ;;
    419666*)
    420     cmd="$1"
    421     shift
    422     case "$cmd" in
    423     help)
    424         git bisect -h ;;
    425     start)
    426         bisect_start "$@" ;;
    427     bad|good)
    428         bisect_state "$cmd" "$@" ;;
    429     skip)
    430         bisect_skip "$@" ;;
    431     next)
    432         # Not sure we want "next" at the UI level anymore.
    433         bisect_next "$@" ;;
    434     visualize|view)
    435         bisect_visualize "$@" ;;
    436     reset)
    437         bisect_reset "$@" ;;
    438     replay)
    439         bisect_replay "$@" ;;
    440     log)
    441         cat "$GIT_DIR/BISECT_LOG" ;;
    442     run)
    443         bisect_run "$@" ;;
    444     *)
    445         usage ;;
    446     esac
     667        cmd="$1"
     668        get_terms
     669        shift
     670        case "$cmd" in
     671        help)
     672                git bisect -h ;;
     673        start)
     674                bisect_start "$@" ;;
     675        bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD")
     676                bisect_state "$cmd" "$@" ;;
     677        skip)
     678                bisect_skip "$@" ;;
     679        next)
     680                # Not sure we want "next" at the UI level anymore.
     681                bisect_next "$@" ;;
     682        visualize|view)
     683                bisect_visualize "$@" ;;
     684        reset)
     685                bisect_reset "$@" ;;
     686        replay)
     687                bisect_replay "$@" ;;
     688        log)
     689                bisect_log ;;
     690        run)
     691                bisect_run "$@" ;;
     692        terms)
     693                bisect_terms "$@" ;;
     694        *)
     695                usage ;;
     696        esac
    447697esac