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