@@ -114,10 +114,11 @@ elements = {
":": (15, ("rangepre", 15), ("range", 15), ("rangepost", 15)),
"not": (10, ("not", 10)),
"!": (10, ("not", 10)),
"and": (5, None, ("and", 5)),
"&": (5, None, ("and", 5)),
+ "%": (5, None, ("only", 5), ("onlypost", 5)),
"or": (4, None, ("or", 4)),
"|": (4, None, ("or", 4)),
"+": (4, None, ("or", 4)),
",": (2, None, ("list", 2)),
")": (0, None, None),
@@ -150,11 +151,11 @@ def tokenize(program, lookup=None):
yield ('..', None, pos)
pos += 1 # skip ahead
elif c == '#' and program[pos:pos + 2] == '##': # look ahead carefully
yield ('##', None, pos)
pos += 1 # skip ahead
- elif c in "():,-|&+!~^": # handle simple operators
+ elif c in "():,-|&+!~^%": # handle simple operators
yield (c, None, pos)
elif (c in '"\'' or c == 'r' and
program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
if c == 'r':
pos += 1
@@ -1198,17 +1199,21 @@ def obsolete(repo, subset, x):
# i18n: "obsolete" is a keyword
getargs(x, 0, 0, _("obsolete takes no arguments"))
obsoletes = obsmod.getrevs(repo, 'obsolete')
return subset & obsoletes
-def only(repo, subset, x):
+def only(repo, subset, x, y=None):
"""``only(set, [set])``
Changesets that are ancestors of the first set that are not ancestors
of any other head in the repo. If a second set is specified, the result
is ancestors of the first set that are not ancestors of the second set
(i.e. ::<set1> - ::<set2>).
"""
+ # if y is not none then we need to combine the operators into a list
+ if y is not None:
+ x = ('list', x, y)
+
cl = repo.changelog
# i18n: "only" is a keyword
args = getargs(x, 1, 2, _('only takes one or two arguments'))
include = getset(repo, spanset(repo), args[0])
if len(args) == 1:
@@ -1920,10 +1925,12 @@ methods = {
"list": listset,
"func": func,
"ancestor": ancestorspec,
"parent": parentspec,
"parentpost": p1,
+ "only": only,
+ "onlypost": only,
}
def optimize(x, small):
if x is None:
return 0, x
@@ -1946,11 +1953,11 @@ def optimize(x, small):
elif op == 'negate':
return optimize(('string',
'-' + getstring(x[1], _("can't negate that"))), small)
elif op in 'string symbol negate':
return smallbonus, x # single revisions are small
- elif op == 'and':
+ elif op in 'and only':
wa, ta = optimize(x[1], True)
wb, tb = optimize(x[2], True)
# (::x and not ::y)/(not ::y and ::x) have a fast path
def isonly(revs, bases):
@@ -436,10 +436,36 @@ Test empty set input
2
4
8
9
+Test '%' operator
+
+ $ log '9%'
+ 8
+ 9
+ $ log '9%5'
+ 2
+ 4
+ 8
+ 9
+ $ log '(7 + 9)%(5 + 2)'
+ 4
+ 6
+ 7
+ 8
+ 9
+
+Test the order of operations
+
+ $ log '7 + 9%5 + 2'
+ 7
+ 2
+ 4
+ 8
+ 9
+
Test explicit numeric revision
$ log 'rev(-1)'
$ log 'rev(0)'
0
$ log 'rev(9)'