X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=git-bisect.sh;h=11313a7949909f61f47ccc061cfc6390b225c630;hb=566842f62bdf1f16c2e94fb431445d2e6c0f3f0b;hp=03df1433ef12014584f23f16e65124c219c2f466;hpb=0a8f4f0020cb35095005852c0797f0b90e9ebb74;p=git.git diff --git a/git-bisect.sh b/git-bisect.sh index 03df1433e..11313a794 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -1,19 +1,21 @@ #!/bin/sh -USAGE='[start|bad|good|next|reset|visualize]' +USAGE='[start|bad|good|next|reset|visualize|replay|log|run]' LONG_USAGE='git bisect start [] reset bisect state and start bisection. git bisect bad [] mark a known-bad revision. git bisect good [...] mark ... known-good revisions. git bisect next find next bisection to test and check it out. git bisect reset [] finish bisection search and go back to branch. git bisect visualize show bisect status in gitk. -git bisect replay replay bisection log -git bisect log show bisect log.' +git bisect replay replay bisection log. +git bisect log show bisect log. +git bisect run ... use ... to automatically bisect.' . git-sh-setup +require_work_tree sq() { - perl -e ' + @@PERL@@ -e ' for (@ARGV) { s/'\''/'\'\\\\\'\''/g; print " '\''$_'\''"; @@ -48,7 +50,7 @@ bisect_start() { head=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD) || die "Bad HEAD - I need a symbolic ref" case "$head" in - refs/heads/bisect*) + refs/heads/bisect) if [ -s "$GIT_DIR/head-name" ]; then branch=`cat "$GIT_DIR/head-name"` else @@ -84,7 +86,7 @@ bisect_bad() { 0) rev=$(git-rev-parse --verify HEAD) ;; 1) - rev=$(git-rev-parse --verify "$1") ;; + rev=$(git-rev-parse --verify "$1^{commit}") ;; *) usage ;; esac || exit @@ -103,7 +105,7 @@ bisect_good() { esac for rev in $revs do - rev=$(git-rev-parse --verify "$rev") || exit + rev=$(git-rev-parse --verify "$rev^{commit}") || exit echo "$rev" >"$GIT_DIR/refs/bisect/good-$rev" echo "# good: "$(git-show-branch $rev) >>"$GIT_DIR/BISECT_LOG" echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG" @@ -121,7 +123,15 @@ bisect_next_check() { case "$next_ok,$1" in no,) false ;; no,fail) - echo >&2 'You need to give me at least one good and one bad revisions.' + THEN='' + test -d "$GIT_DIR/refs/bisect" || { + echo >&2 'You need to start by "git bisect start".' + THEN='then ' + } + echo >&2 'You '$THEN'need to give me at least one good' \ + 'and one bad revisions.' + echo >&2 '(You can use "git bisect bad" and' \ + '"git bisect good" for that.)' exit 1 ;; *) true ;; @@ -139,7 +149,7 @@ bisect_next() { bad=$(git-rev-parse --verify refs/bisect/bad) && good=$(git-rev-parse --sq --revs-only --not \ $(cd "$GIT_DIR" && ls refs/bisect/good-*)) && - rev=$(eval "git-rev-list --bisect $good $bad -- $(cat $GIT_DIR/BISECT_NAMES)") || exit + rev=$(eval "git-rev-list --bisect $good $bad -- $(cat "$GIT_DIR/BISECT_NAMES")") || exit if [ -z "$rev" ]; then echo "$bad was both good and bad" exit 1 @@ -152,7 +162,7 @@ bisect_next() { nr=$(eval "git-rev-list $rev $good -- $(cat $GIT_DIR/BISECT_NAMES)" | wc -l) || exit echo "Bisecting: $nr revisions left to test after this" echo "$rev" > "$GIT_DIR/refs/heads/new-bisect" - git checkout new-bisect || exit + git checkout -q new-bisect || exit mv "$GIT_DIR/refs/heads/new-bisect" "$GIT_DIR/refs/heads/bisect" && GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD refs/heads/bisect git-show-branch "$rev" @@ -171,7 +181,7 @@ bisect_reset() { else branch=master fi ;; - 1) test -f "$GIT_DIR/refs/heads/$1" || { + 1) git-show-ref --verify --quiet -- "refs/heads/$1" || { echo >&2 "$1 does not seem to be a valid branch" exit 1 } @@ -179,11 +189,13 @@ bisect_reset() { *) usage ;; esac - git checkout "$branch" && - rm -fr "$GIT_DIR/refs/bisect" - rm -f "$GIT_DIR/refs/heads/bisect" "$GIT_DIR/head-name" - rm -f "$GIT_DIR/BISECT_LOG" - rm -f "$GIT_DIR/BISECT_NAMES" + if git checkout "$branch"; then + rm -fr "$GIT_DIR/refs/bisect" + rm -f "$GIT_DIR/refs/heads/bisect" "$GIT_DIR/head-name" + rm -f "$GIT_DIR/BISECT_LOG" + rm -f "$GIT_DIR/BISECT_NAMES" + rm -f "$GIT_DIR/BISECT_RUN" + fi } bisect_replay () { @@ -218,6 +230,52 @@ bisect_replay () { bisect_auto_next } +bisect_run () { + bisect_next_check fail + + while true + do + echo "running $@" + "$@" + res=$? + + # Check for really bad run error. + if [ $res -lt 0 -o $res -ge 128 ]; then + echo >&2 "bisect run failed:" + echo >&2 "exit code $res from '$@' is < 0 or >= 128" + exit $res + fi + + # Use "bisect_good" or "bisect_bad" + # depending on run success or failure. + if [ $res -gt 0 ]; then + next_bisect='bisect_bad' + else + next_bisect='bisect_good' + fi + + # We have to use a subshell because bisect_good or + # bisect_bad functions can exit. + ( $next_bisect > "$GIT_DIR/BISECT_RUN" ) + res=$? + + cat "$GIT_DIR/BISECT_RUN" + + if [ $res -ne 0 ]; then + echo >&2 "bisect run failed:" + echo >&2 "$next_bisect exited with error code $res" + exit $res + fi + + if grep "is first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null; then + echo "bisect run success" + exit 0; + fi + + done +} + + case "$#" in 0) usage ;; @@ -242,6 +300,8 @@ case "$#" in bisect_replay "$@" ;; log) cat "$GIT_DIR/BISECT_LOG" ;; + run) + bisect_run "$@" ;; *) usage ;; esac