##// END OF EJS Templates
revset: skip legacy lookup for revspec wrapped in 'revset(...)'...
Boris Feld -
r37778:29eb4caf default
parent child Browse files
Show More
@@ -1,755 +1,760 b''
1 # revsetlang.py - parser, tokenizer and utility for revision set language
1 # revsetlang.py - parser, tokenizer and utility for revision set language
2 #
2 #
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import string
10 import string
11
11
12 from .i18n import _
12 from .i18n import _
13 from . import (
13 from . import (
14 error,
14 error,
15 node,
15 node,
16 parser,
16 parser,
17 pycompat,
17 pycompat,
18 util,
18 util,
19 )
19 )
20 from .utils import (
20 from .utils import (
21 stringutil,
21 stringutil,
22 )
22 )
23
23
24 elements = {
24 elements = {
25 # token-type: binding-strength, primary, prefix, infix, suffix
25 # token-type: binding-strength, primary, prefix, infix, suffix
26 "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None),
26 "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None),
27 "[": (21, None, None, ("subscript", 1, "]"), None),
27 "[": (21, None, None, ("subscript", 1, "]"), None),
28 "#": (21, None, None, ("relation", 21), None),
28 "#": (21, None, None, ("relation", 21), None),
29 "##": (20, None, None, ("_concat", 20), None),
29 "##": (20, None, None, ("_concat", 20), None),
30 "~": (18, None, None, ("ancestor", 18), None),
30 "~": (18, None, None, ("ancestor", 18), None),
31 "^": (18, None, None, ("parent", 18), "parentpost"),
31 "^": (18, None, None, ("parent", 18), "parentpost"),
32 "-": (5, None, ("negate", 19), ("minus", 5), None),
32 "-": (5, None, ("negate", 19), ("minus", 5), None),
33 "::": (17, "dagrangeall", ("dagrangepre", 17), ("dagrange", 17),
33 "::": (17, "dagrangeall", ("dagrangepre", 17), ("dagrange", 17),
34 "dagrangepost"),
34 "dagrangepost"),
35 "..": (17, "dagrangeall", ("dagrangepre", 17), ("dagrange", 17),
35 "..": (17, "dagrangeall", ("dagrangepre", 17), ("dagrange", 17),
36 "dagrangepost"),
36 "dagrangepost"),
37 ":": (15, "rangeall", ("rangepre", 15), ("range", 15), "rangepost"),
37 ":": (15, "rangeall", ("rangepre", 15), ("range", 15), "rangepost"),
38 "not": (10, None, ("not", 10), None, None),
38 "not": (10, None, ("not", 10), None, None),
39 "!": (10, None, ("not", 10), None, None),
39 "!": (10, None, ("not", 10), None, None),
40 "and": (5, None, None, ("and", 5), None),
40 "and": (5, None, None, ("and", 5), None),
41 "&": (5, None, None, ("and", 5), None),
41 "&": (5, None, None, ("and", 5), None),
42 "%": (5, None, None, ("only", 5), "onlypost"),
42 "%": (5, None, None, ("only", 5), "onlypost"),
43 "or": (4, None, None, ("or", 4), None),
43 "or": (4, None, None, ("or", 4), None),
44 "|": (4, None, None, ("or", 4), None),
44 "|": (4, None, None, ("or", 4), None),
45 "+": (4, None, None, ("or", 4), None),
45 "+": (4, None, None, ("or", 4), None),
46 "=": (3, None, None, ("keyvalue", 3), None),
46 "=": (3, None, None, ("keyvalue", 3), None),
47 ",": (2, None, None, ("list", 2), None),
47 ",": (2, None, None, ("list", 2), None),
48 ")": (0, None, None, None, None),
48 ")": (0, None, None, None, None),
49 "]": (0, None, None, None, None),
49 "]": (0, None, None, None, None),
50 "symbol": (0, "symbol", None, None, None),
50 "symbol": (0, "symbol", None, None, None),
51 "string": (0, "string", None, None, None),
51 "string": (0, "string", None, None, None),
52 "end": (0, None, None, None, None),
52 "end": (0, None, None, None, None),
53 }
53 }
54
54
55 keywords = {'and', 'or', 'not'}
55 keywords = {'and', 'or', 'not'}
56
56
57 symbols = {}
57 symbols = {}
58
58
59 _quoteletters = {'"', "'"}
59 _quoteletters = {'"', "'"}
60 _simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%"))
60 _simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%"))
61
61
62 # default set of valid characters for the initial letter of symbols
62 # default set of valid characters for the initial letter of symbols
63 _syminitletters = set(pycompat.iterbytestr(
63 _syminitletters = set(pycompat.iterbytestr(
64 string.ascii_letters.encode('ascii') +
64 string.ascii_letters.encode('ascii') +
65 string.digits.encode('ascii') +
65 string.digits.encode('ascii') +
66 '._@')) | set(map(pycompat.bytechr, xrange(128, 256)))
66 '._@')) | set(map(pycompat.bytechr, xrange(128, 256)))
67
67
68 # default set of valid characters for non-initial letters of symbols
68 # default set of valid characters for non-initial letters of symbols
69 _symletters = _syminitletters | set(pycompat.iterbytestr('-/'))
69 _symletters = _syminitletters | set(pycompat.iterbytestr('-/'))
70
70
71 def tokenize(program, lookup=None, syminitletters=None, symletters=None):
71 def tokenize(program, lookup=None, syminitletters=None, symletters=None):
72 '''
72 '''
73 Parse a revset statement into a stream of tokens
73 Parse a revset statement into a stream of tokens
74
74
75 ``syminitletters`` is the set of valid characters for the initial
75 ``syminitletters`` is the set of valid characters for the initial
76 letter of symbols.
76 letter of symbols.
77
77
78 By default, character ``c`` is recognized as valid for initial
78 By default, character ``c`` is recognized as valid for initial
79 letter of symbols, if ``c.isalnum() or c in '._@' or ord(c) > 127``.
79 letter of symbols, if ``c.isalnum() or c in '._@' or ord(c) > 127``.
80
80
81 ``symletters`` is the set of valid characters for non-initial
81 ``symletters`` is the set of valid characters for non-initial
82 letters of symbols.
82 letters of symbols.
83
83
84 By default, character ``c`` is recognized as valid for non-initial
84 By default, character ``c`` is recognized as valid for non-initial
85 letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``.
85 letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``.
86
86
87 Check that @ is a valid unquoted token character (issue3686):
87 Check that @ is a valid unquoted token character (issue3686):
88 >>> list(tokenize(b"@::"))
88 >>> list(tokenize(b"@::"))
89 [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)]
89 [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)]
90
90
91 '''
91 '''
92 program = pycompat.bytestr(program)
92 program = pycompat.bytestr(program)
93 if syminitletters is None:
93 if syminitletters is None:
94 syminitletters = _syminitletters
94 syminitletters = _syminitletters
95 if symletters is None:
95 if symletters is None:
96 symletters = _symletters
96 symletters = _symletters
97
97
98 if program and lookup:
98 if program and lookup:
99 # attempt to parse old-style ranges first to deal with
99 # attempt to parse old-style ranges first to deal with
100 # things like old-tag which contain query metacharacters
100 # things like old-tag which contain query metacharacters
101 parts = program.split(':', 1)
101 parts = program.split(':', 1)
102 if all(lookup(sym) for sym in parts if sym):
102 if all(lookup(sym) for sym in parts if sym):
103 if parts[0]:
103 if parts[0]:
104 yield ('symbol', parts[0], 0)
104 yield ('symbol', parts[0], 0)
105 if len(parts) > 1:
105 if len(parts) > 1:
106 s = len(parts[0])
106 s = len(parts[0])
107 yield (':', None, s)
107 yield (':', None, s)
108 if parts[1]:
108 if parts[1]:
109 yield ('symbol', parts[1], s + 1)
109 yield ('symbol', parts[1], s + 1)
110 yield ('end', None, len(program))
110 yield ('end', None, len(program))
111 return
111 return
112
112
113 pos, l = 0, len(program)
113 pos, l = 0, len(program)
114 while pos < l:
114 while pos < l:
115 c = program[pos]
115 c = program[pos]
116 if c.isspace(): # skip inter-token whitespace
116 if c.isspace(): # skip inter-token whitespace
117 pass
117 pass
118 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
118 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
119 yield ('::', None, pos)
119 yield ('::', None, pos)
120 pos += 1 # skip ahead
120 pos += 1 # skip ahead
121 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
121 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
122 yield ('..', None, pos)
122 yield ('..', None, pos)
123 pos += 1 # skip ahead
123 pos += 1 # skip ahead
124 elif c == '#' and program[pos:pos + 2] == '##': # look ahead carefully
124 elif c == '#' and program[pos:pos + 2] == '##': # look ahead carefully
125 yield ('##', None, pos)
125 yield ('##', None, pos)
126 pos += 1 # skip ahead
126 pos += 1 # skip ahead
127 elif c in _simpleopletters: # handle simple operators
127 elif c in _simpleopletters: # handle simple operators
128 yield (c, None, pos)
128 yield (c, None, pos)
129 elif (c in _quoteletters or c == 'r' and
129 elif (c in _quoteletters or c == 'r' and
130 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
130 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
131 if c == 'r':
131 if c == 'r':
132 pos += 1
132 pos += 1
133 c = program[pos]
133 c = program[pos]
134 decode = lambda x: x
134 decode = lambda x: x
135 else:
135 else:
136 decode = parser.unescapestr
136 decode = parser.unescapestr
137 pos += 1
137 pos += 1
138 s = pos
138 s = pos
139 while pos < l: # find closing quote
139 while pos < l: # find closing quote
140 d = program[pos]
140 d = program[pos]
141 if d == '\\': # skip over escaped characters
141 if d == '\\': # skip over escaped characters
142 pos += 2
142 pos += 2
143 continue
143 continue
144 if d == c:
144 if d == c:
145 yield ('string', decode(program[s:pos]), s)
145 yield ('string', decode(program[s:pos]), s)
146 break
146 break
147 pos += 1
147 pos += 1
148 else:
148 else:
149 raise error.ParseError(_("unterminated string"), s)
149 raise error.ParseError(_("unterminated string"), s)
150 # gather up a symbol/keyword
150 # gather up a symbol/keyword
151 elif c in syminitletters:
151 elif c in syminitletters:
152 s = pos
152 s = pos
153 pos += 1
153 pos += 1
154 while pos < l: # find end of symbol
154 while pos < l: # find end of symbol
155 d = program[pos]
155 d = program[pos]
156 if d not in symletters:
156 if d not in symletters:
157 break
157 break
158 if d == '.' and program[pos - 1] == '.': # special case for ..
158 if d == '.' and program[pos - 1] == '.': # special case for ..
159 pos -= 1
159 pos -= 1
160 break
160 break
161 pos += 1
161 pos += 1
162 sym = program[s:pos]
162 sym = program[s:pos]
163 if sym in keywords: # operator keywords
163 if sym in keywords: # operator keywords
164 yield (sym, None, s)
164 yield (sym, None, s)
165 elif '-' in sym:
165 elif '-' in sym:
166 # some jerk gave us foo-bar-baz, try to check if it's a symbol
166 # some jerk gave us foo-bar-baz, try to check if it's a symbol
167 if lookup and lookup(sym):
167 if lookup and lookup(sym):
168 # looks like a real symbol
168 # looks like a real symbol
169 yield ('symbol', sym, s)
169 yield ('symbol', sym, s)
170 else:
170 else:
171 # looks like an expression
171 # looks like an expression
172 parts = sym.split('-')
172 parts = sym.split('-')
173 for p in parts[:-1]:
173 for p in parts[:-1]:
174 if p: # possible consecutive -
174 if p: # possible consecutive -
175 yield ('symbol', p, s)
175 yield ('symbol', p, s)
176 s += len(p)
176 s += len(p)
177 yield ('-', None, pos)
177 yield ('-', None, pos)
178 s += 1
178 s += 1
179 if parts[-1]: # possible trailing -
179 if parts[-1]: # possible trailing -
180 yield ('symbol', parts[-1], s)
180 yield ('symbol', parts[-1], s)
181 else:
181 else:
182 yield ('symbol', sym, s)
182 yield ('symbol', sym, s)
183 pos -= 1
183 pos -= 1
184 else:
184 else:
185 raise error.ParseError(_("syntax error in revset '%s'") %
185 raise error.ParseError(_("syntax error in revset '%s'") %
186 program, pos)
186 program, pos)
187 pos += 1
187 pos += 1
188 yield ('end', None, pos)
188 yield ('end', None, pos)
189
189
190 # helpers
190 # helpers
191
191
192 _notset = object()
192 _notset = object()
193
193
194 def getsymbol(x):
194 def getsymbol(x):
195 if x and x[0] == 'symbol':
195 if x and x[0] == 'symbol':
196 return x[1]
196 return x[1]
197 raise error.ParseError(_('not a symbol'))
197 raise error.ParseError(_('not a symbol'))
198
198
199 def getstring(x, err):
199 def getstring(x, err):
200 if x and (x[0] == 'string' or x[0] == 'symbol'):
200 if x and (x[0] == 'string' or x[0] == 'symbol'):
201 return x[1]
201 return x[1]
202 raise error.ParseError(err)
202 raise error.ParseError(err)
203
203
204 def getinteger(x, err, default=_notset):
204 def getinteger(x, err, default=_notset):
205 if not x and default is not _notset:
205 if not x and default is not _notset:
206 return default
206 return default
207 try:
207 try:
208 return int(getstring(x, err))
208 return int(getstring(x, err))
209 except ValueError:
209 except ValueError:
210 raise error.ParseError(err)
210 raise error.ParseError(err)
211
211
212 def getboolean(x, err):
212 def getboolean(x, err):
213 value = stringutil.parsebool(getsymbol(x))
213 value = stringutil.parsebool(getsymbol(x))
214 if value is not None:
214 if value is not None:
215 return value
215 return value
216 raise error.ParseError(err)
216 raise error.ParseError(err)
217
217
218 def getlist(x):
218 def getlist(x):
219 if not x:
219 if not x:
220 return []
220 return []
221 if x[0] == 'list':
221 if x[0] == 'list':
222 return list(x[1:])
222 return list(x[1:])
223 return [x]
223 return [x]
224
224
225 def getrange(x, err):
225 def getrange(x, err):
226 if not x:
226 if not x:
227 raise error.ParseError(err)
227 raise error.ParseError(err)
228 op = x[0]
228 op = x[0]
229 if op == 'range':
229 if op == 'range':
230 return x[1], x[2]
230 return x[1], x[2]
231 elif op == 'rangepre':
231 elif op == 'rangepre':
232 return None, x[1]
232 return None, x[1]
233 elif op == 'rangepost':
233 elif op == 'rangepost':
234 return x[1], None
234 return x[1], None
235 elif op == 'rangeall':
235 elif op == 'rangeall':
236 return None, None
236 return None, None
237 raise error.ParseError(err)
237 raise error.ParseError(err)
238
238
239 def getargs(x, min, max, err):
239 def getargs(x, min, max, err):
240 l = getlist(x)
240 l = getlist(x)
241 if len(l) < min or (max >= 0 and len(l) > max):
241 if len(l) < min or (max >= 0 and len(l) > max):
242 raise error.ParseError(err)
242 raise error.ParseError(err)
243 return l
243 return l
244
244
245 def getargsdict(x, funcname, keys):
245 def getargsdict(x, funcname, keys):
246 return parser.buildargsdict(getlist(x), funcname, parser.splitargspec(keys),
246 return parser.buildargsdict(getlist(x), funcname, parser.splitargspec(keys),
247 keyvaluenode='keyvalue', keynode='symbol')
247 keyvaluenode='keyvalue', keynode='symbol')
248
248
249 # cache of {spec: raw parsed tree} built internally
249 # cache of {spec: raw parsed tree} built internally
250 _treecache = {}
250 _treecache = {}
251
251
252 def _cachedtree(spec):
252 def _cachedtree(spec):
253 # thread safe because parse() is reentrant and dict.__setitem__() is atomic
253 # thread safe because parse() is reentrant and dict.__setitem__() is atomic
254 tree = _treecache.get(spec)
254 tree = _treecache.get(spec)
255 if tree is None:
255 if tree is None:
256 _treecache[spec] = tree = parse(spec)
256 _treecache[spec] = tree = parse(spec)
257 return tree
257 return tree
258
258
259 def _build(tmplspec, *repls):
259 def _build(tmplspec, *repls):
260 """Create raw parsed tree from a template revset statement
260 """Create raw parsed tree from a template revset statement
261
261
262 >>> _build(b'f(_) and _', (b'string', b'1'), (b'symbol', b'2'))
262 >>> _build(b'f(_) and _', (b'string', b'1'), (b'symbol', b'2'))
263 ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2'))
263 ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2'))
264 """
264 """
265 template = _cachedtree(tmplspec)
265 template = _cachedtree(tmplspec)
266 return parser.buildtree(template, ('symbol', '_'), *repls)
266 return parser.buildtree(template, ('symbol', '_'), *repls)
267
267
268 def _match(patspec, tree):
268 def _match(patspec, tree):
269 """Test if a tree matches the given pattern statement; return the matches
269 """Test if a tree matches the given pattern statement; return the matches
270
270
271 >>> _match(b'f(_)', parse(b'f()'))
271 >>> _match(b'f(_)', parse(b'f()'))
272 >>> _match(b'f(_)', parse(b'f(1)'))
272 >>> _match(b'f(_)', parse(b'f(1)'))
273 [('func', ('symbol', 'f'), ('symbol', '1')), ('symbol', '1')]
273 [('func', ('symbol', 'f'), ('symbol', '1')), ('symbol', '1')]
274 >>> _match(b'f(_)', parse(b'f(1, 2)'))
274 >>> _match(b'f(_)', parse(b'f(1, 2)'))
275 """
275 """
276 pattern = _cachedtree(patspec)
276 pattern = _cachedtree(patspec)
277 return parser.matchtree(pattern, tree, ('symbol', '_'),
277 return parser.matchtree(pattern, tree, ('symbol', '_'),
278 {'keyvalue', 'list'})
278 {'keyvalue', 'list'})
279
279
280 def _matchonly(revs, bases):
280 def _matchonly(revs, bases):
281 return _match('ancestors(_) and not ancestors(_)', ('and', revs, bases))
281 return _match('ancestors(_) and not ancestors(_)', ('and', revs, bases))
282
282
283 def _fixops(x):
283 def _fixops(x):
284 """Rewrite raw parsed tree to resolve ambiguous syntax which cannot be
284 """Rewrite raw parsed tree to resolve ambiguous syntax which cannot be
285 handled well by our simple top-down parser"""
285 handled well by our simple top-down parser"""
286 if not isinstance(x, tuple):
286 if not isinstance(x, tuple):
287 return x
287 return x
288
288
289 op = x[0]
289 op = x[0]
290 if op == 'parent':
290 if op == 'parent':
291 # x^:y means (x^) : y, not x ^ (:y)
291 # x^:y means (x^) : y, not x ^ (:y)
292 # x^: means (x^) :, not x ^ (:)
292 # x^: means (x^) :, not x ^ (:)
293 post = ('parentpost', x[1])
293 post = ('parentpost', x[1])
294 if x[2][0] == 'dagrangepre':
294 if x[2][0] == 'dagrangepre':
295 return _fixops(('dagrange', post, x[2][1]))
295 return _fixops(('dagrange', post, x[2][1]))
296 elif x[2][0] == 'dagrangeall':
296 elif x[2][0] == 'dagrangeall':
297 return _fixops(('dagrangepost', post))
297 return _fixops(('dagrangepost', post))
298 elif x[2][0] == 'rangepre':
298 elif x[2][0] == 'rangepre':
299 return _fixops(('range', post, x[2][1]))
299 return _fixops(('range', post, x[2][1]))
300 elif x[2][0] == 'rangeall':
300 elif x[2][0] == 'rangeall':
301 return _fixops(('rangepost', post))
301 return _fixops(('rangepost', post))
302 elif op == 'or':
302 elif op == 'or':
303 # make number of arguments deterministic:
303 # make number of arguments deterministic:
304 # x + y + z -> (or x y z) -> (or (list x y z))
304 # x + y + z -> (or x y z) -> (or (list x y z))
305 return (op, _fixops(('list',) + x[1:]))
305 return (op, _fixops(('list',) + x[1:]))
306 elif op == 'subscript' and x[1][0] == 'relation':
306 elif op == 'subscript' and x[1][0] == 'relation':
307 # x#y[z] ternary
307 # x#y[z] ternary
308 return _fixops(('relsubscript', x[1][1], x[1][2], x[2]))
308 return _fixops(('relsubscript', x[1][1], x[1][2], x[2]))
309
309
310 return (op,) + tuple(_fixops(y) for y in x[1:])
310 return (op,) + tuple(_fixops(y) for y in x[1:])
311
311
312 def _analyze(x):
312 def _analyze(x):
313 if x is None:
313 if x is None:
314 return x
314 return x
315
315
316 op = x[0]
316 op = x[0]
317 if op == 'minus':
317 if op == 'minus':
318 return _analyze(_build('_ and not _', *x[1:]))
318 return _analyze(_build('_ and not _', *x[1:]))
319 elif op == 'only':
319 elif op == 'only':
320 return _analyze(_build('only(_, _)', *x[1:]))
320 return _analyze(_build('only(_, _)', *x[1:]))
321 elif op == 'onlypost':
321 elif op == 'onlypost':
322 return _analyze(_build('only(_)', x[1]))
322 return _analyze(_build('only(_)', x[1]))
323 elif op == 'dagrangeall':
323 elif op == 'dagrangeall':
324 raise error.ParseError(_("can't use '::' in this context"))
324 raise error.ParseError(_("can't use '::' in this context"))
325 elif op == 'dagrangepre':
325 elif op == 'dagrangepre':
326 return _analyze(_build('ancestors(_)', x[1]))
326 return _analyze(_build('ancestors(_)', x[1]))
327 elif op == 'dagrangepost':
327 elif op == 'dagrangepost':
328 return _analyze(_build('descendants(_)', x[1]))
328 return _analyze(_build('descendants(_)', x[1]))
329 elif op == 'negate':
329 elif op == 'negate':
330 s = getstring(x[1], _("can't negate that"))
330 s = getstring(x[1], _("can't negate that"))
331 return _analyze(('string', '-' + s))
331 return _analyze(('string', '-' + s))
332 elif op in ('string', 'symbol'):
332 elif op in ('string', 'symbol'):
333 return x
333 return x
334 elif op == 'rangeall':
334 elif op == 'rangeall':
335 return (op, None)
335 return (op, None)
336 elif op in {'or', 'not', 'rangepre', 'rangepost', 'parentpost'}:
336 elif op in {'or', 'not', 'rangepre', 'rangepost', 'parentpost'}:
337 return (op, _analyze(x[1]))
337 return (op, _analyze(x[1]))
338 elif op == 'group':
338 elif op == 'group':
339 return _analyze(x[1])
339 return _analyze(x[1])
340 elif op in {'and', 'dagrange', 'range', 'parent', 'ancestor', 'relation',
340 elif op in {'and', 'dagrange', 'range', 'parent', 'ancestor', 'relation',
341 'subscript'}:
341 'subscript'}:
342 ta = _analyze(x[1])
342 ta = _analyze(x[1])
343 tb = _analyze(x[2])
343 tb = _analyze(x[2])
344 return (op, ta, tb)
344 return (op, ta, tb)
345 elif op == 'relsubscript':
345 elif op == 'relsubscript':
346 ta = _analyze(x[1])
346 ta = _analyze(x[1])
347 tb = _analyze(x[2])
347 tb = _analyze(x[2])
348 tc = _analyze(x[3])
348 tc = _analyze(x[3])
349 return (op, ta, tb, tc)
349 return (op, ta, tb, tc)
350 elif op == 'list':
350 elif op == 'list':
351 return (op,) + tuple(_analyze(y) for y in x[1:])
351 return (op,) + tuple(_analyze(y) for y in x[1:])
352 elif op == 'keyvalue':
352 elif op == 'keyvalue':
353 return (op, x[1], _analyze(x[2]))
353 return (op, x[1], _analyze(x[2]))
354 elif op == 'func':
354 elif op == 'func':
355 f = getsymbol(x[1])
356 if f == 'revset':
357 return _analyze(x[2])
355 return (op, x[1], _analyze(x[2]))
358 return (op, x[1], _analyze(x[2]))
356 raise ValueError('invalid operator %r' % op)
359 raise ValueError('invalid operator %r' % op)
357
360
358 def analyze(x):
361 def analyze(x):
359 """Transform raw parsed tree to evaluatable tree which can be fed to
362 """Transform raw parsed tree to evaluatable tree which can be fed to
360 optimize() or getset()
363 optimize() or getset()
361
364
362 All pseudo operations should be mapped to real operations or functions
365 All pseudo operations should be mapped to real operations or functions
363 defined in methods or symbols table respectively.
366 defined in methods or symbols table respectively.
364 """
367 """
365 return _analyze(x)
368 return _analyze(x)
366
369
367 def _optimize(x):
370 def _optimize(x):
368 if x is None:
371 if x is None:
369 return 0, x
372 return 0, x
370
373
371 op = x[0]
374 op = x[0]
372 if op in ('string', 'symbol'):
375 if op in ('string', 'symbol'):
373 return 0.5, x # single revisions are small
376 return 0.5, x # single revisions are small
374 elif op == 'and':
377 elif op == 'and':
375 wa, ta = _optimize(x[1])
378 wa, ta = _optimize(x[1])
376 wb, tb = _optimize(x[2])
379 wb, tb = _optimize(x[2])
377 w = min(wa, wb)
380 w = min(wa, wb)
378
381
379 # (draft/secret/_notpublic() & ::x) have a fast path
382 # (draft/secret/_notpublic() & ::x) have a fast path
380 m = _match('_() & ancestors(_)', ('and', ta, tb))
383 m = _match('_() & ancestors(_)', ('and', ta, tb))
381 if m and getsymbol(m[1]) in {'draft', 'secret', '_notpublic'}:
384 if m and getsymbol(m[1]) in {'draft', 'secret', '_notpublic'}:
382 return w, _build('_phaseandancestors(_, _)', m[1], m[2])
385 return w, _build('_phaseandancestors(_, _)', m[1], m[2])
383
386
384 # (::x and not ::y)/(not ::y and ::x) have a fast path
387 # (::x and not ::y)/(not ::y and ::x) have a fast path
385 m = _matchonly(ta, tb) or _matchonly(tb, ta)
388 m = _matchonly(ta, tb) or _matchonly(tb, ta)
386 if m:
389 if m:
387 return w, _build('only(_, _)', *m[1:])
390 return w, _build('only(_, _)', *m[1:])
388
391
389 m = _match('not _', tb)
392 m = _match('not _', tb)
390 if m:
393 if m:
391 return wa, ('difference', ta, m[1])
394 return wa, ('difference', ta, m[1])
392 if wa > wb:
395 if wa > wb:
393 op = 'andsmally'
396 op = 'andsmally'
394 return w, (op, ta, tb)
397 return w, (op, ta, tb)
395 elif op == 'or':
398 elif op == 'or':
396 # fast path for machine-generated expression, that is likely to have
399 # fast path for machine-generated expression, that is likely to have
397 # lots of trivial revisions: 'a + b + c()' to '_list(a b) + c()'
400 # lots of trivial revisions: 'a + b + c()' to '_list(a b) + c()'
398 ws, ts, ss = [], [], []
401 ws, ts, ss = [], [], []
399 def flushss():
402 def flushss():
400 if not ss:
403 if not ss:
401 return
404 return
402 if len(ss) == 1:
405 if len(ss) == 1:
403 w, t = ss[0]
406 w, t = ss[0]
404 else:
407 else:
405 s = '\0'.join(t[1] for w, t in ss)
408 s = '\0'.join(t[1] for w, t in ss)
406 y = _build('_list(_)', ('string', s))
409 y = _build('_list(_)', ('string', s))
407 w, t = _optimize(y)
410 w, t = _optimize(y)
408 ws.append(w)
411 ws.append(w)
409 ts.append(t)
412 ts.append(t)
410 del ss[:]
413 del ss[:]
411 for y in getlist(x[1]):
414 for y in getlist(x[1]):
412 w, t = _optimize(y)
415 w, t = _optimize(y)
413 if t is not None and (t[0] == 'string' or t[0] == 'symbol'):
416 if t is not None and (t[0] == 'string' or t[0] == 'symbol'):
414 ss.append((w, t))
417 ss.append((w, t))
415 continue
418 continue
416 flushss()
419 flushss()
417 ws.append(w)
420 ws.append(w)
418 ts.append(t)
421 ts.append(t)
419 flushss()
422 flushss()
420 if len(ts) == 1:
423 if len(ts) == 1:
421 return ws[0], ts[0] # 'or' operation is fully optimized out
424 return ws[0], ts[0] # 'or' operation is fully optimized out
422 return max(ws), (op, ('list',) + tuple(ts))
425 return max(ws), (op, ('list',) + tuple(ts))
423 elif op == 'not':
426 elif op == 'not':
424 # Optimize not public() to _notpublic() because we have a fast version
427 # Optimize not public() to _notpublic() because we have a fast version
425 if _match('public()', x[1]):
428 if _match('public()', x[1]):
426 o = _optimize(_build('_notpublic()'))
429 o = _optimize(_build('_notpublic()'))
427 return o[0], o[1]
430 return o[0], o[1]
428 else:
431 else:
429 o = _optimize(x[1])
432 o = _optimize(x[1])
430 return o[0], (op, o[1])
433 return o[0], (op, o[1])
431 elif op == 'rangeall':
434 elif op == 'rangeall':
432 return 1, x
435 return 1, x
433 elif op in ('rangepre', 'rangepost', 'parentpost'):
436 elif op in ('rangepre', 'rangepost', 'parentpost'):
434 o = _optimize(x[1])
437 o = _optimize(x[1])
435 return o[0], (op, o[1])
438 return o[0], (op, o[1])
436 elif op in ('dagrange', 'range'):
439 elif op in ('dagrange', 'range'):
437 wa, ta = _optimize(x[1])
440 wa, ta = _optimize(x[1])
438 wb, tb = _optimize(x[2])
441 wb, tb = _optimize(x[2])
439 return wa + wb, (op, ta, tb)
442 return wa + wb, (op, ta, tb)
440 elif op in ('parent', 'ancestor', 'relation', 'subscript'):
443 elif op in ('parent', 'ancestor', 'relation', 'subscript'):
441 w, t = _optimize(x[1])
444 w, t = _optimize(x[1])
442 return w, (op, t, x[2])
445 return w, (op, t, x[2])
443 elif op == 'relsubscript':
446 elif op == 'relsubscript':
444 w, t = _optimize(x[1])
447 w, t = _optimize(x[1])
445 return w, (op, t, x[2], x[3])
448 return w, (op, t, x[2], x[3])
446 elif op == 'list':
449 elif op == 'list':
447 ws, ts = zip(*(_optimize(y) for y in x[1:]))
450 ws, ts = zip(*(_optimize(y) for y in x[1:]))
448 return sum(ws), (op,) + ts
451 return sum(ws), (op,) + ts
449 elif op == 'keyvalue':
452 elif op == 'keyvalue':
450 w, t = _optimize(x[2])
453 w, t = _optimize(x[2])
451 return w, (op, x[1], t)
454 return w, (op, x[1], t)
452 elif op == 'func':
455 elif op == 'func':
453 f = getsymbol(x[1])
456 f = getsymbol(x[1])
454 wa, ta = _optimize(x[2])
457 wa, ta = _optimize(x[2])
455 w = getattr(symbols.get(f), '_weight', 1)
458 w = getattr(symbols.get(f), '_weight', 1)
456 return w + wa, (op, x[1], ta)
459 return w + wa, (op, x[1], ta)
457 raise ValueError('invalid operator %r' % op)
460 raise ValueError('invalid operator %r' % op)
458
461
459 def optimize(tree):
462 def optimize(tree):
460 """Optimize evaluatable tree
463 """Optimize evaluatable tree
461
464
462 All pseudo operations should be transformed beforehand.
465 All pseudo operations should be transformed beforehand.
463 """
466 """
464 _weight, newtree = _optimize(tree)
467 _weight, newtree = _optimize(tree)
465 return newtree
468 return newtree
466
469
467 # the set of valid characters for the initial letter of symbols in
470 # the set of valid characters for the initial letter of symbols in
468 # alias declarations and definitions
471 # alias declarations and definitions
469 _aliassyminitletters = _syminitletters | {'$'}
472 _aliassyminitletters = _syminitletters | {'$'}
470
473
471 def _parsewith(spec, lookup=None, syminitletters=None):
474 def _parsewith(spec, lookup=None, syminitletters=None):
472 """Generate a parse tree of given spec with given tokenizing options
475 """Generate a parse tree of given spec with given tokenizing options
473
476
474 >>> _parsewith(b'foo($1)', syminitletters=_aliassyminitletters)
477 >>> _parsewith(b'foo($1)', syminitletters=_aliassyminitletters)
475 ('func', ('symbol', 'foo'), ('symbol', '$1'))
478 ('func', ('symbol', 'foo'), ('symbol', '$1'))
476 >>> _parsewith(b'$1')
479 >>> _parsewith(b'$1')
477 Traceback (most recent call last):
480 Traceback (most recent call last):
478 ...
481 ...
479 ParseError: ("syntax error in revset '$1'", 0)
482 ParseError: ("syntax error in revset '$1'", 0)
480 >>> _parsewith(b'foo bar')
483 >>> _parsewith(b'foo bar')
481 Traceback (most recent call last):
484 Traceback (most recent call last):
482 ...
485 ...
483 ParseError: ('invalid token', 4)
486 ParseError: ('invalid token', 4)
484 """
487 """
488 if lookup and spec.startswith('revset(') and spec.endswith(')'):
489 lookup = None
485 p = parser.parser(elements)
490 p = parser.parser(elements)
486 tree, pos = p.parse(tokenize(spec, lookup=lookup,
491 tree, pos = p.parse(tokenize(spec, lookup=lookup,
487 syminitletters=syminitletters))
492 syminitletters=syminitletters))
488 if pos != len(spec):
493 if pos != len(spec):
489 raise error.ParseError(_('invalid token'), pos)
494 raise error.ParseError(_('invalid token'), pos)
490 return _fixops(parser.simplifyinfixops(tree, ('list', 'or')))
495 return _fixops(parser.simplifyinfixops(tree, ('list', 'or')))
491
496
492 class _aliasrules(parser.basealiasrules):
497 class _aliasrules(parser.basealiasrules):
493 """Parsing and expansion rule set of revset aliases"""
498 """Parsing and expansion rule set of revset aliases"""
494 _section = _('revset alias')
499 _section = _('revset alias')
495
500
496 @staticmethod
501 @staticmethod
497 def _parse(spec):
502 def _parse(spec):
498 """Parse alias declaration/definition ``spec``
503 """Parse alias declaration/definition ``spec``
499
504
500 This allows symbol names to use also ``$`` as an initial letter
505 This allows symbol names to use also ``$`` as an initial letter
501 (for backward compatibility), and callers of this function should
506 (for backward compatibility), and callers of this function should
502 examine whether ``$`` is used also for unexpected symbols or not.
507 examine whether ``$`` is used also for unexpected symbols or not.
503 """
508 """
504 return _parsewith(spec, syminitletters=_aliassyminitletters)
509 return _parsewith(spec, syminitletters=_aliassyminitletters)
505
510
506 @staticmethod
511 @staticmethod
507 def _trygetfunc(tree):
512 def _trygetfunc(tree):
508 if tree[0] == 'func' and tree[1][0] == 'symbol':
513 if tree[0] == 'func' and tree[1][0] == 'symbol':
509 return tree[1][1], getlist(tree[2])
514 return tree[1][1], getlist(tree[2])
510
515
511 def expandaliases(tree, aliases, warn=None):
516 def expandaliases(tree, aliases, warn=None):
512 """Expand aliases in a tree, aliases is a list of (name, value) tuples"""
517 """Expand aliases in a tree, aliases is a list of (name, value) tuples"""
513 aliases = _aliasrules.buildmap(aliases)
518 aliases = _aliasrules.buildmap(aliases)
514 tree = _aliasrules.expand(aliases, tree)
519 tree = _aliasrules.expand(aliases, tree)
515 # warn about problematic (but not referred) aliases
520 # warn about problematic (but not referred) aliases
516 if warn is not None:
521 if warn is not None:
517 for name, alias in sorted(aliases.iteritems()):
522 for name, alias in sorted(aliases.iteritems()):
518 if alias.error and not alias.warned:
523 if alias.error and not alias.warned:
519 warn(_('warning: %s\n') % (alias.error))
524 warn(_('warning: %s\n') % (alias.error))
520 alias.warned = True
525 alias.warned = True
521 return tree
526 return tree
522
527
523 def foldconcat(tree):
528 def foldconcat(tree):
524 """Fold elements to be concatenated by `##`
529 """Fold elements to be concatenated by `##`
525 """
530 """
526 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
531 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
527 return tree
532 return tree
528 if tree[0] == '_concat':
533 if tree[0] == '_concat':
529 pending = [tree]
534 pending = [tree]
530 l = []
535 l = []
531 while pending:
536 while pending:
532 e = pending.pop()
537 e = pending.pop()
533 if e[0] == '_concat':
538 if e[0] == '_concat':
534 pending.extend(reversed(e[1:]))
539 pending.extend(reversed(e[1:]))
535 elif e[0] in ('string', 'symbol'):
540 elif e[0] in ('string', 'symbol'):
536 l.append(e[1])
541 l.append(e[1])
537 else:
542 else:
538 msg = _("\"##\" can't concatenate \"%s\" element") % (e[0])
543 msg = _("\"##\" can't concatenate \"%s\" element") % (e[0])
539 raise error.ParseError(msg)
544 raise error.ParseError(msg)
540 return ('string', ''.join(l))
545 return ('string', ''.join(l))
541 else:
546 else:
542 return tuple(foldconcat(t) for t in tree)
547 return tuple(foldconcat(t) for t in tree)
543
548
544 def parse(spec, lookup=None):
549 def parse(spec, lookup=None):
545 try:
550 try:
546 return _parsewith(spec, lookup=lookup)
551 return _parsewith(spec, lookup=lookup)
547 except error.ParseError as inst:
552 except error.ParseError as inst:
548 if len(inst.args) > 1: # has location
553 if len(inst.args) > 1: # has location
549 loc = inst.args[1]
554 loc = inst.args[1]
550 # Remove newlines -- spaces are equivalent whitespace.
555 # Remove newlines -- spaces are equivalent whitespace.
551 spec = spec.replace('\n', ' ')
556 spec = spec.replace('\n', ' ')
552 # We want the caret to point to the place in the template that
557 # We want the caret to point to the place in the template that
553 # failed to parse, but in a hint we get a open paren at the
558 # failed to parse, but in a hint we get a open paren at the
554 # start. Therefore, we print "loc + 1" spaces (instead of "loc")
559 # start. Therefore, we print "loc + 1" spaces (instead of "loc")
555 # to line up the caret with the location of the error.
560 # to line up the caret with the location of the error.
556 inst.hint = spec + '\n' + ' ' * (loc + 1) + '^ ' + _('here')
561 inst.hint = spec + '\n' + ' ' * (loc + 1) + '^ ' + _('here')
557 raise
562 raise
558
563
559 def _quote(s):
564 def _quote(s):
560 r"""Quote a value in order to make it safe for the revset engine.
565 r"""Quote a value in order to make it safe for the revset engine.
561
566
562 >>> _quote(b'asdf')
567 >>> _quote(b'asdf')
563 "'asdf'"
568 "'asdf'"
564 >>> _quote(b"asdf'\"")
569 >>> _quote(b"asdf'\"")
565 '\'asdf\\\'"\''
570 '\'asdf\\\'"\''
566 >>> _quote(b'asdf\'')
571 >>> _quote(b'asdf\'')
567 "'asdf\\''"
572 "'asdf\\''"
568 >>> _quote(1)
573 >>> _quote(1)
569 "'1'"
574 "'1'"
570 """
575 """
571 return "'%s'" % stringutil.escapestr(pycompat.bytestr(s))
576 return "'%s'" % stringutil.escapestr(pycompat.bytestr(s))
572
577
573 def _formatargtype(c, arg):
578 def _formatargtype(c, arg):
574 if c == 'd':
579 if c == 'd':
575 return '%d' % int(arg)
580 return '%d' % int(arg)
576 elif c == 's':
581 elif c == 's':
577 return _quote(arg)
582 return _quote(arg)
578 elif c == 'r':
583 elif c == 'r':
579 parse(arg) # make sure syntax errors are confined
584 parse(arg) # make sure syntax errors are confined
580 return '(%s)' % arg
585 return '(%s)' % arg
581 elif c == 'n':
586 elif c == 'n':
582 return _quote(node.hex(arg))
587 return _quote(node.hex(arg))
583 elif c == 'b':
588 elif c == 'b':
584 try:
589 try:
585 return _quote(arg.branch())
590 return _quote(arg.branch())
586 except AttributeError:
591 except AttributeError:
587 raise TypeError
592 raise TypeError
588 raise error.ParseError(_('unexpected revspec format character %s') % c)
593 raise error.ParseError(_('unexpected revspec format character %s') % c)
589
594
590 def _formatlistexp(s, t):
595 def _formatlistexp(s, t):
591 l = len(s)
596 l = len(s)
592 if l == 0:
597 if l == 0:
593 return "_list('')"
598 return "_list('')"
594 elif l == 1:
599 elif l == 1:
595 return _formatargtype(t, s[0])
600 return _formatargtype(t, s[0])
596 elif t == 'd':
601 elif t == 'd':
597 return "_intlist('%s')" % "\0".join('%d' % int(a) for a in s)
602 return "_intlist('%s')" % "\0".join('%d' % int(a) for a in s)
598 elif t == 's':
603 elif t == 's':
599 return "_list(%s)" % _quote("\0".join(s))
604 return "_list(%s)" % _quote("\0".join(s))
600 elif t == 'n':
605 elif t == 'n':
601 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s)
606 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s)
602 elif t == 'b':
607 elif t == 'b':
603 try:
608 try:
604 return "_list('%s')" % "\0".join(a.branch() for a in s)
609 return "_list('%s')" % "\0".join(a.branch() for a in s)
605 except AttributeError:
610 except AttributeError:
606 raise TypeError
611 raise TypeError
607
612
608 m = l // 2
613 m = l // 2
609 return '(%s or %s)' % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t))
614 return '(%s or %s)' % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t))
610
615
611 def _formatparamexp(args, t):
616 def _formatparamexp(args, t):
612 return ', '.join(_formatargtype(t, a) for a in args)
617 return ', '.join(_formatargtype(t, a) for a in args)
613
618
614 _formatlistfuncs = {
619 _formatlistfuncs = {
615 'l': _formatlistexp,
620 'l': _formatlistexp,
616 'p': _formatparamexp,
621 'p': _formatparamexp,
617 }
622 }
618
623
619 def formatspec(expr, *args):
624 def formatspec(expr, *args):
620 '''
625 '''
621 This is a convenience function for using revsets internally, and
626 This is a convenience function for using revsets internally, and
622 escapes arguments appropriately. Aliases are intentionally ignored
627 escapes arguments appropriately. Aliases are intentionally ignored
623 so that intended expression behavior isn't accidentally subverted.
628 so that intended expression behavior isn't accidentally subverted.
624
629
625 Supported arguments:
630 Supported arguments:
626
631
627 %r = revset expression, parenthesized
632 %r = revset expression, parenthesized
628 %d = int(arg), no quoting
633 %d = int(arg), no quoting
629 %s = string(arg), escaped and single-quoted
634 %s = string(arg), escaped and single-quoted
630 %b = arg.branch(), escaped and single-quoted
635 %b = arg.branch(), escaped and single-quoted
631 %n = hex(arg), single-quoted
636 %n = hex(arg), single-quoted
632 %% = a literal '%'
637 %% = a literal '%'
633
638
634 Prefixing the type with 'l' specifies a parenthesized list of that type,
639 Prefixing the type with 'l' specifies a parenthesized list of that type,
635 and 'p' specifies a list of function parameters of that type.
640 and 'p' specifies a list of function parameters of that type.
636
641
637 >>> formatspec(b'%r:: and %lr', b'10 or 11', (b"this()", b"that()"))
642 >>> formatspec(b'%r:: and %lr', b'10 or 11', (b"this()", b"that()"))
638 '(10 or 11):: and ((this()) or (that()))'
643 '(10 or 11):: and ((this()) or (that()))'
639 >>> formatspec(b'%d:: and not %d::', 10, 20)
644 >>> formatspec(b'%d:: and not %d::', 10, 20)
640 '10:: and not 20::'
645 '10:: and not 20::'
641 >>> formatspec(b'%ld or %ld', [], [1])
646 >>> formatspec(b'%ld or %ld', [], [1])
642 "_list('') or 1"
647 "_list('') or 1"
643 >>> formatspec(b'keyword(%s)', b'foo\\xe9')
648 >>> formatspec(b'keyword(%s)', b'foo\\xe9')
644 "keyword('foo\\\\xe9')"
649 "keyword('foo\\\\xe9')"
645 >>> b = lambda: b'default'
650 >>> b = lambda: b'default'
646 >>> b.branch = b
651 >>> b.branch = b
647 >>> formatspec(b'branch(%b)', b)
652 >>> formatspec(b'branch(%b)', b)
648 "branch('default')"
653 "branch('default')"
649 >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd'])
654 >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd'])
650 "root(_list('a\\\\x00b\\\\x00c\\\\x00d'))"
655 "root(_list('a\\\\x00b\\\\x00c\\\\x00d'))"
651 >>> formatspec(b'sort(%r, %ps)', b':', [b'desc', b'user'])
656 >>> formatspec(b'sort(%r, %ps)', b':', [b'desc', b'user'])
652 "sort((:), 'desc', 'user')"
657 "sort((:), 'desc', 'user')"
653 >>> formatspec(b'%ls', [b'a', b"'"])
658 >>> formatspec(b'%ls', [b'a', b"'"])
654 "_list('a\\\\x00\\\\'')"
659 "_list('a\\\\x00\\\\'')"
655 '''
660 '''
656 expr = pycompat.bytestr(expr)
661 expr = pycompat.bytestr(expr)
657 argiter = iter(args)
662 argiter = iter(args)
658 ret = []
663 ret = []
659 pos = 0
664 pos = 0
660 while pos < len(expr):
665 while pos < len(expr):
661 q = expr.find('%', pos)
666 q = expr.find('%', pos)
662 if q < 0:
667 if q < 0:
663 ret.append(expr[pos:])
668 ret.append(expr[pos:])
664 break
669 break
665 ret.append(expr[pos:q])
670 ret.append(expr[pos:q])
666 pos = q + 1
671 pos = q + 1
667 try:
672 try:
668 d = expr[pos]
673 d = expr[pos]
669 except IndexError:
674 except IndexError:
670 raise error.ParseError(_('incomplete revspec format character'))
675 raise error.ParseError(_('incomplete revspec format character'))
671 if d == '%':
676 if d == '%':
672 ret.append(d)
677 ret.append(d)
673 pos += 1
678 pos += 1
674 continue
679 continue
675
680
676 try:
681 try:
677 arg = next(argiter)
682 arg = next(argiter)
678 except StopIteration:
683 except StopIteration:
679 raise error.ParseError(_('missing argument for revspec'))
684 raise error.ParseError(_('missing argument for revspec'))
680 f = _formatlistfuncs.get(d)
685 f = _formatlistfuncs.get(d)
681 if f:
686 if f:
682 # a list of some type
687 # a list of some type
683 pos += 1
688 pos += 1
684 try:
689 try:
685 d = expr[pos]
690 d = expr[pos]
686 except IndexError:
691 except IndexError:
687 raise error.ParseError(_('incomplete revspec format character'))
692 raise error.ParseError(_('incomplete revspec format character'))
688 try:
693 try:
689 ret.append(f(list(arg), d))
694 ret.append(f(list(arg), d))
690 except (TypeError, ValueError):
695 except (TypeError, ValueError):
691 raise error.ParseError(_('invalid argument for revspec'))
696 raise error.ParseError(_('invalid argument for revspec'))
692 else:
697 else:
693 try:
698 try:
694 ret.append(_formatargtype(d, arg))
699 ret.append(_formatargtype(d, arg))
695 except (TypeError, ValueError):
700 except (TypeError, ValueError):
696 raise error.ParseError(_('invalid argument for revspec'))
701 raise error.ParseError(_('invalid argument for revspec'))
697 pos += 1
702 pos += 1
698
703
699 try:
704 try:
700 next(argiter)
705 next(argiter)
701 raise error.ParseError(_('too many revspec arguments specified'))
706 raise error.ParseError(_('too many revspec arguments specified'))
702 except StopIteration:
707 except StopIteration:
703 pass
708 pass
704 return ''.join(ret)
709 return ''.join(ret)
705
710
706 def prettyformat(tree):
711 def prettyformat(tree):
707 return parser.prettyformat(tree, ('string', 'symbol'))
712 return parser.prettyformat(tree, ('string', 'symbol'))
708
713
709 def depth(tree):
714 def depth(tree):
710 if isinstance(tree, tuple):
715 if isinstance(tree, tuple):
711 return max(map(depth, tree)) + 1
716 return max(map(depth, tree)) + 1
712 else:
717 else:
713 return 0
718 return 0
714
719
715 def funcsused(tree):
720 def funcsused(tree):
716 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
721 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
717 return set()
722 return set()
718 else:
723 else:
719 funcs = set()
724 funcs = set()
720 for s in tree[1:]:
725 for s in tree[1:]:
721 funcs |= funcsused(s)
726 funcs |= funcsused(s)
722 if tree[0] == 'func':
727 if tree[0] == 'func':
723 funcs.add(tree[1][1])
728 funcs.add(tree[1][1])
724 return funcs
729 return funcs
725
730
726 _hashre = util.re.compile('[0-9a-fA-F]{1,40}$')
731 _hashre = util.re.compile('[0-9a-fA-F]{1,40}$')
727
732
728 def _ishashlikesymbol(symbol):
733 def _ishashlikesymbol(symbol):
729 """returns true if the symbol looks like a hash"""
734 """returns true if the symbol looks like a hash"""
730 return _hashre.match(symbol)
735 return _hashre.match(symbol)
731
736
732 def gethashlikesymbols(tree):
737 def gethashlikesymbols(tree):
733 """returns the list of symbols of the tree that look like hashes
738 """returns the list of symbols of the tree that look like hashes
734
739
735 >>> gethashlikesymbols(parse(b'3::abe3ff'))
740 >>> gethashlikesymbols(parse(b'3::abe3ff'))
736 ['3', 'abe3ff']
741 ['3', 'abe3ff']
737 >>> gethashlikesymbols(parse(b'precursors(.)'))
742 >>> gethashlikesymbols(parse(b'precursors(.)'))
738 []
743 []
739 >>> gethashlikesymbols(parse(b'precursors(34)'))
744 >>> gethashlikesymbols(parse(b'precursors(34)'))
740 ['34']
745 ['34']
741 >>> gethashlikesymbols(parse(b'abe3ffZ'))
746 >>> gethashlikesymbols(parse(b'abe3ffZ'))
742 []
747 []
743 """
748 """
744 if not tree:
749 if not tree:
745 return []
750 return []
746
751
747 if tree[0] == "symbol":
752 if tree[0] == "symbol":
748 if _ishashlikesymbol(tree[1]):
753 if _ishashlikesymbol(tree[1]):
749 return [tree[1]]
754 return [tree[1]]
750 elif len(tree) >= 3:
755 elif len(tree) >= 3:
751 results = []
756 results = []
752 for subtree in tree[1:]:
757 for subtree in tree[1:]:
753 results += gethashlikesymbols(subtree)
758 results += gethashlikesymbols(subtree)
754 return results
759 return results
755 return []
760 return []
@@ -1,259 +1,289 b''
1
1
2 $ cat >> $HGRCPATH << EOF
2 $ cat >> $HGRCPATH << EOF
3 > [ui]
3 > [ui]
4 > logtemplate="{rev}:{node|short} {desc} [{tags}]\n"
4 > logtemplate="{rev}:{node|short} {desc} [{tags}]\n"
5 > EOF
5 > EOF
6
6
7 $ hg init legacy-lookup
7 $ hg init legacy-lookup
8 $ cd legacy-lookup
8 $ cd legacy-lookup
9 $ echo a > a
9 $ echo a > a
10 $ hg add a
10 $ hg add a
11 $ hg commit -m 'first'
11 $ hg commit -m 'first'
12 $ echo aa > a
12 $ echo aa > a
13 $ hg commit -m 'second'
13 $ hg commit -m 'second'
14 $ hg log -G
14 $ hg log -G
15 @ 1:43114e71eddd second [tip]
15 @ 1:43114e71eddd second [tip]
16 |
16 |
17 o 0:a87874c6ec31 first []
17 o 0:a87874c6ec31 first []
18
18
19
19
20 Create a tag that looks like a revset
20 Create a tag that looks like a revset
21
21
22 $ hg tag 'rev(0)'
22 $ hg tag 'rev(0)'
23 $ hg log -G
23 $ hg log -G
24 @ 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd [tip]
24 @ 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd [tip]
25 |
25 |
26 o 1:43114e71eddd second [rev(0)]
26 o 1:43114e71eddd second [rev(0)]
27 |
27 |
28 o 0:a87874c6ec31 first []
28 o 0:a87874c6ec31 first []
29
29
30
30
31 See how various things are resolved
31 See how various things are resolved
32 -----------------------------------
32 -----------------------------------
33
33
34 Revision numbers
34 Revision numbers
35
35
36 $ hg log -r '0'
36 $ hg log -r '0'
37 0:a87874c6ec31 first []
37 0:a87874c6ec31 first []
38 $ hg log -r '1'
38 $ hg log -r '1'
39 1:43114e71eddd second [rev(0)]
39 1:43114e71eddd second [rev(0)]
40
40
41 "rev(x)" form (the one conflicting with the tags)
41 "rev(x)" form (the one conflicting with the tags)
42 (resolved as a label)
42 (resolved as a label)
43
43
44 $ hg log -r 'rev(0)'
44 $ hg log -r 'rev(0)'
45 1:43114e71eddd second [rev(0)]
45 1:43114e71eddd second [rev(0)]
46 $ hg log -r 'rev(1)'
46 $ hg log -r 'rev(1)'
47 1:43114e71eddd second [rev(0)]
47 1:43114e71eddd second [rev(0)]
48
48
49 same within a simple revspec
49 same within a simple revspec
50 (still resolved as the label)
50 (still resolved as the label)
51
51
52 $ hg log -r ':rev(0)'
52 $ hg log -r ':rev(0)'
53 0:a87874c6ec31 first []
53 0:a87874c6ec31 first []
54 1:43114e71eddd second [rev(0)]
54 1:43114e71eddd second [rev(0)]
55 $ hg log -r 'rev(0):'
55 $ hg log -r 'rev(0):'
56 1:43114e71eddd second [rev(0)]
56 1:43114e71eddd second [rev(0)]
57 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd [tip]
57 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd [tip]
58
58
59 within a more advances revset
59 within a more advances revset
60 (still resolved as the label)
60 (still resolved as the label)
61
61
62 $ hg log -r 'rev(0) and branch(default)'
62 $ hg log -r 'rev(0) and branch(default)'
63 0:a87874c6ec31 first []
63 0:a87874c6ec31 first []
64
64
65 with explicit revset resolution
66 (still resolved as the label)
67
68 $ hg log -r 'revset(rev(0))'
69 0:a87874c6ec31 first []
70
65 some of the above with quote to force its resolution as a label
71 some of the above with quote to force its resolution as a label
66
72
67 $ hg log -r ':"rev(0)"'
73 $ hg log -r ':"rev(0)"'
68 0:a87874c6ec31 first []
74 0:a87874c6ec31 first []
69 1:43114e71eddd second [rev(0)]
75 1:43114e71eddd second [rev(0)]
70 $ hg log -r '"rev(0)":'
76 $ hg log -r '"rev(0)":'
71 1:43114e71eddd second [rev(0)]
77 1:43114e71eddd second [rev(0)]
72 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd [tip]
78 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd [tip]
73 $ hg log -r '"rev(0)" and branch(default)'
79 $ hg log -r '"rev(0)" and branch(default)'
74 1:43114e71eddd second [rev(0)]
80 1:43114e71eddd second [rev(0)]
75
81
76 confusing bits within parents
82 confusing bits within parents
77
83
78 $ hg log -r '(rev(0))'
84 $ hg log -r '(rev(0))'
79 0:a87874c6ec31 first []
85 0:a87874c6ec31 first []
80 $ hg log -r '( rev(0))'
86 $ hg log -r '( rev(0))'
81 0:a87874c6ec31 first []
87 0:a87874c6ec31 first []
82 $ hg log -r '("rev(0)")'
88 $ hg log -r '("rev(0)")'
83 1:43114e71eddd second [rev(0)]
89 1:43114e71eddd second [rev(0)]
84
90
85 Test label with quote in them.
91 Test label with quote in them.
86
92
87 $ hg tag '"foo"'
93 $ hg tag '"foo"'
88
94
89 $ hg log -r '"foo"'
95 $ hg log -r '"foo"'
90 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
96 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
91 $ hg log -r '("foo")'
97 $ hg log -r '("foo")'
92 abort: unknown revision 'foo'!
98 abort: unknown revision 'foo'!
93 [255]
99 [255]
100 $ hg log -r 'revset("foo")'
101 abort: unknown revision 'foo'!
102 [255]
94 $ hg log -r '("\"foo\"")'
103 $ hg log -r '("\"foo\"")'
95 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
104 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
105 $ hg log -r 'revset("\"foo\"")'
106 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
96
107
97 Test label with dash in them.
108 Test label with dash in them.
98
109
99 $ hg tag 'foo-bar'
110 $ hg tag 'foo-bar'
100
111
101 $ hg log -r 'foo-bar'
112 $ hg log -r 'foo-bar'
102 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
113 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
103 $ hg log -r '(foo-bar)'
114 $ hg log -r '(foo-bar)'
104 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
115 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
105 $ hg log -r '"foo-bar"'
116 $ hg log -r '"foo-bar"'
106 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
117 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
107 $ hg log -r '("foo-bar")'
118 $ hg log -r '("foo-bar")'
108 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
119 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
109
120
110 Test label with + in them.
121 Test label with + in them.
111
122
112 $ hg tag 'foo+bar'
123 $ hg tag 'foo+bar'
113
124
114 $ hg log -r 'foo+bar'
125 $ hg log -r 'foo+bar'
115 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
126 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
116 $ hg log -r '(foo+bar)'
127 $ hg log -r '(foo+bar)'
117 abort: unknown revision 'foo'!
128 abort: unknown revision 'foo'!
118 [255]
129 [255]
130 $ hg log -r 'revset(foo+bar)'
131 abort: unknown revision 'foo'!
132 [255]
119 $ hg log -r '"foo+bar"'
133 $ hg log -r '"foo+bar"'
120 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
134 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
121 $ hg log -r '("foo+bar")'
135 $ hg log -r '("foo+bar")'
122 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
136 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
123
137
124 Test tag with numeric version number.
138 Test tag with numeric version number.
125
139
126 $ hg tag '1.2'
140 $ hg tag '1.2'
127
141
128 $ hg log -r '1.2'
142 $ hg log -r '1.2'
129 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
143 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
130 $ hg log -r '(1.2)'
144 $ hg log -r '(1.2)'
131 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
145 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
146 $ hg log -r 'revset(1.2)'
147 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
132 $ hg log -r '"1.2"'
148 $ hg log -r '"1.2"'
133 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
149 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
134 $ hg log -r '("1.2")'
150 $ hg log -r '("1.2")'
135 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
151 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
136 $ hg log -r '::"1.2"'
152 $ hg log -r '::"1.2"'
137 0:a87874c6ec31 first []
153 0:a87874c6ec31 first []
138 1:43114e71eddd second [rev(0)]
154 1:43114e71eddd second [rev(0)]
139 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
155 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
140 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
156 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
141 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
157 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
142 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
158 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
143 $ hg log -r '::1.2'
159 $ hg log -r '::1.2'
144 0:a87874c6ec31 first []
160 0:a87874c6ec31 first []
145 1:43114e71eddd second [rev(0)]
161 1:43114e71eddd second [rev(0)]
146 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
162 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
147 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
163 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
148 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
164 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
149 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
165 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
150
166
151 Test tag with parenthesis (but not a valid revset)
167 Test tag with parenthesis (but not a valid revset)
152
168
153 $ hg tag 'release_4.1(candidate1)'
169 $ hg tag 'release_4.1(candidate1)'
154
170
155 $ hg log -r 'release_4.1(candidate1)'
171 $ hg log -r 'release_4.1(candidate1)'
156 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
172 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
157 $ hg log -r '(release_4.1(candidate1))'
173 $ hg log -r '(release_4.1(candidate1))'
158 hg: parse error: unknown identifier: release_4.1
174 hg: parse error: unknown identifier: release_4.1
159 [255]
175 [255]
176 $ hg log -r 'revset(release_4.1(candidate1))'
177 hg: parse error: unknown identifier: release_4.1
178 [255]
160 $ hg log -r '"release_4.1(candidate1)"'
179 $ hg log -r '"release_4.1(candidate1)"'
161 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
180 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
162 $ hg log -r '("release_4.1(candidate1)")'
181 $ hg log -r '("release_4.1(candidate1)")'
163 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
182 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
164 $ hg log -r '::"release_4.1(candidate1)"'
183 $ hg log -r '::"release_4.1(candidate1)"'
165 0:a87874c6ec31 first []
184 0:a87874c6ec31 first []
166 1:43114e71eddd second [rev(0)]
185 1:43114e71eddd second [rev(0)]
167 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
186 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
168 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
187 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
169 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
188 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
170 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
189 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
171 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
190 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
172 $ hg log -r '::release_4.1(candidate1)'
191 $ hg log -r '::release_4.1(candidate1)'
173 hg: parse error: unknown identifier: release_4.1
192 hg: parse error: unknown identifier: release_4.1
174 [255]
193 [255]
175
194
176 Test tag with parenthesis and other function like char
195 Test tag with parenthesis and other function like char
177
196
178 $ hg tag 'release_4.1(arch=x86,arm)'
197 $ hg tag 'release_4.1(arch=x86,arm)'
179
198
180 $ hg log -r 'release_4.1(arch=x86,arm)'
199 $ hg log -r 'release_4.1(arch=x86,arm)'
181 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
200 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
182 $ hg log -r '(release_4.1(arch=x86,arm))'
201 $ hg log -r '(release_4.1(arch=x86,arm))'
183 hg: parse error: unknown identifier: release_4.1
202 hg: parse error: unknown identifier: release_4.1
184 [255]
203 [255]
204 $ hg log -r 'revset(release_4.1(arch=x86,arm))'
205 hg: parse error: unknown identifier: release_4.1
206 [255]
185 $ hg log -r '"release_4.1(arch=x86,arm)"'
207 $ hg log -r '"release_4.1(arch=x86,arm)"'
186 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
208 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
187 $ hg log -r '("release_4.1(arch=x86,arm)")'
209 $ hg log -r '("release_4.1(arch=x86,arm)")'
188 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
210 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
189 $ hg log -r '::"release_4.1(arch=x86,arm)"'
211 $ hg log -r '::"release_4.1(arch=x86,arm)"'
190 0:a87874c6ec31 first []
212 0:a87874c6ec31 first []
191 1:43114e71eddd second [rev(0)]
213 1:43114e71eddd second [rev(0)]
192 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
214 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
193 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
215 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
194 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
216 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
195 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
217 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
196 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
218 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
197 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
219 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
198 $ hg log -r '::release_4.1(arch=x86,arm)'
220 $ hg log -r '::release_4.1(arch=x86,arm)'
199 hg: parse error: unknown identifier: release_4.1
221 hg: parse error: unknown identifier: release_4.1
200 [255]
222 [255]
201
223
202 Test tag conflicting with revset function
224 Test tag conflicting with revset function
203
225
204 $ hg tag 'secret(team=foo,project=bar)'
226 $ hg tag 'secret(team=foo,project=bar)'
205
227
206 $ hg log -r 'secret(team=foo,project=bar)'
228 $ hg log -r 'secret(team=foo,project=bar)'
207 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)]
229 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)]
208 $ hg log -r '(secret(team=foo,project=bar))'
230 $ hg log -r '(secret(team=foo,project=bar))'
209 hg: parse error: secret takes no arguments
231 hg: parse error: secret takes no arguments
210 [255]
232 [255]
233 $ hg log -r 'revset(secret(team=foo,project=bar))'
234 hg: parse error: secret takes no arguments
235 [255]
211 $ hg log -r '"secret(team=foo,project=bar)"'
236 $ hg log -r '"secret(team=foo,project=bar)"'
212 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)]
237 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)]
213 $ hg log -r '("secret(team=foo,project=bar)")'
238 $ hg log -r '("secret(team=foo,project=bar)")'
214 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)]
239 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)]
215 $ hg log -r '::"secret(team=foo,project=bar)"'
240 $ hg log -r '::"secret(team=foo,project=bar)"'
216 0:a87874c6ec31 first []
241 0:a87874c6ec31 first []
217 1:43114e71eddd second [rev(0)]
242 1:43114e71eddd second [rev(0)]
218 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
243 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
219 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
244 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
220 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
245 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
221 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
246 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
222 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
247 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
223 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
248 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
224 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)]
249 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)]
225 $ hg log -r '::secret(team=foo,project=bar)'
250 $ hg log -r '::secret(team=foo,project=bar)'
226 hg: parse error: secret takes no arguments
251 hg: parse error: secret takes no arguments
227 [255]
252 [255]
228
253
229 Test tag with space
254 Test tag with space
230
255
231 $ hg tag 'my little version'
256 $ hg tag 'my little version'
232
257
233 $ hg log -r 'my little version'
258 $ hg log -r 'my little version'
234 9:269192bf8fc3 Added tag secret(team=foo,project=bar) for changeset 6b2e2d4ea455 [my little version]
259 9:269192bf8fc3 Added tag secret(team=foo,project=bar) for changeset 6b2e2d4ea455 [my little version]
235 $ hg log -r '(my little version)'
260 $ hg log -r '(my little version)'
236 hg: parse error at 4: unexpected token: symbol
261 hg: parse error at 4: unexpected token: symbol
237 ((my little version)
262 ((my little version)
238 ^ here)
263 ^ here)
239 [255]
264 [255]
265 $ hg log -r 'revset(my little version)'
266 hg: parse error at 10: unexpected token: symbol
267 (revset(my little version)
268 ^ here)
269 [255]
240 $ hg log -r '"my little version"'
270 $ hg log -r '"my little version"'
241 9:269192bf8fc3 Added tag secret(team=foo,project=bar) for changeset 6b2e2d4ea455 [my little version]
271 9:269192bf8fc3 Added tag secret(team=foo,project=bar) for changeset 6b2e2d4ea455 [my little version]
242 $ hg log -r '("my little version")'
272 $ hg log -r '("my little version")'
243 9:269192bf8fc3 Added tag secret(team=foo,project=bar) for changeset 6b2e2d4ea455 [my little version]
273 9:269192bf8fc3 Added tag secret(team=foo,project=bar) for changeset 6b2e2d4ea455 [my little version]
244 $ hg log -r '::"my little version"'
274 $ hg log -r '::"my little version"'
245 0:a87874c6ec31 first []
275 0:a87874c6ec31 first []
246 1:43114e71eddd second [rev(0)]
276 1:43114e71eddd second [rev(0)]
247 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
277 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
248 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
278 3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
249 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
279 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
250 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
280 5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
251 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
281 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)]
252 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
282 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)]
253 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)]
283 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)]
254 9:269192bf8fc3 Added tag secret(team=foo,project=bar) for changeset 6b2e2d4ea455 [my little version]
284 9:269192bf8fc3 Added tag secret(team=foo,project=bar) for changeset 6b2e2d4ea455 [my little version]
255 $ hg log -r '::my little version'
285 $ hg log -r '::my little version'
256 hg: parse error at 5: invalid token
286 hg: parse error at 5: invalid token
257 (::my little version
287 (::my little version
258 ^ here)
288 ^ here)
259 [255]
289 [255]
@@ -1,2803 +1,2843 b''
1 $ HGENCODING=utf-8
1 $ HGENCODING=utf-8
2 $ export HGENCODING
2 $ export HGENCODING
3 $ cat > testrevset.py << EOF
3 $ cat > testrevset.py << EOF
4 > import mercurial.revset
4 > import mercurial.revset
5 >
5 >
6 > baseset = mercurial.revset.baseset
6 > baseset = mercurial.revset.baseset
7 >
7 >
8 > def r3232(repo, subset, x):
8 > def r3232(repo, subset, x):
9 > """"simple revset that return [3,2,3,2]
9 > """"simple revset that return [3,2,3,2]
10 >
10 >
11 > revisions duplicated on purpose.
11 > revisions duplicated on purpose.
12 > """
12 > """
13 > if 3 not in subset:
13 > if 3 not in subset:
14 > if 2 in subset:
14 > if 2 in subset:
15 > return baseset([2,2])
15 > return baseset([2,2])
16 > return baseset()
16 > return baseset()
17 > return baseset([3,3,2,2])
17 > return baseset([3,3,2,2])
18 >
18 >
19 > mercurial.revset.symbols[b'r3232'] = r3232
19 > mercurial.revset.symbols[b'r3232'] = r3232
20 > EOF
20 > EOF
21 $ cat >> $HGRCPATH << EOF
21 $ cat >> $HGRCPATH << EOF
22 > [extensions]
22 > [extensions]
23 > drawdag=$TESTDIR/drawdag.py
23 > drawdag=$TESTDIR/drawdag.py
24 > testrevset=$TESTTMP/testrevset.py
24 > testrevset=$TESTTMP/testrevset.py
25 > EOF
25 > EOF
26
26
27 $ try() {
27 $ try() {
28 > hg debugrevspec --debug "$@"
28 > hg debugrevspec --debug "$@"
29 > }
29 > }
30
30
31 $ log() {
31 $ log() {
32 > hg log --template '{rev}\n' -r "$1"
32 > hg log --template '{rev}\n' -r "$1"
33 > }
33 > }
34
34
35 extension to build '_intlist()' and '_hexlist()', which is necessary because
35 extension to build '_intlist()' and '_hexlist()', which is necessary because
36 these predicates use '\0' as a separator:
36 these predicates use '\0' as a separator:
37
37
38 $ cat <<EOF > debugrevlistspec.py
38 $ cat <<EOF > debugrevlistspec.py
39 > from __future__ import absolute_import
39 > from __future__ import absolute_import
40 > from mercurial import (
40 > from mercurial import (
41 > node as nodemod,
41 > node as nodemod,
42 > registrar,
42 > registrar,
43 > revset,
43 > revset,
44 > revsetlang,
44 > revsetlang,
45 > smartset,
45 > smartset,
46 > )
46 > )
47 > cmdtable = {}
47 > cmdtable = {}
48 > command = registrar.command(cmdtable)
48 > command = registrar.command(cmdtable)
49 > @command(b'debugrevlistspec',
49 > @command(b'debugrevlistspec',
50 > [(b'', b'optimize', None, b'print parsed tree after optimizing'),
50 > [(b'', b'optimize', None, b'print parsed tree after optimizing'),
51 > (b'', b'bin', None, b'unhexlify arguments')])
51 > (b'', b'bin', None, b'unhexlify arguments')])
52 > def debugrevlistspec(ui, repo, fmt, *args, **opts):
52 > def debugrevlistspec(ui, repo, fmt, *args, **opts):
53 > if opts['bin']:
53 > if opts['bin']:
54 > args = map(nodemod.bin, args)
54 > args = map(nodemod.bin, args)
55 > expr = revsetlang.formatspec(fmt, list(args))
55 > expr = revsetlang.formatspec(fmt, list(args))
56 > if ui.verbose:
56 > if ui.verbose:
57 > tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
57 > tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
58 > ui.note(revsetlang.prettyformat(tree), b"\n")
58 > ui.note(revsetlang.prettyformat(tree), b"\n")
59 > if opts["optimize"]:
59 > if opts["optimize"]:
60 > opttree = revsetlang.optimize(revsetlang.analyze(tree))
60 > opttree = revsetlang.optimize(revsetlang.analyze(tree))
61 > ui.note(b"* optimized:\n", revsetlang.prettyformat(opttree),
61 > ui.note(b"* optimized:\n", revsetlang.prettyformat(opttree),
62 > b"\n")
62 > b"\n")
63 > func = revset.match(ui, expr, lookup=revset.lookupfn(repo))
63 > func = revset.match(ui, expr, lookup=revset.lookupfn(repo))
64 > revs = func(repo)
64 > revs = func(repo)
65 > if ui.verbose:
65 > if ui.verbose:
66 > ui.note(b"* set:\n", smartset.prettyformat(revs), b"\n")
66 > ui.note(b"* set:\n", smartset.prettyformat(revs), b"\n")
67 > for c in revs:
67 > for c in revs:
68 > ui.write(b"%d\n" % c)
68 > ui.write(b"%d\n" % c)
69 > EOF
69 > EOF
70 $ cat <<EOF >> $HGRCPATH
70 $ cat <<EOF >> $HGRCPATH
71 > [extensions]
71 > [extensions]
72 > debugrevlistspec = $TESTTMP/debugrevlistspec.py
72 > debugrevlistspec = $TESTTMP/debugrevlistspec.py
73 > EOF
73 > EOF
74 $ trylist() {
74 $ trylist() {
75 > hg debugrevlistspec --debug "$@"
75 > hg debugrevlistspec --debug "$@"
76 > }
76 > }
77
77
78 $ hg init repo
78 $ hg init repo
79 $ cd repo
79 $ cd repo
80
80
81 $ echo a > a
81 $ echo a > a
82 $ hg branch a
82 $ hg branch a
83 marked working directory as branch a
83 marked working directory as branch a
84 (branches are permanent and global, did you want a bookmark?)
84 (branches are permanent and global, did you want a bookmark?)
85 $ hg ci -Aqm0
85 $ hg ci -Aqm0
86
86
87 $ echo b > b
87 $ echo b > b
88 $ hg branch b
88 $ hg branch b
89 marked working directory as branch b
89 marked working directory as branch b
90 $ hg ci -Aqm1
90 $ hg ci -Aqm1
91
91
92 $ rm a
92 $ rm a
93 $ hg branch a-b-c-
93 $ hg branch a-b-c-
94 marked working directory as branch a-b-c-
94 marked working directory as branch a-b-c-
95 $ hg ci -Aqm2 -u Bob
95 $ hg ci -Aqm2 -u Bob
96
96
97 $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
97 $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
98 2
98 2
99 $ hg log -r "extra('branch')" --template '{rev}\n'
99 $ hg log -r "extra('branch')" --template '{rev}\n'
100 0
100 0
101 1
101 1
102 2
102 2
103 $ hg log -r "extra('branch', 're:a')" --template '{rev} {branch}\n'
103 $ hg log -r "extra('branch', 're:a')" --template '{rev} {branch}\n'
104 0 a
104 0 a
105 2 a-b-c-
105 2 a-b-c-
106
106
107 $ hg co 1
107 $ hg co 1
108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 $ hg branch +a+b+c+
109 $ hg branch +a+b+c+
110 marked working directory as branch +a+b+c+
110 marked working directory as branch +a+b+c+
111 $ hg ci -Aqm3
111 $ hg ci -Aqm3
112
112
113 $ hg co 2 # interleave
113 $ hg co 2 # interleave
114 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
114 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
115 $ echo bb > b
115 $ echo bb > b
116 $ hg branch -- -a-b-c-
116 $ hg branch -- -a-b-c-
117 marked working directory as branch -a-b-c-
117 marked working directory as branch -a-b-c-
118 $ hg ci -Aqm4 -d "May 12 2005"
118 $ hg ci -Aqm4 -d "May 12 2005"
119
119
120 $ hg co 3
120 $ hg co 3
121 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
122 $ hg branch !a/b/c/
122 $ hg branch !a/b/c/
123 marked working directory as branch !a/b/c/
123 marked working directory as branch !a/b/c/
124 $ hg ci -Aqm"5 bug"
124 $ hg ci -Aqm"5 bug"
125
125
126 $ hg merge 4
126 $ hg merge 4
127 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
127 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
128 (branch merge, don't forget to commit)
128 (branch merge, don't forget to commit)
129 $ hg branch _a_b_c_
129 $ hg branch _a_b_c_
130 marked working directory as branch _a_b_c_
130 marked working directory as branch _a_b_c_
131 $ hg ci -Aqm"6 issue619"
131 $ hg ci -Aqm"6 issue619"
132
132
133 $ hg branch .a.b.c.
133 $ hg branch .a.b.c.
134 marked working directory as branch .a.b.c.
134 marked working directory as branch .a.b.c.
135 $ hg ci -Aqm7
135 $ hg ci -Aqm7
136
136
137 $ hg branch all
137 $ hg branch all
138 marked working directory as branch all
138 marked working directory as branch all
139
139
140 $ hg co 4
140 $ hg co 4
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 $ hg branch Γ©
142 $ hg branch Γ©
143 marked working directory as branch \xc3\xa9 (esc)
143 marked working directory as branch \xc3\xa9 (esc)
144 $ hg ci -Aqm9
144 $ hg ci -Aqm9
145
145
146 $ hg tag -r6 1.0
146 $ hg tag -r6 1.0
147 $ hg bookmark -r6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
147 $ hg bookmark -r6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
148
148
149 $ hg clone --quiet -U -r 7 . ../remote1
149 $ hg clone --quiet -U -r 7 . ../remote1
150 $ hg clone --quiet -U -r 8 . ../remote2
150 $ hg clone --quiet -U -r 8 . ../remote2
151 $ echo "[paths]" >> .hg/hgrc
151 $ echo "[paths]" >> .hg/hgrc
152 $ echo "default = ../remote1" >> .hg/hgrc
152 $ echo "default = ../remote1" >> .hg/hgrc
153
153
154 trivial
154 trivial
155
155
156 $ try 0:1
156 $ try 0:1
157 (range
157 (range
158 (symbol '0')
158 (symbol '0')
159 (symbol '1'))
159 (symbol '1'))
160 * set:
160 * set:
161 <spanset+ 0:2>
161 <spanset+ 0:2>
162 0
162 0
163 1
163 1
164 $ try --optimize :
164 $ try --optimize :
165 (rangeall
165 (rangeall
166 None)
166 None)
167 * optimized:
167 * optimized:
168 (rangeall
168 (rangeall
169 None)
169 None)
170 * set:
170 * set:
171 <spanset+ 0:10>
171 <spanset+ 0:10>
172 0
172 0
173 1
173 1
174 2
174 2
175 3
175 3
176 4
176 4
177 5
177 5
178 6
178 6
179 7
179 7
180 8
180 8
181 9
181 9
182 $ try 3::6
182 $ try 3::6
183 (dagrange
183 (dagrange
184 (symbol '3')
184 (symbol '3')
185 (symbol '6'))
185 (symbol '6'))
186 * set:
186 * set:
187 <baseset+ [3, 5, 6]>
187 <baseset+ [3, 5, 6]>
188 3
188 3
189 5
189 5
190 6
190 6
191 $ try '0|1|2'
191 $ try '0|1|2'
192 (or
192 (or
193 (list
193 (list
194 (symbol '0')
194 (symbol '0')
195 (symbol '1')
195 (symbol '1')
196 (symbol '2')))
196 (symbol '2')))
197 * set:
197 * set:
198 <baseset [0, 1, 2]>
198 <baseset [0, 1, 2]>
199 0
199 0
200 1
200 1
201 2
201 2
202
202
203 names that should work without quoting
203 names that should work without quoting
204
204
205 $ try a
205 $ try a
206 (symbol 'a')
206 (symbol 'a')
207 * set:
207 * set:
208 <baseset [0]>
208 <baseset [0]>
209 0
209 0
210 $ try b-a
210 $ try b-a
211 (minus
211 (minus
212 (symbol 'b')
212 (symbol 'b')
213 (symbol 'a'))
213 (symbol 'a'))
214 * set:
214 * set:
215 <filteredset
215 <filteredset
216 <baseset [1]>,
216 <baseset [1]>,
217 <not
217 <not
218 <baseset [0]>>>
218 <baseset [0]>>>
219 1
219 1
220 $ try _a_b_c_
220 $ try _a_b_c_
221 (symbol '_a_b_c_')
221 (symbol '_a_b_c_')
222 * set:
222 * set:
223 <baseset [6]>
223 <baseset [6]>
224 6
224 6
225 $ try _a_b_c_-a
225 $ try _a_b_c_-a
226 (minus
226 (minus
227 (symbol '_a_b_c_')
227 (symbol '_a_b_c_')
228 (symbol 'a'))
228 (symbol 'a'))
229 * set:
229 * set:
230 <filteredset
230 <filteredset
231 <baseset [6]>,
231 <baseset [6]>,
232 <not
232 <not
233 <baseset [0]>>>
233 <baseset [0]>>>
234 6
234 6
235 $ try .a.b.c.
235 $ try .a.b.c.
236 (symbol '.a.b.c.')
236 (symbol '.a.b.c.')
237 * set:
237 * set:
238 <baseset [7]>
238 <baseset [7]>
239 7
239 7
240 $ try .a.b.c.-a
240 $ try .a.b.c.-a
241 (minus
241 (minus
242 (symbol '.a.b.c.')
242 (symbol '.a.b.c.')
243 (symbol 'a'))
243 (symbol 'a'))
244 * set:
244 * set:
245 <filteredset
245 <filteredset
246 <baseset [7]>,
246 <baseset [7]>,
247 <not
247 <not
248 <baseset [0]>>>
248 <baseset [0]>>>
249 7
249 7
250
250
251 names that should be caught by fallback mechanism
251 names that should be caught by fallback mechanism
252
252
253 $ try -- '-a-b-c-'
253 $ try -- '-a-b-c-'
254 (symbol '-a-b-c-')
254 (symbol '-a-b-c-')
255 * set:
255 * set:
256 <baseset [4]>
256 <baseset [4]>
257 4
257 4
258 $ log -a-b-c-
258 $ log -a-b-c-
259 4
259 4
260 $ try '+a+b+c+'
260 $ try '+a+b+c+'
261 (symbol '+a+b+c+')
261 (symbol '+a+b+c+')
262 * set:
262 * set:
263 <baseset [3]>
263 <baseset [3]>
264 3
264 3
265 $ try '+a+b+c+:'
265 $ try '+a+b+c+:'
266 (rangepost
266 (rangepost
267 (symbol '+a+b+c+'))
267 (symbol '+a+b+c+'))
268 * set:
268 * set:
269 <spanset+ 3:10>
269 <spanset+ 3:10>
270 3
270 3
271 4
271 4
272 5
272 5
273 6
273 6
274 7
274 7
275 8
275 8
276 9
276 9
277 $ try ':+a+b+c+'
277 $ try ':+a+b+c+'
278 (rangepre
278 (rangepre
279 (symbol '+a+b+c+'))
279 (symbol '+a+b+c+'))
280 * set:
280 * set:
281 <spanset+ 0:4>
281 <spanset+ 0:4>
282 0
282 0
283 1
283 1
284 2
284 2
285 3
285 3
286 $ try -- '-a-b-c-:+a+b+c+'
286 $ try -- '-a-b-c-:+a+b+c+'
287 (range
287 (range
288 (symbol '-a-b-c-')
288 (symbol '-a-b-c-')
289 (symbol '+a+b+c+'))
289 (symbol '+a+b+c+'))
290 * set:
290 * set:
291 <spanset- 3:5>
291 <spanset- 3:5>
292 4
292 4
293 3
293 3
294 $ log '-a-b-c-:+a+b+c+'
294 $ log '-a-b-c-:+a+b+c+'
295 4
295 4
296 3
296 3
297
297
298 $ try -- -a-b-c--a # complains
298 $ try -- -a-b-c--a # complains
299 (minus
299 (minus
300 (minus
300 (minus
301 (minus
301 (minus
302 (negate
302 (negate
303 (symbol 'a'))
303 (symbol 'a'))
304 (symbol 'b'))
304 (symbol 'b'))
305 (symbol 'c'))
305 (symbol 'c'))
306 (negate
306 (negate
307 (symbol 'a')))
307 (symbol 'a')))
308 abort: unknown revision '-a'!
308 abort: unknown revision '-a'!
309 [255]
309 [255]
310 $ try Γ©
310 $ try Γ©
311 (symbol '\xc3\xa9')
311 (symbol '\xc3\xa9')
312 * set:
312 * set:
313 <baseset [9]>
313 <baseset [9]>
314 9
314 9
315
315
316 no quoting needed
316 no quoting needed
317
317
318 $ log ::a-b-c-
318 $ log ::a-b-c-
319 0
319 0
320 1
320 1
321 2
321 2
322
322
323 quoting needed
323 quoting needed
324
324
325 $ try '"-a-b-c-"-a'
325 $ try '"-a-b-c-"-a'
326 (minus
326 (minus
327 (string '-a-b-c-')
327 (string '-a-b-c-')
328 (symbol 'a'))
328 (symbol 'a'))
329 * set:
329 * set:
330 <filteredset
330 <filteredset
331 <baseset [4]>,
331 <baseset [4]>,
332 <not
332 <not
333 <baseset [0]>>>
333 <baseset [0]>>>
334 4
334 4
335
335
336 $ log '1 or 2'
336 $ log '1 or 2'
337 1
337 1
338 2
338 2
339 $ log '1|2'
339 $ log '1|2'
340 1
340 1
341 2
341 2
342 $ log '1 and 2'
342 $ log '1 and 2'
343 $ log '1&2'
343 $ log '1&2'
344 $ try '1&2|3' # precedence - and is higher
344 $ try '1&2|3' # precedence - and is higher
345 (or
345 (or
346 (list
346 (list
347 (and
347 (and
348 (symbol '1')
348 (symbol '1')
349 (symbol '2'))
349 (symbol '2'))
350 (symbol '3')))
350 (symbol '3')))
351 * set:
351 * set:
352 <addset
352 <addset
353 <baseset []>,
353 <baseset []>,
354 <baseset [3]>>
354 <baseset [3]>>
355 3
355 3
356 $ try '1|2&3'
356 $ try '1|2&3'
357 (or
357 (or
358 (list
358 (list
359 (symbol '1')
359 (symbol '1')
360 (and
360 (and
361 (symbol '2')
361 (symbol '2')
362 (symbol '3'))))
362 (symbol '3'))))
363 * set:
363 * set:
364 <addset
364 <addset
365 <baseset [1]>,
365 <baseset [1]>,
366 <baseset []>>
366 <baseset []>>
367 1
367 1
368 $ try '1&2&3' # associativity
368 $ try '1&2&3' # associativity
369 (and
369 (and
370 (and
370 (and
371 (symbol '1')
371 (symbol '1')
372 (symbol '2'))
372 (symbol '2'))
373 (symbol '3'))
373 (symbol '3'))
374 * set:
374 * set:
375 <baseset []>
375 <baseset []>
376 $ try '1|(2|3)'
376 $ try '1|(2|3)'
377 (or
377 (or
378 (list
378 (list
379 (symbol '1')
379 (symbol '1')
380 (group
380 (group
381 (or
381 (or
382 (list
382 (list
383 (symbol '2')
383 (symbol '2')
384 (symbol '3'))))))
384 (symbol '3'))))))
385 * set:
385 * set:
386 <addset
386 <addset
387 <baseset [1]>,
387 <baseset [1]>,
388 <baseset [2, 3]>>
388 <baseset [2, 3]>>
389 1
389 1
390 2
390 2
391 3
391 3
392 $ log '1.0' # tag
392 $ log '1.0' # tag
393 6
393 6
394 $ log 'a' # branch
394 $ log 'a' # branch
395 0
395 0
396 $ log '2785f51ee'
396 $ log '2785f51ee'
397 0
397 0
398 $ log 'date(2005)'
398 $ log 'date(2005)'
399 4
399 4
400 $ log 'date(this is a test)'
400 $ log 'date(this is a test)'
401 hg: parse error at 10: unexpected token: symbol
401 hg: parse error at 10: unexpected token: symbol
402 (date(this is a test)
402 (date(this is a test)
403 ^ here)
403 ^ here)
404 [255]
404 [255]
405 $ log 'date()'
405 $ log 'date()'
406 hg: parse error: date requires a string
406 hg: parse error: date requires a string
407 [255]
407 [255]
408 $ log 'date'
408 $ log 'date'
409 abort: unknown revision 'date'!
409 abort: unknown revision 'date'!
410 [255]
410 [255]
411 $ log 'date('
411 $ log 'date('
412 hg: parse error at 5: not a prefix: end
412 hg: parse error at 5: not a prefix: end
413 (date(
413 (date(
414 ^ here)
414 ^ here)
415 [255]
415 [255]
416 $ log 'date("\xy")'
416 $ log 'date("\xy")'
417 hg: parse error: invalid \x escape* (glob)
417 hg: parse error: invalid \x escape* (glob)
418 [255]
418 [255]
419 $ log 'date(tip)'
419 $ log 'date(tip)'
420 hg: parse error: invalid date: 'tip'
420 hg: parse error: invalid date: 'tip'
421 [255]
421 [255]
422 $ log '0:date'
422 $ log '0:date'
423 abort: unknown revision 'date'!
423 abort: unknown revision 'date'!
424 [255]
424 [255]
425 $ log '::"date"'
425 $ log '::"date"'
426 abort: unknown revision 'date'!
426 abort: unknown revision 'date'!
427 [255]
427 [255]
428 $ hg book date -r 4
428 $ hg book date -r 4
429 $ log '0:date'
429 $ log '0:date'
430 0
430 0
431 1
431 1
432 2
432 2
433 3
433 3
434 4
434 4
435 $ log '::date'
435 $ log '::date'
436 0
436 0
437 1
437 1
438 2
438 2
439 4
439 4
440 $ log '::"date"'
440 $ log '::"date"'
441 0
441 0
442 1
442 1
443 2
443 2
444 4
444 4
445 $ log 'date(2005) and 1::'
445 $ log 'date(2005) and 1::'
446 4
446 4
447 $ hg book -d date
447 $ hg book -d date
448
448
449 function name should be a symbol
449 function name should be a symbol
450
450
451 $ log '"date"(2005)'
451 $ log '"date"(2005)'
452 hg: parse error: not a symbol
452 hg: parse error: not a symbol
453 [255]
453 [255]
454
454
455 keyword arguments
455 keyword arguments
456
456
457 $ log 'extra(branch, value=a)'
457 $ log 'extra(branch, value=a)'
458 0
458 0
459
459
460 $ log 'extra(branch, a, b)'
460 $ log 'extra(branch, a, b)'
461 hg: parse error: extra takes at most 2 positional arguments
461 hg: parse error: extra takes at most 2 positional arguments
462 [255]
462 [255]
463 $ log 'extra(a, label=b)'
463 $ log 'extra(a, label=b)'
464 hg: parse error: extra got multiple values for keyword argument 'label'
464 hg: parse error: extra got multiple values for keyword argument 'label'
465 [255]
465 [255]
466 $ log 'extra(label=branch, default)'
466 $ log 'extra(label=branch, default)'
467 hg: parse error: extra got an invalid argument
467 hg: parse error: extra got an invalid argument
468 [255]
468 [255]
469 $ log 'extra(branch, foo+bar=baz)'
469 $ log 'extra(branch, foo+bar=baz)'
470 hg: parse error: extra got an invalid argument
470 hg: parse error: extra got an invalid argument
471 [255]
471 [255]
472 $ log 'extra(unknown=branch)'
472 $ log 'extra(unknown=branch)'
473 hg: parse error: extra got an unexpected keyword argument 'unknown'
473 hg: parse error: extra got an unexpected keyword argument 'unknown'
474 [255]
474 [255]
475
475
476 $ try 'foo=bar|baz'
476 $ try 'foo=bar|baz'
477 (keyvalue
477 (keyvalue
478 (symbol 'foo')
478 (symbol 'foo')
479 (or
479 (or
480 (list
480 (list
481 (symbol 'bar')
481 (symbol 'bar')
482 (symbol 'baz'))))
482 (symbol 'baz'))))
483 hg: parse error: can't use a key-value pair in this context
483 hg: parse error: can't use a key-value pair in this context
484 [255]
484 [255]
485
485
486 right-hand side should be optimized recursively
486 right-hand side should be optimized recursively
487
487
488 $ try --optimize 'foo=(not public())'
488 $ try --optimize 'foo=(not public())'
489 (keyvalue
489 (keyvalue
490 (symbol 'foo')
490 (symbol 'foo')
491 (group
491 (group
492 (not
492 (not
493 (func
493 (func
494 (symbol 'public')
494 (symbol 'public')
495 None))))
495 None))))
496 * optimized:
496 * optimized:
497 (keyvalue
497 (keyvalue
498 (symbol 'foo')
498 (symbol 'foo')
499 (func
499 (func
500 (symbol '_notpublic')
500 (symbol '_notpublic')
501 None))
501 None))
502 hg: parse error: can't use a key-value pair in this context
502 hg: parse error: can't use a key-value pair in this context
503 [255]
503 [255]
504
504
505 relation-subscript operator has the highest binding strength (as function call):
505 relation-subscript operator has the highest binding strength (as function call):
506
506
507 $ hg debugrevspec -p parsed 'tip:tip^#generations[-1]'
507 $ hg debugrevspec -p parsed 'tip:tip^#generations[-1]'
508 * parsed:
508 * parsed:
509 (range
509 (range
510 (symbol 'tip')
510 (symbol 'tip')
511 (relsubscript
511 (relsubscript
512 (parentpost
512 (parentpost
513 (symbol 'tip'))
513 (symbol 'tip'))
514 (symbol 'generations')
514 (symbol 'generations')
515 (negate
515 (negate
516 (symbol '1'))))
516 (symbol '1'))))
517 9
517 9
518 8
518 8
519 7
519 7
520 6
520 6
521 5
521 5
522 4
522 4
523
523
524 $ hg debugrevspec -p parsed --no-show-revs 'not public()#generations[0]'
524 $ hg debugrevspec -p parsed --no-show-revs 'not public()#generations[0]'
525 * parsed:
525 * parsed:
526 (not
526 (not
527 (relsubscript
527 (relsubscript
528 (func
528 (func
529 (symbol 'public')
529 (symbol 'public')
530 None)
530 None)
531 (symbol 'generations')
531 (symbol 'generations')
532 (symbol '0')))
532 (symbol '0')))
533
533
534 left-hand side of relation-subscript operator should be optimized recursively:
534 left-hand side of relation-subscript operator should be optimized recursively:
535
535
536 $ hg debugrevspec -p analyzed -p optimized --no-show-revs \
536 $ hg debugrevspec -p analyzed -p optimized --no-show-revs \
537 > '(not public())#generations[0]'
537 > '(not public())#generations[0]'
538 * analyzed:
538 * analyzed:
539 (relsubscript
539 (relsubscript
540 (not
540 (not
541 (func
541 (func
542 (symbol 'public')
542 (symbol 'public')
543 None))
543 None))
544 (symbol 'generations')
544 (symbol 'generations')
545 (symbol '0'))
545 (symbol '0'))
546 * optimized:
546 * optimized:
547 (relsubscript
547 (relsubscript
548 (func
548 (func
549 (symbol '_notpublic')
549 (symbol '_notpublic')
550 None)
550 None)
551 (symbol 'generations')
551 (symbol 'generations')
552 (symbol '0'))
552 (symbol '0'))
553
553
554 resolution of subscript and relation-subscript ternary operators:
554 resolution of subscript and relation-subscript ternary operators:
555
555
556 $ hg debugrevspec -p analyzed 'tip[0]'
556 $ hg debugrevspec -p analyzed 'tip[0]'
557 * analyzed:
557 * analyzed:
558 (subscript
558 (subscript
559 (symbol 'tip')
559 (symbol 'tip')
560 (symbol '0'))
560 (symbol '0'))
561 hg: parse error: can't use a subscript in this context
561 hg: parse error: can't use a subscript in this context
562 [255]
562 [255]
563
563
564 $ hg debugrevspec -p analyzed 'tip#rel[0]'
564 $ hg debugrevspec -p analyzed 'tip#rel[0]'
565 * analyzed:
565 * analyzed:
566 (relsubscript
566 (relsubscript
567 (symbol 'tip')
567 (symbol 'tip')
568 (symbol 'rel')
568 (symbol 'rel')
569 (symbol '0'))
569 (symbol '0'))
570 hg: parse error: unknown identifier: rel
570 hg: parse error: unknown identifier: rel
571 [255]
571 [255]
572
572
573 $ hg debugrevspec -p analyzed '(tip#rel)[0]'
573 $ hg debugrevspec -p analyzed '(tip#rel)[0]'
574 * analyzed:
574 * analyzed:
575 (subscript
575 (subscript
576 (relation
576 (relation
577 (symbol 'tip')
577 (symbol 'tip')
578 (symbol 'rel'))
578 (symbol 'rel'))
579 (symbol '0'))
579 (symbol '0'))
580 hg: parse error: can't use a subscript in this context
580 hg: parse error: can't use a subscript in this context
581 [255]
581 [255]
582
582
583 $ hg debugrevspec -p analyzed 'tip#rel[0][1]'
583 $ hg debugrevspec -p analyzed 'tip#rel[0][1]'
584 * analyzed:
584 * analyzed:
585 (subscript
585 (subscript
586 (relsubscript
586 (relsubscript
587 (symbol 'tip')
587 (symbol 'tip')
588 (symbol 'rel')
588 (symbol 'rel')
589 (symbol '0'))
589 (symbol '0'))
590 (symbol '1'))
590 (symbol '1'))
591 hg: parse error: can't use a subscript in this context
591 hg: parse error: can't use a subscript in this context
592 [255]
592 [255]
593
593
594 $ hg debugrevspec -p analyzed 'tip#rel0#rel1[1]'
594 $ hg debugrevspec -p analyzed 'tip#rel0#rel1[1]'
595 * analyzed:
595 * analyzed:
596 (relsubscript
596 (relsubscript
597 (relation
597 (relation
598 (symbol 'tip')
598 (symbol 'tip')
599 (symbol 'rel0'))
599 (symbol 'rel0'))
600 (symbol 'rel1')
600 (symbol 'rel1')
601 (symbol '1'))
601 (symbol '1'))
602 hg: parse error: unknown identifier: rel1
602 hg: parse error: unknown identifier: rel1
603 [255]
603 [255]
604
604
605 $ hg debugrevspec -p analyzed 'tip#rel0[0]#rel1[1]'
605 $ hg debugrevspec -p analyzed 'tip#rel0[0]#rel1[1]'
606 * analyzed:
606 * analyzed:
607 (relsubscript
607 (relsubscript
608 (relsubscript
608 (relsubscript
609 (symbol 'tip')
609 (symbol 'tip')
610 (symbol 'rel0')
610 (symbol 'rel0')
611 (symbol '0'))
611 (symbol '0'))
612 (symbol 'rel1')
612 (symbol 'rel1')
613 (symbol '1'))
613 (symbol '1'))
614 hg: parse error: unknown identifier: rel1
614 hg: parse error: unknown identifier: rel1
615 [255]
615 [255]
616
616
617 parse errors of relation, subscript and relation-subscript operators:
617 parse errors of relation, subscript and relation-subscript operators:
618
618
619 $ hg debugrevspec '[0]'
619 $ hg debugrevspec '[0]'
620 hg: parse error at 0: not a prefix: [
620 hg: parse error at 0: not a prefix: [
621 ([0]
621 ([0]
622 ^ here)
622 ^ here)
623 [255]
623 [255]
624 $ hg debugrevspec '.#'
624 $ hg debugrevspec '.#'
625 hg: parse error at 2: not a prefix: end
625 hg: parse error at 2: not a prefix: end
626 (.#
626 (.#
627 ^ here)
627 ^ here)
628 [255]
628 [255]
629 $ hg debugrevspec '#rel'
629 $ hg debugrevspec '#rel'
630 hg: parse error at 0: not a prefix: #
630 hg: parse error at 0: not a prefix: #
631 (#rel
631 (#rel
632 ^ here)
632 ^ here)
633 [255]
633 [255]
634 $ hg debugrevspec '.#rel[0'
634 $ hg debugrevspec '.#rel[0'
635 hg: parse error at 7: unexpected token: end
635 hg: parse error at 7: unexpected token: end
636 (.#rel[0
636 (.#rel[0
637 ^ here)
637 ^ here)
638 [255]
638 [255]
639 $ hg debugrevspec '.]'
639 $ hg debugrevspec '.]'
640 hg: parse error at 1: invalid token
640 hg: parse error at 1: invalid token
641 (.]
641 (.]
642 ^ here)
642 ^ here)
643 [255]
643 [255]
644
644
645 $ hg debugrevspec '.#generations[a]'
645 $ hg debugrevspec '.#generations[a]'
646 hg: parse error: relation subscript must be an integer
646 hg: parse error: relation subscript must be an integer
647 [255]
647 [255]
648 $ hg debugrevspec '.#generations[1-2]'
648 $ hg debugrevspec '.#generations[1-2]'
649 hg: parse error: relation subscript must be an integer
649 hg: parse error: relation subscript must be an integer
650 [255]
650 [255]
651
651
652 parsed tree at stages:
652 parsed tree at stages:
653
653
654 $ hg debugrevspec -p all '()'
654 $ hg debugrevspec -p all '()'
655 * parsed:
655 * parsed:
656 (group
656 (group
657 None)
657 None)
658 * expanded:
658 * expanded:
659 (group
659 (group
660 None)
660 None)
661 * concatenated:
661 * concatenated:
662 (group
662 (group
663 None)
663 None)
664 * analyzed:
664 * analyzed:
665 None
665 None
666 * optimized:
666 * optimized:
667 None
667 None
668 hg: parse error: missing argument
668 hg: parse error: missing argument
669 [255]
669 [255]
670
670
671 $ hg debugrevspec --no-optimized -p all '()'
671 $ hg debugrevspec --no-optimized -p all '()'
672 * parsed:
672 * parsed:
673 (group
673 (group
674 None)
674 None)
675 * expanded:
675 * expanded:
676 (group
676 (group
677 None)
677 None)
678 * concatenated:
678 * concatenated:
679 (group
679 (group
680 None)
680 None)
681 * analyzed:
681 * analyzed:
682 None
682 None
683 hg: parse error: missing argument
683 hg: parse error: missing argument
684 [255]
684 [255]
685
685
686 $ hg debugrevspec -p parsed -p analyzed -p optimized '(0|1)-1'
686 $ hg debugrevspec -p parsed -p analyzed -p optimized '(0|1)-1'
687 * parsed:
687 * parsed:
688 (minus
688 (minus
689 (group
689 (group
690 (or
690 (or
691 (list
691 (list
692 (symbol '0')
692 (symbol '0')
693 (symbol '1'))))
693 (symbol '1'))))
694 (symbol '1'))
694 (symbol '1'))
695 * analyzed:
695 * analyzed:
696 (and
696 (and
697 (or
697 (or
698 (list
698 (list
699 (symbol '0')
699 (symbol '0')
700 (symbol '1')))
700 (symbol '1')))
701 (not
701 (not
702 (symbol '1')))
702 (symbol '1')))
703 * optimized:
703 * optimized:
704 (difference
704 (difference
705 (func
705 (func
706 (symbol '_list')
706 (symbol '_list')
707 (string '0\x001'))
707 (string '0\x001'))
708 (symbol '1'))
708 (symbol '1'))
709 0
709 0
710
710
711 $ hg debugrevspec -p unknown '0'
711 $ hg debugrevspec -p unknown '0'
712 abort: invalid stage name: unknown
712 abort: invalid stage name: unknown
713 [255]
713 [255]
714
714
715 $ hg debugrevspec -p all --optimize '0'
715 $ hg debugrevspec -p all --optimize '0'
716 abort: cannot use --optimize with --show-stage
716 abort: cannot use --optimize with --show-stage
717 [255]
717 [255]
718
718
719 verify optimized tree:
719 verify optimized tree:
720
720
721 $ hg debugrevspec --verify '0|1'
721 $ hg debugrevspec --verify '0|1'
722
722
723 $ hg debugrevspec --verify -v -p analyzed -p optimized 'r3232() & 2'
723 $ hg debugrevspec --verify -v -p analyzed -p optimized 'r3232() & 2'
724 * analyzed:
724 * analyzed:
725 (and
725 (and
726 (func
726 (func
727 (symbol 'r3232')
727 (symbol 'r3232')
728 None)
728 None)
729 (symbol '2'))
729 (symbol '2'))
730 * optimized:
730 * optimized:
731 (andsmally
731 (andsmally
732 (func
732 (func
733 (symbol 'r3232')
733 (symbol 'r3232')
734 None)
734 None)
735 (symbol '2'))
735 (symbol '2'))
736 * analyzed set:
736 * analyzed set:
737 <baseset [2]>
737 <baseset [2]>
738 * optimized set:
738 * optimized set:
739 <baseset [2, 2]>
739 <baseset [2, 2]>
740 --- analyzed
740 --- analyzed
741 +++ optimized
741 +++ optimized
742 2
742 2
743 +2
743 +2
744 [1]
744 [1]
745
745
746 $ hg debugrevspec --no-optimized --verify-optimized '0'
746 $ hg debugrevspec --no-optimized --verify-optimized '0'
747 abort: cannot use --verify-optimized with --no-optimized
747 abort: cannot use --verify-optimized with --no-optimized
748 [255]
748 [255]
749
749
750 Test that symbols only get parsed as functions if there's an opening
750 Test that symbols only get parsed as functions if there's an opening
751 parenthesis.
751 parenthesis.
752
752
753 $ hg book only -r 9
753 $ hg book only -r 9
754 $ log 'only(only)' # Outer "only" is a function, inner "only" is the bookmark
754 $ log 'only(only)' # Outer "only" is a function, inner "only" is the bookmark
755 8
755 8
756 9
756 9
757
757
758 ':y' behaves like '0:y', but can't be rewritten as such since the revision '0'
758 ':y' behaves like '0:y', but can't be rewritten as such since the revision '0'
759 may be hidden (issue5385)
759 may be hidden (issue5385)
760
760
761 $ try -p parsed -p analyzed ':'
761 $ try -p parsed -p analyzed ':'
762 * parsed:
762 * parsed:
763 (rangeall
763 (rangeall
764 None)
764 None)
765 * analyzed:
765 * analyzed:
766 (rangeall
766 (rangeall
767 None)
767 None)
768 * set:
768 * set:
769 <spanset+ 0:10>
769 <spanset+ 0:10>
770 0
770 0
771 1
771 1
772 2
772 2
773 3
773 3
774 4
774 4
775 5
775 5
776 6
776 6
777 7
777 7
778 8
778 8
779 9
779 9
780 $ try -p analyzed ':1'
780 $ try -p analyzed ':1'
781 * analyzed:
781 * analyzed:
782 (rangepre
782 (rangepre
783 (symbol '1'))
783 (symbol '1'))
784 * set:
784 * set:
785 <spanset+ 0:2>
785 <spanset+ 0:2>
786 0
786 0
787 1
787 1
788 $ try -p analyzed ':(1|2)'
788 $ try -p analyzed ':(1|2)'
789 * analyzed:
789 * analyzed:
790 (rangepre
790 (rangepre
791 (or
791 (or
792 (list
792 (list
793 (symbol '1')
793 (symbol '1')
794 (symbol '2'))))
794 (symbol '2'))))
795 * set:
795 * set:
796 <spanset+ 0:3>
796 <spanset+ 0:3>
797 0
797 0
798 1
798 1
799 2
799 2
800 $ try -p analyzed ':(1&2)'
800 $ try -p analyzed ':(1&2)'
801 * analyzed:
801 * analyzed:
802 (rangepre
802 (rangepre
803 (and
803 (and
804 (symbol '1')
804 (symbol '1')
805 (symbol '2')))
805 (symbol '2')))
806 * set:
806 * set:
807 <baseset []>
807 <baseset []>
808
808
809 infix/suffix resolution of ^ operator (issue2884, issue5764):
809 infix/suffix resolution of ^ operator (issue2884, issue5764):
810
810
811 x^:y means (x^):y
811 x^:y means (x^):y
812
812
813 $ try '1^:2'
813 $ try '1^:2'
814 (range
814 (range
815 (parentpost
815 (parentpost
816 (symbol '1'))
816 (symbol '1'))
817 (symbol '2'))
817 (symbol '2'))
818 * set:
818 * set:
819 <spanset+ 0:3>
819 <spanset+ 0:3>
820 0
820 0
821 1
821 1
822 2
822 2
823
823
824 $ try '1^::2'
824 $ try '1^::2'
825 (dagrange
825 (dagrange
826 (parentpost
826 (parentpost
827 (symbol '1'))
827 (symbol '1'))
828 (symbol '2'))
828 (symbol '2'))
829 * set:
829 * set:
830 <baseset+ [0, 1, 2]>
830 <baseset+ [0, 1, 2]>
831 0
831 0
832 1
832 1
833 2
833 2
834
834
835 $ try '1^..2'
835 $ try '1^..2'
836 (dagrange
836 (dagrange
837 (parentpost
837 (parentpost
838 (symbol '1'))
838 (symbol '1'))
839 (symbol '2'))
839 (symbol '2'))
840 * set:
840 * set:
841 <baseset+ [0, 1, 2]>
841 <baseset+ [0, 1, 2]>
842 0
842 0
843 1
843 1
844 2
844 2
845
845
846 $ try '9^:'
846 $ try '9^:'
847 (rangepost
847 (rangepost
848 (parentpost
848 (parentpost
849 (symbol '9')))
849 (symbol '9')))
850 * set:
850 * set:
851 <spanset+ 8:10>
851 <spanset+ 8:10>
852 8
852 8
853 9
853 9
854
854
855 $ try '9^::'
855 $ try '9^::'
856 (dagrangepost
856 (dagrangepost
857 (parentpost
857 (parentpost
858 (symbol '9')))
858 (symbol '9')))
859 * set:
859 * set:
860 <generatorsetasc+>
860 <generatorsetasc+>
861 8
861 8
862 9
862 9
863
863
864 $ try '9^..'
864 $ try '9^..'
865 (dagrangepost
865 (dagrangepost
866 (parentpost
866 (parentpost
867 (symbol '9')))
867 (symbol '9')))
868 * set:
868 * set:
869 <generatorsetasc+>
869 <generatorsetasc+>
870 8
870 8
871 9
871 9
872
872
873 x^:y should be resolved before omitting group operators
873 x^:y should be resolved before omitting group operators
874
874
875 $ try '1^(:2)'
875 $ try '1^(:2)'
876 (parent
876 (parent
877 (symbol '1')
877 (symbol '1')
878 (group
878 (group
879 (rangepre
879 (rangepre
880 (symbol '2'))))
880 (symbol '2'))))
881 hg: parse error: ^ expects a number 0, 1, or 2
881 hg: parse error: ^ expects a number 0, 1, or 2
882 [255]
882 [255]
883
883
884 x^:y should be resolved recursively
884 x^:y should be resolved recursively
885
885
886 $ try 'sort(1^:2)'
886 $ try 'sort(1^:2)'
887 (func
887 (func
888 (symbol 'sort')
888 (symbol 'sort')
889 (range
889 (range
890 (parentpost
890 (parentpost
891 (symbol '1'))
891 (symbol '1'))
892 (symbol '2')))
892 (symbol '2')))
893 * set:
893 * set:
894 <spanset+ 0:3>
894 <spanset+ 0:3>
895 0
895 0
896 1
896 1
897 2
897 2
898
898
899 $ try '(3^:4)^:2'
899 $ try '(3^:4)^:2'
900 (range
900 (range
901 (parentpost
901 (parentpost
902 (group
902 (group
903 (range
903 (range
904 (parentpost
904 (parentpost
905 (symbol '3'))
905 (symbol '3'))
906 (symbol '4'))))
906 (symbol '4'))))
907 (symbol '2'))
907 (symbol '2'))
908 * set:
908 * set:
909 <spanset+ 0:3>
909 <spanset+ 0:3>
910 0
910 0
911 1
911 1
912 2
912 2
913
913
914 $ try '(3^::4)^::2'
914 $ try '(3^::4)^::2'
915 (dagrange
915 (dagrange
916 (parentpost
916 (parentpost
917 (group
917 (group
918 (dagrange
918 (dagrange
919 (parentpost
919 (parentpost
920 (symbol '3'))
920 (symbol '3'))
921 (symbol '4'))))
921 (symbol '4'))))
922 (symbol '2'))
922 (symbol '2'))
923 * set:
923 * set:
924 <baseset+ [0, 1, 2]>
924 <baseset+ [0, 1, 2]>
925 0
925 0
926 1
926 1
927 2
927 2
928
928
929 $ try '(9^:)^:'
929 $ try '(9^:)^:'
930 (rangepost
930 (rangepost
931 (parentpost
931 (parentpost
932 (group
932 (group
933 (rangepost
933 (rangepost
934 (parentpost
934 (parentpost
935 (symbol '9'))))))
935 (symbol '9'))))))
936 * set:
936 * set:
937 <spanset+ 4:10>
937 <spanset+ 4:10>
938 4
938 4
939 5
939 5
940 6
940 6
941 7
941 7
942 8
942 8
943 9
943 9
944
944
945 x^ in alias should also be resolved
945 x^ in alias should also be resolved
946
946
947 $ try 'A' --config 'revsetalias.A=1^:2'
947 $ try 'A' --config 'revsetalias.A=1^:2'
948 (symbol 'A')
948 (symbol 'A')
949 * expanded:
949 * expanded:
950 (range
950 (range
951 (parentpost
951 (parentpost
952 (symbol '1'))
952 (symbol '1'))
953 (symbol '2'))
953 (symbol '2'))
954 * set:
954 * set:
955 <spanset+ 0:3>
955 <spanset+ 0:3>
956 0
956 0
957 1
957 1
958 2
958 2
959
959
960 $ try 'A:2' --config 'revsetalias.A=1^'
960 $ try 'A:2' --config 'revsetalias.A=1^'
961 (range
961 (range
962 (symbol 'A')
962 (symbol 'A')
963 (symbol '2'))
963 (symbol '2'))
964 * expanded:
964 * expanded:
965 (range
965 (range
966 (parentpost
966 (parentpost
967 (symbol '1'))
967 (symbol '1'))
968 (symbol '2'))
968 (symbol '2'))
969 * set:
969 * set:
970 <spanset+ 0:3>
970 <spanset+ 0:3>
971 0
971 0
972 1
972 1
973 2
973 2
974
974
975 but not beyond the boundary of alias expansion, because the resolution should
975 but not beyond the boundary of alias expansion, because the resolution should
976 be made at the parsing stage
976 be made at the parsing stage
977
977
978 $ try '1^A' --config 'revsetalias.A=:2'
978 $ try '1^A' --config 'revsetalias.A=:2'
979 (parent
979 (parent
980 (symbol '1')
980 (symbol '1')
981 (symbol 'A'))
981 (symbol 'A'))
982 * expanded:
982 * expanded:
983 (parent
983 (parent
984 (symbol '1')
984 (symbol '1')
985 (rangepre
985 (rangepre
986 (symbol '2')))
986 (symbol '2')))
987 hg: parse error: ^ expects a number 0, 1, or 2
987 hg: parse error: ^ expects a number 0, 1, or 2
988 [255]
988 [255]
989
989
990 '::' itself isn't a valid expression
990 '::' itself isn't a valid expression
991
991
992 $ try '::'
992 $ try '::'
993 (dagrangeall
993 (dagrangeall
994 None)
994 None)
995 hg: parse error: can't use '::' in this context
995 hg: parse error: can't use '::' in this context
996 [255]
996 [255]
997
997
998 ancestor can accept 0 or more arguments
998 ancestor can accept 0 or more arguments
999
999
1000 $ log 'ancestor()'
1000 $ log 'ancestor()'
1001 $ log 'ancestor(1)'
1001 $ log 'ancestor(1)'
1002 1
1002 1
1003 $ log 'ancestor(4,5)'
1003 $ log 'ancestor(4,5)'
1004 1
1004 1
1005 $ log 'ancestor(4,5) and 4'
1005 $ log 'ancestor(4,5) and 4'
1006 $ log 'ancestor(0,0,1,3)'
1006 $ log 'ancestor(0,0,1,3)'
1007 0
1007 0
1008 $ log 'ancestor(3,1,5,3,5,1)'
1008 $ log 'ancestor(3,1,5,3,5,1)'
1009 1
1009 1
1010 $ log 'ancestor(0,1,3,5)'
1010 $ log 'ancestor(0,1,3,5)'
1011 0
1011 0
1012 $ log 'ancestor(1,2,3,4,5)'
1012 $ log 'ancestor(1,2,3,4,5)'
1013 1
1013 1
1014
1014
1015 test ancestors
1015 test ancestors
1016
1016
1017 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
1017 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
1018 @ 9
1018 @ 9
1019 o 8
1019 o 8
1020 | o 7
1020 | o 7
1021 | o 6
1021 | o 6
1022 |/|
1022 |/|
1023 | o 5
1023 | o 5
1024 o | 4
1024 o | 4
1025 | o 3
1025 | o 3
1026 o | 2
1026 o | 2
1027 |/
1027 |/
1028 o 1
1028 o 1
1029 o 0
1029 o 0
1030
1030
1031 $ log 'ancestors(5)'
1031 $ log 'ancestors(5)'
1032 0
1032 0
1033 1
1033 1
1034 3
1034 3
1035 5
1035 5
1036 $ log 'ancestor(ancestors(5))'
1036 $ log 'ancestor(ancestors(5))'
1037 0
1037 0
1038 $ log '::r3232()'
1038 $ log '::r3232()'
1039 0
1039 0
1040 1
1040 1
1041 2
1041 2
1042 3
1042 3
1043
1043
1044 test ancestors with depth limit
1044 test ancestors with depth limit
1045
1045
1046 (depth=0 selects the node itself)
1046 (depth=0 selects the node itself)
1047
1047
1048 $ log 'reverse(ancestors(9, depth=0))'
1048 $ log 'reverse(ancestors(9, depth=0))'
1049 9
1049 9
1050
1050
1051 (interleaved: '4' would be missing if heap queue were higher depth first)
1051 (interleaved: '4' would be missing if heap queue were higher depth first)
1052
1052
1053 $ log 'reverse(ancestors(8:9, depth=1))'
1053 $ log 'reverse(ancestors(8:9, depth=1))'
1054 9
1054 9
1055 8
1055 8
1056 4
1056 4
1057
1057
1058 (interleaved: '2' would be missing if heap queue were higher depth first)
1058 (interleaved: '2' would be missing if heap queue were higher depth first)
1059
1059
1060 $ log 'reverse(ancestors(7+8, depth=2))'
1060 $ log 'reverse(ancestors(7+8, depth=2))'
1061 8
1061 8
1062 7
1062 7
1063 6
1063 6
1064 5
1064 5
1065 4
1065 4
1066 2
1066 2
1067
1067
1068 (walk example above by separate queries)
1068 (walk example above by separate queries)
1069
1069
1070 $ log 'reverse(ancestors(8, depth=2)) + reverse(ancestors(7, depth=2))'
1070 $ log 'reverse(ancestors(8, depth=2)) + reverse(ancestors(7, depth=2))'
1071 8
1071 8
1072 4
1072 4
1073 2
1073 2
1074 7
1074 7
1075 6
1075 6
1076 5
1076 5
1077
1077
1078 (walk 2nd and 3rd ancestors)
1078 (walk 2nd and 3rd ancestors)
1079
1079
1080 $ log 'reverse(ancestors(7, depth=3, startdepth=2))'
1080 $ log 'reverse(ancestors(7, depth=3, startdepth=2))'
1081 5
1081 5
1082 4
1082 4
1083 3
1083 3
1084 2
1084 2
1085
1085
1086 (interleaved: '4' would be missing if higher-depth ancestors weren't scanned)
1086 (interleaved: '4' would be missing if higher-depth ancestors weren't scanned)
1087
1087
1088 $ log 'reverse(ancestors(7+8, depth=2, startdepth=2))'
1088 $ log 'reverse(ancestors(7+8, depth=2, startdepth=2))'
1089 5
1089 5
1090 4
1090 4
1091 2
1091 2
1092
1092
1093 (note that 'ancestors(x, depth=y, startdepth=z)' does not identical to
1093 (note that 'ancestors(x, depth=y, startdepth=z)' does not identical to
1094 'ancestors(x, depth=y) - ancestors(x, depth=z-1)' because a node may have
1094 'ancestors(x, depth=y) - ancestors(x, depth=z-1)' because a node may have
1095 multiple depths)
1095 multiple depths)
1096
1096
1097 $ log 'reverse(ancestors(7+8, depth=2) - ancestors(7+8, depth=1))'
1097 $ log 'reverse(ancestors(7+8, depth=2) - ancestors(7+8, depth=1))'
1098 5
1098 5
1099 2
1099 2
1100
1100
1101 test bad arguments passed to ancestors()
1101 test bad arguments passed to ancestors()
1102
1102
1103 $ log 'ancestors(., depth=-1)'
1103 $ log 'ancestors(., depth=-1)'
1104 hg: parse error: negative depth
1104 hg: parse error: negative depth
1105 [255]
1105 [255]
1106 $ log 'ancestors(., depth=foo)'
1106 $ log 'ancestors(., depth=foo)'
1107 hg: parse error: ancestors expects an integer depth
1107 hg: parse error: ancestors expects an integer depth
1108 [255]
1108 [255]
1109
1109
1110 test descendants
1110 test descendants
1111
1111
1112 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
1112 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
1113 @ 9
1113 @ 9
1114 o 8
1114 o 8
1115 | o 7
1115 | o 7
1116 | o 6
1116 | o 6
1117 |/|
1117 |/|
1118 | o 5
1118 | o 5
1119 o | 4
1119 o | 4
1120 | o 3
1120 | o 3
1121 o | 2
1121 o | 2
1122 |/
1122 |/
1123 o 1
1123 o 1
1124 o 0
1124 o 0
1125
1125
1126 (null is ultimate root and has optimized path)
1126 (null is ultimate root and has optimized path)
1127
1127
1128 $ log 'null:4 & descendants(null)'
1128 $ log 'null:4 & descendants(null)'
1129 -1
1129 -1
1130 0
1130 0
1131 1
1131 1
1132 2
1132 2
1133 3
1133 3
1134 4
1134 4
1135
1135
1136 (including merge)
1136 (including merge)
1137
1137
1138 $ log ':8 & descendants(2)'
1138 $ log ':8 & descendants(2)'
1139 2
1139 2
1140 4
1140 4
1141 6
1141 6
1142 7
1142 7
1143 8
1143 8
1144
1144
1145 (multiple roots)
1145 (multiple roots)
1146
1146
1147 $ log ':8 & descendants(2+5)'
1147 $ log ':8 & descendants(2+5)'
1148 2
1148 2
1149 4
1149 4
1150 5
1150 5
1151 6
1151 6
1152 7
1152 7
1153 8
1153 8
1154
1154
1155 test descendants with depth limit
1155 test descendants with depth limit
1156
1156
1157 (depth=0 selects the node itself)
1157 (depth=0 selects the node itself)
1158
1158
1159 $ log 'descendants(0, depth=0)'
1159 $ log 'descendants(0, depth=0)'
1160 0
1160 0
1161 $ log 'null: & descendants(null, depth=0)'
1161 $ log 'null: & descendants(null, depth=0)'
1162 -1
1162 -1
1163
1163
1164 (p2 = null should be ignored)
1164 (p2 = null should be ignored)
1165
1165
1166 $ log 'null: & descendants(null, depth=2)'
1166 $ log 'null: & descendants(null, depth=2)'
1167 -1
1167 -1
1168 0
1168 0
1169 1
1169 1
1170
1170
1171 (multiple paths: depth(6) = (2, 3))
1171 (multiple paths: depth(6) = (2, 3))
1172
1172
1173 $ log 'descendants(1+3, depth=2)'
1173 $ log 'descendants(1+3, depth=2)'
1174 1
1174 1
1175 2
1175 2
1176 3
1176 3
1177 4
1177 4
1178 5
1178 5
1179 6
1179 6
1180
1180
1181 (multiple paths: depth(5) = (1, 2), depth(6) = (2, 3))
1181 (multiple paths: depth(5) = (1, 2), depth(6) = (2, 3))
1182
1182
1183 $ log 'descendants(3+1, depth=2, startdepth=2)'
1183 $ log 'descendants(3+1, depth=2, startdepth=2)'
1184 4
1184 4
1185 5
1185 5
1186 6
1186 6
1187
1187
1188 (multiple depths: depth(6) = (0, 2, 4), search for depth=2)
1188 (multiple depths: depth(6) = (0, 2, 4), search for depth=2)
1189
1189
1190 $ log 'descendants(0+3+6, depth=3, startdepth=1)'
1190 $ log 'descendants(0+3+6, depth=3, startdepth=1)'
1191 1
1191 1
1192 2
1192 2
1193 3
1193 3
1194 4
1194 4
1195 5
1195 5
1196 6
1196 6
1197 7
1197 7
1198
1198
1199 (multiple depths: depth(6) = (0, 4), no match)
1199 (multiple depths: depth(6) = (0, 4), no match)
1200
1200
1201 $ log 'descendants(0+6, depth=3, startdepth=1)'
1201 $ log 'descendants(0+6, depth=3, startdepth=1)'
1202 1
1202 1
1203 2
1203 2
1204 3
1204 3
1205 4
1205 4
1206 5
1206 5
1207 7
1207 7
1208
1208
1209 test ancestors/descendants relation subscript:
1209 test ancestors/descendants relation subscript:
1210
1210
1211 $ log 'tip#generations[0]'
1211 $ log 'tip#generations[0]'
1212 9
1212 9
1213 $ log '.#generations[-1]'
1213 $ log '.#generations[-1]'
1214 8
1214 8
1215 $ log '.#g[(-1)]'
1215 $ log '.#g[(-1)]'
1216 8
1216 8
1217
1217
1218 $ hg debugrevspec -p parsed 'roots(:)#g[2]'
1218 $ hg debugrevspec -p parsed 'roots(:)#g[2]'
1219 * parsed:
1219 * parsed:
1220 (relsubscript
1220 (relsubscript
1221 (func
1221 (func
1222 (symbol 'roots')
1222 (symbol 'roots')
1223 (rangeall
1223 (rangeall
1224 None))
1224 None))
1225 (symbol 'g')
1225 (symbol 'g')
1226 (symbol '2'))
1226 (symbol '2'))
1227 2
1227 2
1228 3
1228 3
1229
1229
1230 test author
1230 test author
1231
1231
1232 $ log 'author(bob)'
1232 $ log 'author(bob)'
1233 2
1233 2
1234 $ log 'author("re:bob|test")'
1234 $ log 'author("re:bob|test")'
1235 0
1235 0
1236 1
1236 1
1237 2
1237 2
1238 3
1238 3
1239 4
1239 4
1240 5
1240 5
1241 6
1241 6
1242 7
1242 7
1243 8
1243 8
1244 9
1244 9
1245 $ log 'author(r"re:\S")'
1245 $ log 'author(r"re:\S")'
1246 0
1246 0
1247 1
1247 1
1248 2
1248 2
1249 3
1249 3
1250 4
1250 4
1251 5
1251 5
1252 6
1252 6
1253 7
1253 7
1254 8
1254 8
1255 9
1255 9
1256 $ log 'branch(Γ©)'
1256 $ log 'branch(Γ©)'
1257 8
1257 8
1258 9
1258 9
1259 $ log 'branch(a)'
1259 $ log 'branch(a)'
1260 0
1260 0
1261 $ hg log -r 'branch("re:a")' --template '{rev} {branch}\n'
1261 $ hg log -r 'branch("re:a")' --template '{rev} {branch}\n'
1262 0 a
1262 0 a
1263 2 a-b-c-
1263 2 a-b-c-
1264 3 +a+b+c+
1264 3 +a+b+c+
1265 4 -a-b-c-
1265 4 -a-b-c-
1266 5 !a/b/c/
1266 5 !a/b/c/
1267 6 _a_b_c_
1267 6 _a_b_c_
1268 7 .a.b.c.
1268 7 .a.b.c.
1269 $ log 'children(ancestor(4,5))'
1269 $ log 'children(ancestor(4,5))'
1270 2
1270 2
1271 3
1271 3
1272
1272
1273 $ log 'children(4)'
1273 $ log 'children(4)'
1274 6
1274 6
1275 8
1275 8
1276 $ log 'children(null)'
1276 $ log 'children(null)'
1277 0
1277 0
1278
1278
1279 $ log 'closed()'
1279 $ log 'closed()'
1280 $ log 'contains(a)'
1280 $ log 'contains(a)'
1281 0
1281 0
1282 1
1282 1
1283 3
1283 3
1284 5
1284 5
1285 $ log 'contains("../repo/a")'
1285 $ log 'contains("../repo/a")'
1286 0
1286 0
1287 1
1287 1
1288 3
1288 3
1289 5
1289 5
1290 $ log 'desc(B)'
1290 $ log 'desc(B)'
1291 5
1291 5
1292 $ hg log -r 'desc(r"re:S?u")' --template "{rev} {desc|firstline}\n"
1292 $ hg log -r 'desc(r"re:S?u")' --template "{rev} {desc|firstline}\n"
1293 5 5 bug
1293 5 5 bug
1294 6 6 issue619
1294 6 6 issue619
1295 $ log 'descendants(2 or 3)'
1295 $ log 'descendants(2 or 3)'
1296 2
1296 2
1297 3
1297 3
1298 4
1298 4
1299 5
1299 5
1300 6
1300 6
1301 7
1301 7
1302 8
1302 8
1303 9
1303 9
1304 $ log 'file("b*")'
1304 $ log 'file("b*")'
1305 1
1305 1
1306 4
1306 4
1307 $ log 'filelog("b")'
1307 $ log 'filelog("b")'
1308 1
1308 1
1309 4
1309 4
1310 $ log 'filelog("../repo/b")'
1310 $ log 'filelog("../repo/b")'
1311 1
1311 1
1312 4
1312 4
1313 $ log 'follow()'
1313 $ log 'follow()'
1314 0
1314 0
1315 1
1315 1
1316 2
1316 2
1317 4
1317 4
1318 8
1318 8
1319 9
1319 9
1320 $ log 'grep("issue\d+")'
1320 $ log 'grep("issue\d+")'
1321 6
1321 6
1322 $ try 'grep("(")' # invalid regular expression
1322 $ try 'grep("(")' # invalid regular expression
1323 (func
1323 (func
1324 (symbol 'grep')
1324 (symbol 'grep')
1325 (string '('))
1325 (string '('))
1326 hg: parse error: invalid match pattern: (unbalanced parenthesis|missing \),.*) (re)
1326 hg: parse error: invalid match pattern: (unbalanced parenthesis|missing \),.*) (re)
1327 [255]
1327 [255]
1328 $ try 'grep("\bissue\d+")'
1328 $ try 'grep("\bissue\d+")'
1329 (func
1329 (func
1330 (symbol 'grep')
1330 (symbol 'grep')
1331 (string '\x08issue\\d+'))
1331 (string '\x08issue\\d+'))
1332 * set:
1332 * set:
1333 <filteredset
1333 <filteredset
1334 <fullreposet+ 0:10>,
1334 <fullreposet+ 0:10>,
1335 <grep '\x08issue\\d+'>>
1335 <grep '\x08issue\\d+'>>
1336 $ try 'grep(r"\bissue\d+")'
1336 $ try 'grep(r"\bissue\d+")'
1337 (func
1337 (func
1338 (symbol 'grep')
1338 (symbol 'grep')
1339 (string '\\bissue\\d+'))
1339 (string '\\bissue\\d+'))
1340 * set:
1340 * set:
1341 <filteredset
1341 <filteredset
1342 <fullreposet+ 0:10>,
1342 <fullreposet+ 0:10>,
1343 <grep '\\bissue\\d+'>>
1343 <grep '\\bissue\\d+'>>
1344 6
1344 6
1345 $ try 'grep(r"\")'
1345 $ try 'grep(r"\")'
1346 hg: parse error at 7: unterminated string
1346 hg: parse error at 7: unterminated string
1347 (grep(r"\")
1347 (grep(r"\")
1348 ^ here)
1348 ^ here)
1349 [255]
1349 [255]
1350 $ log 'head()'
1350 $ log 'head()'
1351 0
1351 0
1352 1
1352 1
1353 2
1353 2
1354 3
1354 3
1355 4
1355 4
1356 5
1356 5
1357 6
1357 6
1358 7
1358 7
1359 9
1359 9
1360 $ log 'heads(6::)'
1360 $ log 'heads(6::)'
1361 7
1361 7
1362 $ log 'keyword(issue)'
1362 $ log 'keyword(issue)'
1363 6
1363 6
1364 $ log 'keyword("test a")'
1364 $ log 'keyword("test a")'
1365
1365
1366 Test first (=limit) and last
1366 Test first (=limit) and last
1367
1367
1368 $ log 'limit(head(), 1)'
1368 $ log 'limit(head(), 1)'
1369 0
1369 0
1370 $ log 'limit(author("re:bob|test"), 3, 5)'
1370 $ log 'limit(author("re:bob|test"), 3, 5)'
1371 5
1371 5
1372 6
1372 6
1373 7
1373 7
1374 $ log 'limit(author("re:bob|test"), offset=6)'
1374 $ log 'limit(author("re:bob|test"), offset=6)'
1375 6
1375 6
1376 $ log 'limit(author("re:bob|test"), offset=10)'
1376 $ log 'limit(author("re:bob|test"), offset=10)'
1377 $ log 'limit(all(), 1, -1)'
1377 $ log 'limit(all(), 1, -1)'
1378 hg: parse error: negative offset
1378 hg: parse error: negative offset
1379 [255]
1379 [255]
1380 $ log 'limit(all(), -1)'
1380 $ log 'limit(all(), -1)'
1381 hg: parse error: negative number to select
1381 hg: parse error: negative number to select
1382 [255]
1382 [255]
1383 $ log 'limit(all(), 0)'
1383 $ log 'limit(all(), 0)'
1384
1384
1385 $ log 'last(all(), -1)'
1385 $ log 'last(all(), -1)'
1386 hg: parse error: negative number to select
1386 hg: parse error: negative number to select
1387 [255]
1387 [255]
1388 $ log 'last(all(), 0)'
1388 $ log 'last(all(), 0)'
1389 $ log 'last(all(), 1)'
1389 $ log 'last(all(), 1)'
1390 9
1390 9
1391 $ log 'last(all(), 2)'
1391 $ log 'last(all(), 2)'
1392 8
1392 8
1393 9
1393 9
1394
1394
1395 Test smartset.slice() by first/last()
1395 Test smartset.slice() by first/last()
1396
1396
1397 (using unoptimized set, filteredset as example)
1397 (using unoptimized set, filteredset as example)
1398
1398
1399 $ hg debugrevspec --no-show-revs -s '0:7 & branch("re:")'
1399 $ hg debugrevspec --no-show-revs -s '0:7 & branch("re:")'
1400 * set:
1400 * set:
1401 <filteredset
1401 <filteredset
1402 <spanset+ 0:8>,
1402 <spanset+ 0:8>,
1403 <branch 're:'>>
1403 <branch 're:'>>
1404 $ log 'limit(0:7 & branch("re:"), 3, 4)'
1404 $ log 'limit(0:7 & branch("re:"), 3, 4)'
1405 4
1405 4
1406 5
1406 5
1407 6
1407 6
1408 $ log 'limit(7:0 & branch("re:"), 3, 4)'
1408 $ log 'limit(7:0 & branch("re:"), 3, 4)'
1409 3
1409 3
1410 2
1410 2
1411 1
1411 1
1412 $ log 'last(0:7 & branch("re:"), 2)'
1412 $ log 'last(0:7 & branch("re:"), 2)'
1413 6
1413 6
1414 7
1414 7
1415
1415
1416 (using baseset)
1416 (using baseset)
1417
1417
1418 $ hg debugrevspec --no-show-revs -s 0+1+2+3+4+5+6+7
1418 $ hg debugrevspec --no-show-revs -s 0+1+2+3+4+5+6+7
1419 * set:
1419 * set:
1420 <baseset [0, 1, 2, 3, 4, 5, 6, 7]>
1420 <baseset [0, 1, 2, 3, 4, 5, 6, 7]>
1421 $ hg debugrevspec --no-show-revs -s 0::7
1421 $ hg debugrevspec --no-show-revs -s 0::7
1422 * set:
1422 * set:
1423 <baseset+ [0, 1, 2, 3, 4, 5, 6, 7]>
1423 <baseset+ [0, 1, 2, 3, 4, 5, 6, 7]>
1424 $ log 'limit(0+1+2+3+4+5+6+7, 3, 4)'
1424 $ log 'limit(0+1+2+3+4+5+6+7, 3, 4)'
1425 4
1425 4
1426 5
1426 5
1427 6
1427 6
1428 $ log 'limit(sort(0::7, rev), 3, 4)'
1428 $ log 'limit(sort(0::7, rev), 3, 4)'
1429 4
1429 4
1430 5
1430 5
1431 6
1431 6
1432 $ log 'limit(sort(0::7, -rev), 3, 4)'
1432 $ log 'limit(sort(0::7, -rev), 3, 4)'
1433 3
1433 3
1434 2
1434 2
1435 1
1435 1
1436 $ log 'last(sort(0::7, rev), 2)'
1436 $ log 'last(sort(0::7, rev), 2)'
1437 6
1437 6
1438 7
1438 7
1439 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 6)'
1439 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 6)'
1440 * set:
1440 * set:
1441 <baseset+ [6, 7]>
1441 <baseset+ [6, 7]>
1442 6
1442 6
1443 7
1443 7
1444 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 9)'
1444 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 9)'
1445 * set:
1445 * set:
1446 <baseset+ []>
1446 <baseset+ []>
1447 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 6)'
1447 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 6)'
1448 * set:
1448 * set:
1449 <baseset- [0, 1]>
1449 <baseset- [0, 1]>
1450 1
1450 1
1451 0
1451 0
1452 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 9)'
1452 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 9)'
1453 * set:
1453 * set:
1454 <baseset- []>
1454 <baseset- []>
1455 $ hg debugrevspec -s 'limit(0::7, 0)'
1455 $ hg debugrevspec -s 'limit(0::7, 0)'
1456 * set:
1456 * set:
1457 <baseset+ []>
1457 <baseset+ []>
1458
1458
1459 (using spanset)
1459 (using spanset)
1460
1460
1461 $ hg debugrevspec --no-show-revs -s 0:7
1461 $ hg debugrevspec --no-show-revs -s 0:7
1462 * set:
1462 * set:
1463 <spanset+ 0:8>
1463 <spanset+ 0:8>
1464 $ log 'limit(0:7, 3, 4)'
1464 $ log 'limit(0:7, 3, 4)'
1465 4
1465 4
1466 5
1466 5
1467 6
1467 6
1468 $ log 'limit(7:0, 3, 4)'
1468 $ log 'limit(7:0, 3, 4)'
1469 3
1469 3
1470 2
1470 2
1471 1
1471 1
1472 $ log 'limit(0:7, 3, 6)'
1472 $ log 'limit(0:7, 3, 6)'
1473 6
1473 6
1474 7
1474 7
1475 $ log 'limit(7:0, 3, 6)'
1475 $ log 'limit(7:0, 3, 6)'
1476 1
1476 1
1477 0
1477 0
1478 $ log 'last(0:7, 2)'
1478 $ log 'last(0:7, 2)'
1479 6
1479 6
1480 7
1480 7
1481 $ hg debugrevspec -s 'limit(0:7, 3, 6)'
1481 $ hg debugrevspec -s 'limit(0:7, 3, 6)'
1482 * set:
1482 * set:
1483 <spanset+ 6:8>
1483 <spanset+ 6:8>
1484 6
1484 6
1485 7
1485 7
1486 $ hg debugrevspec -s 'limit(0:7, 3, 9)'
1486 $ hg debugrevspec -s 'limit(0:7, 3, 9)'
1487 * set:
1487 * set:
1488 <spanset+ 8:8>
1488 <spanset+ 8:8>
1489 $ hg debugrevspec -s 'limit(7:0, 3, 6)'
1489 $ hg debugrevspec -s 'limit(7:0, 3, 6)'
1490 * set:
1490 * set:
1491 <spanset- 0:2>
1491 <spanset- 0:2>
1492 1
1492 1
1493 0
1493 0
1494 $ hg debugrevspec -s 'limit(7:0, 3, 9)'
1494 $ hg debugrevspec -s 'limit(7:0, 3, 9)'
1495 * set:
1495 * set:
1496 <spanset- 0:0>
1496 <spanset- 0:0>
1497 $ hg debugrevspec -s 'limit(0:7, 0)'
1497 $ hg debugrevspec -s 'limit(0:7, 0)'
1498 * set:
1498 * set:
1499 <spanset+ 0:0>
1499 <spanset+ 0:0>
1500
1500
1501 Test order of first/last revisions
1501 Test order of first/last revisions
1502
1502
1503 $ hg debugrevspec -s 'first(4:0, 3) & 3:'
1503 $ hg debugrevspec -s 'first(4:0, 3) & 3:'
1504 * set:
1504 * set:
1505 <filteredset
1505 <filteredset
1506 <spanset- 2:5>,
1506 <spanset- 2:5>,
1507 <spanset+ 3:10>>
1507 <spanset+ 3:10>>
1508 4
1508 4
1509 3
1509 3
1510
1510
1511 $ hg debugrevspec -s '3: & first(4:0, 3)'
1511 $ hg debugrevspec -s '3: & first(4:0, 3)'
1512 * set:
1512 * set:
1513 <filteredset
1513 <filteredset
1514 <spanset+ 3:10>,
1514 <spanset+ 3:10>,
1515 <spanset- 2:5>>
1515 <spanset- 2:5>>
1516 3
1516 3
1517 4
1517 4
1518
1518
1519 $ hg debugrevspec -s 'last(4:0, 3) & :1'
1519 $ hg debugrevspec -s 'last(4:0, 3) & :1'
1520 * set:
1520 * set:
1521 <filteredset
1521 <filteredset
1522 <spanset- 0:3>,
1522 <spanset- 0:3>,
1523 <spanset+ 0:2>>
1523 <spanset+ 0:2>>
1524 1
1524 1
1525 0
1525 0
1526
1526
1527 $ hg debugrevspec -s ':1 & last(4:0, 3)'
1527 $ hg debugrevspec -s ':1 & last(4:0, 3)'
1528 * set:
1528 * set:
1529 <filteredset
1529 <filteredset
1530 <spanset+ 0:2>,
1530 <spanset+ 0:2>,
1531 <spanset+ 0:3>>
1531 <spanset+ 0:3>>
1532 0
1532 0
1533 1
1533 1
1534
1534
1535 Test scmutil.revsingle() should return the last revision
1535 Test scmutil.revsingle() should return the last revision
1536
1536
1537 $ hg debugrevspec -s 'last(0::)'
1537 $ hg debugrevspec -s 'last(0::)'
1538 * set:
1538 * set:
1539 <baseset slice=0:1
1539 <baseset slice=0:1
1540 <generatorsetasc->>
1540 <generatorsetasc->>
1541 9
1541 9
1542 $ hg identify -r '0::' --num
1542 $ hg identify -r '0::' --num
1543 9
1543 9
1544
1544
1545 Test matching
1545 Test matching
1546
1546
1547 $ log 'matching(6)'
1547 $ log 'matching(6)'
1548 6
1548 6
1549 $ log 'matching(6:7, "phase parents user date branch summary files description substate")'
1549 $ log 'matching(6:7, "phase parents user date branch summary files description substate")'
1550 6
1550 6
1551 7
1551 7
1552
1552
1553 Testing min and max
1553 Testing min and max
1554
1554
1555 max: simple
1555 max: simple
1556
1556
1557 $ log 'max(contains(a))'
1557 $ log 'max(contains(a))'
1558 5
1558 5
1559
1559
1560 max: simple on unordered set)
1560 max: simple on unordered set)
1561
1561
1562 $ log 'max((4+0+2+5+7) and contains(a))'
1562 $ log 'max((4+0+2+5+7) and contains(a))'
1563 5
1563 5
1564
1564
1565 max: no result
1565 max: no result
1566
1566
1567 $ log 'max(contains(stringthatdoesnotappearanywhere))'
1567 $ log 'max(contains(stringthatdoesnotappearanywhere))'
1568
1568
1569 max: no result on unordered set
1569 max: no result on unordered set
1570
1570
1571 $ log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1571 $ log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1572
1572
1573 min: simple
1573 min: simple
1574
1574
1575 $ log 'min(contains(a))'
1575 $ log 'min(contains(a))'
1576 0
1576 0
1577
1577
1578 min: simple on unordered set
1578 min: simple on unordered set
1579
1579
1580 $ log 'min((4+0+2+5+7) and contains(a))'
1580 $ log 'min((4+0+2+5+7) and contains(a))'
1581 0
1581 0
1582
1582
1583 min: empty
1583 min: empty
1584
1584
1585 $ log 'min(contains(stringthatdoesnotappearanywhere))'
1585 $ log 'min(contains(stringthatdoesnotappearanywhere))'
1586
1586
1587 min: empty on unordered set
1587 min: empty on unordered set
1588
1588
1589 $ log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1589 $ log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1590
1590
1591
1591
1592 $ log 'merge()'
1592 $ log 'merge()'
1593 6
1593 6
1594 $ log 'branchpoint()'
1594 $ log 'branchpoint()'
1595 1
1595 1
1596 4
1596 4
1597 $ log 'modifies(b)'
1597 $ log 'modifies(b)'
1598 4
1598 4
1599 $ log 'modifies("path:b")'
1599 $ log 'modifies("path:b")'
1600 4
1600 4
1601 $ log 'modifies("*")'
1601 $ log 'modifies("*")'
1602 4
1602 4
1603 6
1603 6
1604 $ log 'modifies("set:modified()")'
1604 $ log 'modifies("set:modified()")'
1605 4
1605 4
1606 $ log 'id(5)'
1606 $ log 'id(5)'
1607 2
1607 2
1608 $ log 'only(9)'
1608 $ log 'only(9)'
1609 8
1609 8
1610 9
1610 9
1611 $ log 'only(8)'
1611 $ log 'only(8)'
1612 8
1612 8
1613 $ log 'only(9, 5)'
1613 $ log 'only(9, 5)'
1614 2
1614 2
1615 4
1615 4
1616 8
1616 8
1617 9
1617 9
1618 $ log 'only(7 + 9, 5 + 2)'
1618 $ log 'only(7 + 9, 5 + 2)'
1619 4
1619 4
1620 6
1620 6
1621 7
1621 7
1622 8
1622 8
1623 9
1623 9
1624
1624
1625 Test empty set input
1625 Test empty set input
1626 $ log 'only(p2())'
1626 $ log 'only(p2())'
1627 $ log 'only(p1(), p2())'
1627 $ log 'only(p1(), p2())'
1628 0
1628 0
1629 1
1629 1
1630 2
1630 2
1631 4
1631 4
1632 8
1632 8
1633 9
1633 9
1634
1634
1635 Test '%' operator
1635 Test '%' operator
1636
1636
1637 $ log '9%'
1637 $ log '9%'
1638 8
1638 8
1639 9
1639 9
1640 $ log '9%5'
1640 $ log '9%5'
1641 2
1641 2
1642 4
1642 4
1643 8
1643 8
1644 9
1644 9
1645 $ log '(7 + 9)%(5 + 2)'
1645 $ log '(7 + 9)%(5 + 2)'
1646 4
1646 4
1647 6
1647 6
1648 7
1648 7
1649 8
1649 8
1650 9
1650 9
1651
1651
1652 Test operand of '%' is optimized recursively (issue4670)
1652 Test operand of '%' is optimized recursively (issue4670)
1653
1653
1654 $ try --optimize '8:9-8%'
1654 $ try --optimize '8:9-8%'
1655 (onlypost
1655 (onlypost
1656 (minus
1656 (minus
1657 (range
1657 (range
1658 (symbol '8')
1658 (symbol '8')
1659 (symbol '9'))
1659 (symbol '9'))
1660 (symbol '8')))
1660 (symbol '8')))
1661 * optimized:
1661 * optimized:
1662 (func
1662 (func
1663 (symbol 'only')
1663 (symbol 'only')
1664 (difference
1664 (difference
1665 (range
1665 (range
1666 (symbol '8')
1666 (symbol '8')
1667 (symbol '9'))
1667 (symbol '9'))
1668 (symbol '8')))
1668 (symbol '8')))
1669 * set:
1669 * set:
1670 <baseset+ [8, 9]>
1670 <baseset+ [8, 9]>
1671 8
1671 8
1672 9
1672 9
1673 $ try --optimize '(9)%(5)'
1673 $ try --optimize '(9)%(5)'
1674 (only
1674 (only
1675 (group
1675 (group
1676 (symbol '9'))
1676 (symbol '9'))
1677 (group
1677 (group
1678 (symbol '5')))
1678 (symbol '5')))
1679 * optimized:
1679 * optimized:
1680 (func
1680 (func
1681 (symbol 'only')
1681 (symbol 'only')
1682 (list
1682 (list
1683 (symbol '9')
1683 (symbol '9')
1684 (symbol '5')))
1684 (symbol '5')))
1685 * set:
1685 * set:
1686 <baseset+ [2, 4, 8, 9]>
1686 <baseset+ [2, 4, 8, 9]>
1687 2
1687 2
1688 4
1688 4
1689 8
1689 8
1690 9
1690 9
1691
1691
1692 Test the order of operations
1692 Test the order of operations
1693
1693
1694 $ log '7 + 9%5 + 2'
1694 $ log '7 + 9%5 + 2'
1695 7
1695 7
1696 2
1696 2
1697 4
1697 4
1698 8
1698 8
1699 9
1699 9
1700
1700
1701 Test explicit numeric revision
1701 Test explicit numeric revision
1702 $ log 'rev(-2)'
1702 $ log 'rev(-2)'
1703 $ log 'rev(-1)'
1703 $ log 'rev(-1)'
1704 -1
1704 -1
1705 $ log 'rev(0)'
1705 $ log 'rev(0)'
1706 0
1706 0
1707 $ log 'rev(9)'
1707 $ log 'rev(9)'
1708 9
1708 9
1709 $ log 'rev(10)'
1709 $ log 'rev(10)'
1710 $ log 'rev(tip)'
1710 $ log 'rev(tip)'
1711 hg: parse error: rev expects a number
1711 hg: parse error: rev expects a number
1712 [255]
1712 [255]
1713
1713
1714 Test hexadecimal revision
1714 Test hexadecimal revision
1715 $ log 'id(2)'
1715 $ log 'id(2)'
1716 abort: 00changelog.i@2: ambiguous identifier!
1716 abort: 00changelog.i@2: ambiguous identifier!
1717 [255]
1717 [255]
1718 $ log 'id(23268)'
1718 $ log 'id(23268)'
1719 4
1719 4
1720 $ log 'id(2785f51eece)'
1720 $ log 'id(2785f51eece)'
1721 0
1721 0
1722 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c)'
1722 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c)'
1723 8
1723 8
1724 $ log 'id(d5d0dcbdc4a)'
1724 $ log 'id(d5d0dcbdc4a)'
1725 $ log 'id(d5d0dcbdc4w)'
1725 $ log 'id(d5d0dcbdc4w)'
1726 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532d)'
1726 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532d)'
1727 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532q)'
1727 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532q)'
1728 $ log 'id(1.0)'
1728 $ log 'id(1.0)'
1729 $ log 'id(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)'
1729 $ log 'id(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)'
1730
1730
1731 Test null revision
1731 Test null revision
1732 $ log '(null)'
1732 $ log '(null)'
1733 -1
1733 -1
1734 $ log '(null:0)'
1734 $ log '(null:0)'
1735 -1
1735 -1
1736 0
1736 0
1737 $ log '(0:null)'
1737 $ log '(0:null)'
1738 0
1738 0
1739 -1
1739 -1
1740 $ log 'null::0'
1740 $ log 'null::0'
1741 -1
1741 -1
1742 0
1742 0
1743 $ log 'null:tip - 0:'
1743 $ log 'null:tip - 0:'
1744 -1
1744 -1
1745 $ log 'null: and null::' | head -1
1745 $ log 'null: and null::' | head -1
1746 -1
1746 -1
1747 $ log 'null: or 0:' | head -2
1747 $ log 'null: or 0:' | head -2
1748 -1
1748 -1
1749 0
1749 0
1750 $ log 'ancestors(null)'
1750 $ log 'ancestors(null)'
1751 -1
1751 -1
1752 $ log 'reverse(null:)' | tail -2
1752 $ log 'reverse(null:)' | tail -2
1753 0
1753 0
1754 -1
1754 -1
1755 $ log 'first(null:)'
1755 $ log 'first(null:)'
1756 -1
1756 -1
1757 $ log 'min(null:)'
1757 $ log 'min(null:)'
1758 BROKEN: should be '-1'
1758 BROKEN: should be '-1'
1759 $ log 'tip:null and all()' | tail -2
1759 $ log 'tip:null and all()' | tail -2
1760 1
1760 1
1761 0
1761 0
1762
1762
1763 Test working-directory revision
1763 Test working-directory revision
1764 $ hg debugrevspec 'wdir()'
1764 $ hg debugrevspec 'wdir()'
1765 2147483647
1765 2147483647
1766 $ hg debugrevspec 'wdir()^'
1766 $ hg debugrevspec 'wdir()^'
1767 9
1767 9
1768 $ hg up 7
1768 $ hg up 7
1769 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1769 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1770 $ hg debugrevspec 'wdir()^'
1770 $ hg debugrevspec 'wdir()^'
1771 7
1771 7
1772 $ hg debugrevspec 'wdir()^0'
1772 $ hg debugrevspec 'wdir()^0'
1773 2147483647
1773 2147483647
1774 $ hg debugrevspec 'wdir()~3'
1774 $ hg debugrevspec 'wdir()~3'
1775 5
1775 5
1776 $ hg debugrevspec 'ancestors(wdir())'
1776 $ hg debugrevspec 'ancestors(wdir())'
1777 0
1777 0
1778 1
1778 1
1779 2
1779 2
1780 3
1780 3
1781 4
1781 4
1782 5
1782 5
1783 6
1783 6
1784 7
1784 7
1785 2147483647
1785 2147483647
1786 $ hg debugrevspec 'wdir()~0'
1786 $ hg debugrevspec 'wdir()~0'
1787 2147483647
1787 2147483647
1788 $ hg debugrevspec 'p1(wdir())'
1788 $ hg debugrevspec 'p1(wdir())'
1789 7
1789 7
1790 $ hg debugrevspec 'p2(wdir())'
1790 $ hg debugrevspec 'p2(wdir())'
1791 $ hg debugrevspec 'parents(wdir())'
1791 $ hg debugrevspec 'parents(wdir())'
1792 7
1792 7
1793 $ hg debugrevspec 'wdir()^1'
1793 $ hg debugrevspec 'wdir()^1'
1794 7
1794 7
1795 $ hg debugrevspec 'wdir()^2'
1795 $ hg debugrevspec 'wdir()^2'
1796 $ hg debugrevspec 'wdir()^3'
1796 $ hg debugrevspec 'wdir()^3'
1797 hg: parse error: ^ expects a number 0, 1, or 2
1797 hg: parse error: ^ expects a number 0, 1, or 2
1798 [255]
1798 [255]
1799 For tests consistency
1799 For tests consistency
1800 $ hg up 9
1800 $ hg up 9
1801 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1801 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1802 $ hg debugrevspec 'tip or wdir()'
1802 $ hg debugrevspec 'tip or wdir()'
1803 9
1803 9
1804 2147483647
1804 2147483647
1805 $ hg debugrevspec '0:tip and wdir()'
1805 $ hg debugrevspec '0:tip and wdir()'
1806 $ log '0:wdir()' | tail -3
1806 $ log '0:wdir()' | tail -3
1807 8
1807 8
1808 9
1808 9
1809 2147483647
1809 2147483647
1810 $ log 'wdir():0' | head -3
1810 $ log 'wdir():0' | head -3
1811 2147483647
1811 2147483647
1812 9
1812 9
1813 8
1813 8
1814 $ log 'wdir():wdir()'
1814 $ log 'wdir():wdir()'
1815 2147483647
1815 2147483647
1816 $ log '(all() + wdir()) & min(. + wdir())'
1816 $ log '(all() + wdir()) & min(. + wdir())'
1817 9
1817 9
1818 $ log '(all() + wdir()) & max(. + wdir())'
1818 $ log '(all() + wdir()) & max(. + wdir())'
1819 2147483647
1819 2147483647
1820 $ log 'first(wdir() + .)'
1820 $ log 'first(wdir() + .)'
1821 2147483647
1821 2147483647
1822 $ log 'last(. + wdir())'
1822 $ log 'last(. + wdir())'
1823 2147483647
1823 2147483647
1824
1824
1825 Test working-directory integer revision and node id
1825 Test working-directory integer revision and node id
1826 (BUG: '0:wdir()' is still needed to populate wdir revision)
1826 (BUG: '0:wdir()' is still needed to populate wdir revision)
1827
1827
1828 $ hg debugrevspec '0:wdir() & 2147483647'
1828 $ hg debugrevspec '0:wdir() & 2147483647'
1829 2147483647
1829 2147483647
1830 $ hg debugrevspec '0:wdir() & rev(2147483647)'
1830 $ hg debugrevspec '0:wdir() & rev(2147483647)'
1831 2147483647
1831 2147483647
1832 $ hg debugrevspec '0:wdir() & ffffffffffffffffffffffffffffffffffffffff'
1832 $ hg debugrevspec '0:wdir() & ffffffffffffffffffffffffffffffffffffffff'
1833 2147483647
1833 2147483647
1834 $ hg debugrevspec '0:wdir() & ffffffffffff'
1834 $ hg debugrevspec '0:wdir() & ffffffffffff'
1835 2147483647
1835 2147483647
1836 $ hg debugrevspec '0:wdir() & id(ffffffffffffffffffffffffffffffffffffffff)'
1836 $ hg debugrevspec '0:wdir() & id(ffffffffffffffffffffffffffffffffffffffff)'
1837 2147483647
1837 2147483647
1838 $ hg debugrevspec '0:wdir() & id(ffffffffffff)'
1838 $ hg debugrevspec '0:wdir() & id(ffffffffffff)'
1839 2147483647
1839 2147483647
1840
1840
1841 $ cd ..
1841 $ cd ..
1842
1842
1843 Test short 'ff...' hash collision
1843 Test short 'ff...' hash collision
1844 (BUG: '0:wdir()' is still needed to populate wdir revision)
1844 (BUG: '0:wdir()' is still needed to populate wdir revision)
1845
1845
1846 $ hg init wdir-hashcollision
1846 $ hg init wdir-hashcollision
1847 $ cd wdir-hashcollision
1847 $ cd wdir-hashcollision
1848 $ cat <<EOF >> .hg/hgrc
1848 $ cat <<EOF >> .hg/hgrc
1849 > [experimental]
1849 > [experimental]
1850 > evolution.createmarkers=True
1850 > evolution.createmarkers=True
1851 > EOF
1851 > EOF
1852 $ echo 0 > a
1852 $ echo 0 > a
1853 $ hg ci -qAm 0
1853 $ hg ci -qAm 0
1854 $ for i in 2463 2961 6726 78127; do
1854 $ for i in 2463 2961 6726 78127; do
1855 > hg up -q 0
1855 > hg up -q 0
1856 > echo $i > a
1856 > echo $i > a
1857 > hg ci -qm $i
1857 > hg ci -qm $i
1858 > done
1858 > done
1859 $ hg up -q null
1859 $ hg up -q null
1860 $ hg log -r '0:wdir()' -T '{rev}:{node} {shortest(node, 3)}\n'
1860 $ hg log -r '0:wdir()' -T '{rev}:{node} {shortest(node, 3)}\n'
1861 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a b4e
1861 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a b4e
1862 1:fffbae3886c8fbb2114296380d276fd37715d571 fffba
1862 1:fffbae3886c8fbb2114296380d276fd37715d571 fffba
1863 2:fffb6093b00943f91034b9bdad069402c834e572 fffb6
1863 2:fffb6093b00943f91034b9bdad069402c834e572 fffb6
1864 3:fff48a9b9de34a4d64120c29548214c67980ade3 fff4
1864 3:fff48a9b9de34a4d64120c29548214c67980ade3 fff4
1865 4:ffff85cff0ff78504fcdc3c0bc10de0c65379249 ffff8
1865 4:ffff85cff0ff78504fcdc3c0bc10de0c65379249 ffff8
1866 2147483647:ffffffffffffffffffffffffffffffffffffffff fffff
1866 2147483647:ffffffffffffffffffffffffffffffffffffffff fffff
1867 $ hg debugobsolete fffbae3886c8fbb2114296380d276fd37715d571
1867 $ hg debugobsolete fffbae3886c8fbb2114296380d276fd37715d571
1868 obsoleted 1 changesets
1868 obsoleted 1 changesets
1869
1869
1870 $ hg debugrevspec '0:wdir() & fff'
1870 $ hg debugrevspec '0:wdir() & fff'
1871 abort: 00changelog.i@fff: ambiguous identifier!
1871 abort: 00changelog.i@fff: ambiguous identifier!
1872 [255]
1872 [255]
1873 $ hg debugrevspec '0:wdir() & ffff'
1873 $ hg debugrevspec '0:wdir() & ffff'
1874 abort: 00changelog.i@ffff: ambiguous identifier!
1874 abort: 00changelog.i@ffff: ambiguous identifier!
1875 [255]
1875 [255]
1876 $ hg debugrevspec '0:wdir() & fffb'
1876 $ hg debugrevspec '0:wdir() & fffb'
1877 abort: 00changelog.i@fffb: ambiguous identifier!
1877 abort: 00changelog.i@fffb: ambiguous identifier!
1878 [255]
1878 [255]
1879 BROKEN should be '2' (node lookup uses unfiltered repo since dc25ed84bee8)
1879 BROKEN should be '2' (node lookup uses unfiltered repo since dc25ed84bee8)
1880 $ hg debugrevspec '0:wdir() & id(fffb)'
1880 $ hg debugrevspec '0:wdir() & id(fffb)'
1881 2
1881 2
1882 $ hg debugrevspec '0:wdir() & ffff8'
1882 $ hg debugrevspec '0:wdir() & ffff8'
1883 4
1883 4
1884 $ hg debugrevspec '0:wdir() & fffff'
1884 $ hg debugrevspec '0:wdir() & fffff'
1885 2147483647
1885 2147483647
1886
1886
1887 $ cd ..
1887 $ cd ..
1888
1888
1889 Test branch() with wdir()
1889 Test branch() with wdir()
1890
1890
1891 $ cd repo
1891 $ cd repo
1892
1892
1893 $ log '0:wdir() & branch("literal:Γ©")'
1893 $ log '0:wdir() & branch("literal:Γ©")'
1894 8
1894 8
1895 9
1895 9
1896 2147483647
1896 2147483647
1897 $ log '0:wdir() & branch("re:Γ©")'
1897 $ log '0:wdir() & branch("re:Γ©")'
1898 8
1898 8
1899 9
1899 9
1900 2147483647
1900 2147483647
1901 $ log '0:wdir() & branch("re:^a")'
1901 $ log '0:wdir() & branch("re:^a")'
1902 0
1902 0
1903 2
1903 2
1904 $ log '0:wdir() & branch(8)'
1904 $ log '0:wdir() & branch(8)'
1905 8
1905 8
1906 9
1906 9
1907 2147483647
1907 2147483647
1908
1908
1909 branch(wdir()) returns all revisions belonging to the working branch. The wdir
1909 branch(wdir()) returns all revisions belonging to the working branch. The wdir
1910 itself isn't returned unless it is explicitly populated.
1910 itself isn't returned unless it is explicitly populated.
1911
1911
1912 $ log 'branch(wdir())'
1912 $ log 'branch(wdir())'
1913 8
1913 8
1914 9
1914 9
1915 $ log '0:wdir() & branch(wdir())'
1915 $ log '0:wdir() & branch(wdir())'
1916 8
1916 8
1917 9
1917 9
1918 2147483647
1918 2147483647
1919
1919
1920 $ log 'outgoing()'
1920 $ log 'outgoing()'
1921 8
1921 8
1922 9
1922 9
1923 $ log 'outgoing("../remote1")'
1923 $ log 'outgoing("../remote1")'
1924 8
1924 8
1925 9
1925 9
1926 $ log 'outgoing("../remote2")'
1926 $ log 'outgoing("../remote2")'
1927 3
1927 3
1928 5
1928 5
1929 6
1929 6
1930 7
1930 7
1931 9
1931 9
1932 $ log 'p1(merge())'
1932 $ log 'p1(merge())'
1933 5
1933 5
1934 $ log 'p2(merge())'
1934 $ log 'p2(merge())'
1935 4
1935 4
1936 $ log 'parents(merge())'
1936 $ log 'parents(merge())'
1937 4
1937 4
1938 5
1938 5
1939 $ log 'p1(branchpoint())'
1939 $ log 'p1(branchpoint())'
1940 0
1940 0
1941 2
1941 2
1942 $ log 'p2(branchpoint())'
1942 $ log 'p2(branchpoint())'
1943 $ log 'parents(branchpoint())'
1943 $ log 'parents(branchpoint())'
1944 0
1944 0
1945 2
1945 2
1946 $ log 'removes(a)'
1946 $ log 'removes(a)'
1947 2
1947 2
1948 6
1948 6
1949 $ log 'roots(all())'
1949 $ log 'roots(all())'
1950 0
1950 0
1951 $ log 'reverse(2 or 3 or 4 or 5)'
1951 $ log 'reverse(2 or 3 or 4 or 5)'
1952 5
1952 5
1953 4
1953 4
1954 3
1954 3
1955 2
1955 2
1956 $ log 'reverse(all())'
1956 $ log 'reverse(all())'
1957 9
1957 9
1958 8
1958 8
1959 7
1959 7
1960 6
1960 6
1961 5
1961 5
1962 4
1962 4
1963 3
1963 3
1964 2
1964 2
1965 1
1965 1
1966 0
1966 0
1967 $ log 'reverse(all()) & filelog(b)'
1967 $ log 'reverse(all()) & filelog(b)'
1968 4
1968 4
1969 1
1969 1
1970 $ log 'rev(5)'
1970 $ log 'rev(5)'
1971 5
1971 5
1972 $ log 'sort(limit(reverse(all()), 3))'
1972 $ log 'sort(limit(reverse(all()), 3))'
1973 7
1973 7
1974 8
1974 8
1975 9
1975 9
1976 $ log 'sort(2 or 3 or 4 or 5, date)'
1976 $ log 'sort(2 or 3 or 4 or 5, date)'
1977 2
1977 2
1978 3
1978 3
1979 5
1979 5
1980 4
1980 4
1981 $ log 'tagged()'
1981 $ log 'tagged()'
1982 6
1982 6
1983 $ log 'tag()'
1983 $ log 'tag()'
1984 6
1984 6
1985 $ log 'tag(1.0)'
1985 $ log 'tag(1.0)'
1986 6
1986 6
1987 $ log 'tag(tip)'
1987 $ log 'tag(tip)'
1988 9
1988 9
1989
1989
1990 Test order of revisions in compound expression
1990 Test order of revisions in compound expression
1991 ----------------------------------------------
1991 ----------------------------------------------
1992
1992
1993 The general rule is that only the outermost (= leftmost) predicate can
1993 The general rule is that only the outermost (= leftmost) predicate can
1994 enforce its ordering requirement. The other predicates should take the
1994 enforce its ordering requirement. The other predicates should take the
1995 ordering defined by it.
1995 ordering defined by it.
1996
1996
1997 'A & B' should follow the order of 'A':
1997 'A & B' should follow the order of 'A':
1998
1998
1999 $ log '2:0 & 0::2'
1999 $ log '2:0 & 0::2'
2000 2
2000 2
2001 1
2001 1
2002 0
2002 0
2003
2003
2004 'head()' combines sets in right order:
2004 'head()' combines sets in right order:
2005
2005
2006 $ log '2:0 & head()'
2006 $ log '2:0 & head()'
2007 2
2007 2
2008 1
2008 1
2009 0
2009 0
2010
2010
2011 'x:y' takes ordering parameter into account:
2011 'x:y' takes ordering parameter into account:
2012
2012
2013 $ try -p optimized '3:0 & 0:3 & not 2:1'
2013 $ try -p optimized '3:0 & 0:3 & not 2:1'
2014 * optimized:
2014 * optimized:
2015 (difference
2015 (difference
2016 (and
2016 (and
2017 (range
2017 (range
2018 (symbol '3')
2018 (symbol '3')
2019 (symbol '0'))
2019 (symbol '0'))
2020 (range
2020 (range
2021 (symbol '0')
2021 (symbol '0')
2022 (symbol '3')))
2022 (symbol '3')))
2023 (range
2023 (range
2024 (symbol '2')
2024 (symbol '2')
2025 (symbol '1')))
2025 (symbol '1')))
2026 * set:
2026 * set:
2027 <filteredset
2027 <filteredset
2028 <filteredset
2028 <filteredset
2029 <spanset- 0:4>,
2029 <spanset- 0:4>,
2030 <spanset+ 0:4>>,
2030 <spanset+ 0:4>>,
2031 <not
2031 <not
2032 <spanset+ 1:3>>>
2032 <spanset+ 1:3>>>
2033 3
2033 3
2034 0
2034 0
2035
2035
2036 'a + b', which is optimized to '_list(a b)', should take the ordering of
2036 'a + b', which is optimized to '_list(a b)', should take the ordering of
2037 the left expression:
2037 the left expression:
2038
2038
2039 $ try --optimize '2:0 & (0 + 1 + 2)'
2039 $ try --optimize '2:0 & (0 + 1 + 2)'
2040 (and
2040 (and
2041 (range
2041 (range
2042 (symbol '2')
2042 (symbol '2')
2043 (symbol '0'))
2043 (symbol '0'))
2044 (group
2044 (group
2045 (or
2045 (or
2046 (list
2046 (list
2047 (symbol '0')
2047 (symbol '0')
2048 (symbol '1')
2048 (symbol '1')
2049 (symbol '2')))))
2049 (symbol '2')))))
2050 * optimized:
2050 * optimized:
2051 (and
2051 (and
2052 (range
2052 (range
2053 (symbol '2')
2053 (symbol '2')
2054 (symbol '0'))
2054 (symbol '0'))
2055 (func
2055 (func
2056 (symbol '_list')
2056 (symbol '_list')
2057 (string '0\x001\x002')))
2057 (string '0\x001\x002')))
2058 * set:
2058 * set:
2059 <filteredset
2059 <filteredset
2060 <spanset- 0:3>,
2060 <spanset- 0:3>,
2061 <baseset [0, 1, 2]>>
2061 <baseset [0, 1, 2]>>
2062 2
2062 2
2063 1
2063 1
2064 0
2064 0
2065
2065
2066 'A + B' should take the ordering of the left expression:
2066 'A + B' should take the ordering of the left expression:
2067
2067
2068 $ try --optimize '2:0 & (0:1 + 2)'
2068 $ try --optimize '2:0 & (0:1 + 2)'
2069 (and
2069 (and
2070 (range
2070 (range
2071 (symbol '2')
2071 (symbol '2')
2072 (symbol '0'))
2072 (symbol '0'))
2073 (group
2073 (group
2074 (or
2074 (or
2075 (list
2075 (list
2076 (range
2076 (range
2077 (symbol '0')
2077 (symbol '0')
2078 (symbol '1'))
2078 (symbol '1'))
2079 (symbol '2')))))
2079 (symbol '2')))))
2080 * optimized:
2080 * optimized:
2081 (and
2081 (and
2082 (range
2082 (range
2083 (symbol '2')
2083 (symbol '2')
2084 (symbol '0'))
2084 (symbol '0'))
2085 (or
2085 (or
2086 (list
2086 (list
2087 (range
2087 (range
2088 (symbol '0')
2088 (symbol '0')
2089 (symbol '1'))
2089 (symbol '1'))
2090 (symbol '2'))))
2090 (symbol '2'))))
2091 * set:
2091 * set:
2092 <filteredset
2092 <filteredset
2093 <spanset- 0:3>,
2093 <spanset- 0:3>,
2094 <addset
2094 <addset
2095 <spanset+ 0:2>,
2095 <spanset+ 0:2>,
2096 <baseset [2]>>>
2096 <baseset [2]>>>
2097 2
2097 2
2098 1
2098 1
2099 0
2099 0
2100
2100
2101 '_intlist(a b)' should behave like 'a + b':
2101 '_intlist(a b)' should behave like 'a + b':
2102
2102
2103 $ trylist --optimize '2:0 & %ld' 0 1 2
2103 $ trylist --optimize '2:0 & %ld' 0 1 2
2104 (and
2104 (and
2105 (range
2105 (range
2106 (symbol '2')
2106 (symbol '2')
2107 (symbol '0'))
2107 (symbol '0'))
2108 (func
2108 (func
2109 (symbol '_intlist')
2109 (symbol '_intlist')
2110 (string '0\x001\x002')))
2110 (string '0\x001\x002')))
2111 * optimized:
2111 * optimized:
2112 (andsmally
2112 (andsmally
2113 (range
2113 (range
2114 (symbol '2')
2114 (symbol '2')
2115 (symbol '0'))
2115 (symbol '0'))
2116 (func
2116 (func
2117 (symbol '_intlist')
2117 (symbol '_intlist')
2118 (string '0\x001\x002')))
2118 (string '0\x001\x002')))
2119 * set:
2119 * set:
2120 <filteredset
2120 <filteredset
2121 <spanset- 0:3>,
2121 <spanset- 0:3>,
2122 <baseset+ [0, 1, 2]>>
2122 <baseset+ [0, 1, 2]>>
2123 2
2123 2
2124 1
2124 1
2125 0
2125 0
2126
2126
2127 $ trylist --optimize '%ld & 2:0' 0 2 1
2127 $ trylist --optimize '%ld & 2:0' 0 2 1
2128 (and
2128 (and
2129 (func
2129 (func
2130 (symbol '_intlist')
2130 (symbol '_intlist')
2131 (string '0\x002\x001'))
2131 (string '0\x002\x001'))
2132 (range
2132 (range
2133 (symbol '2')
2133 (symbol '2')
2134 (symbol '0')))
2134 (symbol '0')))
2135 * optimized:
2135 * optimized:
2136 (and
2136 (and
2137 (func
2137 (func
2138 (symbol '_intlist')
2138 (symbol '_intlist')
2139 (string '0\x002\x001'))
2139 (string '0\x002\x001'))
2140 (range
2140 (range
2141 (symbol '2')
2141 (symbol '2')
2142 (symbol '0')))
2142 (symbol '0')))
2143 * set:
2143 * set:
2144 <filteredset
2144 <filteredset
2145 <baseset [0, 2, 1]>,
2145 <baseset [0, 2, 1]>,
2146 <spanset- 0:3>>
2146 <spanset- 0:3>>
2147 0
2147 0
2148 2
2148 2
2149 1
2149 1
2150
2150
2151 '_hexlist(a b)' should behave like 'a + b':
2151 '_hexlist(a b)' should behave like 'a + b':
2152
2152
2153 $ trylist --optimize --bin '2:0 & %ln' `hg log -T '{node} ' -r0:2`
2153 $ trylist --optimize --bin '2:0 & %ln' `hg log -T '{node} ' -r0:2`
2154 (and
2154 (and
2155 (range
2155 (range
2156 (symbol '2')
2156 (symbol '2')
2157 (symbol '0'))
2157 (symbol '0'))
2158 (func
2158 (func
2159 (symbol '_hexlist')
2159 (symbol '_hexlist')
2160 (string '*'))) (glob)
2160 (string '*'))) (glob)
2161 * optimized:
2161 * optimized:
2162 (and
2162 (and
2163 (range
2163 (range
2164 (symbol '2')
2164 (symbol '2')
2165 (symbol '0'))
2165 (symbol '0'))
2166 (func
2166 (func
2167 (symbol '_hexlist')
2167 (symbol '_hexlist')
2168 (string '*'))) (glob)
2168 (string '*'))) (glob)
2169 * set:
2169 * set:
2170 <filteredset
2170 <filteredset
2171 <spanset- 0:3>,
2171 <spanset- 0:3>,
2172 <baseset [0, 1, 2]>>
2172 <baseset [0, 1, 2]>>
2173 2
2173 2
2174 1
2174 1
2175 0
2175 0
2176
2176
2177 $ trylist --optimize --bin '%ln & 2:0' `hg log -T '{node} ' -r0+2+1`
2177 $ trylist --optimize --bin '%ln & 2:0' `hg log -T '{node} ' -r0+2+1`
2178 (and
2178 (and
2179 (func
2179 (func
2180 (symbol '_hexlist')
2180 (symbol '_hexlist')
2181 (string '*')) (glob)
2181 (string '*')) (glob)
2182 (range
2182 (range
2183 (symbol '2')
2183 (symbol '2')
2184 (symbol '0')))
2184 (symbol '0')))
2185 * optimized:
2185 * optimized:
2186 (andsmally
2186 (andsmally
2187 (func
2187 (func
2188 (symbol '_hexlist')
2188 (symbol '_hexlist')
2189 (string '*')) (glob)
2189 (string '*')) (glob)
2190 (range
2190 (range
2191 (symbol '2')
2191 (symbol '2')
2192 (symbol '0')))
2192 (symbol '0')))
2193 * set:
2193 * set:
2194 <baseset [0, 2, 1]>
2194 <baseset [0, 2, 1]>
2195 0
2195 0
2196 2
2196 2
2197 1
2197 1
2198
2198
2199 '_list' should not go through the slow follow-order path if order doesn't
2199 '_list' should not go through the slow follow-order path if order doesn't
2200 matter:
2200 matter:
2201
2201
2202 $ try -p optimized '2:0 & not (0 + 1)'
2202 $ try -p optimized '2:0 & not (0 + 1)'
2203 * optimized:
2203 * optimized:
2204 (difference
2204 (difference
2205 (range
2205 (range
2206 (symbol '2')
2206 (symbol '2')
2207 (symbol '0'))
2207 (symbol '0'))
2208 (func
2208 (func
2209 (symbol '_list')
2209 (symbol '_list')
2210 (string '0\x001')))
2210 (string '0\x001')))
2211 * set:
2211 * set:
2212 <filteredset
2212 <filteredset
2213 <spanset- 0:3>,
2213 <spanset- 0:3>,
2214 <not
2214 <not
2215 <baseset [0, 1]>>>
2215 <baseset [0, 1]>>>
2216 2
2216 2
2217
2217
2218 $ try -p optimized '2:0 & not (0:2 & (0 + 1))'
2218 $ try -p optimized '2:0 & not (0:2 & (0 + 1))'
2219 * optimized:
2219 * optimized:
2220 (difference
2220 (difference
2221 (range
2221 (range
2222 (symbol '2')
2222 (symbol '2')
2223 (symbol '0'))
2223 (symbol '0'))
2224 (and
2224 (and
2225 (range
2225 (range
2226 (symbol '0')
2226 (symbol '0')
2227 (symbol '2'))
2227 (symbol '2'))
2228 (func
2228 (func
2229 (symbol '_list')
2229 (symbol '_list')
2230 (string '0\x001'))))
2230 (string '0\x001'))))
2231 * set:
2231 * set:
2232 <filteredset
2232 <filteredset
2233 <spanset- 0:3>,
2233 <spanset- 0:3>,
2234 <not
2234 <not
2235 <baseset [0, 1]>>>
2235 <baseset [0, 1]>>>
2236 2
2236 2
2237
2237
2238 because 'present()' does nothing other than suppressing an error, the
2238 because 'present()' does nothing other than suppressing an error, the
2239 ordering requirement should be forwarded to the nested expression
2239 ordering requirement should be forwarded to the nested expression
2240
2240
2241 $ try -p optimized 'present(2 + 0 + 1)'
2241 $ try -p optimized 'present(2 + 0 + 1)'
2242 * optimized:
2242 * optimized:
2243 (func
2243 (func
2244 (symbol 'present')
2244 (symbol 'present')
2245 (func
2245 (func
2246 (symbol '_list')
2246 (symbol '_list')
2247 (string '2\x000\x001')))
2247 (string '2\x000\x001')))
2248 * set:
2248 * set:
2249 <baseset [2, 0, 1]>
2249 <baseset [2, 0, 1]>
2250 2
2250 2
2251 0
2251 0
2252 1
2252 1
2253
2253
2254 $ try --optimize '2:0 & present(0 + 1 + 2)'
2254 $ try --optimize '2:0 & present(0 + 1 + 2)'
2255 (and
2255 (and
2256 (range
2256 (range
2257 (symbol '2')
2257 (symbol '2')
2258 (symbol '0'))
2258 (symbol '0'))
2259 (func
2259 (func
2260 (symbol 'present')
2260 (symbol 'present')
2261 (or
2261 (or
2262 (list
2262 (list
2263 (symbol '0')
2263 (symbol '0')
2264 (symbol '1')
2264 (symbol '1')
2265 (symbol '2')))))
2265 (symbol '2')))))
2266 * optimized:
2266 * optimized:
2267 (and
2267 (and
2268 (range
2268 (range
2269 (symbol '2')
2269 (symbol '2')
2270 (symbol '0'))
2270 (symbol '0'))
2271 (func
2271 (func
2272 (symbol 'present')
2272 (symbol 'present')
2273 (func
2273 (func
2274 (symbol '_list')
2274 (symbol '_list')
2275 (string '0\x001\x002'))))
2275 (string '0\x001\x002'))))
2276 * set:
2276 * set:
2277 <filteredset
2277 <filteredset
2278 <spanset- 0:3>,
2278 <spanset- 0:3>,
2279 <baseset [0, 1, 2]>>
2279 <baseset [0, 1, 2]>>
2280 2
2280 2
2281 1
2281 1
2282 0
2282 0
2283
2283
2284 'reverse()' should take effect only if it is the outermost expression:
2284 'reverse()' should take effect only if it is the outermost expression:
2285
2285
2286 $ try --optimize '0:2 & reverse(all())'
2286 $ try --optimize '0:2 & reverse(all())'
2287 (and
2287 (and
2288 (range
2288 (range
2289 (symbol '0')
2289 (symbol '0')
2290 (symbol '2'))
2290 (symbol '2'))
2291 (func
2291 (func
2292 (symbol 'reverse')
2292 (symbol 'reverse')
2293 (func
2293 (func
2294 (symbol 'all')
2294 (symbol 'all')
2295 None)))
2295 None)))
2296 * optimized:
2296 * optimized:
2297 (and
2297 (and
2298 (range
2298 (range
2299 (symbol '0')
2299 (symbol '0')
2300 (symbol '2'))
2300 (symbol '2'))
2301 (func
2301 (func
2302 (symbol 'reverse')
2302 (symbol 'reverse')
2303 (func
2303 (func
2304 (symbol 'all')
2304 (symbol 'all')
2305 None)))
2305 None)))
2306 * set:
2306 * set:
2307 <filteredset
2307 <filteredset
2308 <spanset+ 0:3>,
2308 <spanset+ 0:3>,
2309 <spanset+ 0:10>>
2309 <spanset+ 0:10>>
2310 0
2310 0
2311 1
2311 1
2312 2
2312 2
2313
2313
2314 'sort()' should take effect only if it is the outermost expression:
2314 'sort()' should take effect only if it is the outermost expression:
2315
2315
2316 $ try --optimize '0:2 & sort(all(), -rev)'
2316 $ try --optimize '0:2 & sort(all(), -rev)'
2317 (and
2317 (and
2318 (range
2318 (range
2319 (symbol '0')
2319 (symbol '0')
2320 (symbol '2'))
2320 (symbol '2'))
2321 (func
2321 (func
2322 (symbol 'sort')
2322 (symbol 'sort')
2323 (list
2323 (list
2324 (func
2324 (func
2325 (symbol 'all')
2325 (symbol 'all')
2326 None)
2326 None)
2327 (negate
2327 (negate
2328 (symbol 'rev')))))
2328 (symbol 'rev')))))
2329 * optimized:
2329 * optimized:
2330 (and
2330 (and
2331 (range
2331 (range
2332 (symbol '0')
2332 (symbol '0')
2333 (symbol '2'))
2333 (symbol '2'))
2334 (func
2334 (func
2335 (symbol 'sort')
2335 (symbol 'sort')
2336 (list
2336 (list
2337 (func
2337 (func
2338 (symbol 'all')
2338 (symbol 'all')
2339 None)
2339 None)
2340 (string '-rev'))))
2340 (string '-rev'))))
2341 * set:
2341 * set:
2342 <filteredset
2342 <filteredset
2343 <spanset+ 0:3>,
2343 <spanset+ 0:3>,
2344 <spanset+ 0:10>>
2344 <spanset+ 0:10>>
2345 0
2345 0
2346 1
2346 1
2347 2
2347 2
2348
2348
2349 invalid argument passed to noop sort():
2349 invalid argument passed to noop sort():
2350
2350
2351 $ log '0:2 & sort()'
2351 $ log '0:2 & sort()'
2352 hg: parse error: sort requires one or two arguments
2352 hg: parse error: sort requires one or two arguments
2353 [255]
2353 [255]
2354 $ log '0:2 & sort(all(), -invalid)'
2354 $ log '0:2 & sort(all(), -invalid)'
2355 hg: parse error: unknown sort key '-invalid'
2355 hg: parse error: unknown sort key '-invalid'
2356 [255]
2356 [255]
2357
2357
2358 for 'A & f(B)', 'B' should not be affected by the order of 'A':
2358 for 'A & f(B)', 'B' should not be affected by the order of 'A':
2359
2359
2360 $ try --optimize '2:0 & first(1 + 0 + 2)'
2360 $ try --optimize '2:0 & first(1 + 0 + 2)'
2361 (and
2361 (and
2362 (range
2362 (range
2363 (symbol '2')
2363 (symbol '2')
2364 (symbol '0'))
2364 (symbol '0'))
2365 (func
2365 (func
2366 (symbol 'first')
2366 (symbol 'first')
2367 (or
2367 (or
2368 (list
2368 (list
2369 (symbol '1')
2369 (symbol '1')
2370 (symbol '0')
2370 (symbol '0')
2371 (symbol '2')))))
2371 (symbol '2')))))
2372 * optimized:
2372 * optimized:
2373 (and
2373 (and
2374 (range
2374 (range
2375 (symbol '2')
2375 (symbol '2')
2376 (symbol '0'))
2376 (symbol '0'))
2377 (func
2377 (func
2378 (symbol 'first')
2378 (symbol 'first')
2379 (func
2379 (func
2380 (symbol '_list')
2380 (symbol '_list')
2381 (string '1\x000\x002'))))
2381 (string '1\x000\x002'))))
2382 * set:
2382 * set:
2383 <filteredset
2383 <filteredset
2384 <baseset [1]>,
2384 <baseset [1]>,
2385 <spanset- 0:3>>
2385 <spanset- 0:3>>
2386 1
2386 1
2387
2387
2388 $ try --optimize '2:0 & not last(0 + 2 + 1)'
2388 $ try --optimize '2:0 & not last(0 + 2 + 1)'
2389 (and
2389 (and
2390 (range
2390 (range
2391 (symbol '2')
2391 (symbol '2')
2392 (symbol '0'))
2392 (symbol '0'))
2393 (not
2393 (not
2394 (func
2394 (func
2395 (symbol 'last')
2395 (symbol 'last')
2396 (or
2396 (or
2397 (list
2397 (list
2398 (symbol '0')
2398 (symbol '0')
2399 (symbol '2')
2399 (symbol '2')
2400 (symbol '1'))))))
2400 (symbol '1'))))))
2401 * optimized:
2401 * optimized:
2402 (difference
2402 (difference
2403 (range
2403 (range
2404 (symbol '2')
2404 (symbol '2')
2405 (symbol '0'))
2405 (symbol '0'))
2406 (func
2406 (func
2407 (symbol 'last')
2407 (symbol 'last')
2408 (func
2408 (func
2409 (symbol '_list')
2409 (symbol '_list')
2410 (string '0\x002\x001'))))
2410 (string '0\x002\x001'))))
2411 * set:
2411 * set:
2412 <filteredset
2412 <filteredset
2413 <spanset- 0:3>,
2413 <spanset- 0:3>,
2414 <not
2414 <not
2415 <baseset [1]>>>
2415 <baseset [1]>>>
2416 2
2416 2
2417 0
2417 0
2418
2418
2419 for 'A & (op)(B)', 'B' should not be affected by the order of 'A':
2419 for 'A & (op)(B)', 'B' should not be affected by the order of 'A':
2420
2420
2421 $ try --optimize '2:0 & (1 + 0 + 2):(0 + 2 + 1)'
2421 $ try --optimize '2:0 & (1 + 0 + 2):(0 + 2 + 1)'
2422 (and
2422 (and
2423 (range
2423 (range
2424 (symbol '2')
2424 (symbol '2')
2425 (symbol '0'))
2425 (symbol '0'))
2426 (range
2426 (range
2427 (group
2427 (group
2428 (or
2428 (or
2429 (list
2429 (list
2430 (symbol '1')
2430 (symbol '1')
2431 (symbol '0')
2431 (symbol '0')
2432 (symbol '2'))))
2432 (symbol '2'))))
2433 (group
2433 (group
2434 (or
2434 (or
2435 (list
2435 (list
2436 (symbol '0')
2436 (symbol '0')
2437 (symbol '2')
2437 (symbol '2')
2438 (symbol '1'))))))
2438 (symbol '1'))))))
2439 * optimized:
2439 * optimized:
2440 (and
2440 (and
2441 (range
2441 (range
2442 (symbol '2')
2442 (symbol '2')
2443 (symbol '0'))
2443 (symbol '0'))
2444 (range
2444 (range
2445 (func
2445 (func
2446 (symbol '_list')
2446 (symbol '_list')
2447 (string '1\x000\x002'))
2447 (string '1\x000\x002'))
2448 (func
2448 (func
2449 (symbol '_list')
2449 (symbol '_list')
2450 (string '0\x002\x001'))))
2450 (string '0\x002\x001'))))
2451 * set:
2451 * set:
2452 <filteredset
2452 <filteredset
2453 <spanset- 0:3>,
2453 <spanset- 0:3>,
2454 <baseset [1]>>
2454 <baseset [1]>>
2455 1
2455 1
2456
2456
2457 'A & B' can be rewritten as 'flipand(B, A)' by weight.
2457 'A & B' can be rewritten as 'flipand(B, A)' by weight.
2458
2458
2459 $ try --optimize 'contains("glob:*") & (2 + 0 + 1)'
2459 $ try --optimize 'contains("glob:*") & (2 + 0 + 1)'
2460 (and
2460 (and
2461 (func
2461 (func
2462 (symbol 'contains')
2462 (symbol 'contains')
2463 (string 'glob:*'))
2463 (string 'glob:*'))
2464 (group
2464 (group
2465 (or
2465 (or
2466 (list
2466 (list
2467 (symbol '2')
2467 (symbol '2')
2468 (symbol '0')
2468 (symbol '0')
2469 (symbol '1')))))
2469 (symbol '1')))))
2470 * optimized:
2470 * optimized:
2471 (andsmally
2471 (andsmally
2472 (func
2472 (func
2473 (symbol 'contains')
2473 (symbol 'contains')
2474 (string 'glob:*'))
2474 (string 'glob:*'))
2475 (func
2475 (func
2476 (symbol '_list')
2476 (symbol '_list')
2477 (string '2\x000\x001')))
2477 (string '2\x000\x001')))
2478 * set:
2478 * set:
2479 <filteredset
2479 <filteredset
2480 <baseset+ [0, 1, 2]>,
2480 <baseset+ [0, 1, 2]>,
2481 <contains 'glob:*'>>
2481 <contains 'glob:*'>>
2482 0
2482 0
2483 1
2483 1
2484 2
2484 2
2485
2485
2486 and in this example, 'A & B' is rewritten as 'B & A', but 'A' overrides
2486 and in this example, 'A & B' is rewritten as 'B & A', but 'A' overrides
2487 the order appropriately:
2487 the order appropriately:
2488
2488
2489 $ try --optimize 'reverse(contains("glob:*")) & (0 + 2 + 1)'
2489 $ try --optimize 'reverse(contains("glob:*")) & (0 + 2 + 1)'
2490 (and
2490 (and
2491 (func
2491 (func
2492 (symbol 'reverse')
2492 (symbol 'reverse')
2493 (func
2493 (func
2494 (symbol 'contains')
2494 (symbol 'contains')
2495 (string 'glob:*')))
2495 (string 'glob:*')))
2496 (group
2496 (group
2497 (or
2497 (or
2498 (list
2498 (list
2499 (symbol '0')
2499 (symbol '0')
2500 (symbol '2')
2500 (symbol '2')
2501 (symbol '1')))))
2501 (symbol '1')))))
2502 * optimized:
2502 * optimized:
2503 (andsmally
2503 (andsmally
2504 (func
2504 (func
2505 (symbol 'reverse')
2505 (symbol 'reverse')
2506 (func
2506 (func
2507 (symbol 'contains')
2507 (symbol 'contains')
2508 (string 'glob:*')))
2508 (string 'glob:*')))
2509 (func
2509 (func
2510 (symbol '_list')
2510 (symbol '_list')
2511 (string '0\x002\x001')))
2511 (string '0\x002\x001')))
2512 * set:
2512 * set:
2513 <filteredset
2513 <filteredset
2514 <baseset- [0, 1, 2]>,
2514 <baseset- [0, 1, 2]>,
2515 <contains 'glob:*'>>
2515 <contains 'glob:*'>>
2516 2
2516 2
2517 1
2517 1
2518 0
2518 0
2519
2519
2520 test sort revset
2520 test sort revset
2521 --------------------------------------------
2521 --------------------------------------------
2522
2522
2523 test when adding two unordered revsets
2523 test when adding two unordered revsets
2524
2524
2525 $ log 'sort(keyword(issue) or modifies(b))'
2525 $ log 'sort(keyword(issue) or modifies(b))'
2526 4
2526 4
2527 6
2527 6
2528
2528
2529 test when sorting a reversed collection in the same way it is
2529 test when sorting a reversed collection in the same way it is
2530
2530
2531 $ log 'sort(reverse(all()), -rev)'
2531 $ log 'sort(reverse(all()), -rev)'
2532 9
2532 9
2533 8
2533 8
2534 7
2534 7
2535 6
2535 6
2536 5
2536 5
2537 4
2537 4
2538 3
2538 3
2539 2
2539 2
2540 1
2540 1
2541 0
2541 0
2542
2542
2543 test when sorting a reversed collection
2543 test when sorting a reversed collection
2544
2544
2545 $ log 'sort(reverse(all()), rev)'
2545 $ log 'sort(reverse(all()), rev)'
2546 0
2546 0
2547 1
2547 1
2548 2
2548 2
2549 3
2549 3
2550 4
2550 4
2551 5
2551 5
2552 6
2552 6
2553 7
2553 7
2554 8
2554 8
2555 9
2555 9
2556
2556
2557
2557
2558 test sorting two sorted collections in different orders
2558 test sorting two sorted collections in different orders
2559
2559
2560 $ log 'sort(outgoing() or reverse(removes(a)), rev)'
2560 $ log 'sort(outgoing() or reverse(removes(a)), rev)'
2561 2
2561 2
2562 6
2562 6
2563 8
2563 8
2564 9
2564 9
2565
2565
2566 test sorting two sorted collections in different orders backwards
2566 test sorting two sorted collections in different orders backwards
2567
2567
2568 $ log 'sort(outgoing() or reverse(removes(a)), -rev)'
2568 $ log 'sort(outgoing() or reverse(removes(a)), -rev)'
2569 9
2569 9
2570 8
2570 8
2571 6
2571 6
2572 2
2572 2
2573
2573
2574 test empty sort key which is noop
2574 test empty sort key which is noop
2575
2575
2576 $ log 'sort(0 + 2 + 1, "")'
2576 $ log 'sort(0 + 2 + 1, "")'
2577 0
2577 0
2578 2
2578 2
2579 1
2579 1
2580
2580
2581 test invalid sort keys
2581 test invalid sort keys
2582
2582
2583 $ log 'sort(all(), -invalid)'
2583 $ log 'sort(all(), -invalid)'
2584 hg: parse error: unknown sort key '-invalid'
2584 hg: parse error: unknown sort key '-invalid'
2585 [255]
2585 [255]
2586
2586
2587 $ cd ..
2587 $ cd ..
2588
2588
2589 test sorting by multiple keys including variable-length strings
2589 test sorting by multiple keys including variable-length strings
2590
2590
2591 $ hg init sorting
2591 $ hg init sorting
2592 $ cd sorting
2592 $ cd sorting
2593 $ cat <<EOF >> .hg/hgrc
2593 $ cat <<EOF >> .hg/hgrc
2594 > [ui]
2594 > [ui]
2595 > logtemplate = '{rev} {branch|p5}{desc|p5}{author|p5}{date|hgdate}\n'
2595 > logtemplate = '{rev} {branch|p5}{desc|p5}{author|p5}{date|hgdate}\n'
2596 > [templatealias]
2596 > [templatealias]
2597 > p5(s) = pad(s, 5)
2597 > p5(s) = pad(s, 5)
2598 > EOF
2598 > EOF
2599 $ hg branch -qf b12
2599 $ hg branch -qf b12
2600 $ hg ci -m m111 -u u112 -d '111 10800'
2600 $ hg ci -m m111 -u u112 -d '111 10800'
2601 $ hg branch -qf b11
2601 $ hg branch -qf b11
2602 $ hg ci -m m12 -u u111 -d '112 7200'
2602 $ hg ci -m m12 -u u111 -d '112 7200'
2603 $ hg branch -qf b111
2603 $ hg branch -qf b111
2604 $ hg ci -m m11 -u u12 -d '111 3600'
2604 $ hg ci -m m11 -u u12 -d '111 3600'
2605 $ hg branch -qf b112
2605 $ hg branch -qf b112
2606 $ hg ci -m m111 -u u11 -d '120 0'
2606 $ hg ci -m m111 -u u11 -d '120 0'
2607 $ hg branch -qf b111
2607 $ hg branch -qf b111
2608 $ hg ci -m m112 -u u111 -d '110 14400'
2608 $ hg ci -m m112 -u u111 -d '110 14400'
2609 created new head
2609 created new head
2610
2610
2611 compare revisions (has fast path):
2611 compare revisions (has fast path):
2612
2612
2613 $ hg log -r 'sort(all(), rev)'
2613 $ hg log -r 'sort(all(), rev)'
2614 0 b12 m111 u112 111 10800
2614 0 b12 m111 u112 111 10800
2615 1 b11 m12 u111 112 7200
2615 1 b11 m12 u111 112 7200
2616 2 b111 m11 u12 111 3600
2616 2 b111 m11 u12 111 3600
2617 3 b112 m111 u11 120 0
2617 3 b112 m111 u11 120 0
2618 4 b111 m112 u111 110 14400
2618 4 b111 m112 u111 110 14400
2619
2619
2620 $ hg log -r 'sort(all(), -rev)'
2620 $ hg log -r 'sort(all(), -rev)'
2621 4 b111 m112 u111 110 14400
2621 4 b111 m112 u111 110 14400
2622 3 b112 m111 u11 120 0
2622 3 b112 m111 u11 120 0
2623 2 b111 m11 u12 111 3600
2623 2 b111 m11 u12 111 3600
2624 1 b11 m12 u111 112 7200
2624 1 b11 m12 u111 112 7200
2625 0 b12 m111 u112 111 10800
2625 0 b12 m111 u112 111 10800
2626
2626
2627 compare variable-length strings (issue5218):
2627 compare variable-length strings (issue5218):
2628
2628
2629 $ hg log -r 'sort(all(), branch)'
2629 $ hg log -r 'sort(all(), branch)'
2630 1 b11 m12 u111 112 7200
2630 1 b11 m12 u111 112 7200
2631 2 b111 m11 u12 111 3600
2631 2 b111 m11 u12 111 3600
2632 4 b111 m112 u111 110 14400
2632 4 b111 m112 u111 110 14400
2633 3 b112 m111 u11 120 0
2633 3 b112 m111 u11 120 0
2634 0 b12 m111 u112 111 10800
2634 0 b12 m111 u112 111 10800
2635
2635
2636 $ hg log -r 'sort(all(), -branch)'
2636 $ hg log -r 'sort(all(), -branch)'
2637 0 b12 m111 u112 111 10800
2637 0 b12 m111 u112 111 10800
2638 3 b112 m111 u11 120 0
2638 3 b112 m111 u11 120 0
2639 2 b111 m11 u12 111 3600
2639 2 b111 m11 u12 111 3600
2640 4 b111 m112 u111 110 14400
2640 4 b111 m112 u111 110 14400
2641 1 b11 m12 u111 112 7200
2641 1 b11 m12 u111 112 7200
2642
2642
2643 $ hg log -r 'sort(all(), desc)'
2643 $ hg log -r 'sort(all(), desc)'
2644 2 b111 m11 u12 111 3600
2644 2 b111 m11 u12 111 3600
2645 0 b12 m111 u112 111 10800
2645 0 b12 m111 u112 111 10800
2646 3 b112 m111 u11 120 0
2646 3 b112 m111 u11 120 0
2647 4 b111 m112 u111 110 14400
2647 4 b111 m112 u111 110 14400
2648 1 b11 m12 u111 112 7200
2648 1 b11 m12 u111 112 7200
2649
2649
2650 $ hg log -r 'sort(all(), -desc)'
2650 $ hg log -r 'sort(all(), -desc)'
2651 1 b11 m12 u111 112 7200
2651 1 b11 m12 u111 112 7200
2652 4 b111 m112 u111 110 14400
2652 4 b111 m112 u111 110 14400
2653 0 b12 m111 u112 111 10800
2653 0 b12 m111 u112 111 10800
2654 3 b112 m111 u11 120 0
2654 3 b112 m111 u11 120 0
2655 2 b111 m11 u12 111 3600
2655 2 b111 m11 u12 111 3600
2656
2656
2657 $ hg log -r 'sort(all(), user)'
2657 $ hg log -r 'sort(all(), user)'
2658 3 b112 m111 u11 120 0
2658 3 b112 m111 u11 120 0
2659 1 b11 m12 u111 112 7200
2659 1 b11 m12 u111 112 7200
2660 4 b111 m112 u111 110 14400
2660 4 b111 m112 u111 110 14400
2661 0 b12 m111 u112 111 10800
2661 0 b12 m111 u112 111 10800
2662 2 b111 m11 u12 111 3600
2662 2 b111 m11 u12 111 3600
2663
2663
2664 $ hg log -r 'sort(all(), -user)'
2664 $ hg log -r 'sort(all(), -user)'
2665 2 b111 m11 u12 111 3600
2665 2 b111 m11 u12 111 3600
2666 0 b12 m111 u112 111 10800
2666 0 b12 m111 u112 111 10800
2667 1 b11 m12 u111 112 7200
2667 1 b11 m12 u111 112 7200
2668 4 b111 m112 u111 110 14400
2668 4 b111 m112 u111 110 14400
2669 3 b112 m111 u11 120 0
2669 3 b112 m111 u11 120 0
2670
2670
2671 compare dates (tz offset should have no effect):
2671 compare dates (tz offset should have no effect):
2672
2672
2673 $ hg log -r 'sort(all(), date)'
2673 $ hg log -r 'sort(all(), date)'
2674 4 b111 m112 u111 110 14400
2674 4 b111 m112 u111 110 14400
2675 0 b12 m111 u112 111 10800
2675 0 b12 m111 u112 111 10800
2676 2 b111 m11 u12 111 3600
2676 2 b111 m11 u12 111 3600
2677 1 b11 m12 u111 112 7200
2677 1 b11 m12 u111 112 7200
2678 3 b112 m111 u11 120 0
2678 3 b112 m111 u11 120 0
2679
2679
2680 $ hg log -r 'sort(all(), -date)'
2680 $ hg log -r 'sort(all(), -date)'
2681 3 b112 m111 u11 120 0
2681 3 b112 m111 u11 120 0
2682 1 b11 m12 u111 112 7200
2682 1 b11 m12 u111 112 7200
2683 0 b12 m111 u112 111 10800
2683 0 b12 m111 u112 111 10800
2684 2 b111 m11 u12 111 3600
2684 2 b111 m11 u12 111 3600
2685 4 b111 m112 u111 110 14400
2685 4 b111 m112 u111 110 14400
2686
2686
2687 be aware that 'sort(x, -k)' is not exactly the same as 'reverse(sort(x, k))'
2687 be aware that 'sort(x, -k)' is not exactly the same as 'reverse(sort(x, k))'
2688 because '-k' reverses the comparison, not the list itself:
2688 because '-k' reverses the comparison, not the list itself:
2689
2689
2690 $ hg log -r 'sort(0 + 2, date)'
2690 $ hg log -r 'sort(0 + 2, date)'
2691 0 b12 m111 u112 111 10800
2691 0 b12 m111 u112 111 10800
2692 2 b111 m11 u12 111 3600
2692 2 b111 m11 u12 111 3600
2693
2693
2694 $ hg log -r 'sort(0 + 2, -date)'
2694 $ hg log -r 'sort(0 + 2, -date)'
2695 0 b12 m111 u112 111 10800
2695 0 b12 m111 u112 111 10800
2696 2 b111 m11 u12 111 3600
2696 2 b111 m11 u12 111 3600
2697
2697
2698 $ hg log -r 'reverse(sort(0 + 2, date))'
2698 $ hg log -r 'reverse(sort(0 + 2, date))'
2699 2 b111 m11 u12 111 3600
2699 2 b111 m11 u12 111 3600
2700 0 b12 m111 u112 111 10800
2700 0 b12 m111 u112 111 10800
2701
2701
2702 sort by multiple keys:
2702 sort by multiple keys:
2703
2703
2704 $ hg log -r 'sort(all(), "branch -rev")'
2704 $ hg log -r 'sort(all(), "branch -rev")'
2705 1 b11 m12 u111 112 7200
2705 1 b11 m12 u111 112 7200
2706 4 b111 m112 u111 110 14400
2706 4 b111 m112 u111 110 14400
2707 2 b111 m11 u12 111 3600
2707 2 b111 m11 u12 111 3600
2708 3 b112 m111 u11 120 0
2708 3 b112 m111 u11 120 0
2709 0 b12 m111 u112 111 10800
2709 0 b12 m111 u112 111 10800
2710
2710
2711 $ hg log -r 'sort(all(), "-desc -date")'
2711 $ hg log -r 'sort(all(), "-desc -date")'
2712 1 b11 m12 u111 112 7200
2712 1 b11 m12 u111 112 7200
2713 4 b111 m112 u111 110 14400
2713 4 b111 m112 u111 110 14400
2714 3 b112 m111 u11 120 0
2714 3 b112 m111 u11 120 0
2715 0 b12 m111 u112 111 10800
2715 0 b12 m111 u112 111 10800
2716 2 b111 m11 u12 111 3600
2716 2 b111 m11 u12 111 3600
2717
2717
2718 $ hg log -r 'sort(all(), "user -branch date rev")'
2718 $ hg log -r 'sort(all(), "user -branch date rev")'
2719 3 b112 m111 u11 120 0
2719 3 b112 m111 u11 120 0
2720 4 b111 m112 u111 110 14400
2720 4 b111 m112 u111 110 14400
2721 1 b11 m12 u111 112 7200
2721 1 b11 m12 u111 112 7200
2722 0 b12 m111 u112 111 10800
2722 0 b12 m111 u112 111 10800
2723 2 b111 m11 u12 111 3600
2723 2 b111 m11 u12 111 3600
2724
2724
2725 toposort prioritises graph branches
2725 toposort prioritises graph branches
2726
2726
2727 $ hg up 2
2727 $ hg up 2
2728 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2728 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2729 $ touch a
2729 $ touch a
2730 $ hg addremove
2730 $ hg addremove
2731 adding a
2731 adding a
2732 $ hg ci -m 't1' -u 'tu' -d '130 0'
2732 $ hg ci -m 't1' -u 'tu' -d '130 0'
2733 created new head
2733 created new head
2734 $ echo 'a' >> a
2734 $ echo 'a' >> a
2735 $ hg ci -m 't2' -u 'tu' -d '130 0'
2735 $ hg ci -m 't2' -u 'tu' -d '130 0'
2736 $ hg book book1
2736 $ hg book book1
2737 $ hg up 4
2737 $ hg up 4
2738 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2738 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2739 (leaving bookmark book1)
2739 (leaving bookmark book1)
2740 $ touch a
2740 $ touch a
2741 $ hg addremove
2741 $ hg addremove
2742 adding a
2742 adding a
2743 $ hg ci -m 't3' -u 'tu' -d '130 0'
2743 $ hg ci -m 't3' -u 'tu' -d '130 0'
2744
2744
2745 $ hg log -r 'sort(all(), topo)'
2745 $ hg log -r 'sort(all(), topo)'
2746 7 b111 t3 tu 130 0
2746 7 b111 t3 tu 130 0
2747 4 b111 m112 u111 110 14400
2747 4 b111 m112 u111 110 14400
2748 3 b112 m111 u11 120 0
2748 3 b112 m111 u11 120 0
2749 6 b111 t2 tu 130 0
2749 6 b111 t2 tu 130 0
2750 5 b111 t1 tu 130 0
2750 5 b111 t1 tu 130 0
2751 2 b111 m11 u12 111 3600
2751 2 b111 m11 u12 111 3600
2752 1 b11 m12 u111 112 7200
2752 1 b11 m12 u111 112 7200
2753 0 b12 m111 u112 111 10800
2753 0 b12 m111 u112 111 10800
2754
2754
2755 $ hg log -r 'sort(all(), -topo)'
2755 $ hg log -r 'sort(all(), -topo)'
2756 0 b12 m111 u112 111 10800
2756 0 b12 m111 u112 111 10800
2757 1 b11 m12 u111 112 7200
2757 1 b11 m12 u111 112 7200
2758 2 b111 m11 u12 111 3600
2758 2 b111 m11 u12 111 3600
2759 5 b111 t1 tu 130 0
2759 5 b111 t1 tu 130 0
2760 6 b111 t2 tu 130 0
2760 6 b111 t2 tu 130 0
2761 3 b112 m111 u11 120 0
2761 3 b112 m111 u11 120 0
2762 4 b111 m112 u111 110 14400
2762 4 b111 m112 u111 110 14400
2763 7 b111 t3 tu 130 0
2763 7 b111 t3 tu 130 0
2764
2764
2765 $ hg log -r 'sort(all(), topo, topo.firstbranch=book1)'
2765 $ hg log -r 'sort(all(), topo, topo.firstbranch=book1)'
2766 6 b111 t2 tu 130 0
2766 6 b111 t2 tu 130 0
2767 5 b111 t1 tu 130 0
2767 5 b111 t1 tu 130 0
2768 7 b111 t3 tu 130 0
2768 7 b111 t3 tu 130 0
2769 4 b111 m112 u111 110 14400
2769 4 b111 m112 u111 110 14400
2770 3 b112 m111 u11 120 0
2770 3 b112 m111 u11 120 0
2771 2 b111 m11 u12 111 3600
2771 2 b111 m11 u12 111 3600
2772 1 b11 m12 u111 112 7200
2772 1 b11 m12 u111 112 7200
2773 0 b12 m111 u112 111 10800
2773 0 b12 m111 u112 111 10800
2774
2774
2775 topographical sorting can't be combined with other sort keys, and you can't
2775 topographical sorting can't be combined with other sort keys, and you can't
2776 use the topo.firstbranch option when topo sort is not active:
2776 use the topo.firstbranch option when topo sort is not active:
2777
2777
2778 $ hg log -r 'sort(all(), "topo user")'
2778 $ hg log -r 'sort(all(), "topo user")'
2779 hg: parse error: topo sort order cannot be combined with other sort keys
2779 hg: parse error: topo sort order cannot be combined with other sort keys
2780 [255]
2780 [255]
2781
2781
2782 $ hg log -r 'sort(all(), user, topo.firstbranch=book1)'
2782 $ hg log -r 'sort(all(), user, topo.firstbranch=book1)'
2783 hg: parse error: topo.firstbranch can only be used when using the topo sort key
2783 hg: parse error: topo.firstbranch can only be used when using the topo sort key
2784 [255]
2784 [255]
2785
2785
2786 topo.firstbranch should accept any kind of expressions:
2786 topo.firstbranch should accept any kind of expressions:
2787
2787
2788 $ hg log -r 'sort(0, topo, topo.firstbranch=(book1))'
2788 $ hg log -r 'sort(0, topo, topo.firstbranch=(book1))'
2789 0 b12 m111 u112 111 10800
2789 0 b12 m111 u112 111 10800
2790
2790
2791 $ cd ..
2791 $ cd ..
2792 $ cd repo
2792 $ cd repo
2793
2793
2794 test multiline revset with errors
2794 test multiline revset with errors
2795
2795
2796 $ echo > multiline-revset
2796 $ echo > multiline-revset
2797 $ echo '. +' >> multiline-revset
2797 $ echo '. +' >> multiline-revset
2798 $ echo '.^ +' >> multiline-revset
2798 $ echo '.^ +' >> multiline-revset
2799 $ hg log -r "`cat multiline-revset`"
2799 $ hg log -r "`cat multiline-revset`"
2800 hg: parse error at 9: not a prefix: end
2800 hg: parse error at 9: not a prefix: end
2801 ( . + .^ +
2801 ( . + .^ +
2802 ^ here)
2802 ^ here)
2803 [255]
2803 [255]
2804 $ hg debugrevspec -v 'revset(first(rev(0)))' -p all
2805 * parsed:
2806 (func
2807 (symbol 'revset')
2808 (func
2809 (symbol 'first')
2810 (func
2811 (symbol 'rev')
2812 (symbol '0'))))
2813 * expanded:
2814 (func
2815 (symbol 'revset')
2816 (func
2817 (symbol 'first')
2818 (func
2819 (symbol 'rev')
2820 (symbol '0'))))
2821 * concatenated:
2822 (func
2823 (symbol 'revset')
2824 (func
2825 (symbol 'first')
2826 (func
2827 (symbol 'rev')
2828 (symbol '0'))))
2829 * analyzed:
2830 (func
2831 (symbol 'first')
2832 (func
2833 (symbol 'rev')
2834 (symbol '0')))
2835 * optimized:
2836 (func
2837 (symbol 'first')
2838 (func
2839 (symbol 'rev')
2840 (symbol '0')))
2841 * set:
2842 <baseset+ [0]>
2843 0
General Comments 0
You need to be logged in to leave comments. Login now