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