##// END OF EJS Templates
errors: raise StateError in `hg bisect`...
Martin von Zweigbergk -
r46487:e641bb2a default
parent child Browse files
Show More
@@ -1,329 +1,329
1 1 # changelog bisection for mercurial
2 2 #
3 3 # Copyright 2007 Matt Mackall
4 4 # Copyright 2005, 2006 Benoit Boissinot <benoit.boissinot@ens-lyon.org>
5 5 #
6 6 # Inspired by git bisect, extension skeleton taken from mq.py.
7 7 #
8 8 # This software may be used and distributed according to the terms of the
9 9 # GNU General Public License version 2 or any later version.
10 10
11 11 from __future__ import absolute_import
12 12
13 13 import collections
14 14 import contextlib
15 15
16 16 from .i18n import _
17 17 from .node import (
18 18 hex,
19 19 short,
20 20 )
21 21 from . import error
22 22
23 23
24 24 def bisect(repo, state):
25 25 """find the next node (if any) for testing during a bisect search.
26 26 returns a (nodes, number, good) tuple.
27 27
28 28 'nodes' is the final result of the bisect if 'number' is 0.
29 29 Otherwise 'number' indicates the remaining possible candidates for
30 30 the search and 'nodes' contains the next bisect target.
31 31 'good' is True if bisect is searching for a first good changeset, False
32 32 if searching for a first bad one.
33 33 """
34 34
35 35 repo = repo.unfiltered()
36 36 changelog = repo.changelog
37 37 clparents = changelog.parentrevs
38 38 skip = {changelog.rev(n) for n in state[b'skip']}
39 39
40 40 def buildancestors(bad, good):
41 41 badrev = min([changelog.rev(n) for n in bad])
42 42 ancestors = collections.defaultdict(lambda: None)
43 43 for rev in repo.revs(b"descendants(%ln) - ancestors(%ln)", good, good):
44 44 ancestors[rev] = []
45 45 if ancestors[badrev] is None:
46 46 return badrev, None
47 47 return badrev, ancestors
48 48
49 49 good = False
50 50 badrev, ancestors = buildancestors(state[b'bad'], state[b'good'])
51 51 if not ancestors: # looking for bad to good transition?
52 52 good = True
53 53 badrev, ancestors = buildancestors(state[b'good'], state[b'bad'])
54 54 bad = changelog.node(badrev)
55 55 if not ancestors: # now we're confused
56 56 if (
57 57 len(state[b'bad']) == 1
58 58 and len(state[b'good']) == 1
59 59 and state[b'bad'] != state[b'good']
60 60 ):
61 61 raise error.Abort(_(b"starting revisions are not directly related"))
62 62 raise error.Abort(
63 63 _(b"inconsistent state, %d:%s is good and bad")
64 64 % (badrev, short(bad))
65 65 )
66 66
67 67 # build children dict
68 68 children = {}
69 69 visit = collections.deque([badrev])
70 70 candidates = []
71 71 while visit:
72 72 rev = visit.popleft()
73 73 if ancestors[rev] == []:
74 74 candidates.append(rev)
75 75 for prev in clparents(rev):
76 76 if prev != -1:
77 77 if prev in children:
78 78 children[prev].append(rev)
79 79 else:
80 80 children[prev] = [rev]
81 81 visit.append(prev)
82 82
83 83 candidates.sort()
84 84 # have we narrowed it down to one entry?
85 85 # or have all other possible candidates besides 'bad' have been skipped?
86 86 tot = len(candidates)
87 87 unskipped = [c for c in candidates if (c not in skip) and (c != badrev)]
88 88 if tot == 1 or not unskipped:
89 89 return ([changelog.node(c) for c in candidates], 0, good)
90 90 perfect = tot // 2
91 91
92 92 # find the best node to test
93 93 best_rev = None
94 94 best_len = -1
95 95 poison = set()
96 96 for rev in candidates:
97 97 if rev in poison:
98 98 # poison children
99 99 poison.update(children.get(rev, []))
100 100 continue
101 101
102 102 a = ancestors[rev] or [rev]
103 103 ancestors[rev] = None
104 104
105 105 x = len(a) # number of ancestors
106 106 y = tot - x # number of non-ancestors
107 107 value = min(x, y) # how good is this test?
108 108 if value > best_len and rev not in skip:
109 109 best_len = value
110 110 best_rev = rev
111 111 if value == perfect: # found a perfect candidate? quit early
112 112 break
113 113
114 114 if y < perfect and rev not in skip: # all downhill from here?
115 115 # poison children
116 116 poison.update(children.get(rev, []))
117 117 continue
118 118
119 119 for c in children.get(rev, []):
120 120 if ancestors[c]:
121 121 ancestors[c] = list(set(ancestors[c] + a))
122 122 else:
123 123 ancestors[c] = a + [c]
124 124
125 125 assert best_rev is not None
126 126 best_node = changelog.node(best_rev)
127 127
128 128 return ([best_node], tot, good)
129 129
130 130
131 131 def extendrange(repo, state, nodes, good):
132 132 # bisect is incomplete when it ends on a merge node and
133 133 # one of the parent was not checked.
134 134 parents = repo[nodes[0]].parents()
135 135 if len(parents) > 1:
136 136 if good:
137 137 side = state[b'bad']
138 138 else:
139 139 side = state[b'good']
140 140 num = len({i.node() for i in parents} & set(side))
141 141 if num == 1:
142 142 return parents[0].ancestor(parents[1])
143 143 return None
144 144
145 145
146 146 def load_state(repo):
147 147 state = {b'current': [], b'good': [], b'bad': [], b'skip': []}
148 148 for l in repo.vfs.tryreadlines(b"bisect.state"):
149 149 kind, node = l[:-1].split()
150 150 node = repo.unfiltered().lookup(node)
151 151 if kind not in state:
152 152 raise error.Abort(_(b"unknown bisect kind %s") % kind)
153 153 state[kind].append(node)
154 154 return state
155 155
156 156
157 157 def save_state(repo, state):
158 158 f = repo.vfs(b"bisect.state", b"w", atomictemp=True)
159 159 with repo.wlock():
160 160 for kind in sorted(state):
161 161 for node in state[kind]:
162 162 f.write(b"%s %s\n" % (kind, hex(node)))
163 163 f.close()
164 164
165 165
166 166 def resetstate(repo):
167 167 """remove any bisect state from the repository"""
168 168 if repo.vfs.exists(b"bisect.state"):
169 169 repo.vfs.unlink(b"bisect.state")
170 170
171 171
172 172 def checkstate(state):
173 173 """check we have both 'good' and 'bad' to define a range
174 174
175 Raise Abort exception otherwise."""
175 Raise StateError exception otherwise."""
176 176 if state[b'good'] and state[b'bad']:
177 177 return True
178 178 if not state[b'good']:
179 raise error.Abort(_(b'cannot bisect (no known good revisions)'))
179 raise error.StateError(_(b'cannot bisect (no known good revisions)'))
180 180 else:
181 raise error.Abort(_(b'cannot bisect (no known bad revisions)'))
181 raise error.StateError(_(b'cannot bisect (no known bad revisions)'))
182 182
183 183
184 184 @contextlib.contextmanager
185 185 def restore_state(repo, state, node):
186 186 try:
187 187 yield
188 188 finally:
189 189 state[b'current'] = [node]
190 190 save_state(repo, state)
191 191
192 192
193 193 def get(repo, status):
194 194 """
195 195 Return a list of revision(s) that match the given status:
196 196
197 197 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
198 198 - ``goods``, ``bads`` : csets topologically good/bad
199 199 - ``range`` : csets taking part in the bisection
200 200 - ``pruned`` : csets that are goods, bads or skipped
201 201 - ``untested`` : csets whose fate is yet unknown
202 202 - ``ignored`` : csets ignored due to DAG topology
203 203 - ``current`` : the cset currently being bisected
204 204 """
205 205 state = load_state(repo)
206 206 if status in (b'good', b'bad', b'skip', b'current'):
207 207 return map(repo.unfiltered().changelog.rev, state[status])
208 208 else:
209 209 # In the following sets, we do *not* call 'bisect()' with more
210 210 # than one level of recursion, because that can be very, very
211 211 # time consuming. Instead, we always develop the expression as
212 212 # much as possible.
213 213
214 214 # 'range' is all csets that make the bisection:
215 215 # - have a good ancestor and a bad descendant, or conversely
216 216 # that's because the bisection can go either way
217 217 range = b'( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )'
218 218
219 219 _t = repo.revs(b'bisect(good)::bisect(bad)')
220 220 # The sets of topologically good or bad csets
221 221 if len(_t) == 0:
222 222 # Goods are topologically after bads
223 223 goods = b'bisect(good)::' # Pruned good csets
224 224 bads = b'::bisect(bad)' # Pruned bad csets
225 225 else:
226 226 # Goods are topologically before bads
227 227 goods = b'::bisect(good)' # Pruned good csets
228 228 bads = b'bisect(bad)::' # Pruned bad csets
229 229
230 230 # 'pruned' is all csets whose fate is already known: good, bad, skip
231 231 skips = b'bisect(skip)' # Pruned skipped csets
232 232 pruned = b'( (%s) | (%s) | (%s) )' % (goods, bads, skips)
233 233
234 234 # 'untested' is all cset that are- in 'range', but not in 'pruned'
235 235 untested = b'( (%s) - (%s) )' % (range, pruned)
236 236
237 237 # 'ignored' is all csets that were not used during the bisection
238 238 # due to DAG topology, but may however have had an impact.
239 239 # E.g., a branch merged between bads and goods, but whose branch-
240 240 # point is out-side of the range.
241 241 iba = b'::bisect(bad) - ::bisect(good)' # Ignored bads' ancestors
242 242 iga = b'::bisect(good) - ::bisect(bad)' # Ignored goods' ancestors
243 243 ignored = b'( ( (%s) | (%s) ) - (%s) )' % (iba, iga, range)
244 244
245 245 if status == b'range':
246 246 return repo.revs(range)
247 247 elif status == b'pruned':
248 248 return repo.revs(pruned)
249 249 elif status == b'untested':
250 250 return repo.revs(untested)
251 251 elif status == b'ignored':
252 252 return repo.revs(ignored)
253 253 elif status == b"goods":
254 254 return repo.revs(goods)
255 255 elif status == b"bads":
256 256 return repo.revs(bads)
257 257 else:
258 258 raise error.ParseError(_(b'invalid bisect state'))
259 259
260 260
261 261 def label(repo, node):
262 262 rev = repo.changelog.rev(node)
263 263
264 264 # Try explicit sets
265 265 if rev in get(repo, b'good'):
266 266 # i18n: bisect changeset status
267 267 return _(b'good')
268 268 if rev in get(repo, b'bad'):
269 269 # i18n: bisect changeset status
270 270 return _(b'bad')
271 271 if rev in get(repo, b'skip'):
272 272 # i18n: bisect changeset status
273 273 return _(b'skipped')
274 274 if rev in get(repo, b'untested') or rev in get(repo, b'current'):
275 275 # i18n: bisect changeset status
276 276 return _(b'untested')
277 277 if rev in get(repo, b'ignored'):
278 278 # i18n: bisect changeset status
279 279 return _(b'ignored')
280 280
281 281 # Try implicit sets
282 282 if rev in get(repo, b'goods'):
283 283 # i18n: bisect changeset status
284 284 return _(b'good (implicit)')
285 285 if rev in get(repo, b'bads'):
286 286 # i18n: bisect changeset status
287 287 return _(b'bad (implicit)')
288 288
289 289 return None
290 290
291 291
292 292 def printresult(ui, repo, state, displayer, nodes, good):
293 293 repo = repo.unfiltered()
294 294 if len(nodes) == 1:
295 295 # narrowed it down to a single revision
296 296 if good:
297 297 ui.write(_(b"The first good revision is:\n"))
298 298 else:
299 299 ui.write(_(b"The first bad revision is:\n"))
300 300 displayer.show(repo[nodes[0]])
301 301 extendnode = extendrange(repo, state, nodes, good)
302 302 if extendnode is not None:
303 303 ui.write(
304 304 _(
305 305 b'Not all ancestors of this changeset have been'
306 306 b' checked.\nUse bisect --extend to continue the '
307 307 b'bisection from\nthe common ancestor, %s.\n'
308 308 )
309 309 % extendnode
310 310 )
311 311 else:
312 312 # multiple possible revisions
313 313 if good:
314 314 ui.write(
315 315 _(
316 316 b"Due to skipped revisions, the first "
317 317 b"good revision could be any of:\n"
318 318 )
319 319 )
320 320 else:
321 321 ui.write(
322 322 _(
323 323 b"Due to skipped revisions, the first "
324 324 b"bad revision could be any of:\n"
325 325 )
326 326 )
327 327 for n in nodes:
328 328 displayer.show(repo[n])
329 329 displayer.close()
@@ -1,796 +1,796
1 1 $ hg init
2 2
3 3
4 4 committing changes
5 5
6 6 $ count=0
7 7 $ echo > a
8 8 $ while test $count -lt 32 ; do
9 9 > echo 'a' >> a
10 10 > test $count -eq 0 && hg add
11 11 > hg ci -m "msg $count" -d "$count 0"
12 12 > count=`expr $count + 1`
13 13 > done
14 14 adding a
15 15
16 16
17 17 $ hg log
18 18 changeset: 31:58c80a7c8a40
19 19 tag: tip
20 20 user: test
21 21 date: Thu Jan 01 00:00:31 1970 +0000
22 22 summary: msg 31
23 23
24 24 changeset: 30:ed2d2f24b11c
25 25 user: test
26 26 date: Thu Jan 01 00:00:30 1970 +0000
27 27 summary: msg 30
28 28
29 29 changeset: 29:b5bd63375ab9
30 30 user: test
31 31 date: Thu Jan 01 00:00:29 1970 +0000
32 32 summary: msg 29
33 33
34 34 changeset: 28:8e0c2264c8af
35 35 user: test
36 36 date: Thu Jan 01 00:00:28 1970 +0000
37 37 summary: msg 28
38 38
39 39 changeset: 27:288867a866e9
40 40 user: test
41 41 date: Thu Jan 01 00:00:27 1970 +0000
42 42 summary: msg 27
43 43
44 44 changeset: 26:3efc6fd51aeb
45 45 user: test
46 46 date: Thu Jan 01 00:00:26 1970 +0000
47 47 summary: msg 26
48 48
49 49 changeset: 25:02a84173a97a
50 50 user: test
51 51 date: Thu Jan 01 00:00:25 1970 +0000
52 52 summary: msg 25
53 53
54 54 changeset: 24:10e0acd3809e
55 55 user: test
56 56 date: Thu Jan 01 00:00:24 1970 +0000
57 57 summary: msg 24
58 58
59 59 changeset: 23:5ec79163bff4
60 60 user: test
61 61 date: Thu Jan 01 00:00:23 1970 +0000
62 62 summary: msg 23
63 63
64 64 changeset: 22:06c7993750ce
65 65 user: test
66 66 date: Thu Jan 01 00:00:22 1970 +0000
67 67 summary: msg 22
68 68
69 69 changeset: 21:e5db6aa3fe2a
70 70 user: test
71 71 date: Thu Jan 01 00:00:21 1970 +0000
72 72 summary: msg 21
73 73
74 74 changeset: 20:7128fb4fdbc9
75 75 user: test
76 76 date: Thu Jan 01 00:00:20 1970 +0000
77 77 summary: msg 20
78 78
79 79 changeset: 19:52798545b482
80 80 user: test
81 81 date: Thu Jan 01 00:00:19 1970 +0000
82 82 summary: msg 19
83 83
84 84 changeset: 18:86977a90077e
85 85 user: test
86 86 date: Thu Jan 01 00:00:18 1970 +0000
87 87 summary: msg 18
88 88
89 89 changeset: 17:03515f4a9080
90 90 user: test
91 91 date: Thu Jan 01 00:00:17 1970 +0000
92 92 summary: msg 17
93 93
94 94 changeset: 16:a2e6ea4973e9
95 95 user: test
96 96 date: Thu Jan 01 00:00:16 1970 +0000
97 97 summary: msg 16
98 98
99 99 changeset: 15:e7fa0811edb0
100 100 user: test
101 101 date: Thu Jan 01 00:00:15 1970 +0000
102 102 summary: msg 15
103 103
104 104 changeset: 14:ce8f0998e922
105 105 user: test
106 106 date: Thu Jan 01 00:00:14 1970 +0000
107 107 summary: msg 14
108 108
109 109 changeset: 13:9d7d07bc967c
110 110 user: test
111 111 date: Thu Jan 01 00:00:13 1970 +0000
112 112 summary: msg 13
113 113
114 114 changeset: 12:1941b52820a5
115 115 user: test
116 116 date: Thu Jan 01 00:00:12 1970 +0000
117 117 summary: msg 12
118 118
119 119 changeset: 11:7b4cd9578619
120 120 user: test
121 121 date: Thu Jan 01 00:00:11 1970 +0000
122 122 summary: msg 11
123 123
124 124 changeset: 10:7c5eff49a6b6
125 125 user: test
126 126 date: Thu Jan 01 00:00:10 1970 +0000
127 127 summary: msg 10
128 128
129 129 changeset: 9:eb44510ef29a
130 130 user: test
131 131 date: Thu Jan 01 00:00:09 1970 +0000
132 132 summary: msg 9
133 133
134 134 changeset: 8:453eb4dba229
135 135 user: test
136 136 date: Thu Jan 01 00:00:08 1970 +0000
137 137 summary: msg 8
138 138
139 139 changeset: 7:03750880c6b5
140 140 user: test
141 141 date: Thu Jan 01 00:00:07 1970 +0000
142 142 summary: msg 7
143 143
144 144 changeset: 6:a3d5c6fdf0d3
145 145 user: test
146 146 date: Thu Jan 01 00:00:06 1970 +0000
147 147 summary: msg 6
148 148
149 149 changeset: 5:7874a09ea728
150 150 user: test
151 151 date: Thu Jan 01 00:00:05 1970 +0000
152 152 summary: msg 5
153 153
154 154 changeset: 4:9b2ba8336a65
155 155 user: test
156 156 date: Thu Jan 01 00:00:04 1970 +0000
157 157 summary: msg 4
158 158
159 159 changeset: 3:b53bea5e2fcb
160 160 user: test
161 161 date: Thu Jan 01 00:00:03 1970 +0000
162 162 summary: msg 3
163 163
164 164 changeset: 2:db07c04beaca
165 165 user: test
166 166 date: Thu Jan 01 00:00:02 1970 +0000
167 167 summary: msg 2
168 168
169 169 changeset: 1:5cd978ea5149
170 170 user: test
171 171 date: Thu Jan 01 00:00:01 1970 +0000
172 172 summary: msg 1
173 173
174 174 changeset: 0:b99c7b9c8e11
175 175 user: test
176 176 date: Thu Jan 01 00:00:00 1970 +0000
177 177 summary: msg 0
178 178
179 179
180 180 $ hg up -C
181 181 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
182 182
183 183 bisect test
184 184
185 185 $ hg bisect -r
186 186 $ hg bisect -b
187 187 $ hg status -v
188 188 # The repository is in an unfinished *bisect* state.
189 189
190 190 # To mark the changeset good: hg bisect --good
191 191 # To mark the changeset bad: hg bisect --bad
192 192 # To abort: hg bisect --reset
193 193
194 194 $ hg status -v --config commands.status.skipstates=bisect
195 195 $ hg summary
196 196 parent: 31:58c80a7c8a40 tip
197 197 msg 31
198 198 branch: default
199 199 commit: (clean)
200 200 update: (current)
201 201 phases: 32 draft
202 202 $ hg bisect -g 1
203 203 Testing changeset 16:a2e6ea4973e9 (30 changesets remaining, ~4 tests)
204 204 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
205 205 $ hg bisect -g
206 206 Testing changeset 23:5ec79163bff4 (15 changesets remaining, ~3 tests)
207 207 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
208 208
209 209 skip
210 210
211 211 $ hg bisect -s
212 212 Testing changeset 24:10e0acd3809e (15 changesets remaining, ~3 tests)
213 213 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
214 214 $ hg bisect -g
215 215 Testing changeset 27:288867a866e9 (7 changesets remaining, ~2 tests)
216 216 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
217 217 $ hg bisect -g
218 218 Testing changeset 29:b5bd63375ab9 (4 changesets remaining, ~2 tests)
219 219 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 220 $ hg bisect -b
221 221 Testing changeset 28:8e0c2264c8af (2 changesets remaining, ~1 tests)
222 222 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
223 223 $ hg bisect -g
224 224 The first bad revision is:
225 225 changeset: 29:b5bd63375ab9
226 226 user: test
227 227 date: Thu Jan 01 00:00:29 1970 +0000
228 228 summary: msg 29
229 229
230 230
231 231 mark revsets instead of single revs
232 232
233 233 $ hg bisect -r
234 234 $ hg bisect -b "0::3"
235 235 $ hg bisect -s "13::16"
236 236 $ hg bisect -g "26::tip"
237 237 Testing changeset 12:1941b52820a5 (23 changesets remaining, ~4 tests)
238 238 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
239 239 $ cat .hg/bisect.state
240 240 bad b99c7b9c8e11558adef3fad9af211c58d46f325b
241 241 bad 5cd978ea51499179507ee7b6f340d2dbaa401185
242 242 bad db07c04beaca44cf24832541e7f4a2346a95275b
243 243 bad b53bea5e2fcb30d3e00bd3409507a5659ce0fd8b
244 244 current 1941b52820a544549596820a8ae006842b0e2c64
245 245 good 3efc6fd51aeb8594398044c6c846ca59ae021203
246 246 good 288867a866e9adb7a29880b66936c874b80f4651
247 247 good 8e0c2264c8af790daf3585ada0669d93dee09c83
248 248 good b5bd63375ab9a290419f2024b7f4ee9ea7ce90a8
249 249 good ed2d2f24b11c368fa8aa0da9f4e1db580abade59
250 250 good 58c80a7c8a4025a94cedaf7b4a4e3124e8909a96
251 251 skip 9d7d07bc967ca98ad0600c24953fd289ad5fa991
252 252 skip ce8f0998e922c179e80819d5066fbe46e2998784
253 253 skip e7fa0811edb063f6319531f0d0a865882138e180
254 254 skip a2e6ea4973e9196ddd3386493b0c214b41fd97d3
255 255
256 256 bisect reverse test
257 257
258 258 $ hg bisect -r
259 259 $ hg bisect -b null
260 260 $ hg bisect -g tip
261 261 Testing changeset 15:e7fa0811edb0 (32 changesets remaining, ~5 tests)
262 262 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
263 263 $ hg bisect -g
264 264 Testing changeset 7:03750880c6b5 (16 changesets remaining, ~4 tests)
265 265 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
266 266
267 267 skip
268 268
269 269 $ hg bisect -s
270 270 Testing changeset 6:a3d5c6fdf0d3 (16 changesets remaining, ~4 tests)
271 271 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
272 272 $ hg bisect -g
273 273 Testing changeset 2:db07c04beaca (7 changesets remaining, ~2 tests)
274 274 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
275 275 $ hg bisect -g
276 276 Testing changeset 0:b99c7b9c8e11 (3 changesets remaining, ~1 tests)
277 277 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
278 278 $ hg bisect -b
279 279 Testing changeset 1:5cd978ea5149 (2 changesets remaining, ~1 tests)
280 280 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
281 281 $ hg bisect -g
282 282 The first good revision is:
283 283 changeset: 1:5cd978ea5149
284 284 user: test
285 285 date: Thu Jan 01 00:00:01 1970 +0000
286 286 summary: msg 1
287 287
288 288
289 289 $ hg bisect -r
290 290 $ hg bisect -g tip
291 291 $ hg bisect -b tip
292 292 abort: inconsistent state, 31:58c80a7c8a40 is good and bad
293 293 [255]
294 294
295 295 $ hg bisect -r
296 296 $ hg bisect -g null
297 297 $ hg bisect -bU tip
298 298 Testing changeset 15:e7fa0811edb0 (32 changesets remaining, ~5 tests)
299 299 $ hg id
300 300 5cd978ea5149
301 301
302 302
303 303 Issue1228: hg bisect crashes when you skip the last rev in bisection
304 304 Issue1182: hg bisect exception
305 305
306 306 $ hg bisect -r
307 307 $ hg bisect -b 4
308 308 $ hg bisect -g 0
309 309 Testing changeset 2:db07c04beaca (4 changesets remaining, ~2 tests)
310 310 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
311 311 $ hg bisect -s
312 312 Testing changeset 1:5cd978ea5149 (4 changesets remaining, ~2 tests)
313 313 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
314 314 $ hg bisect -s
315 315 Testing changeset 3:b53bea5e2fcb (4 changesets remaining, ~2 tests)
316 316 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
317 317 $ hg bisect -s
318 318 Due to skipped revisions, the first bad revision could be any of:
319 319 changeset: 1:5cd978ea5149
320 320 user: test
321 321 date: Thu Jan 01 00:00:01 1970 +0000
322 322 summary: msg 1
323 323
324 324 changeset: 2:db07c04beaca
325 325 user: test
326 326 date: Thu Jan 01 00:00:02 1970 +0000
327 327 summary: msg 2
328 328
329 329 changeset: 3:b53bea5e2fcb
330 330 user: test
331 331 date: Thu Jan 01 00:00:03 1970 +0000
332 332 summary: msg 3
333 333
334 334 changeset: 4:9b2ba8336a65
335 335 user: test
336 336 date: Thu Jan 01 00:00:04 1970 +0000
337 337 summary: msg 4
338 338
339 339
340 340
341 341 reproduce non converging bisect, issue1182
342 342
343 343 $ hg bisect -r
344 344 $ hg bisect -g 0
345 345 $ hg bisect -b 2
346 346 Testing changeset 1:5cd978ea5149 (2 changesets remaining, ~1 tests)
347 347 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
348 348 $ hg bisect -s
349 349 Due to skipped revisions, the first bad revision could be any of:
350 350 changeset: 1:5cd978ea5149
351 351 user: test
352 352 date: Thu Jan 01 00:00:01 1970 +0000
353 353 summary: msg 1
354 354
355 355 changeset: 2:db07c04beaca
356 356 user: test
357 357 date: Thu Jan 01 00:00:02 1970 +0000
358 358 summary: msg 2
359 359
360 360
361 361
362 362 test no action
363 363
364 364 $ hg bisect -r
365 365 $ hg bisect
366 366 abort: cannot bisect (no known good revisions)
367 [255]
367 [20]
368 368
369 369
370 370 reproduce AssertionError, issue1445
371 371
372 372 $ hg bisect -r
373 373 $ hg bisect -b 6
374 374 $ hg bisect -g 0
375 375 Testing changeset 3:b53bea5e2fcb (6 changesets remaining, ~2 tests)
376 376 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 377 $ hg bisect -s
378 378 Testing changeset 2:db07c04beaca (6 changesets remaining, ~2 tests)
379 379 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
380 380 $ hg bisect -s
381 381 Testing changeset 4:9b2ba8336a65 (6 changesets remaining, ~2 tests)
382 382 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
383 383 $ hg bisect -s
384 384 Testing changeset 1:5cd978ea5149 (6 changesets remaining, ~2 tests)
385 385 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
386 386 $ hg bisect -s
387 387 Testing changeset 5:7874a09ea728 (6 changesets remaining, ~2 tests)
388 388 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
389 389 $ hg bisect -g
390 390 The first bad revision is:
391 391 changeset: 6:a3d5c6fdf0d3
392 392 user: test
393 393 date: Thu Jan 01 00:00:06 1970 +0000
394 394 summary: msg 6
395 395
396 396 $ hg log -r "bisect(good)"
397 397 changeset: 0:b99c7b9c8e11
398 398 user: test
399 399 date: Thu Jan 01 00:00:00 1970 +0000
400 400 summary: msg 0
401 401
402 402 changeset: 5:7874a09ea728
403 403 user: test
404 404 date: Thu Jan 01 00:00:05 1970 +0000
405 405 summary: msg 5
406 406
407 407 $ hg log -r "bisect(bad)"
408 408 changeset: 6:a3d5c6fdf0d3
409 409 user: test
410 410 date: Thu Jan 01 00:00:06 1970 +0000
411 411 summary: msg 6
412 412
413 413 $ hg log -r "bisect(current)"
414 414 changeset: 5:7874a09ea728
415 415 user: test
416 416 date: Thu Jan 01 00:00:05 1970 +0000
417 417 summary: msg 5
418 418
419 419 $ hg log -r "bisect(skip)"
420 420 changeset: 1:5cd978ea5149
421 421 user: test
422 422 date: Thu Jan 01 00:00:01 1970 +0000
423 423 summary: msg 1
424 424
425 425 changeset: 2:db07c04beaca
426 426 user: test
427 427 date: Thu Jan 01 00:00:02 1970 +0000
428 428 summary: msg 2
429 429
430 430 changeset: 3:b53bea5e2fcb
431 431 user: test
432 432 date: Thu Jan 01 00:00:03 1970 +0000
433 433 summary: msg 3
434 434
435 435 changeset: 4:9b2ba8336a65
436 436 user: test
437 437 date: Thu Jan 01 00:00:04 1970 +0000
438 438 summary: msg 4
439 439
440 440
441 441 test legacy bisected() keyword
442 442
443 443 $ hg log -r "bisected(bad)"
444 444 changeset: 6:a3d5c6fdf0d3
445 445 user: test
446 446 date: Thu Jan 01 00:00:06 1970 +0000
447 447 summary: msg 6
448 448
449 449
450 450 $ set +e
451 451
452 452 test invalid command
453 453 assuming that the shell returns 127 if command not found ...
454 454
455 455 $ hg bisect -r
456 456 $ hg bisect --command 'exit 127'
457 457 abort: failed to execute exit 127
458 458 [255]
459 459
460 460
461 461 test bisecting command
462 462
463 463 $ cat > script.py <<EOF
464 464 > #!$PYTHON
465 465 > from __future__ import absolute_import
466 466 > import sys
467 467 > from mercurial import hg, ui as uimod
468 468 > repo = hg.repository(uimod.ui.load(), b'.')
469 469 > if repo[b'.'].rev() < 6:
470 470 > sys.exit(1)
471 471 > EOF
472 472 $ chmod +x script.py
473 473 $ hg bisect -r
474 474 $ hg up -qr tip
475 475 $ hg bisect --command "\"$PYTHON\" \"$TESTTMP/script.py\" and some parameters"
476 476 changeset 31:58c80a7c8a40: good
477 477 abort: cannot bisect (no known bad revisions)
478 [255]
478 [20]
479 479 $ hg up -qr 0
480 480 $ hg bisect --command "\"$PYTHON\" \"$TESTTMP/script.py\" and some parameters"
481 481 changeset 0:b99c7b9c8e11: bad
482 482 changeset 15:e7fa0811edb0: good
483 483 changeset 7:03750880c6b5: good
484 484 changeset 3:b53bea5e2fcb: bad
485 485 changeset 5:7874a09ea728: bad
486 486 changeset 6:a3d5c6fdf0d3: good
487 487 The first good revision is:
488 488 changeset: 6:a3d5c6fdf0d3
489 489 user: test
490 490 date: Thu Jan 01 00:00:06 1970 +0000
491 491 summary: msg 6
492 492
493 493
494 494
495 495 test bisecting via a command without updating the working dir, and
496 496 ensure that the bisect state file is updated before running a test
497 497 command
498 498
499 499 $ hg update null
500 500 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
501 501 $ cat > script.sh <<'EOF'
502 502 > #!/bin/sh
503 503 > test -n "$HG_NODE" || (echo HG_NODE missing; exit 127)
504 504 > current="`hg log -r \"bisect(current)\" --template {node}`"
505 505 > test "$current" = "$HG_NODE" || (echo current is bad: $current; exit 127)
506 506 > rev="`hg log -r $HG_NODE --template {rev}`"
507 507 > test "$rev" -ge 6
508 508 > EOF
509 509 $ chmod +x script.sh
510 510 $ hg bisect -r
511 511 $ hg bisect --good tip --noupdate
512 512 $ hg bisect --bad 0 --noupdate
513 513 Testing changeset 15:e7fa0811edb0 (31 changesets remaining, ~4 tests)
514 514 $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params" --noupdate
515 515 changeset 15:e7fa0811edb0: good
516 516 changeset 7:03750880c6b5: good
517 517 changeset 3:b53bea5e2fcb: bad
518 518 changeset 5:7874a09ea728: bad
519 519 changeset 6:a3d5c6fdf0d3: good
520 520 The first good revision is:
521 521 changeset: 6:a3d5c6fdf0d3
522 522 user: test
523 523 date: Thu Jan 01 00:00:06 1970 +0000
524 524 summary: msg 6
525 525
526 526
527 527 ensure that we still don't have a working dir
528 528
529 529 $ hg parents
530 530
531 531
532 532 test the same case, this time with updating
533 533
534 534 $ cat > script.sh <<'EOF'
535 535 > #!/bin/sh
536 536 > test -n "$HG_NODE" || (echo HG_NODE missing; exit 127)
537 537 > current="`hg log -r \"bisect(current)\" --template {node}`"
538 538 > test "$current" = "$HG_NODE" || (echo current is bad: $current; exit 127)
539 539 > rev="`hg log -r . --template {rev}`"
540 540 > test "$rev" -ge 6
541 541 > EOF
542 542 $ chmod +x script.sh
543 543 $ hg bisect -r
544 544 $ hg up -qr tip
545 545 $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params"
546 546 changeset 31:58c80a7c8a40: good
547 547 abort: cannot bisect (no known bad revisions)
548 [255]
548 [20]
549 549 $ hg up -qr 0
550 550 $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params"
551 551 changeset 0:b99c7b9c8e11: bad
552 552 changeset 15:e7fa0811edb0: good
553 553 changeset 7:03750880c6b5: good
554 554 changeset 3:b53bea5e2fcb: bad
555 555 changeset 5:7874a09ea728: bad
556 556 changeset 6:a3d5c6fdf0d3: good
557 557 The first good revision is:
558 558 changeset: 6:a3d5c6fdf0d3
559 559 user: test
560 560 date: Thu Jan 01 00:00:06 1970 +0000
561 561 summary: msg 6
562 562
563 563 $ hg graft -q 15
564 564 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
565 565 abort: unresolved conflicts, can't continue
566 566 (use 'hg resolve' and 'hg graft --continue')
567 567 [1]
568 568 $ hg bisect --reset
569 569 $ hg up -C .
570 570 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
571 571
572 572 Check that bisect does not break on obsolete changesets
573 573 =========================================================
574 574
575 575 $ cat >> $HGRCPATH << EOF
576 576 > [experimental]
577 577 > evolution.createmarkers=True
578 578 > EOF
579 579
580 580 tip is obsolete
581 581 ---------------------
582 582
583 583 $ hg debugobsolete `hg id --debug -i -r tip`
584 584 1 new obsolescence markers
585 585 obsoleted 1 changesets
586 586 $ hg bisect --reset
587 587 $ hg bisect --good 15
588 588 $ hg bisect --bad 30
589 589 Testing changeset 22:06c7993750ce (15 changesets remaining, ~3 tests)
590 590 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
591 591 $ hg bisect --command true
592 592 changeset 22:06c7993750ce: good
593 593 changeset 26:3efc6fd51aeb: good
594 594 changeset 28:8e0c2264c8af: good
595 595 changeset 29:b5bd63375ab9: good
596 596 The first bad revision is:
597 597 changeset: 30:ed2d2f24b11c
598 598 tag: tip
599 599 user: test
600 600 date: Thu Jan 01 00:00:30 1970 +0000
601 601 summary: msg 30
602 602
603 603
604 604 Rewritten commits should not crash
605 605
606 606 $ hg co 29
607 607 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
608 608 $ hg revert --all -r 30
609 609 reverting a
610 610 $ hg commit -m 'msg 30 -- fixed'
611 611 created new head
612 612 $ hg debugobsolete `hg id --debug -i -r 30` `hg id --debug -i -r .`
613 613 1 new obsolescence markers
614 614 obsoleted 1 changesets
615 615 $ hg bisect
616 616 The first bad revision is:
617 617 changeset: 30:ed2d2f24b11c
618 618 user: test
619 619 date: Thu Jan 01 00:00:30 1970 +0000
620 620 obsolete: rewritten as 32:8a638ebd1122
621 621 summary: msg 30
622 622
623 623
624 624 Log template does not crash
625 625
626 626 $ hg log -GTbisect -r 15::
627 627 @ changeset: 32:8a638ebd1122
628 628 | bisect: good (implicit)
629 629 | tag: tip
630 630 | parent: 29:b5bd63375ab9
631 631 | user: test
632 632 | date: Thu Jan 01 00:00:00 1970 +0000
633 633 | summary: msg 30 -- fixed
634 634 |
635 635 o changeset: 29:b5bd63375ab9
636 636 | bisect: good
637 637 | user: test
638 638 | date: Thu Jan 01 00:00:29 1970 +0000
639 639 | summary: msg 29
640 640 |
641 641 o changeset: 28:8e0c2264c8af
642 642 | bisect: good
643 643 | user: test
644 644 | date: Thu Jan 01 00:00:28 1970 +0000
645 645 | summary: msg 28
646 646 |
647 647 o changeset: 27:288867a866e9
648 648 | bisect: ignored
649 649 | user: test
650 650 | date: Thu Jan 01 00:00:27 1970 +0000
651 651 | summary: msg 27
652 652 |
653 653 o changeset: 26:3efc6fd51aeb
654 654 | bisect: good
655 655 | user: test
656 656 | date: Thu Jan 01 00:00:26 1970 +0000
657 657 | summary: msg 26
658 658 |
659 659 o changeset: 25:02a84173a97a
660 660 | bisect: ignored
661 661 | user: test
662 662 | date: Thu Jan 01 00:00:25 1970 +0000
663 663 | summary: msg 25
664 664 |
665 665 o changeset: 24:10e0acd3809e
666 666 | bisect: ignored
667 667 | user: test
668 668 | date: Thu Jan 01 00:00:24 1970 +0000
669 669 | summary: msg 24
670 670 |
671 671 o changeset: 23:5ec79163bff4
672 672 | bisect: ignored
673 673 | user: test
674 674 | date: Thu Jan 01 00:00:23 1970 +0000
675 675 | summary: msg 23
676 676 |
677 677 o changeset: 22:06c7993750ce
678 678 | bisect: good
679 679 | user: test
680 680 | date: Thu Jan 01 00:00:22 1970 +0000
681 681 | summary: msg 22
682 682 |
683 683 o changeset: 21:e5db6aa3fe2a
684 684 | bisect: ignored
685 685 | user: test
686 686 | date: Thu Jan 01 00:00:21 1970 +0000
687 687 | summary: msg 21
688 688 |
689 689 o changeset: 20:7128fb4fdbc9
690 690 | bisect: ignored
691 691 | user: test
692 692 | date: Thu Jan 01 00:00:20 1970 +0000
693 693 | summary: msg 20
694 694 |
695 695 o changeset: 19:52798545b482
696 696 | bisect: ignored
697 697 | user: test
698 698 | date: Thu Jan 01 00:00:19 1970 +0000
699 699 | summary: msg 19
700 700 |
701 701 o changeset: 18:86977a90077e
702 702 | bisect: ignored
703 703 | user: test
704 704 | date: Thu Jan 01 00:00:18 1970 +0000
705 705 | summary: msg 18
706 706 |
707 707 o changeset: 17:03515f4a9080
708 708 | bisect: ignored
709 709 | user: test
710 710 | date: Thu Jan 01 00:00:17 1970 +0000
711 711 | summary: msg 17
712 712 |
713 713 o changeset: 16:a2e6ea4973e9
714 714 | bisect: ignored
715 715 | user: test
716 716 | date: Thu Jan 01 00:00:16 1970 +0000
717 717 | summary: msg 16
718 718 |
719 719 o changeset: 15:e7fa0811edb0
720 720 | bisect: good
721 721 ~ user: test
722 722 date: Thu Jan 01 00:00:15 1970 +0000
723 723 summary: msg 15
724 724
725 725 $ hg debugobsolete --delete `hg debugobsolete --index -T'{index}\n' | tail -1`
726 726 deleted 1 obsolescence markers
727 727
728 728 Changeset in the bad:good range is obsolete
729 729 ---------------------------------------------
730 730
731 731 $ hg up 30
732 732 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
733 733 $ echo 'a' >> a
734 734 $ hg ci -m "msg 32" -d "32 0"
735 735 $ hg bisect --reset
736 736 $ hg bisect --good .
737 737 $ hg bisect --bad 25
738 738 Testing changeset 28:8e0c2264c8af (6 changesets remaining, ~2 tests)
739 739 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
740 740 $ hg bisect --command true
741 741 changeset 28:8e0c2264c8af: good
742 742 changeset 26:3efc6fd51aeb: good
743 743 The first good revision is:
744 744 changeset: 26:3efc6fd51aeb
745 745 user: test
746 746 date: Thu Jan 01 00:00:26 1970 +0000
747 747 summary: msg 26
748 748
749 749 Test the validation message when exclusive options are used:
750 750
751 751 $ hg bisect -r
752 752 $ hg bisect -b -c false
753 753 abort: --bad and --command are incompatible
754 754 [10]
755 755 $ hg bisect -b -e
756 756 abort: --bad and --extend are incompatible
757 757 [10]
758 758 $ hg bisect -b -g
759 759 abort: --bad and --good are incompatible
760 760 [10]
761 761 $ hg bisect -b -r
762 762 abort: --bad and --reset are incompatible
763 763 [10]
764 764 $ hg bisect -b -s
765 765 abort: --bad and --skip are incompatible
766 766 [10]
767 767 $ hg bisect -c false -e
768 768 abort: --command and --extend are incompatible
769 769 [10]
770 770 $ hg bisect -c false -g
771 771 abort: --command and --good are incompatible
772 772 [10]
773 773 $ hg bisect -c false -r
774 774 abort: --command and --reset are incompatible
775 775 [10]
776 776 $ hg bisect -c false -s
777 777 abort: --command and --skip are incompatible
778 778 [10]
779 779 $ hg bisect -e -g
780 780 abort: --extend and --good are incompatible
781 781 [10]
782 782 $ hg bisect -e -r
783 783 abort: --extend and --reset are incompatible
784 784 [10]
785 785 $ hg bisect -e -s
786 786 abort: --extend and --skip are incompatible
787 787 [10]
788 788 $ hg bisect -g -r
789 789 abort: --good and --reset are incompatible
790 790 [10]
791 791 $ hg bisect -g -s
792 792 abort: --good and --skip are incompatible
793 793 [10]
794 794 $ hg bisect -r -s
795 795 abort: --reset and --skip are incompatible
796 796 [10]
General Comments 0
You need to be logged in to leave comments. Login now