##// END OF EJS Templates
bisect: do not crash with rewritten commits
timeless -
r42497:52c3d16d default draft
parent child Browse files
Show More
@@ -1,294 +1,296 b''
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
15 15 from .i18n import _
16 16 from .node import (
17 17 hex,
18 18 short,
19 19 )
20 20 from . import (
21 21 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 repo = repo.unfiltered()
35 36 changelog = repo.changelog
36 37 clparents = changelog.parentrevs
37 38 skip = {changelog.rev(n) for n in state['skip']}
38 39
39 40 def buildancestors(bad, good):
40 41 badrev = min([changelog.rev(n) for n in bad])
41 42 ancestors = collections.defaultdict(lambda: None)
42 43 for rev in repo.revs("descendants(%ln) - ancestors(%ln)", good, good):
43 44 ancestors[rev] = []
44 45 if ancestors[badrev] is None:
45 46 return badrev, None
46 47 return badrev, ancestors
47 48
48 49 good = False
49 50 badrev, ancestors = buildancestors(state['bad'], state['good'])
50 51 if not ancestors: # looking for bad to good transition?
51 52 good = True
52 53 badrev, ancestors = buildancestors(state['good'], state['bad'])
53 54 bad = changelog.node(badrev)
54 55 if not ancestors: # now we're confused
55 56 if (len(state['bad']) == 1 and len(state['good']) == 1 and
56 57 state['bad'] != state['good']):
57 58 raise error.Abort(_("starting revisions are not directly related"))
58 59 raise error.Abort(_("inconsistent state, %d:%s is good and bad")
59 60 % (badrev, short(bad)))
60 61
61 62 # build children dict
62 63 children = {}
63 64 visit = collections.deque([badrev])
64 65 candidates = []
65 66 while visit:
66 67 rev = visit.popleft()
67 68 if ancestors[rev] == []:
68 69 candidates.append(rev)
69 70 for prev in clparents(rev):
70 71 if prev != -1:
71 72 if prev in children:
72 73 children[prev].append(rev)
73 74 else:
74 75 children[prev] = [rev]
75 76 visit.append(prev)
76 77
77 78 candidates.sort()
78 79 # have we narrowed it down to one entry?
79 80 # or have all other possible candidates besides 'bad' have been skipped?
80 81 tot = len(candidates)
81 82 unskipped = [c for c in candidates if (c not in skip) and (c != badrev)]
82 83 if tot == 1 or not unskipped:
83 84 return ([changelog.node(c) for c in candidates], 0, good)
84 85 perfect = tot // 2
85 86
86 87 # find the best node to test
87 88 best_rev = None
88 89 best_len = -1
89 90 poison = set()
90 91 for rev in candidates:
91 92 if rev in poison:
92 93 # poison children
93 94 poison.update(children.get(rev, []))
94 95 continue
95 96
96 97 a = ancestors[rev] or [rev]
97 98 ancestors[rev] = None
98 99
99 100 x = len(a) # number of ancestors
100 101 y = tot - x # number of non-ancestors
101 102 value = min(x, y) # how good is this test?
102 103 if value > best_len and rev not in skip:
103 104 best_len = value
104 105 best_rev = rev
105 106 if value == perfect: # found a perfect candidate? quit early
106 107 break
107 108
108 109 if y < perfect and rev not in skip: # all downhill from here?
109 110 # poison children
110 111 poison.update(children.get(rev, []))
111 112 continue
112 113
113 114 for c in children.get(rev, []):
114 115 if ancestors[c]:
115 116 ancestors[c] = list(set(ancestors[c] + a))
116 117 else:
117 118 ancestors[c] = a + [c]
118 119
119 120 assert best_rev is not None
120 121 best_node = changelog.node(best_rev)
121 122
122 123 return ([best_node], tot, good)
123 124
124 125 def extendrange(repo, state, nodes, good):
125 126 # bisect is incomplete when it ends on a merge node and
126 127 # one of the parent was not checked.
127 128 parents = repo[nodes[0]].parents()
128 129 if len(parents) > 1:
129 130 if good:
130 131 side = state['bad']
131 132 else:
132 133 side = state['good']
133 134 num = len(set(i.node() for i in parents) & set(side))
134 135 if num == 1:
135 136 return parents[0].ancestor(parents[1])
136 137 return None
137 138
138 139 def load_state(repo):
139 140 state = {'current': [], 'good': [], 'bad': [], 'skip': []}
140 141 for l in repo.vfs.tryreadlines("bisect.state"):
141 142 kind, node = l[:-1].split()
142 node = repo.lookup(node)
143 node = repo.unfiltered().lookup(node)
143 144 if kind not in state:
144 145 raise error.Abort(_("unknown bisect kind %s") % kind)
145 146 state[kind].append(node)
146 147 return state
147 148
148 149
149 150 def save_state(repo, state):
150 151 f = repo.vfs("bisect.state", "w", atomictemp=True)
151 152 with repo.wlock():
152 153 for kind in sorted(state):
153 154 for node in state[kind]:
154 155 f.write("%s %s\n" % (kind, hex(node)))
155 156 f.close()
156 157
157 158 def resetstate(repo):
158 159 """remove any bisect state from the repository"""
159 160 if repo.vfs.exists("bisect.state"):
160 161 repo.vfs.unlink("bisect.state")
161 162
162 163 def checkstate(state):
163 164 """check we have both 'good' and 'bad' to define a range
164 165
165 166 Raise Abort exception otherwise."""
166 167 if state['good'] and state['bad']:
167 168 return True
168 169 if not state['good']:
169 170 raise error.Abort(_('cannot bisect (no known good revisions)'))
170 171 else:
171 172 raise error.Abort(_('cannot bisect (no known bad revisions)'))
172 173
173 174 def get(repo, status):
174 175 """
175 176 Return a list of revision(s) that match the given status:
176 177
177 178 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
178 179 - ``goods``, ``bads`` : csets topologically good/bad
179 180 - ``range`` : csets taking part in the bisection
180 181 - ``pruned`` : csets that are goods, bads or skipped
181 182 - ``untested`` : csets whose fate is yet unknown
182 183 - ``ignored`` : csets ignored due to DAG topology
183 184 - ``current`` : the cset currently being bisected
184 185 """
185 186 state = load_state(repo)
186 187 if status in ('good', 'bad', 'skip', 'current'):
187 return map(repo.changelog.rev, state[status])
188 return map(repo.unfiltered().changelog.rev, state[status])
188 189 else:
189 190 # In the following sets, we do *not* call 'bisect()' with more
190 191 # than one level of recursion, because that can be very, very
191 192 # time consuming. Instead, we always develop the expression as
192 193 # much as possible.
193 194
194 195 # 'range' is all csets that make the bisection:
195 196 # - have a good ancestor and a bad descendant, or conversely
196 197 # that's because the bisection can go either way
197 198 range = '( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )'
198 199
199 200 _t = repo.revs('bisect(good)::bisect(bad)')
200 201 # The sets of topologically good or bad csets
201 202 if len(_t) == 0:
202 203 # Goods are topologically after bads
203 204 goods = 'bisect(good)::' # Pruned good csets
204 205 bads = '::bisect(bad)' # Pruned bad csets
205 206 else:
206 207 # Goods are topologically before bads
207 208 goods = '::bisect(good)' # Pruned good csets
208 209 bads = 'bisect(bad)::' # Pruned bad csets
209 210
210 211 # 'pruned' is all csets whose fate is already known: good, bad, skip
211 212 skips = 'bisect(skip)' # Pruned skipped csets
212 213 pruned = '( (%s) | (%s) | (%s) )' % (goods, bads, skips)
213 214
214 215 # 'untested' is all cset that are- in 'range', but not in 'pruned'
215 216 untested = '( (%s) - (%s) )' % (range, pruned)
216 217
217 218 # 'ignored' is all csets that were not used during the bisection
218 219 # due to DAG topology, but may however have had an impact.
219 220 # E.g., a branch merged between bads and goods, but whose branch-
220 221 # point is out-side of the range.
221 222 iba = '::bisect(bad) - ::bisect(good)' # Ignored bads' ancestors
222 223 iga = '::bisect(good) - ::bisect(bad)' # Ignored goods' ancestors
223 224 ignored = '( ( (%s) | (%s) ) - (%s) )' % (iba, iga, range)
224 225
225 226 if status == 'range':
226 227 return repo.revs(range)
227 228 elif status == 'pruned':
228 229 return repo.revs(pruned)
229 230 elif status == 'untested':
230 231 return repo.revs(untested)
231 232 elif status == 'ignored':
232 233 return repo.revs(ignored)
233 234 elif status == "goods":
234 235 return repo.revs(goods)
235 236 elif status == "bads":
236 237 return repo.revs(bads)
237 238 else:
238 239 raise error.ParseError(_('invalid bisect state'))
239 240
240 241 def label(repo, node):
241 242 rev = repo.changelog.rev(node)
242 243
243 244 # Try explicit sets
244 245 if rev in get(repo, 'good'):
245 246 # i18n: bisect changeset status
246 247 return _('good')
247 248 if rev in get(repo, 'bad'):
248 249 # i18n: bisect changeset status
249 250 return _('bad')
250 251 if rev in get(repo, 'skip'):
251 252 # i18n: bisect changeset status
252 253 return _('skipped')
253 254 if rev in get(repo, 'untested') or rev in get(repo, 'current'):
254 255 # i18n: bisect changeset status
255 256 return _('untested')
256 257 if rev in get(repo, 'ignored'):
257 258 # i18n: bisect changeset status
258 259 return _('ignored')
259 260
260 261 # Try implicit sets
261 262 if rev in get(repo, 'goods'):
262 263 # i18n: bisect changeset status
263 264 return _('good (implicit)')
264 265 if rev in get(repo, 'bads'):
265 266 # i18n: bisect changeset status
266 267 return _('bad (implicit)')
267 268
268 269 return None
269 270
270 271 def printresult(ui, repo, state, displayer, nodes, good):
272 repo = repo.unfiltered()
271 273 if len(nodes) == 1:
272 274 # narrowed it down to a single revision
273 275 if good:
274 276 ui.write(_("The first good revision is:\n"))
275 277 else:
276 278 ui.write(_("The first bad revision is:\n"))
277 279 displayer.show(repo[nodes[0]])
278 280 extendnode = extendrange(repo, state, nodes, good)
279 281 if extendnode is not None:
280 282 ui.write(_('Not all ancestors of this changeset have been'
281 283 ' checked.\nUse bisect --extend to continue the '
282 284 'bisection from\nthe common ancestor, %s.\n')
283 285 % extendnode)
284 286 else:
285 287 # multiple possible revisions
286 288 if good:
287 289 ui.write(_("Due to skipped revisions, the first "
288 290 "good revision could be any of:\n"))
289 291 else:
290 292 ui.write(_("Due to skipped revisions, the first "
291 293 "bad revision could be any of:\n"))
292 294 for n in nodes:
293 295 displayer.show(repo[n])
294 296 displayer.close()
@@ -1,671 +1,794 b''
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 367 [255]
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 478 [255]
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 548 [255]
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 [255]
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 obsoleted 1 changesets
585 585 $ hg bisect --reset
586 586 $ hg bisect --good 15
587 587 $ hg bisect --bad 30
588 588 Testing changeset 22:06c7993750ce (15 changesets remaining, ~3 tests)
589 589 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
590 590 $ hg bisect --command true
591 591 changeset 22:06c7993750ce: good
592 592 changeset 26:3efc6fd51aeb: good
593 593 changeset 28:8e0c2264c8af: good
594 594 changeset 29:b5bd63375ab9: good
595 595 The first bad revision is:
596 596 changeset: 30:ed2d2f24b11c
597 597 tag: tip
598 598 user: test
599 599 date: Thu Jan 01 00:00:30 1970 +0000
600 600 summary: msg 30
601 601
602 602
603 Rewritten commits should not crash
604
605 $ hg co 29
606 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
607 $ hg revert --all -r 30
608 reverting a
609 $ hg commit -m 'msg 30 -- fixed'
610 created new head
611 $ hg debugobsolete `hg id --debug -i -r 30` `hg id --debug -i -r .`
612 obsoleted 1 changesets
613 $ hg bisect
614 The first bad revision is:
615 changeset: 30:ed2d2f24b11c
616 user: test
617 date: Thu Jan 01 00:00:30 1970 +0000
618 obsolete: rewritten as 32:8a638ebd1122
619 summary: msg 30
620
621
622 Log template does not crash
623
624 $ hg log -GTbisect -r 15::
625 @ changeset: 32:8a638ebd1122
626 | bisect: good (implicit)
627 | tag: tip
628 | parent: 29:b5bd63375ab9
629 | user: test
630 | date: Thu Jan 01 00:00:00 1970 +0000
631 | summary: msg 30 -- fixed
632 |
633 o changeset: 29:b5bd63375ab9
634 | bisect: good
635 | user: test
636 | date: Thu Jan 01 00:00:29 1970 +0000
637 | summary: msg 29
638 |
639 o changeset: 28:8e0c2264c8af
640 | bisect: good
641 | user: test
642 | date: Thu Jan 01 00:00:28 1970 +0000
643 | summary: msg 28
644 |
645 o changeset: 27:288867a866e9
646 | bisect: ignored
647 | user: test
648 | date: Thu Jan 01 00:00:27 1970 +0000
649 | summary: msg 27
650 |
651 o changeset: 26:3efc6fd51aeb
652 | bisect: good
653 | user: test
654 | date: Thu Jan 01 00:00:26 1970 +0000
655 | summary: msg 26
656 |
657 o changeset: 25:02a84173a97a
658 | bisect: ignored
659 | user: test
660 | date: Thu Jan 01 00:00:25 1970 +0000
661 | summary: msg 25
662 |
663 o changeset: 24:10e0acd3809e
664 | bisect: ignored
665 | user: test
666 | date: Thu Jan 01 00:00:24 1970 +0000
667 | summary: msg 24
668 |
669 o changeset: 23:5ec79163bff4
670 | bisect: ignored
671 | user: test
672 | date: Thu Jan 01 00:00:23 1970 +0000
673 | summary: msg 23
674 |
675 o changeset: 22:06c7993750ce
676 | bisect: good
677 | user: test
678 | date: Thu Jan 01 00:00:22 1970 +0000
679 | summary: msg 22
680 |
681 o changeset: 21:e5db6aa3fe2a
682 | bisect: ignored
683 | user: test
684 | date: Thu Jan 01 00:00:21 1970 +0000
685 | summary: msg 21
686 |
687 o changeset: 20:7128fb4fdbc9
688 | bisect: ignored
689 | user: test
690 | date: Thu Jan 01 00:00:20 1970 +0000
691 | summary: msg 20
692 |
693 o changeset: 19:52798545b482
694 | bisect: ignored
695 | user: test
696 | date: Thu Jan 01 00:00:19 1970 +0000
697 | summary: msg 19
698 |
699 o changeset: 18:86977a90077e
700 | bisect: ignored
701 | user: test
702 | date: Thu Jan 01 00:00:18 1970 +0000
703 | summary: msg 18
704 |
705 o changeset: 17:03515f4a9080
706 | bisect: ignored
707 | user: test
708 | date: Thu Jan 01 00:00:17 1970 +0000
709 | summary: msg 17
710 |
711 o changeset: 16:a2e6ea4973e9
712 | bisect: ignored
713 | user: test
714 | date: Thu Jan 01 00:00:16 1970 +0000
715 | summary: msg 16
716 |
717 o changeset: 15:e7fa0811edb0
718 | bisect: good
719 ~ user: test
720 date: Thu Jan 01 00:00:15 1970 +0000
721 summary: msg 15
722
723 $ hg debugobsolete --delete `hg debugobsolete --index -T'{index}\n' | tail -1`
724 deleted 1 obsolescence markers
725
603 726 Changeset in the bad:good range is obsolete
604 727 ---------------------------------------------
605 728
606 729 $ hg up 30
607 730 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
608 731 $ echo 'a' >> a
609 732 $ hg ci -m "msg 32" -d "32 0"
610 733 $ hg bisect --reset
611 734 $ hg bisect --good .
612 735 $ hg bisect --bad 25
613 736 Testing changeset 28:8e0c2264c8af (6 changesets remaining, ~2 tests)
614 737 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
615 738 $ hg bisect --command true
616 739 changeset 28:8e0c2264c8af: good
617 740 changeset 26:3efc6fd51aeb: good
618 741 The first good revision is:
619 742 changeset: 26:3efc6fd51aeb
620 743 user: test
621 744 date: Thu Jan 01 00:00:26 1970 +0000
622 745 summary: msg 26
623 746
624 747 Test the validation message when exclusive options are used:
625 748
626 749 $ hg bisect -r
627 750 $ hg bisect -b -c false
628 751 abort: --bad and --command are incompatible
629 752 [255]
630 753 $ hg bisect -b -e
631 754 abort: --bad and --extend are incompatible
632 755 [255]
633 756 $ hg bisect -b -g
634 757 abort: --bad and --good are incompatible
635 758 [255]
636 759 $ hg bisect -b -r
637 760 abort: --bad and --reset are incompatible
638 761 [255]
639 762 $ hg bisect -b -s
640 763 abort: --bad and --skip are incompatible
641 764 [255]
642 765 $ hg bisect -c false -e
643 766 abort: --command and --extend are incompatible
644 767 [255]
645 768 $ hg bisect -c false -g
646 769 abort: --command and --good are incompatible
647 770 [255]
648 771 $ hg bisect -c false -r
649 772 abort: --command and --reset are incompatible
650 773 [255]
651 774 $ hg bisect -c false -s
652 775 abort: --command and --skip are incompatible
653 776 [255]
654 777 $ hg bisect -e -g
655 778 abort: --extend and --good are incompatible
656 779 [255]
657 780 $ hg bisect -e -r
658 781 abort: --extend and --reset are incompatible
659 782 [255]
660 783 $ hg bisect -e -s
661 784 abort: --extend and --skip are incompatible
662 785 [255]
663 786 $ hg bisect -g -r
664 787 abort: --good and --reset are incompatible
665 788 [255]
666 789 $ hg bisect -g -s
667 790 abort: --good and --skip are incompatible
668 791 [255]
669 792 $ hg bisect -r -s
670 793 abort: --reset and --skip are incompatible
671 794 [255]
General Comments 0
You need to be logged in to leave comments. Login now