Mercurial > hg
comparison mercurial/ancestor.py @ 39481:b6a0e06b0f7d
lazyancestors: extract __iter__ to free function
The next patch will keep a reference to the returned iterator in a
field, which would otherwise result in a reference cycle.
Differential Revision: https://phab.mercurial-scm.org/D4517
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Sun, 09 Sep 2018 23:16:55 -0700 |
parents | 8eb2145ff0fb |
children | 77a2f6d805f2 |
comparison
equal
deleted
inserted
replaced
39480:89630d0b3e23 | 39481:b6a0e06b0f7d |
---|---|
257 thisvisit.add(p) | 257 thisvisit.add(p) |
258 | 258 |
259 missing.reverse() | 259 missing.reverse() |
260 return missing | 260 return missing |
261 | 261 |
262 # Extracted from lazyancestors.__iter__ to avoid a reference cycle | |
263 def _lazyancestorsiter(parentrevs, initrevs, stoprev, inclusive): | |
264 seen = {nullrev} | |
265 revs = initrevs | |
266 | |
267 schedule = heapq.heappush | |
268 nextitem = heapq.heappop | |
269 see = seen.add | |
270 | |
271 if inclusive: | |
272 visit = [-r for r in revs] | |
273 seen.update(revs) | |
274 heapq.heapify(visit) | |
275 else: | |
276 visit = [] | |
277 heapq.heapify(visit) | |
278 for r in revs: | |
279 for parent in parentrevs(r): | |
280 if parent not in seen: | |
281 schedule(visit, -parent) | |
282 see(parent) | |
283 | |
284 while visit: | |
285 current = -nextitem(visit) | |
286 if current >= stoprev: | |
287 yield current | |
288 for parent in parentrevs(current): | |
289 if parent not in seen: | |
290 schedule(visit, -parent) | |
291 see(parent) | |
292 | |
262 class lazyancestors(object): | 293 class lazyancestors(object): |
263 def __init__(self, pfunc, revs, stoprev=0, inclusive=False): | 294 def __init__(self, pfunc, revs, stoprev=0, inclusive=False): |
264 """Create a new object generating ancestors for the given revs. Does | 295 """Create a new object generating ancestors for the given revs. Does |
265 not generate revs lower than stoprev. | 296 not generate revs lower than stoprev. |
266 | 297 |
309 revision number order. That order is also topological: a child is | 340 revision number order. That order is also topological: a child is |
310 always emitted before its parent. | 341 always emitted before its parent. |
311 | 342 |
312 If inclusive is True, the source revisions are also yielded. The | 343 If inclusive is True, the source revisions are also yielded. The |
313 reverse revision number order is still enforced.""" | 344 reverse revision number order is still enforced.""" |
314 seen = {nullrev} | 345 for rev in _lazyancestorsiter(self._parentrevs, self._initrevs, |
315 revs = self._initrevs | 346 self._stoprev, self._inclusive): |
316 | 347 yield rev |
317 parentrevs = self._parentrevs | |
318 stoprev = self._stoprev | |
319 schedule = heapq.heappush | |
320 nextitem = heapq.heappop | |
321 see = seen.add | |
322 | |
323 if self._inclusive: | |
324 visit = [-r for r in revs] | |
325 seen.update(revs) | |
326 heapq.heapify(visit) | |
327 else: | |
328 visit = [] | |
329 heapq.heapify(visit) | |
330 for r in revs: | |
331 for parent in parentrevs(r): | |
332 if parent not in seen: | |
333 schedule(visit, -parent) | |
334 see(parent) | |
335 | |
336 while visit: | |
337 current = -nextitem(visit) | |
338 if current >= stoprev: | |
339 yield current | |
340 for parent in parentrevs(current): | |
341 if parent not in seen: | |
342 schedule(visit, -parent) | |
343 see(parent) | |
344 | 348 |
345 def __contains__(self, target): | 349 def __contains__(self, target): |
346 """Test whether target is an ancestor of self._initrevs.""" | 350 """Test whether target is an ancestor of self._initrevs.""" |
347 # Trying to do both __iter__ and __contains__ using the same visit | 351 # Trying to do both __iter__ and __contains__ using the same visit |
348 # heap and seen set is complex enough that it slows down both. Keep | 352 # heap and seen set is complex enough that it slows down both. Keep |