X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=git-bisect.sh;h=991b2ef37e5121d89f40d1b10964bf5d5beed40b;hb=f7597acac069bbaad8887cb315a4e5420222971a;hp=d8d9bfde4cdd4b558992c68cb7cdaaa1b8a1212d;hpb=68951af30c2ac7f74f0d794a8674ac320a84250a;p=git.git diff --git a/git-bisect.sh b/git-bisect.sh index d8d9bfde4..991b2ef37 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -44,7 +44,7 @@ sq() { } bisect_autostart() { - test -f "$GIT_DIR/BISECT_NAMES" || { + test -s "$GIT_DIR/BISECT_START" || { echo >&2 'You need to start by "git bisect start"' if test -t 0 then @@ -63,37 +63,42 @@ bisect_autostart() { bisect_start() { # - # Verify HEAD. If we were bisecting before this, reset to the - # top-of-line master first! + # Verify HEAD. # head=$(GIT_DIR="$GIT_DIR" git symbolic-ref -q HEAD) || head=$(GIT_DIR="$GIT_DIR" git rev-parse --verify HEAD) || die "Bad HEAD - I need a HEAD" + + # + # Check if we are bisecting. + # start_head='' - case "$head" in - refs/heads/bisect) - if [ -s "$GIT_DIR/BISECT_START" ]; then - branch=`cat "$GIT_DIR/BISECT_START"` - else - branch=master - fi - git checkout $branch || exit - ;; - refs/heads/*|$_x40) - # This error message should only be triggered by cogito usage, - # and cogito users should understand it relates to cg-seek. - [ -s "$GIT_DIR/head-name" ] && die "won't bisect on seeked tree" - start_head="${head#refs/heads/}" - ;; - *) - die "Bad HEAD - strange symbolic ref" - ;; - esac + if test -s "$GIT_DIR/BISECT_START" + then + # Reset to the rev from where we started. + start_head=$(cat "$GIT_DIR/BISECT_START") + git checkout "$start_head" || exit + else + # Get rev from where we start. + case "$head" in + refs/heads/*|$_x40) + # This error message should only be triggered by + # cogito usage, and cogito users should understand + # it relates to cg-seek. + [ -s "$GIT_DIR/head-name" ] && + die "won't bisect on seeked tree" + start_head="${head#refs/heads/}" + ;; + *) + die "Bad HEAD - strange symbolic ref" + ;; + esac + fi # - # Get rid of any old bisect state + # Get rid of any old bisect state. # - bisect_clean_state + bisect_clean_state || exit # # Check for one bad and then some good revisions. @@ -113,7 +118,7 @@ bisect_start() { break ;; *) - rev=$(git rev-parse --verify "$arg^{commit}" 2>/dev/null) || { + rev=$(git rev-parse -q --verify "$arg^{commit}") || { test $has_double_dash -eq 1 && die "'$arg' does not appear to be a valid revision" break @@ -128,11 +133,29 @@ bisect_start() { esac done - sq "$@" >"$GIT_DIR/BISECT_NAMES" - test -n "$start_head" && echo "$start_head" >"$GIT_DIR/BISECT_START" - eval "$eval" - echo "git-bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" + # + # Change state. + # In case of mistaken revs or checkout error, or signals received, + # "bisect_auto_next" below may exit or misbehave. + # We have to trap this to be able to clean up using + # "bisect_clean_state". + # + trap 'bisect_clean_state' 0 + trap 'exit 255' 1 2 3 15 + + # + # Write new start state. + # + echo "$start_head" >"$GIT_DIR/BISECT_START" && + sq "$@" >"$GIT_DIR/BISECT_NAMES" && + eval "$eval" && + echo "git-bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit + # + # Check if we can proceed to the next bisect state. + # bisect_auto_next + + trap '-' 0 } bisect_write() { @@ -144,9 +167,9 @@ bisect_write() { good|skip) tag="$state"-"$rev" ;; *) die "Bad bisect_write argument: $state" ;; esac - git update-ref "refs/bisect/$tag" "$rev" + git update-ref "refs/bisect/$tag" "$rev" || exit echo "# $state: $(git show-branch $rev)" >>"$GIT_DIR/BISECT_LOG" - test -z "$nolog" && echo "git-bisect $state $rev" >>"$GIT_DIR/BISECT_LOG" + test -n "$nolog" || echo "git-bisect $state $rev" >>"$GIT_DIR/BISECT_LOG" } bisect_state() { @@ -203,7 +226,7 @@ bisect_next_check() { ;; *) THEN='' - test -f "$GIT_DIR/BISECT_NAMES" || { + test -s "$GIT_DIR/BISECT_START" || { echo >&2 'You need to start by "git bisect start".' THEN='then ' } @@ -219,18 +242,33 @@ 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 $_eval + eval_rev_list "$_eval" return fi # Let's parse the output of: # "git rev-list --bisect-vars --bisect-all ..." - eval $_eval | while read hash line + eval_rev_list "$_eval" | while read hash line do case "$VARS,$FOUND,$TRIED,$hash" in # We display some vars. @@ -328,9 +366,7 @@ bisect_next() { exit_if_skipped_commits "$bisect_rev" echo "Bisecting: $bisect_nr revisions left to test after this" - git branch -f new-bisect "$bisect_rev" - git checkout -q new-bisect || exit - git branch -M new-bisect bisect + git checkout -q "$bisect_rev" || exit git show-branch "$bisect_rev" } @@ -356,40 +392,35 @@ bisect_visualize() { } bisect_reset() { - test -f "$GIT_DIR/BISECT_NAMES" || { + test -s "$GIT_DIR/BISECT_START" || { echo "We are not bisecting." return } case "$#" in - 0) if [ -s "$GIT_DIR/BISECT_START" ]; then - branch=`cat "$GIT_DIR/BISECT_START"` - else - branch=master - fi ;; + 0) branch=$(cat "$GIT_DIR/BISECT_START") ;; 1) git show-ref --verify --quiet -- "refs/heads/$1" || die "$1 does not seem to be a valid branch" branch="$1" ;; *) usage ;; esac - if git checkout "$branch"; then - # Cleanup head-name if it got left by an old version of git-bisect - rm -f "$GIT_DIR/head-name" - rm -f "$GIT_DIR/BISECT_START" - bisect_clean_state - fi + git checkout "$branch" && bisect_clean_state } bisect_clean_state() { # There may be some refs packed during bisection. - git for-each-ref --format='%(refname) %(objectname)' refs/bisect/\* refs/heads/bisect | + git for-each-ref --format='%(refname) %(objectname)' refs/bisect/\* | while read ref hash do - git update-ref -d $ref $hash + git update-ref -d $ref $hash || exit done - rm -f "$GIT_DIR/BISECT_LOG" - rm -f "$GIT_DIR/BISECT_NAMES" - rm -f "$GIT_DIR/BISECT_RUN" + rm -f "$GIT_DIR/BISECT_LOG" && + rm -f "$GIT_DIR/BISECT_NAMES" && + rm -f "$GIT_DIR/BISECT_RUN" && + # Cleanup head-name if it got left by an old version of git-bisect + rm -f "$GIT_DIR/head-name" && + + rm -f "$GIT_DIR/BISECT_START" } bisect_replay () {