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