##// END OF EJS Templates
revset: add depth limit to descendants() (issue5374)...
Yuya Nishihara -
r33080:a53bfc28 default
parent child Browse files
Show More
@@ -125,10 +125,38 b' def _genrevdescendants(repo, revs, follo'
125 125 yield i
126 126 break
127 127
128 def revdescendants(repo, revs, followfirst):
128 def _builddescendantsmap(repo, startrev, followfirst):
129 """Build map of 'rev -> child revs', offset from startrev"""
130 cl = repo.changelog
131 nullrev = node.nullrev
132 descmap = [[] for _rev in xrange(startrev, len(cl))]
133 for currev in cl.revs(startrev + 1):
134 p1rev, p2rev = cl.parentrevs(currev)
135 if p1rev >= startrev:
136 descmap[p1rev - startrev].append(currev)
137 if not followfirst and p2rev != nullrev and p2rev >= startrev:
138 descmap[p2rev - startrev].append(currev)
139 return descmap
140
141 def _genrevdescendantsofdepth(repo, revs, followfirst, startdepth, stopdepth):
142 startrev = revs.min()
143 descmap = _builddescendantsmap(repo, startrev, followfirst)
144 def pfunc(rev):
145 return descmap[rev - startrev]
146 return _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse=False)
147
148 def revdescendants(repo, revs, followfirst, startdepth=None, stopdepth=None):
129 149 """Like revlog.descendants() but supports additional options, includes
130 the given revs themselves, and returns a smartset"""
131 gen = _genrevdescendants(repo, revs, followfirst)
150 the given revs themselves, and returns a smartset
151
152 Scan ends at the stopdepth (exlusive) if specified. Revisions found
153 earlier than the startdepth are omitted.
154 """
155 if startdepth is None and stopdepth is None:
156 gen = _genrevdescendants(repo, revs, followfirst)
157 else:
158 gen = _genrevdescendantsofdepth(repo, revs, followfirst,
159 startdepth, stopdepth)
132 160 return generatorset(gen, iterasc=True)
133 161
134 162 def _reachablerootspure(repo, minroot, roots, heads, includepath):
@@ -595,23 +595,42 b' def desc(repo, subset, x):'
595 595 return subset.filter(lambda r: matcher(repo[r].description()),
596 596 condrepr=('<desc %r>', ds))
597 597
598 def _descendants(repo, subset, x, followfirst=False):
598 def _descendants(repo, subset, x, followfirst=False, startdepth=None,
599 stopdepth=None):
599 600 roots = getset(repo, fullreposet(repo), x)
600 601 if not roots:
601 602 return baseset()
602 s = dagop.revdescendants(repo, roots, followfirst)
603 s = dagop.revdescendants(repo, roots, followfirst, startdepth, stopdepth)
603 604 return subset & s
604 605
605 @predicate('descendants(set)', safe=True)
606 @predicate('descendants(set[, depth])', safe=True)
606 607 def descendants(repo, subset, x):
607 608 """Changesets which are descendants of changesets in set, including the
608 609 given changesets themselves.
610
611 If depth is specified, the result only includes changesets up to
612 the specified generation.
609 613 """
610 args = getargsdict(x, 'descendants', 'set')
614 # startdepth is for internal use only until we can decide the UI
615 args = getargsdict(x, 'descendants', 'set depth startdepth')
611 616 if 'set' not in args:
612 617 # i18n: "descendants" is a keyword
613 618 raise error.ParseError(_('descendants takes at least 1 argument'))
614 return _descendants(repo, subset, args['set'])
619 startdepth = stopdepth = None
620 if 'startdepth' in args:
621 n = getinteger(args['startdepth'],
622 "descendants expects an integer startdepth")
623 if n < 0:
624 raise error.ParseError("negative startdepth")
625 startdepth = n
626 if 'depth' in args:
627 # i18n: "descendants" is a keyword
628 n = getinteger(args['depth'], _("descendants expects an integer depth"))
629 if n < 0:
630 raise error.ParseError(_("negative depth"))
631 stopdepth = n + 1
632 return _descendants(repo, subset, args['set'],
633 startdepth=startdepth, stopdepth=stopdepth)
615 634
616 635 @predicate('_firstdescendants', safe=True)
617 636 def _firstdescendants(repo, subset, x):
@@ -980,6 +980,60 b' test descendants'
980 980 7
981 981 8
982 982
983 test descendants with depth limit
984
985 (depth=0 selects the node itself)
986
987 $ log 'descendants(0, depth=0)'
988 0
989 $ log 'null: & descendants(null, depth=0)'
990 -1
991
992 (p2 = null should be ignored)
993
994 $ log 'null: & descendants(null, depth=2)'
995 -1
996 0
997 1
998
999 (multiple paths: depth(6) = (2, 3))
1000
1001 $ log 'descendants(1+3, depth=2)'
1002 1
1003 2
1004 3
1005 4
1006 5
1007 6
1008
1009 (multiple paths: depth(5) = (1, 2), depth(6) = (2, 3))
1010
1011 $ log 'descendants(3+1, depth=2, startdepth=2)'
1012 4
1013 5
1014 6
1015
1016 (multiple depths: depth(6) = (0, 2, 4), search for depth=2)
1017
1018 $ log 'descendants(0+3+6, depth=3, startdepth=1)'
1019 1
1020 2
1021 3
1022 4
1023 5
1024 6
1025 7
1026
1027 (multiple depths: depth(6) = (0, 4), no match)
1028
1029 $ log 'descendants(0+6, depth=3, startdepth=1)'
1030 1
1031 2
1032 3
1033 4
1034 5
1035 7
1036
983 1037 test author
984 1038
985 1039 $ log 'author(bob)'
General Comments 0
You need to be logged in to leave comments. Login now