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