Skip to content

Commit d3e54c8

Browse files
chriscoolgitster
authored andcommitted
git-bisect: make "start", "good" and "skip" succeed or fail atomically
Before this patch, when "git bisect start", "git bisect good" or "git bisect skip" were called with many revisions, they could fail after having already marked some revisions as "good", "bad" or "skip". This could be especilally bad for "git bisect start" because as the file ".git/BISECT_NAMES" would not have been written, there would have been no attempt to clear the marked revisions on a "git bisect reset". That's because if there is no ".git/BISECT_NAMES" file, nothing is done to clean things up, as the bisect session is not supposed to have started. While at it, let's also create the ".git/BISECT_START" file, only after ".git/BISECT_NAMES" as been created. Signed-off-by: Christian Couder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2e6e3e8 commit d3e54c8

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

git-bisect.sh

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ bisect_start() {
6565
head=$(GIT_DIR="$GIT_DIR" git symbolic-ref -q HEAD) ||
6666
head=$(GIT_DIR="$GIT_DIR" git rev-parse --verify HEAD) ||
6767
die "Bad HEAD - I need a HEAD"
68+
start_head=''
6869
case "$head" in
6970
refs/heads/bisect)
7071
if [ -s "$GIT_DIR/BISECT_START" ]; then
@@ -78,7 +79,7 @@ bisect_start() {
7879
# This error message should only be triggered by cogito usage,
7980
# and cogito users should understand it relates to cg-seek.
8081
[ -s "$GIT_DIR/head-name" ] && die "won't bisect on seeked tree"
81-
echo "${head#refs/heads/}" >"$GIT_DIR/BISECT_START"
82+
start_head="${head#refs/heads/}"
8283
;;
8384
*)
8485
die "Bad HEAD - strange symbolic ref"
@@ -99,6 +100,7 @@ bisect_start() {
99100
done
100101
orig_args=$(sq "$@")
101102
bad_seen=0
103+
eval=''
102104
while [ $# -gt 0 ]; do
103105
arg="$1"
104106
case "$arg" in
@@ -116,13 +118,15 @@ bisect_start() {
116118
0) state='bad' ; bad_seen=1 ;;
117119
*) state='good' ;;
118120
esac
119-
bisect_write "$state" "$rev" 'nolog'
121+
eval="$eval bisect_write '$state' '$rev' 'nolog'; "
120122
shift
121123
;;
122124
esac
123125
done
124126

125127
sq "$@" >"$GIT_DIR/BISECT_NAMES"
128+
test -n "$start_head" && echo "$start_head" >"$GIT_DIR/BISECT_START"
129+
eval "$eval"
126130
echo "git-bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG"
127131
bisect_auto_next
128132
}
@@ -153,12 +157,14 @@ bisect_state() {
153157
bisect_write "$state" "$rev" ;;
154158
2,bad|*,good|*,skip)
155159
shift
160+
eval=''
156161
for rev in "$@"
157162
do
158163
sha=$(git rev-parse --verify "$rev^{commit}") ||
159164
die "Bad rev input: $rev"
160-
bisect_write "$state" "$sha"
161-
done ;;
165+
eval="$eval bisect_write '$state' '$sha'; "
166+
done
167+
eval "$eval" ;;
162168
*,bad)
163169
die "'git bisect bad' can take only one argument." ;;
164170
*)

t/t6030-bisect-porcelain.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,20 @@ test_expect_success 'bisect start with one bad and good' '
7171
git bisect next
7272
'
7373

74-
test_expect_success 'bisect good and bad fails if not given only revs' '
74+
test_expect_success 'bisect fails if given any junk instead of revs' '
7575
git bisect reset &&
76+
test_must_fail git bisect start foo $HASH1 -- &&
77+
test_must_fail git bisect start $HASH4 $HASH1 bar -- &&
78+
test -z "$(git for-each-ref "refs/bisect/*")" &&
79+
test_must_fail ls .git/BISECT_* &&
7680
git bisect start &&
7781
test_must_fail git bisect good foo $HASH1 &&
7882
test_must_fail git bisect good $HASH1 bar &&
7983
test_must_fail git bisect bad frotz &&
8084
test_must_fail git bisect bad $HASH3 $HASH4 &&
8185
test_must_fail git bisect skip bar $HASH3 &&
8286
test_must_fail git bisect skip $HASH1 foo &&
87+
test -z "$(git for-each-ref "refs/bisect/*")" &&
8388
git bisect good $HASH1 &&
8489
git bisect bad $HASH4
8590
'

0 commit comments

Comments
 (0)