##// END OF EJS Templates
revset: define successors revset...
Jun Wu -
r33377:5d63e5f4 default
parent child Browse files
Show More
@@ -1,2064 +1,2087 b''
1 # revset.py - revision set queries for mercurial
1 # revset.py - revision set queries for mercurial
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 re
10 import re
11
11
12 from .i18n import _
12 from .i18n import _
13 from . import (
13 from . import (
14 dagop,
14 dagop,
15 destutil,
15 destutil,
16 encoding,
16 encoding,
17 error,
17 error,
18 hbisect,
18 hbisect,
19 match as matchmod,
19 match as matchmod,
20 node,
20 node,
21 obsolete as obsmod,
21 obsolete as obsmod,
22 obsutil,
22 pathutil,
23 pathutil,
23 phases,
24 phases,
24 registrar,
25 registrar,
25 repoview,
26 repoview,
26 revsetlang,
27 revsetlang,
27 scmutil,
28 scmutil,
28 smartset,
29 smartset,
29 util,
30 util,
30 )
31 )
31
32
32 # helpers for processing parsed tree
33 # helpers for processing parsed tree
33 getsymbol = revsetlang.getsymbol
34 getsymbol = revsetlang.getsymbol
34 getstring = revsetlang.getstring
35 getstring = revsetlang.getstring
35 getinteger = revsetlang.getinteger
36 getinteger = revsetlang.getinteger
36 getboolean = revsetlang.getboolean
37 getboolean = revsetlang.getboolean
37 getlist = revsetlang.getlist
38 getlist = revsetlang.getlist
38 getrange = revsetlang.getrange
39 getrange = revsetlang.getrange
39 getargs = revsetlang.getargs
40 getargs = revsetlang.getargs
40 getargsdict = revsetlang.getargsdict
41 getargsdict = revsetlang.getargsdict
41
42
42 # constants used as an argument of match() and matchany()
43 # constants used as an argument of match() and matchany()
43 anyorder = revsetlang.anyorder
44 anyorder = revsetlang.anyorder
44 defineorder = revsetlang.defineorder
45 defineorder = revsetlang.defineorder
45 followorder = revsetlang.followorder
46 followorder = revsetlang.followorder
46
47
47 baseset = smartset.baseset
48 baseset = smartset.baseset
48 generatorset = smartset.generatorset
49 generatorset = smartset.generatorset
49 spanset = smartset.spanset
50 spanset = smartset.spanset
50 fullreposet = smartset.fullreposet
51 fullreposet = smartset.fullreposet
51
52
52 # helpers
53 # helpers
53
54
54 def getset(repo, subset, x):
55 def getset(repo, subset, x):
55 if not x:
56 if not x:
56 raise error.ParseError(_("missing argument"))
57 raise error.ParseError(_("missing argument"))
57 return methods[x[0]](repo, subset, *x[1:])
58 return methods[x[0]](repo, subset, *x[1:])
58
59
59 def _getrevsource(repo, r):
60 def _getrevsource(repo, r):
60 extra = repo[r].extra()
61 extra = repo[r].extra()
61 for label in ('source', 'transplant_source', 'rebase_source'):
62 for label in ('source', 'transplant_source', 'rebase_source'):
62 if label in extra:
63 if label in extra:
63 try:
64 try:
64 return repo[extra[label]].rev()
65 return repo[extra[label]].rev()
65 except error.RepoLookupError:
66 except error.RepoLookupError:
66 pass
67 pass
67 return None
68 return None
68
69
69 # operator methods
70 # operator methods
70
71
71 def stringset(repo, subset, x):
72 def stringset(repo, subset, x):
72 x = scmutil.intrev(repo[x])
73 x = scmutil.intrev(repo[x])
73 if (x in subset
74 if (x in subset
74 or x == node.nullrev and isinstance(subset, fullreposet)):
75 or x == node.nullrev and isinstance(subset, fullreposet)):
75 return baseset([x])
76 return baseset([x])
76 return baseset()
77 return baseset()
77
78
78 def rangeset(repo, subset, x, y, order):
79 def rangeset(repo, subset, x, y, order):
79 m = getset(repo, fullreposet(repo), x)
80 m = getset(repo, fullreposet(repo), x)
80 n = getset(repo, fullreposet(repo), y)
81 n = getset(repo, fullreposet(repo), y)
81
82
82 if not m or not n:
83 if not m or not n:
83 return baseset()
84 return baseset()
84 return _makerangeset(repo, subset, m.first(), n.last(), order)
85 return _makerangeset(repo, subset, m.first(), n.last(), order)
85
86
86 def rangeall(repo, subset, x, order):
87 def rangeall(repo, subset, x, order):
87 assert x is None
88 assert x is None
88 return _makerangeset(repo, subset, 0, len(repo) - 1, order)
89 return _makerangeset(repo, subset, 0, len(repo) - 1, order)
89
90
90 def rangepre(repo, subset, y, order):
91 def rangepre(repo, subset, y, order):
91 # ':y' can't be rewritten to '0:y' since '0' may be hidden
92 # ':y' can't be rewritten to '0:y' since '0' may be hidden
92 n = getset(repo, fullreposet(repo), y)
93 n = getset(repo, fullreposet(repo), y)
93 if not n:
94 if not n:
94 return baseset()
95 return baseset()
95 return _makerangeset(repo, subset, 0, n.last(), order)
96 return _makerangeset(repo, subset, 0, n.last(), order)
96
97
97 def rangepost(repo, subset, x, order):
98 def rangepost(repo, subset, x, order):
98 m = getset(repo, fullreposet(repo), x)
99 m = getset(repo, fullreposet(repo), x)
99 if not m:
100 if not m:
100 return baseset()
101 return baseset()
101 return _makerangeset(repo, subset, m.first(), len(repo) - 1, order)
102 return _makerangeset(repo, subset, m.first(), len(repo) - 1, order)
102
103
103 def _makerangeset(repo, subset, m, n, order):
104 def _makerangeset(repo, subset, m, n, order):
104 if m == n:
105 if m == n:
105 r = baseset([m])
106 r = baseset([m])
106 elif n == node.wdirrev:
107 elif n == node.wdirrev:
107 r = spanset(repo, m, len(repo)) + baseset([n])
108 r = spanset(repo, m, len(repo)) + baseset([n])
108 elif m == node.wdirrev:
109 elif m == node.wdirrev:
109 r = baseset([m]) + spanset(repo, len(repo) - 1, n - 1)
110 r = baseset([m]) + spanset(repo, len(repo) - 1, n - 1)
110 elif m < n:
111 elif m < n:
111 r = spanset(repo, m, n + 1)
112 r = spanset(repo, m, n + 1)
112 else:
113 else:
113 r = spanset(repo, m, n - 1)
114 r = spanset(repo, m, n - 1)
114
115
115 if order == defineorder:
116 if order == defineorder:
116 return r & subset
117 return r & subset
117 else:
118 else:
118 # carrying the sorting over when possible would be more efficient
119 # carrying the sorting over when possible would be more efficient
119 return subset & r
120 return subset & r
120
121
121 def dagrange(repo, subset, x, y, order):
122 def dagrange(repo, subset, x, y, order):
122 r = fullreposet(repo)
123 r = fullreposet(repo)
123 xs = dagop.reachableroots(repo, getset(repo, r, x), getset(repo, r, y),
124 xs = dagop.reachableroots(repo, getset(repo, r, x), getset(repo, r, y),
124 includepath=True)
125 includepath=True)
125 return subset & xs
126 return subset & xs
126
127
127 def andset(repo, subset, x, y, order):
128 def andset(repo, subset, x, y, order):
128 return getset(repo, getset(repo, subset, x), y)
129 return getset(repo, getset(repo, subset, x), y)
129
130
130 def differenceset(repo, subset, x, y, order):
131 def differenceset(repo, subset, x, y, order):
131 return getset(repo, subset, x) - getset(repo, subset, y)
132 return getset(repo, subset, x) - getset(repo, subset, y)
132
133
133 def _orsetlist(repo, subset, xs):
134 def _orsetlist(repo, subset, xs):
134 assert xs
135 assert xs
135 if len(xs) == 1:
136 if len(xs) == 1:
136 return getset(repo, subset, xs[0])
137 return getset(repo, subset, xs[0])
137 p = len(xs) // 2
138 p = len(xs) // 2
138 a = _orsetlist(repo, subset, xs[:p])
139 a = _orsetlist(repo, subset, xs[:p])
139 b = _orsetlist(repo, subset, xs[p:])
140 b = _orsetlist(repo, subset, xs[p:])
140 return a + b
141 return a + b
141
142
142 def orset(repo, subset, x, order):
143 def orset(repo, subset, x, order):
143 xs = getlist(x)
144 xs = getlist(x)
144 if order == followorder:
145 if order == followorder:
145 # slow path to take the subset order
146 # slow path to take the subset order
146 return subset & _orsetlist(repo, fullreposet(repo), xs)
147 return subset & _orsetlist(repo, fullreposet(repo), xs)
147 else:
148 else:
148 return _orsetlist(repo, subset, xs)
149 return _orsetlist(repo, subset, xs)
149
150
150 def notset(repo, subset, x, order):
151 def notset(repo, subset, x, order):
151 return subset - getset(repo, subset, x)
152 return subset - getset(repo, subset, x)
152
153
153 def listset(repo, subset, *xs):
154 def listset(repo, subset, *xs):
154 raise error.ParseError(_("can't use a list in this context"),
155 raise error.ParseError(_("can't use a list in this context"),
155 hint=_('see hg help "revsets.x or y"'))
156 hint=_('see hg help "revsets.x or y"'))
156
157
157 def keyvaluepair(repo, subset, k, v):
158 def keyvaluepair(repo, subset, k, v):
158 raise error.ParseError(_("can't use a key-value pair in this context"))
159 raise error.ParseError(_("can't use a key-value pair in this context"))
159
160
160 def func(repo, subset, a, b, order):
161 def func(repo, subset, a, b, order):
161 f = getsymbol(a)
162 f = getsymbol(a)
162 if f in symbols:
163 if f in symbols:
163 func = symbols[f]
164 func = symbols[f]
164 if getattr(func, '_takeorder', False):
165 if getattr(func, '_takeorder', False):
165 return func(repo, subset, b, order)
166 return func(repo, subset, b, order)
166 return func(repo, subset, b)
167 return func(repo, subset, b)
167
168
168 keep = lambda fn: getattr(fn, '__doc__', None) is not None
169 keep = lambda fn: getattr(fn, '__doc__', None) is not None
169
170
170 syms = [s for (s, fn) in symbols.items() if keep(fn)]
171 syms = [s for (s, fn) in symbols.items() if keep(fn)]
171 raise error.UnknownIdentifier(f, syms)
172 raise error.UnknownIdentifier(f, syms)
172
173
173 # functions
174 # functions
174
175
175 # symbols are callables like:
176 # symbols are callables like:
176 # fn(repo, subset, x)
177 # fn(repo, subset, x)
177 # with:
178 # with:
178 # repo - current repository instance
179 # repo - current repository instance
179 # subset - of revisions to be examined
180 # subset - of revisions to be examined
180 # x - argument in tree form
181 # x - argument in tree form
181 symbols = {}
182 symbols = {}
182
183
183 # symbols which can't be used for a DoS attack for any given input
184 # symbols which can't be used for a DoS attack for any given input
184 # (e.g. those which accept regexes as plain strings shouldn't be included)
185 # (e.g. those which accept regexes as plain strings shouldn't be included)
185 # functions that just return a lot of changesets (like all) don't count here
186 # functions that just return a lot of changesets (like all) don't count here
186 safesymbols = set()
187 safesymbols = set()
187
188
188 predicate = registrar.revsetpredicate()
189 predicate = registrar.revsetpredicate()
189
190
190 @predicate('_destupdate')
191 @predicate('_destupdate')
191 def _destupdate(repo, subset, x):
192 def _destupdate(repo, subset, x):
192 # experimental revset for update destination
193 # experimental revset for update destination
193 args = getargsdict(x, 'limit', 'clean')
194 args = getargsdict(x, 'limit', 'clean')
194 return subset & baseset([destutil.destupdate(repo, **args)[0]])
195 return subset & baseset([destutil.destupdate(repo, **args)[0]])
195
196
196 @predicate('_destmerge')
197 @predicate('_destmerge')
197 def _destmerge(repo, subset, x):
198 def _destmerge(repo, subset, x):
198 # experimental revset for merge destination
199 # experimental revset for merge destination
199 sourceset = None
200 sourceset = None
200 if x is not None:
201 if x is not None:
201 sourceset = getset(repo, fullreposet(repo), x)
202 sourceset = getset(repo, fullreposet(repo), x)
202 return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)])
203 return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)])
203
204
204 @predicate('adds(pattern)', safe=True)
205 @predicate('adds(pattern)', safe=True)
205 def adds(repo, subset, x):
206 def adds(repo, subset, x):
206 """Changesets that add a file matching pattern.
207 """Changesets that add a file matching pattern.
207
208
208 The pattern without explicit kind like ``glob:`` is expected to be
209 The pattern without explicit kind like ``glob:`` is expected to be
209 relative to the current directory and match against a file or a
210 relative to the current directory and match against a file or a
210 directory.
211 directory.
211 """
212 """
212 # i18n: "adds" is a keyword
213 # i18n: "adds" is a keyword
213 pat = getstring(x, _("adds requires a pattern"))
214 pat = getstring(x, _("adds requires a pattern"))
214 return checkstatus(repo, subset, pat, 1)
215 return checkstatus(repo, subset, pat, 1)
215
216
216 @predicate('ancestor(*changeset)', safe=True)
217 @predicate('ancestor(*changeset)', safe=True)
217 def ancestor(repo, subset, x):
218 def ancestor(repo, subset, x):
218 """A greatest common ancestor of the changesets.
219 """A greatest common ancestor of the changesets.
219
220
220 Accepts 0 or more changesets.
221 Accepts 0 or more changesets.
221 Will return empty list when passed no args.
222 Will return empty list when passed no args.
222 Greatest common ancestor of a single changeset is that changeset.
223 Greatest common ancestor of a single changeset is that changeset.
223 """
224 """
224 # i18n: "ancestor" is a keyword
225 # i18n: "ancestor" is a keyword
225 l = getlist(x)
226 l = getlist(x)
226 rl = fullreposet(repo)
227 rl = fullreposet(repo)
227 anc = None
228 anc = None
228
229
229 # (getset(repo, rl, i) for i in l) generates a list of lists
230 # (getset(repo, rl, i) for i in l) generates a list of lists
230 for revs in (getset(repo, rl, i) for i in l):
231 for revs in (getset(repo, rl, i) for i in l):
231 for r in revs:
232 for r in revs:
232 if anc is None:
233 if anc is None:
233 anc = repo[r]
234 anc = repo[r]
234 else:
235 else:
235 anc = anc.ancestor(repo[r])
236 anc = anc.ancestor(repo[r])
236
237
237 if anc is not None and anc.rev() in subset:
238 if anc is not None and anc.rev() in subset:
238 return baseset([anc.rev()])
239 return baseset([anc.rev()])
239 return baseset()
240 return baseset()
240
241
241 def _ancestors(repo, subset, x, followfirst=False, startdepth=None,
242 def _ancestors(repo, subset, x, followfirst=False, startdepth=None,
242 stopdepth=None):
243 stopdepth=None):
243 heads = getset(repo, fullreposet(repo), x)
244 heads = getset(repo, fullreposet(repo), x)
244 if not heads:
245 if not heads:
245 return baseset()
246 return baseset()
246 s = dagop.revancestors(repo, heads, followfirst, startdepth, stopdepth)
247 s = dagop.revancestors(repo, heads, followfirst, startdepth, stopdepth)
247 return subset & s
248 return subset & s
248
249
249 @predicate('ancestors(set[, depth])', safe=True)
250 @predicate('ancestors(set[, depth])', safe=True)
250 def ancestors(repo, subset, x):
251 def ancestors(repo, subset, x):
251 """Changesets that are ancestors of changesets in set, including the
252 """Changesets that are ancestors of changesets in set, including the
252 given changesets themselves.
253 given changesets themselves.
253
254
254 If depth is specified, the result only includes changesets up to
255 If depth is specified, the result only includes changesets up to
255 the specified generation.
256 the specified generation.
256 """
257 """
257 # startdepth is for internal use only until we can decide the UI
258 # startdepth is for internal use only until we can decide the UI
258 args = getargsdict(x, 'ancestors', 'set depth startdepth')
259 args = getargsdict(x, 'ancestors', 'set depth startdepth')
259 if 'set' not in args:
260 if 'set' not in args:
260 # i18n: "ancestors" is a keyword
261 # i18n: "ancestors" is a keyword
261 raise error.ParseError(_('ancestors takes at least 1 argument'))
262 raise error.ParseError(_('ancestors takes at least 1 argument'))
262 startdepth = stopdepth = None
263 startdepth = stopdepth = None
263 if 'startdepth' in args:
264 if 'startdepth' in args:
264 n = getinteger(args['startdepth'],
265 n = getinteger(args['startdepth'],
265 "ancestors expects an integer startdepth")
266 "ancestors expects an integer startdepth")
266 if n < 0:
267 if n < 0:
267 raise error.ParseError("negative startdepth")
268 raise error.ParseError("negative startdepth")
268 startdepth = n
269 startdepth = n
269 if 'depth' in args:
270 if 'depth' in args:
270 # i18n: "ancestors" is a keyword
271 # i18n: "ancestors" is a keyword
271 n = getinteger(args['depth'], _("ancestors expects an integer depth"))
272 n = getinteger(args['depth'], _("ancestors expects an integer depth"))
272 if n < 0:
273 if n < 0:
273 raise error.ParseError(_("negative depth"))
274 raise error.ParseError(_("negative depth"))
274 stopdepth = n + 1
275 stopdepth = n + 1
275 return _ancestors(repo, subset, args['set'],
276 return _ancestors(repo, subset, args['set'],
276 startdepth=startdepth, stopdepth=stopdepth)
277 startdepth=startdepth, stopdepth=stopdepth)
277
278
278 @predicate('_firstancestors', safe=True)
279 @predicate('_firstancestors', safe=True)
279 def _firstancestors(repo, subset, x):
280 def _firstancestors(repo, subset, x):
280 # ``_firstancestors(set)``
281 # ``_firstancestors(set)``
281 # Like ``ancestors(set)`` but follows only the first parents.
282 # Like ``ancestors(set)`` but follows only the first parents.
282 return _ancestors(repo, subset, x, followfirst=True)
283 return _ancestors(repo, subset, x, followfirst=True)
283
284
284 def _childrenspec(repo, subset, x, n, order):
285 def _childrenspec(repo, subset, x, n, order):
285 """Changesets that are the Nth child of a changeset
286 """Changesets that are the Nth child of a changeset
286 in set.
287 in set.
287 """
288 """
288 cs = set()
289 cs = set()
289 for r in getset(repo, fullreposet(repo), x):
290 for r in getset(repo, fullreposet(repo), x):
290 for i in range(n):
291 for i in range(n):
291 c = repo[r].children()
292 c = repo[r].children()
292 if len(c) == 0:
293 if len(c) == 0:
293 break
294 break
294 if len(c) > 1:
295 if len(c) > 1:
295 raise error.RepoLookupError(
296 raise error.RepoLookupError(
296 _("revision in set has more than one child"))
297 _("revision in set has more than one child"))
297 r = c[0].rev()
298 r = c[0].rev()
298 else:
299 else:
299 cs.add(r)
300 cs.add(r)
300 return subset & cs
301 return subset & cs
301
302
302 def ancestorspec(repo, subset, x, n, order):
303 def ancestorspec(repo, subset, x, n, order):
303 """``set~n``
304 """``set~n``
304 Changesets that are the Nth ancestor (first parents only) of a changeset
305 Changesets that are the Nth ancestor (first parents only) of a changeset
305 in set.
306 in set.
306 """
307 """
307 n = getinteger(n, _("~ expects a number"))
308 n = getinteger(n, _("~ expects a number"))
308 if n < 0:
309 if n < 0:
309 # children lookup
310 # children lookup
310 return _childrenspec(repo, subset, x, -n, order)
311 return _childrenspec(repo, subset, x, -n, order)
311 ps = set()
312 ps = set()
312 cl = repo.changelog
313 cl = repo.changelog
313 for r in getset(repo, fullreposet(repo), x):
314 for r in getset(repo, fullreposet(repo), x):
314 for i in range(n):
315 for i in range(n):
315 try:
316 try:
316 r = cl.parentrevs(r)[0]
317 r = cl.parentrevs(r)[0]
317 except error.WdirUnsupported:
318 except error.WdirUnsupported:
318 r = repo[r].parents()[0].rev()
319 r = repo[r].parents()[0].rev()
319 ps.add(r)
320 ps.add(r)
320 return subset & ps
321 return subset & ps
321
322
322 @predicate('author(string)', safe=True)
323 @predicate('author(string)', safe=True)
323 def author(repo, subset, x):
324 def author(repo, subset, x):
324 """Alias for ``user(string)``.
325 """Alias for ``user(string)``.
325 """
326 """
326 # i18n: "author" is a keyword
327 # i18n: "author" is a keyword
327 n = getstring(x, _("author requires a string"))
328 n = getstring(x, _("author requires a string"))
328 kind, pattern, matcher = _substringmatcher(n, casesensitive=False)
329 kind, pattern, matcher = _substringmatcher(n, casesensitive=False)
329 return subset.filter(lambda x: matcher(repo[x].user()),
330 return subset.filter(lambda x: matcher(repo[x].user()),
330 condrepr=('<user %r>', n))
331 condrepr=('<user %r>', n))
331
332
332 @predicate('bisect(string)', safe=True)
333 @predicate('bisect(string)', safe=True)
333 def bisect(repo, subset, x):
334 def bisect(repo, subset, x):
334 """Changesets marked in the specified bisect status:
335 """Changesets marked in the specified bisect status:
335
336
336 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
337 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
337 - ``goods``, ``bads`` : csets topologically good/bad
338 - ``goods``, ``bads`` : csets topologically good/bad
338 - ``range`` : csets taking part in the bisection
339 - ``range`` : csets taking part in the bisection
339 - ``pruned`` : csets that are goods, bads or skipped
340 - ``pruned`` : csets that are goods, bads or skipped
340 - ``untested`` : csets whose fate is yet unknown
341 - ``untested`` : csets whose fate is yet unknown
341 - ``ignored`` : csets ignored due to DAG topology
342 - ``ignored`` : csets ignored due to DAG topology
342 - ``current`` : the cset currently being bisected
343 - ``current`` : the cset currently being bisected
343 """
344 """
344 # i18n: "bisect" is a keyword
345 # i18n: "bisect" is a keyword
345 status = getstring(x, _("bisect requires a string")).lower()
346 status = getstring(x, _("bisect requires a string")).lower()
346 state = set(hbisect.get(repo, status))
347 state = set(hbisect.get(repo, status))
347 return subset & state
348 return subset & state
348
349
349 # Backward-compatibility
350 # Backward-compatibility
350 # - no help entry so that we do not advertise it any more
351 # - no help entry so that we do not advertise it any more
351 @predicate('bisected', safe=True)
352 @predicate('bisected', safe=True)
352 def bisected(repo, subset, x):
353 def bisected(repo, subset, x):
353 return bisect(repo, subset, x)
354 return bisect(repo, subset, x)
354
355
355 @predicate('bookmark([name])', safe=True)
356 @predicate('bookmark([name])', safe=True)
356 def bookmark(repo, subset, x):
357 def bookmark(repo, subset, x):
357 """The named bookmark or all bookmarks.
358 """The named bookmark or all bookmarks.
358
359
359 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`.
360 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`.
360 """
361 """
361 # i18n: "bookmark" is a keyword
362 # i18n: "bookmark" is a keyword
362 args = getargs(x, 0, 1, _('bookmark takes one or no arguments'))
363 args = getargs(x, 0, 1, _('bookmark takes one or no arguments'))
363 if args:
364 if args:
364 bm = getstring(args[0],
365 bm = getstring(args[0],
365 # i18n: "bookmark" is a keyword
366 # i18n: "bookmark" is a keyword
366 _('the argument to bookmark must be a string'))
367 _('the argument to bookmark must be a string'))
367 kind, pattern, matcher = util.stringmatcher(bm)
368 kind, pattern, matcher = util.stringmatcher(bm)
368 bms = set()
369 bms = set()
369 if kind == 'literal':
370 if kind == 'literal':
370 bmrev = repo._bookmarks.get(pattern, None)
371 bmrev = repo._bookmarks.get(pattern, None)
371 if not bmrev:
372 if not bmrev:
372 raise error.RepoLookupError(_("bookmark '%s' does not exist")
373 raise error.RepoLookupError(_("bookmark '%s' does not exist")
373 % pattern)
374 % pattern)
374 bms.add(repo[bmrev].rev())
375 bms.add(repo[bmrev].rev())
375 else:
376 else:
376 matchrevs = set()
377 matchrevs = set()
377 for name, bmrev in repo._bookmarks.iteritems():
378 for name, bmrev in repo._bookmarks.iteritems():
378 if matcher(name):
379 if matcher(name):
379 matchrevs.add(bmrev)
380 matchrevs.add(bmrev)
380 if not matchrevs:
381 if not matchrevs:
381 raise error.RepoLookupError(_("no bookmarks exist"
382 raise error.RepoLookupError(_("no bookmarks exist"
382 " that match '%s'") % pattern)
383 " that match '%s'") % pattern)
383 for bmrev in matchrevs:
384 for bmrev in matchrevs:
384 bms.add(repo[bmrev].rev())
385 bms.add(repo[bmrev].rev())
385 else:
386 else:
386 bms = {repo[r].rev() for r in repo._bookmarks.values()}
387 bms = {repo[r].rev() for r in repo._bookmarks.values()}
387 bms -= {node.nullrev}
388 bms -= {node.nullrev}
388 return subset & bms
389 return subset & bms
389
390
390 @predicate('branch(string or set)', safe=True)
391 @predicate('branch(string or set)', safe=True)
391 def branch(repo, subset, x):
392 def branch(repo, subset, x):
392 """
393 """
393 All changesets belonging to the given branch or the branches of the given
394 All changesets belonging to the given branch or the branches of the given
394 changesets.
395 changesets.
395
396
396 Pattern matching is supported for `string`. See
397 Pattern matching is supported for `string`. See
397 :hg:`help revisions.patterns`.
398 :hg:`help revisions.patterns`.
398 """
399 """
399 getbi = repo.revbranchcache().branchinfo
400 getbi = repo.revbranchcache().branchinfo
400 def getbranch(r):
401 def getbranch(r):
401 try:
402 try:
402 return getbi(r)[0]
403 return getbi(r)[0]
403 except error.WdirUnsupported:
404 except error.WdirUnsupported:
404 return repo[r].branch()
405 return repo[r].branch()
405
406
406 try:
407 try:
407 b = getstring(x, '')
408 b = getstring(x, '')
408 except error.ParseError:
409 except error.ParseError:
409 # not a string, but another revspec, e.g. tip()
410 # not a string, but another revspec, e.g. tip()
410 pass
411 pass
411 else:
412 else:
412 kind, pattern, matcher = util.stringmatcher(b)
413 kind, pattern, matcher = util.stringmatcher(b)
413 if kind == 'literal':
414 if kind == 'literal':
414 # note: falls through to the revspec case if no branch with
415 # note: falls through to the revspec case if no branch with
415 # this name exists and pattern kind is not specified explicitly
416 # this name exists and pattern kind is not specified explicitly
416 if pattern in repo.branchmap():
417 if pattern in repo.branchmap():
417 return subset.filter(lambda r: matcher(getbranch(r)),
418 return subset.filter(lambda r: matcher(getbranch(r)),
418 condrepr=('<branch %r>', b))
419 condrepr=('<branch %r>', b))
419 if b.startswith('literal:'):
420 if b.startswith('literal:'):
420 raise error.RepoLookupError(_("branch '%s' does not exist")
421 raise error.RepoLookupError(_("branch '%s' does not exist")
421 % pattern)
422 % pattern)
422 else:
423 else:
423 return subset.filter(lambda r: matcher(getbranch(r)),
424 return subset.filter(lambda r: matcher(getbranch(r)),
424 condrepr=('<branch %r>', b))
425 condrepr=('<branch %r>', b))
425
426
426 s = getset(repo, fullreposet(repo), x)
427 s = getset(repo, fullreposet(repo), x)
427 b = set()
428 b = set()
428 for r in s:
429 for r in s:
429 b.add(getbranch(r))
430 b.add(getbranch(r))
430 c = s.__contains__
431 c = s.__contains__
431 return subset.filter(lambda r: c(r) or getbranch(r) in b,
432 return subset.filter(lambda r: c(r) or getbranch(r) in b,
432 condrepr=lambda: '<branch %r>' % sorted(b))
433 condrepr=lambda: '<branch %r>' % sorted(b))
433
434
434 @predicate('bumped()', safe=True)
435 @predicate('bumped()', safe=True)
435 def bumped(repo, subset, x):
436 def bumped(repo, subset, x):
436 """Mutable changesets marked as successors of public changesets.
437 """Mutable changesets marked as successors of public changesets.
437
438
438 Only non-public and non-obsolete changesets can be `bumped`.
439 Only non-public and non-obsolete changesets can be `bumped`.
439 """
440 """
440 # i18n: "bumped" is a keyword
441 # i18n: "bumped" is a keyword
441 getargs(x, 0, 0, _("bumped takes no arguments"))
442 getargs(x, 0, 0, _("bumped takes no arguments"))
442 bumped = obsmod.getrevs(repo, 'bumped')
443 bumped = obsmod.getrevs(repo, 'bumped')
443 return subset & bumped
444 return subset & bumped
444
445
445 @predicate('bundle()', safe=True)
446 @predicate('bundle()', safe=True)
446 def bundle(repo, subset, x):
447 def bundle(repo, subset, x):
447 """Changesets in the bundle.
448 """Changesets in the bundle.
448
449
449 Bundle must be specified by the -R option."""
450 Bundle must be specified by the -R option."""
450
451
451 try:
452 try:
452 bundlerevs = repo.changelog.bundlerevs
453 bundlerevs = repo.changelog.bundlerevs
453 except AttributeError:
454 except AttributeError:
454 raise error.Abort(_("no bundle provided - specify with -R"))
455 raise error.Abort(_("no bundle provided - specify with -R"))
455 return subset & bundlerevs
456 return subset & bundlerevs
456
457
457 def checkstatus(repo, subset, pat, field):
458 def checkstatus(repo, subset, pat, field):
458 hasset = matchmod.patkind(pat) == 'set'
459 hasset = matchmod.patkind(pat) == 'set'
459
460
460 mcache = [None]
461 mcache = [None]
461 def matches(x):
462 def matches(x):
462 c = repo[x]
463 c = repo[x]
463 if not mcache[0] or hasset:
464 if not mcache[0] or hasset:
464 mcache[0] = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
465 mcache[0] = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
465 m = mcache[0]
466 m = mcache[0]
466 fname = None
467 fname = None
467 if not m.anypats() and len(m.files()) == 1:
468 if not m.anypats() and len(m.files()) == 1:
468 fname = m.files()[0]
469 fname = m.files()[0]
469 if fname is not None:
470 if fname is not None:
470 if fname not in c.files():
471 if fname not in c.files():
471 return False
472 return False
472 else:
473 else:
473 for f in c.files():
474 for f in c.files():
474 if m(f):
475 if m(f):
475 break
476 break
476 else:
477 else:
477 return False
478 return False
478 files = repo.status(c.p1().node(), c.node())[field]
479 files = repo.status(c.p1().node(), c.node())[field]
479 if fname is not None:
480 if fname is not None:
480 if fname in files:
481 if fname in files:
481 return True
482 return True
482 else:
483 else:
483 for f in files:
484 for f in files:
484 if m(f):
485 if m(f):
485 return True
486 return True
486
487
487 return subset.filter(matches, condrepr=('<status[%r] %r>', field, pat))
488 return subset.filter(matches, condrepr=('<status[%r] %r>', field, pat))
488
489
489 def _children(repo, subset, parentset):
490 def _children(repo, subset, parentset):
490 if not parentset:
491 if not parentset:
491 return baseset()
492 return baseset()
492 cs = set()
493 cs = set()
493 pr = repo.changelog.parentrevs
494 pr = repo.changelog.parentrevs
494 minrev = parentset.min()
495 minrev = parentset.min()
495 nullrev = node.nullrev
496 nullrev = node.nullrev
496 for r in subset:
497 for r in subset:
497 if r <= minrev:
498 if r <= minrev:
498 continue
499 continue
499 p1, p2 = pr(r)
500 p1, p2 = pr(r)
500 if p1 in parentset:
501 if p1 in parentset:
501 cs.add(r)
502 cs.add(r)
502 if p2 != nullrev and p2 in parentset:
503 if p2 != nullrev and p2 in parentset:
503 cs.add(r)
504 cs.add(r)
504 return baseset(cs)
505 return baseset(cs)
505
506
506 @predicate('children(set)', safe=True)
507 @predicate('children(set)', safe=True)
507 def children(repo, subset, x):
508 def children(repo, subset, x):
508 """Child changesets of changesets in set.
509 """Child changesets of changesets in set.
509 """
510 """
510 s = getset(repo, fullreposet(repo), x)
511 s = getset(repo, fullreposet(repo), x)
511 cs = _children(repo, subset, s)
512 cs = _children(repo, subset, s)
512 return subset & cs
513 return subset & cs
513
514
514 @predicate('closed()', safe=True)
515 @predicate('closed()', safe=True)
515 def closed(repo, subset, x):
516 def closed(repo, subset, x):
516 """Changeset is closed.
517 """Changeset is closed.
517 """
518 """
518 # i18n: "closed" is a keyword
519 # i18n: "closed" is a keyword
519 getargs(x, 0, 0, _("closed takes no arguments"))
520 getargs(x, 0, 0, _("closed takes no arguments"))
520 return subset.filter(lambda r: repo[r].closesbranch(),
521 return subset.filter(lambda r: repo[r].closesbranch(),
521 condrepr='<branch closed>')
522 condrepr='<branch closed>')
522
523
523 @predicate('contains(pattern)')
524 @predicate('contains(pattern)')
524 def contains(repo, subset, x):
525 def contains(repo, subset, x):
525 """The revision's manifest contains a file matching pattern (but might not
526 """The revision's manifest contains a file matching pattern (but might not
526 modify it). See :hg:`help patterns` for information about file patterns.
527 modify it). See :hg:`help patterns` for information about file patterns.
527
528
528 The pattern without explicit kind like ``glob:`` is expected to be
529 The pattern without explicit kind like ``glob:`` is expected to be
529 relative to the current directory and match against a file exactly
530 relative to the current directory and match against a file exactly
530 for efficiency.
531 for efficiency.
531 """
532 """
532 # i18n: "contains" is a keyword
533 # i18n: "contains" is a keyword
533 pat = getstring(x, _("contains requires a pattern"))
534 pat = getstring(x, _("contains requires a pattern"))
534
535
535 def matches(x):
536 def matches(x):
536 if not matchmod.patkind(pat):
537 if not matchmod.patkind(pat):
537 pats = pathutil.canonpath(repo.root, repo.getcwd(), pat)
538 pats = pathutil.canonpath(repo.root, repo.getcwd(), pat)
538 if pats in repo[x]:
539 if pats in repo[x]:
539 return True
540 return True
540 else:
541 else:
541 c = repo[x]
542 c = repo[x]
542 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
543 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
543 for f in c.manifest():
544 for f in c.manifest():
544 if m(f):
545 if m(f):
545 return True
546 return True
546 return False
547 return False
547
548
548 return subset.filter(matches, condrepr=('<contains %r>', pat))
549 return subset.filter(matches, condrepr=('<contains %r>', pat))
549
550
550 @predicate('converted([id])', safe=True)
551 @predicate('converted([id])', safe=True)
551 def converted(repo, subset, x):
552 def converted(repo, subset, x):
552 """Changesets converted from the given identifier in the old repository if
553 """Changesets converted from the given identifier in the old repository if
553 present, or all converted changesets if no identifier is specified.
554 present, or all converted changesets if no identifier is specified.
554 """
555 """
555
556
556 # There is exactly no chance of resolving the revision, so do a simple
557 # There is exactly no chance of resolving the revision, so do a simple
557 # string compare and hope for the best
558 # string compare and hope for the best
558
559
559 rev = None
560 rev = None
560 # i18n: "converted" is a keyword
561 # i18n: "converted" is a keyword
561 l = getargs(x, 0, 1, _('converted takes one or no arguments'))
562 l = getargs(x, 0, 1, _('converted takes one or no arguments'))
562 if l:
563 if l:
563 # i18n: "converted" is a keyword
564 # i18n: "converted" is a keyword
564 rev = getstring(l[0], _('converted requires a revision'))
565 rev = getstring(l[0], _('converted requires a revision'))
565
566
566 def _matchvalue(r):
567 def _matchvalue(r):
567 source = repo[r].extra().get('convert_revision', None)
568 source = repo[r].extra().get('convert_revision', None)
568 return source is not None and (rev is None or source.startswith(rev))
569 return source is not None and (rev is None or source.startswith(rev))
569
570
570 return subset.filter(lambda r: _matchvalue(r),
571 return subset.filter(lambda r: _matchvalue(r),
571 condrepr=('<converted %r>', rev))
572 condrepr=('<converted %r>', rev))
572
573
573 @predicate('date(interval)', safe=True)
574 @predicate('date(interval)', safe=True)
574 def date(repo, subset, x):
575 def date(repo, subset, x):
575 """Changesets within the interval, see :hg:`help dates`.
576 """Changesets within the interval, see :hg:`help dates`.
576 """
577 """
577 # i18n: "date" is a keyword
578 # i18n: "date" is a keyword
578 ds = getstring(x, _("date requires a string"))
579 ds = getstring(x, _("date requires a string"))
579 dm = util.matchdate(ds)
580 dm = util.matchdate(ds)
580 return subset.filter(lambda x: dm(repo[x].date()[0]),
581 return subset.filter(lambda x: dm(repo[x].date()[0]),
581 condrepr=('<date %r>', ds))
582 condrepr=('<date %r>', ds))
582
583
583 @predicate('desc(string)', safe=True)
584 @predicate('desc(string)', safe=True)
584 def desc(repo, subset, x):
585 def desc(repo, subset, x):
585 """Search commit message for string. The match is case-insensitive.
586 """Search commit message for string. The match is case-insensitive.
586
587
587 Pattern matching is supported for `string`. See
588 Pattern matching is supported for `string`. See
588 :hg:`help revisions.patterns`.
589 :hg:`help revisions.patterns`.
589 """
590 """
590 # i18n: "desc" is a keyword
591 # i18n: "desc" is a keyword
591 ds = getstring(x, _("desc requires a string"))
592 ds = getstring(x, _("desc requires a string"))
592
593
593 kind, pattern, matcher = _substringmatcher(ds, casesensitive=False)
594 kind, pattern, matcher = _substringmatcher(ds, casesensitive=False)
594
595
595 return subset.filter(lambda r: matcher(repo[r].description()),
596 return subset.filter(lambda r: matcher(repo[r].description()),
596 condrepr=('<desc %r>', ds))
597 condrepr=('<desc %r>', ds))
597
598
598 def _descendants(repo, subset, x, followfirst=False, startdepth=None,
599 def _descendants(repo, subset, x, followfirst=False, startdepth=None,
599 stopdepth=None):
600 stopdepth=None):
600 roots = getset(repo, fullreposet(repo), x)
601 roots = getset(repo, fullreposet(repo), x)
601 if not roots:
602 if not roots:
602 return baseset()
603 return baseset()
603 s = dagop.revdescendants(repo, roots, followfirst, startdepth, stopdepth)
604 s = dagop.revdescendants(repo, roots, followfirst, startdepth, stopdepth)
604 return subset & s
605 return subset & s
605
606
606 @predicate('descendants(set[, depth])', safe=True)
607 @predicate('descendants(set[, depth])', safe=True)
607 def descendants(repo, subset, x):
608 def descendants(repo, subset, x):
608 """Changesets which are descendants of changesets in set, including the
609 """Changesets which are descendants of changesets in set, including the
609 given changesets themselves.
610 given changesets themselves.
610
611
611 If depth is specified, the result only includes changesets up to
612 If depth is specified, the result only includes changesets up to
612 the specified generation.
613 the specified generation.
613 """
614 """
614 # startdepth is for internal use only until we can decide the UI
615 # startdepth is for internal use only until we can decide the UI
615 args = getargsdict(x, 'descendants', 'set depth startdepth')
616 args = getargsdict(x, 'descendants', 'set depth startdepth')
616 if 'set' not in args:
617 if 'set' not in args:
617 # i18n: "descendants" is a keyword
618 # i18n: "descendants" is a keyword
618 raise error.ParseError(_('descendants takes at least 1 argument'))
619 raise error.ParseError(_('descendants takes at least 1 argument'))
619 startdepth = stopdepth = None
620 startdepth = stopdepth = None
620 if 'startdepth' in args:
621 if 'startdepth' in args:
621 n = getinteger(args['startdepth'],
622 n = getinteger(args['startdepth'],
622 "descendants expects an integer startdepth")
623 "descendants expects an integer startdepth")
623 if n < 0:
624 if n < 0:
624 raise error.ParseError("negative startdepth")
625 raise error.ParseError("negative startdepth")
625 startdepth = n
626 startdepth = n
626 if 'depth' in args:
627 if 'depth' in args:
627 # i18n: "descendants" is a keyword
628 # i18n: "descendants" is a keyword
628 n = getinteger(args['depth'], _("descendants expects an integer depth"))
629 n = getinteger(args['depth'], _("descendants expects an integer depth"))
629 if n < 0:
630 if n < 0:
630 raise error.ParseError(_("negative depth"))
631 raise error.ParseError(_("negative depth"))
631 stopdepth = n + 1
632 stopdepth = n + 1
632 return _descendants(repo, subset, args['set'],
633 return _descendants(repo, subset, args['set'],
633 startdepth=startdepth, stopdepth=stopdepth)
634 startdepth=startdepth, stopdepth=stopdepth)
634
635
635 @predicate('_firstdescendants', safe=True)
636 @predicate('_firstdescendants', safe=True)
636 def _firstdescendants(repo, subset, x):
637 def _firstdescendants(repo, subset, x):
637 # ``_firstdescendants(set)``
638 # ``_firstdescendants(set)``
638 # Like ``descendants(set)`` but follows only the first parents.
639 # Like ``descendants(set)`` but follows only the first parents.
639 return _descendants(repo, subset, x, followfirst=True)
640 return _descendants(repo, subset, x, followfirst=True)
640
641
641 @predicate('destination([set])', safe=True)
642 @predicate('destination([set])', safe=True)
642 def destination(repo, subset, x):
643 def destination(repo, subset, x):
643 """Changesets that were created by a graft, transplant or rebase operation,
644 """Changesets that were created by a graft, transplant or rebase operation,
644 with the given revisions specified as the source. Omitting the optional set
645 with the given revisions specified as the source. Omitting the optional set
645 is the same as passing all().
646 is the same as passing all().
646 """
647 """
647 if x is not None:
648 if x is not None:
648 sources = getset(repo, fullreposet(repo), x)
649 sources = getset(repo, fullreposet(repo), x)
649 else:
650 else:
650 sources = fullreposet(repo)
651 sources = fullreposet(repo)
651
652
652 dests = set()
653 dests = set()
653
654
654 # subset contains all of the possible destinations that can be returned, so
655 # subset contains all of the possible destinations that can be returned, so
655 # iterate over them and see if their source(s) were provided in the arg set.
656 # iterate over them and see if their source(s) were provided in the arg set.
656 # Even if the immediate src of r is not in the arg set, src's source (or
657 # Even if the immediate src of r is not in the arg set, src's source (or
657 # further back) may be. Scanning back further than the immediate src allows
658 # further back) may be. Scanning back further than the immediate src allows
658 # transitive transplants and rebases to yield the same results as transitive
659 # transitive transplants and rebases to yield the same results as transitive
659 # grafts.
660 # grafts.
660 for r in subset:
661 for r in subset:
661 src = _getrevsource(repo, r)
662 src = _getrevsource(repo, r)
662 lineage = None
663 lineage = None
663
664
664 while src is not None:
665 while src is not None:
665 if lineage is None:
666 if lineage is None:
666 lineage = list()
667 lineage = list()
667
668
668 lineage.append(r)
669 lineage.append(r)
669
670
670 # The visited lineage is a match if the current source is in the arg
671 # The visited lineage is a match if the current source is in the arg
671 # set. Since every candidate dest is visited by way of iterating
672 # set. Since every candidate dest is visited by way of iterating
672 # subset, any dests further back in the lineage will be tested by a
673 # subset, any dests further back in the lineage will be tested by a
673 # different iteration over subset. Likewise, if the src was already
674 # different iteration over subset. Likewise, if the src was already
674 # selected, the current lineage can be selected without going back
675 # selected, the current lineage can be selected without going back
675 # further.
676 # further.
676 if src in sources or src in dests:
677 if src in sources or src in dests:
677 dests.update(lineage)
678 dests.update(lineage)
678 break
679 break
679
680
680 r = src
681 r = src
681 src = _getrevsource(repo, r)
682 src = _getrevsource(repo, r)
682
683
683 return subset.filter(dests.__contains__,
684 return subset.filter(dests.__contains__,
684 condrepr=lambda: '<destination %r>' % sorted(dests))
685 condrepr=lambda: '<destination %r>' % sorted(dests))
685
686
686 @predicate('divergent()', safe=True)
687 @predicate('divergent()', safe=True)
687 def divergent(repo, subset, x):
688 def divergent(repo, subset, x):
688 """
689 """
689 Final successors of changesets with an alternative set of final successors.
690 Final successors of changesets with an alternative set of final successors.
690 """
691 """
691 # i18n: "divergent" is a keyword
692 # i18n: "divergent" is a keyword
692 getargs(x, 0, 0, _("divergent takes no arguments"))
693 getargs(x, 0, 0, _("divergent takes no arguments"))
693 divergent = obsmod.getrevs(repo, 'divergent')
694 divergent = obsmod.getrevs(repo, 'divergent')
694 return subset & divergent
695 return subset & divergent
695
696
696 @predicate('extinct()', safe=True)
697 @predicate('extinct()', safe=True)
697 def extinct(repo, subset, x):
698 def extinct(repo, subset, x):
698 """Obsolete changesets with obsolete descendants only.
699 """Obsolete changesets with obsolete descendants only.
699 """
700 """
700 # i18n: "extinct" is a keyword
701 # i18n: "extinct" is a keyword
701 getargs(x, 0, 0, _("extinct takes no arguments"))
702 getargs(x, 0, 0, _("extinct takes no arguments"))
702 extincts = obsmod.getrevs(repo, 'extinct')
703 extincts = obsmod.getrevs(repo, 'extinct')
703 return subset & extincts
704 return subset & extincts
704
705
705 @predicate('extra(label, [value])', safe=True)
706 @predicate('extra(label, [value])', safe=True)
706 def extra(repo, subset, x):
707 def extra(repo, subset, x):
707 """Changesets with the given label in the extra metadata, with the given
708 """Changesets with the given label in the extra metadata, with the given
708 optional value.
709 optional value.
709
710
710 Pattern matching is supported for `value`. See
711 Pattern matching is supported for `value`. See
711 :hg:`help revisions.patterns`.
712 :hg:`help revisions.patterns`.
712 """
713 """
713 args = getargsdict(x, 'extra', 'label value')
714 args = getargsdict(x, 'extra', 'label value')
714 if 'label' not in args:
715 if 'label' not in args:
715 # i18n: "extra" is a keyword
716 # i18n: "extra" is a keyword
716 raise error.ParseError(_('extra takes at least 1 argument'))
717 raise error.ParseError(_('extra takes at least 1 argument'))
717 # i18n: "extra" is a keyword
718 # i18n: "extra" is a keyword
718 label = getstring(args['label'], _('first argument to extra must be '
719 label = getstring(args['label'], _('first argument to extra must be '
719 'a string'))
720 'a string'))
720 value = None
721 value = None
721
722
722 if 'value' in args:
723 if 'value' in args:
723 # i18n: "extra" is a keyword
724 # i18n: "extra" is a keyword
724 value = getstring(args['value'], _('second argument to extra must be '
725 value = getstring(args['value'], _('second argument to extra must be '
725 'a string'))
726 'a string'))
726 kind, value, matcher = util.stringmatcher(value)
727 kind, value, matcher = util.stringmatcher(value)
727
728
728 def _matchvalue(r):
729 def _matchvalue(r):
729 extra = repo[r].extra()
730 extra = repo[r].extra()
730 return label in extra and (value is None or matcher(extra[label]))
731 return label in extra and (value is None or matcher(extra[label]))
731
732
732 return subset.filter(lambda r: _matchvalue(r),
733 return subset.filter(lambda r: _matchvalue(r),
733 condrepr=('<extra[%r] %r>', label, value))
734 condrepr=('<extra[%r] %r>', label, value))
734
735
735 @predicate('filelog(pattern)', safe=True)
736 @predicate('filelog(pattern)', safe=True)
736 def filelog(repo, subset, x):
737 def filelog(repo, subset, x):
737 """Changesets connected to the specified filelog.
738 """Changesets connected to the specified filelog.
738
739
739 For performance reasons, visits only revisions mentioned in the file-level
740 For performance reasons, visits only revisions mentioned in the file-level
740 filelog, rather than filtering through all changesets (much faster, but
741 filelog, rather than filtering through all changesets (much faster, but
741 doesn't include deletes or duplicate changes). For a slower, more accurate
742 doesn't include deletes or duplicate changes). For a slower, more accurate
742 result, use ``file()``.
743 result, use ``file()``.
743
744
744 The pattern without explicit kind like ``glob:`` is expected to be
745 The pattern without explicit kind like ``glob:`` is expected to be
745 relative to the current directory and match against a file exactly
746 relative to the current directory and match against a file exactly
746 for efficiency.
747 for efficiency.
747
748
748 If some linkrev points to revisions filtered by the current repoview, we'll
749 If some linkrev points to revisions filtered by the current repoview, we'll
749 work around it to return a non-filtered value.
750 work around it to return a non-filtered value.
750 """
751 """
751
752
752 # i18n: "filelog" is a keyword
753 # i18n: "filelog" is a keyword
753 pat = getstring(x, _("filelog requires a pattern"))
754 pat = getstring(x, _("filelog requires a pattern"))
754 s = set()
755 s = set()
755 cl = repo.changelog
756 cl = repo.changelog
756
757
757 if not matchmod.patkind(pat):
758 if not matchmod.patkind(pat):
758 f = pathutil.canonpath(repo.root, repo.getcwd(), pat)
759 f = pathutil.canonpath(repo.root, repo.getcwd(), pat)
759 files = [f]
760 files = [f]
760 else:
761 else:
761 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[None])
762 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[None])
762 files = (f for f in repo[None] if m(f))
763 files = (f for f in repo[None] if m(f))
763
764
764 for f in files:
765 for f in files:
765 fl = repo.file(f)
766 fl = repo.file(f)
766 known = {}
767 known = {}
767 scanpos = 0
768 scanpos = 0
768 for fr in list(fl):
769 for fr in list(fl):
769 fn = fl.node(fr)
770 fn = fl.node(fr)
770 if fn in known:
771 if fn in known:
771 s.add(known[fn])
772 s.add(known[fn])
772 continue
773 continue
773
774
774 lr = fl.linkrev(fr)
775 lr = fl.linkrev(fr)
775 if lr in cl:
776 if lr in cl:
776 s.add(lr)
777 s.add(lr)
777 elif scanpos is not None:
778 elif scanpos is not None:
778 # lowest matching changeset is filtered, scan further
779 # lowest matching changeset is filtered, scan further
779 # ahead in changelog
780 # ahead in changelog
780 start = max(lr, scanpos) + 1
781 start = max(lr, scanpos) + 1
781 scanpos = None
782 scanpos = None
782 for r in cl.revs(start):
783 for r in cl.revs(start):
783 # minimize parsing of non-matching entries
784 # minimize parsing of non-matching entries
784 if f in cl.revision(r) and f in cl.readfiles(r):
785 if f in cl.revision(r) and f in cl.readfiles(r):
785 try:
786 try:
786 # try to use manifest delta fastpath
787 # try to use manifest delta fastpath
787 n = repo[r].filenode(f)
788 n = repo[r].filenode(f)
788 if n not in known:
789 if n not in known:
789 if n == fn:
790 if n == fn:
790 s.add(r)
791 s.add(r)
791 scanpos = r
792 scanpos = r
792 break
793 break
793 else:
794 else:
794 known[n] = r
795 known[n] = r
795 except error.ManifestLookupError:
796 except error.ManifestLookupError:
796 # deletion in changelog
797 # deletion in changelog
797 continue
798 continue
798
799
799 return subset & s
800 return subset & s
800
801
801 @predicate('first(set, [n])', safe=True, takeorder=True)
802 @predicate('first(set, [n])', safe=True, takeorder=True)
802 def first(repo, subset, x, order):
803 def first(repo, subset, x, order):
803 """An alias for limit().
804 """An alias for limit().
804 """
805 """
805 return limit(repo, subset, x, order)
806 return limit(repo, subset, x, order)
806
807
807 def _follow(repo, subset, x, name, followfirst=False):
808 def _follow(repo, subset, x, name, followfirst=False):
808 l = getargs(x, 0, 2, _("%s takes no arguments or a pattern "
809 l = getargs(x, 0, 2, _("%s takes no arguments or a pattern "
809 "and an optional revset") % name)
810 "and an optional revset") % name)
810 c = repo['.']
811 c = repo['.']
811 if l:
812 if l:
812 x = getstring(l[0], _("%s expected a pattern") % name)
813 x = getstring(l[0], _("%s expected a pattern") % name)
813 rev = None
814 rev = None
814 if len(l) >= 2:
815 if len(l) >= 2:
815 revs = getset(repo, fullreposet(repo), l[1])
816 revs = getset(repo, fullreposet(repo), l[1])
816 if len(revs) != 1:
817 if len(revs) != 1:
817 raise error.RepoLookupError(
818 raise error.RepoLookupError(
818 _("%s expected one starting revision") % name)
819 _("%s expected one starting revision") % name)
819 rev = revs.last()
820 rev = revs.last()
820 c = repo[rev]
821 c = repo[rev]
821 matcher = matchmod.match(repo.root, repo.getcwd(), [x],
822 matcher = matchmod.match(repo.root, repo.getcwd(), [x],
822 ctx=repo[rev], default='path')
823 ctx=repo[rev], default='path')
823
824
824 files = c.manifest().walk(matcher)
825 files = c.manifest().walk(matcher)
825
826
826 s = set()
827 s = set()
827 for fname in files:
828 for fname in files:
828 fctx = c[fname]
829 fctx = c[fname]
829 s = s.union(set(c.rev() for c in fctx.ancestors(followfirst)))
830 s = s.union(set(c.rev() for c in fctx.ancestors(followfirst)))
830 # include the revision responsible for the most recent version
831 # include the revision responsible for the most recent version
831 s.add(fctx.introrev())
832 s.add(fctx.introrev())
832 else:
833 else:
833 s = dagop.revancestors(repo, baseset([c.rev()]), followfirst)
834 s = dagop.revancestors(repo, baseset([c.rev()]), followfirst)
834
835
835 return subset & s
836 return subset & s
836
837
837 @predicate('follow([pattern[, startrev]])', safe=True)
838 @predicate('follow([pattern[, startrev]])', safe=True)
838 def follow(repo, subset, x):
839 def follow(repo, subset, x):
839 """
840 """
840 An alias for ``::.`` (ancestors of the working directory's first parent).
841 An alias for ``::.`` (ancestors of the working directory's first parent).
841 If pattern is specified, the histories of files matching given
842 If pattern is specified, the histories of files matching given
842 pattern in the revision given by startrev are followed, including copies.
843 pattern in the revision given by startrev are followed, including copies.
843 """
844 """
844 return _follow(repo, subset, x, 'follow')
845 return _follow(repo, subset, x, 'follow')
845
846
846 @predicate('_followfirst', safe=True)
847 @predicate('_followfirst', safe=True)
847 def _followfirst(repo, subset, x):
848 def _followfirst(repo, subset, x):
848 # ``followfirst([pattern[, startrev]])``
849 # ``followfirst([pattern[, startrev]])``
849 # Like ``follow([pattern[, startrev]])`` but follows only the first parent
850 # Like ``follow([pattern[, startrev]])`` but follows only the first parent
850 # of every revisions or files revisions.
851 # of every revisions or files revisions.
851 return _follow(repo, subset, x, '_followfirst', followfirst=True)
852 return _follow(repo, subset, x, '_followfirst', followfirst=True)
852
853
853 @predicate('followlines(file, fromline:toline[, startrev=., descend=False])',
854 @predicate('followlines(file, fromline:toline[, startrev=., descend=False])',
854 safe=True)
855 safe=True)
855 def followlines(repo, subset, x):
856 def followlines(repo, subset, x):
856 """Changesets modifying `file` in line range ('fromline', 'toline').
857 """Changesets modifying `file` in line range ('fromline', 'toline').
857
858
858 Line range corresponds to 'file' content at 'startrev' and should hence be
859 Line range corresponds to 'file' content at 'startrev' and should hence be
859 consistent with file size. If startrev is not specified, working directory's
860 consistent with file size. If startrev is not specified, working directory's
860 parent is used.
861 parent is used.
861
862
862 By default, ancestors of 'startrev' are returned. If 'descend' is True,
863 By default, ancestors of 'startrev' are returned. If 'descend' is True,
863 descendants of 'startrev' are returned though renames are (currently) not
864 descendants of 'startrev' are returned though renames are (currently) not
864 followed in this direction.
865 followed in this direction.
865 """
866 """
866 args = getargsdict(x, 'followlines', 'file *lines startrev descend')
867 args = getargsdict(x, 'followlines', 'file *lines startrev descend')
867 if len(args['lines']) != 1:
868 if len(args['lines']) != 1:
868 raise error.ParseError(_("followlines requires a line range"))
869 raise error.ParseError(_("followlines requires a line range"))
869
870
870 rev = '.'
871 rev = '.'
871 if 'startrev' in args:
872 if 'startrev' in args:
872 revs = getset(repo, fullreposet(repo), args['startrev'])
873 revs = getset(repo, fullreposet(repo), args['startrev'])
873 if len(revs) != 1:
874 if len(revs) != 1:
874 raise error.ParseError(
875 raise error.ParseError(
875 # i18n: "followlines" is a keyword
876 # i18n: "followlines" is a keyword
876 _("followlines expects exactly one revision"))
877 _("followlines expects exactly one revision"))
877 rev = revs.last()
878 rev = revs.last()
878
879
879 pat = getstring(args['file'], _("followlines requires a pattern"))
880 pat = getstring(args['file'], _("followlines requires a pattern"))
880 if not matchmod.patkind(pat):
881 if not matchmod.patkind(pat):
881 fname = pathutil.canonpath(repo.root, repo.getcwd(), pat)
882 fname = pathutil.canonpath(repo.root, repo.getcwd(), pat)
882 else:
883 else:
883 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[rev])
884 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[rev])
884 files = [f for f in repo[rev] if m(f)]
885 files = [f for f in repo[rev] if m(f)]
885 if len(files) != 1:
886 if len(files) != 1:
886 # i18n: "followlines" is a keyword
887 # i18n: "followlines" is a keyword
887 raise error.ParseError(_("followlines expects exactly one file"))
888 raise error.ParseError(_("followlines expects exactly one file"))
888 fname = files[0]
889 fname = files[0]
889
890
890 # i18n: "followlines" is a keyword
891 # i18n: "followlines" is a keyword
891 lr = getrange(args['lines'][0], _("followlines expects a line range"))
892 lr = getrange(args['lines'][0], _("followlines expects a line range"))
892 fromline, toline = [getinteger(a, _("line range bounds must be integers"))
893 fromline, toline = [getinteger(a, _("line range bounds must be integers"))
893 for a in lr]
894 for a in lr]
894 fromline, toline = util.processlinerange(fromline, toline)
895 fromline, toline = util.processlinerange(fromline, toline)
895
896
896 fctx = repo[rev].filectx(fname)
897 fctx = repo[rev].filectx(fname)
897 descend = False
898 descend = False
898 if 'descend' in args:
899 if 'descend' in args:
899 descend = getboolean(args['descend'],
900 descend = getboolean(args['descend'],
900 # i18n: "descend" is a keyword
901 # i18n: "descend" is a keyword
901 _("descend argument must be a boolean"))
902 _("descend argument must be a boolean"))
902 if descend:
903 if descend:
903 rs = generatorset(
904 rs = generatorset(
904 (c.rev() for c, _linerange
905 (c.rev() for c, _linerange
905 in dagop.blockdescendants(fctx, fromline, toline)),
906 in dagop.blockdescendants(fctx, fromline, toline)),
906 iterasc=True)
907 iterasc=True)
907 else:
908 else:
908 rs = generatorset(
909 rs = generatorset(
909 (c.rev() for c, _linerange
910 (c.rev() for c, _linerange
910 in dagop.blockancestors(fctx, fromline, toline)),
911 in dagop.blockancestors(fctx, fromline, toline)),
911 iterasc=False)
912 iterasc=False)
912 return subset & rs
913 return subset & rs
913
914
914 @predicate('all()', safe=True)
915 @predicate('all()', safe=True)
915 def getall(repo, subset, x):
916 def getall(repo, subset, x):
916 """All changesets, the same as ``0:tip``.
917 """All changesets, the same as ``0:tip``.
917 """
918 """
918 # i18n: "all" is a keyword
919 # i18n: "all" is a keyword
919 getargs(x, 0, 0, _("all takes no arguments"))
920 getargs(x, 0, 0, _("all takes no arguments"))
920 return subset & spanset(repo) # drop "null" if any
921 return subset & spanset(repo) # drop "null" if any
921
922
922 @predicate('grep(regex)')
923 @predicate('grep(regex)')
923 def grep(repo, subset, x):
924 def grep(repo, subset, x):
924 """Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
925 """Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
925 to ensure special escape characters are handled correctly. Unlike
926 to ensure special escape characters are handled correctly. Unlike
926 ``keyword(string)``, the match is case-sensitive.
927 ``keyword(string)``, the match is case-sensitive.
927 """
928 """
928 try:
929 try:
929 # i18n: "grep" is a keyword
930 # i18n: "grep" is a keyword
930 gr = re.compile(getstring(x, _("grep requires a string")))
931 gr = re.compile(getstring(x, _("grep requires a string")))
931 except re.error as e:
932 except re.error as e:
932 raise error.ParseError(_('invalid match pattern: %s') % e)
933 raise error.ParseError(_('invalid match pattern: %s') % e)
933
934
934 def matches(x):
935 def matches(x):
935 c = repo[x]
936 c = repo[x]
936 for e in c.files() + [c.user(), c.description()]:
937 for e in c.files() + [c.user(), c.description()]:
937 if gr.search(e):
938 if gr.search(e):
938 return True
939 return True
939 return False
940 return False
940
941
941 return subset.filter(matches, condrepr=('<grep %r>', gr.pattern))
942 return subset.filter(matches, condrepr=('<grep %r>', gr.pattern))
942
943
943 @predicate('_matchfiles', safe=True)
944 @predicate('_matchfiles', safe=True)
944 def _matchfiles(repo, subset, x):
945 def _matchfiles(repo, subset, x):
945 # _matchfiles takes a revset list of prefixed arguments:
946 # _matchfiles takes a revset list of prefixed arguments:
946 #
947 #
947 # [p:foo, i:bar, x:baz]
948 # [p:foo, i:bar, x:baz]
948 #
949 #
949 # builds a match object from them and filters subset. Allowed
950 # builds a match object from them and filters subset. Allowed
950 # prefixes are 'p:' for regular patterns, 'i:' for include
951 # prefixes are 'p:' for regular patterns, 'i:' for include
951 # patterns and 'x:' for exclude patterns. Use 'r:' prefix to pass
952 # patterns and 'x:' for exclude patterns. Use 'r:' prefix to pass
952 # a revision identifier, or the empty string to reference the
953 # a revision identifier, or the empty string to reference the
953 # working directory, from which the match object is
954 # working directory, from which the match object is
954 # initialized. Use 'd:' to set the default matching mode, default
955 # initialized. Use 'd:' to set the default matching mode, default
955 # to 'glob'. At most one 'r:' and 'd:' argument can be passed.
956 # to 'glob'. At most one 'r:' and 'd:' argument can be passed.
956
957
957 l = getargs(x, 1, -1, "_matchfiles requires at least one argument")
958 l = getargs(x, 1, -1, "_matchfiles requires at least one argument")
958 pats, inc, exc = [], [], []
959 pats, inc, exc = [], [], []
959 rev, default = None, None
960 rev, default = None, None
960 for arg in l:
961 for arg in l:
961 s = getstring(arg, "_matchfiles requires string arguments")
962 s = getstring(arg, "_matchfiles requires string arguments")
962 prefix, value = s[:2], s[2:]
963 prefix, value = s[:2], s[2:]
963 if prefix == 'p:':
964 if prefix == 'p:':
964 pats.append(value)
965 pats.append(value)
965 elif prefix == 'i:':
966 elif prefix == 'i:':
966 inc.append(value)
967 inc.append(value)
967 elif prefix == 'x:':
968 elif prefix == 'x:':
968 exc.append(value)
969 exc.append(value)
969 elif prefix == 'r:':
970 elif prefix == 'r:':
970 if rev is not None:
971 if rev is not None:
971 raise error.ParseError('_matchfiles expected at most one '
972 raise error.ParseError('_matchfiles expected at most one '
972 'revision')
973 'revision')
973 if value != '': # empty means working directory; leave rev as None
974 if value != '': # empty means working directory; leave rev as None
974 rev = value
975 rev = value
975 elif prefix == 'd:':
976 elif prefix == 'd:':
976 if default is not None:
977 if default is not None:
977 raise error.ParseError('_matchfiles expected at most one '
978 raise error.ParseError('_matchfiles expected at most one '
978 'default mode')
979 'default mode')
979 default = value
980 default = value
980 else:
981 else:
981 raise error.ParseError('invalid _matchfiles prefix: %s' % prefix)
982 raise error.ParseError('invalid _matchfiles prefix: %s' % prefix)
982 if not default:
983 if not default:
983 default = 'glob'
984 default = 'glob'
984
985
985 m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc,
986 m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc,
986 exclude=exc, ctx=repo[rev], default=default)
987 exclude=exc, ctx=repo[rev], default=default)
987
988
988 # This directly read the changelog data as creating changectx for all
989 # This directly read the changelog data as creating changectx for all
989 # revisions is quite expensive.
990 # revisions is quite expensive.
990 getfiles = repo.changelog.readfiles
991 getfiles = repo.changelog.readfiles
991 wdirrev = node.wdirrev
992 wdirrev = node.wdirrev
992 def matches(x):
993 def matches(x):
993 if x == wdirrev:
994 if x == wdirrev:
994 files = repo[x].files()
995 files = repo[x].files()
995 else:
996 else:
996 files = getfiles(x)
997 files = getfiles(x)
997 for f in files:
998 for f in files:
998 if m(f):
999 if m(f):
999 return True
1000 return True
1000 return False
1001 return False
1001
1002
1002 return subset.filter(matches,
1003 return subset.filter(matches,
1003 condrepr=('<matchfiles patterns=%r, include=%r '
1004 condrepr=('<matchfiles patterns=%r, include=%r '
1004 'exclude=%r, default=%r, rev=%r>',
1005 'exclude=%r, default=%r, rev=%r>',
1005 pats, inc, exc, default, rev))
1006 pats, inc, exc, default, rev))
1006
1007
1007 @predicate('file(pattern)', safe=True)
1008 @predicate('file(pattern)', safe=True)
1008 def hasfile(repo, subset, x):
1009 def hasfile(repo, subset, x):
1009 """Changesets affecting files matched by pattern.
1010 """Changesets affecting files matched by pattern.
1010
1011
1011 For a faster but less accurate result, consider using ``filelog()``
1012 For a faster but less accurate result, consider using ``filelog()``
1012 instead.
1013 instead.
1013
1014
1014 This predicate uses ``glob:`` as the default kind of pattern.
1015 This predicate uses ``glob:`` as the default kind of pattern.
1015 """
1016 """
1016 # i18n: "file" is a keyword
1017 # i18n: "file" is a keyword
1017 pat = getstring(x, _("file requires a pattern"))
1018 pat = getstring(x, _("file requires a pattern"))
1018 return _matchfiles(repo, subset, ('string', 'p:' + pat))
1019 return _matchfiles(repo, subset, ('string', 'p:' + pat))
1019
1020
1020 @predicate('head()', safe=True)
1021 @predicate('head()', safe=True)
1021 def head(repo, subset, x):
1022 def head(repo, subset, x):
1022 """Changeset is a named branch head.
1023 """Changeset is a named branch head.
1023 """
1024 """
1024 # i18n: "head" is a keyword
1025 # i18n: "head" is a keyword
1025 getargs(x, 0, 0, _("head takes no arguments"))
1026 getargs(x, 0, 0, _("head takes no arguments"))
1026 hs = set()
1027 hs = set()
1027 cl = repo.changelog
1028 cl = repo.changelog
1028 for ls in repo.branchmap().itervalues():
1029 for ls in repo.branchmap().itervalues():
1029 hs.update(cl.rev(h) for h in ls)
1030 hs.update(cl.rev(h) for h in ls)
1030 return subset & baseset(hs)
1031 return subset & baseset(hs)
1031
1032
1032 @predicate('heads(set)', safe=True)
1033 @predicate('heads(set)', safe=True)
1033 def heads(repo, subset, x):
1034 def heads(repo, subset, x):
1034 """Members of set with no children in set.
1035 """Members of set with no children in set.
1035 """
1036 """
1036 s = getset(repo, subset, x)
1037 s = getset(repo, subset, x)
1037 ps = parents(repo, subset, x)
1038 ps = parents(repo, subset, x)
1038 return s - ps
1039 return s - ps
1039
1040
1040 @predicate('hidden()', safe=True)
1041 @predicate('hidden()', safe=True)
1041 def hidden(repo, subset, x):
1042 def hidden(repo, subset, x):
1042 """Hidden changesets.
1043 """Hidden changesets.
1043 """
1044 """
1044 # i18n: "hidden" is a keyword
1045 # i18n: "hidden" is a keyword
1045 getargs(x, 0, 0, _("hidden takes no arguments"))
1046 getargs(x, 0, 0, _("hidden takes no arguments"))
1046 hiddenrevs = repoview.filterrevs(repo, 'visible')
1047 hiddenrevs = repoview.filterrevs(repo, 'visible')
1047 return subset & hiddenrevs
1048 return subset & hiddenrevs
1048
1049
1049 @predicate('keyword(string)', safe=True)
1050 @predicate('keyword(string)', safe=True)
1050 def keyword(repo, subset, x):
1051 def keyword(repo, subset, x):
1051 """Search commit message, user name, and names of changed files for
1052 """Search commit message, user name, and names of changed files for
1052 string. The match is case-insensitive.
1053 string. The match is case-insensitive.
1053
1054
1054 For a regular expression or case sensitive search of these fields, use
1055 For a regular expression or case sensitive search of these fields, use
1055 ``grep(regex)``.
1056 ``grep(regex)``.
1056 """
1057 """
1057 # i18n: "keyword" is a keyword
1058 # i18n: "keyword" is a keyword
1058 kw = encoding.lower(getstring(x, _("keyword requires a string")))
1059 kw = encoding.lower(getstring(x, _("keyword requires a string")))
1059
1060
1060 def matches(r):
1061 def matches(r):
1061 c = repo[r]
1062 c = repo[r]
1062 return any(kw in encoding.lower(t)
1063 return any(kw in encoding.lower(t)
1063 for t in c.files() + [c.user(), c.description()])
1064 for t in c.files() + [c.user(), c.description()])
1064
1065
1065 return subset.filter(matches, condrepr=('<keyword %r>', kw))
1066 return subset.filter(matches, condrepr=('<keyword %r>', kw))
1066
1067
1067 @predicate('limit(set[, n[, offset]])', safe=True, takeorder=True)
1068 @predicate('limit(set[, n[, offset]])', safe=True, takeorder=True)
1068 def limit(repo, subset, x, order):
1069 def limit(repo, subset, x, order):
1069 """First n members of set, defaulting to 1, starting from offset.
1070 """First n members of set, defaulting to 1, starting from offset.
1070 """
1071 """
1071 args = getargsdict(x, 'limit', 'set n offset')
1072 args = getargsdict(x, 'limit', 'set n offset')
1072 if 'set' not in args:
1073 if 'set' not in args:
1073 # i18n: "limit" is a keyword
1074 # i18n: "limit" is a keyword
1074 raise error.ParseError(_("limit requires one to three arguments"))
1075 raise error.ParseError(_("limit requires one to three arguments"))
1075 # i18n: "limit" is a keyword
1076 # i18n: "limit" is a keyword
1076 lim = getinteger(args.get('n'), _("limit expects a number"), default=1)
1077 lim = getinteger(args.get('n'), _("limit expects a number"), default=1)
1077 if lim < 0:
1078 if lim < 0:
1078 raise error.ParseError(_("negative number to select"))
1079 raise error.ParseError(_("negative number to select"))
1079 # i18n: "limit" is a keyword
1080 # i18n: "limit" is a keyword
1080 ofs = getinteger(args.get('offset'), _("limit expects a number"), default=0)
1081 ofs = getinteger(args.get('offset'), _("limit expects a number"), default=0)
1081 if ofs < 0:
1082 if ofs < 0:
1082 raise error.ParseError(_("negative offset"))
1083 raise error.ParseError(_("negative offset"))
1083 os = getset(repo, fullreposet(repo), args['set'])
1084 os = getset(repo, fullreposet(repo), args['set'])
1084 ls = os.slice(ofs, ofs + lim)
1085 ls = os.slice(ofs, ofs + lim)
1085 if order == followorder and lim > 1:
1086 if order == followorder and lim > 1:
1086 return subset & ls
1087 return subset & ls
1087 return ls & subset
1088 return ls & subset
1088
1089
1089 @predicate('last(set, [n])', safe=True, takeorder=True)
1090 @predicate('last(set, [n])', safe=True, takeorder=True)
1090 def last(repo, subset, x, order):
1091 def last(repo, subset, x, order):
1091 """Last n members of set, defaulting to 1.
1092 """Last n members of set, defaulting to 1.
1092 """
1093 """
1093 # i18n: "last" is a keyword
1094 # i18n: "last" is a keyword
1094 l = getargs(x, 1, 2, _("last requires one or two arguments"))
1095 l = getargs(x, 1, 2, _("last requires one or two arguments"))
1095 lim = 1
1096 lim = 1
1096 if len(l) == 2:
1097 if len(l) == 2:
1097 # i18n: "last" is a keyword
1098 # i18n: "last" is a keyword
1098 lim = getinteger(l[1], _("last expects a number"))
1099 lim = getinteger(l[1], _("last expects a number"))
1099 if lim < 0:
1100 if lim < 0:
1100 raise error.ParseError(_("negative number to select"))
1101 raise error.ParseError(_("negative number to select"))
1101 os = getset(repo, fullreposet(repo), l[0])
1102 os = getset(repo, fullreposet(repo), l[0])
1102 os.reverse()
1103 os.reverse()
1103 ls = os.slice(0, lim)
1104 ls = os.slice(0, lim)
1104 if order == followorder and lim > 1:
1105 if order == followorder and lim > 1:
1105 return subset & ls
1106 return subset & ls
1106 ls.reverse()
1107 ls.reverse()
1107 return ls & subset
1108 return ls & subset
1108
1109
1109 @predicate('max(set)', safe=True)
1110 @predicate('max(set)', safe=True)
1110 def maxrev(repo, subset, x):
1111 def maxrev(repo, subset, x):
1111 """Changeset with highest revision number in set.
1112 """Changeset with highest revision number in set.
1112 """
1113 """
1113 os = getset(repo, fullreposet(repo), x)
1114 os = getset(repo, fullreposet(repo), x)
1114 try:
1115 try:
1115 m = os.max()
1116 m = os.max()
1116 if m in subset:
1117 if m in subset:
1117 return baseset([m], datarepr=('<max %r, %r>', subset, os))
1118 return baseset([m], datarepr=('<max %r, %r>', subset, os))
1118 except ValueError:
1119 except ValueError:
1119 # os.max() throws a ValueError when the collection is empty.
1120 # os.max() throws a ValueError when the collection is empty.
1120 # Same as python's max().
1121 # Same as python's max().
1121 pass
1122 pass
1122 return baseset(datarepr=('<max %r, %r>', subset, os))
1123 return baseset(datarepr=('<max %r, %r>', subset, os))
1123
1124
1124 @predicate('merge()', safe=True)
1125 @predicate('merge()', safe=True)
1125 def merge(repo, subset, x):
1126 def merge(repo, subset, x):
1126 """Changeset is a merge changeset.
1127 """Changeset is a merge changeset.
1127 """
1128 """
1128 # i18n: "merge" is a keyword
1129 # i18n: "merge" is a keyword
1129 getargs(x, 0, 0, _("merge takes no arguments"))
1130 getargs(x, 0, 0, _("merge takes no arguments"))
1130 cl = repo.changelog
1131 cl = repo.changelog
1131 return subset.filter(lambda r: cl.parentrevs(r)[1] != -1,
1132 return subset.filter(lambda r: cl.parentrevs(r)[1] != -1,
1132 condrepr='<merge>')
1133 condrepr='<merge>')
1133
1134
1134 @predicate('branchpoint()', safe=True)
1135 @predicate('branchpoint()', safe=True)
1135 def branchpoint(repo, subset, x):
1136 def branchpoint(repo, subset, x):
1136 """Changesets with more than one child.
1137 """Changesets with more than one child.
1137 """
1138 """
1138 # i18n: "branchpoint" is a keyword
1139 # i18n: "branchpoint" is a keyword
1139 getargs(x, 0, 0, _("branchpoint takes no arguments"))
1140 getargs(x, 0, 0, _("branchpoint takes no arguments"))
1140 cl = repo.changelog
1141 cl = repo.changelog
1141 if not subset:
1142 if not subset:
1142 return baseset()
1143 return baseset()
1143 # XXX this should be 'parentset.min()' assuming 'parentset' is a smartset
1144 # XXX this should be 'parentset.min()' assuming 'parentset' is a smartset
1144 # (and if it is not, it should.)
1145 # (and if it is not, it should.)
1145 baserev = min(subset)
1146 baserev = min(subset)
1146 parentscount = [0]*(len(repo) - baserev)
1147 parentscount = [0]*(len(repo) - baserev)
1147 for r in cl.revs(start=baserev + 1):
1148 for r in cl.revs(start=baserev + 1):
1148 for p in cl.parentrevs(r):
1149 for p in cl.parentrevs(r):
1149 if p >= baserev:
1150 if p >= baserev:
1150 parentscount[p - baserev] += 1
1151 parentscount[p - baserev] += 1
1151 return subset.filter(lambda r: parentscount[r - baserev] > 1,
1152 return subset.filter(lambda r: parentscount[r - baserev] > 1,
1152 condrepr='<branchpoint>')
1153 condrepr='<branchpoint>')
1153
1154
1154 @predicate('min(set)', safe=True)
1155 @predicate('min(set)', safe=True)
1155 def minrev(repo, subset, x):
1156 def minrev(repo, subset, x):
1156 """Changeset with lowest revision number in set.
1157 """Changeset with lowest revision number in set.
1157 """
1158 """
1158 os = getset(repo, fullreposet(repo), x)
1159 os = getset(repo, fullreposet(repo), x)
1159 try:
1160 try:
1160 m = os.min()
1161 m = os.min()
1161 if m in subset:
1162 if m in subset:
1162 return baseset([m], datarepr=('<min %r, %r>', subset, os))
1163 return baseset([m], datarepr=('<min %r, %r>', subset, os))
1163 except ValueError:
1164 except ValueError:
1164 # os.min() throws a ValueError when the collection is empty.
1165 # os.min() throws a ValueError when the collection is empty.
1165 # Same as python's min().
1166 # Same as python's min().
1166 pass
1167 pass
1167 return baseset(datarepr=('<min %r, %r>', subset, os))
1168 return baseset(datarepr=('<min %r, %r>', subset, os))
1168
1169
1169 @predicate('modifies(pattern)', safe=True)
1170 @predicate('modifies(pattern)', safe=True)
1170 def modifies(repo, subset, x):
1171 def modifies(repo, subset, x):
1171 """Changesets modifying files matched by pattern.
1172 """Changesets modifying files matched by pattern.
1172
1173
1173 The pattern without explicit kind like ``glob:`` is expected to be
1174 The pattern without explicit kind like ``glob:`` is expected to be
1174 relative to the current directory and match against a file or a
1175 relative to the current directory and match against a file or a
1175 directory.
1176 directory.
1176 """
1177 """
1177 # i18n: "modifies" is a keyword
1178 # i18n: "modifies" is a keyword
1178 pat = getstring(x, _("modifies requires a pattern"))
1179 pat = getstring(x, _("modifies requires a pattern"))
1179 return checkstatus(repo, subset, pat, 0)
1180 return checkstatus(repo, subset, pat, 0)
1180
1181
1181 @predicate('named(namespace)')
1182 @predicate('named(namespace)')
1182 def named(repo, subset, x):
1183 def named(repo, subset, x):
1183 """The changesets in a given namespace.
1184 """The changesets in a given namespace.
1184
1185
1185 Pattern matching is supported for `namespace`. See
1186 Pattern matching is supported for `namespace`. See
1186 :hg:`help revisions.patterns`.
1187 :hg:`help revisions.patterns`.
1187 """
1188 """
1188 # i18n: "named" is a keyword
1189 # i18n: "named" is a keyword
1189 args = getargs(x, 1, 1, _('named requires a namespace argument'))
1190 args = getargs(x, 1, 1, _('named requires a namespace argument'))
1190
1191
1191 ns = getstring(args[0],
1192 ns = getstring(args[0],
1192 # i18n: "named" is a keyword
1193 # i18n: "named" is a keyword
1193 _('the argument to named must be a string'))
1194 _('the argument to named must be a string'))
1194 kind, pattern, matcher = util.stringmatcher(ns)
1195 kind, pattern, matcher = util.stringmatcher(ns)
1195 namespaces = set()
1196 namespaces = set()
1196 if kind == 'literal':
1197 if kind == 'literal':
1197 if pattern not in repo.names:
1198 if pattern not in repo.names:
1198 raise error.RepoLookupError(_("namespace '%s' does not exist")
1199 raise error.RepoLookupError(_("namespace '%s' does not exist")
1199 % ns)
1200 % ns)
1200 namespaces.add(repo.names[pattern])
1201 namespaces.add(repo.names[pattern])
1201 else:
1202 else:
1202 for name, ns in repo.names.iteritems():
1203 for name, ns in repo.names.iteritems():
1203 if matcher(name):
1204 if matcher(name):
1204 namespaces.add(ns)
1205 namespaces.add(ns)
1205 if not namespaces:
1206 if not namespaces:
1206 raise error.RepoLookupError(_("no namespace exists"
1207 raise error.RepoLookupError(_("no namespace exists"
1207 " that match '%s'") % pattern)
1208 " that match '%s'") % pattern)
1208
1209
1209 names = set()
1210 names = set()
1210 for ns in namespaces:
1211 for ns in namespaces:
1211 for name in ns.listnames(repo):
1212 for name in ns.listnames(repo):
1212 if name not in ns.deprecated:
1213 if name not in ns.deprecated:
1213 names.update(repo[n].rev() for n in ns.nodes(repo, name))
1214 names.update(repo[n].rev() for n in ns.nodes(repo, name))
1214
1215
1215 names -= {node.nullrev}
1216 names -= {node.nullrev}
1216 return subset & names
1217 return subset & names
1217
1218
1218 @predicate('id(string)', safe=True)
1219 @predicate('id(string)', safe=True)
1219 def node_(repo, subset, x):
1220 def node_(repo, subset, x):
1220 """Revision non-ambiguously specified by the given hex string prefix.
1221 """Revision non-ambiguously specified by the given hex string prefix.
1221 """
1222 """
1222 # i18n: "id" is a keyword
1223 # i18n: "id" is a keyword
1223 l = getargs(x, 1, 1, _("id requires one argument"))
1224 l = getargs(x, 1, 1, _("id requires one argument"))
1224 # i18n: "id" is a keyword
1225 # i18n: "id" is a keyword
1225 n = getstring(l[0], _("id requires a string"))
1226 n = getstring(l[0], _("id requires a string"))
1226 if len(n) == 40:
1227 if len(n) == 40:
1227 try:
1228 try:
1228 rn = repo.changelog.rev(node.bin(n))
1229 rn = repo.changelog.rev(node.bin(n))
1229 except error.WdirUnsupported:
1230 except error.WdirUnsupported:
1230 rn = node.wdirrev
1231 rn = node.wdirrev
1231 except (LookupError, TypeError):
1232 except (LookupError, TypeError):
1232 rn = None
1233 rn = None
1233 else:
1234 else:
1234 rn = None
1235 rn = None
1235 try:
1236 try:
1236 pm = repo.changelog._partialmatch(n)
1237 pm = repo.changelog._partialmatch(n)
1237 if pm is not None:
1238 if pm is not None:
1238 rn = repo.changelog.rev(pm)
1239 rn = repo.changelog.rev(pm)
1239 except error.WdirUnsupported:
1240 except error.WdirUnsupported:
1240 rn = node.wdirrev
1241 rn = node.wdirrev
1241
1242
1242 if rn is None:
1243 if rn is None:
1243 return baseset()
1244 return baseset()
1244 result = baseset([rn])
1245 result = baseset([rn])
1245 return result & subset
1246 return result & subset
1246
1247
1247 @predicate('obsolete()', safe=True)
1248 @predicate('obsolete()', safe=True)
1248 def obsolete(repo, subset, x):
1249 def obsolete(repo, subset, x):
1249 """Mutable changeset with a newer version."""
1250 """Mutable changeset with a newer version."""
1250 # i18n: "obsolete" is a keyword
1251 # i18n: "obsolete" is a keyword
1251 getargs(x, 0, 0, _("obsolete takes no arguments"))
1252 getargs(x, 0, 0, _("obsolete takes no arguments"))
1252 obsoletes = obsmod.getrevs(repo, 'obsolete')
1253 obsoletes = obsmod.getrevs(repo, 'obsolete')
1253 return subset & obsoletes
1254 return subset & obsoletes
1254
1255
1255 @predicate('only(set, [set])', safe=True)
1256 @predicate('only(set, [set])', safe=True)
1256 def only(repo, subset, x):
1257 def only(repo, subset, x):
1257 """Changesets that are ancestors of the first set that are not ancestors
1258 """Changesets that are ancestors of the first set that are not ancestors
1258 of any other head in the repo. If a second set is specified, the result
1259 of any other head in the repo. If a second set is specified, the result
1259 is ancestors of the first set that are not ancestors of the second set
1260 is ancestors of the first set that are not ancestors of the second set
1260 (i.e. ::<set1> - ::<set2>).
1261 (i.e. ::<set1> - ::<set2>).
1261 """
1262 """
1262 cl = repo.changelog
1263 cl = repo.changelog
1263 # i18n: "only" is a keyword
1264 # i18n: "only" is a keyword
1264 args = getargs(x, 1, 2, _('only takes one or two arguments'))
1265 args = getargs(x, 1, 2, _('only takes one or two arguments'))
1265 include = getset(repo, fullreposet(repo), args[0])
1266 include = getset(repo, fullreposet(repo), args[0])
1266 if len(args) == 1:
1267 if len(args) == 1:
1267 if not include:
1268 if not include:
1268 return baseset()
1269 return baseset()
1269
1270
1270 descendants = set(dagop.revdescendants(repo, include, False))
1271 descendants = set(dagop.revdescendants(repo, include, False))
1271 exclude = [rev for rev in cl.headrevs()
1272 exclude = [rev for rev in cl.headrevs()
1272 if not rev in descendants and not rev in include]
1273 if not rev in descendants and not rev in include]
1273 else:
1274 else:
1274 exclude = getset(repo, fullreposet(repo), args[1])
1275 exclude = getset(repo, fullreposet(repo), args[1])
1275
1276
1276 results = set(cl.findmissingrevs(common=exclude, heads=include))
1277 results = set(cl.findmissingrevs(common=exclude, heads=include))
1277 # XXX we should turn this into a baseset instead of a set, smartset may do
1278 # XXX we should turn this into a baseset instead of a set, smartset may do
1278 # some optimizations from the fact this is a baseset.
1279 # some optimizations from the fact this is a baseset.
1279 return subset & results
1280 return subset & results
1280
1281
1281 @predicate('origin([set])', safe=True)
1282 @predicate('origin([set])', safe=True)
1282 def origin(repo, subset, x):
1283 def origin(repo, subset, x):
1283 """
1284 """
1284 Changesets that were specified as a source for the grafts, transplants or
1285 Changesets that were specified as a source for the grafts, transplants or
1285 rebases that created the given revisions. Omitting the optional set is the
1286 rebases that created the given revisions. Omitting the optional set is the
1286 same as passing all(). If a changeset created by these operations is itself
1287 same as passing all(). If a changeset created by these operations is itself
1287 specified as a source for one of these operations, only the source changeset
1288 specified as a source for one of these operations, only the source changeset
1288 for the first operation is selected.
1289 for the first operation is selected.
1289 """
1290 """
1290 if x is not None:
1291 if x is not None:
1291 dests = getset(repo, fullreposet(repo), x)
1292 dests = getset(repo, fullreposet(repo), x)
1292 else:
1293 else:
1293 dests = fullreposet(repo)
1294 dests = fullreposet(repo)
1294
1295
1295 def _firstsrc(rev):
1296 def _firstsrc(rev):
1296 src = _getrevsource(repo, rev)
1297 src = _getrevsource(repo, rev)
1297 if src is None:
1298 if src is None:
1298 return None
1299 return None
1299
1300
1300 while True:
1301 while True:
1301 prev = _getrevsource(repo, src)
1302 prev = _getrevsource(repo, src)
1302
1303
1303 if prev is None:
1304 if prev is None:
1304 return src
1305 return src
1305 src = prev
1306 src = prev
1306
1307
1307 o = {_firstsrc(r) for r in dests}
1308 o = {_firstsrc(r) for r in dests}
1308 o -= {None}
1309 o -= {None}
1309 # XXX we should turn this into a baseset instead of a set, smartset may do
1310 # XXX we should turn this into a baseset instead of a set, smartset may do
1310 # some optimizations from the fact this is a baseset.
1311 # some optimizations from the fact this is a baseset.
1311 return subset & o
1312 return subset & o
1312
1313
1313 @predicate('outgoing([path])', safe=False)
1314 @predicate('outgoing([path])', safe=False)
1314 def outgoing(repo, subset, x):
1315 def outgoing(repo, subset, x):
1315 """Changesets not found in the specified destination repository, or the
1316 """Changesets not found in the specified destination repository, or the
1316 default push location.
1317 default push location.
1317 """
1318 """
1318 # Avoid cycles.
1319 # Avoid cycles.
1319 from . import (
1320 from . import (
1320 discovery,
1321 discovery,
1321 hg,
1322 hg,
1322 )
1323 )
1323 # i18n: "outgoing" is a keyword
1324 # i18n: "outgoing" is a keyword
1324 l = getargs(x, 0, 1, _("outgoing takes one or no arguments"))
1325 l = getargs(x, 0, 1, _("outgoing takes one or no arguments"))
1325 # i18n: "outgoing" is a keyword
1326 # i18n: "outgoing" is a keyword
1326 dest = l and getstring(l[0], _("outgoing requires a repository path")) or ''
1327 dest = l and getstring(l[0], _("outgoing requires a repository path")) or ''
1327 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
1328 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
1328 dest, branches = hg.parseurl(dest)
1329 dest, branches = hg.parseurl(dest)
1329 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1330 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1330 if revs:
1331 if revs:
1331 revs = [repo.lookup(rev) for rev in revs]
1332 revs = [repo.lookup(rev) for rev in revs]
1332 other = hg.peer(repo, {}, dest)
1333 other = hg.peer(repo, {}, dest)
1333 repo.ui.pushbuffer()
1334 repo.ui.pushbuffer()
1334 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs)
1335 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs)
1335 repo.ui.popbuffer()
1336 repo.ui.popbuffer()
1336 cl = repo.changelog
1337 cl = repo.changelog
1337 o = {cl.rev(r) for r in outgoing.missing}
1338 o = {cl.rev(r) for r in outgoing.missing}
1338 return subset & o
1339 return subset & o
1339
1340
1340 @predicate('p1([set])', safe=True)
1341 @predicate('p1([set])', safe=True)
1341 def p1(repo, subset, x):
1342 def p1(repo, subset, x):
1342 """First parent of changesets in set, or the working directory.
1343 """First parent of changesets in set, or the working directory.
1343 """
1344 """
1344 if x is None:
1345 if x is None:
1345 p = repo[x].p1().rev()
1346 p = repo[x].p1().rev()
1346 if p >= 0:
1347 if p >= 0:
1347 return subset & baseset([p])
1348 return subset & baseset([p])
1348 return baseset()
1349 return baseset()
1349
1350
1350 ps = set()
1351 ps = set()
1351 cl = repo.changelog
1352 cl = repo.changelog
1352 for r in getset(repo, fullreposet(repo), x):
1353 for r in getset(repo, fullreposet(repo), x):
1353 try:
1354 try:
1354 ps.add(cl.parentrevs(r)[0])
1355 ps.add(cl.parentrevs(r)[0])
1355 except error.WdirUnsupported:
1356 except error.WdirUnsupported:
1356 ps.add(repo[r].parents()[0].rev())
1357 ps.add(repo[r].parents()[0].rev())
1357 ps -= {node.nullrev}
1358 ps -= {node.nullrev}
1358 # XXX we should turn this into a baseset instead of a set, smartset may do
1359 # XXX we should turn this into a baseset instead of a set, smartset may do
1359 # some optimizations from the fact this is a baseset.
1360 # some optimizations from the fact this is a baseset.
1360 return subset & ps
1361 return subset & ps
1361
1362
1362 @predicate('p2([set])', safe=True)
1363 @predicate('p2([set])', safe=True)
1363 def p2(repo, subset, x):
1364 def p2(repo, subset, x):
1364 """Second parent of changesets in set, or the working directory.
1365 """Second parent of changesets in set, or the working directory.
1365 """
1366 """
1366 if x is None:
1367 if x is None:
1367 ps = repo[x].parents()
1368 ps = repo[x].parents()
1368 try:
1369 try:
1369 p = ps[1].rev()
1370 p = ps[1].rev()
1370 if p >= 0:
1371 if p >= 0:
1371 return subset & baseset([p])
1372 return subset & baseset([p])
1372 return baseset()
1373 return baseset()
1373 except IndexError:
1374 except IndexError:
1374 return baseset()
1375 return baseset()
1375
1376
1376 ps = set()
1377 ps = set()
1377 cl = repo.changelog
1378 cl = repo.changelog
1378 for r in getset(repo, fullreposet(repo), x):
1379 for r in getset(repo, fullreposet(repo), x):
1379 try:
1380 try:
1380 ps.add(cl.parentrevs(r)[1])
1381 ps.add(cl.parentrevs(r)[1])
1381 except error.WdirUnsupported:
1382 except error.WdirUnsupported:
1382 parents = repo[r].parents()
1383 parents = repo[r].parents()
1383 if len(parents) == 2:
1384 if len(parents) == 2:
1384 ps.add(parents[1])
1385 ps.add(parents[1])
1385 ps -= {node.nullrev}
1386 ps -= {node.nullrev}
1386 # XXX we should turn this into a baseset instead of a set, smartset may do
1387 # XXX we should turn this into a baseset instead of a set, smartset may do
1387 # some optimizations from the fact this is a baseset.
1388 # some optimizations from the fact this is a baseset.
1388 return subset & ps
1389 return subset & ps
1389
1390
1390 def parentpost(repo, subset, x, order):
1391 def parentpost(repo, subset, x, order):
1391 return p1(repo, subset, x)
1392 return p1(repo, subset, x)
1392
1393
1393 @predicate('parents([set])', safe=True)
1394 @predicate('parents([set])', safe=True)
1394 def parents(repo, subset, x):
1395 def parents(repo, subset, x):
1395 """
1396 """
1396 The set of all parents for all changesets in set, or the working directory.
1397 The set of all parents for all changesets in set, or the working directory.
1397 """
1398 """
1398 if x is None:
1399 if x is None:
1399 ps = set(p.rev() for p in repo[x].parents())
1400 ps = set(p.rev() for p in repo[x].parents())
1400 else:
1401 else:
1401 ps = set()
1402 ps = set()
1402 cl = repo.changelog
1403 cl = repo.changelog
1403 up = ps.update
1404 up = ps.update
1404 parentrevs = cl.parentrevs
1405 parentrevs = cl.parentrevs
1405 for r in getset(repo, fullreposet(repo), x):
1406 for r in getset(repo, fullreposet(repo), x):
1406 try:
1407 try:
1407 up(parentrevs(r))
1408 up(parentrevs(r))
1408 except error.WdirUnsupported:
1409 except error.WdirUnsupported:
1409 up(p.rev() for p in repo[r].parents())
1410 up(p.rev() for p in repo[r].parents())
1410 ps -= {node.nullrev}
1411 ps -= {node.nullrev}
1411 return subset & ps
1412 return subset & ps
1412
1413
1413 def _phase(repo, subset, *targets):
1414 def _phase(repo, subset, *targets):
1414 """helper to select all rev in <targets> phases"""
1415 """helper to select all rev in <targets> phases"""
1415 s = repo._phasecache.getrevset(repo, targets)
1416 s = repo._phasecache.getrevset(repo, targets)
1416 return subset & s
1417 return subset & s
1417
1418
1418 @predicate('draft()', safe=True)
1419 @predicate('draft()', safe=True)
1419 def draft(repo, subset, x):
1420 def draft(repo, subset, x):
1420 """Changeset in draft phase."""
1421 """Changeset in draft phase."""
1421 # i18n: "draft" is a keyword
1422 # i18n: "draft" is a keyword
1422 getargs(x, 0, 0, _("draft takes no arguments"))
1423 getargs(x, 0, 0, _("draft takes no arguments"))
1423 target = phases.draft
1424 target = phases.draft
1424 return _phase(repo, subset, target)
1425 return _phase(repo, subset, target)
1425
1426
1426 @predicate('secret()', safe=True)
1427 @predicate('secret()', safe=True)
1427 def secret(repo, subset, x):
1428 def secret(repo, subset, x):
1428 """Changeset in secret phase."""
1429 """Changeset in secret phase."""
1429 # i18n: "secret" is a keyword
1430 # i18n: "secret" is a keyword
1430 getargs(x, 0, 0, _("secret takes no arguments"))
1431 getargs(x, 0, 0, _("secret takes no arguments"))
1431 target = phases.secret
1432 target = phases.secret
1432 return _phase(repo, subset, target)
1433 return _phase(repo, subset, target)
1433
1434
1434 def parentspec(repo, subset, x, n, order):
1435 def parentspec(repo, subset, x, n, order):
1435 """``set^0``
1436 """``set^0``
1436 The set.
1437 The set.
1437 ``set^1`` (or ``set^``), ``set^2``
1438 ``set^1`` (or ``set^``), ``set^2``
1438 First or second parent, respectively, of all changesets in set.
1439 First or second parent, respectively, of all changesets in set.
1439 """
1440 """
1440 try:
1441 try:
1441 n = int(n[1])
1442 n = int(n[1])
1442 if n not in (0, 1, 2):
1443 if n not in (0, 1, 2):
1443 raise ValueError
1444 raise ValueError
1444 except (TypeError, ValueError):
1445 except (TypeError, ValueError):
1445 raise error.ParseError(_("^ expects a number 0, 1, or 2"))
1446 raise error.ParseError(_("^ expects a number 0, 1, or 2"))
1446 ps = set()
1447 ps = set()
1447 cl = repo.changelog
1448 cl = repo.changelog
1448 for r in getset(repo, fullreposet(repo), x):
1449 for r in getset(repo, fullreposet(repo), x):
1449 if n == 0:
1450 if n == 0:
1450 ps.add(r)
1451 ps.add(r)
1451 elif n == 1:
1452 elif n == 1:
1452 try:
1453 try:
1453 ps.add(cl.parentrevs(r)[0])
1454 ps.add(cl.parentrevs(r)[0])
1454 except error.WdirUnsupported:
1455 except error.WdirUnsupported:
1455 ps.add(repo[r].parents()[0].rev())
1456 ps.add(repo[r].parents()[0].rev())
1456 else:
1457 else:
1457 try:
1458 try:
1458 parents = cl.parentrevs(r)
1459 parents = cl.parentrevs(r)
1459 if parents[1] != node.nullrev:
1460 if parents[1] != node.nullrev:
1460 ps.add(parents[1])
1461 ps.add(parents[1])
1461 except error.WdirUnsupported:
1462 except error.WdirUnsupported:
1462 parents = repo[r].parents()
1463 parents = repo[r].parents()
1463 if len(parents) == 2:
1464 if len(parents) == 2:
1464 ps.add(parents[1].rev())
1465 ps.add(parents[1].rev())
1465 return subset & ps
1466 return subset & ps
1466
1467
1467 @predicate('present(set)', safe=True)
1468 @predicate('present(set)', safe=True)
1468 def present(repo, subset, x):
1469 def present(repo, subset, x):
1469 """An empty set, if any revision in set isn't found; otherwise,
1470 """An empty set, if any revision in set isn't found; otherwise,
1470 all revisions in set.
1471 all revisions in set.
1471
1472
1472 If any of specified revisions is not present in the local repository,
1473 If any of specified revisions is not present in the local repository,
1473 the query is normally aborted. But this predicate allows the query
1474 the query is normally aborted. But this predicate allows the query
1474 to continue even in such cases.
1475 to continue even in such cases.
1475 """
1476 """
1476 try:
1477 try:
1477 return getset(repo, subset, x)
1478 return getset(repo, subset, x)
1478 except error.RepoLookupError:
1479 except error.RepoLookupError:
1479 return baseset()
1480 return baseset()
1480
1481
1481 # for internal use
1482 # for internal use
1482 @predicate('_notpublic', safe=True)
1483 @predicate('_notpublic', safe=True)
1483 def _notpublic(repo, subset, x):
1484 def _notpublic(repo, subset, x):
1484 getargs(x, 0, 0, "_notpublic takes no arguments")
1485 getargs(x, 0, 0, "_notpublic takes no arguments")
1485 return _phase(repo, subset, phases.draft, phases.secret)
1486 return _phase(repo, subset, phases.draft, phases.secret)
1486
1487
1487 @predicate('public()', safe=True)
1488 @predicate('public()', safe=True)
1488 def public(repo, subset, x):
1489 def public(repo, subset, x):
1489 """Changeset in public phase."""
1490 """Changeset in public phase."""
1490 # i18n: "public" is a keyword
1491 # i18n: "public" is a keyword
1491 getargs(x, 0, 0, _("public takes no arguments"))
1492 getargs(x, 0, 0, _("public takes no arguments"))
1492 phase = repo._phasecache.phase
1493 phase = repo._phasecache.phase
1493 target = phases.public
1494 target = phases.public
1494 condition = lambda r: phase(repo, r) == target
1495 condition = lambda r: phase(repo, r) == target
1495 return subset.filter(condition, condrepr=('<phase %r>', target),
1496 return subset.filter(condition, condrepr=('<phase %r>', target),
1496 cache=False)
1497 cache=False)
1497
1498
1498 @predicate('remote([id [,path]])', safe=False)
1499 @predicate('remote([id [,path]])', safe=False)
1499 def remote(repo, subset, x):
1500 def remote(repo, subset, x):
1500 """Local revision that corresponds to the given identifier in a
1501 """Local revision that corresponds to the given identifier in a
1501 remote repository, if present. Here, the '.' identifier is a
1502 remote repository, if present. Here, the '.' identifier is a
1502 synonym for the current local branch.
1503 synonym for the current local branch.
1503 """
1504 """
1504
1505
1505 from . import hg # avoid start-up nasties
1506 from . import hg # avoid start-up nasties
1506 # i18n: "remote" is a keyword
1507 # i18n: "remote" is a keyword
1507 l = getargs(x, 0, 2, _("remote takes zero, one, or two arguments"))
1508 l = getargs(x, 0, 2, _("remote takes zero, one, or two arguments"))
1508
1509
1509 q = '.'
1510 q = '.'
1510 if len(l) > 0:
1511 if len(l) > 0:
1511 # i18n: "remote" is a keyword
1512 # i18n: "remote" is a keyword
1512 q = getstring(l[0], _("remote requires a string id"))
1513 q = getstring(l[0], _("remote requires a string id"))
1513 if q == '.':
1514 if q == '.':
1514 q = repo['.'].branch()
1515 q = repo['.'].branch()
1515
1516
1516 dest = ''
1517 dest = ''
1517 if len(l) > 1:
1518 if len(l) > 1:
1518 # i18n: "remote" is a keyword
1519 # i18n: "remote" is a keyword
1519 dest = getstring(l[1], _("remote requires a repository path"))
1520 dest = getstring(l[1], _("remote requires a repository path"))
1520 dest = repo.ui.expandpath(dest or 'default')
1521 dest = repo.ui.expandpath(dest or 'default')
1521 dest, branches = hg.parseurl(dest)
1522 dest, branches = hg.parseurl(dest)
1522 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1523 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1523 if revs:
1524 if revs:
1524 revs = [repo.lookup(rev) for rev in revs]
1525 revs = [repo.lookup(rev) for rev in revs]
1525 other = hg.peer(repo, {}, dest)
1526 other = hg.peer(repo, {}, dest)
1526 n = other.lookup(q)
1527 n = other.lookup(q)
1527 if n in repo:
1528 if n in repo:
1528 r = repo[n].rev()
1529 r = repo[n].rev()
1529 if r in subset:
1530 if r in subset:
1530 return baseset([r])
1531 return baseset([r])
1531 return baseset()
1532 return baseset()
1532
1533
1533 @predicate('removes(pattern)', safe=True)
1534 @predicate('removes(pattern)', safe=True)
1534 def removes(repo, subset, x):
1535 def removes(repo, subset, x):
1535 """Changesets which remove files matching pattern.
1536 """Changesets which remove files matching pattern.
1536
1537
1537 The pattern without explicit kind like ``glob:`` is expected to be
1538 The pattern without explicit kind like ``glob:`` is expected to be
1538 relative to the current directory and match against a file or a
1539 relative to the current directory and match against a file or a
1539 directory.
1540 directory.
1540 """
1541 """
1541 # i18n: "removes" is a keyword
1542 # i18n: "removes" is a keyword
1542 pat = getstring(x, _("removes requires a pattern"))
1543 pat = getstring(x, _("removes requires a pattern"))
1543 return checkstatus(repo, subset, pat, 2)
1544 return checkstatus(repo, subset, pat, 2)
1544
1545
1545 @predicate('rev(number)', safe=True)
1546 @predicate('rev(number)', safe=True)
1546 def rev(repo, subset, x):
1547 def rev(repo, subset, x):
1547 """Revision with the given numeric identifier.
1548 """Revision with the given numeric identifier.
1548 """
1549 """
1549 # i18n: "rev" is a keyword
1550 # i18n: "rev" is a keyword
1550 l = getargs(x, 1, 1, _("rev requires one argument"))
1551 l = getargs(x, 1, 1, _("rev requires one argument"))
1551 try:
1552 try:
1552 # i18n: "rev" is a keyword
1553 # i18n: "rev" is a keyword
1553 l = int(getstring(l[0], _("rev requires a number")))
1554 l = int(getstring(l[0], _("rev requires a number")))
1554 except (TypeError, ValueError):
1555 except (TypeError, ValueError):
1555 # i18n: "rev" is a keyword
1556 # i18n: "rev" is a keyword
1556 raise error.ParseError(_("rev expects a number"))
1557 raise error.ParseError(_("rev expects a number"))
1557 if l not in repo.changelog and l not in (node.nullrev, node.wdirrev):
1558 if l not in repo.changelog and l not in (node.nullrev, node.wdirrev):
1558 return baseset()
1559 return baseset()
1559 return subset & baseset([l])
1560 return subset & baseset([l])
1560
1561
1561 @predicate('matching(revision [, field])', safe=True)
1562 @predicate('matching(revision [, field])', safe=True)
1562 def matching(repo, subset, x):
1563 def matching(repo, subset, x):
1563 """Changesets in which a given set of fields match the set of fields in the
1564 """Changesets in which a given set of fields match the set of fields in the
1564 selected revision or set.
1565 selected revision or set.
1565
1566
1566 To match more than one field pass the list of fields to match separated
1567 To match more than one field pass the list of fields to match separated
1567 by spaces (e.g. ``author description``).
1568 by spaces (e.g. ``author description``).
1568
1569
1569 Valid fields are most regular revision fields and some special fields.
1570 Valid fields are most regular revision fields and some special fields.
1570
1571
1571 Regular revision fields are ``description``, ``author``, ``branch``,
1572 Regular revision fields are ``description``, ``author``, ``branch``,
1572 ``date``, ``files``, ``phase``, ``parents``, ``substate``, ``user``
1573 ``date``, ``files``, ``phase``, ``parents``, ``substate``, ``user``
1573 and ``diff``.
1574 and ``diff``.
1574 Note that ``author`` and ``user`` are synonyms. ``diff`` refers to the
1575 Note that ``author`` and ``user`` are synonyms. ``diff`` refers to the
1575 contents of the revision. Two revisions matching their ``diff`` will
1576 contents of the revision. Two revisions matching their ``diff`` will
1576 also match their ``files``.
1577 also match their ``files``.
1577
1578
1578 Special fields are ``summary`` and ``metadata``:
1579 Special fields are ``summary`` and ``metadata``:
1579 ``summary`` matches the first line of the description.
1580 ``summary`` matches the first line of the description.
1580 ``metadata`` is equivalent to matching ``description user date``
1581 ``metadata`` is equivalent to matching ``description user date``
1581 (i.e. it matches the main metadata fields).
1582 (i.e. it matches the main metadata fields).
1582
1583
1583 ``metadata`` is the default field which is used when no fields are
1584 ``metadata`` is the default field which is used when no fields are
1584 specified. You can match more than one field at a time.
1585 specified. You can match more than one field at a time.
1585 """
1586 """
1586 # i18n: "matching" is a keyword
1587 # i18n: "matching" is a keyword
1587 l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
1588 l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
1588
1589
1589 revs = getset(repo, fullreposet(repo), l[0])
1590 revs = getset(repo, fullreposet(repo), l[0])
1590
1591
1591 fieldlist = ['metadata']
1592 fieldlist = ['metadata']
1592 if len(l) > 1:
1593 if len(l) > 1:
1593 fieldlist = getstring(l[1],
1594 fieldlist = getstring(l[1],
1594 # i18n: "matching" is a keyword
1595 # i18n: "matching" is a keyword
1595 _("matching requires a string "
1596 _("matching requires a string "
1596 "as its second argument")).split()
1597 "as its second argument")).split()
1597
1598
1598 # Make sure that there are no repeated fields,
1599 # Make sure that there are no repeated fields,
1599 # expand the 'special' 'metadata' field type
1600 # expand the 'special' 'metadata' field type
1600 # and check the 'files' whenever we check the 'diff'
1601 # and check the 'files' whenever we check the 'diff'
1601 fields = []
1602 fields = []
1602 for field in fieldlist:
1603 for field in fieldlist:
1603 if field == 'metadata':
1604 if field == 'metadata':
1604 fields += ['user', 'description', 'date']
1605 fields += ['user', 'description', 'date']
1605 elif field == 'diff':
1606 elif field == 'diff':
1606 # a revision matching the diff must also match the files
1607 # a revision matching the diff must also match the files
1607 # since matching the diff is very costly, make sure to
1608 # since matching the diff is very costly, make sure to
1608 # also match the files first
1609 # also match the files first
1609 fields += ['files', 'diff']
1610 fields += ['files', 'diff']
1610 else:
1611 else:
1611 if field == 'author':
1612 if field == 'author':
1612 field = 'user'
1613 field = 'user'
1613 fields.append(field)
1614 fields.append(field)
1614 fields = set(fields)
1615 fields = set(fields)
1615 if 'summary' in fields and 'description' in fields:
1616 if 'summary' in fields and 'description' in fields:
1616 # If a revision matches its description it also matches its summary
1617 # If a revision matches its description it also matches its summary
1617 fields.discard('summary')
1618 fields.discard('summary')
1618
1619
1619 # We may want to match more than one field
1620 # We may want to match more than one field
1620 # Not all fields take the same amount of time to be matched
1621 # Not all fields take the same amount of time to be matched
1621 # Sort the selected fields in order of increasing matching cost
1622 # Sort the selected fields in order of increasing matching cost
1622 fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary',
1623 fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary',
1623 'files', 'description', 'substate', 'diff']
1624 'files', 'description', 'substate', 'diff']
1624 def fieldkeyfunc(f):
1625 def fieldkeyfunc(f):
1625 try:
1626 try:
1626 return fieldorder.index(f)
1627 return fieldorder.index(f)
1627 except ValueError:
1628 except ValueError:
1628 # assume an unknown field is very costly
1629 # assume an unknown field is very costly
1629 return len(fieldorder)
1630 return len(fieldorder)
1630 fields = list(fields)
1631 fields = list(fields)
1631 fields.sort(key=fieldkeyfunc)
1632 fields.sort(key=fieldkeyfunc)
1632
1633
1633 # Each field will be matched with its own "getfield" function
1634 # Each field will be matched with its own "getfield" function
1634 # which will be added to the getfieldfuncs array of functions
1635 # which will be added to the getfieldfuncs array of functions
1635 getfieldfuncs = []
1636 getfieldfuncs = []
1636 _funcs = {
1637 _funcs = {
1637 'user': lambda r: repo[r].user(),
1638 'user': lambda r: repo[r].user(),
1638 'branch': lambda r: repo[r].branch(),
1639 'branch': lambda r: repo[r].branch(),
1639 'date': lambda r: repo[r].date(),
1640 'date': lambda r: repo[r].date(),
1640 'description': lambda r: repo[r].description(),
1641 'description': lambda r: repo[r].description(),
1641 'files': lambda r: repo[r].files(),
1642 'files': lambda r: repo[r].files(),
1642 'parents': lambda r: repo[r].parents(),
1643 'parents': lambda r: repo[r].parents(),
1643 'phase': lambda r: repo[r].phase(),
1644 'phase': lambda r: repo[r].phase(),
1644 'substate': lambda r: repo[r].substate,
1645 'substate': lambda r: repo[r].substate,
1645 'summary': lambda r: repo[r].description().splitlines()[0],
1646 'summary': lambda r: repo[r].description().splitlines()[0],
1646 'diff': lambda r: list(repo[r].diff(git=True),)
1647 'diff': lambda r: list(repo[r].diff(git=True),)
1647 }
1648 }
1648 for info in fields:
1649 for info in fields:
1649 getfield = _funcs.get(info, None)
1650 getfield = _funcs.get(info, None)
1650 if getfield is None:
1651 if getfield is None:
1651 raise error.ParseError(
1652 raise error.ParseError(
1652 # i18n: "matching" is a keyword
1653 # i18n: "matching" is a keyword
1653 _("unexpected field name passed to matching: %s") % info)
1654 _("unexpected field name passed to matching: %s") % info)
1654 getfieldfuncs.append(getfield)
1655 getfieldfuncs.append(getfield)
1655 # convert the getfield array of functions into a "getinfo" function
1656 # convert the getfield array of functions into a "getinfo" function
1656 # which returns an array of field values (or a single value if there
1657 # which returns an array of field values (or a single value if there
1657 # is only one field to match)
1658 # is only one field to match)
1658 getinfo = lambda r: [f(r) for f in getfieldfuncs]
1659 getinfo = lambda r: [f(r) for f in getfieldfuncs]
1659
1660
1660 def matches(x):
1661 def matches(x):
1661 for rev in revs:
1662 for rev in revs:
1662 target = getinfo(rev)
1663 target = getinfo(rev)
1663 match = True
1664 match = True
1664 for n, f in enumerate(getfieldfuncs):
1665 for n, f in enumerate(getfieldfuncs):
1665 if target[n] != f(x):
1666 if target[n] != f(x):
1666 match = False
1667 match = False
1667 if match:
1668 if match:
1668 return True
1669 return True
1669 return False
1670 return False
1670
1671
1671 return subset.filter(matches, condrepr=('<matching%r %r>', fields, revs))
1672 return subset.filter(matches, condrepr=('<matching%r %r>', fields, revs))
1672
1673
1673 @predicate('reverse(set)', safe=True, takeorder=True)
1674 @predicate('reverse(set)', safe=True, takeorder=True)
1674 def reverse(repo, subset, x, order):
1675 def reverse(repo, subset, x, order):
1675 """Reverse order of set.
1676 """Reverse order of set.
1676 """
1677 """
1677 l = getset(repo, subset, x)
1678 l = getset(repo, subset, x)
1678 if order == defineorder:
1679 if order == defineorder:
1679 l.reverse()
1680 l.reverse()
1680 return l
1681 return l
1681
1682
1682 @predicate('roots(set)', safe=True)
1683 @predicate('roots(set)', safe=True)
1683 def roots(repo, subset, x):
1684 def roots(repo, subset, x):
1684 """Changesets in set with no parent changeset in set.
1685 """Changesets in set with no parent changeset in set.
1685 """
1686 """
1686 s = getset(repo, fullreposet(repo), x)
1687 s = getset(repo, fullreposet(repo), x)
1687 parents = repo.changelog.parentrevs
1688 parents = repo.changelog.parentrevs
1688 def filter(r):
1689 def filter(r):
1689 for p in parents(r):
1690 for p in parents(r):
1690 if 0 <= p and p in s:
1691 if 0 <= p and p in s:
1691 return False
1692 return False
1692 return True
1693 return True
1693 return subset & s.filter(filter, condrepr='<roots>')
1694 return subset & s.filter(filter, condrepr='<roots>')
1694
1695
1695 _sortkeyfuncs = {
1696 _sortkeyfuncs = {
1696 'rev': lambda c: c.rev(),
1697 'rev': lambda c: c.rev(),
1697 'branch': lambda c: c.branch(),
1698 'branch': lambda c: c.branch(),
1698 'desc': lambda c: c.description(),
1699 'desc': lambda c: c.description(),
1699 'user': lambda c: c.user(),
1700 'user': lambda c: c.user(),
1700 'author': lambda c: c.user(),
1701 'author': lambda c: c.user(),
1701 'date': lambda c: c.date()[0],
1702 'date': lambda c: c.date()[0],
1702 }
1703 }
1703
1704
1704 def _getsortargs(x):
1705 def _getsortargs(x):
1705 """Parse sort options into (set, [(key, reverse)], opts)"""
1706 """Parse sort options into (set, [(key, reverse)], opts)"""
1706 args = getargsdict(x, 'sort', 'set keys topo.firstbranch')
1707 args = getargsdict(x, 'sort', 'set keys topo.firstbranch')
1707 if 'set' not in args:
1708 if 'set' not in args:
1708 # i18n: "sort" is a keyword
1709 # i18n: "sort" is a keyword
1709 raise error.ParseError(_('sort requires one or two arguments'))
1710 raise error.ParseError(_('sort requires one or two arguments'))
1710 keys = "rev"
1711 keys = "rev"
1711 if 'keys' in args:
1712 if 'keys' in args:
1712 # i18n: "sort" is a keyword
1713 # i18n: "sort" is a keyword
1713 keys = getstring(args['keys'], _("sort spec must be a string"))
1714 keys = getstring(args['keys'], _("sort spec must be a string"))
1714
1715
1715 keyflags = []
1716 keyflags = []
1716 for k in keys.split():
1717 for k in keys.split():
1717 fk = k
1718 fk = k
1718 reverse = (k[0] == '-')
1719 reverse = (k[0] == '-')
1719 if reverse:
1720 if reverse:
1720 k = k[1:]
1721 k = k[1:]
1721 if k not in _sortkeyfuncs and k != 'topo':
1722 if k not in _sortkeyfuncs and k != 'topo':
1722 raise error.ParseError(_("unknown sort key %r") % fk)
1723 raise error.ParseError(_("unknown sort key %r") % fk)
1723 keyflags.append((k, reverse))
1724 keyflags.append((k, reverse))
1724
1725
1725 if len(keyflags) > 1 and any(k == 'topo' for k, reverse in keyflags):
1726 if len(keyflags) > 1 and any(k == 'topo' for k, reverse in keyflags):
1726 # i18n: "topo" is a keyword
1727 # i18n: "topo" is a keyword
1727 raise error.ParseError(_('topo sort order cannot be combined '
1728 raise error.ParseError(_('topo sort order cannot be combined '
1728 'with other sort keys'))
1729 'with other sort keys'))
1729
1730
1730 opts = {}
1731 opts = {}
1731 if 'topo.firstbranch' in args:
1732 if 'topo.firstbranch' in args:
1732 if any(k == 'topo' for k, reverse in keyflags):
1733 if any(k == 'topo' for k, reverse in keyflags):
1733 opts['topo.firstbranch'] = args['topo.firstbranch']
1734 opts['topo.firstbranch'] = args['topo.firstbranch']
1734 else:
1735 else:
1735 # i18n: "topo" and "topo.firstbranch" are keywords
1736 # i18n: "topo" and "topo.firstbranch" are keywords
1736 raise error.ParseError(_('topo.firstbranch can only be used '
1737 raise error.ParseError(_('topo.firstbranch can only be used '
1737 'when using the topo sort key'))
1738 'when using the topo sort key'))
1738
1739
1739 return args['set'], keyflags, opts
1740 return args['set'], keyflags, opts
1740
1741
1741 @predicate('sort(set[, [-]key... [, ...]])', safe=True, takeorder=True)
1742 @predicate('sort(set[, [-]key... [, ...]])', safe=True, takeorder=True)
1742 def sort(repo, subset, x, order):
1743 def sort(repo, subset, x, order):
1743 """Sort set by keys. The default sort order is ascending, specify a key
1744 """Sort set by keys. The default sort order is ascending, specify a key
1744 as ``-key`` to sort in descending order.
1745 as ``-key`` to sort in descending order.
1745
1746
1746 The keys can be:
1747 The keys can be:
1747
1748
1748 - ``rev`` for the revision number,
1749 - ``rev`` for the revision number,
1749 - ``branch`` for the branch name,
1750 - ``branch`` for the branch name,
1750 - ``desc`` for the commit message (description),
1751 - ``desc`` for the commit message (description),
1751 - ``user`` for user name (``author`` can be used as an alias),
1752 - ``user`` for user name (``author`` can be used as an alias),
1752 - ``date`` for the commit date
1753 - ``date`` for the commit date
1753 - ``topo`` for a reverse topographical sort
1754 - ``topo`` for a reverse topographical sort
1754
1755
1755 The ``topo`` sort order cannot be combined with other sort keys. This sort
1756 The ``topo`` sort order cannot be combined with other sort keys. This sort
1756 takes one optional argument, ``topo.firstbranch``, which takes a revset that
1757 takes one optional argument, ``topo.firstbranch``, which takes a revset that
1757 specifies what topographical branches to prioritize in the sort.
1758 specifies what topographical branches to prioritize in the sort.
1758
1759
1759 """
1760 """
1760 s, keyflags, opts = _getsortargs(x)
1761 s, keyflags, opts = _getsortargs(x)
1761 revs = getset(repo, subset, s)
1762 revs = getset(repo, subset, s)
1762
1763
1763 if not keyflags or order != defineorder:
1764 if not keyflags or order != defineorder:
1764 return revs
1765 return revs
1765 if len(keyflags) == 1 and keyflags[0][0] == "rev":
1766 if len(keyflags) == 1 and keyflags[0][0] == "rev":
1766 revs.sort(reverse=keyflags[0][1])
1767 revs.sort(reverse=keyflags[0][1])
1767 return revs
1768 return revs
1768 elif keyflags[0][0] == "topo":
1769 elif keyflags[0][0] == "topo":
1769 firstbranch = ()
1770 firstbranch = ()
1770 if 'topo.firstbranch' in opts:
1771 if 'topo.firstbranch' in opts:
1771 firstbranch = getset(repo, subset, opts['topo.firstbranch'])
1772 firstbranch = getset(repo, subset, opts['topo.firstbranch'])
1772 revs = baseset(dagop.toposort(revs, repo.changelog.parentrevs,
1773 revs = baseset(dagop.toposort(revs, repo.changelog.parentrevs,
1773 firstbranch),
1774 firstbranch),
1774 istopo=True)
1775 istopo=True)
1775 if keyflags[0][1]:
1776 if keyflags[0][1]:
1776 revs.reverse()
1777 revs.reverse()
1777 return revs
1778 return revs
1778
1779
1779 # sort() is guaranteed to be stable
1780 # sort() is guaranteed to be stable
1780 ctxs = [repo[r] for r in revs]
1781 ctxs = [repo[r] for r in revs]
1781 for k, reverse in reversed(keyflags):
1782 for k, reverse in reversed(keyflags):
1782 ctxs.sort(key=_sortkeyfuncs[k], reverse=reverse)
1783 ctxs.sort(key=_sortkeyfuncs[k], reverse=reverse)
1783 return baseset([c.rev() for c in ctxs])
1784 return baseset([c.rev() for c in ctxs])
1784
1785
1785 @predicate('subrepo([pattern])')
1786 @predicate('subrepo([pattern])')
1786 def subrepo(repo, subset, x):
1787 def subrepo(repo, subset, x):
1787 """Changesets that add, modify or remove the given subrepo. If no subrepo
1788 """Changesets that add, modify or remove the given subrepo. If no subrepo
1788 pattern is named, any subrepo changes are returned.
1789 pattern is named, any subrepo changes are returned.
1789 """
1790 """
1790 # i18n: "subrepo" is a keyword
1791 # i18n: "subrepo" is a keyword
1791 args = getargs(x, 0, 1, _('subrepo takes at most one argument'))
1792 args = getargs(x, 0, 1, _('subrepo takes at most one argument'))
1792 pat = None
1793 pat = None
1793 if len(args) != 0:
1794 if len(args) != 0:
1794 pat = getstring(args[0], _("subrepo requires a pattern"))
1795 pat = getstring(args[0], _("subrepo requires a pattern"))
1795
1796
1796 m = matchmod.exact(repo.root, repo.root, ['.hgsubstate'])
1797 m = matchmod.exact(repo.root, repo.root, ['.hgsubstate'])
1797
1798
1798 def submatches(names):
1799 def submatches(names):
1799 k, p, m = util.stringmatcher(pat)
1800 k, p, m = util.stringmatcher(pat)
1800 for name in names:
1801 for name in names:
1801 if m(name):
1802 if m(name):
1802 yield name
1803 yield name
1803
1804
1804 def matches(x):
1805 def matches(x):
1805 c = repo[x]
1806 c = repo[x]
1806 s = repo.status(c.p1().node(), c.node(), match=m)
1807 s = repo.status(c.p1().node(), c.node(), match=m)
1807
1808
1808 if pat is None:
1809 if pat is None:
1809 return s.added or s.modified or s.removed
1810 return s.added or s.modified or s.removed
1810
1811
1811 if s.added:
1812 if s.added:
1812 return any(submatches(c.substate.keys()))
1813 return any(submatches(c.substate.keys()))
1813
1814
1814 if s.modified:
1815 if s.modified:
1815 subs = set(c.p1().substate.keys())
1816 subs = set(c.p1().substate.keys())
1816 subs.update(c.substate.keys())
1817 subs.update(c.substate.keys())
1817
1818
1818 for path in submatches(subs):
1819 for path in submatches(subs):
1819 if c.p1().substate.get(path) != c.substate.get(path):
1820 if c.p1().substate.get(path) != c.substate.get(path):
1820 return True
1821 return True
1821
1822
1822 if s.removed:
1823 if s.removed:
1823 return any(submatches(c.p1().substate.keys()))
1824 return any(submatches(c.p1().substate.keys()))
1824
1825
1825 return False
1826 return False
1826
1827
1827 return subset.filter(matches, condrepr=('<subrepo %r>', pat))
1828 return subset.filter(matches, condrepr=('<subrepo %r>', pat))
1828
1829
1830 def _mapbynodefunc(repo, s, f):
1831 """(repo, smartset, [node] -> [node]) -> smartset
1832
1833 Helper method to map a smartset to another smartset given a function only
1834 talking about nodes. Handles converting between rev numbers and nodes, and
1835 filtering.
1836 """
1837 cl = repo.unfiltered().changelog
1838 torev = cl.rev
1839 tonode = cl.node
1840 nodemap = cl.nodemap
1841 result = set(torev(n) for n in f(tonode(r) for r in s) if n in nodemap)
1842 return smartset.baseset(result - repo.changelog.filteredrevs)
1843
1844 @predicate('successors(set)', safe=True)
1845 def successors(repo, subset, x):
1846 """All successors for set, including the given set themselves"""
1847 s = getset(repo, fullreposet(repo), x)
1848 f = lambda nodes: obsutil.allsuccessors(repo.obsstore, nodes)
1849 d = _mapbynodefunc(repo, s, f)
1850 return subset & d
1851
1829 def _substringmatcher(pattern, casesensitive=True):
1852 def _substringmatcher(pattern, casesensitive=True):
1830 kind, pattern, matcher = util.stringmatcher(pattern,
1853 kind, pattern, matcher = util.stringmatcher(pattern,
1831 casesensitive=casesensitive)
1854 casesensitive=casesensitive)
1832 if kind == 'literal':
1855 if kind == 'literal':
1833 if not casesensitive:
1856 if not casesensitive:
1834 pattern = encoding.lower(pattern)
1857 pattern = encoding.lower(pattern)
1835 matcher = lambda s: pattern in encoding.lower(s)
1858 matcher = lambda s: pattern in encoding.lower(s)
1836 else:
1859 else:
1837 matcher = lambda s: pattern in s
1860 matcher = lambda s: pattern in s
1838 return kind, pattern, matcher
1861 return kind, pattern, matcher
1839
1862
1840 @predicate('tag([name])', safe=True)
1863 @predicate('tag([name])', safe=True)
1841 def tag(repo, subset, x):
1864 def tag(repo, subset, x):
1842 """The specified tag by name, or all tagged revisions if no name is given.
1865 """The specified tag by name, or all tagged revisions if no name is given.
1843
1866
1844 Pattern matching is supported for `name`. See
1867 Pattern matching is supported for `name`. See
1845 :hg:`help revisions.patterns`.
1868 :hg:`help revisions.patterns`.
1846 """
1869 """
1847 # i18n: "tag" is a keyword
1870 # i18n: "tag" is a keyword
1848 args = getargs(x, 0, 1, _("tag takes one or no arguments"))
1871 args = getargs(x, 0, 1, _("tag takes one or no arguments"))
1849 cl = repo.changelog
1872 cl = repo.changelog
1850 if args:
1873 if args:
1851 pattern = getstring(args[0],
1874 pattern = getstring(args[0],
1852 # i18n: "tag" is a keyword
1875 # i18n: "tag" is a keyword
1853 _('the argument to tag must be a string'))
1876 _('the argument to tag must be a string'))
1854 kind, pattern, matcher = util.stringmatcher(pattern)
1877 kind, pattern, matcher = util.stringmatcher(pattern)
1855 if kind == 'literal':
1878 if kind == 'literal':
1856 # avoid resolving all tags
1879 # avoid resolving all tags
1857 tn = repo._tagscache.tags.get(pattern, None)
1880 tn = repo._tagscache.tags.get(pattern, None)
1858 if tn is None:
1881 if tn is None:
1859 raise error.RepoLookupError(_("tag '%s' does not exist")
1882 raise error.RepoLookupError(_("tag '%s' does not exist")
1860 % pattern)
1883 % pattern)
1861 s = {repo[tn].rev()}
1884 s = {repo[tn].rev()}
1862 else:
1885 else:
1863 s = {cl.rev(n) for t, n in repo.tagslist() if matcher(t)}
1886 s = {cl.rev(n) for t, n in repo.tagslist() if matcher(t)}
1864 else:
1887 else:
1865 s = {cl.rev(n) for t, n in repo.tagslist() if t != 'tip'}
1888 s = {cl.rev(n) for t, n in repo.tagslist() if t != 'tip'}
1866 return subset & s
1889 return subset & s
1867
1890
1868 @predicate('tagged', safe=True)
1891 @predicate('tagged', safe=True)
1869 def tagged(repo, subset, x):
1892 def tagged(repo, subset, x):
1870 return tag(repo, subset, x)
1893 return tag(repo, subset, x)
1871
1894
1872 @predicate('unstable()', safe=True)
1895 @predicate('unstable()', safe=True)
1873 def unstable(repo, subset, x):
1896 def unstable(repo, subset, x):
1874 """Non-obsolete changesets with obsolete ancestors.
1897 """Non-obsolete changesets with obsolete ancestors.
1875 """
1898 """
1876 # i18n: "unstable" is a keyword
1899 # i18n: "unstable" is a keyword
1877 getargs(x, 0, 0, _("unstable takes no arguments"))
1900 getargs(x, 0, 0, _("unstable takes no arguments"))
1878 unstables = obsmod.getrevs(repo, 'unstable')
1901 unstables = obsmod.getrevs(repo, 'unstable')
1879 return subset & unstables
1902 return subset & unstables
1880
1903
1881
1904
1882 @predicate('user(string)', safe=True)
1905 @predicate('user(string)', safe=True)
1883 def user(repo, subset, x):
1906 def user(repo, subset, x):
1884 """User name contains string. The match is case-insensitive.
1907 """User name contains string. The match is case-insensitive.
1885
1908
1886 Pattern matching is supported for `string`. See
1909 Pattern matching is supported for `string`. See
1887 :hg:`help revisions.patterns`.
1910 :hg:`help revisions.patterns`.
1888 """
1911 """
1889 return author(repo, subset, x)
1912 return author(repo, subset, x)
1890
1913
1891 @predicate('wdir()', safe=True)
1914 @predicate('wdir()', safe=True)
1892 def wdir(repo, subset, x):
1915 def wdir(repo, subset, x):
1893 """Working directory. (EXPERIMENTAL)"""
1916 """Working directory. (EXPERIMENTAL)"""
1894 # i18n: "wdir" is a keyword
1917 # i18n: "wdir" is a keyword
1895 getargs(x, 0, 0, _("wdir takes no arguments"))
1918 getargs(x, 0, 0, _("wdir takes no arguments"))
1896 if node.wdirrev in subset or isinstance(subset, fullreposet):
1919 if node.wdirrev in subset or isinstance(subset, fullreposet):
1897 return baseset([node.wdirrev])
1920 return baseset([node.wdirrev])
1898 return baseset()
1921 return baseset()
1899
1922
1900 def _orderedlist(repo, subset, x):
1923 def _orderedlist(repo, subset, x):
1901 s = getstring(x, "internal error")
1924 s = getstring(x, "internal error")
1902 if not s:
1925 if not s:
1903 return baseset()
1926 return baseset()
1904 # remove duplicates here. it's difficult for caller to deduplicate sets
1927 # remove duplicates here. it's difficult for caller to deduplicate sets
1905 # because different symbols can point to the same rev.
1928 # because different symbols can point to the same rev.
1906 cl = repo.changelog
1929 cl = repo.changelog
1907 ls = []
1930 ls = []
1908 seen = set()
1931 seen = set()
1909 for t in s.split('\0'):
1932 for t in s.split('\0'):
1910 try:
1933 try:
1911 # fast path for integer revision
1934 # fast path for integer revision
1912 r = int(t)
1935 r = int(t)
1913 if str(r) != t or r not in cl:
1936 if str(r) != t or r not in cl:
1914 raise ValueError
1937 raise ValueError
1915 revs = [r]
1938 revs = [r]
1916 except ValueError:
1939 except ValueError:
1917 revs = stringset(repo, subset, t)
1940 revs = stringset(repo, subset, t)
1918
1941
1919 for r in revs:
1942 for r in revs:
1920 if r in seen:
1943 if r in seen:
1921 continue
1944 continue
1922 if (r in subset
1945 if (r in subset
1923 or r == node.nullrev and isinstance(subset, fullreposet)):
1946 or r == node.nullrev and isinstance(subset, fullreposet)):
1924 ls.append(r)
1947 ls.append(r)
1925 seen.add(r)
1948 seen.add(r)
1926 return baseset(ls)
1949 return baseset(ls)
1927
1950
1928 # for internal use
1951 # for internal use
1929 @predicate('_list', safe=True, takeorder=True)
1952 @predicate('_list', safe=True, takeorder=True)
1930 def _list(repo, subset, x, order):
1953 def _list(repo, subset, x, order):
1931 if order == followorder:
1954 if order == followorder:
1932 # slow path to take the subset order
1955 # slow path to take the subset order
1933 return subset & _orderedlist(repo, fullreposet(repo), x)
1956 return subset & _orderedlist(repo, fullreposet(repo), x)
1934 else:
1957 else:
1935 return _orderedlist(repo, subset, x)
1958 return _orderedlist(repo, subset, x)
1936
1959
1937 def _orderedintlist(repo, subset, x):
1960 def _orderedintlist(repo, subset, x):
1938 s = getstring(x, "internal error")
1961 s = getstring(x, "internal error")
1939 if not s:
1962 if not s:
1940 return baseset()
1963 return baseset()
1941 ls = [int(r) for r in s.split('\0')]
1964 ls = [int(r) for r in s.split('\0')]
1942 s = subset
1965 s = subset
1943 return baseset([r for r in ls if r in s])
1966 return baseset([r for r in ls if r in s])
1944
1967
1945 # for internal use
1968 # for internal use
1946 @predicate('_intlist', safe=True, takeorder=True)
1969 @predicate('_intlist', safe=True, takeorder=True)
1947 def _intlist(repo, subset, x, order):
1970 def _intlist(repo, subset, x, order):
1948 if order == followorder:
1971 if order == followorder:
1949 # slow path to take the subset order
1972 # slow path to take the subset order
1950 return subset & _orderedintlist(repo, fullreposet(repo), x)
1973 return subset & _orderedintlist(repo, fullreposet(repo), x)
1951 else:
1974 else:
1952 return _orderedintlist(repo, subset, x)
1975 return _orderedintlist(repo, subset, x)
1953
1976
1954 def _orderedhexlist(repo, subset, x):
1977 def _orderedhexlist(repo, subset, x):
1955 s = getstring(x, "internal error")
1978 s = getstring(x, "internal error")
1956 if not s:
1979 if not s:
1957 return baseset()
1980 return baseset()
1958 cl = repo.changelog
1981 cl = repo.changelog
1959 ls = [cl.rev(node.bin(r)) for r in s.split('\0')]
1982 ls = [cl.rev(node.bin(r)) for r in s.split('\0')]
1960 s = subset
1983 s = subset
1961 return baseset([r for r in ls if r in s])
1984 return baseset([r for r in ls if r in s])
1962
1985
1963 # for internal use
1986 # for internal use
1964 @predicate('_hexlist', safe=True, takeorder=True)
1987 @predicate('_hexlist', safe=True, takeorder=True)
1965 def _hexlist(repo, subset, x, order):
1988 def _hexlist(repo, subset, x, order):
1966 if order == followorder:
1989 if order == followorder:
1967 # slow path to take the subset order
1990 # slow path to take the subset order
1968 return subset & _orderedhexlist(repo, fullreposet(repo), x)
1991 return subset & _orderedhexlist(repo, fullreposet(repo), x)
1969 else:
1992 else:
1970 return _orderedhexlist(repo, subset, x)
1993 return _orderedhexlist(repo, subset, x)
1971
1994
1972 methods = {
1995 methods = {
1973 "range": rangeset,
1996 "range": rangeset,
1974 "rangeall": rangeall,
1997 "rangeall": rangeall,
1975 "rangepre": rangepre,
1998 "rangepre": rangepre,
1976 "rangepost": rangepost,
1999 "rangepost": rangepost,
1977 "dagrange": dagrange,
2000 "dagrange": dagrange,
1978 "string": stringset,
2001 "string": stringset,
1979 "symbol": stringset,
2002 "symbol": stringset,
1980 "and": andset,
2003 "and": andset,
1981 "or": orset,
2004 "or": orset,
1982 "not": notset,
2005 "not": notset,
1983 "difference": differenceset,
2006 "difference": differenceset,
1984 "list": listset,
2007 "list": listset,
1985 "keyvalue": keyvaluepair,
2008 "keyvalue": keyvaluepair,
1986 "func": func,
2009 "func": func,
1987 "ancestor": ancestorspec,
2010 "ancestor": ancestorspec,
1988 "parent": parentspec,
2011 "parent": parentspec,
1989 "parentpost": parentpost,
2012 "parentpost": parentpost,
1990 }
2013 }
1991
2014
1992 def posttreebuilthook(tree, repo):
2015 def posttreebuilthook(tree, repo):
1993 # hook for extensions to execute code on the optimized tree
2016 # hook for extensions to execute code on the optimized tree
1994 pass
2017 pass
1995
2018
1996 def match(ui, spec, repo=None, order=defineorder):
2019 def match(ui, spec, repo=None, order=defineorder):
1997 """Create a matcher for a single revision spec
2020 """Create a matcher for a single revision spec
1998
2021
1999 If order=followorder, a matcher takes the ordering specified by the input
2022 If order=followorder, a matcher takes the ordering specified by the input
2000 set.
2023 set.
2001 """
2024 """
2002 return matchany(ui, [spec], repo=repo, order=order)
2025 return matchany(ui, [spec], repo=repo, order=order)
2003
2026
2004 def matchany(ui, specs, repo=None, order=defineorder, localalias=None):
2027 def matchany(ui, specs, repo=None, order=defineorder, localalias=None):
2005 """Create a matcher that will include any revisions matching one of the
2028 """Create a matcher that will include any revisions matching one of the
2006 given specs
2029 given specs
2007
2030
2008 If order=followorder, a matcher takes the ordering specified by the input
2031 If order=followorder, a matcher takes the ordering specified by the input
2009 set.
2032 set.
2010
2033
2011 If localalias is not None, it is a dict {name: definitionstring}. It takes
2034 If localalias is not None, it is a dict {name: definitionstring}. It takes
2012 precedence over [revsetalias] config section.
2035 precedence over [revsetalias] config section.
2013 """
2036 """
2014 if not specs:
2037 if not specs:
2015 def mfunc(repo, subset=None):
2038 def mfunc(repo, subset=None):
2016 return baseset()
2039 return baseset()
2017 return mfunc
2040 return mfunc
2018 if not all(specs):
2041 if not all(specs):
2019 raise error.ParseError(_("empty query"))
2042 raise error.ParseError(_("empty query"))
2020 lookup = None
2043 lookup = None
2021 if repo:
2044 if repo:
2022 lookup = repo.__contains__
2045 lookup = repo.__contains__
2023 if len(specs) == 1:
2046 if len(specs) == 1:
2024 tree = revsetlang.parse(specs[0], lookup)
2047 tree = revsetlang.parse(specs[0], lookup)
2025 else:
2048 else:
2026 tree = ('or',
2049 tree = ('or',
2027 ('list',) + tuple(revsetlang.parse(s, lookup) for s in specs))
2050 ('list',) + tuple(revsetlang.parse(s, lookup) for s in specs))
2028
2051
2029 aliases = []
2052 aliases = []
2030 warn = None
2053 warn = None
2031 if ui:
2054 if ui:
2032 aliases.extend(ui.configitems('revsetalias'))
2055 aliases.extend(ui.configitems('revsetalias'))
2033 warn = ui.warn
2056 warn = ui.warn
2034 if localalias:
2057 if localalias:
2035 aliases.extend(localalias.items())
2058 aliases.extend(localalias.items())
2036 if aliases:
2059 if aliases:
2037 tree = revsetlang.expandaliases(tree, aliases, warn=warn)
2060 tree = revsetlang.expandaliases(tree, aliases, warn=warn)
2038 tree = revsetlang.foldconcat(tree)
2061 tree = revsetlang.foldconcat(tree)
2039 tree = revsetlang.analyze(tree, order)
2062 tree = revsetlang.analyze(tree, order)
2040 tree = revsetlang.optimize(tree)
2063 tree = revsetlang.optimize(tree)
2041 posttreebuilthook(tree, repo)
2064 posttreebuilthook(tree, repo)
2042 return makematcher(tree)
2065 return makematcher(tree)
2043
2066
2044 def makematcher(tree):
2067 def makematcher(tree):
2045 """Create a matcher from an evaluatable tree"""
2068 """Create a matcher from an evaluatable tree"""
2046 def mfunc(repo, subset=None):
2069 def mfunc(repo, subset=None):
2047 if subset is None:
2070 if subset is None:
2048 subset = fullreposet(repo)
2071 subset = fullreposet(repo)
2049 return getset(repo, subset, tree)
2072 return getset(repo, subset, tree)
2050 return mfunc
2073 return mfunc
2051
2074
2052 def loadpredicate(ui, extname, registrarobj):
2075 def loadpredicate(ui, extname, registrarobj):
2053 """Load revset predicates from specified registrarobj
2076 """Load revset predicates from specified registrarobj
2054 """
2077 """
2055 for name, func in registrarobj._table.iteritems():
2078 for name, func in registrarobj._table.iteritems():
2056 symbols[name] = func
2079 symbols[name] = func
2057 if func._safe:
2080 if func._safe:
2058 safesymbols.add(name)
2081 safesymbols.add(name)
2059
2082
2060 # load built-in predicates explicitly to setup safesymbols
2083 # load built-in predicates explicitly to setup safesymbols
2061 loadpredicate(None, None, predicate)
2084 loadpredicate(None, None, predicate)
2062
2085
2063 # tell hggettext to extract docstrings from these functions:
2086 # tell hggettext to extract docstrings from these functions:
2064 i18nfunctions = symbols.values()
2087 i18nfunctions = symbols.values()
@@ -1,4285 +1,4339 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 > testrevset=$TESTTMP/testrevset.py
24 > testrevset=$TESTTMP/testrevset.py
24 > EOF
25 > EOF
25
26
26 $ try() {
27 $ try() {
27 > hg debugrevspec --debug "$@"
28 > hg debugrevspec --debug "$@"
28 > }
29 > }
29
30
30 $ log() {
31 $ log() {
31 > hg log --template '{rev}\n' -r "$1"
32 > hg log --template '{rev}\n' -r "$1"
32 > }
33 > }
33
34
34 extension to build '_intlist()' and '_hexlist()', which is necessary because
35 extension to build '_intlist()' and '_hexlist()', which is necessary because
35 these predicates use '\0' as a separator:
36 these predicates use '\0' as a separator:
36
37
37 $ cat <<EOF > debugrevlistspec.py
38 $ cat <<EOF > debugrevlistspec.py
38 > from __future__ import absolute_import
39 > from __future__ import absolute_import
39 > from mercurial import (
40 > from mercurial import (
40 > node as nodemod,
41 > node as nodemod,
41 > registrar,
42 > registrar,
42 > revset,
43 > revset,
43 > revsetlang,
44 > revsetlang,
44 > smartset,
45 > smartset,
45 > )
46 > )
46 > cmdtable = {}
47 > cmdtable = {}
47 > command = registrar.command(cmdtable)
48 > command = registrar.command(cmdtable)
48 > @command(b'debugrevlistspec',
49 > @command(b'debugrevlistspec',
49 > [('', 'optimize', None, 'print parsed tree after optimizing'),
50 > [('', 'optimize', None, 'print parsed tree after optimizing'),
50 > ('', 'bin', None, 'unhexlify arguments')])
51 > ('', 'bin', None, 'unhexlify arguments')])
51 > def debugrevlistspec(ui, repo, fmt, *args, **opts):
52 > def debugrevlistspec(ui, repo, fmt, *args, **opts):
52 > if opts['bin']:
53 > if opts['bin']:
53 > args = map(nodemod.bin, args)
54 > args = map(nodemod.bin, args)
54 > expr = revsetlang.formatspec(fmt, list(args))
55 > expr = revsetlang.formatspec(fmt, list(args))
55 > if ui.verbose:
56 > if ui.verbose:
56 > tree = revsetlang.parse(expr, lookup=repo.__contains__)
57 > tree = revsetlang.parse(expr, lookup=repo.__contains__)
57 > ui.note(revsetlang.prettyformat(tree), "\n")
58 > ui.note(revsetlang.prettyformat(tree), "\n")
58 > if opts["optimize"]:
59 > if opts["optimize"]:
59 > opttree = revsetlang.optimize(revsetlang.analyze(tree))
60 > opttree = revsetlang.optimize(revsetlang.analyze(tree))
60 > ui.note("* optimized:\n", revsetlang.prettyformat(opttree),
61 > ui.note("* optimized:\n", revsetlang.prettyformat(opttree),
61 > "\n")
62 > "\n")
62 > func = revset.match(ui, expr, repo)
63 > func = revset.match(ui, expr, repo)
63 > revs = func(repo)
64 > revs = func(repo)
64 > if ui.verbose:
65 > if ui.verbose:
65 > ui.note("* set:\n", smartset.prettyformat(revs), "\n")
66 > ui.note("* set:\n", smartset.prettyformat(revs), "\n")
66 > for c in revs:
67 > for c in revs:
67 > ui.write("%s\n" % c)
68 > ui.write("%s\n" % c)
68 > EOF
69 > EOF
69 $ cat <<EOF >> $HGRCPATH
70 $ cat <<EOF >> $HGRCPATH
70 > [extensions]
71 > [extensions]
71 > debugrevlistspec = $TESTTMP/debugrevlistspec.py
72 > debugrevlistspec = $TESTTMP/debugrevlistspec.py
72 > EOF
73 > EOF
73 $ trylist() {
74 $ trylist() {
74 > hg debugrevlistspec --debug "$@"
75 > hg debugrevlistspec --debug "$@"
75 > }
76 > }
76
77
77 $ hg init repo
78 $ hg init repo
78 $ cd repo
79 $ cd repo
79
80
80 $ echo a > a
81 $ echo a > a
81 $ hg branch a
82 $ hg branch a
82 marked working directory as branch a
83 marked working directory as branch a
83 (branches are permanent and global, did you want a bookmark?)
84 (branches are permanent and global, did you want a bookmark?)
84 $ hg ci -Aqm0
85 $ hg ci -Aqm0
85
86
86 $ echo b > b
87 $ echo b > b
87 $ hg branch b
88 $ hg branch b
88 marked working directory as branch b
89 marked working directory as branch b
89 $ hg ci -Aqm1
90 $ hg ci -Aqm1
90
91
91 $ rm a
92 $ rm a
92 $ hg branch a-b-c-
93 $ hg branch a-b-c-
93 marked working directory as branch a-b-c-
94 marked working directory as branch a-b-c-
94 $ hg ci -Aqm2 -u Bob
95 $ hg ci -Aqm2 -u Bob
95
96
96 $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
97 $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
97 2
98 2
98 $ hg log -r "extra('branch')" --template '{rev}\n'
99 $ hg log -r "extra('branch')" --template '{rev}\n'
99 0
100 0
100 1
101 1
101 2
102 2
102 $ hg log -r "extra('branch', 're:a')" --template '{rev} {branch}\n'
103 $ hg log -r "extra('branch', 're:a')" --template '{rev} {branch}\n'
103 0 a
104 0 a
104 2 a-b-c-
105 2 a-b-c-
105
106
106 $ hg co 1
107 $ hg co 1
107 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
108 $ hg branch +a+b+c+
109 $ hg branch +a+b+c+
109 marked working directory as branch +a+b+c+
110 marked working directory as branch +a+b+c+
110 $ hg ci -Aqm3
111 $ hg ci -Aqm3
111
112
112 $ hg co 2 # interleave
113 $ hg co 2 # interleave
113 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
114 $ echo bb > b
115 $ echo bb > b
115 $ hg branch -- -a-b-c-
116 $ hg branch -- -a-b-c-
116 marked working directory as branch -a-b-c-
117 marked working directory as branch -a-b-c-
117 $ hg ci -Aqm4 -d "May 12 2005"
118 $ hg ci -Aqm4 -d "May 12 2005"
118
119
119 $ hg co 3
120 $ hg co 3
120 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
121 $ hg branch !a/b/c/
122 $ hg branch !a/b/c/
122 marked working directory as branch !a/b/c/
123 marked working directory as branch !a/b/c/
123 $ hg ci -Aqm"5 bug"
124 $ hg ci -Aqm"5 bug"
124
125
125 $ hg merge 4
126 $ hg merge 4
126 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
127 (branch merge, don't forget to commit)
128 (branch merge, don't forget to commit)
128 $ hg branch _a_b_c_
129 $ hg branch _a_b_c_
129 marked working directory as branch _a_b_c_
130 marked working directory as branch _a_b_c_
130 $ hg ci -Aqm"6 issue619"
131 $ hg ci -Aqm"6 issue619"
131
132
132 $ hg branch .a.b.c.
133 $ hg branch .a.b.c.
133 marked working directory as branch .a.b.c.
134 marked working directory as branch .a.b.c.
134 $ hg ci -Aqm7
135 $ hg ci -Aqm7
135
136
136 $ hg branch all
137 $ hg branch all
137 marked working directory as branch all
138 marked working directory as branch all
138
139
139 $ hg co 4
140 $ hg co 4
140 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
141 $ hg branch Γ©
142 $ hg branch Γ©
142 marked working directory as branch \xc3\xa9 (esc)
143 marked working directory as branch \xc3\xa9 (esc)
143 $ hg ci -Aqm9
144 $ hg ci -Aqm9
144
145
145 $ hg tag -r6 1.0
146 $ hg tag -r6 1.0
146 $ hg bookmark -r6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
147 $ hg bookmark -r6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
147
148
148 $ hg clone --quiet -U -r 7 . ../remote1
149 $ hg clone --quiet -U -r 7 . ../remote1
149 $ hg clone --quiet -U -r 8 . ../remote2
150 $ hg clone --quiet -U -r 8 . ../remote2
150 $ echo "[paths]" >> .hg/hgrc
151 $ echo "[paths]" >> .hg/hgrc
151 $ echo "default = ../remote1" >> .hg/hgrc
152 $ echo "default = ../remote1" >> .hg/hgrc
152
153
153 trivial
154 trivial
154
155
155 $ try 0:1
156 $ try 0:1
156 (range
157 (range
157 ('symbol', '0')
158 ('symbol', '0')
158 ('symbol', '1'))
159 ('symbol', '1'))
159 * set:
160 * set:
160 <spanset+ 0:2>
161 <spanset+ 0:2>
161 0
162 0
162 1
163 1
163 $ try --optimize :
164 $ try --optimize :
164 (rangeall
165 (rangeall
165 None)
166 None)
166 * optimized:
167 * optimized:
167 (rangeall
168 (rangeall
168 None
169 None
169 define)
170 define)
170 * set:
171 * set:
171 <spanset+ 0:10>
172 <spanset+ 0:10>
172 0
173 0
173 1
174 1
174 2
175 2
175 3
176 3
176 4
177 4
177 5
178 5
178 6
179 6
179 7
180 7
180 8
181 8
181 9
182 9
182 $ try 3::6
183 $ try 3::6
183 (dagrange
184 (dagrange
184 ('symbol', '3')
185 ('symbol', '3')
185 ('symbol', '6'))
186 ('symbol', '6'))
186 * set:
187 * set:
187 <baseset+ [3, 5, 6]>
188 <baseset+ [3, 5, 6]>
188 3
189 3
189 5
190 5
190 6
191 6
191 $ try '0|1|2'
192 $ try '0|1|2'
192 (or
193 (or
193 (list
194 (list
194 ('symbol', '0')
195 ('symbol', '0')
195 ('symbol', '1')
196 ('symbol', '1')
196 ('symbol', '2')))
197 ('symbol', '2')))
197 * set:
198 * set:
198 <baseset [0, 1, 2]>
199 <baseset [0, 1, 2]>
199 0
200 0
200 1
201 1
201 2
202 2
202
203
203 names that should work without quoting
204 names that should work without quoting
204
205
205 $ try a
206 $ try a
206 ('symbol', 'a')
207 ('symbol', 'a')
207 * set:
208 * set:
208 <baseset [0]>
209 <baseset [0]>
209 0
210 0
210 $ try b-a
211 $ try b-a
211 (minus
212 (minus
212 ('symbol', 'b')
213 ('symbol', 'b')
213 ('symbol', 'a'))
214 ('symbol', 'a'))
214 * set:
215 * set:
215 <filteredset
216 <filteredset
216 <baseset [1]>,
217 <baseset [1]>,
217 <not
218 <not
218 <baseset [0]>>>
219 <baseset [0]>>>
219 1
220 1
220 $ try _a_b_c_
221 $ try _a_b_c_
221 ('symbol', '_a_b_c_')
222 ('symbol', '_a_b_c_')
222 * set:
223 * set:
223 <baseset [6]>
224 <baseset [6]>
224 6
225 6
225 $ try _a_b_c_-a
226 $ try _a_b_c_-a
226 (minus
227 (minus
227 ('symbol', '_a_b_c_')
228 ('symbol', '_a_b_c_')
228 ('symbol', 'a'))
229 ('symbol', 'a'))
229 * set:
230 * set:
230 <filteredset
231 <filteredset
231 <baseset [6]>,
232 <baseset [6]>,
232 <not
233 <not
233 <baseset [0]>>>
234 <baseset [0]>>>
234 6
235 6
235 $ try .a.b.c.
236 $ try .a.b.c.
236 ('symbol', '.a.b.c.')
237 ('symbol', '.a.b.c.')
237 * set:
238 * set:
238 <baseset [7]>
239 <baseset [7]>
239 7
240 7
240 $ try .a.b.c.-a
241 $ try .a.b.c.-a
241 (minus
242 (minus
242 ('symbol', '.a.b.c.')
243 ('symbol', '.a.b.c.')
243 ('symbol', 'a'))
244 ('symbol', 'a'))
244 * set:
245 * set:
245 <filteredset
246 <filteredset
246 <baseset [7]>,
247 <baseset [7]>,
247 <not
248 <not
248 <baseset [0]>>>
249 <baseset [0]>>>
249 7
250 7
250
251
251 names that should be caught by fallback mechanism
252 names that should be caught by fallback mechanism
252
253
253 $ try -- '-a-b-c-'
254 $ try -- '-a-b-c-'
254 ('symbol', '-a-b-c-')
255 ('symbol', '-a-b-c-')
255 * set:
256 * set:
256 <baseset [4]>
257 <baseset [4]>
257 4
258 4
258 $ log -a-b-c-
259 $ log -a-b-c-
259 4
260 4
260 $ try '+a+b+c+'
261 $ try '+a+b+c+'
261 ('symbol', '+a+b+c+')
262 ('symbol', '+a+b+c+')
262 * set:
263 * set:
263 <baseset [3]>
264 <baseset [3]>
264 3
265 3
265 $ try '+a+b+c+:'
266 $ try '+a+b+c+:'
266 (rangepost
267 (rangepost
267 ('symbol', '+a+b+c+'))
268 ('symbol', '+a+b+c+'))
268 * set:
269 * set:
269 <spanset+ 3:10>
270 <spanset+ 3:10>
270 3
271 3
271 4
272 4
272 5
273 5
273 6
274 6
274 7
275 7
275 8
276 8
276 9
277 9
277 $ try ':+a+b+c+'
278 $ try ':+a+b+c+'
278 (rangepre
279 (rangepre
279 ('symbol', '+a+b+c+'))
280 ('symbol', '+a+b+c+'))
280 * set:
281 * set:
281 <spanset+ 0:4>
282 <spanset+ 0:4>
282 0
283 0
283 1
284 1
284 2
285 2
285 3
286 3
286 $ try -- '-a-b-c-:+a+b+c+'
287 $ try -- '-a-b-c-:+a+b+c+'
287 (range
288 (range
288 ('symbol', '-a-b-c-')
289 ('symbol', '-a-b-c-')
289 ('symbol', '+a+b+c+'))
290 ('symbol', '+a+b+c+'))
290 * set:
291 * set:
291 <spanset- 3:5>
292 <spanset- 3:5>
292 4
293 4
293 3
294 3
294 $ log '-a-b-c-:+a+b+c+'
295 $ log '-a-b-c-:+a+b+c+'
295 4
296 4
296 3
297 3
297
298
298 $ try -- -a-b-c--a # complains
299 $ try -- -a-b-c--a # complains
299 (minus
300 (minus
300 (minus
301 (minus
301 (minus
302 (minus
302 (negate
303 (negate
303 ('symbol', 'a'))
304 ('symbol', 'a'))
304 ('symbol', 'b'))
305 ('symbol', 'b'))
305 ('symbol', 'c'))
306 ('symbol', 'c'))
306 (negate
307 (negate
307 ('symbol', 'a')))
308 ('symbol', 'a')))
308 abort: unknown revision '-a'!
309 abort: unknown revision '-a'!
309 [255]
310 [255]
310 $ try Γ©
311 $ try Γ©
311 ('symbol', '\xc3\xa9')
312 ('symbol', '\xc3\xa9')
312 * set:
313 * set:
313 <baseset [9]>
314 <baseset [9]>
314 9
315 9
315
316
316 no quoting needed
317 no quoting needed
317
318
318 $ log ::a-b-c-
319 $ log ::a-b-c-
319 0
320 0
320 1
321 1
321 2
322 2
322
323
323 quoting needed
324 quoting needed
324
325
325 $ try '"-a-b-c-"-a'
326 $ try '"-a-b-c-"-a'
326 (minus
327 (minus
327 ('string', '-a-b-c-')
328 ('string', '-a-b-c-')
328 ('symbol', 'a'))
329 ('symbol', 'a'))
329 * set:
330 * set:
330 <filteredset
331 <filteredset
331 <baseset [4]>,
332 <baseset [4]>,
332 <not
333 <not
333 <baseset [0]>>>
334 <baseset [0]>>>
334 4
335 4
335
336
336 $ log '1 or 2'
337 $ log '1 or 2'
337 1
338 1
338 2
339 2
339 $ log '1|2'
340 $ log '1|2'
340 1
341 1
341 2
342 2
342 $ log '1 and 2'
343 $ log '1 and 2'
343 $ log '1&2'
344 $ log '1&2'
344 $ try '1&2|3' # precedence - and is higher
345 $ try '1&2|3' # precedence - and is higher
345 (or
346 (or
346 (list
347 (list
347 (and
348 (and
348 ('symbol', '1')
349 ('symbol', '1')
349 ('symbol', '2'))
350 ('symbol', '2'))
350 ('symbol', '3')))
351 ('symbol', '3')))
351 * set:
352 * set:
352 <addset
353 <addset
353 <baseset []>,
354 <baseset []>,
354 <baseset [3]>>
355 <baseset [3]>>
355 3
356 3
356 $ try '1|2&3'
357 $ try '1|2&3'
357 (or
358 (or
358 (list
359 (list
359 ('symbol', '1')
360 ('symbol', '1')
360 (and
361 (and
361 ('symbol', '2')
362 ('symbol', '2')
362 ('symbol', '3'))))
363 ('symbol', '3'))))
363 * set:
364 * set:
364 <addset
365 <addset
365 <baseset [1]>,
366 <baseset [1]>,
366 <baseset []>>
367 <baseset []>>
367 1
368 1
368 $ try '1&2&3' # associativity
369 $ try '1&2&3' # associativity
369 (and
370 (and
370 (and
371 (and
371 ('symbol', '1')
372 ('symbol', '1')
372 ('symbol', '2'))
373 ('symbol', '2'))
373 ('symbol', '3'))
374 ('symbol', '3'))
374 * set:
375 * set:
375 <baseset []>
376 <baseset []>
376 $ try '1|(2|3)'
377 $ try '1|(2|3)'
377 (or
378 (or
378 (list
379 (list
379 ('symbol', '1')
380 ('symbol', '1')
380 (group
381 (group
381 (or
382 (or
382 (list
383 (list
383 ('symbol', '2')
384 ('symbol', '2')
384 ('symbol', '3'))))))
385 ('symbol', '3'))))))
385 * set:
386 * set:
386 <addset
387 <addset
387 <baseset [1]>,
388 <baseset [1]>,
388 <baseset [2, 3]>>
389 <baseset [2, 3]>>
389 1
390 1
390 2
391 2
391 3
392 3
392 $ log '1.0' # tag
393 $ log '1.0' # tag
393 6
394 6
394 $ log 'a' # branch
395 $ log 'a' # branch
395 0
396 0
396 $ log '2785f51ee'
397 $ log '2785f51ee'
397 0
398 0
398 $ log 'date(2005)'
399 $ log 'date(2005)'
399 4
400 4
400 $ log 'date(this is a test)'
401 $ log 'date(this is a test)'
401 hg: parse error at 10: unexpected token: symbol
402 hg: parse error at 10: unexpected token: symbol
402 [255]
403 [255]
403 $ log 'date()'
404 $ log 'date()'
404 hg: parse error: date requires a string
405 hg: parse error: date requires a string
405 [255]
406 [255]
406 $ log 'date'
407 $ log 'date'
407 abort: unknown revision 'date'!
408 abort: unknown revision 'date'!
408 [255]
409 [255]
409 $ log 'date('
410 $ log 'date('
410 hg: parse error at 5: not a prefix: end
411 hg: parse error at 5: not a prefix: end
411 [255]
412 [255]
412 $ log 'date("\xy")'
413 $ log 'date("\xy")'
413 hg: parse error: invalid \x escape
414 hg: parse error: invalid \x escape
414 [255]
415 [255]
415 $ log 'date(tip)'
416 $ log 'date(tip)'
416 hg: parse error: invalid date: 'tip'
417 hg: parse error: invalid date: 'tip'
417 [255]
418 [255]
418 $ log '0:date'
419 $ log '0:date'
419 abort: unknown revision 'date'!
420 abort: unknown revision 'date'!
420 [255]
421 [255]
421 $ log '::"date"'
422 $ log '::"date"'
422 abort: unknown revision 'date'!
423 abort: unknown revision 'date'!
423 [255]
424 [255]
424 $ hg book date -r 4
425 $ hg book date -r 4
425 $ log '0:date'
426 $ log '0:date'
426 0
427 0
427 1
428 1
428 2
429 2
429 3
430 3
430 4
431 4
431 $ log '::date'
432 $ log '::date'
432 0
433 0
433 1
434 1
434 2
435 2
435 4
436 4
436 $ log '::"date"'
437 $ log '::"date"'
437 0
438 0
438 1
439 1
439 2
440 2
440 4
441 4
441 $ log 'date(2005) and 1::'
442 $ log 'date(2005) and 1::'
442 4
443 4
443 $ hg book -d date
444 $ hg book -d date
444
445
445 function name should be a symbol
446 function name should be a symbol
446
447
447 $ log '"date"(2005)'
448 $ log '"date"(2005)'
448 hg: parse error: not a symbol
449 hg: parse error: not a symbol
449 [255]
450 [255]
450
451
451 keyword arguments
452 keyword arguments
452
453
453 $ log 'extra(branch, value=a)'
454 $ log 'extra(branch, value=a)'
454 0
455 0
455
456
456 $ log 'extra(branch, a, b)'
457 $ log 'extra(branch, a, b)'
457 hg: parse error: extra takes at most 2 positional arguments
458 hg: parse error: extra takes at most 2 positional arguments
458 [255]
459 [255]
459 $ log 'extra(a, label=b)'
460 $ log 'extra(a, label=b)'
460 hg: parse error: extra got multiple values for keyword argument 'label'
461 hg: parse error: extra got multiple values for keyword argument 'label'
461 [255]
462 [255]
462 $ log 'extra(label=branch, default)'
463 $ log 'extra(label=branch, default)'
463 hg: parse error: extra got an invalid argument
464 hg: parse error: extra got an invalid argument
464 [255]
465 [255]
465 $ log 'extra(branch, foo+bar=baz)'
466 $ log 'extra(branch, foo+bar=baz)'
466 hg: parse error: extra got an invalid argument
467 hg: parse error: extra got an invalid argument
467 [255]
468 [255]
468 $ log 'extra(unknown=branch)'
469 $ log 'extra(unknown=branch)'
469 hg: parse error: extra got an unexpected keyword argument 'unknown'
470 hg: parse error: extra got an unexpected keyword argument 'unknown'
470 [255]
471 [255]
471
472
472 $ try 'foo=bar|baz'
473 $ try 'foo=bar|baz'
473 (keyvalue
474 (keyvalue
474 ('symbol', 'foo')
475 ('symbol', 'foo')
475 (or
476 (or
476 (list
477 (list
477 ('symbol', 'bar')
478 ('symbol', 'bar')
478 ('symbol', 'baz'))))
479 ('symbol', 'baz'))))
479 hg: parse error: can't use a key-value pair in this context
480 hg: parse error: can't use a key-value pair in this context
480 [255]
481 [255]
481
482
482 right-hand side should be optimized recursively
483 right-hand side should be optimized recursively
483
484
484 $ try --optimize 'foo=(not public())'
485 $ try --optimize 'foo=(not public())'
485 (keyvalue
486 (keyvalue
486 ('symbol', 'foo')
487 ('symbol', 'foo')
487 (group
488 (group
488 (not
489 (not
489 (func
490 (func
490 ('symbol', 'public')
491 ('symbol', 'public')
491 None))))
492 None))))
492 * optimized:
493 * optimized:
493 (keyvalue
494 (keyvalue
494 ('symbol', 'foo')
495 ('symbol', 'foo')
495 (func
496 (func
496 ('symbol', '_notpublic')
497 ('symbol', '_notpublic')
497 None
498 None
498 any))
499 any))
499 hg: parse error: can't use a key-value pair in this context
500 hg: parse error: can't use a key-value pair in this context
500 [255]
501 [255]
501
502
502 parsed tree at stages:
503 parsed tree at stages:
503
504
504 $ hg debugrevspec -p all '()'
505 $ hg debugrevspec -p all '()'
505 * parsed:
506 * parsed:
506 (group
507 (group
507 None)
508 None)
508 * expanded:
509 * expanded:
509 (group
510 (group
510 None)
511 None)
511 * concatenated:
512 * concatenated:
512 (group
513 (group
513 None)
514 None)
514 * analyzed:
515 * analyzed:
515 None
516 None
516 * optimized:
517 * optimized:
517 None
518 None
518 hg: parse error: missing argument
519 hg: parse error: missing argument
519 [255]
520 [255]
520
521
521 $ hg debugrevspec --no-optimized -p all '()'
522 $ hg debugrevspec --no-optimized -p all '()'
522 * parsed:
523 * parsed:
523 (group
524 (group
524 None)
525 None)
525 * expanded:
526 * expanded:
526 (group
527 (group
527 None)
528 None)
528 * concatenated:
529 * concatenated:
529 (group
530 (group
530 None)
531 None)
531 * analyzed:
532 * analyzed:
532 None
533 None
533 hg: parse error: missing argument
534 hg: parse error: missing argument
534 [255]
535 [255]
535
536
536 $ hg debugrevspec -p parsed -p analyzed -p optimized '(0|1)-1'
537 $ hg debugrevspec -p parsed -p analyzed -p optimized '(0|1)-1'
537 * parsed:
538 * parsed:
538 (minus
539 (minus
539 (group
540 (group
540 (or
541 (or
541 (list
542 (list
542 ('symbol', '0')
543 ('symbol', '0')
543 ('symbol', '1'))))
544 ('symbol', '1'))))
544 ('symbol', '1'))
545 ('symbol', '1'))
545 * analyzed:
546 * analyzed:
546 (and
547 (and
547 (or
548 (or
548 (list
549 (list
549 ('symbol', '0')
550 ('symbol', '0')
550 ('symbol', '1'))
551 ('symbol', '1'))
551 define)
552 define)
552 (not
553 (not
553 ('symbol', '1')
554 ('symbol', '1')
554 follow)
555 follow)
555 define)
556 define)
556 * optimized:
557 * optimized:
557 (difference
558 (difference
558 (func
559 (func
559 ('symbol', '_list')
560 ('symbol', '_list')
560 ('string', '0\x001')
561 ('string', '0\x001')
561 define)
562 define)
562 ('symbol', '1')
563 ('symbol', '1')
563 define)
564 define)
564 0
565 0
565
566
566 $ hg debugrevspec -p unknown '0'
567 $ hg debugrevspec -p unknown '0'
567 abort: invalid stage name: unknown
568 abort: invalid stage name: unknown
568 [255]
569 [255]
569
570
570 $ hg debugrevspec -p all --optimize '0'
571 $ hg debugrevspec -p all --optimize '0'
571 abort: cannot use --optimize with --show-stage
572 abort: cannot use --optimize with --show-stage
572 [255]
573 [255]
573
574
574 verify optimized tree:
575 verify optimized tree:
575
576
576 $ hg debugrevspec --verify '0|1'
577 $ hg debugrevspec --verify '0|1'
577
578
578 $ hg debugrevspec --verify -v -p analyzed -p optimized 'r3232() & 2'
579 $ hg debugrevspec --verify -v -p analyzed -p optimized 'r3232() & 2'
579 * analyzed:
580 * analyzed:
580 (and
581 (and
581 (func
582 (func
582 ('symbol', 'r3232')
583 ('symbol', 'r3232')
583 None
584 None
584 define)
585 define)
585 ('symbol', '2')
586 ('symbol', '2')
586 define)
587 define)
587 * optimized:
588 * optimized:
588 (and
589 (and
589 ('symbol', '2')
590 ('symbol', '2')
590 (func
591 (func
591 ('symbol', 'r3232')
592 ('symbol', 'r3232')
592 None
593 None
593 define)
594 define)
594 define)
595 define)
595 * analyzed set:
596 * analyzed set:
596 <baseset [2]>
597 <baseset [2]>
597 * optimized set:
598 * optimized set:
598 <baseset [2, 2]>
599 <baseset [2, 2]>
599 --- analyzed
600 --- analyzed
600 +++ optimized
601 +++ optimized
601 2
602 2
602 +2
603 +2
603 [1]
604 [1]
604
605
605 $ hg debugrevspec --no-optimized --verify-optimized '0'
606 $ hg debugrevspec --no-optimized --verify-optimized '0'
606 abort: cannot use --verify-optimized with --no-optimized
607 abort: cannot use --verify-optimized with --no-optimized
607 [255]
608 [255]
608
609
609 Test that symbols only get parsed as functions if there's an opening
610 Test that symbols only get parsed as functions if there's an opening
610 parenthesis.
611 parenthesis.
611
612
612 $ hg book only -r 9
613 $ hg book only -r 9
613 $ log 'only(only)' # Outer "only" is a function, inner "only" is the bookmark
614 $ log 'only(only)' # Outer "only" is a function, inner "only" is the bookmark
614 8
615 8
615 9
616 9
616
617
617 ':y' behaves like '0:y', but can't be rewritten as such since the revision '0'
618 ':y' behaves like '0:y', but can't be rewritten as such since the revision '0'
618 may be hidden (issue5385)
619 may be hidden (issue5385)
619
620
620 $ try -p parsed -p analyzed ':'
621 $ try -p parsed -p analyzed ':'
621 * parsed:
622 * parsed:
622 (rangeall
623 (rangeall
623 None)
624 None)
624 * analyzed:
625 * analyzed:
625 (rangeall
626 (rangeall
626 None
627 None
627 define)
628 define)
628 * set:
629 * set:
629 <spanset+ 0:10>
630 <spanset+ 0:10>
630 0
631 0
631 1
632 1
632 2
633 2
633 3
634 3
634 4
635 4
635 5
636 5
636 6
637 6
637 7
638 7
638 8
639 8
639 9
640 9
640 $ try -p analyzed ':1'
641 $ try -p analyzed ':1'
641 * analyzed:
642 * analyzed:
642 (rangepre
643 (rangepre
643 ('symbol', '1')
644 ('symbol', '1')
644 define)
645 define)
645 * set:
646 * set:
646 <spanset+ 0:2>
647 <spanset+ 0:2>
647 0
648 0
648 1
649 1
649 $ try -p analyzed ':(1|2)'
650 $ try -p analyzed ':(1|2)'
650 * analyzed:
651 * analyzed:
651 (rangepre
652 (rangepre
652 (or
653 (or
653 (list
654 (list
654 ('symbol', '1')
655 ('symbol', '1')
655 ('symbol', '2'))
656 ('symbol', '2'))
656 define)
657 define)
657 define)
658 define)
658 * set:
659 * set:
659 <spanset+ 0:3>
660 <spanset+ 0:3>
660 0
661 0
661 1
662 1
662 2
663 2
663 $ try -p analyzed ':(1&2)'
664 $ try -p analyzed ':(1&2)'
664 * analyzed:
665 * analyzed:
665 (rangepre
666 (rangepre
666 (and
667 (and
667 ('symbol', '1')
668 ('symbol', '1')
668 ('symbol', '2')
669 ('symbol', '2')
669 define)
670 define)
670 define)
671 define)
671 * set:
672 * set:
672 <baseset []>
673 <baseset []>
673
674
674 infix/suffix resolution of ^ operator (issue2884):
675 infix/suffix resolution of ^ operator (issue2884):
675
676
676 x^:y means (x^):y
677 x^:y means (x^):y
677
678
678 $ try '1^:2'
679 $ try '1^:2'
679 (range
680 (range
680 (parentpost
681 (parentpost
681 ('symbol', '1'))
682 ('symbol', '1'))
682 ('symbol', '2'))
683 ('symbol', '2'))
683 * set:
684 * set:
684 <spanset+ 0:3>
685 <spanset+ 0:3>
685 0
686 0
686 1
687 1
687 2
688 2
688
689
689 $ try '1^::2'
690 $ try '1^::2'
690 (dagrange
691 (dagrange
691 (parentpost
692 (parentpost
692 ('symbol', '1'))
693 ('symbol', '1'))
693 ('symbol', '2'))
694 ('symbol', '2'))
694 * set:
695 * set:
695 <baseset+ [0, 1, 2]>
696 <baseset+ [0, 1, 2]>
696 0
697 0
697 1
698 1
698 2
699 2
699
700
700 $ try '9^:'
701 $ try '9^:'
701 (rangepost
702 (rangepost
702 (parentpost
703 (parentpost
703 ('symbol', '9')))
704 ('symbol', '9')))
704 * set:
705 * set:
705 <spanset+ 8:10>
706 <spanset+ 8:10>
706 8
707 8
707 9
708 9
708
709
709 x^:y should be resolved before omitting group operators
710 x^:y should be resolved before omitting group operators
710
711
711 $ try '1^(:2)'
712 $ try '1^(:2)'
712 (parent
713 (parent
713 ('symbol', '1')
714 ('symbol', '1')
714 (group
715 (group
715 (rangepre
716 (rangepre
716 ('symbol', '2'))))
717 ('symbol', '2'))))
717 hg: parse error: ^ expects a number 0, 1, or 2
718 hg: parse error: ^ expects a number 0, 1, or 2
718 [255]
719 [255]
719
720
720 x^:y should be resolved recursively
721 x^:y should be resolved recursively
721
722
722 $ try 'sort(1^:2)'
723 $ try 'sort(1^:2)'
723 (func
724 (func
724 ('symbol', 'sort')
725 ('symbol', 'sort')
725 (range
726 (range
726 (parentpost
727 (parentpost
727 ('symbol', '1'))
728 ('symbol', '1'))
728 ('symbol', '2')))
729 ('symbol', '2')))
729 * set:
730 * set:
730 <spanset+ 0:3>
731 <spanset+ 0:3>
731 0
732 0
732 1
733 1
733 2
734 2
734
735
735 $ try '(3^:4)^:2'
736 $ try '(3^:4)^:2'
736 (range
737 (range
737 (parentpost
738 (parentpost
738 (group
739 (group
739 (range
740 (range
740 (parentpost
741 (parentpost
741 ('symbol', '3'))
742 ('symbol', '3'))
742 ('symbol', '4'))))
743 ('symbol', '4'))))
743 ('symbol', '2'))
744 ('symbol', '2'))
744 * set:
745 * set:
745 <spanset+ 0:3>
746 <spanset+ 0:3>
746 0
747 0
747 1
748 1
748 2
749 2
749
750
750 $ try '(3^::4)^::2'
751 $ try '(3^::4)^::2'
751 (dagrange
752 (dagrange
752 (parentpost
753 (parentpost
753 (group
754 (group
754 (dagrange
755 (dagrange
755 (parentpost
756 (parentpost
756 ('symbol', '3'))
757 ('symbol', '3'))
757 ('symbol', '4'))))
758 ('symbol', '4'))))
758 ('symbol', '2'))
759 ('symbol', '2'))
759 * set:
760 * set:
760 <baseset+ [0, 1, 2]>
761 <baseset+ [0, 1, 2]>
761 0
762 0
762 1
763 1
763 2
764 2
764
765
765 $ try '(9^:)^:'
766 $ try '(9^:)^:'
766 (rangepost
767 (rangepost
767 (parentpost
768 (parentpost
768 (group
769 (group
769 (rangepost
770 (rangepost
770 (parentpost
771 (parentpost
771 ('symbol', '9'))))))
772 ('symbol', '9'))))))
772 * set:
773 * set:
773 <spanset+ 4:10>
774 <spanset+ 4:10>
774 4
775 4
775 5
776 5
776 6
777 6
777 7
778 7
778 8
779 8
779 9
780 9
780
781
781 x^ in alias should also be resolved
782 x^ in alias should also be resolved
782
783
783 $ try 'A' --config 'revsetalias.A=1^:2'
784 $ try 'A' --config 'revsetalias.A=1^:2'
784 ('symbol', 'A')
785 ('symbol', 'A')
785 * expanded:
786 * expanded:
786 (range
787 (range
787 (parentpost
788 (parentpost
788 ('symbol', '1'))
789 ('symbol', '1'))
789 ('symbol', '2'))
790 ('symbol', '2'))
790 * set:
791 * set:
791 <spanset+ 0:3>
792 <spanset+ 0:3>
792 0
793 0
793 1
794 1
794 2
795 2
795
796
796 $ try 'A:2' --config 'revsetalias.A=1^'
797 $ try 'A:2' --config 'revsetalias.A=1^'
797 (range
798 (range
798 ('symbol', 'A')
799 ('symbol', 'A')
799 ('symbol', '2'))
800 ('symbol', '2'))
800 * expanded:
801 * expanded:
801 (range
802 (range
802 (parentpost
803 (parentpost
803 ('symbol', '1'))
804 ('symbol', '1'))
804 ('symbol', '2'))
805 ('symbol', '2'))
805 * set:
806 * set:
806 <spanset+ 0:3>
807 <spanset+ 0:3>
807 0
808 0
808 1
809 1
809 2
810 2
810
811
811 but not beyond the boundary of alias expansion, because the resolution should
812 but not beyond the boundary of alias expansion, because the resolution should
812 be made at the parsing stage
813 be made at the parsing stage
813
814
814 $ try '1^A' --config 'revsetalias.A=:2'
815 $ try '1^A' --config 'revsetalias.A=:2'
815 (parent
816 (parent
816 ('symbol', '1')
817 ('symbol', '1')
817 ('symbol', 'A'))
818 ('symbol', 'A'))
818 * expanded:
819 * expanded:
819 (parent
820 (parent
820 ('symbol', '1')
821 ('symbol', '1')
821 (rangepre
822 (rangepre
822 ('symbol', '2')))
823 ('symbol', '2')))
823 hg: parse error: ^ expects a number 0, 1, or 2
824 hg: parse error: ^ expects a number 0, 1, or 2
824 [255]
825 [255]
825
826
826 ancestor can accept 0 or more arguments
827 ancestor can accept 0 or more arguments
827
828
828 $ log 'ancestor()'
829 $ log 'ancestor()'
829 $ log 'ancestor(1)'
830 $ log 'ancestor(1)'
830 1
831 1
831 $ log 'ancestor(4,5)'
832 $ log 'ancestor(4,5)'
832 1
833 1
833 $ log 'ancestor(4,5) and 4'
834 $ log 'ancestor(4,5) and 4'
834 $ log 'ancestor(0,0,1,3)'
835 $ log 'ancestor(0,0,1,3)'
835 0
836 0
836 $ log 'ancestor(3,1,5,3,5,1)'
837 $ log 'ancestor(3,1,5,3,5,1)'
837 1
838 1
838 $ log 'ancestor(0,1,3,5)'
839 $ log 'ancestor(0,1,3,5)'
839 0
840 0
840 $ log 'ancestor(1,2,3,4,5)'
841 $ log 'ancestor(1,2,3,4,5)'
841 1
842 1
842
843
843 test ancestors
844 test ancestors
844
845
845 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
846 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
846 @ 9
847 @ 9
847 o 8
848 o 8
848 | o 7
849 | o 7
849 | o 6
850 | o 6
850 |/|
851 |/|
851 | o 5
852 | o 5
852 o | 4
853 o | 4
853 | o 3
854 | o 3
854 o | 2
855 o | 2
855 |/
856 |/
856 o 1
857 o 1
857 o 0
858 o 0
858
859
859 $ log 'ancestors(5)'
860 $ log 'ancestors(5)'
860 0
861 0
861 1
862 1
862 3
863 3
863 5
864 5
864 $ log 'ancestor(ancestors(5))'
865 $ log 'ancestor(ancestors(5))'
865 0
866 0
866 $ log '::r3232()'
867 $ log '::r3232()'
867 0
868 0
868 1
869 1
869 2
870 2
870 3
871 3
871
872
872 test ancestors with depth limit
873 test ancestors with depth limit
873
874
874 (depth=0 selects the node itself)
875 (depth=0 selects the node itself)
875
876
876 $ log 'reverse(ancestors(9, depth=0))'
877 $ log 'reverse(ancestors(9, depth=0))'
877 9
878 9
878
879
879 (interleaved: '4' would be missing if heap queue were higher depth first)
880 (interleaved: '4' would be missing if heap queue were higher depth first)
880
881
881 $ log 'reverse(ancestors(8:9, depth=1))'
882 $ log 'reverse(ancestors(8:9, depth=1))'
882 9
883 9
883 8
884 8
884 4
885 4
885
886
886 (interleaved: '2' would be missing if heap queue were higher depth first)
887 (interleaved: '2' would be missing if heap queue were higher depth first)
887
888
888 $ log 'reverse(ancestors(7+8, depth=2))'
889 $ log 'reverse(ancestors(7+8, depth=2))'
889 8
890 8
890 7
891 7
891 6
892 6
892 5
893 5
893 4
894 4
894 2
895 2
895
896
896 (walk example above by separate queries)
897 (walk example above by separate queries)
897
898
898 $ log 'reverse(ancestors(8, depth=2)) + reverse(ancestors(7, depth=2))'
899 $ log 'reverse(ancestors(8, depth=2)) + reverse(ancestors(7, depth=2))'
899 8
900 8
900 4
901 4
901 2
902 2
902 7
903 7
903 6
904 6
904 5
905 5
905
906
906 (walk 2nd and 3rd ancestors)
907 (walk 2nd and 3rd ancestors)
907
908
908 $ log 'reverse(ancestors(7, depth=3, startdepth=2))'
909 $ log 'reverse(ancestors(7, depth=3, startdepth=2))'
909 5
910 5
910 4
911 4
911 3
912 3
912 2
913 2
913
914
914 (interleaved: '4' would be missing if higher-depth ancestors weren't scanned)
915 (interleaved: '4' would be missing if higher-depth ancestors weren't scanned)
915
916
916 $ log 'reverse(ancestors(7+8, depth=2, startdepth=2))'
917 $ log 'reverse(ancestors(7+8, depth=2, startdepth=2))'
917 5
918 5
918 4
919 4
919 2
920 2
920
921
921 (note that 'ancestors(x, depth=y, startdepth=z)' does not identical to
922 (note that 'ancestors(x, depth=y, startdepth=z)' does not identical to
922 'ancestors(x, depth=y) - ancestors(x, depth=z-1)' because a node may have
923 'ancestors(x, depth=y) - ancestors(x, depth=z-1)' because a node may have
923 multiple depths)
924 multiple depths)
924
925
925 $ log 'reverse(ancestors(7+8, depth=2) - ancestors(7+8, depth=1))'
926 $ log 'reverse(ancestors(7+8, depth=2) - ancestors(7+8, depth=1))'
926 5
927 5
927 2
928 2
928
929
929 test bad arguments passed to ancestors()
930 test bad arguments passed to ancestors()
930
931
931 $ log 'ancestors(., depth=-1)'
932 $ log 'ancestors(., depth=-1)'
932 hg: parse error: negative depth
933 hg: parse error: negative depth
933 [255]
934 [255]
934 $ log 'ancestors(., depth=foo)'
935 $ log 'ancestors(., depth=foo)'
935 hg: parse error: ancestors expects an integer depth
936 hg: parse error: ancestors expects an integer depth
936 [255]
937 [255]
937
938
938 test descendants
939 test descendants
939
940
940 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
941 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
941 @ 9
942 @ 9
942 o 8
943 o 8
943 | o 7
944 | o 7
944 | o 6
945 | o 6
945 |/|
946 |/|
946 | o 5
947 | o 5
947 o | 4
948 o | 4
948 | o 3
949 | o 3
949 o | 2
950 o | 2
950 |/
951 |/
951 o 1
952 o 1
952 o 0
953 o 0
953
954
954 (null is ultimate root and has optimized path)
955 (null is ultimate root and has optimized path)
955
956
956 $ log 'null:4 & descendants(null)'
957 $ log 'null:4 & descendants(null)'
957 -1
958 -1
958 0
959 0
959 1
960 1
960 2
961 2
961 3
962 3
962 4
963 4
963
964
964 (including merge)
965 (including merge)
965
966
966 $ log ':8 & descendants(2)'
967 $ log ':8 & descendants(2)'
967 2
968 2
968 4
969 4
969 6
970 6
970 7
971 7
971 8
972 8
972
973
973 (multiple roots)
974 (multiple roots)
974
975
975 $ log ':8 & descendants(2+5)'
976 $ log ':8 & descendants(2+5)'
976 2
977 2
977 4
978 4
978 5
979 5
979 6
980 6
980 7
981 7
981 8
982 8
982
983
983 test descendants with depth limit
984 test descendants with depth limit
984
985
985 (depth=0 selects the node itself)
986 (depth=0 selects the node itself)
986
987
987 $ log 'descendants(0, depth=0)'
988 $ log 'descendants(0, depth=0)'
988 0
989 0
989 $ log 'null: & descendants(null, depth=0)'
990 $ log 'null: & descendants(null, depth=0)'
990 -1
991 -1
991
992
992 (p2 = null should be ignored)
993 (p2 = null should be ignored)
993
994
994 $ log 'null: & descendants(null, depth=2)'
995 $ log 'null: & descendants(null, depth=2)'
995 -1
996 -1
996 0
997 0
997 1
998 1
998
999
999 (multiple paths: depth(6) = (2, 3))
1000 (multiple paths: depth(6) = (2, 3))
1000
1001
1001 $ log 'descendants(1+3, depth=2)'
1002 $ log 'descendants(1+3, depth=2)'
1002 1
1003 1
1003 2
1004 2
1004 3
1005 3
1005 4
1006 4
1006 5
1007 5
1007 6
1008 6
1008
1009
1009 (multiple paths: depth(5) = (1, 2), depth(6) = (2, 3))
1010 (multiple paths: depth(5) = (1, 2), depth(6) = (2, 3))
1010
1011
1011 $ log 'descendants(3+1, depth=2, startdepth=2)'
1012 $ log 'descendants(3+1, depth=2, startdepth=2)'
1012 4
1013 4
1013 5
1014 5
1014 6
1015 6
1015
1016
1016 (multiple depths: depth(6) = (0, 2, 4), search for depth=2)
1017 (multiple depths: depth(6) = (0, 2, 4), search for depth=2)
1017
1018
1018 $ log 'descendants(0+3+6, depth=3, startdepth=1)'
1019 $ log 'descendants(0+3+6, depth=3, startdepth=1)'
1019 1
1020 1
1020 2
1021 2
1021 3
1022 3
1022 4
1023 4
1023 5
1024 5
1024 6
1025 6
1025 7
1026 7
1026
1027
1027 (multiple depths: depth(6) = (0, 4), no match)
1028 (multiple depths: depth(6) = (0, 4), no match)
1028
1029
1029 $ log 'descendants(0+6, depth=3, startdepth=1)'
1030 $ log 'descendants(0+6, depth=3, startdepth=1)'
1030 1
1031 1
1031 2
1032 2
1032 3
1033 3
1033 4
1034 4
1034 5
1035 5
1035 7
1036 7
1036
1037
1037 test author
1038 test author
1038
1039
1039 $ log 'author(bob)'
1040 $ log 'author(bob)'
1040 2
1041 2
1041 $ log 'author("re:bob|test")'
1042 $ log 'author("re:bob|test")'
1042 0
1043 0
1043 1
1044 1
1044 2
1045 2
1045 3
1046 3
1046 4
1047 4
1047 5
1048 5
1048 6
1049 6
1049 7
1050 7
1050 8
1051 8
1051 9
1052 9
1052 $ log 'author(r"re:\S")'
1053 $ log 'author(r"re:\S")'
1053 0
1054 0
1054 1
1055 1
1055 2
1056 2
1056 3
1057 3
1057 4
1058 4
1058 5
1059 5
1059 6
1060 6
1060 7
1061 7
1061 8
1062 8
1062 9
1063 9
1063 $ log 'branch(Γ©)'
1064 $ log 'branch(Γ©)'
1064 8
1065 8
1065 9
1066 9
1066 $ log 'branch(a)'
1067 $ log 'branch(a)'
1067 0
1068 0
1068 $ hg log -r 'branch("re:a")' --template '{rev} {branch}\n'
1069 $ hg log -r 'branch("re:a")' --template '{rev} {branch}\n'
1069 0 a
1070 0 a
1070 2 a-b-c-
1071 2 a-b-c-
1071 3 +a+b+c+
1072 3 +a+b+c+
1072 4 -a-b-c-
1073 4 -a-b-c-
1073 5 !a/b/c/
1074 5 !a/b/c/
1074 6 _a_b_c_
1075 6 _a_b_c_
1075 7 .a.b.c.
1076 7 .a.b.c.
1076 $ log 'children(ancestor(4,5))'
1077 $ log 'children(ancestor(4,5))'
1077 2
1078 2
1078 3
1079 3
1079
1080
1080 $ log 'children(4)'
1081 $ log 'children(4)'
1081 6
1082 6
1082 8
1083 8
1083 $ log 'children(null)'
1084 $ log 'children(null)'
1084 0
1085 0
1085
1086
1086 $ log 'closed()'
1087 $ log 'closed()'
1087 $ log 'contains(a)'
1088 $ log 'contains(a)'
1088 0
1089 0
1089 1
1090 1
1090 3
1091 3
1091 5
1092 5
1092 $ log 'contains("../repo/a")'
1093 $ log 'contains("../repo/a")'
1093 0
1094 0
1094 1
1095 1
1095 3
1096 3
1096 5
1097 5
1097 $ log 'desc(B)'
1098 $ log 'desc(B)'
1098 5
1099 5
1099 $ hg log -r 'desc(r"re:S?u")' --template "{rev} {desc|firstline}\n"
1100 $ hg log -r 'desc(r"re:S?u")' --template "{rev} {desc|firstline}\n"
1100 5 5 bug
1101 5 5 bug
1101 6 6 issue619
1102 6 6 issue619
1102 $ log 'descendants(2 or 3)'
1103 $ log 'descendants(2 or 3)'
1103 2
1104 2
1104 3
1105 3
1105 4
1106 4
1106 5
1107 5
1107 6
1108 6
1108 7
1109 7
1109 8
1110 8
1110 9
1111 9
1111 $ log 'file("b*")'
1112 $ log 'file("b*")'
1112 1
1113 1
1113 4
1114 4
1114 $ log 'filelog("b")'
1115 $ log 'filelog("b")'
1115 1
1116 1
1116 4
1117 4
1117 $ log 'filelog("../repo/b")'
1118 $ log 'filelog("../repo/b")'
1118 1
1119 1
1119 4
1120 4
1120 $ log 'follow()'
1121 $ log 'follow()'
1121 0
1122 0
1122 1
1123 1
1123 2
1124 2
1124 4
1125 4
1125 8
1126 8
1126 9
1127 9
1127 $ log 'grep("issue\d+")'
1128 $ log 'grep("issue\d+")'
1128 6
1129 6
1129 $ try 'grep("(")' # invalid regular expression
1130 $ try 'grep("(")' # invalid regular expression
1130 (func
1131 (func
1131 ('symbol', 'grep')
1132 ('symbol', 'grep')
1132 ('string', '('))
1133 ('string', '('))
1133 hg: parse error: invalid match pattern: unbalanced parenthesis
1134 hg: parse error: invalid match pattern: unbalanced parenthesis
1134 [255]
1135 [255]
1135 $ try 'grep("\bissue\d+")'
1136 $ try 'grep("\bissue\d+")'
1136 (func
1137 (func
1137 ('symbol', 'grep')
1138 ('symbol', 'grep')
1138 ('string', '\x08issue\\d+'))
1139 ('string', '\x08issue\\d+'))
1139 * set:
1140 * set:
1140 <filteredset
1141 <filteredset
1141 <fullreposet+ 0:10>,
1142 <fullreposet+ 0:10>,
1142 <grep '\x08issue\\d+'>>
1143 <grep '\x08issue\\d+'>>
1143 $ try 'grep(r"\bissue\d+")'
1144 $ try 'grep(r"\bissue\d+")'
1144 (func
1145 (func
1145 ('symbol', 'grep')
1146 ('symbol', 'grep')
1146 ('string', '\\bissue\\d+'))
1147 ('string', '\\bissue\\d+'))
1147 * set:
1148 * set:
1148 <filteredset
1149 <filteredset
1149 <fullreposet+ 0:10>,
1150 <fullreposet+ 0:10>,
1150 <grep '\\bissue\\d+'>>
1151 <grep '\\bissue\\d+'>>
1151 6
1152 6
1152 $ try 'grep(r"\")'
1153 $ try 'grep(r"\")'
1153 hg: parse error at 7: unterminated string
1154 hg: parse error at 7: unterminated string
1154 [255]
1155 [255]
1155 $ log 'head()'
1156 $ log 'head()'
1156 0
1157 0
1157 1
1158 1
1158 2
1159 2
1159 3
1160 3
1160 4
1161 4
1161 5
1162 5
1162 6
1163 6
1163 7
1164 7
1164 9
1165 9
1165 $ log 'heads(6::)'
1166 $ log 'heads(6::)'
1166 7
1167 7
1167 $ log 'keyword(issue)'
1168 $ log 'keyword(issue)'
1168 6
1169 6
1169 $ log 'keyword("test a")'
1170 $ log 'keyword("test a")'
1170
1171
1171 Test first (=limit) and last
1172 Test first (=limit) and last
1172
1173
1173 $ log 'limit(head(), 1)'
1174 $ log 'limit(head(), 1)'
1174 0
1175 0
1175 $ log 'limit(author("re:bob|test"), 3, 5)'
1176 $ log 'limit(author("re:bob|test"), 3, 5)'
1176 5
1177 5
1177 6
1178 6
1178 7
1179 7
1179 $ log 'limit(author("re:bob|test"), offset=6)'
1180 $ log 'limit(author("re:bob|test"), offset=6)'
1180 6
1181 6
1181 $ log 'limit(author("re:bob|test"), offset=10)'
1182 $ log 'limit(author("re:bob|test"), offset=10)'
1182 $ log 'limit(all(), 1, -1)'
1183 $ log 'limit(all(), 1, -1)'
1183 hg: parse error: negative offset
1184 hg: parse error: negative offset
1184 [255]
1185 [255]
1185 $ log 'limit(all(), -1)'
1186 $ log 'limit(all(), -1)'
1186 hg: parse error: negative number to select
1187 hg: parse error: negative number to select
1187 [255]
1188 [255]
1188 $ log 'limit(all(), 0)'
1189 $ log 'limit(all(), 0)'
1189
1190
1190 $ log 'last(all(), -1)'
1191 $ log 'last(all(), -1)'
1191 hg: parse error: negative number to select
1192 hg: parse error: negative number to select
1192 [255]
1193 [255]
1193 $ log 'last(all(), 0)'
1194 $ log 'last(all(), 0)'
1194 $ log 'last(all(), 1)'
1195 $ log 'last(all(), 1)'
1195 9
1196 9
1196 $ log 'last(all(), 2)'
1197 $ log 'last(all(), 2)'
1197 8
1198 8
1198 9
1199 9
1199
1200
1200 Test smartset.slice() by first/last()
1201 Test smartset.slice() by first/last()
1201
1202
1202 (using unoptimized set, filteredset as example)
1203 (using unoptimized set, filteredset as example)
1203
1204
1204 $ hg debugrevspec --no-show-revs -s '0:7 & branch("re:")'
1205 $ hg debugrevspec --no-show-revs -s '0:7 & branch("re:")'
1205 * set:
1206 * set:
1206 <filteredset
1207 <filteredset
1207 <spanset+ 0:8>,
1208 <spanset+ 0:8>,
1208 <branch 're:'>>
1209 <branch 're:'>>
1209 $ log 'limit(0:7 & branch("re:"), 3, 4)'
1210 $ log 'limit(0:7 & branch("re:"), 3, 4)'
1210 4
1211 4
1211 5
1212 5
1212 6
1213 6
1213 $ log 'limit(7:0 & branch("re:"), 3, 4)'
1214 $ log 'limit(7:0 & branch("re:"), 3, 4)'
1214 3
1215 3
1215 2
1216 2
1216 1
1217 1
1217 $ log 'last(0:7 & branch("re:"), 2)'
1218 $ log 'last(0:7 & branch("re:"), 2)'
1218 6
1219 6
1219 7
1220 7
1220
1221
1221 (using baseset)
1222 (using baseset)
1222
1223
1223 $ hg debugrevspec --no-show-revs -s 0+1+2+3+4+5+6+7
1224 $ hg debugrevspec --no-show-revs -s 0+1+2+3+4+5+6+7
1224 * set:
1225 * set:
1225 <baseset [0, 1, 2, 3, 4, 5, 6, 7]>
1226 <baseset [0, 1, 2, 3, 4, 5, 6, 7]>
1226 $ hg debugrevspec --no-show-revs -s 0::7
1227 $ hg debugrevspec --no-show-revs -s 0::7
1227 * set:
1228 * set:
1228 <baseset+ [0, 1, 2, 3, 4, 5, 6, 7]>
1229 <baseset+ [0, 1, 2, 3, 4, 5, 6, 7]>
1229 $ log 'limit(0+1+2+3+4+5+6+7, 3, 4)'
1230 $ log 'limit(0+1+2+3+4+5+6+7, 3, 4)'
1230 4
1231 4
1231 5
1232 5
1232 6
1233 6
1233 $ log 'limit(sort(0::7, rev), 3, 4)'
1234 $ log 'limit(sort(0::7, rev), 3, 4)'
1234 4
1235 4
1235 5
1236 5
1236 6
1237 6
1237 $ log 'limit(sort(0::7, -rev), 3, 4)'
1238 $ log 'limit(sort(0::7, -rev), 3, 4)'
1238 3
1239 3
1239 2
1240 2
1240 1
1241 1
1241 $ log 'last(sort(0::7, rev), 2)'
1242 $ log 'last(sort(0::7, rev), 2)'
1242 6
1243 6
1243 7
1244 7
1244 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 6)'
1245 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 6)'
1245 * set:
1246 * set:
1246 <baseset+ [6, 7]>
1247 <baseset+ [6, 7]>
1247 6
1248 6
1248 7
1249 7
1249 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 9)'
1250 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 9)'
1250 * set:
1251 * set:
1251 <baseset+ []>
1252 <baseset+ []>
1252 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 6)'
1253 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 6)'
1253 * set:
1254 * set:
1254 <baseset- [0, 1]>
1255 <baseset- [0, 1]>
1255 1
1256 1
1256 0
1257 0
1257 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 9)'
1258 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 9)'
1258 * set:
1259 * set:
1259 <baseset- []>
1260 <baseset- []>
1260 $ hg debugrevspec -s 'limit(0::7, 0)'
1261 $ hg debugrevspec -s 'limit(0::7, 0)'
1261 * set:
1262 * set:
1262 <baseset+ []>
1263 <baseset+ []>
1263
1264
1264 (using spanset)
1265 (using spanset)
1265
1266
1266 $ hg debugrevspec --no-show-revs -s 0:7
1267 $ hg debugrevspec --no-show-revs -s 0:7
1267 * set:
1268 * set:
1268 <spanset+ 0:8>
1269 <spanset+ 0:8>
1269 $ log 'limit(0:7, 3, 4)'
1270 $ log 'limit(0:7, 3, 4)'
1270 4
1271 4
1271 5
1272 5
1272 6
1273 6
1273 $ log 'limit(7:0, 3, 4)'
1274 $ log 'limit(7:0, 3, 4)'
1274 3
1275 3
1275 2
1276 2
1276 1
1277 1
1277 $ log 'limit(0:7, 3, 6)'
1278 $ log 'limit(0:7, 3, 6)'
1278 6
1279 6
1279 7
1280 7
1280 $ log 'limit(7:0, 3, 6)'
1281 $ log 'limit(7:0, 3, 6)'
1281 1
1282 1
1282 0
1283 0
1283 $ log 'last(0:7, 2)'
1284 $ log 'last(0:7, 2)'
1284 6
1285 6
1285 7
1286 7
1286 $ hg debugrevspec -s 'limit(0:7, 3, 6)'
1287 $ hg debugrevspec -s 'limit(0:7, 3, 6)'
1287 * set:
1288 * set:
1288 <spanset+ 6:8>
1289 <spanset+ 6:8>
1289 6
1290 6
1290 7
1291 7
1291 $ hg debugrevspec -s 'limit(0:7, 3, 9)'
1292 $ hg debugrevspec -s 'limit(0:7, 3, 9)'
1292 * set:
1293 * set:
1293 <spanset+ 8:8>
1294 <spanset+ 8:8>
1294 $ hg debugrevspec -s 'limit(7:0, 3, 6)'
1295 $ hg debugrevspec -s 'limit(7:0, 3, 6)'
1295 * set:
1296 * set:
1296 <spanset- 0:2>
1297 <spanset- 0:2>
1297 1
1298 1
1298 0
1299 0
1299 $ hg debugrevspec -s 'limit(7:0, 3, 9)'
1300 $ hg debugrevspec -s 'limit(7:0, 3, 9)'
1300 * set:
1301 * set:
1301 <spanset- 0:0>
1302 <spanset- 0:0>
1302 $ hg debugrevspec -s 'limit(0:7, 0)'
1303 $ hg debugrevspec -s 'limit(0:7, 0)'
1303 * set:
1304 * set:
1304 <spanset+ 0:0>
1305 <spanset+ 0:0>
1305
1306
1306 Test order of first/last revisions
1307 Test order of first/last revisions
1307
1308
1308 $ hg debugrevspec -s 'first(4:0, 3) & 3:'
1309 $ hg debugrevspec -s 'first(4:0, 3) & 3:'
1309 * set:
1310 * set:
1310 <filteredset
1311 <filteredset
1311 <spanset- 2:5>,
1312 <spanset- 2:5>,
1312 <spanset+ 3:10>>
1313 <spanset+ 3:10>>
1313 4
1314 4
1314 3
1315 3
1315
1316
1316 $ hg debugrevspec -s '3: & first(4:0, 3)'
1317 $ hg debugrevspec -s '3: & first(4:0, 3)'
1317 * set:
1318 * set:
1318 <filteredset
1319 <filteredset
1319 <spanset+ 3:10>,
1320 <spanset+ 3:10>,
1320 <spanset- 2:5>>
1321 <spanset- 2:5>>
1321 3
1322 3
1322 4
1323 4
1323
1324
1324 $ hg debugrevspec -s 'last(4:0, 3) & :1'
1325 $ hg debugrevspec -s 'last(4:0, 3) & :1'
1325 * set:
1326 * set:
1326 <filteredset
1327 <filteredset
1327 <spanset- 0:3>,
1328 <spanset- 0:3>,
1328 <spanset+ 0:2>>
1329 <spanset+ 0:2>>
1329 1
1330 1
1330 0
1331 0
1331
1332
1332 $ hg debugrevspec -s ':1 & last(4:0, 3)'
1333 $ hg debugrevspec -s ':1 & last(4:0, 3)'
1333 * set:
1334 * set:
1334 <filteredset
1335 <filteredset
1335 <spanset+ 0:2>,
1336 <spanset+ 0:2>,
1336 <spanset+ 0:3>>
1337 <spanset+ 0:3>>
1337 0
1338 0
1338 1
1339 1
1339
1340
1340 Test scmutil.revsingle() should return the last revision
1341 Test scmutil.revsingle() should return the last revision
1341
1342
1342 $ hg debugrevspec -s 'last(0::)'
1343 $ hg debugrevspec -s 'last(0::)'
1343 * set:
1344 * set:
1344 <baseset slice=0:1
1345 <baseset slice=0:1
1345 <generatorset->>
1346 <generatorset->>
1346 9
1347 9
1347 $ hg identify -r '0::' --num
1348 $ hg identify -r '0::' --num
1348 9
1349 9
1349
1350
1350 Test matching
1351 Test matching
1351
1352
1352 $ log 'matching(6)'
1353 $ log 'matching(6)'
1353 6
1354 6
1354 $ log 'matching(6:7, "phase parents user date branch summary files description substate")'
1355 $ log 'matching(6:7, "phase parents user date branch summary files description substate")'
1355 6
1356 6
1356 7
1357 7
1357
1358
1358 Testing min and max
1359 Testing min and max
1359
1360
1360 max: simple
1361 max: simple
1361
1362
1362 $ log 'max(contains(a))'
1363 $ log 'max(contains(a))'
1363 5
1364 5
1364
1365
1365 max: simple on unordered set)
1366 max: simple on unordered set)
1366
1367
1367 $ log 'max((4+0+2+5+7) and contains(a))'
1368 $ log 'max((4+0+2+5+7) and contains(a))'
1368 5
1369 5
1369
1370
1370 max: no result
1371 max: no result
1371
1372
1372 $ log 'max(contains(stringthatdoesnotappearanywhere))'
1373 $ log 'max(contains(stringthatdoesnotappearanywhere))'
1373
1374
1374 max: no result on unordered set
1375 max: no result on unordered set
1375
1376
1376 $ log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1377 $ log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1377
1378
1378 min: simple
1379 min: simple
1379
1380
1380 $ log 'min(contains(a))'
1381 $ log 'min(contains(a))'
1381 0
1382 0
1382
1383
1383 min: simple on unordered set
1384 min: simple on unordered set
1384
1385
1385 $ log 'min((4+0+2+5+7) and contains(a))'
1386 $ log 'min((4+0+2+5+7) and contains(a))'
1386 0
1387 0
1387
1388
1388 min: empty
1389 min: empty
1389
1390
1390 $ log 'min(contains(stringthatdoesnotappearanywhere))'
1391 $ log 'min(contains(stringthatdoesnotappearanywhere))'
1391
1392
1392 min: empty on unordered set
1393 min: empty on unordered set
1393
1394
1394 $ log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1395 $ log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1395
1396
1396
1397
1397 $ log 'merge()'
1398 $ log 'merge()'
1398 6
1399 6
1399 $ log 'branchpoint()'
1400 $ log 'branchpoint()'
1400 1
1401 1
1401 4
1402 4
1402 $ log 'modifies(b)'
1403 $ log 'modifies(b)'
1403 4
1404 4
1404 $ log 'modifies("path:b")'
1405 $ log 'modifies("path:b")'
1405 4
1406 4
1406 $ log 'modifies("*")'
1407 $ log 'modifies("*")'
1407 4
1408 4
1408 6
1409 6
1409 $ log 'modifies("set:modified()")'
1410 $ log 'modifies("set:modified()")'
1410 4
1411 4
1411 $ log 'id(5)'
1412 $ log 'id(5)'
1412 2
1413 2
1413 $ log 'only(9)'
1414 $ log 'only(9)'
1414 8
1415 8
1415 9
1416 9
1416 $ log 'only(8)'
1417 $ log 'only(8)'
1417 8
1418 8
1418 $ log 'only(9, 5)'
1419 $ log 'only(9, 5)'
1419 2
1420 2
1420 4
1421 4
1421 8
1422 8
1422 9
1423 9
1423 $ log 'only(7 + 9, 5 + 2)'
1424 $ log 'only(7 + 9, 5 + 2)'
1424 4
1425 4
1425 6
1426 6
1426 7
1427 7
1427 8
1428 8
1428 9
1429 9
1429
1430
1430 Test empty set input
1431 Test empty set input
1431 $ log 'only(p2())'
1432 $ log 'only(p2())'
1432 $ log 'only(p1(), p2())'
1433 $ log 'only(p1(), p2())'
1433 0
1434 0
1434 1
1435 1
1435 2
1436 2
1436 4
1437 4
1437 8
1438 8
1438 9
1439 9
1439
1440
1440 Test '%' operator
1441 Test '%' operator
1441
1442
1442 $ log '9%'
1443 $ log '9%'
1443 8
1444 8
1444 9
1445 9
1445 $ log '9%5'
1446 $ log '9%5'
1446 2
1447 2
1447 4
1448 4
1448 8
1449 8
1449 9
1450 9
1450 $ log '(7 + 9)%(5 + 2)'
1451 $ log '(7 + 9)%(5 + 2)'
1451 4
1452 4
1452 6
1453 6
1453 7
1454 7
1454 8
1455 8
1455 9
1456 9
1456
1457
1457 Test operand of '%' is optimized recursively (issue4670)
1458 Test operand of '%' is optimized recursively (issue4670)
1458
1459
1459 $ try --optimize '8:9-8%'
1460 $ try --optimize '8:9-8%'
1460 (onlypost
1461 (onlypost
1461 (minus
1462 (minus
1462 (range
1463 (range
1463 ('symbol', '8')
1464 ('symbol', '8')
1464 ('symbol', '9'))
1465 ('symbol', '9'))
1465 ('symbol', '8')))
1466 ('symbol', '8')))
1466 * optimized:
1467 * optimized:
1467 (func
1468 (func
1468 ('symbol', 'only')
1469 ('symbol', 'only')
1469 (difference
1470 (difference
1470 (range
1471 (range
1471 ('symbol', '8')
1472 ('symbol', '8')
1472 ('symbol', '9')
1473 ('symbol', '9')
1473 define)
1474 define)
1474 ('symbol', '8')
1475 ('symbol', '8')
1475 define)
1476 define)
1476 define)
1477 define)
1477 * set:
1478 * set:
1478 <baseset+ [8, 9]>
1479 <baseset+ [8, 9]>
1479 8
1480 8
1480 9
1481 9
1481 $ try --optimize '(9)%(5)'
1482 $ try --optimize '(9)%(5)'
1482 (only
1483 (only
1483 (group
1484 (group
1484 ('symbol', '9'))
1485 ('symbol', '9'))
1485 (group
1486 (group
1486 ('symbol', '5')))
1487 ('symbol', '5')))
1487 * optimized:
1488 * optimized:
1488 (func
1489 (func
1489 ('symbol', 'only')
1490 ('symbol', 'only')
1490 (list
1491 (list
1491 ('symbol', '9')
1492 ('symbol', '9')
1492 ('symbol', '5'))
1493 ('symbol', '5'))
1493 define)
1494 define)
1494 * set:
1495 * set:
1495 <baseset+ [2, 4, 8, 9]>
1496 <baseset+ [2, 4, 8, 9]>
1496 2
1497 2
1497 4
1498 4
1498 8
1499 8
1499 9
1500 9
1500
1501
1501 Test the order of operations
1502 Test the order of operations
1502
1503
1503 $ log '7 + 9%5 + 2'
1504 $ log '7 + 9%5 + 2'
1504 7
1505 7
1505 2
1506 2
1506 4
1507 4
1507 8
1508 8
1508 9
1509 9
1509
1510
1510 Test explicit numeric revision
1511 Test explicit numeric revision
1511 $ log 'rev(-2)'
1512 $ log 'rev(-2)'
1512 $ log 'rev(-1)'
1513 $ log 'rev(-1)'
1513 -1
1514 -1
1514 $ log 'rev(0)'
1515 $ log 'rev(0)'
1515 0
1516 0
1516 $ log 'rev(9)'
1517 $ log 'rev(9)'
1517 9
1518 9
1518 $ log 'rev(10)'
1519 $ log 'rev(10)'
1519 $ log 'rev(tip)'
1520 $ log 'rev(tip)'
1520 hg: parse error: rev expects a number
1521 hg: parse error: rev expects a number
1521 [255]
1522 [255]
1522
1523
1523 Test hexadecimal revision
1524 Test hexadecimal revision
1524 $ log 'id(2)'
1525 $ log 'id(2)'
1525 abort: 00changelog.i@2: ambiguous identifier!
1526 abort: 00changelog.i@2: ambiguous identifier!
1526 [255]
1527 [255]
1527 $ log 'id(23268)'
1528 $ log 'id(23268)'
1528 4
1529 4
1529 $ log 'id(2785f51eece)'
1530 $ log 'id(2785f51eece)'
1530 0
1531 0
1531 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c)'
1532 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c)'
1532 8
1533 8
1533 $ log 'id(d5d0dcbdc4a)'
1534 $ log 'id(d5d0dcbdc4a)'
1534 $ log 'id(d5d0dcbdc4w)'
1535 $ log 'id(d5d0dcbdc4w)'
1535 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532d)'
1536 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532d)'
1536 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532q)'
1537 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532q)'
1537 $ log 'id(1.0)'
1538 $ log 'id(1.0)'
1538 $ log 'id(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)'
1539 $ log 'id(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)'
1539
1540
1540 Test null revision
1541 Test null revision
1541 $ log '(null)'
1542 $ log '(null)'
1542 -1
1543 -1
1543 $ log '(null:0)'
1544 $ log '(null:0)'
1544 -1
1545 -1
1545 0
1546 0
1546 $ log '(0:null)'
1547 $ log '(0:null)'
1547 0
1548 0
1548 -1
1549 -1
1549 $ log 'null::0'
1550 $ log 'null::0'
1550 -1
1551 -1
1551 0
1552 0
1552 $ log 'null:tip - 0:'
1553 $ log 'null:tip - 0:'
1553 -1
1554 -1
1554 $ log 'null: and null::' | head -1
1555 $ log 'null: and null::' | head -1
1555 -1
1556 -1
1556 $ log 'null: or 0:' | head -2
1557 $ log 'null: or 0:' | head -2
1557 -1
1558 -1
1558 0
1559 0
1559 $ log 'ancestors(null)'
1560 $ log 'ancestors(null)'
1560 -1
1561 -1
1561 $ log 'reverse(null:)' | tail -2
1562 $ log 'reverse(null:)' | tail -2
1562 0
1563 0
1563 -1
1564 -1
1564 $ log 'first(null:)'
1565 $ log 'first(null:)'
1565 -1
1566 -1
1566 $ log 'min(null:)'
1567 $ log 'min(null:)'
1567 BROKEN: should be '-1'
1568 BROKEN: should be '-1'
1568 $ log 'tip:null and all()' | tail -2
1569 $ log 'tip:null and all()' | tail -2
1569 1
1570 1
1570 0
1571 0
1571
1572
1572 Test working-directory revision
1573 Test working-directory revision
1573 $ hg debugrevspec 'wdir()'
1574 $ hg debugrevspec 'wdir()'
1574 2147483647
1575 2147483647
1575 $ hg debugrevspec 'wdir()^'
1576 $ hg debugrevspec 'wdir()^'
1576 9
1577 9
1577 $ hg up 7
1578 $ hg up 7
1578 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1579 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1579 $ hg debugrevspec 'wdir()^'
1580 $ hg debugrevspec 'wdir()^'
1580 7
1581 7
1581 $ hg debugrevspec 'wdir()^0'
1582 $ hg debugrevspec 'wdir()^0'
1582 2147483647
1583 2147483647
1583 $ hg debugrevspec 'wdir()~3'
1584 $ hg debugrevspec 'wdir()~3'
1584 5
1585 5
1585 $ hg debugrevspec 'ancestors(wdir())'
1586 $ hg debugrevspec 'ancestors(wdir())'
1586 0
1587 0
1587 1
1588 1
1588 2
1589 2
1589 3
1590 3
1590 4
1591 4
1591 5
1592 5
1592 6
1593 6
1593 7
1594 7
1594 2147483647
1595 2147483647
1595 $ hg debugrevspec 'wdir()~0'
1596 $ hg debugrevspec 'wdir()~0'
1596 2147483647
1597 2147483647
1597 $ hg debugrevspec 'p1(wdir())'
1598 $ hg debugrevspec 'p1(wdir())'
1598 7
1599 7
1599 $ hg debugrevspec 'p2(wdir())'
1600 $ hg debugrevspec 'p2(wdir())'
1600 $ hg debugrevspec 'parents(wdir())'
1601 $ hg debugrevspec 'parents(wdir())'
1601 7
1602 7
1602 $ hg debugrevspec 'wdir()^1'
1603 $ hg debugrevspec 'wdir()^1'
1603 7
1604 7
1604 $ hg debugrevspec 'wdir()^2'
1605 $ hg debugrevspec 'wdir()^2'
1605 $ hg debugrevspec 'wdir()^3'
1606 $ hg debugrevspec 'wdir()^3'
1606 hg: parse error: ^ expects a number 0, 1, or 2
1607 hg: parse error: ^ expects a number 0, 1, or 2
1607 [255]
1608 [255]
1608 For tests consistency
1609 For tests consistency
1609 $ hg up 9
1610 $ hg up 9
1610 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1611 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1611 $ hg debugrevspec 'tip or wdir()'
1612 $ hg debugrevspec 'tip or wdir()'
1612 9
1613 9
1613 2147483647
1614 2147483647
1614 $ hg debugrevspec '0:tip and wdir()'
1615 $ hg debugrevspec '0:tip and wdir()'
1615 $ log '0:wdir()' | tail -3
1616 $ log '0:wdir()' | tail -3
1616 8
1617 8
1617 9
1618 9
1618 2147483647
1619 2147483647
1619 $ log 'wdir():0' | head -3
1620 $ log 'wdir():0' | head -3
1620 2147483647
1621 2147483647
1621 9
1622 9
1622 8
1623 8
1623 $ log 'wdir():wdir()'
1624 $ log 'wdir():wdir()'
1624 2147483647
1625 2147483647
1625 $ log '(all() + wdir()) & min(. + wdir())'
1626 $ log '(all() + wdir()) & min(. + wdir())'
1626 9
1627 9
1627 $ log '(all() + wdir()) & max(. + wdir())'
1628 $ log '(all() + wdir()) & max(. + wdir())'
1628 2147483647
1629 2147483647
1629 $ log 'first(wdir() + .)'
1630 $ log 'first(wdir() + .)'
1630 2147483647
1631 2147483647
1631 $ log 'last(. + wdir())'
1632 $ log 'last(. + wdir())'
1632 2147483647
1633 2147483647
1633
1634
1634 Test working-directory integer revision and node id
1635 Test working-directory integer revision and node id
1635 (BUG: '0:wdir()' is still needed to populate wdir revision)
1636 (BUG: '0:wdir()' is still needed to populate wdir revision)
1636
1637
1637 $ hg debugrevspec '0:wdir() & 2147483647'
1638 $ hg debugrevspec '0:wdir() & 2147483647'
1638 2147483647
1639 2147483647
1639 $ hg debugrevspec '0:wdir() & rev(2147483647)'
1640 $ hg debugrevspec '0:wdir() & rev(2147483647)'
1640 2147483647
1641 2147483647
1641 $ hg debugrevspec '0:wdir() & ffffffffffffffffffffffffffffffffffffffff'
1642 $ hg debugrevspec '0:wdir() & ffffffffffffffffffffffffffffffffffffffff'
1642 2147483647
1643 2147483647
1643 $ hg debugrevspec '0:wdir() & ffffffffffff'
1644 $ hg debugrevspec '0:wdir() & ffffffffffff'
1644 2147483647
1645 2147483647
1645 $ hg debugrevspec '0:wdir() & id(ffffffffffffffffffffffffffffffffffffffff)'
1646 $ hg debugrevspec '0:wdir() & id(ffffffffffffffffffffffffffffffffffffffff)'
1646 2147483647
1647 2147483647
1647 $ hg debugrevspec '0:wdir() & id(ffffffffffff)'
1648 $ hg debugrevspec '0:wdir() & id(ffffffffffff)'
1648 2147483647
1649 2147483647
1649
1650
1650 $ cd ..
1651 $ cd ..
1651
1652
1652 Test short 'ff...' hash collision
1653 Test short 'ff...' hash collision
1653 (BUG: '0:wdir()' is still needed to populate wdir revision)
1654 (BUG: '0:wdir()' is still needed to populate wdir revision)
1654
1655
1655 $ hg init wdir-hashcollision
1656 $ hg init wdir-hashcollision
1656 $ cd wdir-hashcollision
1657 $ cd wdir-hashcollision
1657 $ cat <<EOF >> .hg/hgrc
1658 $ cat <<EOF >> .hg/hgrc
1658 > [experimental]
1659 > [experimental]
1659 > evolution = createmarkers
1660 > evolution = createmarkers
1660 > EOF
1661 > EOF
1661 $ echo 0 > a
1662 $ echo 0 > a
1662 $ hg ci -qAm 0
1663 $ hg ci -qAm 0
1663 $ for i in 2463 2961 6726 78127; do
1664 $ for i in 2463 2961 6726 78127; do
1664 > hg up -q 0
1665 > hg up -q 0
1665 > echo $i > a
1666 > echo $i > a
1666 > hg ci -qm $i
1667 > hg ci -qm $i
1667 > done
1668 > done
1668 $ hg up -q null
1669 $ hg up -q null
1669 $ hg log -r '0:wdir()' -T '{rev}:{node} {shortest(node, 3)}\n'
1670 $ hg log -r '0:wdir()' -T '{rev}:{node} {shortest(node, 3)}\n'
1670 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a b4e
1671 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a b4e
1671 1:fffbae3886c8fbb2114296380d276fd37715d571 fffba
1672 1:fffbae3886c8fbb2114296380d276fd37715d571 fffba
1672 2:fffb6093b00943f91034b9bdad069402c834e572 fffb6
1673 2:fffb6093b00943f91034b9bdad069402c834e572 fffb6
1673 3:fff48a9b9de34a4d64120c29548214c67980ade3 fff4
1674 3:fff48a9b9de34a4d64120c29548214c67980ade3 fff4
1674 4:ffff85cff0ff78504fcdc3c0bc10de0c65379249 ffff8
1675 4:ffff85cff0ff78504fcdc3c0bc10de0c65379249 ffff8
1675 2147483647:ffffffffffffffffffffffffffffffffffffffff fffff
1676 2147483647:ffffffffffffffffffffffffffffffffffffffff fffff
1676 $ hg debugobsolete fffbae3886c8fbb2114296380d276fd37715d571
1677 $ hg debugobsolete fffbae3886c8fbb2114296380d276fd37715d571
1677
1678
1678 $ hg debugrevspec '0:wdir() & fff'
1679 $ hg debugrevspec '0:wdir() & fff'
1679 abort: 00changelog.i@fff: ambiguous identifier!
1680 abort: 00changelog.i@fff: ambiguous identifier!
1680 [255]
1681 [255]
1681 $ hg debugrevspec '0:wdir() & ffff'
1682 $ hg debugrevspec '0:wdir() & ffff'
1682 abort: 00changelog.i@ffff: ambiguous identifier!
1683 abort: 00changelog.i@ffff: ambiguous identifier!
1683 [255]
1684 [255]
1684 $ hg debugrevspec '0:wdir() & fffb'
1685 $ hg debugrevspec '0:wdir() & fffb'
1685 abort: 00changelog.i@fffb: ambiguous identifier!
1686 abort: 00changelog.i@fffb: ambiguous identifier!
1686 [255]
1687 [255]
1687 BROKEN should be '2' (node lookup uses unfiltered repo since dc25ed84bee8)
1688 BROKEN should be '2' (node lookup uses unfiltered repo since dc25ed84bee8)
1688 $ hg debugrevspec '0:wdir() & id(fffb)'
1689 $ hg debugrevspec '0:wdir() & id(fffb)'
1689 2
1690 2
1690 $ hg debugrevspec '0:wdir() & ffff8'
1691 $ hg debugrevspec '0:wdir() & ffff8'
1691 4
1692 4
1692 $ hg debugrevspec '0:wdir() & fffff'
1693 $ hg debugrevspec '0:wdir() & fffff'
1693 2147483647
1694 2147483647
1694
1695
1695 $ cd ..
1696 $ cd ..
1696
1697
1697 Test branch() with wdir()
1698 Test branch() with wdir()
1698
1699
1699 $ cd repo
1700 $ cd repo
1700
1701
1701 $ log '0:wdir() & branch("literal:Γ©")'
1702 $ log '0:wdir() & branch("literal:Γ©")'
1702 8
1703 8
1703 9
1704 9
1704 2147483647
1705 2147483647
1705 $ log '0:wdir() & branch("re:Γ©")'
1706 $ log '0:wdir() & branch("re:Γ©")'
1706 8
1707 8
1707 9
1708 9
1708 2147483647
1709 2147483647
1709 $ log '0:wdir() & branch("re:^a")'
1710 $ log '0:wdir() & branch("re:^a")'
1710 0
1711 0
1711 2
1712 2
1712 $ log '0:wdir() & branch(8)'
1713 $ log '0:wdir() & branch(8)'
1713 8
1714 8
1714 9
1715 9
1715 2147483647
1716 2147483647
1716
1717
1717 branch(wdir()) returns all revisions belonging to the working branch. The wdir
1718 branch(wdir()) returns all revisions belonging to the working branch. The wdir
1718 itself isn't returned unless it is explicitly populated.
1719 itself isn't returned unless it is explicitly populated.
1719
1720
1720 $ log 'branch(wdir())'
1721 $ log 'branch(wdir())'
1721 8
1722 8
1722 9
1723 9
1723 $ log '0:wdir() & branch(wdir())'
1724 $ log '0:wdir() & branch(wdir())'
1724 8
1725 8
1725 9
1726 9
1726 2147483647
1727 2147483647
1727
1728
1728 $ log 'outgoing()'
1729 $ log 'outgoing()'
1729 8
1730 8
1730 9
1731 9
1731 $ log 'outgoing("../remote1")'
1732 $ log 'outgoing("../remote1")'
1732 8
1733 8
1733 9
1734 9
1734 $ log 'outgoing("../remote2")'
1735 $ log 'outgoing("../remote2")'
1735 3
1736 3
1736 5
1737 5
1737 6
1738 6
1738 7
1739 7
1739 9
1740 9
1740 $ log 'p1(merge())'
1741 $ log 'p1(merge())'
1741 5
1742 5
1742 $ log 'p2(merge())'
1743 $ log 'p2(merge())'
1743 4
1744 4
1744 $ log 'parents(merge())'
1745 $ log 'parents(merge())'
1745 4
1746 4
1746 5
1747 5
1747 $ log 'p1(branchpoint())'
1748 $ log 'p1(branchpoint())'
1748 0
1749 0
1749 2
1750 2
1750 $ log 'p2(branchpoint())'
1751 $ log 'p2(branchpoint())'
1751 $ log 'parents(branchpoint())'
1752 $ log 'parents(branchpoint())'
1752 0
1753 0
1753 2
1754 2
1754 $ log 'removes(a)'
1755 $ log 'removes(a)'
1755 2
1756 2
1756 6
1757 6
1757 $ log 'roots(all())'
1758 $ log 'roots(all())'
1758 0
1759 0
1759 $ log 'reverse(2 or 3 or 4 or 5)'
1760 $ log 'reverse(2 or 3 or 4 or 5)'
1760 5
1761 5
1761 4
1762 4
1762 3
1763 3
1763 2
1764 2
1764 $ log 'reverse(all())'
1765 $ log 'reverse(all())'
1765 9
1766 9
1766 8
1767 8
1767 7
1768 7
1768 6
1769 6
1769 5
1770 5
1770 4
1771 4
1771 3
1772 3
1772 2
1773 2
1773 1
1774 1
1774 0
1775 0
1775 $ log 'reverse(all()) & filelog(b)'
1776 $ log 'reverse(all()) & filelog(b)'
1776 4
1777 4
1777 1
1778 1
1778 $ log 'rev(5)'
1779 $ log 'rev(5)'
1779 5
1780 5
1780 $ log 'sort(limit(reverse(all()), 3))'
1781 $ log 'sort(limit(reverse(all()), 3))'
1781 7
1782 7
1782 8
1783 8
1783 9
1784 9
1784 $ log 'sort(2 or 3 or 4 or 5, date)'
1785 $ log 'sort(2 or 3 or 4 or 5, date)'
1785 2
1786 2
1786 3
1787 3
1787 5
1788 5
1788 4
1789 4
1789 $ log 'tagged()'
1790 $ log 'tagged()'
1790 6
1791 6
1791 $ log 'tag()'
1792 $ log 'tag()'
1792 6
1793 6
1793 $ log 'tag(1.0)'
1794 $ log 'tag(1.0)'
1794 6
1795 6
1795 $ log 'tag(tip)'
1796 $ log 'tag(tip)'
1796 9
1797 9
1797
1798
1798 Test order of revisions in compound expression
1799 Test order of revisions in compound expression
1799 ----------------------------------------------
1800 ----------------------------------------------
1800
1801
1801 The general rule is that only the outermost (= leftmost) predicate can
1802 The general rule is that only the outermost (= leftmost) predicate can
1802 enforce its ordering requirement. The other predicates should take the
1803 enforce its ordering requirement. The other predicates should take the
1803 ordering defined by it.
1804 ordering defined by it.
1804
1805
1805 'A & B' should follow the order of 'A':
1806 'A & B' should follow the order of 'A':
1806
1807
1807 $ log '2:0 & 0::2'
1808 $ log '2:0 & 0::2'
1808 2
1809 2
1809 1
1810 1
1810 0
1811 0
1811
1812
1812 'head()' combines sets in right order:
1813 'head()' combines sets in right order:
1813
1814
1814 $ log '2:0 & head()'
1815 $ log '2:0 & head()'
1815 2
1816 2
1816 1
1817 1
1817 0
1818 0
1818
1819
1819 'x:y' takes ordering parameter into account:
1820 'x:y' takes ordering parameter into account:
1820
1821
1821 $ try -p optimized '3:0 & 0:3 & not 2:1'
1822 $ try -p optimized '3:0 & 0:3 & not 2:1'
1822 * optimized:
1823 * optimized:
1823 (difference
1824 (difference
1824 (and
1825 (and
1825 (range
1826 (range
1826 ('symbol', '3')
1827 ('symbol', '3')
1827 ('symbol', '0')
1828 ('symbol', '0')
1828 define)
1829 define)
1829 (range
1830 (range
1830 ('symbol', '0')
1831 ('symbol', '0')
1831 ('symbol', '3')
1832 ('symbol', '3')
1832 follow)
1833 follow)
1833 define)
1834 define)
1834 (range
1835 (range
1835 ('symbol', '2')
1836 ('symbol', '2')
1836 ('symbol', '1')
1837 ('symbol', '1')
1837 any)
1838 any)
1838 define)
1839 define)
1839 * set:
1840 * set:
1840 <filteredset
1841 <filteredset
1841 <filteredset
1842 <filteredset
1842 <spanset- 0:4>,
1843 <spanset- 0:4>,
1843 <spanset+ 0:4>>,
1844 <spanset+ 0:4>>,
1844 <not
1845 <not
1845 <spanset+ 1:3>>>
1846 <spanset+ 1:3>>>
1846 3
1847 3
1847 0
1848 0
1848
1849
1849 'a + b', which is optimized to '_list(a b)', should take the ordering of
1850 'a + b', which is optimized to '_list(a b)', should take the ordering of
1850 the left expression:
1851 the left expression:
1851
1852
1852 $ try --optimize '2:0 & (0 + 1 + 2)'
1853 $ try --optimize '2:0 & (0 + 1 + 2)'
1853 (and
1854 (and
1854 (range
1855 (range
1855 ('symbol', '2')
1856 ('symbol', '2')
1856 ('symbol', '0'))
1857 ('symbol', '0'))
1857 (group
1858 (group
1858 (or
1859 (or
1859 (list
1860 (list
1860 ('symbol', '0')
1861 ('symbol', '0')
1861 ('symbol', '1')
1862 ('symbol', '1')
1862 ('symbol', '2')))))
1863 ('symbol', '2')))))
1863 * optimized:
1864 * optimized:
1864 (and
1865 (and
1865 (range
1866 (range
1866 ('symbol', '2')
1867 ('symbol', '2')
1867 ('symbol', '0')
1868 ('symbol', '0')
1868 define)
1869 define)
1869 (func
1870 (func
1870 ('symbol', '_list')
1871 ('symbol', '_list')
1871 ('string', '0\x001\x002')
1872 ('string', '0\x001\x002')
1872 follow)
1873 follow)
1873 define)
1874 define)
1874 * set:
1875 * set:
1875 <filteredset
1876 <filteredset
1876 <spanset- 0:3>,
1877 <spanset- 0:3>,
1877 <baseset [0, 1, 2]>>
1878 <baseset [0, 1, 2]>>
1878 2
1879 2
1879 1
1880 1
1880 0
1881 0
1881
1882
1882 'A + B' should take the ordering of the left expression:
1883 'A + B' should take the ordering of the left expression:
1883
1884
1884 $ try --optimize '2:0 & (0:1 + 2)'
1885 $ try --optimize '2:0 & (0:1 + 2)'
1885 (and
1886 (and
1886 (range
1887 (range
1887 ('symbol', '2')
1888 ('symbol', '2')
1888 ('symbol', '0'))
1889 ('symbol', '0'))
1889 (group
1890 (group
1890 (or
1891 (or
1891 (list
1892 (list
1892 (range
1893 (range
1893 ('symbol', '0')
1894 ('symbol', '0')
1894 ('symbol', '1'))
1895 ('symbol', '1'))
1895 ('symbol', '2')))))
1896 ('symbol', '2')))))
1896 * optimized:
1897 * optimized:
1897 (and
1898 (and
1898 (range
1899 (range
1899 ('symbol', '2')
1900 ('symbol', '2')
1900 ('symbol', '0')
1901 ('symbol', '0')
1901 define)
1902 define)
1902 (or
1903 (or
1903 (list
1904 (list
1904 ('symbol', '2')
1905 ('symbol', '2')
1905 (range
1906 (range
1906 ('symbol', '0')
1907 ('symbol', '0')
1907 ('symbol', '1')
1908 ('symbol', '1')
1908 follow))
1909 follow))
1909 follow)
1910 follow)
1910 define)
1911 define)
1911 * set:
1912 * set:
1912 <filteredset
1913 <filteredset
1913 <spanset- 0:3>,
1914 <spanset- 0:3>,
1914 <addset
1915 <addset
1915 <baseset [2]>,
1916 <baseset [2]>,
1916 <spanset+ 0:2>>>
1917 <spanset+ 0:2>>>
1917 2
1918 2
1918 1
1919 1
1919 0
1920 0
1920
1921
1921 '_intlist(a b)' should behave like 'a + b':
1922 '_intlist(a b)' should behave like 'a + b':
1922
1923
1923 $ trylist --optimize '2:0 & %ld' 0 1 2
1924 $ trylist --optimize '2:0 & %ld' 0 1 2
1924 (and
1925 (and
1925 (range
1926 (range
1926 ('symbol', '2')
1927 ('symbol', '2')
1927 ('symbol', '0'))
1928 ('symbol', '0'))
1928 (func
1929 (func
1929 ('symbol', '_intlist')
1930 ('symbol', '_intlist')
1930 ('string', '0\x001\x002')))
1931 ('string', '0\x001\x002')))
1931 * optimized:
1932 * optimized:
1932 (and
1933 (and
1933 (func
1934 (func
1934 ('symbol', '_intlist')
1935 ('symbol', '_intlist')
1935 ('string', '0\x001\x002')
1936 ('string', '0\x001\x002')
1936 follow)
1937 follow)
1937 (range
1938 (range
1938 ('symbol', '2')
1939 ('symbol', '2')
1939 ('symbol', '0')
1940 ('symbol', '0')
1940 define)
1941 define)
1941 define)
1942 define)
1942 * set:
1943 * set:
1943 <filteredset
1944 <filteredset
1944 <spanset- 0:3>,
1945 <spanset- 0:3>,
1945 <baseset+ [0, 1, 2]>>
1946 <baseset+ [0, 1, 2]>>
1946 2
1947 2
1947 1
1948 1
1948 0
1949 0
1949
1950
1950 $ trylist --optimize '%ld & 2:0' 0 2 1
1951 $ trylist --optimize '%ld & 2:0' 0 2 1
1951 (and
1952 (and
1952 (func
1953 (func
1953 ('symbol', '_intlist')
1954 ('symbol', '_intlist')
1954 ('string', '0\x002\x001'))
1955 ('string', '0\x002\x001'))
1955 (range
1956 (range
1956 ('symbol', '2')
1957 ('symbol', '2')
1957 ('symbol', '0')))
1958 ('symbol', '0')))
1958 * optimized:
1959 * optimized:
1959 (and
1960 (and
1960 (func
1961 (func
1961 ('symbol', '_intlist')
1962 ('symbol', '_intlist')
1962 ('string', '0\x002\x001')
1963 ('string', '0\x002\x001')
1963 define)
1964 define)
1964 (range
1965 (range
1965 ('symbol', '2')
1966 ('symbol', '2')
1966 ('symbol', '0')
1967 ('symbol', '0')
1967 follow)
1968 follow)
1968 define)
1969 define)
1969 * set:
1970 * set:
1970 <filteredset
1971 <filteredset
1971 <baseset [0, 2, 1]>,
1972 <baseset [0, 2, 1]>,
1972 <spanset- 0:3>>
1973 <spanset- 0:3>>
1973 0
1974 0
1974 2
1975 2
1975 1
1976 1
1976
1977
1977 '_hexlist(a b)' should behave like 'a + b':
1978 '_hexlist(a b)' should behave like 'a + b':
1978
1979
1979 $ trylist --optimize --bin '2:0 & %ln' `hg log -T '{node} ' -r0:2`
1980 $ trylist --optimize --bin '2:0 & %ln' `hg log -T '{node} ' -r0:2`
1980 (and
1981 (and
1981 (range
1982 (range
1982 ('symbol', '2')
1983 ('symbol', '2')
1983 ('symbol', '0'))
1984 ('symbol', '0'))
1984 (func
1985 (func
1985 ('symbol', '_hexlist')
1986 ('symbol', '_hexlist')
1986 ('string', '*'))) (glob)
1987 ('string', '*'))) (glob)
1987 * optimized:
1988 * optimized:
1988 (and
1989 (and
1989 (range
1990 (range
1990 ('symbol', '2')
1991 ('symbol', '2')
1991 ('symbol', '0')
1992 ('symbol', '0')
1992 define)
1993 define)
1993 (func
1994 (func
1994 ('symbol', '_hexlist')
1995 ('symbol', '_hexlist')
1995 ('string', '*') (glob)
1996 ('string', '*') (glob)
1996 follow)
1997 follow)
1997 define)
1998 define)
1998 * set:
1999 * set:
1999 <filteredset
2000 <filteredset
2000 <spanset- 0:3>,
2001 <spanset- 0:3>,
2001 <baseset [0, 1, 2]>>
2002 <baseset [0, 1, 2]>>
2002 2
2003 2
2003 1
2004 1
2004 0
2005 0
2005
2006
2006 $ trylist --optimize --bin '%ln & 2:0' `hg log -T '{node} ' -r0+2+1`
2007 $ trylist --optimize --bin '%ln & 2:0' `hg log -T '{node} ' -r0+2+1`
2007 (and
2008 (and
2008 (func
2009 (func
2009 ('symbol', '_hexlist')
2010 ('symbol', '_hexlist')
2010 ('string', '*')) (glob)
2011 ('string', '*')) (glob)
2011 (range
2012 (range
2012 ('symbol', '2')
2013 ('symbol', '2')
2013 ('symbol', '0')))
2014 ('symbol', '0')))
2014 * optimized:
2015 * optimized:
2015 (and
2016 (and
2016 (range
2017 (range
2017 ('symbol', '2')
2018 ('symbol', '2')
2018 ('symbol', '0')
2019 ('symbol', '0')
2019 follow)
2020 follow)
2020 (func
2021 (func
2021 ('symbol', '_hexlist')
2022 ('symbol', '_hexlist')
2022 ('string', '*') (glob)
2023 ('string', '*') (glob)
2023 define)
2024 define)
2024 define)
2025 define)
2025 * set:
2026 * set:
2026 <baseset [0, 2, 1]>
2027 <baseset [0, 2, 1]>
2027 0
2028 0
2028 2
2029 2
2029 1
2030 1
2030
2031
2031 '_list' should not go through the slow follow-order path if order doesn't
2032 '_list' should not go through the slow follow-order path if order doesn't
2032 matter:
2033 matter:
2033
2034
2034 $ try -p optimized '2:0 & not (0 + 1)'
2035 $ try -p optimized '2:0 & not (0 + 1)'
2035 * optimized:
2036 * optimized:
2036 (difference
2037 (difference
2037 (range
2038 (range
2038 ('symbol', '2')
2039 ('symbol', '2')
2039 ('symbol', '0')
2040 ('symbol', '0')
2040 define)
2041 define)
2041 (func
2042 (func
2042 ('symbol', '_list')
2043 ('symbol', '_list')
2043 ('string', '0\x001')
2044 ('string', '0\x001')
2044 any)
2045 any)
2045 define)
2046 define)
2046 * set:
2047 * set:
2047 <filteredset
2048 <filteredset
2048 <spanset- 0:3>,
2049 <spanset- 0:3>,
2049 <not
2050 <not
2050 <baseset [0, 1]>>>
2051 <baseset [0, 1]>>>
2051 2
2052 2
2052
2053
2053 $ try -p optimized '2:0 & not (0:2 & (0 + 1))'
2054 $ try -p optimized '2:0 & not (0:2 & (0 + 1))'
2054 * optimized:
2055 * optimized:
2055 (difference
2056 (difference
2056 (range
2057 (range
2057 ('symbol', '2')
2058 ('symbol', '2')
2058 ('symbol', '0')
2059 ('symbol', '0')
2059 define)
2060 define)
2060 (and
2061 (and
2061 (range
2062 (range
2062 ('symbol', '0')
2063 ('symbol', '0')
2063 ('symbol', '2')
2064 ('symbol', '2')
2064 any)
2065 any)
2065 (func
2066 (func
2066 ('symbol', '_list')
2067 ('symbol', '_list')
2067 ('string', '0\x001')
2068 ('string', '0\x001')
2068 any)
2069 any)
2069 any)
2070 any)
2070 define)
2071 define)
2071 * set:
2072 * set:
2072 <filteredset
2073 <filteredset
2073 <spanset- 0:3>,
2074 <spanset- 0:3>,
2074 <not
2075 <not
2075 <baseset [0, 1]>>>
2076 <baseset [0, 1]>>>
2076 2
2077 2
2077
2078
2078 because 'present()' does nothing other than suppressing an error, the
2079 because 'present()' does nothing other than suppressing an error, the
2079 ordering requirement should be forwarded to the nested expression
2080 ordering requirement should be forwarded to the nested expression
2080
2081
2081 $ try -p optimized 'present(2 + 0 + 1)'
2082 $ try -p optimized 'present(2 + 0 + 1)'
2082 * optimized:
2083 * optimized:
2083 (func
2084 (func
2084 ('symbol', 'present')
2085 ('symbol', 'present')
2085 (func
2086 (func
2086 ('symbol', '_list')
2087 ('symbol', '_list')
2087 ('string', '2\x000\x001')
2088 ('string', '2\x000\x001')
2088 define)
2089 define)
2089 define)
2090 define)
2090 * set:
2091 * set:
2091 <baseset [2, 0, 1]>
2092 <baseset [2, 0, 1]>
2092 2
2093 2
2093 0
2094 0
2094 1
2095 1
2095
2096
2096 $ try --optimize '2:0 & present(0 + 1 + 2)'
2097 $ try --optimize '2:0 & present(0 + 1 + 2)'
2097 (and
2098 (and
2098 (range
2099 (range
2099 ('symbol', '2')
2100 ('symbol', '2')
2100 ('symbol', '0'))
2101 ('symbol', '0'))
2101 (func
2102 (func
2102 ('symbol', 'present')
2103 ('symbol', 'present')
2103 (or
2104 (or
2104 (list
2105 (list
2105 ('symbol', '0')
2106 ('symbol', '0')
2106 ('symbol', '1')
2107 ('symbol', '1')
2107 ('symbol', '2')))))
2108 ('symbol', '2')))))
2108 * optimized:
2109 * optimized:
2109 (and
2110 (and
2110 (range
2111 (range
2111 ('symbol', '2')
2112 ('symbol', '2')
2112 ('symbol', '0')
2113 ('symbol', '0')
2113 define)
2114 define)
2114 (func
2115 (func
2115 ('symbol', 'present')
2116 ('symbol', 'present')
2116 (func
2117 (func
2117 ('symbol', '_list')
2118 ('symbol', '_list')
2118 ('string', '0\x001\x002')
2119 ('string', '0\x001\x002')
2119 follow)
2120 follow)
2120 follow)
2121 follow)
2121 define)
2122 define)
2122 * set:
2123 * set:
2123 <filteredset
2124 <filteredset
2124 <spanset- 0:3>,
2125 <spanset- 0:3>,
2125 <baseset [0, 1, 2]>>
2126 <baseset [0, 1, 2]>>
2126 2
2127 2
2127 1
2128 1
2128 0
2129 0
2129
2130
2130 'reverse()' should take effect only if it is the outermost expression:
2131 'reverse()' should take effect only if it is the outermost expression:
2131
2132
2132 $ try --optimize '0:2 & reverse(all())'
2133 $ try --optimize '0:2 & reverse(all())'
2133 (and
2134 (and
2134 (range
2135 (range
2135 ('symbol', '0')
2136 ('symbol', '0')
2136 ('symbol', '2'))
2137 ('symbol', '2'))
2137 (func
2138 (func
2138 ('symbol', 'reverse')
2139 ('symbol', 'reverse')
2139 (func
2140 (func
2140 ('symbol', 'all')
2141 ('symbol', 'all')
2141 None)))
2142 None)))
2142 * optimized:
2143 * optimized:
2143 (and
2144 (and
2144 (range
2145 (range
2145 ('symbol', '0')
2146 ('symbol', '0')
2146 ('symbol', '2')
2147 ('symbol', '2')
2147 define)
2148 define)
2148 (func
2149 (func
2149 ('symbol', 'reverse')
2150 ('symbol', 'reverse')
2150 (func
2151 (func
2151 ('symbol', 'all')
2152 ('symbol', 'all')
2152 None
2153 None
2153 define)
2154 define)
2154 follow)
2155 follow)
2155 define)
2156 define)
2156 * set:
2157 * set:
2157 <filteredset
2158 <filteredset
2158 <spanset+ 0:3>,
2159 <spanset+ 0:3>,
2159 <spanset+ 0:10>>
2160 <spanset+ 0:10>>
2160 0
2161 0
2161 1
2162 1
2162 2
2163 2
2163
2164
2164 'sort()' should take effect only if it is the outermost expression:
2165 'sort()' should take effect only if it is the outermost expression:
2165
2166
2166 $ try --optimize '0:2 & sort(all(), -rev)'
2167 $ try --optimize '0:2 & sort(all(), -rev)'
2167 (and
2168 (and
2168 (range
2169 (range
2169 ('symbol', '0')
2170 ('symbol', '0')
2170 ('symbol', '2'))
2171 ('symbol', '2'))
2171 (func
2172 (func
2172 ('symbol', 'sort')
2173 ('symbol', 'sort')
2173 (list
2174 (list
2174 (func
2175 (func
2175 ('symbol', 'all')
2176 ('symbol', 'all')
2176 None)
2177 None)
2177 (negate
2178 (negate
2178 ('symbol', 'rev')))))
2179 ('symbol', 'rev')))))
2179 * optimized:
2180 * optimized:
2180 (and
2181 (and
2181 (range
2182 (range
2182 ('symbol', '0')
2183 ('symbol', '0')
2183 ('symbol', '2')
2184 ('symbol', '2')
2184 define)
2185 define)
2185 (func
2186 (func
2186 ('symbol', 'sort')
2187 ('symbol', 'sort')
2187 (list
2188 (list
2188 (func
2189 (func
2189 ('symbol', 'all')
2190 ('symbol', 'all')
2190 None
2191 None
2191 define)
2192 define)
2192 ('string', '-rev'))
2193 ('string', '-rev'))
2193 follow)
2194 follow)
2194 define)
2195 define)
2195 * set:
2196 * set:
2196 <filteredset
2197 <filteredset
2197 <spanset+ 0:3>,
2198 <spanset+ 0:3>,
2198 <spanset+ 0:10>>
2199 <spanset+ 0:10>>
2199 0
2200 0
2200 1
2201 1
2201 2
2202 2
2202
2203
2203 invalid argument passed to noop sort():
2204 invalid argument passed to noop sort():
2204
2205
2205 $ log '0:2 & sort()'
2206 $ log '0:2 & sort()'
2206 hg: parse error: sort requires one or two arguments
2207 hg: parse error: sort requires one or two arguments
2207 [255]
2208 [255]
2208 $ log '0:2 & sort(all(), -invalid)'
2209 $ log '0:2 & sort(all(), -invalid)'
2209 hg: parse error: unknown sort key '-invalid'
2210 hg: parse error: unknown sort key '-invalid'
2210 [255]
2211 [255]
2211
2212
2212 for 'A & f(B)', 'B' should not be affected by the order of 'A':
2213 for 'A & f(B)', 'B' should not be affected by the order of 'A':
2213
2214
2214 $ try --optimize '2:0 & first(1 + 0 + 2)'
2215 $ try --optimize '2:0 & first(1 + 0 + 2)'
2215 (and
2216 (and
2216 (range
2217 (range
2217 ('symbol', '2')
2218 ('symbol', '2')
2218 ('symbol', '0'))
2219 ('symbol', '0'))
2219 (func
2220 (func
2220 ('symbol', 'first')
2221 ('symbol', 'first')
2221 (or
2222 (or
2222 (list
2223 (list
2223 ('symbol', '1')
2224 ('symbol', '1')
2224 ('symbol', '0')
2225 ('symbol', '0')
2225 ('symbol', '2')))))
2226 ('symbol', '2')))))
2226 * optimized:
2227 * optimized:
2227 (and
2228 (and
2228 (range
2229 (range
2229 ('symbol', '2')
2230 ('symbol', '2')
2230 ('symbol', '0')
2231 ('symbol', '0')
2231 define)
2232 define)
2232 (func
2233 (func
2233 ('symbol', 'first')
2234 ('symbol', 'first')
2234 (func
2235 (func
2235 ('symbol', '_list')
2236 ('symbol', '_list')
2236 ('string', '1\x000\x002')
2237 ('string', '1\x000\x002')
2237 define)
2238 define)
2238 follow)
2239 follow)
2239 define)
2240 define)
2240 * set:
2241 * set:
2241 <filteredset
2242 <filteredset
2242 <baseset [1]>,
2243 <baseset [1]>,
2243 <spanset- 0:3>>
2244 <spanset- 0:3>>
2244 1
2245 1
2245
2246
2246 $ try --optimize '2:0 & not last(0 + 2 + 1)'
2247 $ try --optimize '2:0 & not last(0 + 2 + 1)'
2247 (and
2248 (and
2248 (range
2249 (range
2249 ('symbol', '2')
2250 ('symbol', '2')
2250 ('symbol', '0'))
2251 ('symbol', '0'))
2251 (not
2252 (not
2252 (func
2253 (func
2253 ('symbol', 'last')
2254 ('symbol', 'last')
2254 (or
2255 (or
2255 (list
2256 (list
2256 ('symbol', '0')
2257 ('symbol', '0')
2257 ('symbol', '2')
2258 ('symbol', '2')
2258 ('symbol', '1'))))))
2259 ('symbol', '1'))))))
2259 * optimized:
2260 * optimized:
2260 (difference
2261 (difference
2261 (range
2262 (range
2262 ('symbol', '2')
2263 ('symbol', '2')
2263 ('symbol', '0')
2264 ('symbol', '0')
2264 define)
2265 define)
2265 (func
2266 (func
2266 ('symbol', 'last')
2267 ('symbol', 'last')
2267 (func
2268 (func
2268 ('symbol', '_list')
2269 ('symbol', '_list')
2269 ('string', '0\x002\x001')
2270 ('string', '0\x002\x001')
2270 define)
2271 define)
2271 any)
2272 any)
2272 define)
2273 define)
2273 * set:
2274 * set:
2274 <filteredset
2275 <filteredset
2275 <spanset- 0:3>,
2276 <spanset- 0:3>,
2276 <not
2277 <not
2277 <baseset [1]>>>
2278 <baseset [1]>>>
2278 2
2279 2
2279 0
2280 0
2280
2281
2281 for 'A & (op)(B)', 'B' should not be affected by the order of 'A':
2282 for 'A & (op)(B)', 'B' should not be affected by the order of 'A':
2282
2283
2283 $ try --optimize '2:0 & (1 + 0 + 2):(0 + 2 + 1)'
2284 $ try --optimize '2:0 & (1 + 0 + 2):(0 + 2 + 1)'
2284 (and
2285 (and
2285 (range
2286 (range
2286 ('symbol', '2')
2287 ('symbol', '2')
2287 ('symbol', '0'))
2288 ('symbol', '0'))
2288 (range
2289 (range
2289 (group
2290 (group
2290 (or
2291 (or
2291 (list
2292 (list
2292 ('symbol', '1')
2293 ('symbol', '1')
2293 ('symbol', '0')
2294 ('symbol', '0')
2294 ('symbol', '2'))))
2295 ('symbol', '2'))))
2295 (group
2296 (group
2296 (or
2297 (or
2297 (list
2298 (list
2298 ('symbol', '0')
2299 ('symbol', '0')
2299 ('symbol', '2')
2300 ('symbol', '2')
2300 ('symbol', '1'))))))
2301 ('symbol', '1'))))))
2301 * optimized:
2302 * optimized:
2302 (and
2303 (and
2303 (range
2304 (range
2304 ('symbol', '2')
2305 ('symbol', '2')
2305 ('symbol', '0')
2306 ('symbol', '0')
2306 define)
2307 define)
2307 (range
2308 (range
2308 (func
2309 (func
2309 ('symbol', '_list')
2310 ('symbol', '_list')
2310 ('string', '1\x000\x002')
2311 ('string', '1\x000\x002')
2311 define)
2312 define)
2312 (func
2313 (func
2313 ('symbol', '_list')
2314 ('symbol', '_list')
2314 ('string', '0\x002\x001')
2315 ('string', '0\x002\x001')
2315 define)
2316 define)
2316 follow)
2317 follow)
2317 define)
2318 define)
2318 * set:
2319 * set:
2319 <filteredset
2320 <filteredset
2320 <spanset- 0:3>,
2321 <spanset- 0:3>,
2321 <baseset [1]>>
2322 <baseset [1]>>
2322 1
2323 1
2323
2324
2324 'A & B' can be rewritten as 'B & A' by weight, but that's fine as long as
2325 'A & B' can be rewritten as 'B & A' by weight, but that's fine as long as
2325 the ordering rule is determined before the rewrite; in this example,
2326 the ordering rule is determined before the rewrite; in this example,
2326 'B' follows the order of the initial set, which is the same order as 'A'
2327 'B' follows the order of the initial set, which is the same order as 'A'
2327 since 'A' also follows the order:
2328 since 'A' also follows the order:
2328
2329
2329 $ try --optimize 'contains("glob:*") & (2 + 0 + 1)'
2330 $ try --optimize 'contains("glob:*") & (2 + 0 + 1)'
2330 (and
2331 (and
2331 (func
2332 (func
2332 ('symbol', 'contains')
2333 ('symbol', 'contains')
2333 ('string', 'glob:*'))
2334 ('string', 'glob:*'))
2334 (group
2335 (group
2335 (or
2336 (or
2336 (list
2337 (list
2337 ('symbol', '2')
2338 ('symbol', '2')
2338 ('symbol', '0')
2339 ('symbol', '0')
2339 ('symbol', '1')))))
2340 ('symbol', '1')))))
2340 * optimized:
2341 * optimized:
2341 (and
2342 (and
2342 (func
2343 (func
2343 ('symbol', '_list')
2344 ('symbol', '_list')
2344 ('string', '2\x000\x001')
2345 ('string', '2\x000\x001')
2345 follow)
2346 follow)
2346 (func
2347 (func
2347 ('symbol', 'contains')
2348 ('symbol', 'contains')
2348 ('string', 'glob:*')
2349 ('string', 'glob:*')
2349 define)
2350 define)
2350 define)
2351 define)
2351 * set:
2352 * set:
2352 <filteredset
2353 <filteredset
2353 <baseset+ [0, 1, 2]>,
2354 <baseset+ [0, 1, 2]>,
2354 <contains 'glob:*'>>
2355 <contains 'glob:*'>>
2355 0
2356 0
2356 1
2357 1
2357 2
2358 2
2358
2359
2359 and in this example, 'A & B' is rewritten as 'B & A', but 'A' overrides
2360 and in this example, 'A & B' is rewritten as 'B & A', but 'A' overrides
2360 the order appropriately:
2361 the order appropriately:
2361
2362
2362 $ try --optimize 'reverse(contains("glob:*")) & (0 + 2 + 1)'
2363 $ try --optimize 'reverse(contains("glob:*")) & (0 + 2 + 1)'
2363 (and
2364 (and
2364 (func
2365 (func
2365 ('symbol', 'reverse')
2366 ('symbol', 'reverse')
2366 (func
2367 (func
2367 ('symbol', 'contains')
2368 ('symbol', 'contains')
2368 ('string', 'glob:*')))
2369 ('string', 'glob:*')))
2369 (group
2370 (group
2370 (or
2371 (or
2371 (list
2372 (list
2372 ('symbol', '0')
2373 ('symbol', '0')
2373 ('symbol', '2')
2374 ('symbol', '2')
2374 ('symbol', '1')))))
2375 ('symbol', '1')))))
2375 * optimized:
2376 * optimized:
2376 (and
2377 (and
2377 (func
2378 (func
2378 ('symbol', '_list')
2379 ('symbol', '_list')
2379 ('string', '0\x002\x001')
2380 ('string', '0\x002\x001')
2380 follow)
2381 follow)
2381 (func
2382 (func
2382 ('symbol', 'reverse')
2383 ('symbol', 'reverse')
2383 (func
2384 (func
2384 ('symbol', 'contains')
2385 ('symbol', 'contains')
2385 ('string', 'glob:*')
2386 ('string', 'glob:*')
2386 define)
2387 define)
2387 define)
2388 define)
2388 define)
2389 define)
2389 * set:
2390 * set:
2390 <filteredset
2391 <filteredset
2391 <baseset- [0, 1, 2]>,
2392 <baseset- [0, 1, 2]>,
2392 <contains 'glob:*'>>
2393 <contains 'glob:*'>>
2393 2
2394 2
2394 1
2395 1
2395 0
2396 0
2396
2397
2397 'A + B' can be rewritten to 'B + A' by weight only when the order doesn't
2398 'A + B' can be rewritten to 'B + A' by weight only when the order doesn't
2398 matter (e.g. 'X & (A + B)' can be 'X & (B + A)', but '(A + B) & X' can't):
2399 matter (e.g. 'X & (A + B)' can be 'X & (B + A)', but '(A + B) & X' can't):
2399
2400
2400 $ try -p optimized '0:2 & (reverse(contains("a")) + 2)'
2401 $ try -p optimized '0:2 & (reverse(contains("a")) + 2)'
2401 * optimized:
2402 * optimized:
2402 (and
2403 (and
2403 (range
2404 (range
2404 ('symbol', '0')
2405 ('symbol', '0')
2405 ('symbol', '2')
2406 ('symbol', '2')
2406 define)
2407 define)
2407 (or
2408 (or
2408 (list
2409 (list
2409 ('symbol', '2')
2410 ('symbol', '2')
2410 (func
2411 (func
2411 ('symbol', 'reverse')
2412 ('symbol', 'reverse')
2412 (func
2413 (func
2413 ('symbol', 'contains')
2414 ('symbol', 'contains')
2414 ('string', 'a')
2415 ('string', 'a')
2415 define)
2416 define)
2416 follow))
2417 follow))
2417 follow)
2418 follow)
2418 define)
2419 define)
2419 * set:
2420 * set:
2420 <filteredset
2421 <filteredset
2421 <spanset+ 0:3>,
2422 <spanset+ 0:3>,
2422 <addset
2423 <addset
2423 <baseset [2]>,
2424 <baseset [2]>,
2424 <filteredset
2425 <filteredset
2425 <fullreposet+ 0:10>,
2426 <fullreposet+ 0:10>,
2426 <contains 'a'>>>>
2427 <contains 'a'>>>>
2427 0
2428 0
2428 1
2429 1
2429 2
2430 2
2430
2431
2431 $ try -p optimized '(reverse(contains("a")) + 2) & 0:2'
2432 $ try -p optimized '(reverse(contains("a")) + 2) & 0:2'
2432 * optimized:
2433 * optimized:
2433 (and
2434 (and
2434 (range
2435 (range
2435 ('symbol', '0')
2436 ('symbol', '0')
2436 ('symbol', '2')
2437 ('symbol', '2')
2437 follow)
2438 follow)
2438 (or
2439 (or
2439 (list
2440 (list
2440 (func
2441 (func
2441 ('symbol', 'reverse')
2442 ('symbol', 'reverse')
2442 (func
2443 (func
2443 ('symbol', 'contains')
2444 ('symbol', 'contains')
2444 ('string', 'a')
2445 ('string', 'a')
2445 define)
2446 define)
2446 define)
2447 define)
2447 ('symbol', '2'))
2448 ('symbol', '2'))
2448 define)
2449 define)
2449 define)
2450 define)
2450 * set:
2451 * set:
2451 <addset
2452 <addset
2452 <filteredset
2453 <filteredset
2453 <spanset- 0:3>,
2454 <spanset- 0:3>,
2454 <contains 'a'>>,
2455 <contains 'a'>>,
2455 <baseset [2]>>
2456 <baseset [2]>>
2456 1
2457 1
2457 0
2458 0
2458 2
2459 2
2459
2460
2460 test sort revset
2461 test sort revset
2461 --------------------------------------------
2462 --------------------------------------------
2462
2463
2463 test when adding two unordered revsets
2464 test when adding two unordered revsets
2464
2465
2465 $ log 'sort(keyword(issue) or modifies(b))'
2466 $ log 'sort(keyword(issue) or modifies(b))'
2466 4
2467 4
2467 6
2468 6
2468
2469
2469 test when sorting a reversed collection in the same way it is
2470 test when sorting a reversed collection in the same way it is
2470
2471
2471 $ log 'sort(reverse(all()), -rev)'
2472 $ log 'sort(reverse(all()), -rev)'
2472 9
2473 9
2473 8
2474 8
2474 7
2475 7
2475 6
2476 6
2476 5
2477 5
2477 4
2478 4
2478 3
2479 3
2479 2
2480 2
2480 1
2481 1
2481 0
2482 0
2482
2483
2483 test when sorting a reversed collection
2484 test when sorting a reversed collection
2484
2485
2485 $ log 'sort(reverse(all()), rev)'
2486 $ log 'sort(reverse(all()), rev)'
2486 0
2487 0
2487 1
2488 1
2488 2
2489 2
2489 3
2490 3
2490 4
2491 4
2491 5
2492 5
2492 6
2493 6
2493 7
2494 7
2494 8
2495 8
2495 9
2496 9
2496
2497
2497
2498
2498 test sorting two sorted collections in different orders
2499 test sorting two sorted collections in different orders
2499
2500
2500 $ log 'sort(outgoing() or reverse(removes(a)), rev)'
2501 $ log 'sort(outgoing() or reverse(removes(a)), rev)'
2501 2
2502 2
2502 6
2503 6
2503 8
2504 8
2504 9
2505 9
2505
2506
2506 test sorting two sorted collections in different orders backwards
2507 test sorting two sorted collections in different orders backwards
2507
2508
2508 $ log 'sort(outgoing() or reverse(removes(a)), -rev)'
2509 $ log 'sort(outgoing() or reverse(removes(a)), -rev)'
2509 9
2510 9
2510 8
2511 8
2511 6
2512 6
2512 2
2513 2
2513
2514
2514 test empty sort key which is noop
2515 test empty sort key which is noop
2515
2516
2516 $ log 'sort(0 + 2 + 1, "")'
2517 $ log 'sort(0 + 2 + 1, "")'
2517 0
2518 0
2518 2
2519 2
2519 1
2520 1
2520
2521
2521 test invalid sort keys
2522 test invalid sort keys
2522
2523
2523 $ log 'sort(all(), -invalid)'
2524 $ log 'sort(all(), -invalid)'
2524 hg: parse error: unknown sort key '-invalid'
2525 hg: parse error: unknown sort key '-invalid'
2525 [255]
2526 [255]
2526
2527
2527 $ cd ..
2528 $ cd ..
2528
2529
2529 test sorting by multiple keys including variable-length strings
2530 test sorting by multiple keys including variable-length strings
2530
2531
2531 $ hg init sorting
2532 $ hg init sorting
2532 $ cd sorting
2533 $ cd sorting
2533 $ cat <<EOF >> .hg/hgrc
2534 $ cat <<EOF >> .hg/hgrc
2534 > [ui]
2535 > [ui]
2535 > logtemplate = '{rev} {branch|p5}{desc|p5}{author|p5}{date|hgdate}\n'
2536 > logtemplate = '{rev} {branch|p5}{desc|p5}{author|p5}{date|hgdate}\n'
2536 > [templatealias]
2537 > [templatealias]
2537 > p5(s) = pad(s, 5)
2538 > p5(s) = pad(s, 5)
2538 > EOF
2539 > EOF
2539 $ hg branch -qf b12
2540 $ hg branch -qf b12
2540 $ hg ci -m m111 -u u112 -d '111 10800'
2541 $ hg ci -m m111 -u u112 -d '111 10800'
2541 $ hg branch -qf b11
2542 $ hg branch -qf b11
2542 $ hg ci -m m12 -u u111 -d '112 7200'
2543 $ hg ci -m m12 -u u111 -d '112 7200'
2543 $ hg branch -qf b111
2544 $ hg branch -qf b111
2544 $ hg ci -m m11 -u u12 -d '111 3600'
2545 $ hg ci -m m11 -u u12 -d '111 3600'
2545 $ hg branch -qf b112
2546 $ hg branch -qf b112
2546 $ hg ci -m m111 -u u11 -d '120 0'
2547 $ hg ci -m m111 -u u11 -d '120 0'
2547 $ hg branch -qf b111
2548 $ hg branch -qf b111
2548 $ hg ci -m m112 -u u111 -d '110 14400'
2549 $ hg ci -m m112 -u u111 -d '110 14400'
2549 created new head
2550 created new head
2550
2551
2551 compare revisions (has fast path):
2552 compare revisions (has fast path):
2552
2553
2553 $ hg log -r 'sort(all(), rev)'
2554 $ hg log -r 'sort(all(), rev)'
2554 0 b12 m111 u112 111 10800
2555 0 b12 m111 u112 111 10800
2555 1 b11 m12 u111 112 7200
2556 1 b11 m12 u111 112 7200
2556 2 b111 m11 u12 111 3600
2557 2 b111 m11 u12 111 3600
2557 3 b112 m111 u11 120 0
2558 3 b112 m111 u11 120 0
2558 4 b111 m112 u111 110 14400
2559 4 b111 m112 u111 110 14400
2559
2560
2560 $ hg log -r 'sort(all(), -rev)'
2561 $ hg log -r 'sort(all(), -rev)'
2561 4 b111 m112 u111 110 14400
2562 4 b111 m112 u111 110 14400
2562 3 b112 m111 u11 120 0
2563 3 b112 m111 u11 120 0
2563 2 b111 m11 u12 111 3600
2564 2 b111 m11 u12 111 3600
2564 1 b11 m12 u111 112 7200
2565 1 b11 m12 u111 112 7200
2565 0 b12 m111 u112 111 10800
2566 0 b12 m111 u112 111 10800
2566
2567
2567 compare variable-length strings (issue5218):
2568 compare variable-length strings (issue5218):
2568
2569
2569 $ hg log -r 'sort(all(), branch)'
2570 $ hg log -r 'sort(all(), branch)'
2570 1 b11 m12 u111 112 7200
2571 1 b11 m12 u111 112 7200
2571 2 b111 m11 u12 111 3600
2572 2 b111 m11 u12 111 3600
2572 4 b111 m112 u111 110 14400
2573 4 b111 m112 u111 110 14400
2573 3 b112 m111 u11 120 0
2574 3 b112 m111 u11 120 0
2574 0 b12 m111 u112 111 10800
2575 0 b12 m111 u112 111 10800
2575
2576
2576 $ hg log -r 'sort(all(), -branch)'
2577 $ hg log -r 'sort(all(), -branch)'
2577 0 b12 m111 u112 111 10800
2578 0 b12 m111 u112 111 10800
2578 3 b112 m111 u11 120 0
2579 3 b112 m111 u11 120 0
2579 2 b111 m11 u12 111 3600
2580 2 b111 m11 u12 111 3600
2580 4 b111 m112 u111 110 14400
2581 4 b111 m112 u111 110 14400
2581 1 b11 m12 u111 112 7200
2582 1 b11 m12 u111 112 7200
2582
2583
2583 $ hg log -r 'sort(all(), desc)'
2584 $ hg log -r 'sort(all(), desc)'
2584 2 b111 m11 u12 111 3600
2585 2 b111 m11 u12 111 3600
2585 0 b12 m111 u112 111 10800
2586 0 b12 m111 u112 111 10800
2586 3 b112 m111 u11 120 0
2587 3 b112 m111 u11 120 0
2587 4 b111 m112 u111 110 14400
2588 4 b111 m112 u111 110 14400
2588 1 b11 m12 u111 112 7200
2589 1 b11 m12 u111 112 7200
2589
2590
2590 $ hg log -r 'sort(all(), -desc)'
2591 $ hg log -r 'sort(all(), -desc)'
2591 1 b11 m12 u111 112 7200
2592 1 b11 m12 u111 112 7200
2592 4 b111 m112 u111 110 14400
2593 4 b111 m112 u111 110 14400
2593 0 b12 m111 u112 111 10800
2594 0 b12 m111 u112 111 10800
2594 3 b112 m111 u11 120 0
2595 3 b112 m111 u11 120 0
2595 2 b111 m11 u12 111 3600
2596 2 b111 m11 u12 111 3600
2596
2597
2597 $ hg log -r 'sort(all(), user)'
2598 $ hg log -r 'sort(all(), user)'
2598 3 b112 m111 u11 120 0
2599 3 b112 m111 u11 120 0
2599 1 b11 m12 u111 112 7200
2600 1 b11 m12 u111 112 7200
2600 4 b111 m112 u111 110 14400
2601 4 b111 m112 u111 110 14400
2601 0 b12 m111 u112 111 10800
2602 0 b12 m111 u112 111 10800
2602 2 b111 m11 u12 111 3600
2603 2 b111 m11 u12 111 3600
2603
2604
2604 $ hg log -r 'sort(all(), -user)'
2605 $ hg log -r 'sort(all(), -user)'
2605 2 b111 m11 u12 111 3600
2606 2 b111 m11 u12 111 3600
2606 0 b12 m111 u112 111 10800
2607 0 b12 m111 u112 111 10800
2607 1 b11 m12 u111 112 7200
2608 1 b11 m12 u111 112 7200
2608 4 b111 m112 u111 110 14400
2609 4 b111 m112 u111 110 14400
2609 3 b112 m111 u11 120 0
2610 3 b112 m111 u11 120 0
2610
2611
2611 compare dates (tz offset should have no effect):
2612 compare dates (tz offset should have no effect):
2612
2613
2613 $ hg log -r 'sort(all(), date)'
2614 $ hg log -r 'sort(all(), date)'
2614 4 b111 m112 u111 110 14400
2615 4 b111 m112 u111 110 14400
2615 0 b12 m111 u112 111 10800
2616 0 b12 m111 u112 111 10800
2616 2 b111 m11 u12 111 3600
2617 2 b111 m11 u12 111 3600
2617 1 b11 m12 u111 112 7200
2618 1 b11 m12 u111 112 7200
2618 3 b112 m111 u11 120 0
2619 3 b112 m111 u11 120 0
2619
2620
2620 $ hg log -r 'sort(all(), -date)'
2621 $ hg log -r 'sort(all(), -date)'
2621 3 b112 m111 u11 120 0
2622 3 b112 m111 u11 120 0
2622 1 b11 m12 u111 112 7200
2623 1 b11 m12 u111 112 7200
2623 0 b12 m111 u112 111 10800
2624 0 b12 m111 u112 111 10800
2624 2 b111 m11 u12 111 3600
2625 2 b111 m11 u12 111 3600
2625 4 b111 m112 u111 110 14400
2626 4 b111 m112 u111 110 14400
2626
2627
2627 be aware that 'sort(x, -k)' is not exactly the same as 'reverse(sort(x, k))'
2628 be aware that 'sort(x, -k)' is not exactly the same as 'reverse(sort(x, k))'
2628 because '-k' reverses the comparison, not the list itself:
2629 because '-k' reverses the comparison, not the list itself:
2629
2630
2630 $ hg log -r 'sort(0 + 2, date)'
2631 $ hg log -r 'sort(0 + 2, date)'
2631 0 b12 m111 u112 111 10800
2632 0 b12 m111 u112 111 10800
2632 2 b111 m11 u12 111 3600
2633 2 b111 m11 u12 111 3600
2633
2634
2634 $ hg log -r 'sort(0 + 2, -date)'
2635 $ hg log -r 'sort(0 + 2, -date)'
2635 0 b12 m111 u112 111 10800
2636 0 b12 m111 u112 111 10800
2636 2 b111 m11 u12 111 3600
2637 2 b111 m11 u12 111 3600
2637
2638
2638 $ hg log -r 'reverse(sort(0 + 2, date))'
2639 $ hg log -r 'reverse(sort(0 + 2, date))'
2639 2 b111 m11 u12 111 3600
2640 2 b111 m11 u12 111 3600
2640 0 b12 m111 u112 111 10800
2641 0 b12 m111 u112 111 10800
2641
2642
2642 sort by multiple keys:
2643 sort by multiple keys:
2643
2644
2644 $ hg log -r 'sort(all(), "branch -rev")'
2645 $ hg log -r 'sort(all(), "branch -rev")'
2645 1 b11 m12 u111 112 7200
2646 1 b11 m12 u111 112 7200
2646 4 b111 m112 u111 110 14400
2647 4 b111 m112 u111 110 14400
2647 2 b111 m11 u12 111 3600
2648 2 b111 m11 u12 111 3600
2648 3 b112 m111 u11 120 0
2649 3 b112 m111 u11 120 0
2649 0 b12 m111 u112 111 10800
2650 0 b12 m111 u112 111 10800
2650
2651
2651 $ hg log -r 'sort(all(), "-desc -date")'
2652 $ hg log -r 'sort(all(), "-desc -date")'
2652 1 b11 m12 u111 112 7200
2653 1 b11 m12 u111 112 7200
2653 4 b111 m112 u111 110 14400
2654 4 b111 m112 u111 110 14400
2654 3 b112 m111 u11 120 0
2655 3 b112 m111 u11 120 0
2655 0 b12 m111 u112 111 10800
2656 0 b12 m111 u112 111 10800
2656 2 b111 m11 u12 111 3600
2657 2 b111 m11 u12 111 3600
2657
2658
2658 $ hg log -r 'sort(all(), "user -branch date rev")'
2659 $ hg log -r 'sort(all(), "user -branch date rev")'
2659 3 b112 m111 u11 120 0
2660 3 b112 m111 u11 120 0
2660 4 b111 m112 u111 110 14400
2661 4 b111 m112 u111 110 14400
2661 1 b11 m12 u111 112 7200
2662 1 b11 m12 u111 112 7200
2662 0 b12 m111 u112 111 10800
2663 0 b12 m111 u112 111 10800
2663 2 b111 m11 u12 111 3600
2664 2 b111 m11 u12 111 3600
2664
2665
2665 toposort prioritises graph branches
2666 toposort prioritises graph branches
2666
2667
2667 $ hg up 2
2668 $ hg up 2
2668 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2669 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2669 $ touch a
2670 $ touch a
2670 $ hg addremove
2671 $ hg addremove
2671 adding a
2672 adding a
2672 $ hg ci -m 't1' -u 'tu' -d '130 0'
2673 $ hg ci -m 't1' -u 'tu' -d '130 0'
2673 created new head
2674 created new head
2674 $ echo 'a' >> a
2675 $ echo 'a' >> a
2675 $ hg ci -m 't2' -u 'tu' -d '130 0'
2676 $ hg ci -m 't2' -u 'tu' -d '130 0'
2676 $ hg book book1
2677 $ hg book book1
2677 $ hg up 4
2678 $ hg up 4
2678 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2679 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2679 (leaving bookmark book1)
2680 (leaving bookmark book1)
2680 $ touch a
2681 $ touch a
2681 $ hg addremove
2682 $ hg addremove
2682 adding a
2683 adding a
2683 $ hg ci -m 't3' -u 'tu' -d '130 0'
2684 $ hg ci -m 't3' -u 'tu' -d '130 0'
2684
2685
2685 $ hg log -r 'sort(all(), topo)'
2686 $ hg log -r 'sort(all(), topo)'
2686 7 b111 t3 tu 130 0
2687 7 b111 t3 tu 130 0
2687 4 b111 m112 u111 110 14400
2688 4 b111 m112 u111 110 14400
2688 3 b112 m111 u11 120 0
2689 3 b112 m111 u11 120 0
2689 6 b111 t2 tu 130 0
2690 6 b111 t2 tu 130 0
2690 5 b111 t1 tu 130 0
2691 5 b111 t1 tu 130 0
2691 2 b111 m11 u12 111 3600
2692 2 b111 m11 u12 111 3600
2692 1 b11 m12 u111 112 7200
2693 1 b11 m12 u111 112 7200
2693 0 b12 m111 u112 111 10800
2694 0 b12 m111 u112 111 10800
2694
2695
2695 $ hg log -r 'sort(all(), -topo)'
2696 $ hg log -r 'sort(all(), -topo)'
2696 0 b12 m111 u112 111 10800
2697 0 b12 m111 u112 111 10800
2697 1 b11 m12 u111 112 7200
2698 1 b11 m12 u111 112 7200
2698 2 b111 m11 u12 111 3600
2699 2 b111 m11 u12 111 3600
2699 5 b111 t1 tu 130 0
2700 5 b111 t1 tu 130 0
2700 6 b111 t2 tu 130 0
2701 6 b111 t2 tu 130 0
2701 3 b112 m111 u11 120 0
2702 3 b112 m111 u11 120 0
2702 4 b111 m112 u111 110 14400
2703 4 b111 m112 u111 110 14400
2703 7 b111 t3 tu 130 0
2704 7 b111 t3 tu 130 0
2704
2705
2705 $ hg log -r 'sort(all(), topo, topo.firstbranch=book1)'
2706 $ hg log -r 'sort(all(), topo, topo.firstbranch=book1)'
2706 6 b111 t2 tu 130 0
2707 6 b111 t2 tu 130 0
2707 5 b111 t1 tu 130 0
2708 5 b111 t1 tu 130 0
2708 7 b111 t3 tu 130 0
2709 7 b111 t3 tu 130 0
2709 4 b111 m112 u111 110 14400
2710 4 b111 m112 u111 110 14400
2710 3 b112 m111 u11 120 0
2711 3 b112 m111 u11 120 0
2711 2 b111 m11 u12 111 3600
2712 2 b111 m11 u12 111 3600
2712 1 b11 m12 u111 112 7200
2713 1 b11 m12 u111 112 7200
2713 0 b12 m111 u112 111 10800
2714 0 b12 m111 u112 111 10800
2714
2715
2715 topographical sorting can't be combined with other sort keys, and you can't
2716 topographical sorting can't be combined with other sort keys, and you can't
2716 use the topo.firstbranch option when topo sort is not active:
2717 use the topo.firstbranch option when topo sort is not active:
2717
2718
2718 $ hg log -r 'sort(all(), "topo user")'
2719 $ hg log -r 'sort(all(), "topo user")'
2719 hg: parse error: topo sort order cannot be combined with other sort keys
2720 hg: parse error: topo sort order cannot be combined with other sort keys
2720 [255]
2721 [255]
2721
2722
2722 $ hg log -r 'sort(all(), user, topo.firstbranch=book1)'
2723 $ hg log -r 'sort(all(), user, topo.firstbranch=book1)'
2723 hg: parse error: topo.firstbranch can only be used when using the topo sort key
2724 hg: parse error: topo.firstbranch can only be used when using the topo sort key
2724 [255]
2725 [255]
2725
2726
2726 topo.firstbranch should accept any kind of expressions:
2727 topo.firstbranch should accept any kind of expressions:
2727
2728
2728 $ hg log -r 'sort(0, topo, topo.firstbranch=(book1))'
2729 $ hg log -r 'sort(0, topo, topo.firstbranch=(book1))'
2729 0 b12 m111 u112 111 10800
2730 0 b12 m111 u112 111 10800
2730
2731
2731 $ cd ..
2732 $ cd ..
2732 $ cd repo
2733 $ cd repo
2733
2734
2734 test subtracting something from an addset
2735 test subtracting something from an addset
2735
2736
2736 $ log '(outgoing() or removes(a)) - removes(a)'
2737 $ log '(outgoing() or removes(a)) - removes(a)'
2737 8
2738 8
2738 9
2739 9
2739
2740
2740 test intersecting something with an addset
2741 test intersecting something with an addset
2741
2742
2742 $ log 'parents(outgoing() or removes(a))'
2743 $ log 'parents(outgoing() or removes(a))'
2743 1
2744 1
2744 4
2745 4
2745 5
2746 5
2746 8
2747 8
2747
2748
2748 test that `or` operation combines elements in the right order:
2749 test that `or` operation combines elements in the right order:
2749
2750
2750 $ log '3:4 or 2:5'
2751 $ log '3:4 or 2:5'
2751 3
2752 3
2752 4
2753 4
2753 2
2754 2
2754 5
2755 5
2755 $ log '3:4 or 5:2'
2756 $ log '3:4 or 5:2'
2756 3
2757 3
2757 4
2758 4
2758 5
2759 5
2759 2
2760 2
2760 $ log 'sort(3:4 or 2:5)'
2761 $ log 'sort(3:4 or 2:5)'
2761 2
2762 2
2762 3
2763 3
2763 4
2764 4
2764 5
2765 5
2765 $ log 'sort(3:4 or 5:2)'
2766 $ log 'sort(3:4 or 5:2)'
2766 2
2767 2
2767 3
2768 3
2768 4
2769 4
2769 5
2770 5
2770
2771
2771 test that more than one `-r`s are combined in the right order and deduplicated:
2772 test that more than one `-r`s are combined in the right order and deduplicated:
2772
2773
2773 $ hg log -T '{rev}\n' -r 3 -r 3 -r 4 -r 5:2 -r 'ancestors(4)'
2774 $ hg log -T '{rev}\n' -r 3 -r 3 -r 4 -r 5:2 -r 'ancestors(4)'
2774 3
2775 3
2775 4
2776 4
2776 5
2777 5
2777 2
2778 2
2778 0
2779 0
2779 1
2780 1
2780
2781
2781 test that `or` operation skips duplicated revisions from right-hand side
2782 test that `or` operation skips duplicated revisions from right-hand side
2782
2783
2783 $ try 'reverse(1::5) or ancestors(4)'
2784 $ try 'reverse(1::5) or ancestors(4)'
2784 (or
2785 (or
2785 (list
2786 (list
2786 (func
2787 (func
2787 ('symbol', 'reverse')
2788 ('symbol', 'reverse')
2788 (dagrange
2789 (dagrange
2789 ('symbol', '1')
2790 ('symbol', '1')
2790 ('symbol', '5')))
2791 ('symbol', '5')))
2791 (func
2792 (func
2792 ('symbol', 'ancestors')
2793 ('symbol', 'ancestors')
2793 ('symbol', '4'))))
2794 ('symbol', '4'))))
2794 * set:
2795 * set:
2795 <addset
2796 <addset
2796 <baseset- [1, 3, 5]>,
2797 <baseset- [1, 3, 5]>,
2797 <generatorset+>>
2798 <generatorset+>>
2798 5
2799 5
2799 3
2800 3
2800 1
2801 1
2801 0
2802 0
2802 2
2803 2
2803 4
2804 4
2804 $ try 'sort(ancestors(4) or reverse(1::5))'
2805 $ try 'sort(ancestors(4) or reverse(1::5))'
2805 (func
2806 (func
2806 ('symbol', 'sort')
2807 ('symbol', 'sort')
2807 (or
2808 (or
2808 (list
2809 (list
2809 (func
2810 (func
2810 ('symbol', 'ancestors')
2811 ('symbol', 'ancestors')
2811 ('symbol', '4'))
2812 ('symbol', '4'))
2812 (func
2813 (func
2813 ('symbol', 'reverse')
2814 ('symbol', 'reverse')
2814 (dagrange
2815 (dagrange
2815 ('symbol', '1')
2816 ('symbol', '1')
2816 ('symbol', '5'))))))
2817 ('symbol', '5'))))))
2817 * set:
2818 * set:
2818 <addset+
2819 <addset+
2819 <generatorset+>,
2820 <generatorset+>,
2820 <baseset- [1, 3, 5]>>
2821 <baseset- [1, 3, 5]>>
2821 0
2822 0
2822 1
2823 1
2823 2
2824 2
2824 3
2825 3
2825 4
2826 4
2826 5
2827 5
2827
2828
2828 test optimization of trivial `or` operation
2829 test optimization of trivial `or` operation
2829
2830
2830 $ try --optimize '0|(1)|"2"|-2|tip|null'
2831 $ try --optimize '0|(1)|"2"|-2|tip|null'
2831 (or
2832 (or
2832 (list
2833 (list
2833 ('symbol', '0')
2834 ('symbol', '0')
2834 (group
2835 (group
2835 ('symbol', '1'))
2836 ('symbol', '1'))
2836 ('string', '2')
2837 ('string', '2')
2837 (negate
2838 (negate
2838 ('symbol', '2'))
2839 ('symbol', '2'))
2839 ('symbol', 'tip')
2840 ('symbol', 'tip')
2840 ('symbol', 'null')))
2841 ('symbol', 'null')))
2841 * optimized:
2842 * optimized:
2842 (func
2843 (func
2843 ('symbol', '_list')
2844 ('symbol', '_list')
2844 ('string', '0\x001\x002\x00-2\x00tip\x00null')
2845 ('string', '0\x001\x002\x00-2\x00tip\x00null')
2845 define)
2846 define)
2846 * set:
2847 * set:
2847 <baseset [0, 1, 2, 8, 9, -1]>
2848 <baseset [0, 1, 2, 8, 9, -1]>
2848 0
2849 0
2849 1
2850 1
2850 2
2851 2
2851 8
2852 8
2852 9
2853 9
2853 -1
2854 -1
2854
2855
2855 $ try --optimize '0|1|2:3'
2856 $ try --optimize '0|1|2:3'
2856 (or
2857 (or
2857 (list
2858 (list
2858 ('symbol', '0')
2859 ('symbol', '0')
2859 ('symbol', '1')
2860 ('symbol', '1')
2860 (range
2861 (range
2861 ('symbol', '2')
2862 ('symbol', '2')
2862 ('symbol', '3'))))
2863 ('symbol', '3'))))
2863 * optimized:
2864 * optimized:
2864 (or
2865 (or
2865 (list
2866 (list
2866 (func
2867 (func
2867 ('symbol', '_list')
2868 ('symbol', '_list')
2868 ('string', '0\x001')
2869 ('string', '0\x001')
2869 define)
2870 define)
2870 (range
2871 (range
2871 ('symbol', '2')
2872 ('symbol', '2')
2872 ('symbol', '3')
2873 ('symbol', '3')
2873 define))
2874 define))
2874 define)
2875 define)
2875 * set:
2876 * set:
2876 <addset
2877 <addset
2877 <baseset [0, 1]>,
2878 <baseset [0, 1]>,
2878 <spanset+ 2:4>>
2879 <spanset+ 2:4>>
2879 0
2880 0
2880 1
2881 1
2881 2
2882 2
2882 3
2883 3
2883
2884
2884 $ try --optimize '0:1|2|3:4|5|6'
2885 $ try --optimize '0:1|2|3:4|5|6'
2885 (or
2886 (or
2886 (list
2887 (list
2887 (range
2888 (range
2888 ('symbol', '0')
2889 ('symbol', '0')
2889 ('symbol', '1'))
2890 ('symbol', '1'))
2890 ('symbol', '2')
2891 ('symbol', '2')
2891 (range
2892 (range
2892 ('symbol', '3')
2893 ('symbol', '3')
2893 ('symbol', '4'))
2894 ('symbol', '4'))
2894 ('symbol', '5')
2895 ('symbol', '5')
2895 ('symbol', '6')))
2896 ('symbol', '6')))
2896 * optimized:
2897 * optimized:
2897 (or
2898 (or
2898 (list
2899 (list
2899 (range
2900 (range
2900 ('symbol', '0')
2901 ('symbol', '0')
2901 ('symbol', '1')
2902 ('symbol', '1')
2902 define)
2903 define)
2903 ('symbol', '2')
2904 ('symbol', '2')
2904 (range
2905 (range
2905 ('symbol', '3')
2906 ('symbol', '3')
2906 ('symbol', '4')
2907 ('symbol', '4')
2907 define)
2908 define)
2908 (func
2909 (func
2909 ('symbol', '_list')
2910 ('symbol', '_list')
2910 ('string', '5\x006')
2911 ('string', '5\x006')
2911 define))
2912 define))
2912 define)
2913 define)
2913 * set:
2914 * set:
2914 <addset
2915 <addset
2915 <addset
2916 <addset
2916 <spanset+ 0:2>,
2917 <spanset+ 0:2>,
2917 <baseset [2]>>,
2918 <baseset [2]>>,
2918 <addset
2919 <addset
2919 <spanset+ 3:5>,
2920 <spanset+ 3:5>,
2920 <baseset [5, 6]>>>
2921 <baseset [5, 6]>>>
2921 0
2922 0
2922 1
2923 1
2923 2
2924 2
2924 3
2925 3
2925 4
2926 4
2926 5
2927 5
2927 6
2928 6
2928
2929
2929 unoptimized `or` looks like this
2930 unoptimized `or` looks like this
2930
2931
2931 $ try --no-optimized -p analyzed '0|1|2|3|4'
2932 $ try --no-optimized -p analyzed '0|1|2|3|4'
2932 * analyzed:
2933 * analyzed:
2933 (or
2934 (or
2934 (list
2935 (list
2935 ('symbol', '0')
2936 ('symbol', '0')
2936 ('symbol', '1')
2937 ('symbol', '1')
2937 ('symbol', '2')
2938 ('symbol', '2')
2938 ('symbol', '3')
2939 ('symbol', '3')
2939 ('symbol', '4'))
2940 ('symbol', '4'))
2940 define)
2941 define)
2941 * set:
2942 * set:
2942 <addset
2943 <addset
2943 <addset
2944 <addset
2944 <baseset [0]>,
2945 <baseset [0]>,
2945 <baseset [1]>>,
2946 <baseset [1]>>,
2946 <addset
2947 <addset
2947 <baseset [2]>,
2948 <baseset [2]>,
2948 <addset
2949 <addset
2949 <baseset [3]>,
2950 <baseset [3]>,
2950 <baseset [4]>>>>
2951 <baseset [4]>>>>
2951 0
2952 0
2952 1
2953 1
2953 2
2954 2
2954 3
2955 3
2955 4
2956 4
2956
2957
2957 test that `_list` should be narrowed by provided `subset`
2958 test that `_list` should be narrowed by provided `subset`
2958
2959
2959 $ log '0:2 and (null|1|2|3)'
2960 $ log '0:2 and (null|1|2|3)'
2960 1
2961 1
2961 2
2962 2
2962
2963
2963 test that `_list` should remove duplicates
2964 test that `_list` should remove duplicates
2964
2965
2965 $ log '0|1|2|1|2|-1|tip'
2966 $ log '0|1|2|1|2|-1|tip'
2966 0
2967 0
2967 1
2968 1
2968 2
2969 2
2969 9
2970 9
2970
2971
2971 test unknown revision in `_list`
2972 test unknown revision in `_list`
2972
2973
2973 $ log '0|unknown'
2974 $ log '0|unknown'
2974 abort: unknown revision 'unknown'!
2975 abort: unknown revision 'unknown'!
2975 [255]
2976 [255]
2976
2977
2977 test integer range in `_list`
2978 test integer range in `_list`
2978
2979
2979 $ log '-1|-10'
2980 $ log '-1|-10'
2980 9
2981 9
2981 0
2982 0
2982
2983
2983 $ log '-10|-11'
2984 $ log '-10|-11'
2984 abort: unknown revision '-11'!
2985 abort: unknown revision '-11'!
2985 [255]
2986 [255]
2986
2987
2987 $ log '9|10'
2988 $ log '9|10'
2988 abort: unknown revision '10'!
2989 abort: unknown revision '10'!
2989 [255]
2990 [255]
2990
2991
2991 test '0000' != '0' in `_list`
2992 test '0000' != '0' in `_list`
2992
2993
2993 $ log '0|0000'
2994 $ log '0|0000'
2994 0
2995 0
2995 -1
2996 -1
2996
2997
2997 test ',' in `_list`
2998 test ',' in `_list`
2998 $ log '0,1'
2999 $ log '0,1'
2999 hg: parse error: can't use a list in this context
3000 hg: parse error: can't use a list in this context
3000 (see hg help "revsets.x or y")
3001 (see hg help "revsets.x or y")
3001 [255]
3002 [255]
3002 $ try '0,1,2'
3003 $ try '0,1,2'
3003 (list
3004 (list
3004 ('symbol', '0')
3005 ('symbol', '0')
3005 ('symbol', '1')
3006 ('symbol', '1')
3006 ('symbol', '2'))
3007 ('symbol', '2'))
3007 hg: parse error: can't use a list in this context
3008 hg: parse error: can't use a list in this context
3008 (see hg help "revsets.x or y")
3009 (see hg help "revsets.x or y")
3009 [255]
3010 [255]
3010
3011
3011 test that chained `or` operations make balanced addsets
3012 test that chained `or` operations make balanced addsets
3012
3013
3013 $ try '0:1|1:2|2:3|3:4|4:5'
3014 $ try '0:1|1:2|2:3|3:4|4:5'
3014 (or
3015 (or
3015 (list
3016 (list
3016 (range
3017 (range
3017 ('symbol', '0')
3018 ('symbol', '0')
3018 ('symbol', '1'))
3019 ('symbol', '1'))
3019 (range
3020 (range
3020 ('symbol', '1')
3021 ('symbol', '1')
3021 ('symbol', '2'))
3022 ('symbol', '2'))
3022 (range
3023 (range
3023 ('symbol', '2')
3024 ('symbol', '2')
3024 ('symbol', '3'))
3025 ('symbol', '3'))
3025 (range
3026 (range
3026 ('symbol', '3')
3027 ('symbol', '3')
3027 ('symbol', '4'))
3028 ('symbol', '4'))
3028 (range
3029 (range
3029 ('symbol', '4')
3030 ('symbol', '4')
3030 ('symbol', '5'))))
3031 ('symbol', '5'))))
3031 * set:
3032 * set:
3032 <addset
3033 <addset
3033 <addset
3034 <addset
3034 <spanset+ 0:2>,
3035 <spanset+ 0:2>,
3035 <spanset+ 1:3>>,
3036 <spanset+ 1:3>>,
3036 <addset
3037 <addset
3037 <spanset+ 2:4>,
3038 <spanset+ 2:4>,
3038 <addset
3039 <addset
3039 <spanset+ 3:5>,
3040 <spanset+ 3:5>,
3040 <spanset+ 4:6>>>>
3041 <spanset+ 4:6>>>>
3041 0
3042 0
3042 1
3043 1
3043 2
3044 2
3044 3
3045 3
3045 4
3046 4
3046 5
3047 5
3047
3048
3048 no crash by empty group "()" while optimizing `or` operations
3049 no crash by empty group "()" while optimizing `or` operations
3049
3050
3050 $ try --optimize '0|()'
3051 $ try --optimize '0|()'
3051 (or
3052 (or
3052 (list
3053 (list
3053 ('symbol', '0')
3054 ('symbol', '0')
3054 (group
3055 (group
3055 None)))
3056 None)))
3056 * optimized:
3057 * optimized:
3057 (or
3058 (or
3058 (list
3059 (list
3059 ('symbol', '0')
3060 ('symbol', '0')
3060 None)
3061 None)
3061 define)
3062 define)
3062 hg: parse error: missing argument
3063 hg: parse error: missing argument
3063 [255]
3064 [255]
3064
3065
3065 test that chained `or` operations never eat up stack (issue4624)
3066 test that chained `or` operations never eat up stack (issue4624)
3066 (uses `0:1` instead of `0` to avoid future optimization of trivial revisions)
3067 (uses `0:1` instead of `0` to avoid future optimization of trivial revisions)
3067
3068
3068 $ hg log -T '{rev}\n' -r `$PYTHON -c "print '+'.join(['0:1'] * 500)"`
3069 $ hg log -T '{rev}\n' -r `$PYTHON -c "print '+'.join(['0:1'] * 500)"`
3069 0
3070 0
3070 1
3071 1
3071
3072
3072 test that repeated `-r` options never eat up stack (issue4565)
3073 test that repeated `-r` options never eat up stack (issue4565)
3073 (uses `-r 0::1` to avoid possible optimization at old-style parser)
3074 (uses `-r 0::1` to avoid possible optimization at old-style parser)
3074
3075
3075 $ hg log -T '{rev}\n' `$PYTHON -c "for i in xrange(500): print '-r 0::1 ',"`
3076 $ hg log -T '{rev}\n' `$PYTHON -c "for i in xrange(500): print '-r 0::1 ',"`
3076 0
3077 0
3077 1
3078 1
3078
3079
3079 check that conversion to only works
3080 check that conversion to only works
3080 $ try --optimize '::3 - ::1'
3081 $ try --optimize '::3 - ::1'
3081 (minus
3082 (minus
3082 (dagrangepre
3083 (dagrangepre
3083 ('symbol', '3'))
3084 ('symbol', '3'))
3084 (dagrangepre
3085 (dagrangepre
3085 ('symbol', '1')))
3086 ('symbol', '1')))
3086 * optimized:
3087 * optimized:
3087 (func
3088 (func
3088 ('symbol', 'only')
3089 ('symbol', 'only')
3089 (list
3090 (list
3090 ('symbol', '3')
3091 ('symbol', '3')
3091 ('symbol', '1'))
3092 ('symbol', '1'))
3092 define)
3093 define)
3093 * set:
3094 * set:
3094 <baseset+ [3]>
3095 <baseset+ [3]>
3095 3
3096 3
3096 $ try --optimize 'ancestors(1) - ancestors(3)'
3097 $ try --optimize 'ancestors(1) - ancestors(3)'
3097 (minus
3098 (minus
3098 (func
3099 (func
3099 ('symbol', 'ancestors')
3100 ('symbol', 'ancestors')
3100 ('symbol', '1'))
3101 ('symbol', '1'))
3101 (func
3102 (func
3102 ('symbol', 'ancestors')
3103 ('symbol', 'ancestors')
3103 ('symbol', '3')))
3104 ('symbol', '3')))
3104 * optimized:
3105 * optimized:
3105 (func
3106 (func
3106 ('symbol', 'only')
3107 ('symbol', 'only')
3107 (list
3108 (list
3108 ('symbol', '1')
3109 ('symbol', '1')
3109 ('symbol', '3'))
3110 ('symbol', '3'))
3110 define)
3111 define)
3111 * set:
3112 * set:
3112 <baseset+ []>
3113 <baseset+ []>
3113 $ try --optimize 'not ::2 and ::6'
3114 $ try --optimize 'not ::2 and ::6'
3114 (and
3115 (and
3115 (not
3116 (not
3116 (dagrangepre
3117 (dagrangepre
3117 ('symbol', '2')))
3118 ('symbol', '2')))
3118 (dagrangepre
3119 (dagrangepre
3119 ('symbol', '6')))
3120 ('symbol', '6')))
3120 * optimized:
3121 * optimized:
3121 (func
3122 (func
3122 ('symbol', 'only')
3123 ('symbol', 'only')
3123 (list
3124 (list
3124 ('symbol', '6')
3125 ('symbol', '6')
3125 ('symbol', '2'))
3126 ('symbol', '2'))
3126 define)
3127 define)
3127 * set:
3128 * set:
3128 <baseset+ [3, 4, 5, 6]>
3129 <baseset+ [3, 4, 5, 6]>
3129 3
3130 3
3130 4
3131 4
3131 5
3132 5
3132 6
3133 6
3133 $ try --optimize 'ancestors(6) and not ancestors(4)'
3134 $ try --optimize 'ancestors(6) and not ancestors(4)'
3134 (and
3135 (and
3135 (func
3136 (func
3136 ('symbol', 'ancestors')
3137 ('symbol', 'ancestors')
3137 ('symbol', '6'))
3138 ('symbol', '6'))
3138 (not
3139 (not
3139 (func
3140 (func
3140 ('symbol', 'ancestors')
3141 ('symbol', 'ancestors')
3141 ('symbol', '4'))))
3142 ('symbol', '4'))))
3142 * optimized:
3143 * optimized:
3143 (func
3144 (func
3144 ('symbol', 'only')
3145 ('symbol', 'only')
3145 (list
3146 (list
3146 ('symbol', '6')
3147 ('symbol', '6')
3147 ('symbol', '4'))
3148 ('symbol', '4'))
3148 define)
3149 define)
3149 * set:
3150 * set:
3150 <baseset+ [3, 5, 6]>
3151 <baseset+ [3, 5, 6]>
3151 3
3152 3
3152 5
3153 5
3153 6
3154 6
3154
3155
3155 no crash by empty group "()" while optimizing to "only()"
3156 no crash by empty group "()" while optimizing to "only()"
3156
3157
3157 $ try --optimize '::1 and ()'
3158 $ try --optimize '::1 and ()'
3158 (and
3159 (and
3159 (dagrangepre
3160 (dagrangepre
3160 ('symbol', '1'))
3161 ('symbol', '1'))
3161 (group
3162 (group
3162 None))
3163 None))
3163 * optimized:
3164 * optimized:
3164 (and
3165 (and
3165 None
3166 None
3166 (func
3167 (func
3167 ('symbol', 'ancestors')
3168 ('symbol', 'ancestors')
3168 ('symbol', '1')
3169 ('symbol', '1')
3169 define)
3170 define)
3170 define)
3171 define)
3171 hg: parse error: missing argument
3172 hg: parse error: missing argument
3172 [255]
3173 [255]
3173
3174
3174 optimization to only() works only if ancestors() takes only one argument
3175 optimization to only() works only if ancestors() takes only one argument
3175
3176
3176 $ hg debugrevspec -p optimized 'ancestors(6) - ancestors(4, 1)'
3177 $ hg debugrevspec -p optimized 'ancestors(6) - ancestors(4, 1)'
3177 * optimized:
3178 * optimized:
3178 (difference
3179 (difference
3179 (func
3180 (func
3180 ('symbol', 'ancestors')
3181 ('symbol', 'ancestors')
3181 ('symbol', '6')
3182 ('symbol', '6')
3182 define)
3183 define)
3183 (func
3184 (func
3184 ('symbol', 'ancestors')
3185 ('symbol', 'ancestors')
3185 (list
3186 (list
3186 ('symbol', '4')
3187 ('symbol', '4')
3187 ('symbol', '1'))
3188 ('symbol', '1'))
3188 any)
3189 any)
3189 define)
3190 define)
3190 0
3191 0
3191 1
3192 1
3192 3
3193 3
3193 5
3194 5
3194 6
3195 6
3195 $ hg debugrevspec -p optimized 'ancestors(6, 1) - ancestors(4)'
3196 $ hg debugrevspec -p optimized 'ancestors(6, 1) - ancestors(4)'
3196 * optimized:
3197 * optimized:
3197 (difference
3198 (difference
3198 (func
3199 (func
3199 ('symbol', 'ancestors')
3200 ('symbol', 'ancestors')
3200 (list
3201 (list
3201 ('symbol', '6')
3202 ('symbol', '6')
3202 ('symbol', '1'))
3203 ('symbol', '1'))
3203 define)
3204 define)
3204 (func
3205 (func
3205 ('symbol', 'ancestors')
3206 ('symbol', 'ancestors')
3206 ('symbol', '4')
3207 ('symbol', '4')
3207 any)
3208 any)
3208 define)
3209 define)
3209 5
3210 5
3210 6
3211 6
3211
3212
3212 optimization disabled if keyword arguments passed (because we're too lazy
3213 optimization disabled if keyword arguments passed (because we're too lazy
3213 to support it)
3214 to support it)
3214
3215
3215 $ hg debugrevspec -p optimized 'ancestors(set=6) - ancestors(set=4)'
3216 $ hg debugrevspec -p optimized 'ancestors(set=6) - ancestors(set=4)'
3216 * optimized:
3217 * optimized:
3217 (difference
3218 (difference
3218 (func
3219 (func
3219 ('symbol', 'ancestors')
3220 ('symbol', 'ancestors')
3220 (keyvalue
3221 (keyvalue
3221 ('symbol', 'set')
3222 ('symbol', 'set')
3222 ('symbol', '6'))
3223 ('symbol', '6'))
3223 define)
3224 define)
3224 (func
3225 (func
3225 ('symbol', 'ancestors')
3226 ('symbol', 'ancestors')
3226 (keyvalue
3227 (keyvalue
3227 ('symbol', 'set')
3228 ('symbol', 'set')
3228 ('symbol', '4'))
3229 ('symbol', '4'))
3229 any)
3230 any)
3230 define)
3231 define)
3231 3
3232 3
3232 5
3233 5
3233 6
3234 6
3234
3235
3235 invalid function call should not be optimized to only()
3236 invalid function call should not be optimized to only()
3236
3237
3237 $ log '"ancestors"(6) and not ancestors(4)'
3238 $ log '"ancestors"(6) and not ancestors(4)'
3238 hg: parse error: not a symbol
3239 hg: parse error: not a symbol
3239 [255]
3240 [255]
3240
3241
3241 $ log 'ancestors(6) and not "ancestors"(4)'
3242 $ log 'ancestors(6) and not "ancestors"(4)'
3242 hg: parse error: not a symbol
3243 hg: parse error: not a symbol
3243 [255]
3244 [255]
3244
3245
3245 we can use patterns when searching for tags
3246 we can use patterns when searching for tags
3246
3247
3247 $ log 'tag("1..*")'
3248 $ log 'tag("1..*")'
3248 abort: tag '1..*' does not exist!
3249 abort: tag '1..*' does not exist!
3249 [255]
3250 [255]
3250 $ log 'tag("re:1..*")'
3251 $ log 'tag("re:1..*")'
3251 6
3252 6
3252 $ log 'tag("re:[0-9].[0-9]")'
3253 $ log 'tag("re:[0-9].[0-9]")'
3253 6
3254 6
3254 $ log 'tag("literal:1.0")'
3255 $ log 'tag("literal:1.0")'
3255 6
3256 6
3256 $ log 'tag("re:0..*")'
3257 $ log 'tag("re:0..*")'
3257
3258
3258 $ log 'tag(unknown)'
3259 $ log 'tag(unknown)'
3259 abort: tag 'unknown' does not exist!
3260 abort: tag 'unknown' does not exist!
3260 [255]
3261 [255]
3261 $ log 'tag("re:unknown")'
3262 $ log 'tag("re:unknown")'
3262 $ log 'present(tag("unknown"))'
3263 $ log 'present(tag("unknown"))'
3263 $ log 'present(tag("re:unknown"))'
3264 $ log 'present(tag("re:unknown"))'
3264 $ log 'branch(unknown)'
3265 $ log 'branch(unknown)'
3265 abort: unknown revision 'unknown'!
3266 abort: unknown revision 'unknown'!
3266 [255]
3267 [255]
3267 $ log 'branch("literal:unknown")'
3268 $ log 'branch("literal:unknown")'
3268 abort: branch 'unknown' does not exist!
3269 abort: branch 'unknown' does not exist!
3269 [255]
3270 [255]
3270 $ log 'branch("re:unknown")'
3271 $ log 'branch("re:unknown")'
3271 $ log 'present(branch("unknown"))'
3272 $ log 'present(branch("unknown"))'
3272 $ log 'present(branch("re:unknown"))'
3273 $ log 'present(branch("re:unknown"))'
3273 $ log 'user(bob)'
3274 $ log 'user(bob)'
3274 2
3275 2
3275
3276
3276 $ log '4::8'
3277 $ log '4::8'
3277 4
3278 4
3278 8
3279 8
3279 $ log '4:8'
3280 $ log '4:8'
3280 4
3281 4
3281 5
3282 5
3282 6
3283 6
3283 7
3284 7
3284 8
3285 8
3285
3286
3286 $ log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
3287 $ log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
3287 4
3288 4
3288 2
3289 2
3289 5
3290 5
3290
3291
3291 $ log 'not 0 and 0:2'
3292 $ log 'not 0 and 0:2'
3292 1
3293 1
3293 2
3294 2
3294 $ log 'not 1 and 0:2'
3295 $ log 'not 1 and 0:2'
3295 0
3296 0
3296 2
3297 2
3297 $ log 'not 2 and 0:2'
3298 $ log 'not 2 and 0:2'
3298 0
3299 0
3299 1
3300 1
3300 $ log '(1 and 2)::'
3301 $ log '(1 and 2)::'
3301 $ log '(1 and 2):'
3302 $ log '(1 and 2):'
3302 $ log '(1 and 2):3'
3303 $ log '(1 and 2):3'
3303 $ log 'sort(head(), -rev)'
3304 $ log 'sort(head(), -rev)'
3304 9
3305 9
3305 7
3306 7
3306 6
3307 6
3307 5
3308 5
3308 4
3309 4
3309 3
3310 3
3310 2
3311 2
3311 1
3312 1
3312 0
3313 0
3313 $ log '4::8 - 8'
3314 $ log '4::8 - 8'
3314 4
3315 4
3315
3316
3316 matching() should preserve the order of the input set:
3317 matching() should preserve the order of the input set:
3317
3318
3318 $ log '(2 or 3 or 1) and matching(1 or 2 or 3)'
3319 $ log '(2 or 3 or 1) and matching(1 or 2 or 3)'
3319 2
3320 2
3320 3
3321 3
3321 1
3322 1
3322
3323
3323 $ log 'named("unknown")'
3324 $ log 'named("unknown")'
3324 abort: namespace 'unknown' does not exist!
3325 abort: namespace 'unknown' does not exist!
3325 [255]
3326 [255]
3326 $ log 'named("re:unknown")'
3327 $ log 'named("re:unknown")'
3327 abort: no namespace exists that match 'unknown'!
3328 abort: no namespace exists that match 'unknown'!
3328 [255]
3329 [255]
3329 $ log 'present(named("unknown"))'
3330 $ log 'present(named("unknown"))'
3330 $ log 'present(named("re:unknown"))'
3331 $ log 'present(named("re:unknown"))'
3331
3332
3332 $ log 'tag()'
3333 $ log 'tag()'
3333 6
3334 6
3334 $ log 'named("tags")'
3335 $ log 'named("tags")'
3335 6
3336 6
3336
3337
3337 issue2437
3338 issue2437
3338
3339
3339 $ log '3 and p1(5)'
3340 $ log '3 and p1(5)'
3340 3
3341 3
3341 $ log '4 and p2(6)'
3342 $ log '4 and p2(6)'
3342 4
3343 4
3343 $ log '1 and parents(:2)'
3344 $ log '1 and parents(:2)'
3344 1
3345 1
3345 $ log '2 and children(1:)'
3346 $ log '2 and children(1:)'
3346 2
3347 2
3347 $ log 'roots(all()) or roots(all())'
3348 $ log 'roots(all()) or roots(all())'
3348 0
3349 0
3349 $ hg debugrevspec 'roots(all()) or roots(all())'
3350 $ hg debugrevspec 'roots(all()) or roots(all())'
3350 0
3351 0
3351 $ log 'heads(branch(Γ©)) or heads(branch(Γ©))'
3352 $ log 'heads(branch(Γ©)) or heads(branch(Γ©))'
3352 9
3353 9
3353 $ log 'ancestors(8) and (heads(branch("-a-b-c-")) or heads(branch(Γ©)))'
3354 $ log 'ancestors(8) and (heads(branch("-a-b-c-")) or heads(branch(Γ©)))'
3354 4
3355 4
3355
3356
3356 issue2654: report a parse error if the revset was not completely parsed
3357 issue2654: report a parse error if the revset was not completely parsed
3357
3358
3358 $ log '1 OR 2'
3359 $ log '1 OR 2'
3359 hg: parse error at 2: invalid token
3360 hg: parse error at 2: invalid token
3360 [255]
3361 [255]
3361
3362
3362 or operator should preserve ordering:
3363 or operator should preserve ordering:
3363 $ log 'reverse(2::4) or tip'
3364 $ log 'reverse(2::4) or tip'
3364 4
3365 4
3365 2
3366 2
3366 9
3367 9
3367
3368
3368 parentrevspec
3369 parentrevspec
3369
3370
3370 $ log 'merge()^0'
3371 $ log 'merge()^0'
3371 6
3372 6
3372 $ log 'merge()^'
3373 $ log 'merge()^'
3373 5
3374 5
3374 $ log 'merge()^1'
3375 $ log 'merge()^1'
3375 5
3376 5
3376 $ log 'merge()^2'
3377 $ log 'merge()^2'
3377 4
3378 4
3378 $ log '(not merge())^2'
3379 $ log '(not merge())^2'
3379 $ log 'merge()^^'
3380 $ log 'merge()^^'
3380 3
3381 3
3381 $ log 'merge()^1^'
3382 $ log 'merge()^1^'
3382 3
3383 3
3383 $ log 'merge()^^^'
3384 $ log 'merge()^^^'
3384 1
3385 1
3385
3386
3386 $ hg debugrevspec -s '(merge() | 0)~-1'
3387 $ hg debugrevspec -s '(merge() | 0)~-1'
3387 * set:
3388 * set:
3388 <baseset+ [1, 7]>
3389 <baseset+ [1, 7]>
3389 1
3390 1
3390 7
3391 7
3391 $ log 'merge()~-1'
3392 $ log 'merge()~-1'
3392 7
3393 7
3393 $ log 'tip~-1'
3394 $ log 'tip~-1'
3394 $ log '(tip | merge())~-1'
3395 $ log '(tip | merge())~-1'
3395 7
3396 7
3396 $ log 'merge()~0'
3397 $ log 'merge()~0'
3397 6
3398 6
3398 $ log 'merge()~1'
3399 $ log 'merge()~1'
3399 5
3400 5
3400 $ log 'merge()~2'
3401 $ log 'merge()~2'
3401 3
3402 3
3402 $ log 'merge()~2^1'
3403 $ log 'merge()~2^1'
3403 1
3404 1
3404 $ log 'merge()~3'
3405 $ log 'merge()~3'
3405 1
3406 1
3406
3407
3407 $ log '(-3:tip)^'
3408 $ log '(-3:tip)^'
3408 4
3409 4
3409 6
3410 6
3410 8
3411 8
3411
3412
3412 $ log 'tip^foo'
3413 $ log 'tip^foo'
3413 hg: parse error: ^ expects a number 0, 1, or 2
3414 hg: parse error: ^ expects a number 0, 1, or 2
3414 [255]
3415 [255]
3415
3416
3416 $ log 'branchpoint()~-1'
3417 $ log 'branchpoint()~-1'
3417 abort: revision in set has more than one child!
3418 abort: revision in set has more than one child!
3418 [255]
3419 [255]
3419
3420
3420 Bogus function gets suggestions
3421 Bogus function gets suggestions
3421 $ log 'add()'
3422 $ log 'add()'
3422 hg: parse error: unknown identifier: add
3423 hg: parse error: unknown identifier: add
3423 (did you mean adds?)
3424 (did you mean adds?)
3424 [255]
3425 [255]
3425 $ log 'added()'
3426 $ log 'added()'
3426 hg: parse error: unknown identifier: added
3427 hg: parse error: unknown identifier: added
3427 (did you mean adds?)
3428 (did you mean adds?)
3428 [255]
3429 [255]
3429 $ log 'remo()'
3430 $ log 'remo()'
3430 hg: parse error: unknown identifier: remo
3431 hg: parse error: unknown identifier: remo
3431 (did you mean one of remote, removes?)
3432 (did you mean one of remote, removes?)
3432 [255]
3433 [255]
3433 $ log 'babar()'
3434 $ log 'babar()'
3434 hg: parse error: unknown identifier: babar
3435 hg: parse error: unknown identifier: babar
3435 [255]
3436 [255]
3436
3437
3437 Bogus function with a similar internal name doesn't suggest the internal name
3438 Bogus function with a similar internal name doesn't suggest the internal name
3438 $ log 'matches()'
3439 $ log 'matches()'
3439 hg: parse error: unknown identifier: matches
3440 hg: parse error: unknown identifier: matches
3440 (did you mean matching?)
3441 (did you mean matching?)
3441 [255]
3442 [255]
3442
3443
3443 Undocumented functions aren't suggested as similar either
3444 Undocumented functions aren't suggested as similar either
3444 $ log 'tagged2()'
3445 $ log 'tagged2()'
3445 hg: parse error: unknown identifier: tagged2
3446 hg: parse error: unknown identifier: tagged2
3446 [255]
3447 [255]
3447
3448
3448 multiple revspecs
3449 multiple revspecs
3449
3450
3450 $ hg log -r 'tip~1:tip' -r 'tip~2:tip~1' --template '{rev}\n'
3451 $ hg log -r 'tip~1:tip' -r 'tip~2:tip~1' --template '{rev}\n'
3451 8
3452 8
3452 9
3453 9
3453 4
3454 4
3454 5
3455 5
3455 6
3456 6
3456 7
3457 7
3457
3458
3458 test usage in revpair (with "+")
3459 test usage in revpair (with "+")
3459
3460
3460 (real pair)
3461 (real pair)
3461
3462
3462 $ hg diff -r 'tip^^' -r 'tip'
3463 $ hg diff -r 'tip^^' -r 'tip'
3463 diff -r 2326846efdab -r 24286f4ae135 .hgtags
3464 diff -r 2326846efdab -r 24286f4ae135 .hgtags
3464 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3465 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3465 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
3466 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
3466 @@ -0,0 +1,1 @@
3467 @@ -0,0 +1,1 @@
3467 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
3468 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
3468 $ hg diff -r 'tip^^::tip'
3469 $ hg diff -r 'tip^^::tip'
3469 diff -r 2326846efdab -r 24286f4ae135 .hgtags
3470 diff -r 2326846efdab -r 24286f4ae135 .hgtags
3470 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3471 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3471 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
3472 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
3472 @@ -0,0 +1,1 @@
3473 @@ -0,0 +1,1 @@
3473 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
3474 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
3474
3475
3475 (single rev)
3476 (single rev)
3476
3477
3477 $ hg diff -r 'tip^' -r 'tip^'
3478 $ hg diff -r 'tip^' -r 'tip^'
3478 $ hg diff -r 'tip^:tip^'
3479 $ hg diff -r 'tip^:tip^'
3479
3480
3480 (single rev that does not looks like a range)
3481 (single rev that does not looks like a range)
3481
3482
3482 $ hg diff -r 'tip^::tip^ or tip^'
3483 $ hg diff -r 'tip^::tip^ or tip^'
3483 diff -r d5d0dcbdc4d9 .hgtags
3484 diff -r d5d0dcbdc4d9 .hgtags
3484 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3485 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3485 +++ b/.hgtags * (glob)
3486 +++ b/.hgtags * (glob)
3486 @@ -0,0 +1,1 @@
3487 @@ -0,0 +1,1 @@
3487 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
3488 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
3488 $ hg diff -r 'tip^ or tip^'
3489 $ hg diff -r 'tip^ or tip^'
3489 diff -r d5d0dcbdc4d9 .hgtags
3490 diff -r d5d0dcbdc4d9 .hgtags
3490 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3491 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3491 +++ b/.hgtags * (glob)
3492 +++ b/.hgtags * (glob)
3492 @@ -0,0 +1,1 @@
3493 @@ -0,0 +1,1 @@
3493 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
3494 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
3494
3495
3495 (no rev)
3496 (no rev)
3496
3497
3497 $ hg diff -r 'author("babar") or author("celeste")'
3498 $ hg diff -r 'author("babar") or author("celeste")'
3498 abort: empty revision range
3499 abort: empty revision range
3499 [255]
3500 [255]
3500
3501
3501 aliases:
3502 aliases:
3502
3503
3503 $ echo '[revsetalias]' >> .hg/hgrc
3504 $ echo '[revsetalias]' >> .hg/hgrc
3504 $ echo 'm = merge()' >> .hg/hgrc
3505 $ echo 'm = merge()' >> .hg/hgrc
3505 (revset aliases can override builtin revsets)
3506 (revset aliases can override builtin revsets)
3506 $ echo 'p2($1) = p1($1)' >> .hg/hgrc
3507 $ echo 'p2($1) = p1($1)' >> .hg/hgrc
3507 $ echo 'sincem = descendants(m)' >> .hg/hgrc
3508 $ echo 'sincem = descendants(m)' >> .hg/hgrc
3508 $ echo 'd($1) = reverse(sort($1, date))' >> .hg/hgrc
3509 $ echo 'd($1) = reverse(sort($1, date))' >> .hg/hgrc
3509 $ echo 'rs(ARG1, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
3510 $ echo 'rs(ARG1, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
3510 $ echo 'rs4(ARG1, ARGA, ARGB, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
3511 $ echo 'rs4(ARG1, ARGA, ARGB, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
3511
3512
3512 $ try m
3513 $ try m
3513 ('symbol', 'm')
3514 ('symbol', 'm')
3514 * expanded:
3515 * expanded:
3515 (func
3516 (func
3516 ('symbol', 'merge')
3517 ('symbol', 'merge')
3517 None)
3518 None)
3518 * set:
3519 * set:
3519 <filteredset
3520 <filteredset
3520 <fullreposet+ 0:10>,
3521 <fullreposet+ 0:10>,
3521 <merge>>
3522 <merge>>
3522 6
3523 6
3523
3524
3524 $ HGPLAIN=1
3525 $ HGPLAIN=1
3525 $ export HGPLAIN
3526 $ export HGPLAIN
3526 $ try m
3527 $ try m
3527 ('symbol', 'm')
3528 ('symbol', 'm')
3528 abort: unknown revision 'm'!
3529 abort: unknown revision 'm'!
3529 [255]
3530 [255]
3530
3531
3531 $ HGPLAINEXCEPT=revsetalias
3532 $ HGPLAINEXCEPT=revsetalias
3532 $ export HGPLAINEXCEPT
3533 $ export HGPLAINEXCEPT
3533 $ try m
3534 $ try m
3534 ('symbol', 'm')
3535 ('symbol', 'm')
3535 * expanded:
3536 * expanded:
3536 (func
3537 (func
3537 ('symbol', 'merge')
3538 ('symbol', 'merge')
3538 None)
3539 None)
3539 * set:
3540 * set:
3540 <filteredset
3541 <filteredset
3541 <fullreposet+ 0:10>,
3542 <fullreposet+ 0:10>,
3542 <merge>>
3543 <merge>>
3543 6
3544 6
3544
3545
3545 $ unset HGPLAIN
3546 $ unset HGPLAIN
3546 $ unset HGPLAINEXCEPT
3547 $ unset HGPLAINEXCEPT
3547
3548
3548 $ try 'p2(.)'
3549 $ try 'p2(.)'
3549 (func
3550 (func
3550 ('symbol', 'p2')
3551 ('symbol', 'p2')
3551 ('symbol', '.'))
3552 ('symbol', '.'))
3552 * expanded:
3553 * expanded:
3553 (func
3554 (func
3554 ('symbol', 'p1')
3555 ('symbol', 'p1')
3555 ('symbol', '.'))
3556 ('symbol', '.'))
3556 * set:
3557 * set:
3557 <baseset+ [8]>
3558 <baseset+ [8]>
3558 8
3559 8
3559
3560
3560 $ HGPLAIN=1
3561 $ HGPLAIN=1
3561 $ export HGPLAIN
3562 $ export HGPLAIN
3562 $ try 'p2(.)'
3563 $ try 'p2(.)'
3563 (func
3564 (func
3564 ('symbol', 'p2')
3565 ('symbol', 'p2')
3565 ('symbol', '.'))
3566 ('symbol', '.'))
3566 * set:
3567 * set:
3567 <baseset+ []>
3568 <baseset+ []>
3568
3569
3569 $ HGPLAINEXCEPT=revsetalias
3570 $ HGPLAINEXCEPT=revsetalias
3570 $ export HGPLAINEXCEPT
3571 $ export HGPLAINEXCEPT
3571 $ try 'p2(.)'
3572 $ try 'p2(.)'
3572 (func
3573 (func
3573 ('symbol', 'p2')
3574 ('symbol', 'p2')
3574 ('symbol', '.'))
3575 ('symbol', '.'))
3575 * expanded:
3576 * expanded:
3576 (func
3577 (func
3577 ('symbol', 'p1')
3578 ('symbol', 'p1')
3578 ('symbol', '.'))
3579 ('symbol', '.'))
3579 * set:
3580 * set:
3580 <baseset+ [8]>
3581 <baseset+ [8]>
3581 8
3582 8
3582
3583
3583 $ unset HGPLAIN
3584 $ unset HGPLAIN
3584 $ unset HGPLAINEXCEPT
3585 $ unset HGPLAINEXCEPT
3585
3586
3586 test alias recursion
3587 test alias recursion
3587
3588
3588 $ try sincem
3589 $ try sincem
3589 ('symbol', 'sincem')
3590 ('symbol', 'sincem')
3590 * expanded:
3591 * expanded:
3591 (func
3592 (func
3592 ('symbol', 'descendants')
3593 ('symbol', 'descendants')
3593 (func
3594 (func
3594 ('symbol', 'merge')
3595 ('symbol', 'merge')
3595 None))
3596 None))
3596 * set:
3597 * set:
3597 <generatorset+>
3598 <generatorset+>
3598 6
3599 6
3599 7
3600 7
3600
3601
3601 test infinite recursion
3602 test infinite recursion
3602
3603
3603 $ echo 'recurse1 = recurse2' >> .hg/hgrc
3604 $ echo 'recurse1 = recurse2' >> .hg/hgrc
3604 $ echo 'recurse2 = recurse1' >> .hg/hgrc
3605 $ echo 'recurse2 = recurse1' >> .hg/hgrc
3605 $ try recurse1
3606 $ try recurse1
3606 ('symbol', 'recurse1')
3607 ('symbol', 'recurse1')
3607 hg: parse error: infinite expansion of revset alias "recurse1" detected
3608 hg: parse error: infinite expansion of revset alias "recurse1" detected
3608 [255]
3609 [255]
3609
3610
3610 $ echo 'level1($1, $2) = $1 or $2' >> .hg/hgrc
3611 $ echo 'level1($1, $2) = $1 or $2' >> .hg/hgrc
3611 $ echo 'level2($1, $2) = level1($2, $1)' >> .hg/hgrc
3612 $ echo 'level2($1, $2) = level1($2, $1)' >> .hg/hgrc
3612 $ try "level2(level1(1, 2), 3)"
3613 $ try "level2(level1(1, 2), 3)"
3613 (func
3614 (func
3614 ('symbol', 'level2')
3615 ('symbol', 'level2')
3615 (list
3616 (list
3616 (func
3617 (func
3617 ('symbol', 'level1')
3618 ('symbol', 'level1')
3618 (list
3619 (list
3619 ('symbol', '1')
3620 ('symbol', '1')
3620 ('symbol', '2')))
3621 ('symbol', '2')))
3621 ('symbol', '3')))
3622 ('symbol', '3')))
3622 * expanded:
3623 * expanded:
3623 (or
3624 (or
3624 (list
3625 (list
3625 ('symbol', '3')
3626 ('symbol', '3')
3626 (or
3627 (or
3627 (list
3628 (list
3628 ('symbol', '1')
3629 ('symbol', '1')
3629 ('symbol', '2')))))
3630 ('symbol', '2')))))
3630 * set:
3631 * set:
3631 <addset
3632 <addset
3632 <baseset [3]>,
3633 <baseset [3]>,
3633 <baseset [1, 2]>>
3634 <baseset [1, 2]>>
3634 3
3635 3
3635 1
3636 1
3636 2
3637 2
3637
3638
3638 test nesting and variable passing
3639 test nesting and variable passing
3639
3640
3640 $ echo 'nested($1) = nested2($1)' >> .hg/hgrc
3641 $ echo 'nested($1) = nested2($1)' >> .hg/hgrc
3641 $ echo 'nested2($1) = nested3($1)' >> .hg/hgrc
3642 $ echo 'nested2($1) = nested3($1)' >> .hg/hgrc
3642 $ echo 'nested3($1) = max($1)' >> .hg/hgrc
3643 $ echo 'nested3($1) = max($1)' >> .hg/hgrc
3643 $ try 'nested(2:5)'
3644 $ try 'nested(2:5)'
3644 (func
3645 (func
3645 ('symbol', 'nested')
3646 ('symbol', 'nested')
3646 (range
3647 (range
3647 ('symbol', '2')
3648 ('symbol', '2')
3648 ('symbol', '5')))
3649 ('symbol', '5')))
3649 * expanded:
3650 * expanded:
3650 (func
3651 (func
3651 ('symbol', 'max')
3652 ('symbol', 'max')
3652 (range
3653 (range
3653 ('symbol', '2')
3654 ('symbol', '2')
3654 ('symbol', '5')))
3655 ('symbol', '5')))
3655 * set:
3656 * set:
3656 <baseset
3657 <baseset
3657 <max
3658 <max
3658 <fullreposet+ 0:10>,
3659 <fullreposet+ 0:10>,
3659 <spanset+ 2:6>>>
3660 <spanset+ 2:6>>>
3660 5
3661 5
3661
3662
3662 test chained `or` operations are flattened at parsing phase
3663 test chained `or` operations are flattened at parsing phase
3663
3664
3664 $ echo 'chainedorops($1, $2, $3) = $1|$2|$3' >> .hg/hgrc
3665 $ echo 'chainedorops($1, $2, $3) = $1|$2|$3' >> .hg/hgrc
3665 $ try 'chainedorops(0:1, 1:2, 2:3)'
3666 $ try 'chainedorops(0:1, 1:2, 2:3)'
3666 (func
3667 (func
3667 ('symbol', 'chainedorops')
3668 ('symbol', 'chainedorops')
3668 (list
3669 (list
3669 (range
3670 (range
3670 ('symbol', '0')
3671 ('symbol', '0')
3671 ('symbol', '1'))
3672 ('symbol', '1'))
3672 (range
3673 (range
3673 ('symbol', '1')
3674 ('symbol', '1')
3674 ('symbol', '2'))
3675 ('symbol', '2'))
3675 (range
3676 (range
3676 ('symbol', '2')
3677 ('symbol', '2')
3677 ('symbol', '3'))))
3678 ('symbol', '3'))))
3678 * expanded:
3679 * expanded:
3679 (or
3680 (or
3680 (list
3681 (list
3681 (range
3682 (range
3682 ('symbol', '0')
3683 ('symbol', '0')
3683 ('symbol', '1'))
3684 ('symbol', '1'))
3684 (range
3685 (range
3685 ('symbol', '1')
3686 ('symbol', '1')
3686 ('symbol', '2'))
3687 ('symbol', '2'))
3687 (range
3688 (range
3688 ('symbol', '2')
3689 ('symbol', '2')
3689 ('symbol', '3'))))
3690 ('symbol', '3'))))
3690 * set:
3691 * set:
3691 <addset
3692 <addset
3692 <spanset+ 0:2>,
3693 <spanset+ 0:2>,
3693 <addset
3694 <addset
3694 <spanset+ 1:3>,
3695 <spanset+ 1:3>,
3695 <spanset+ 2:4>>>
3696 <spanset+ 2:4>>>
3696 0
3697 0
3697 1
3698 1
3698 2
3699 2
3699 3
3700 3
3700
3701
3701 test variable isolation, variable placeholders are rewritten as string
3702 test variable isolation, variable placeholders are rewritten as string
3702 then parsed and matched again as string. Check they do not leak too
3703 then parsed and matched again as string. Check they do not leak too
3703 far away.
3704 far away.
3704
3705
3705 $ echo 'injectparamasstring = max("$1")' >> .hg/hgrc
3706 $ echo 'injectparamasstring = max("$1")' >> .hg/hgrc
3706 $ echo 'callinjection($1) = descendants(injectparamasstring)' >> .hg/hgrc
3707 $ echo 'callinjection($1) = descendants(injectparamasstring)' >> .hg/hgrc
3707 $ try 'callinjection(2:5)'
3708 $ try 'callinjection(2:5)'
3708 (func
3709 (func
3709 ('symbol', 'callinjection')
3710 ('symbol', 'callinjection')
3710 (range
3711 (range
3711 ('symbol', '2')
3712 ('symbol', '2')
3712 ('symbol', '5')))
3713 ('symbol', '5')))
3713 * expanded:
3714 * expanded:
3714 (func
3715 (func
3715 ('symbol', 'descendants')
3716 ('symbol', 'descendants')
3716 (func
3717 (func
3717 ('symbol', 'max')
3718 ('symbol', 'max')
3718 ('string', '$1')))
3719 ('string', '$1')))
3719 abort: unknown revision '$1'!
3720 abort: unknown revision '$1'!
3720 [255]
3721 [255]
3721
3722
3722 test scope of alias expansion: 'universe' is expanded prior to 'shadowall(0)',
3723 test scope of alias expansion: 'universe' is expanded prior to 'shadowall(0)',
3723 but 'all()' should never be substituted to '0()'.
3724 but 'all()' should never be substituted to '0()'.
3724
3725
3725 $ echo 'universe = all()' >> .hg/hgrc
3726 $ echo 'universe = all()' >> .hg/hgrc
3726 $ echo 'shadowall(all) = all and universe' >> .hg/hgrc
3727 $ echo 'shadowall(all) = all and universe' >> .hg/hgrc
3727 $ try 'shadowall(0)'
3728 $ try 'shadowall(0)'
3728 (func
3729 (func
3729 ('symbol', 'shadowall')
3730 ('symbol', 'shadowall')
3730 ('symbol', '0'))
3731 ('symbol', '0'))
3731 * expanded:
3732 * expanded:
3732 (and
3733 (and
3733 ('symbol', '0')
3734 ('symbol', '0')
3734 (func
3735 (func
3735 ('symbol', 'all')
3736 ('symbol', 'all')
3736 None))
3737 None))
3737 * set:
3738 * set:
3738 <filteredset
3739 <filteredset
3739 <baseset [0]>,
3740 <baseset [0]>,
3740 <spanset+ 0:10>>
3741 <spanset+ 0:10>>
3741 0
3742 0
3742
3743
3743 test unknown reference:
3744 test unknown reference:
3744
3745
3745 $ try "unknownref(0)" --config 'revsetalias.unknownref($1)=$1:$2'
3746 $ try "unknownref(0)" --config 'revsetalias.unknownref($1)=$1:$2'
3746 (func
3747 (func
3747 ('symbol', 'unknownref')
3748 ('symbol', 'unknownref')
3748 ('symbol', '0'))
3749 ('symbol', '0'))
3749 abort: bad definition of revset alias "unknownref": invalid symbol '$2'
3750 abort: bad definition of revset alias "unknownref": invalid symbol '$2'
3750 [255]
3751 [255]
3751
3752
3752 $ hg debugrevspec --debug --config revsetalias.anotherbadone='branch(' "tip"
3753 $ hg debugrevspec --debug --config revsetalias.anotherbadone='branch(' "tip"
3753 ('symbol', 'tip')
3754 ('symbol', 'tip')
3754 warning: bad definition of revset alias "anotherbadone": at 7: not a prefix: end
3755 warning: bad definition of revset alias "anotherbadone": at 7: not a prefix: end
3755 * set:
3756 * set:
3756 <baseset [9]>
3757 <baseset [9]>
3757 9
3758 9
3758
3759
3759 $ try 'tip'
3760 $ try 'tip'
3760 ('symbol', 'tip')
3761 ('symbol', 'tip')
3761 * set:
3762 * set:
3762 <baseset [9]>
3763 <baseset [9]>
3763 9
3764 9
3764
3765
3765 $ hg debugrevspec --debug --config revsetalias.'bad name'='tip' "tip"
3766 $ hg debugrevspec --debug --config revsetalias.'bad name'='tip' "tip"
3766 ('symbol', 'tip')
3767 ('symbol', 'tip')
3767 warning: bad declaration of revset alias "bad name": at 4: invalid token
3768 warning: bad declaration of revset alias "bad name": at 4: invalid token
3768 * set:
3769 * set:
3769 <baseset [9]>
3770 <baseset [9]>
3770 9
3771 9
3771 $ echo 'strictreplacing($1, $10) = $10 or desc("$1")' >> .hg/hgrc
3772 $ echo 'strictreplacing($1, $10) = $10 or desc("$1")' >> .hg/hgrc
3772 $ try 'strictreplacing("foo", tip)'
3773 $ try 'strictreplacing("foo", tip)'
3773 (func
3774 (func
3774 ('symbol', 'strictreplacing')
3775 ('symbol', 'strictreplacing')
3775 (list
3776 (list
3776 ('string', 'foo')
3777 ('string', 'foo')
3777 ('symbol', 'tip')))
3778 ('symbol', 'tip')))
3778 * expanded:
3779 * expanded:
3779 (or
3780 (or
3780 (list
3781 (list
3781 ('symbol', 'tip')
3782 ('symbol', 'tip')
3782 (func
3783 (func
3783 ('symbol', 'desc')
3784 ('symbol', 'desc')
3784 ('string', '$1'))))
3785 ('string', '$1'))))
3785 * set:
3786 * set:
3786 <addset
3787 <addset
3787 <baseset [9]>,
3788 <baseset [9]>,
3788 <filteredset
3789 <filteredset
3789 <fullreposet+ 0:10>,
3790 <fullreposet+ 0:10>,
3790 <desc '$1'>>>
3791 <desc '$1'>>>
3791 9
3792 9
3792
3793
3793 $ try 'd(2:5)'
3794 $ try 'd(2:5)'
3794 (func
3795 (func
3795 ('symbol', 'd')
3796 ('symbol', 'd')
3796 (range
3797 (range
3797 ('symbol', '2')
3798 ('symbol', '2')
3798 ('symbol', '5')))
3799 ('symbol', '5')))
3799 * expanded:
3800 * expanded:
3800 (func
3801 (func
3801 ('symbol', 'reverse')
3802 ('symbol', 'reverse')
3802 (func
3803 (func
3803 ('symbol', 'sort')
3804 ('symbol', 'sort')
3804 (list
3805 (list
3805 (range
3806 (range
3806 ('symbol', '2')
3807 ('symbol', '2')
3807 ('symbol', '5'))
3808 ('symbol', '5'))
3808 ('symbol', 'date'))))
3809 ('symbol', 'date'))))
3809 * set:
3810 * set:
3810 <baseset [4, 5, 3, 2]>
3811 <baseset [4, 5, 3, 2]>
3811 4
3812 4
3812 5
3813 5
3813 3
3814 3
3814 2
3815 2
3815 $ try 'rs(2 or 3, date)'
3816 $ try 'rs(2 or 3, date)'
3816 (func
3817 (func
3817 ('symbol', 'rs')
3818 ('symbol', 'rs')
3818 (list
3819 (list
3819 (or
3820 (or
3820 (list
3821 (list
3821 ('symbol', '2')
3822 ('symbol', '2')
3822 ('symbol', '3')))
3823 ('symbol', '3')))
3823 ('symbol', 'date')))
3824 ('symbol', 'date')))
3824 * expanded:
3825 * expanded:
3825 (func
3826 (func
3826 ('symbol', 'reverse')
3827 ('symbol', 'reverse')
3827 (func
3828 (func
3828 ('symbol', 'sort')
3829 ('symbol', 'sort')
3829 (list
3830 (list
3830 (or
3831 (or
3831 (list
3832 (list
3832 ('symbol', '2')
3833 ('symbol', '2')
3833 ('symbol', '3')))
3834 ('symbol', '3')))
3834 ('symbol', 'date'))))
3835 ('symbol', 'date'))))
3835 * set:
3836 * set:
3836 <baseset [3, 2]>
3837 <baseset [3, 2]>
3837 3
3838 3
3838 2
3839 2
3839 $ try 'rs()'
3840 $ try 'rs()'
3840 (func
3841 (func
3841 ('symbol', 'rs')
3842 ('symbol', 'rs')
3842 None)
3843 None)
3843 hg: parse error: invalid number of arguments: 0
3844 hg: parse error: invalid number of arguments: 0
3844 [255]
3845 [255]
3845 $ try 'rs(2)'
3846 $ try 'rs(2)'
3846 (func
3847 (func
3847 ('symbol', 'rs')
3848 ('symbol', 'rs')
3848 ('symbol', '2'))
3849 ('symbol', '2'))
3849 hg: parse error: invalid number of arguments: 1
3850 hg: parse error: invalid number of arguments: 1
3850 [255]
3851 [255]
3851 $ try 'rs(2, data, 7)'
3852 $ try 'rs(2, data, 7)'
3852 (func
3853 (func
3853 ('symbol', 'rs')
3854 ('symbol', 'rs')
3854 (list
3855 (list
3855 ('symbol', '2')
3856 ('symbol', '2')
3856 ('symbol', 'data')
3857 ('symbol', 'data')
3857 ('symbol', '7')))
3858 ('symbol', '7')))
3858 hg: parse error: invalid number of arguments: 3
3859 hg: parse error: invalid number of arguments: 3
3859 [255]
3860 [255]
3860 $ try 'rs4(2 or 3, x, x, date)'
3861 $ try 'rs4(2 or 3, x, x, date)'
3861 (func
3862 (func
3862 ('symbol', 'rs4')
3863 ('symbol', 'rs4')
3863 (list
3864 (list
3864 (or
3865 (or
3865 (list
3866 (list
3866 ('symbol', '2')
3867 ('symbol', '2')
3867 ('symbol', '3')))
3868 ('symbol', '3')))
3868 ('symbol', 'x')
3869 ('symbol', 'x')
3869 ('symbol', 'x')
3870 ('symbol', 'x')
3870 ('symbol', 'date')))
3871 ('symbol', 'date')))
3871 * expanded:
3872 * expanded:
3872 (func
3873 (func
3873 ('symbol', 'reverse')
3874 ('symbol', 'reverse')
3874 (func
3875 (func
3875 ('symbol', 'sort')
3876 ('symbol', 'sort')
3876 (list
3877 (list
3877 (or
3878 (or
3878 (list
3879 (list
3879 ('symbol', '2')
3880 ('symbol', '2')
3880 ('symbol', '3')))
3881 ('symbol', '3')))
3881 ('symbol', 'date'))))
3882 ('symbol', 'date'))))
3882 * set:
3883 * set:
3883 <baseset [3, 2]>
3884 <baseset [3, 2]>
3884 3
3885 3
3885 2
3886 2
3886
3887
3887 issue4553: check that revset aliases override existing hash prefix
3888 issue4553: check that revset aliases override existing hash prefix
3888
3889
3889 $ hg log -qr e
3890 $ hg log -qr e
3890 6:e0cc66ef77e8
3891 6:e0cc66ef77e8
3891
3892
3892 $ hg log -qr e --config revsetalias.e="all()"
3893 $ hg log -qr e --config revsetalias.e="all()"
3893 0:2785f51eece5
3894 0:2785f51eece5
3894 1:d75937da8da0
3895 1:d75937da8da0
3895 2:5ed5505e9f1c
3896 2:5ed5505e9f1c
3896 3:8528aa5637f2
3897 3:8528aa5637f2
3897 4:2326846efdab
3898 4:2326846efdab
3898 5:904fa392b941
3899 5:904fa392b941
3899 6:e0cc66ef77e8
3900 6:e0cc66ef77e8
3900 7:013af1973af4
3901 7:013af1973af4
3901 8:d5d0dcbdc4d9
3902 8:d5d0dcbdc4d9
3902 9:24286f4ae135
3903 9:24286f4ae135
3903
3904
3904 $ hg log -qr e: --config revsetalias.e="0"
3905 $ hg log -qr e: --config revsetalias.e="0"
3905 0:2785f51eece5
3906 0:2785f51eece5
3906 1:d75937da8da0
3907 1:d75937da8da0
3907 2:5ed5505e9f1c
3908 2:5ed5505e9f1c
3908 3:8528aa5637f2
3909 3:8528aa5637f2
3909 4:2326846efdab
3910 4:2326846efdab
3910 5:904fa392b941
3911 5:904fa392b941
3911 6:e0cc66ef77e8
3912 6:e0cc66ef77e8
3912 7:013af1973af4
3913 7:013af1973af4
3913 8:d5d0dcbdc4d9
3914 8:d5d0dcbdc4d9
3914 9:24286f4ae135
3915 9:24286f4ae135
3915
3916
3916 $ hg log -qr :e --config revsetalias.e="9"
3917 $ hg log -qr :e --config revsetalias.e="9"
3917 0:2785f51eece5
3918 0:2785f51eece5
3918 1:d75937da8da0
3919 1:d75937da8da0
3919 2:5ed5505e9f1c
3920 2:5ed5505e9f1c
3920 3:8528aa5637f2
3921 3:8528aa5637f2
3921 4:2326846efdab
3922 4:2326846efdab
3922 5:904fa392b941
3923 5:904fa392b941
3923 6:e0cc66ef77e8
3924 6:e0cc66ef77e8
3924 7:013af1973af4
3925 7:013af1973af4
3925 8:d5d0dcbdc4d9
3926 8:d5d0dcbdc4d9
3926 9:24286f4ae135
3927 9:24286f4ae135
3927
3928
3928 $ hg log -qr e:
3929 $ hg log -qr e:
3929 6:e0cc66ef77e8
3930 6:e0cc66ef77e8
3930 7:013af1973af4
3931 7:013af1973af4
3931 8:d5d0dcbdc4d9
3932 8:d5d0dcbdc4d9
3932 9:24286f4ae135
3933 9:24286f4ae135
3933
3934
3934 $ hg log -qr :e
3935 $ hg log -qr :e
3935 0:2785f51eece5
3936 0:2785f51eece5
3936 1:d75937da8da0
3937 1:d75937da8da0
3937 2:5ed5505e9f1c
3938 2:5ed5505e9f1c
3938 3:8528aa5637f2
3939 3:8528aa5637f2
3939 4:2326846efdab
3940 4:2326846efdab
3940 5:904fa392b941
3941 5:904fa392b941
3941 6:e0cc66ef77e8
3942 6:e0cc66ef77e8
3942
3943
3943 issue2549 - correct optimizations
3944 issue2549 - correct optimizations
3944
3945
3945 $ try 'limit(1 or 2 or 3, 2) and not 2'
3946 $ try 'limit(1 or 2 or 3, 2) and not 2'
3946 (and
3947 (and
3947 (func
3948 (func
3948 ('symbol', 'limit')
3949 ('symbol', 'limit')
3949 (list
3950 (list
3950 (or
3951 (or
3951 (list
3952 (list
3952 ('symbol', '1')
3953 ('symbol', '1')
3953 ('symbol', '2')
3954 ('symbol', '2')
3954 ('symbol', '3')))
3955 ('symbol', '3')))
3955 ('symbol', '2')))
3956 ('symbol', '2')))
3956 (not
3957 (not
3957 ('symbol', '2')))
3958 ('symbol', '2')))
3958 * set:
3959 * set:
3959 <filteredset
3960 <filteredset
3960 <baseset [1, 2]>,
3961 <baseset [1, 2]>,
3961 <not
3962 <not
3962 <baseset [2]>>>
3963 <baseset [2]>>>
3963 1
3964 1
3964 $ try 'max(1 or 2) and not 2'
3965 $ try 'max(1 or 2) and not 2'
3965 (and
3966 (and
3966 (func
3967 (func
3967 ('symbol', 'max')
3968 ('symbol', 'max')
3968 (or
3969 (or
3969 (list
3970 (list
3970 ('symbol', '1')
3971 ('symbol', '1')
3971 ('symbol', '2'))))
3972 ('symbol', '2'))))
3972 (not
3973 (not
3973 ('symbol', '2')))
3974 ('symbol', '2')))
3974 * set:
3975 * set:
3975 <filteredset
3976 <filteredset
3976 <baseset
3977 <baseset
3977 <max
3978 <max
3978 <fullreposet+ 0:10>,
3979 <fullreposet+ 0:10>,
3979 <baseset [1, 2]>>>,
3980 <baseset [1, 2]>>>,
3980 <not
3981 <not
3981 <baseset [2]>>>
3982 <baseset [2]>>>
3982 $ try 'min(1 or 2) and not 1'
3983 $ try 'min(1 or 2) and not 1'
3983 (and
3984 (and
3984 (func
3985 (func
3985 ('symbol', 'min')
3986 ('symbol', 'min')
3986 (or
3987 (or
3987 (list
3988 (list
3988 ('symbol', '1')
3989 ('symbol', '1')
3989 ('symbol', '2'))))
3990 ('symbol', '2'))))
3990 (not
3991 (not
3991 ('symbol', '1')))
3992 ('symbol', '1')))
3992 * set:
3993 * set:
3993 <filteredset
3994 <filteredset
3994 <baseset
3995 <baseset
3995 <min
3996 <min
3996 <fullreposet+ 0:10>,
3997 <fullreposet+ 0:10>,
3997 <baseset [1, 2]>>>,
3998 <baseset [1, 2]>>>,
3998 <not
3999 <not
3999 <baseset [1]>>>
4000 <baseset [1]>>>
4000 $ try 'last(1 or 2, 1) and not 2'
4001 $ try 'last(1 or 2, 1) and not 2'
4001 (and
4002 (and
4002 (func
4003 (func
4003 ('symbol', 'last')
4004 ('symbol', 'last')
4004 (list
4005 (list
4005 (or
4006 (or
4006 (list
4007 (list
4007 ('symbol', '1')
4008 ('symbol', '1')
4008 ('symbol', '2')))
4009 ('symbol', '2')))
4009 ('symbol', '1')))
4010 ('symbol', '1')))
4010 (not
4011 (not
4011 ('symbol', '2')))
4012 ('symbol', '2')))
4012 * set:
4013 * set:
4013 <filteredset
4014 <filteredset
4014 <baseset [2]>,
4015 <baseset [2]>,
4015 <not
4016 <not
4016 <baseset [2]>>>
4017 <baseset [2]>>>
4017
4018
4018 issue4289 - ordering of built-ins
4019 issue4289 - ordering of built-ins
4019 $ hg log -M -q -r 3:2
4020 $ hg log -M -q -r 3:2
4020 3:8528aa5637f2
4021 3:8528aa5637f2
4021 2:5ed5505e9f1c
4022 2:5ed5505e9f1c
4022
4023
4023 test revsets started with 40-chars hash (issue3669)
4024 test revsets started with 40-chars hash (issue3669)
4024
4025
4025 $ ISSUE3669_TIP=`hg tip --template '{node}'`
4026 $ ISSUE3669_TIP=`hg tip --template '{node}'`
4026 $ hg log -r "${ISSUE3669_TIP}" --template '{rev}\n'
4027 $ hg log -r "${ISSUE3669_TIP}" --template '{rev}\n'
4027 9
4028 9
4028 $ hg log -r "${ISSUE3669_TIP}^" --template '{rev}\n'
4029 $ hg log -r "${ISSUE3669_TIP}^" --template '{rev}\n'
4029 8
4030 8
4030
4031
4031 test or-ed indirect predicates (issue3775)
4032 test or-ed indirect predicates (issue3775)
4032
4033
4033 $ log '6 or 6^1' | sort
4034 $ log '6 or 6^1' | sort
4034 5
4035 5
4035 6
4036 6
4036 $ log '6^1 or 6' | sort
4037 $ log '6^1 or 6' | sort
4037 5
4038 5
4038 6
4039 6
4039 $ log '4 or 4~1' | sort
4040 $ log '4 or 4~1' | sort
4040 2
4041 2
4041 4
4042 4
4042 $ log '4~1 or 4' | sort
4043 $ log '4~1 or 4' | sort
4043 2
4044 2
4044 4
4045 4
4045 $ log '(0 or 2):(4 or 6) or 0 or 6' | sort
4046 $ log '(0 or 2):(4 or 6) or 0 or 6' | sort
4046 0
4047 0
4047 1
4048 1
4048 2
4049 2
4049 3
4050 3
4050 4
4051 4
4051 5
4052 5
4052 6
4053 6
4053 $ log '0 or 6 or (0 or 2):(4 or 6)' | sort
4054 $ log '0 or 6 or (0 or 2):(4 or 6)' | sort
4054 0
4055 0
4055 1
4056 1
4056 2
4057 2
4057 3
4058 3
4058 4
4059 4
4059 5
4060 5
4060 6
4061 6
4061
4062
4062 tests for 'remote()' predicate:
4063 tests for 'remote()' predicate:
4063 #. (csets in remote) (id) (remote)
4064 #. (csets in remote) (id) (remote)
4064 1. less than local current branch "default"
4065 1. less than local current branch "default"
4065 2. same with local specified "default"
4066 2. same with local specified "default"
4066 3. more than local specified specified
4067 3. more than local specified specified
4067
4068
4068 $ hg clone --quiet -U . ../remote3
4069 $ hg clone --quiet -U . ../remote3
4069 $ cd ../remote3
4070 $ cd ../remote3
4070 $ hg update -q 7
4071 $ hg update -q 7
4071 $ echo r > r
4072 $ echo r > r
4072 $ hg ci -Aqm 10
4073 $ hg ci -Aqm 10
4073 $ log 'remote()'
4074 $ log 'remote()'
4074 7
4075 7
4075 $ log 'remote("a-b-c-")'
4076 $ log 'remote("a-b-c-")'
4076 2
4077 2
4077 $ cd ../repo
4078 $ cd ../repo
4078 $ log 'remote(".a.b.c.", "../remote3")'
4079 $ log 'remote(".a.b.c.", "../remote3")'
4079
4080
4080 tests for concatenation of strings/symbols by "##"
4081 tests for concatenation of strings/symbols by "##"
4081
4082
4082 $ try "278 ## '5f5' ## 1ee ## 'ce5'"
4083 $ try "278 ## '5f5' ## 1ee ## 'ce5'"
4083 (_concat
4084 (_concat
4084 (_concat
4085 (_concat
4085 (_concat
4086 (_concat
4086 ('symbol', '278')
4087 ('symbol', '278')
4087 ('string', '5f5'))
4088 ('string', '5f5'))
4088 ('symbol', '1ee'))
4089 ('symbol', '1ee'))
4089 ('string', 'ce5'))
4090 ('string', 'ce5'))
4090 * concatenated:
4091 * concatenated:
4091 ('string', '2785f51eece5')
4092 ('string', '2785f51eece5')
4092 * set:
4093 * set:
4093 <baseset [0]>
4094 <baseset [0]>
4094 0
4095 0
4095
4096
4096 $ echo 'cat4($1, $2, $3, $4) = $1 ## $2 ## $3 ## $4' >> .hg/hgrc
4097 $ echo 'cat4($1, $2, $3, $4) = $1 ## $2 ## $3 ## $4' >> .hg/hgrc
4097 $ try "cat4(278, '5f5', 1ee, 'ce5')"
4098 $ try "cat4(278, '5f5', 1ee, 'ce5')"
4098 (func
4099 (func
4099 ('symbol', 'cat4')
4100 ('symbol', 'cat4')
4100 (list
4101 (list
4101 ('symbol', '278')
4102 ('symbol', '278')
4102 ('string', '5f5')
4103 ('string', '5f5')
4103 ('symbol', '1ee')
4104 ('symbol', '1ee')
4104 ('string', 'ce5')))
4105 ('string', 'ce5')))
4105 * expanded:
4106 * expanded:
4106 (_concat
4107 (_concat
4107 (_concat
4108 (_concat
4108 (_concat
4109 (_concat
4109 ('symbol', '278')
4110 ('symbol', '278')
4110 ('string', '5f5'))
4111 ('string', '5f5'))
4111 ('symbol', '1ee'))
4112 ('symbol', '1ee'))
4112 ('string', 'ce5'))
4113 ('string', 'ce5'))
4113 * concatenated:
4114 * concatenated:
4114 ('string', '2785f51eece5')
4115 ('string', '2785f51eece5')
4115 * set:
4116 * set:
4116 <baseset [0]>
4117 <baseset [0]>
4117 0
4118 0
4118
4119
4119 (check concatenation in alias nesting)
4120 (check concatenation in alias nesting)
4120
4121
4121 $ echo 'cat2($1, $2) = $1 ## $2' >> .hg/hgrc
4122 $ echo 'cat2($1, $2) = $1 ## $2' >> .hg/hgrc
4122 $ echo 'cat2x2($1, $2, $3, $4) = cat2($1 ## $2, $3 ## $4)' >> .hg/hgrc
4123 $ echo 'cat2x2($1, $2, $3, $4) = cat2($1 ## $2, $3 ## $4)' >> .hg/hgrc
4123 $ log "cat2x2(278, '5f5', 1ee, 'ce5')"
4124 $ log "cat2x2(278, '5f5', 1ee, 'ce5')"
4124 0
4125 0
4125
4126
4126 (check operator priority)
4127 (check operator priority)
4127
4128
4128 $ echo 'cat2n2($1, $2, $3, $4) = $1 ## $2 or $3 ## $4~2' >> .hg/hgrc
4129 $ echo 'cat2n2($1, $2, $3, $4) = $1 ## $2 or $3 ## $4~2' >> .hg/hgrc
4129 $ log "cat2n2(2785f5, 1eece5, 24286f, 4ae135)"
4130 $ log "cat2n2(2785f5, 1eece5, 24286f, 4ae135)"
4130 0
4131 0
4131 4
4132 4
4132
4133
4133 $ cd ..
4134 $ cd ..
4134
4135
4135 prepare repository that has "default" branches of multiple roots
4136 prepare repository that has "default" branches of multiple roots
4136
4137
4137 $ hg init namedbranch
4138 $ hg init namedbranch
4138 $ cd namedbranch
4139 $ cd namedbranch
4139
4140
4140 $ echo default0 >> a
4141 $ echo default0 >> a
4141 $ hg ci -Aqm0
4142 $ hg ci -Aqm0
4142 $ echo default1 >> a
4143 $ echo default1 >> a
4143 $ hg ci -m1
4144 $ hg ci -m1
4144
4145
4145 $ hg branch -q stable
4146 $ hg branch -q stable
4146 $ echo stable2 >> a
4147 $ echo stable2 >> a
4147 $ hg ci -m2
4148 $ hg ci -m2
4148 $ echo stable3 >> a
4149 $ echo stable3 >> a
4149 $ hg ci -m3
4150 $ hg ci -m3
4150
4151
4151 $ hg update -q null
4152 $ hg update -q null
4152 $ echo default4 >> a
4153 $ echo default4 >> a
4153 $ hg ci -Aqm4
4154 $ hg ci -Aqm4
4154 $ echo default5 >> a
4155 $ echo default5 >> a
4155 $ hg ci -m5
4156 $ hg ci -m5
4156
4157
4157 "null" revision belongs to "default" branch (issue4683)
4158 "null" revision belongs to "default" branch (issue4683)
4158
4159
4159 $ log 'branch(null)'
4160 $ log 'branch(null)'
4160 0
4161 0
4161 1
4162 1
4162 4
4163 4
4163 5
4164 5
4164
4165
4165 "null" revision belongs to "default" branch, but it shouldn't appear in set
4166 "null" revision belongs to "default" branch, but it shouldn't appear in set
4166 unless explicitly specified (issue4682)
4167 unless explicitly specified (issue4682)
4167
4168
4168 $ log 'children(branch(default))'
4169 $ log 'children(branch(default))'
4169 1
4170 1
4170 2
4171 2
4171 5
4172 5
4172
4173
4173 $ cd ..
4174 $ cd ..
4174
4175
4175 test author/desc/keyword in problematic encoding
4176 test author/desc/keyword in problematic encoding
4176 # unicode: cp932:
4177 # unicode: cp932:
4177 # u30A2 0x83 0x41(= 'A')
4178 # u30A2 0x83 0x41(= 'A')
4178 # u30C2 0x83 0x61(= 'a')
4179 # u30C2 0x83 0x61(= 'a')
4179
4180
4180 $ hg init problematicencoding
4181 $ hg init problematicencoding
4181 $ cd problematicencoding
4182 $ cd problematicencoding
4182
4183
4183 $ $PYTHON > setup.sh <<EOF
4184 $ $PYTHON > setup.sh <<EOF
4184 > print u'''
4185 > print u'''
4185 > echo a > text
4186 > echo a > text
4186 > hg add text
4187 > hg add text
4187 > hg --encoding utf-8 commit -u '\u30A2' -m none
4188 > hg --encoding utf-8 commit -u '\u30A2' -m none
4188 > echo b > text
4189 > echo b > text
4189 > hg --encoding utf-8 commit -u '\u30C2' -m none
4190 > hg --encoding utf-8 commit -u '\u30C2' -m none
4190 > echo c > text
4191 > echo c > text
4191 > hg --encoding utf-8 commit -u none -m '\u30A2'
4192 > hg --encoding utf-8 commit -u none -m '\u30A2'
4192 > echo d > text
4193 > echo d > text
4193 > hg --encoding utf-8 commit -u none -m '\u30C2'
4194 > hg --encoding utf-8 commit -u none -m '\u30C2'
4194 > '''.encode('utf-8')
4195 > '''.encode('utf-8')
4195 > EOF
4196 > EOF
4196 $ sh < setup.sh
4197 $ sh < setup.sh
4197
4198
4198 test in problematic encoding
4199 test in problematic encoding
4199 $ $PYTHON > test.sh <<EOF
4200 $ $PYTHON > test.sh <<EOF
4200 > print u'''
4201 > print u'''
4201 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30A2)'
4202 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30A2)'
4202 > echo ====
4203 > echo ====
4203 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30C2)'
4204 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30C2)'
4204 > echo ====
4205 > echo ====
4205 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30A2)'
4206 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30A2)'
4206 > echo ====
4207 > echo ====
4207 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30C2)'
4208 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30C2)'
4208 > echo ====
4209 > echo ====
4209 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30A2)'
4210 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30A2)'
4210 > echo ====
4211 > echo ====
4211 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30C2)'
4212 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30C2)'
4212 > '''.encode('cp932')
4213 > '''.encode('cp932')
4213 > EOF
4214 > EOF
4214 $ sh < test.sh
4215 $ sh < test.sh
4215 0
4216 0
4216 ====
4217 ====
4217 1
4218 1
4218 ====
4219 ====
4219 2
4220 2
4220 ====
4221 ====
4221 3
4222 3
4222 ====
4223 ====
4223 0
4224 0
4224 2
4225 2
4225 ====
4226 ====
4226 1
4227 1
4227 3
4228 3
4228
4229
4229 test error message of bad revset
4230 test error message of bad revset
4230 $ hg log -r 'foo\\'
4231 $ hg log -r 'foo\\'
4231 hg: parse error at 3: syntax error in revset 'foo\\'
4232 hg: parse error at 3: syntax error in revset 'foo\\'
4232 [255]
4233 [255]
4233
4234
4234 $ cd ..
4235 $ cd ..
4235
4236
4236 Test that revset predicate of extension isn't loaded at failure of
4237 Test that revset predicate of extension isn't loaded at failure of
4237 loading it
4238 loading it
4238
4239
4239 $ cd repo
4240 $ cd repo
4240
4241
4241 $ cat <<EOF > $TESTTMP/custompredicate.py
4242 $ cat <<EOF > $TESTTMP/custompredicate.py
4242 > from mercurial import error, registrar, revset
4243 > from mercurial import error, registrar, revset
4243 >
4244 >
4244 > revsetpredicate = registrar.revsetpredicate()
4245 > revsetpredicate = registrar.revsetpredicate()
4245 >
4246 >
4246 > @revsetpredicate('custom1()')
4247 > @revsetpredicate('custom1()')
4247 > def custom1(repo, subset, x):
4248 > def custom1(repo, subset, x):
4248 > return revset.baseset([1])
4249 > return revset.baseset([1])
4249 >
4250 >
4250 > raise error.Abort('intentional failure of loading extension')
4251 > raise error.Abort('intentional failure of loading extension')
4251 > EOF
4252 > EOF
4252 $ cat <<EOF > .hg/hgrc
4253 $ cat <<EOF > .hg/hgrc
4253 > [extensions]
4254 > [extensions]
4254 > custompredicate = $TESTTMP/custompredicate.py
4255 > custompredicate = $TESTTMP/custompredicate.py
4255 > EOF
4256 > EOF
4256
4257
4257 $ hg debugrevspec "custom1()"
4258 $ hg debugrevspec "custom1()"
4258 *** failed to import extension custompredicate from $TESTTMP/custompredicate.py: intentional failure of loading extension
4259 *** failed to import extension custompredicate from $TESTTMP/custompredicate.py: intentional failure of loading extension
4259 hg: parse error: unknown identifier: custom1
4260 hg: parse error: unknown identifier: custom1
4260 [255]
4261 [255]
4261
4262
4262 Test repo.anyrevs with customized revset overrides
4263 Test repo.anyrevs with customized revset overrides
4263
4264
4264 $ cat > $TESTTMP/printprevset.py <<EOF
4265 $ cat > $TESTTMP/printprevset.py <<EOF
4265 > from mercurial import encoding
4266 > from mercurial import encoding
4266 > def reposetup(ui, repo):
4267 > def reposetup(ui, repo):
4267 > alias = {}
4268 > alias = {}
4268 > p = encoding.environ.get('P')
4269 > p = encoding.environ.get('P')
4269 > if p:
4270 > if p:
4270 > alias['P'] = p
4271 > alias['P'] = p
4271 > revs = repo.anyrevs(['P'], user=True, localalias=alias)
4272 > revs = repo.anyrevs(['P'], user=True, localalias=alias)
4272 > ui.write('P=%r' % list(revs))
4273 > ui.write('P=%r' % list(revs))
4273 > EOF
4274 > EOF
4274
4275
4275 $ cat >> .hg/hgrc <<EOF
4276 $ cat >> .hg/hgrc <<EOF
4276 > custompredicate = !
4277 > custompredicate = !
4277 > printprevset = $TESTTMP/printprevset.py
4278 > printprevset = $TESTTMP/printprevset.py
4278 > EOF
4279 > EOF
4279
4280
4280 $ hg --config revsetalias.P=1 log -r . -T '\n'
4281 $ hg --config revsetalias.P=1 log -r . -T '\n'
4281 P=[1]
4282 P=[1]
4282 $ P=3 hg --config revsetalias.P=2 log -r . -T '\n'
4283 $ P=3 hg --config revsetalias.P=2 log -r . -T '\n'
4283 P=[3]
4284 P=[3]
4284
4285
4285 $ cd ..
4286 $ cd ..
4287
4288 Test obsstore related revsets
4289
4290 $ hg init repo1
4291 $ cd repo1
4292 $ cat <<EOF >> .hg/hgrc
4293 > [experimental]
4294 > evolution = createmarkers
4295 > EOF
4296
4297 $ hg debugdrawdag <<'EOS'
4298 > F G
4299 > |/ # split: B -> E, F
4300 > B C D E # amend: B -> C -> D
4301 > \|/ | # amend: F -> G
4302 > A A Z # amend: A -> Z
4303 > EOS
4304
4305 $ hg log -r 'successors(Z)' -T '{desc}\n'
4306 Z
4307
4308 $ hg log -r 'successors(F)' -T '{desc}\n'
4309 F
4310 G
4311
4312 $ hg tag --remove --local C D E F G
4313
4314 $ hg log -r 'successors(B)' -T '{desc}\n'
4315 B
4316 D
4317 E
4318 G
4319
4320 $ hg log -r 'successors(B)' -T '{desc}\n' --hidden
4321 B
4322 C
4323 D
4324 E
4325 F
4326 G
4327
4328 $ hg log -r 'successors(B)-obsolete()' -T '{desc}\n' --hidden
4329 D
4330 E
4331 G
4332
4333 $ hg log -r 'successors(B+A)-divergent()' -T '{desc}\n'
4334 A
4335 Z
4336 B
4337
4338 $ hg log -r 'successors(B+A)-divergent()-obsolete()' -T '{desc}\n'
4339 Z
General Comments 0
You need to be logged in to leave comments. Login now