Browse Source

Merge branch 'cc/bisect'

* cc/bisect:
  bisect: use a detached HEAD to bisect
  bisect: trap critical errors in "bisect_start"
  bisect: fix left over "BISECT_START" file when starting with junk rev
  bisect: add test cases to check that "git bisect start" is atomic
maint
Junio C Hamano 17 years ago
parent
commit
325566cc5d
  1. 98
      git-bisect.sh
  2. 79
      t/t6030-bisect-porcelain.sh

98
git-bisect.sh

@ -63,40 +63,40 @@ bisect_autostart() {


bisect_start() { bisect_start() {
# #
# Verify HEAD. If we were bisecting before this, reset to the # Verify HEAD.
# top-of-line master first!
# #
head=$(GIT_DIR="$GIT_DIR" git symbolic-ref -q HEAD) || head=$(GIT_DIR="$GIT_DIR" git symbolic-ref -q HEAD) ||
head=$(GIT_DIR="$GIT_DIR" git rev-parse --verify HEAD) || head=$(GIT_DIR="$GIT_DIR" git rev-parse --verify HEAD) ||
die "Bad HEAD - I need a HEAD" die "Bad HEAD - I need a HEAD"

# #
# Check that we either already have BISECT_START, or that the # Check if we are bisecting.
# branches bisect, new-bisect don't exist, to not override them.
# #
test -s "$GIT_DIR/BISECT_START" ||
if git show-ref --verify -q refs/heads/bisect ||
git show-ref --verify -q refs/heads/new-bisect; then
die 'The branches "bisect" and "new-bisect" must not exist.'
fi
start_head='' start_head=''
case "$head" in if test -s "$GIT_DIR/BISECT_START"
refs/heads/bisect) then
branch=`cat "$GIT_DIR/BISECT_START"` # Reset to the rev from where we started.
git checkout $branch || exit start_head=$(cat "$GIT_DIR/BISECT_START")
;; git checkout "$start_head" || exit
refs/heads/*|$_x40) else
# This error message should only be triggered by cogito usage, # Get rev from where we start.
# and cogito users should understand it relates to cg-seek. case "$head" in
[ -s "$GIT_DIR/head-name" ] && die "won't bisect on seeked tree" refs/heads/*|$_x40)
start_head="${head#refs/heads/}" # This error message should only be triggered by
;; # cogito usage, and cogito users should understand
*) # it relates to cg-seek.
die "Bad HEAD - strange symbolic ref" [ -s "$GIT_DIR/head-name" ] &&
;; die "won't bisect on seeked tree"
esac 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


@ -118,7 +118,7 @@ bisect_start() {
break 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 && test $has_double_dash -eq 1 &&
die "'$arg' does not appear to be a valid revision" die "'$arg' does not appear to be a valid revision"
break break
@ -133,11 +133,29 @@ bisect_start() {
esac esac
done done


sq "$@" >"$GIT_DIR/BISECT_NAMES" #
test -n "$start_head" && echo "$start_head" >"$GIT_DIR/BISECT_START" # Change state.
eval "$eval" # In case of mistaken revs or checkout error, or signals received,
echo "git-bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" # "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.
#
sq "$@" >"$GIT_DIR/BISECT_NAMES" &&
echo "$start_head" >"$GIT_DIR/BISECT_START" &&
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 bisect_auto_next

trap '-' 0
} }


bisect_write() { bisect_write() {
@ -149,9 +167,9 @@ bisect_write() {
good|skip) tag="$state"-"$rev" ;; good|skip) tag="$state"-"$rev" ;;
*) die "Bad bisect_write argument: $state" ;; *) die "Bad bisect_write argument: $state" ;;
esac 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" 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() { bisect_state() {
@ -348,9 +366,7 @@ bisect_next() {
exit_if_skipped_commits "$bisect_rev" exit_if_skipped_commits "$bisect_rev"


echo "Bisecting: $bisect_nr revisions left to test after this" echo "Bisecting: $bisect_nr revisions left to test after this"
git branch -D new-bisect 2> /dev/null git checkout -q "$bisect_rev" || exit
git checkout -q -b new-bisect "$bisect_rev" || exit
git branch -M new-bisect bisect
git show-branch "$bisect_rev" git show-branch "$bisect_rev"
} }


@ -392,24 +408,22 @@ bisect_reset() {
*) *)
usage ;; usage ;;
esac esac
if git checkout "$branch"; then git checkout "$branch" && bisect_clean_state
# 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
} }


bisect_clean_state() { bisect_clean_state() {
# There may be some refs packed during bisection. # 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 while read ref hash
do do
git update-ref -d $ref $hash git update-ref -d $ref $hash
done done
rm -f "$GIT_DIR/BISECT_START"
rm -f "$GIT_DIR/BISECT_LOG" rm -f "$GIT_DIR/BISECT_LOG"
rm -f "$GIT_DIR/BISECT_NAMES" rm -f "$GIT_DIR/BISECT_NAMES"
rm -f "$GIT_DIR/BISECT_RUN" 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"
} }


bisect_replay () { bisect_replay () {

79
t/t6030-bisect-porcelain.sh

@ -126,6 +126,47 @@ test_expect_success 'bisect reset removes packed refs' '
test -z "$(git for-each-ref "refs/heads/bisect")" test -z "$(git for-each-ref "refs/heads/bisect")"
' '


test_expect_success 'bisect start: back in good branch' '
git branch > branch.output &&
grep "* other" branch.output > /dev/null &&
git bisect start $HASH4 $HASH1 -- &&
git bisect good &&
git bisect start $HASH4 $HASH1 -- &&
git bisect bad &&
git bisect reset &&
git branch > branch.output &&
grep "* other" branch.output > /dev/null
'

test_expect_success 'bisect start: no ".git/BISECT_START" if junk rev' '
git bisect start $HASH4 $HASH1 -- &&
git bisect good &&
test_must_fail git bisect start $HASH4 foo -- &&
git branch > branch.output &&
grep "* other" branch.output > /dev/null &&
test_must_fail test -e .git/BISECT_START
'

test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' '
git bisect start $HASH4 $HASH1 -- &&
git bisect good &&
test_must_fail git bisect start $HASH1 $HASH4 -- &&
git branch > branch.output &&
grep "* other" branch.output > /dev/null &&
test_must_fail test -e .git/BISECT_START
'

test_expect_success 'bisect start: no ".git/BISECT_START" if checkout error' '
echo "temp stuff" > hello &&
test_must_fail git bisect start $HASH4 $HASH1 -- &&
git branch &&
git branch > branch.output &&
grep "* other" branch.output > /dev/null &&
test_must_fail test -e .git/BISECT_START &&
test -z "$(git for-each-ref "refs/bisect/*")" &&
git checkout HEAD hello
'

# $HASH1 is good, $HASH4 is bad, we skip $HASH3 # $HASH1 is good, $HASH4 is bad, we skip $HASH3
# but $HASH2 is bad, # but $HASH2 is bad,
# so we should find $HASH2 as the first bad commit # so we should find $HASH2 as the first bad commit
@ -281,25 +322,6 @@ test_expect_success 'bisect starting with a detached HEAD' '
test $HEAD = $(cat .git/BISECT_START) && test $HEAD = $(cat .git/BISECT_START) &&
git bisect reset && git bisect reset &&
test $HEAD = $(git rev-parse --verify HEAD) test $HEAD = $(git rev-parse --verify HEAD)

'

test_expect_success 'bisect refuses to start if branch bisect exists' '
git bisect reset &&
git branch bisect &&
test_must_fail git bisect start &&
git branch -d bisect &&
git checkout -b bisect &&
test_must_fail git bisect start &&
git checkout master &&
git branch -d bisect
'

test_expect_success 'bisect refuses to start if branch new-bisect exists' '
git bisect reset &&
git branch new-bisect &&
test_must_fail git bisect start &&
git branch -d new-bisect
' '


test_expect_success 'bisect errors out if bad and good are mistaken' ' test_expect_success 'bisect errors out if bad and good are mistaken' '
@ -309,6 +331,25 @@ test_expect_success 'bisect errors out if bad and good are mistaken' '
git bisect reset git bisect reset
' '


test_expect_success 'bisect does not create a "bisect" branch' '
git bisect reset &&
git bisect start $HASH7 $HASH1 &&
git branch bisect &&
rev_hash4=$(git rev-parse --verify HEAD) &&
test "$rev_hash4" = "$HASH4" &&
git branch -D bisect &&
git bisect good &&
git branch bisect &&
rev_hash6=$(git rev-parse --verify HEAD) &&
test "$rev_hash6" = "$HASH6" &&
git bisect good > my_bisect_log.txt &&
grep "$HASH7 is first bad commit" my_bisect_log.txt &&
git bisect reset &&
rev_hash6=$(git rev-parse --verify bisect) &&
test "$rev_hash6" = "$HASH6" &&
git branch -D bisect
'

# #
# #
test_done test_done

Loading…
Cancel
Save