Mercurial > public > mercurial-scm > hg
comparison mercurial/revset.py @ 14070:305c97670d7a
revset: add ^ and ~ operators from parentrevspec extension
^ (Nth parent) and ~ (Nth first ancestor) are infix operators that match
certain ancestors of the set:
set^0
the set
set^1 (also available as set^)
the first parent of every changeset in set
set^2
the second parent of every changeset in set
set~0
the set
set~1
the first ancestor (i.e. the first parent) of every changeset in set
set~2
the second ancestor (i.e. first parent of first parent) of every changeset
in set
set~N
the Nth ancestor (following first parents only) of every changeset in set;
set~N is equivalent to set^1^1..., with ^1 repeated N times.
author | Kevin Gessner <kevin@kevingessner.com> |
---|---|
date | Sat, 30 Apr 2011 17:43:04 +0200 |
parents | 611d2f8a4ba2 |
children | 2e4d79dcc0a0 |
comparison
equal
deleted
inserted
replaced
14069:e38846a79a23 | 14070:305c97670d7a |
---|---|
11 import match as matchmod | 11 import match as matchmod |
12 from i18n import _ | 12 from i18n import _ |
13 | 13 |
14 elements = { | 14 elements = { |
15 "(": (20, ("group", 1, ")"), ("func", 1, ")")), | 15 "(": (20, ("group", 1, ")"), ("func", 1, ")")), |
16 "~": (18, None, ("ancestor", 18)), | |
17 "^": (18, None, ("parent", 18), ("parentpost", 18)), | |
16 "-": (5, ("negate", 19), ("minus", 5)), | 18 "-": (5, ("negate", 19), ("minus", 5)), |
17 "::": (17, ("dagrangepre", 17), ("dagrange", 17), | 19 "::": (17, ("dagrangepre", 17), ("dagrange", 17), |
18 ("dagrangepost", 17)), | 20 ("dagrangepost", 17)), |
19 "..": (17, ("dagrangepre", 17), ("dagrange", 17), | 21 "..": (17, ("dagrangepre", 17), ("dagrange", 17), |
20 ("dagrangepost", 17)), | 22 ("dagrangepost", 17)), |
45 yield ('::', None, pos) | 47 yield ('::', None, pos) |
46 pos += 1 # skip ahead | 48 pos += 1 # skip ahead |
47 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully | 49 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully |
48 yield ('..', None, pos) | 50 yield ('..', None, pos) |
49 pos += 1 # skip ahead | 51 pos += 1 # skip ahead |
50 elif c in "():,-|&+!": # handle simple operators | 52 elif c in "():,-|&+!~^": # handle simple operators |
51 yield (c, None, pos) | 53 yield (c, None, pos) |
52 elif (c in '"\'' or c == 'r' and | 54 elif (c in '"\'' or c == 'r' and |
53 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings | 55 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings |
54 if c == 'r': | 56 if c == 'r': |
55 pos += 1 | 57 pos += 1 |
207 if not args: | 209 if not args: |
208 return [] | 210 return [] |
209 s = set(repo.changelog.ancestors(*args)) | set(args) | 211 s = set(repo.changelog.ancestors(*args)) | set(args) |
210 return [r for r in subset if r in s] | 212 return [r for r in subset if r in s] |
211 | 213 |
214 def ancestorspec(repo, subset, x, n): | |
215 """``set~n`` | |
216 Changesets that are the Nth ancestor (first parents only) of a changeset in set. | |
217 """ | |
218 try: | |
219 n = int(n[1]) | |
220 except ValueError: | |
221 raise error.ParseError(_("~ expects a number")) | |
222 ps = set() | |
223 cl = repo.changelog | |
224 for r in getset(repo, subset, x): | |
225 for i in range(n): | |
226 r = cl.parentrevs(r)[0] | |
227 ps.add(r) | |
228 return [r for r in subset if r in ps] | |
229 | |
212 def author(repo, subset, x): | 230 def author(repo, subset, x): |
213 """``author(string)`` | 231 """``author(string)`` |
214 Alias for ``user(string)``. | 232 Alias for ``user(string)``. |
215 """ | 233 """ |
216 # i18n: "author" is a keyword | 234 # i18n: "author" is a keyword |
584 | 602 |
585 ps = set() | 603 ps = set() |
586 cl = repo.changelog | 604 cl = repo.changelog |
587 for r in getset(repo, range(len(repo)), x): | 605 for r in getset(repo, range(len(repo)), x): |
588 ps.update(cl.parentrevs(r)) | 606 ps.update(cl.parentrevs(r)) |
607 return [r for r in subset if r in ps] | |
608 | |
609 def parentspec(repo, subset, x, n): | |
610 """``set^0`` | |
611 The set. | |
612 ``set^1`` (or ``set^``), ``set^2`` | |
613 First or second parent, respectively, of all changesets in set. | |
614 """ | |
615 try: | |
616 n = int(n[1]) | |
617 if n not in (0,1,2): | |
618 raise ValueError | |
619 except ValueError: | |
620 raise error.ParseError(_("^ expects a number 0, 1, or 2")) | |
621 ps = set() | |
622 cl = repo.changelog | |
623 for r in getset(repo, subset, x): | |
624 if n == 0: | |
625 ps.add(r) | |
626 elif n == 1: | |
627 ps.add(cl.parentrevs(r)[0]) | |
628 elif n == 2: | |
629 parents = cl.parentrevs(r) | |
630 if len(parents) > 1: | |
631 ps.add(parents[1]) | |
589 return [r for r in subset if r in ps] | 632 return [r for r in subset if r in ps] |
590 | 633 |
591 def present(repo, subset, x): | 634 def present(repo, subset, x): |
592 """``present(set)`` | 635 """``present(set)`` |
593 An empty set, if any revision in set isn't found; otherwise, | 636 An empty set, if any revision in set isn't found; otherwise, |
767 "and": andset, | 810 "and": andset, |
768 "or": orset, | 811 "or": orset, |
769 "not": notset, | 812 "not": notset, |
770 "list": listset, | 813 "list": listset, |
771 "func": func, | 814 "func": func, |
815 "ancestor": ancestorspec, | |
816 "parent": parentspec, | |
817 "parentpost": p1, | |
772 } | 818 } |
773 | 819 |
774 def optimize(x, small): | 820 def optimize(x, small): |
775 if x is None: | 821 if x is None: |
776 return 0, x | 822 return 0, x |
812 wb, wa = wa, wb | 858 wb, wa = wa, wb |
813 return max(wa, wb), (op, ta, tb) | 859 return max(wa, wb), (op, ta, tb) |
814 elif op == 'not': | 860 elif op == 'not': |
815 o = optimize(x[1], not small) | 861 o = optimize(x[1], not small) |
816 return o[0], (op, o[1]) | 862 return o[0], (op, o[1]) |
863 elif op == 'parentpost': | |
864 o = optimize(x[1], small) | |
865 return o[0], (op, o[1]) | |
817 elif op == 'group': | 866 elif op == 'group': |
818 return optimize(x[1], small) | 867 return optimize(x[1], small) |
819 elif op in 'range list': | 868 elif op in 'range list parent ancestorspec': |
820 wa, ta = optimize(x[1], small) | 869 wa, ta = optimize(x[1], small) |
821 wb, tb = optimize(x[2], small) | 870 wb, tb = optimize(x[2], small) |
822 return wa + wb, (op, ta, tb) | 871 return wa + wb, (op, ta, tb) |
823 elif op == 'func': | 872 elif op == 'func': |
824 f = getstring(x[1], _("not a symbol")) | 873 f = getstring(x[1], _("not a symbol")) |