##// END OF EJS Templates
revset: add ^ and ~ operators from parentrevspec extension...
Kevin Gessner -
r14070:305c9767 default
parent child Browse files
Show More
@@ -42,6 +42,20 b' These are the supported infix operators:'
42
42
43 ``x - y``
43 ``x - y``
44 Changesets in x but not in y.
44 Changesets in x but not in y.
45
46 ``x^n``
47 The nth parent of x, n == 0, 1, or 2.
48 For n == 0, x; for n == 1, the first parent of each changeset in x;
49 for n == 2, the second parent of changeset in x.
50
51 ``x~n``
52 The nth first ancestor of x; ``x~0`` is x; ``x~3`` is ``x^^^``.
53
54 There is a single postfix operator:
55
56 ``x^``
57 Equivalent to ``x^1``, the first parent of each changeset in x.
58
45
59
46 The following predicates are supported:
60 The following predicates are supported:
47
61
@@ -13,6 +13,8 b' 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)),
@@ -47,7 +49,7 b' def tokenize(program):'
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
@@ -209,6 +211,22 b' def ancestors(repo, subset, x):'
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)``.
@@ -588,6 +606,31 b' def parents(repo, subset, x):'
588 ps.update(cl.parentrevs(r))
606 ps.update(cl.parentrevs(r))
589 return [r for r in subset if r in ps]
607 return [r for r in subset if r in ps]
590
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])
632 return [r for r in subset if r in ps]
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,
@@ -769,6 +812,9 b' methods = {'
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):
@@ -814,9 +860,12 b' def optimize(x, small):'
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)
@@ -374,3 +374,32 b' or operator should preserve ordering:'
374 4
374 4
375 2
375 2
376 9
376 9
377
378 parentrevspec
379
380 $ log 'merge()^0'
381 6
382 $ log 'merge()^'
383 5
384 $ log 'merge()^1'
385 5
386 $ log 'merge()^2'
387 4
388
389 $ log 'merge()~0'
390 6
391 $ log 'merge()~1'
392 5
393 $ log 'merge()~2'
394 3
395 $ log 'merge()~3'
396 1
397
398 $ log '(-3:tip)^'
399 4
400 6
401 8
402
403 $ log 'tip^foo'
404 hg: parse error: ^ expects a number 0, 1, or 2
405 [255]
General Comments 0
You need to be logged in to leave comments. Login now