comparison mercurial/hbisect.py @ 15146:b39d85be78a8

hbisect.get: use simpler code with repo.set(), fix 'pruned' set Use repo.set() wherever possible, instead of locally trying to reproduce complex graph computations. 'pruned' now means 'all csets that will no longer be visited by the bisection'. The change is done is this very patch instead of its own dedicated one becasue the code changes all over the place, and the previous 'pruned' code was totally rewritten by the cleanup, so it was easier to just change the behavior at the same time. The previous series went in too fast for this cleanup pass to be included, so here it is. ;-) Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
date Tue, 20 Sep 2011 20:19:48 +0200
parents 883d28233a4d
children 395ca8cd2669
comparison
equal deleted inserted replaced
15145:ff26712a0c50 15146:b39d85be78a8
158 """ 158 """
159 Return a list of revision(s) that match the given status: 159 Return a list of revision(s) that match the given status:
160 160
161 - ``good``, ``bad``, ``skip``: as the names imply 161 - ``good``, ``bad``, ``skip``: as the names imply
162 - ``range`` : all csets taking part in the bisection 162 - ``range`` : all csets taking part in the bisection
163 - ``pruned`` : good|bad|skip, excluding out-of-range csets 163 - ``pruned`` : csets that are good, bad or skipped
164 - ``untested`` : csets whose fate is yet unknown 164 - ``untested`` : csets whose fate is yet unknown
165 """ 165 """
166 state = load_state(repo) 166 state = load_state(repo)
167 if status in ('good', 'bad', 'skip'): 167 if status in ('good', 'bad', 'skip'):
168 return [repo.changelog.rev(n) for n in state[status]] 168 return [repo.changelog.rev(n) for n in state[status]]
169 else: 169 else:
170 # Build sets of good, bad, and skipped csets 170 # In the floowing sets, we do *not* call 'bisect()' with more
171 goods = set(repo.changelog.rev(n) for n in state['good']) 171 # than one level of recusrsion, because that can be very, very
172 bads = set(repo.changelog.rev(n) for n in state['bad']) 172 # time consuming. Instead, we always develop the expression as
173 skips = set(repo.changelog.rev(n) for n in state['skip']) 173 # much as possible.
174 174
175 # Build kinship of good csets 175 # 'range' is all csets that make the bisection:
176 ga = goods.copy() # Goods' Ancestors 176 # - have a good ancestor and a bad descendant, or conversely
177 gd = goods.copy() # Goods' Descendants 177 # that's because the bisection can go either way
178 for g in goods: 178 range = '( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )'
179 ga |= set(repo.changelog.ancestors(g)) 179
180 gd |= set(repo.changelog.descendants(g)) 180 # 'pruned' is all csets whose fate is already known:
181 181 # - a good ancestor and a good ascendant, or
182 # Build kinship of bad csets 182 # - a bad ancestor and a bad descendant, or
183 ba = bads.copy() # Bads' Ancestors 183 # - skipped
184 bd = bads.copy() # Bads' Descendants 184 # But in case of irrelevant goods/bads, we also need to
185 for b in bads: 185 # include them.
186 ba |= set(repo.changelog.ancestors(b)) 186 pg = 'bisect(good)::bisect(good)' # Pruned goods
187 bd |= set(repo.changelog.descendants(b)) 187 pb = 'bisect(bad)::bisect(bad)' # Pruned bads
188 188 ps = 'bisect(skip)' # Pruned skipped
189 # Build the range of the bisection 189 pruned = '( (%s) | (%s) | (%s) )' % (pg, pb, ps)
190 range = set(c for c in ba if c in gd) 190
191 range |= set(c for c in ga if c in bd) 191 # 'untested' is all cset that are- in 'range', but not in 'pruned'
192 untested = '( (%s) - (%s) )' % (range, pruned)
192 193
193 if status == 'range': 194 if status == 'range':
194 return [c for c in range] 195 return [c.rev() for c in repo.set(range)]
195 elif status == 'pruned': 196 elif status == 'pruned':
196 # We do not want skipped csets that are out-of-range 197 return [c.rev() for c in repo.set(pruned)]
197 return [c for c in range if c in (goods | bads | skips)]
198 elif status == 'untested': 198 elif status == 'untested':
199 # Return the csets in range that are not pruned 199 return [c.rev() for c in repo.set(untested)]
200 return [c for c in range if not c in (goods | bads | skips)]
201 200
202 else: 201 else:
203 raise error.ParseError(_('invalid bisect state')) 202 raise error.ParseError(_('invalid bisect state'))