comparison mercurial/revset.py @ 20692:7af341082b76

revset: changed descendants revset to use lazy generators Performance Benchmarking: $ time hg log -qr "0:: and 0:5" ... real 0m3.665s user 0m3.364s sys 0m0.289s $ time ./hg log -qr "0:: and 0:5" ... real 0m0.492s user 0m0.394s sys 0m0.097s
author Lucas Moscovicz <lmoscovicz@fb.com>
date Mon, 10 Feb 2014 12:26:45 -0800
parents c1f666e27345
children d04aac468bf4
comparison
equal deleted inserted replaced
20691:c1f666e27345 20692:7af341082b76
49 return descgeneratorset(iterate()) 49 return descgeneratorset(iterate())
50 50
51 def _revdescendants(repo, revs, followfirst): 51 def _revdescendants(repo, revs, followfirst):
52 """Like revlog.descendants() but supports followfirst.""" 52 """Like revlog.descendants() but supports followfirst."""
53 cut = followfirst and 1 or None 53 cut = followfirst and 1 or None
54 cl = repo.changelog 54
55 first = min(revs) 55 def iterate():
56 nullrev = node.nullrev 56 cl = repo.changelog
57 if first == nullrev: 57 first = min(revs)
58 # Are there nodes with a null first parent and a non-null 58 nullrev = node.nullrev
59 # second one? Maybe. Do we care? Probably not. 59 if first == nullrev:
60 for i in cl: 60 # Are there nodes with a null first parent and a non-null
61 yield i 61 # second one? Maybe. Do we care? Probably not.
62 return 62 for i in cl:
63
64 seen = set(revs)
65 for i in cl.revs(first + 1):
66 for x in cl.parentrevs(i)[:cut]:
67 if x != nullrev and x in seen:
68 seen.add(i)
69 yield i 63 yield i
70 break 64 else:
65 seen = set(revs)
66 for i in cl.revs(first + 1):
67 for x in cl.parentrevs(i)[:cut]:
68 if x != nullrev and x in seen:
69 seen.add(i)
70 yield i
71 break
72
73 return ascgeneratorset(iterate())
71 74
72 def _revsbetween(repo, roots, heads): 75 def _revsbetween(repo, roots, heads):
73 """Return all paths between roots and heads, inclusive of both endpoint 76 """Return all paths between roots and heads, inclusive of both endpoint
74 sets.""" 77 sets."""
75 if not roots: 78 if not roots:
639 642
640 def _descendants(repo, subset, x, followfirst=False): 643 def _descendants(repo, subset, x, followfirst=False):
641 args = getset(repo, spanset(repo), x) 644 args = getset(repo, spanset(repo), x)
642 if not args: 645 if not args:
643 return baseset([]) 646 return baseset([])
644 s = set(_revdescendants(repo, args, followfirst)) | set(args) 647 s = _revdescendants(repo, args, followfirst)
645 return subset & s 648 a = set(args)
649 return subset.filter(lambda r: r in s or r in a)
646 650
647 def descendants(repo, subset, x): 651 def descendants(repo, subset, x):
648 """``descendants(set)`` 652 """``descendants(set)``
649 Changesets which are descendants of changesets in set. 653 Changesets which are descendants of changesets in set.
650 """ 654 """