Show More
@@ -125,10 +125,38 b' def _genrevdescendants(repo, revs, follo' | |||||
125 | yield i |
|
125 | yield i | |
126 | break |
|
126 | break | |
127 |
|
127 | |||
128 |
def |
|
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 | """Like revlog.descendants() but supports additional options, includes |
|
149 | """Like revlog.descendants() but supports additional options, includes | |
130 |
the given revs themselves, and returns a smartset |
|
150 | the given revs themselves, and returns a smartset | |
131 | gen = _genrevdescendants(repo, revs, followfirst) |
|
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 | return generatorset(gen, iterasc=True) |
|
160 | return generatorset(gen, iterasc=True) | |
133 |
|
161 | |||
134 | def _reachablerootspure(repo, minroot, roots, heads, includepath): |
|
162 | def _reachablerootspure(repo, minroot, roots, heads, includepath): |
@@ -595,23 +595,42 b' def desc(repo, subset, x):' | |||||
595 | return subset.filter(lambda r: matcher(repo[r].description()), |
|
595 | return subset.filter(lambda r: matcher(repo[r].description()), | |
596 | condrepr=('<desc %r>', ds)) |
|
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 | roots = getset(repo, fullreposet(repo), x) |
|
600 | roots = getset(repo, fullreposet(repo), x) | |
600 | if not roots: |
|
601 | if not roots: | |
601 | return baseset() |
|
602 | return baseset() | |
602 | s = dagop.revdescendants(repo, roots, followfirst) |
|
603 | s = dagop.revdescendants(repo, roots, followfirst, startdepth, stopdepth) | |
603 | return subset & s |
|
604 | return subset & s | |
604 |
|
605 | |||
605 | @predicate('descendants(set)', safe=True) |
|
606 | @predicate('descendants(set[, depth])', safe=True) | |
606 | def descendants(repo, subset, x): |
|
607 | def descendants(repo, subset, x): | |
607 | """Changesets which are descendants of changesets in set, including the |
|
608 | """Changesets which are descendants of changesets in set, including the | |
608 | given changesets themselves. |
|
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 | if 'set' not in args: |
|
616 | if 'set' not in args: | |
612 | # i18n: "descendants" is a keyword |
|
617 | # i18n: "descendants" is a keyword | |
613 | raise error.ParseError(_('descendants takes at least 1 argument')) |
|
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 | @predicate('_firstdescendants', safe=True) |
|
635 | @predicate('_firstdescendants', safe=True) | |
617 | def _firstdescendants(repo, subset, x): |
|
636 | def _firstdescendants(repo, subset, x): |
@@ -980,6 +980,60 b' test descendants' | |||||
980 | 7 |
|
980 | 7 | |
981 | 8 |
|
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 | test author |
|
1037 | test author | |
984 |
|
1038 | |||
985 | $ log 'author(bob)' |
|
1039 | $ log 'author(bob)' |
General Comments 0
You need to be logged in to leave comments.
Login now