@matheusbsbs / matheus-bagliano / commits / d3e54c8829
Fork 0

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 <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Christian Couder committed Apr 14, 2008 at 05:41 UTC d3e54c88291c2d880ff3a72167c5d3159aed8e97
2 files changed +16 -5
git-bisect.sh
+10 -4
@@ -65,6 +65,7 @@ bisect_start() {
65 head=$(GIT_DIR="$GIT_DIR" git symbolic-ref -q HEAD) ||
66 head=$(GIT_DIR="$GIT_DIR" git rev-parse --verify HEAD) ||
67 die "Bad HEAD - I need a HEAD"
68 + start_head=''
69 case "$head" in
70 refs/heads/bisect)
71 if [ -s "$GIT_DIR/BISECT_START" ]; then
@@ -78,7 +79,7 @@ bisect_start() {
79 # This error message should only be triggered by cogito usage,
80 # and cogito users should understand it relates to cg-seek.
81 [ -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/}"
83 ;;
84 *)
85 die "Bad HEAD - strange symbolic ref"
@@ -99,6 +100,7 @@ bisect_start() {
100 done
101 orig_args=$(sq "$@")
102 bad_seen=0
103 + eval=''
104 while [ $# -gt 0 ]; do
105 arg="$1"
106 case "$arg" in
@@ -116,13 +118,15 @@ bisect_start() {
118 0) state='bad' ; bad_seen=1 ;;
119 *) state='good' ;;
120 esac
119 - bisect_write "$state" "$rev" 'nolog'
121 + eval="$eval bisect_write '$state' '$rev' 'nolog'; "
122 shift
123 ;;
124 esac
125 done
126
127 sq "$@" >"$GIT_DIR/BISECT_NAMES"
128 + test -n "$start_head" && echo "$start_head" >"$GIT_DIR/BISECT_START"
129 + eval "$eval"
130 echo "git-bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG"
131 bisect_auto_next
132 }
@@ -153,12 +157,14 @@ bisect_state() {
157 bisect_write "$state" "$rev" ;;
158 2,bad|*,good|*,skip)
159 shift
160 + eval=''
161 for rev in "$@"
162 do
163 sha=$(git rev-parse --verify "$rev^{commit}") ||
164 die "Bad rev input: $rev"
160 - bisect_write "$state" "$sha"
161 - done ;;
165 + eval="$eval bisect_write '$state' '$sha'; "
166 + done
167 + eval "$eval" ;;
168 *,bad)
169 die "'git bisect bad' can take only one argument." ;;
170 *)
t/t6030-bisect-porcelain.sh
+6 -1
@@ -71,8 +71,12 @@ test_expect_success 'bisect start with one bad and good' '
71 git bisect next
72 '
73
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' '
75 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_* &&
80 git bisect start &&
81 test_must_fail git bisect good foo $HASH1 &&
82 test_must_fail git bisect good $HASH1 bar &&
@@ -80,6 +84,7 @@ test_expect_success 'bisect good and bad fails if not given only revs' '
84 test_must_fail git bisect bad $HASH3 $HASH4 &&
85 test_must_fail git bisect skip bar $HASH3 &&
86 test_must_fail git bisect skip $HASH1 foo &&
87 + test -z "$(git for-each-ref "refs/bisect/*")" &&
88 git bisect good $HASH1 &&
89 git bisect bad $HASH4
90 '