##// END OF EJS Templates
revset: fix outgoing argument handling
Wagner Bruna -
r11882:b75dea24 stable
parent child Browse files
Show More
@@ -1,572 +1,572 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 import re
8 import re
9 import parser, util, error, discovery
9 import parser, util, error, discovery
10 import match as _match
10 import match as _match
11 from i18n import _
11 from i18n import _
12
12
13 elements = {
13 elements = {
14 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
14 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
15 "-": (19, ("negate", 19), ("minus", 19)),
15 "-": (19, ("negate", 19), ("minus", 19)),
16 "::": (17, ("dagrangepre", 17), ("dagrange", 17),
16 "::": (17, ("dagrangepre", 17), ("dagrange", 17),
17 ("dagrangepost", 17)),
17 ("dagrangepost", 17)),
18 "..": (17, ("dagrangepre", 17), ("dagrange", 17),
18 "..": (17, ("dagrangepre", 17), ("dagrange", 17),
19 ("dagrangepost", 17)),
19 ("dagrangepost", 17)),
20 ":": (15, ("rangepre", 15), ("range", 15), ("rangepost", 15)),
20 ":": (15, ("rangepre", 15), ("range", 15), ("rangepost", 15)),
21 "not": (10, ("not", 10)),
21 "not": (10, ("not", 10)),
22 "!": (10, ("not", 10)),
22 "!": (10, ("not", 10)),
23 "and": (5, None, ("and", 5)),
23 "and": (5, None, ("and", 5)),
24 "&": (5, None, ("and", 5)),
24 "&": (5, None, ("and", 5)),
25 "or": (4, None, ("or", 4)),
25 "or": (4, None, ("or", 4)),
26 "|": (4, None, ("or", 4)),
26 "|": (4, None, ("or", 4)),
27 "+": (4, None, ("or", 4)),
27 "+": (4, None, ("or", 4)),
28 ",": (2, None, ("list", 2)),
28 ",": (2, None, ("list", 2)),
29 ")": (0, None, None),
29 ")": (0, None, None),
30 "symbol": (0, ("symbol",), None),
30 "symbol": (0, ("symbol",), None),
31 "string": (0, ("string",), None),
31 "string": (0, ("string",), None),
32 "end": (0, None, None),
32 "end": (0, None, None),
33 }
33 }
34
34
35 keywords = set(['and', 'or', 'not'])
35 keywords = set(['and', 'or', 'not'])
36
36
37 def tokenize(program):
37 def tokenize(program):
38 pos, l = 0, len(program)
38 pos, l = 0, len(program)
39 while pos < l:
39 while pos < l:
40 c = program[pos]
40 c = program[pos]
41 if c.isspace(): # skip inter-token whitespace
41 if c.isspace(): # skip inter-token whitespace
42 pass
42 pass
43 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
43 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
44 yield ('::', None, pos)
44 yield ('::', None, pos)
45 pos += 1 # skip ahead
45 pos += 1 # skip ahead
46 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
46 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
47 yield ('..', None, pos)
47 yield ('..', None, pos)
48 pos += 1 # skip ahead
48 pos += 1 # skip ahead
49 elif c in "():,-|&+!": # handle simple operators
49 elif c in "():,-|&+!": # handle simple operators
50 yield (c, None, pos)
50 yield (c, None, pos)
51 elif c in '"\'': # handle quoted strings
51 elif c in '"\'': # handle quoted strings
52 pos += 1
52 pos += 1
53 s = pos
53 s = pos
54 while pos < l: # find closing quote
54 while pos < l: # find closing quote
55 d = program[pos]
55 d = program[pos]
56 if d == '\\': # skip over escaped characters
56 if d == '\\': # skip over escaped characters
57 pos += 2
57 pos += 2
58 continue
58 continue
59 if d == c:
59 if d == c:
60 yield ('string', program[s:pos].decode('string-escape'), s)
60 yield ('string', program[s:pos].decode('string-escape'), s)
61 break
61 break
62 pos += 1
62 pos += 1
63 else:
63 else:
64 raise error.ParseError(_("unterminated string"), s)
64 raise error.ParseError(_("unterminated string"), s)
65 elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
65 elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
66 s = pos
66 s = pos
67 pos += 1
67 pos += 1
68 while pos < l: # find end of symbol
68 while pos < l: # find end of symbol
69 d = program[pos]
69 d = program[pos]
70 if not (d.isalnum() or d in "._" or ord(d) > 127):
70 if not (d.isalnum() or d in "._" or ord(d) > 127):
71 break
71 break
72 if d == '.' and program[pos - 1] == '.': # special case for ..
72 if d == '.' and program[pos - 1] == '.': # special case for ..
73 pos -= 1
73 pos -= 1
74 break
74 break
75 pos += 1
75 pos += 1
76 sym = program[s:pos]
76 sym = program[s:pos]
77 if sym in keywords: # operator keywords
77 if sym in keywords: # operator keywords
78 yield (sym, None, s)
78 yield (sym, None, s)
79 else:
79 else:
80 yield ('symbol', sym, s)
80 yield ('symbol', sym, s)
81 pos -= 1
81 pos -= 1
82 else:
82 else:
83 raise error.ParseError(_("syntax error"), pos)
83 raise error.ParseError(_("syntax error"), pos)
84 pos += 1
84 pos += 1
85 yield ('end', None, pos)
85 yield ('end', None, pos)
86
86
87 # helpers
87 # helpers
88
88
89 def getstring(x, err):
89 def getstring(x, err):
90 if x and (x[0] == 'string' or x[0] == 'symbol'):
90 if x and (x[0] == 'string' or x[0] == 'symbol'):
91 return x[1]
91 return x[1]
92 raise error.ParseError(err)
92 raise error.ParseError(err)
93
93
94 def getlist(x):
94 def getlist(x):
95 if not x:
95 if not x:
96 return []
96 return []
97 if x[0] == 'list':
97 if x[0] == 'list':
98 return getlist(x[1]) + [x[2]]
98 return getlist(x[1]) + [x[2]]
99 return [x]
99 return [x]
100
100
101 def getargs(x, min, max, err):
101 def getargs(x, min, max, err):
102 l = getlist(x)
102 l = getlist(x)
103 if len(l) < min or len(l) > max:
103 if len(l) < min or len(l) > max:
104 raise error.ParseError(err)
104 raise error.ParseError(err)
105 return l
105 return l
106
106
107 def getset(repo, subset, x):
107 def getset(repo, subset, x):
108 if not x:
108 if not x:
109 raise error.ParseError(_("missing argument"))
109 raise error.ParseError(_("missing argument"))
110 return methods[x[0]](repo, subset, *x[1:])
110 return methods[x[0]](repo, subset, *x[1:])
111
111
112 # operator methods
112 # operator methods
113
113
114 def stringset(repo, subset, x):
114 def stringset(repo, subset, x):
115 x = repo[x].rev()
115 x = repo[x].rev()
116 if x == -1 and len(subset) == len(repo):
116 if x == -1 and len(subset) == len(repo):
117 return [-1]
117 return [-1]
118 if x in subset:
118 if x in subset:
119 return [x]
119 return [x]
120 return []
120 return []
121
121
122 def symbolset(repo, subset, x):
122 def symbolset(repo, subset, x):
123 if x in symbols:
123 if x in symbols:
124 raise error.ParseError(_("can't use %s here") % x)
124 raise error.ParseError(_("can't use %s here") % x)
125 return stringset(repo, subset, x)
125 return stringset(repo, subset, x)
126
126
127 def rangeset(repo, subset, x, y):
127 def rangeset(repo, subset, x, y):
128 m = getset(repo, subset, x)
128 m = getset(repo, subset, x)
129 if not m:
129 if not m:
130 m = getset(repo, range(len(repo)), x)
130 m = getset(repo, range(len(repo)), x)
131
131
132 n = getset(repo, subset, y)
132 n = getset(repo, subset, y)
133 if not n:
133 if not n:
134 n = getset(repo, range(len(repo)), y)
134 n = getset(repo, range(len(repo)), y)
135
135
136 if not m or not n:
136 if not m or not n:
137 return []
137 return []
138 m, n = m[0], n[-1]
138 m, n = m[0], n[-1]
139
139
140 if m < n:
140 if m < n:
141 r = range(m, n + 1)
141 r = range(m, n + 1)
142 else:
142 else:
143 r = range(m, n - 1, -1)
143 r = range(m, n - 1, -1)
144 s = set(subset)
144 s = set(subset)
145 return [x for x in r if x in s]
145 return [x for x in r if x in s]
146
146
147 def andset(repo, subset, x, y):
147 def andset(repo, subset, x, y):
148 return getset(repo, getset(repo, subset, x), y)
148 return getset(repo, getset(repo, subset, x), y)
149
149
150 def orset(repo, subset, x, y):
150 def orset(repo, subset, x, y):
151 s = set(getset(repo, subset, x))
151 s = set(getset(repo, subset, x))
152 s |= set(getset(repo, [r for r in subset if r not in s], y))
152 s |= set(getset(repo, [r for r in subset if r not in s], y))
153 return [r for r in subset if r in s]
153 return [r for r in subset if r in s]
154
154
155 def notset(repo, subset, x):
155 def notset(repo, subset, x):
156 s = set(getset(repo, subset, x))
156 s = set(getset(repo, subset, x))
157 return [r for r in subset if r not in s]
157 return [r for r in subset if r not in s]
158
158
159 def listset(repo, subset, a, b):
159 def listset(repo, subset, a, b):
160 raise error.ParseError(_("can't use a list in this context"))
160 raise error.ParseError(_("can't use a list in this context"))
161
161
162 def func(repo, subset, a, b):
162 def func(repo, subset, a, b):
163 if a[0] == 'symbol' and a[1] in symbols:
163 if a[0] == 'symbol' and a[1] in symbols:
164 return symbols[a[1]](repo, subset, b)
164 return symbols[a[1]](repo, subset, b)
165 raise error.ParseError(_("not a function: %s") % a[1])
165 raise error.ParseError(_("not a function: %s") % a[1])
166
166
167 # functions
167 # functions
168
168
169 def p1(repo, subset, x):
169 def p1(repo, subset, x):
170 ps = set()
170 ps = set()
171 cl = repo.changelog
171 cl = repo.changelog
172 for r in getset(repo, subset, x):
172 for r in getset(repo, subset, x):
173 ps.add(cl.parentrevs(r)[0])
173 ps.add(cl.parentrevs(r)[0])
174 return [r for r in subset if r in ps]
174 return [r for r in subset if r in ps]
175
175
176 def p2(repo, subset, x):
176 def p2(repo, subset, x):
177 ps = set()
177 ps = set()
178 cl = repo.changelog
178 cl = repo.changelog
179 for r in getset(repo, subset, x):
179 for r in getset(repo, subset, x):
180 ps.add(cl.parentrevs(r)[1])
180 ps.add(cl.parentrevs(r)[1])
181 return [r for r in subset if r in ps]
181 return [r for r in subset if r in ps]
182
182
183 def parents(repo, subset, x):
183 def parents(repo, subset, x):
184 ps = set()
184 ps = set()
185 cl = repo.changelog
185 cl = repo.changelog
186 for r in getset(repo, subset, x):
186 for r in getset(repo, subset, x):
187 ps.update(cl.parentrevs(r))
187 ps.update(cl.parentrevs(r))
188 return [r for r in subset if r in ps]
188 return [r for r in subset if r in ps]
189
189
190 def maxrev(repo, subset, x):
190 def maxrev(repo, subset, x):
191 s = getset(repo, subset, x)
191 s = getset(repo, subset, x)
192 if s:
192 if s:
193 m = max(s)
193 m = max(s)
194 if m in subset:
194 if m in subset:
195 return [m]
195 return [m]
196 return []
196 return []
197
197
198 def limit(repo, subset, x):
198 def limit(repo, subset, x):
199 l = getargs(x, 2, 2, _("limit wants two arguments"))
199 l = getargs(x, 2, 2, _("limit wants two arguments"))
200 try:
200 try:
201 lim = int(getstring(l[1], _("limit wants a number")))
201 lim = int(getstring(l[1], _("limit wants a number")))
202 except ValueError:
202 except ValueError:
203 raise error.ParseError(_("limit expects a number"))
203 raise error.ParseError(_("limit expects a number"))
204 return getset(repo, subset, l[0])[:lim]
204 return getset(repo, subset, l[0])[:lim]
205
205
206 def children(repo, subset, x):
206 def children(repo, subset, x):
207 cs = set()
207 cs = set()
208 cl = repo.changelog
208 cl = repo.changelog
209 s = set(getset(repo, subset, x))
209 s = set(getset(repo, subset, x))
210 for r in xrange(0, len(repo)):
210 for r in xrange(0, len(repo)):
211 for p in cl.parentrevs(r):
211 for p in cl.parentrevs(r):
212 if p in s:
212 if p in s:
213 cs.add(r)
213 cs.add(r)
214 return [r for r in subset if r in cs]
214 return [r for r in subset if r in cs]
215
215
216 def branch(repo, subset, x):
216 def branch(repo, subset, x):
217 s = getset(repo, range(len(repo)), x)
217 s = getset(repo, range(len(repo)), x)
218 b = set()
218 b = set()
219 for r in s:
219 for r in s:
220 b.add(repo[r].branch())
220 b.add(repo[r].branch())
221 s = set(s)
221 s = set(s)
222 return [r for r in subset if r in s or repo[r].branch() in b]
222 return [r for r in subset if r in s or repo[r].branch() in b]
223
223
224 def ancestor(repo, subset, x):
224 def ancestor(repo, subset, x):
225 l = getargs(x, 2, 2, _("ancestor wants two arguments"))
225 l = getargs(x, 2, 2, _("ancestor wants two arguments"))
226 r = range(len(repo))
226 r = range(len(repo))
227 a = getset(repo, r, l[0])
227 a = getset(repo, r, l[0])
228 b = getset(repo, r, l[1])
228 b = getset(repo, r, l[1])
229 if len(a) != 1 or len(b) != 1:
229 if len(a) != 1 or len(b) != 1:
230 raise error.ParseError(_("ancestor arguments must be single revisions"))
230 raise error.ParseError(_("ancestor arguments must be single revisions"))
231 an = [repo[a[0]].ancestor(repo[b[0]]).rev()]
231 an = [repo[a[0]].ancestor(repo[b[0]]).rev()]
232
232
233 return [r for r in an if r in subset]
233 return [r for r in an if r in subset]
234
234
235 def ancestors(repo, subset, x):
235 def ancestors(repo, subset, x):
236 args = getset(repo, range(len(repo)), x)
236 args = getset(repo, range(len(repo)), x)
237 if not args:
237 if not args:
238 return []
238 return []
239 s = set(repo.changelog.ancestors(*args)) | set(args)
239 s = set(repo.changelog.ancestors(*args)) | set(args)
240 return [r for r in subset if r in s]
240 return [r for r in subset if r in s]
241
241
242 def descendants(repo, subset, x):
242 def descendants(repo, subset, x):
243 args = getset(repo, range(len(repo)), x)
243 args = getset(repo, range(len(repo)), x)
244 if not args:
244 if not args:
245 return []
245 return []
246 s = set(repo.changelog.descendants(*args)) | set(args)
246 s = set(repo.changelog.descendants(*args)) | set(args)
247 return [r for r in subset if r in s]
247 return [r for r in subset if r in s]
248
248
249 def follow(repo, subset, x):
249 def follow(repo, subset, x):
250 getargs(x, 0, 0, _("follow takes no arguments"))
250 getargs(x, 0, 0, _("follow takes no arguments"))
251 p = repo['.'].rev()
251 p = repo['.'].rev()
252 s = set(repo.changelog.ancestors(p)) | set([p])
252 s = set(repo.changelog.ancestors(p)) | set([p])
253 return [r for r in subset if r in s]
253 return [r for r in subset if r in s]
254
254
255 def date(repo, subset, x):
255 def date(repo, subset, x):
256 ds = getstring(x, _("date wants a string"))
256 ds = getstring(x, _("date wants a string"))
257 dm = util.matchdate(ds)
257 dm = util.matchdate(ds)
258 return [r for r in subset if dm(repo[r].date()[0])]
258 return [r for r in subset if dm(repo[r].date()[0])]
259
259
260 def keyword(repo, subset, x):
260 def keyword(repo, subset, x):
261 kw = getstring(x, _("keyword wants a string")).lower()
261 kw = getstring(x, _("keyword wants a string")).lower()
262 l = []
262 l = []
263 for r in subset:
263 for r in subset:
264 c = repo[r]
264 c = repo[r]
265 t = " ".join(c.files() + [c.user(), c.description()])
265 t = " ".join(c.files() + [c.user(), c.description()])
266 if kw in t.lower():
266 if kw in t.lower():
267 l.append(r)
267 l.append(r)
268 return l
268 return l
269
269
270 def grep(repo, subset, x):
270 def grep(repo, subset, x):
271 gr = re.compile(getstring(x, _("grep wants a string")))
271 gr = re.compile(getstring(x, _("grep wants a string")))
272 l = []
272 l = []
273 for r in subset:
273 for r in subset:
274 c = repo[r]
274 c = repo[r]
275 for e in c.files() + [c.user(), c.description()]:
275 for e in c.files() + [c.user(), c.description()]:
276 if gr.search(e):
276 if gr.search(e):
277 l.append(r)
277 l.append(r)
278 continue
278 continue
279 return l
279 return l
280
280
281 def author(repo, subset, x):
281 def author(repo, subset, x):
282 n = getstring(x, _("author wants a string")).lower()
282 n = getstring(x, _("author wants a string")).lower()
283 return [r for r in subset if n in repo[r].user().lower()]
283 return [r for r in subset if n in repo[r].user().lower()]
284
284
285 def hasfile(repo, subset, x):
285 def hasfile(repo, subset, x):
286 pat = getstring(x, _("file wants a pattern"))
286 pat = getstring(x, _("file wants a pattern"))
287 m = _match.match(repo.root, repo.getcwd(), [pat])
287 m = _match.match(repo.root, repo.getcwd(), [pat])
288 s = []
288 s = []
289 for r in subset:
289 for r in subset:
290 for f in repo[r].files():
290 for f in repo[r].files():
291 if m(f):
291 if m(f):
292 s.append(r)
292 s.append(r)
293 continue
293 continue
294 return s
294 return s
295
295
296 def contains(repo, subset, x):
296 def contains(repo, subset, x):
297 pat = getstring(x, _("contains wants a pattern"))
297 pat = getstring(x, _("contains wants a pattern"))
298 m = _match.match(repo.root, repo.getcwd(), [pat])
298 m = _match.match(repo.root, repo.getcwd(), [pat])
299 s = []
299 s = []
300 if m.files() == [pat]:
300 if m.files() == [pat]:
301 for r in subset:
301 for r in subset:
302 if pat in repo[r]:
302 if pat in repo[r]:
303 s.append(r)
303 s.append(r)
304 continue
304 continue
305 else:
305 else:
306 for r in subset:
306 for r in subset:
307 for f in repo[r].manifest():
307 for f in repo[r].manifest():
308 if m(f):
308 if m(f):
309 s.append(r)
309 s.append(r)
310 continue
310 continue
311 return s
311 return s
312
312
313 def checkstatus(repo, subset, pat, field):
313 def checkstatus(repo, subset, pat, field):
314 m = _match.match(repo.root, repo.getcwd(), [pat])
314 m = _match.match(repo.root, repo.getcwd(), [pat])
315 s = []
315 s = []
316 fast = (m.files() == [pat])
316 fast = (m.files() == [pat])
317 for r in subset:
317 for r in subset:
318 c = repo[r]
318 c = repo[r]
319 if fast:
319 if fast:
320 if pat not in c.files():
320 if pat not in c.files():
321 continue
321 continue
322 else:
322 else:
323 for f in c.files():
323 for f in c.files():
324 if m(f):
324 if m(f):
325 break
325 break
326 else:
326 else:
327 continue
327 continue
328 files = repo.status(c.p1().node(), c.node())[field]
328 files = repo.status(c.p1().node(), c.node())[field]
329 if fast:
329 if fast:
330 if pat in files:
330 if pat in files:
331 s.append(r)
331 s.append(r)
332 continue
332 continue
333 else:
333 else:
334 for f in files:
334 for f in files:
335 if m(f):
335 if m(f):
336 s.append(r)
336 s.append(r)
337 continue
337 continue
338 return s
338 return s
339
339
340 def modifies(repo, subset, x):
340 def modifies(repo, subset, x):
341 pat = getstring(x, _("modifies wants a pattern"))
341 pat = getstring(x, _("modifies wants a pattern"))
342 return checkstatus(repo, subset, pat, 0)
342 return checkstatus(repo, subset, pat, 0)
343
343
344 def adds(repo, subset, x):
344 def adds(repo, subset, x):
345 pat = getstring(x, _("adds wants a pattern"))
345 pat = getstring(x, _("adds wants a pattern"))
346 return checkstatus(repo, subset, pat, 1)
346 return checkstatus(repo, subset, pat, 1)
347
347
348 def removes(repo, subset, x):
348 def removes(repo, subset, x):
349 pat = getstring(x, _("removes wants a pattern"))
349 pat = getstring(x, _("removes wants a pattern"))
350 return checkstatus(repo, subset, pat, 2)
350 return checkstatus(repo, subset, pat, 2)
351
351
352 def merge(repo, subset, x):
352 def merge(repo, subset, x):
353 getargs(x, 0, 0, _("merge takes no arguments"))
353 getargs(x, 0, 0, _("merge takes no arguments"))
354 cl = repo.changelog
354 cl = repo.changelog
355 return [r for r in subset if cl.parentrevs(r)[1] != -1]
355 return [r for r in subset if cl.parentrevs(r)[1] != -1]
356
356
357 def closed(repo, subset, x):
357 def closed(repo, subset, x):
358 getargs(x, 0, 0, _("closed takes no arguments"))
358 getargs(x, 0, 0, _("closed takes no arguments"))
359 return [r for r in subset if repo[r].extra().get('close')]
359 return [r for r in subset if repo[r].extra().get('close')]
360
360
361 def head(repo, subset, x):
361 def head(repo, subset, x):
362 getargs(x, 0, 0, _("head takes no arguments"))
362 getargs(x, 0, 0, _("head takes no arguments"))
363 hs = set()
363 hs = set()
364 for b, ls in repo.branchmap().iteritems():
364 for b, ls in repo.branchmap().iteritems():
365 hs.update(repo[h].rev() for h in ls)
365 hs.update(repo[h].rev() for h in ls)
366 return [r for r in subset if r in hs]
366 return [r for r in subset if r in hs]
367
367
368 def reverse(repo, subset, x):
368 def reverse(repo, subset, x):
369 l = getset(repo, subset, x)
369 l = getset(repo, subset, x)
370 l.reverse()
370 l.reverse()
371 return l
371 return l
372
372
373 def sort(repo, subset, x):
373 def sort(repo, subset, x):
374 l = getargs(x, 1, 2, _("sort wants one or two arguments"))
374 l = getargs(x, 1, 2, _("sort wants one or two arguments"))
375 keys = "rev"
375 keys = "rev"
376 if len(l) == 2:
376 if len(l) == 2:
377 keys = getstring(l[1], _("sort spec must be a string"))
377 keys = getstring(l[1], _("sort spec must be a string"))
378
378
379 s = l[0]
379 s = l[0]
380 keys = keys.split()
380 keys = keys.split()
381 l = []
381 l = []
382 def invert(s):
382 def invert(s):
383 return "".join(chr(255 - ord(c)) for c in s)
383 return "".join(chr(255 - ord(c)) for c in s)
384 for r in getset(repo, subset, s):
384 for r in getset(repo, subset, s):
385 c = repo[r]
385 c = repo[r]
386 e = []
386 e = []
387 for k in keys:
387 for k in keys:
388 if k == 'rev':
388 if k == 'rev':
389 e.append(r)
389 e.append(r)
390 elif k == '-rev':
390 elif k == '-rev':
391 e.append(-r)
391 e.append(-r)
392 elif k == 'branch':
392 elif k == 'branch':
393 e.append(c.branch())
393 e.append(c.branch())
394 elif k == '-branch':
394 elif k == '-branch':
395 e.append(invert(c.branch()))
395 e.append(invert(c.branch()))
396 elif k == 'desc':
396 elif k == 'desc':
397 e.append(c.description())
397 e.append(c.description())
398 elif k == '-desc':
398 elif k == '-desc':
399 e.append(invert(c.description()))
399 e.append(invert(c.description()))
400 elif k in 'user author':
400 elif k in 'user author':
401 e.append(c.user())
401 e.append(c.user())
402 elif k in '-user -author':
402 elif k in '-user -author':
403 e.append(invert(c.user()))
403 e.append(invert(c.user()))
404 elif k == 'date':
404 elif k == 'date':
405 e.append(c.date()[0])
405 e.append(c.date()[0])
406 elif k == '-date':
406 elif k == '-date':
407 e.append(-c.date()[0])
407 e.append(-c.date()[0])
408 else:
408 else:
409 raise error.ParseError(_("unknown sort key %r") % k)
409 raise error.ParseError(_("unknown sort key %r") % k)
410 e.append(r)
410 e.append(r)
411 l.append(e)
411 l.append(e)
412 l.sort()
412 l.sort()
413 return [e[-1] for e in l]
413 return [e[-1] for e in l]
414
414
415 def getall(repo, subset, x):
415 def getall(repo, subset, x):
416 getargs(x, 0, 0, _("all takes no arguments"))
416 getargs(x, 0, 0, _("all takes no arguments"))
417 return subset
417 return subset
418
418
419 def heads(repo, subset, x):
419 def heads(repo, subset, x):
420 s = getset(repo, subset, x)
420 s = getset(repo, subset, x)
421 ps = set(parents(repo, subset, x))
421 ps = set(parents(repo, subset, x))
422 return [r for r in s if r not in ps]
422 return [r for r in s if r not in ps]
423
423
424 def roots(repo, subset, x):
424 def roots(repo, subset, x):
425 s = getset(repo, subset, x)
425 s = getset(repo, subset, x)
426 cs = set(children(repo, subset, x))
426 cs = set(children(repo, subset, x))
427 return [r for r in s if r not in cs]
427 return [r for r in s if r not in cs]
428
428
429 def outgoing(repo, subset, x):
429 def outgoing(repo, subset, x):
430 import hg # avoid start-up nasties
430 import hg # avoid start-up nasties
431 l = getargs(x, 0, 1, _("outgoing wants a repository path"))
431 l = getargs(x, 0, 1, _("outgoing wants a repository path"))
432 dest = l[1:] or ''
432 dest = l and getstring(l[0], _("outgoing wants a repository path")) or ''
433 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
433 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
434 dest, branches = hg.parseurl(dest)
434 dest, branches = hg.parseurl(dest)
435 other = hg.repository(hg.remoteui(repo, {}), dest)
435 other = hg.repository(hg.remoteui(repo, {}), dest)
436 repo.ui.pushbuffer()
436 repo.ui.pushbuffer()
437 o = discovery.findoutgoing(repo, other)
437 o = discovery.findoutgoing(repo, other)
438 repo.ui.popbuffer()
438 repo.ui.popbuffer()
439 cl = repo.changelog
439 cl = repo.changelog
440 o = set([cl.rev(r) for r in repo.changelog.nodesbetween(o, None)[0]])
440 o = set([cl.rev(r) for r in repo.changelog.nodesbetween(o, None)[0]])
441 return [r for r in subset if r in o]
441 return [r for r in subset if r in o]
442
442
443 def tagged(repo, subset, x):
443 def tagged(repo, subset, x):
444 getargs(x, 0, 0, _("tagged takes no arguments"))
444 getargs(x, 0, 0, _("tagged takes no arguments"))
445 cl = repo.changelog
445 cl = repo.changelog
446 s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
446 s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
447 return [r for r in subset if r in s]
447 return [r for r in subset if r in s]
448
448
449 symbols = {
449 symbols = {
450 "adds": adds,
450 "adds": adds,
451 "all": getall,
451 "all": getall,
452 "ancestor": ancestor,
452 "ancestor": ancestor,
453 "ancestors": ancestors,
453 "ancestors": ancestors,
454 "author": author,
454 "author": author,
455 "branch": branch,
455 "branch": branch,
456 "children": children,
456 "children": children,
457 "closed": closed,
457 "closed": closed,
458 "contains": contains,
458 "contains": contains,
459 "date": date,
459 "date": date,
460 "descendants": descendants,
460 "descendants": descendants,
461 "file": hasfile,
461 "file": hasfile,
462 "follow": follow,
462 "follow": follow,
463 "grep": grep,
463 "grep": grep,
464 "head": head,
464 "head": head,
465 "heads": heads,
465 "heads": heads,
466 "keyword": keyword,
466 "keyword": keyword,
467 "limit": limit,
467 "limit": limit,
468 "max": maxrev,
468 "max": maxrev,
469 "merge": merge,
469 "merge": merge,
470 "modifies": modifies,
470 "modifies": modifies,
471 "outgoing": outgoing,
471 "outgoing": outgoing,
472 "p1": p1,
472 "p1": p1,
473 "p2": p2,
473 "p2": p2,
474 "parents": parents,
474 "parents": parents,
475 "removes": removes,
475 "removes": removes,
476 "reverse": reverse,
476 "reverse": reverse,
477 "roots": roots,
477 "roots": roots,
478 "sort": sort,
478 "sort": sort,
479 "tagged": tagged,
479 "tagged": tagged,
480 "user": author,
480 "user": author,
481 }
481 }
482
482
483 methods = {
483 methods = {
484 "range": rangeset,
484 "range": rangeset,
485 "string": stringset,
485 "string": stringset,
486 "symbol": symbolset,
486 "symbol": symbolset,
487 "and": andset,
487 "and": andset,
488 "or": orset,
488 "or": orset,
489 "not": notset,
489 "not": notset,
490 "list": listset,
490 "list": listset,
491 "func": func,
491 "func": func,
492 }
492 }
493
493
494 def optimize(x, small):
494 def optimize(x, small):
495 if x == None:
495 if x == None:
496 return 0, x
496 return 0, x
497
497
498 smallbonus = 1
498 smallbonus = 1
499 if small:
499 if small:
500 smallbonus = .5
500 smallbonus = .5
501
501
502 op = x[0]
502 op = x[0]
503 if op == 'minus':
503 if op == 'minus':
504 return optimize(('and', x[1], ('not', x[2])), small)
504 return optimize(('and', x[1], ('not', x[2])), small)
505 elif op == 'dagrange':
505 elif op == 'dagrange':
506 return optimize(('and', ('func', ('symbol', 'descendants'), x[1]),
506 return optimize(('and', ('func', ('symbol', 'descendants'), x[1]),
507 ('func', ('symbol', 'ancestors'), x[2])), small)
507 ('func', ('symbol', 'ancestors'), x[2])), small)
508 elif op == 'dagrangepre':
508 elif op == 'dagrangepre':
509 return optimize(('func', ('symbol', 'ancestors'), x[1]), small)
509 return optimize(('func', ('symbol', 'ancestors'), x[1]), small)
510 elif op == 'dagrangepost':
510 elif op == 'dagrangepost':
511 return optimize(('func', ('symbol', 'descendants'), x[1]), small)
511 return optimize(('func', ('symbol', 'descendants'), x[1]), small)
512 elif op == 'rangepre':
512 elif op == 'rangepre':
513 return optimize(('range', ('string', '0'), x[1]), small)
513 return optimize(('range', ('string', '0'), x[1]), small)
514 elif op == 'rangepost':
514 elif op == 'rangepost':
515 return optimize(('range', x[1], ('string', 'tip')), small)
515 return optimize(('range', x[1], ('string', 'tip')), small)
516 elif op == 'negate':
516 elif op == 'negate':
517 return optimize(('string',
517 return optimize(('string',
518 '-' + getstring(x[1], _("can't negate that"))), small)
518 '-' + getstring(x[1], _("can't negate that"))), small)
519 elif op in 'string symbol negate':
519 elif op in 'string symbol negate':
520 return smallbonus, x # single revisions are small
520 return smallbonus, x # single revisions are small
521 elif op == 'and' or op == 'dagrange':
521 elif op == 'and' or op == 'dagrange':
522 wa, ta = optimize(x[1], True)
522 wa, ta = optimize(x[1], True)
523 wb, tb = optimize(x[2], True)
523 wb, tb = optimize(x[2], True)
524 w = min(wa, wb)
524 w = min(wa, wb)
525 if wa > wb:
525 if wa > wb:
526 return w, (op, tb, ta)
526 return w, (op, tb, ta)
527 return w, (op, ta, tb)
527 return w, (op, ta, tb)
528 elif op == 'or':
528 elif op == 'or':
529 wa, ta = optimize(x[1], False)
529 wa, ta = optimize(x[1], False)
530 wb, tb = optimize(x[2], False)
530 wb, tb = optimize(x[2], False)
531 if wb < wa:
531 if wb < wa:
532 wb, wa = wa, wb
532 wb, wa = wa, wb
533 return max(wa, wb), (op, ta, tb)
533 return max(wa, wb), (op, ta, tb)
534 elif op == 'not':
534 elif op == 'not':
535 o = optimize(x[1], not small)
535 o = optimize(x[1], not small)
536 return o[0], (op, o[1])
536 return o[0], (op, o[1])
537 elif op == 'group':
537 elif op == 'group':
538 return optimize(x[1], small)
538 return optimize(x[1], small)
539 elif op in 'range list':
539 elif op in 'range list':
540 wa, ta = optimize(x[1], small)
540 wa, ta = optimize(x[1], small)
541 wb, tb = optimize(x[2], small)
541 wb, tb = optimize(x[2], small)
542 return wa + wb, (op, ta, tb)
542 return wa + wb, (op, ta, tb)
543 elif op == 'func':
543 elif op == 'func':
544 f = getstring(x[1], _("not a symbol"))
544 f = getstring(x[1], _("not a symbol"))
545 wa, ta = optimize(x[2], small)
545 wa, ta = optimize(x[2], small)
546 if f in "grep date user author keyword branch file":
546 if f in "grep date user author keyword branch file":
547 w = 10 # slow
547 w = 10 # slow
548 elif f in "modifies adds removes outgoing":
548 elif f in "modifies adds removes outgoing":
549 w = 30 # slower
549 w = 30 # slower
550 elif f == "contains":
550 elif f == "contains":
551 w = 100 # very slow
551 w = 100 # very slow
552 elif f == "ancestor":
552 elif f == "ancestor":
553 w = 1 * smallbonus
553 w = 1 * smallbonus
554 elif f == "reverse limit":
554 elif f == "reverse limit":
555 w = 0
555 w = 0
556 elif f in "sort":
556 elif f in "sort":
557 w = 10 # assume most sorts look at changelog
557 w = 10 # assume most sorts look at changelog
558 else:
558 else:
559 w = 1
559 w = 1
560 return w + wa, (op, x[1], ta)
560 return w + wa, (op, x[1], ta)
561 return 1, x
561 return 1, x
562
562
563 parse = parser.parser(tokenize, elements).parse
563 parse = parser.parser(tokenize, elements).parse
564
564
565 def match(spec):
565 def match(spec):
566 if not spec:
566 if not spec:
567 raise error.ParseError(_("empty query"))
567 raise error.ParseError(_("empty query"))
568 tree = parse(spec)
568 tree = parse(spec)
569 weight, tree = optimize(tree, True)
569 weight, tree = optimize(tree, True)
570 def mfunc(repo, subset):
570 def mfunc(repo, subset):
571 return getset(repo, subset, tree)
571 return getset(repo, subset, tree)
572 return mfunc
572 return mfunc
@@ -1,137 +1,145 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 HGENCODING=utf-8
3 HGENCODING=utf-8
4 export HGENCODING
4 export HGENCODING
5
5
6 try() {
6 try() {
7 echo '% hg debugrevspec' $@
7 echo '% hg debugrevspec' $@
8 hg debugrevspec --debug $@
8 hg debugrevspec --debug $@
9 }
9 }
10
10
11 log() {
11 log() {
12 echo "% log '$1'"
12 echo "% log '$1'"
13 hg log --template '{rev}\n' -r "$1"
13 hg log --template '{rev}\n' -r "$1"
14 }
14 }
15
15
16 hg init repo
16 hg init repo
17 cd repo
17 cd repo
18
18
19 echo a > a
19 echo a > a
20 hg branch a
20 hg branch a
21 hg ci -Aqm0
21 hg ci -Aqm0
22
22
23 echo b > b
23 echo b > b
24 hg branch b
24 hg branch b
25 hg ci -Aqm1
25 hg ci -Aqm1
26
26
27 rm a
27 rm a
28 hg branch a-b-c-
28 hg branch a-b-c-
29 hg ci -Aqm2 -u Bob
29 hg ci -Aqm2 -u Bob
30
30
31 hg co 1
31 hg co 1
32 hg branch +a+b+c+
32 hg branch +a+b+c+
33 hg ci -Aqm3
33 hg ci -Aqm3
34
34
35 hg co 2 # interleave
35 hg co 2 # interleave
36 echo bb > b
36 echo bb > b
37 hg branch -- -a-b-c-
37 hg branch -- -a-b-c-
38 hg ci -Aqm4 -d "May 12 2005"
38 hg ci -Aqm4 -d "May 12 2005"
39
39
40 hg co 3
40 hg co 3
41 hg branch /a/b/c/
41 hg branch /a/b/c/
42 hg ci -Aqm"5 bug"
42 hg ci -Aqm"5 bug"
43
43
44 hg merge 4
44 hg merge 4
45 hg branch _a_b_c_
45 hg branch _a_b_c_
46 hg ci -Aqm"6 issue619"
46 hg ci -Aqm"6 issue619"
47
47
48 hg branch .a.b.c.
48 hg branch .a.b.c.
49 hg ci -Aqm7
49 hg ci -Aqm7
50
50
51 hg branch all
51 hg branch all
52 hg ci --close-branch -Aqm8
52 hg ci --close-branch -Aqm8
53
53
54 hg co 4
54 hg co 4
55 hg branch Γ©
55 hg branch Γ©
56 hg ci -Aqm9
56 hg ci -Aqm9
57
57
58 hg tag -r6 1.0
58 hg tag -r6 1.0
59
59
60 hg clone --quiet -U -r 7 . ../remote1
61 hg clone --quiet -U -r 8 . ../remote2
62 echo "[paths]" >> .hg/hgrc
63 echo "default = ../remote1" >> .hg/hgrc
64
60 # names that should work without quoting
65 # names that should work without quoting
61 try a
66 try a
62 try b-a
67 try b-a
63 try _a_b_c_
68 try _a_b_c_
64 try _a_b_c_-a
69 try _a_b_c_-a
65 try .a.b.c.
70 try .a.b.c.
66 try .a.b.c.-a
71 try .a.b.c.-a
67 try -- '-a-b-c-' # complains
72 try -- '-a-b-c-' # complains
68 log -a-b-c- # succeeds with fallback
73 log -a-b-c- # succeeds with fallback
69 try -- -a-b-c--a # complains
74 try -- -a-b-c--a # complains
70 try Γ©
75 try Γ©
71
76
72 # quoting needed
77 # quoting needed
73 try '"-a-b-c-"-a'
78 try '"-a-b-c-"-a'
74
79
75 log '1 or 2'
80 log '1 or 2'
76 log '1|2'
81 log '1|2'
77 log '1 and 2'
82 log '1 and 2'
78 log '1&2'
83 log '1&2'
79 try '1&2|3' # precedence - and is higher
84 try '1&2|3' # precedence - and is higher
80 try '1|2&3'
85 try '1|2&3'
81 try '1&2&3' # associativity
86 try '1&2&3' # associativity
82 try '1|(2|3)'
87 try '1|(2|3)'
83 log '1.0' # tag
88 log '1.0' # tag
84 log 'a' # branch
89 log 'a' # branch
85 log '2785f51ee'
90 log '2785f51ee'
86 log 'date(2005)'
91 log 'date(2005)'
87 log 'date(this is a test)'
92 log 'date(this is a test)'
88 log 'date()'
93 log 'date()'
89 log 'date'
94 log 'date'
90 log 'date('
95 log 'date('
91 log 'date(tip)'
96 log 'date(tip)'
92 log '"date"'
97 log '"date"'
93 log 'date(2005) and 1::'
98 log 'date(2005) and 1::'
94
99
95 log 'ancestor(1)'
100 log 'ancestor(1)'
96 log 'ancestor(4,5)'
101 log 'ancestor(4,5)'
97 log 'ancestor(4,5) and 4'
102 log 'ancestor(4,5) and 4'
98 log 'ancestors(5)'
103 log 'ancestors(5)'
99 log 'author(bob)'
104 log 'author(bob)'
100 log 'branch(Γ©)'
105 log 'branch(Γ©)'
101 log 'children(ancestor(4,5))'
106 log 'children(ancestor(4,5))'
102 log 'closed()'
107 log 'closed()'
103 log 'contains(a)'
108 log 'contains(a)'
104 log 'descendants(2 or 3)'
109 log 'descendants(2 or 3)'
105 log 'file(b)'
110 log 'file(b)'
106 log 'follow()'
111 log 'follow()'
107 log 'grep("issue\d+")'
112 log 'grep("issue\d+")'
108 log 'head()'
113 log 'head()'
109 log 'heads(6::)'
114 log 'heads(6::)'
110 log 'keyword(issue)'
115 log 'keyword(issue)'
111 log 'limit(head(), 1)'
116 log 'limit(head(), 1)'
112 log 'max(contains(a))'
117 log 'max(contains(a))'
113 log 'merge()'
118 log 'merge()'
114 log 'modifies(b)'
119 log 'modifies(b)'
120 log 'outgoing()'
121 log 'outgoing("../remote1")'
122 log 'outgoing("../remote2")'
115 log 'p1(merge())'
123 log 'p1(merge())'
116 log 'p2(merge())'
124 log 'p2(merge())'
117 log 'parents(merge())'
125 log 'parents(merge())'
118 log 'removes(a)'
126 log 'removes(a)'
119 log 'roots(all())'
127 log 'roots(all())'
120 log 'reverse(2 or 3 or 4 or 5)'
128 log 'reverse(2 or 3 or 4 or 5)'
121 log 'sort(limit(reverse(all()), 3))'
129 log 'sort(limit(reverse(all()), 3))'
122 log 'sort(2 or 3 or 4 or 5, date)'
130 log 'sort(2 or 3 or 4 or 5, date)'
123 log 'tagged()'
131 log 'tagged()'
124 log 'user(bob)'
132 log 'user(bob)'
125
133
126 log '4::8'
134 log '4::8'
127 log '4:8'
135 log '4:8'
128
136
129 log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
137 log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
130
138
131 log 'not 0 and 0:2'
139 log 'not 0 and 0:2'
132 log 'not 1 and 0:2'
140 log 'not 1 and 0:2'
133 log 'not 2 and 0:2'
141 log 'not 2 and 0:2'
134 log '(1 and 2)::'
142 log '(1 and 2)::'
135 log '(1 and 2):'
143 log '(1 and 2):'
136 log '(1 and 2):3'
144 log '(1 and 2):3'
137 log 'sort(head(), -rev)'
145 log 'sort(head(), -rev)'
@@ -1,223 +1,235 b''
1 marked working directory as branch a
1 marked working directory as branch a
2 marked working directory as branch b
2 marked working directory as branch b
3 marked working directory as branch a-b-c-
3 marked working directory as branch a-b-c-
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 marked working directory as branch +a+b+c+
5 marked working directory as branch +a+b+c+
6 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
6 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
7 marked working directory as branch -a-b-c-
7 marked working directory as branch -a-b-c-
8 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
8 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
9 marked working directory as branch /a/b/c/
9 marked working directory as branch /a/b/c/
10 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
10 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
11 (branch merge, don't forget to commit)
11 (branch merge, don't forget to commit)
12 marked working directory as branch _a_b_c_
12 marked working directory as branch _a_b_c_
13 marked working directory as branch .a.b.c.
13 marked working directory as branch .a.b.c.
14 marked working directory as branch all
14 marked working directory as branch all
15 abort: can only close branch heads
15 abort: can only close branch heads
16 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 marked working directory as branch Γ©
17 marked working directory as branch Γ©
18 % hg debugrevspec a
18 % hg debugrevspec a
19 ('symbol', 'a')
19 ('symbol', 'a')
20 0
20 0
21 % hg debugrevspec b-a
21 % hg debugrevspec b-a
22 ('minus', ('symbol', 'b'), ('symbol', 'a'))
22 ('minus', ('symbol', 'b'), ('symbol', 'a'))
23 1
23 1
24 % hg debugrevspec _a_b_c_
24 % hg debugrevspec _a_b_c_
25 ('symbol', '_a_b_c_')
25 ('symbol', '_a_b_c_')
26 6
26 6
27 % hg debugrevspec _a_b_c_-a
27 % hg debugrevspec _a_b_c_-a
28 ('minus', ('symbol', '_a_b_c_'), ('symbol', 'a'))
28 ('minus', ('symbol', '_a_b_c_'), ('symbol', 'a'))
29 6
29 6
30 % hg debugrevspec .a.b.c.
30 % hg debugrevspec .a.b.c.
31 ('symbol', '.a.b.c.')
31 ('symbol', '.a.b.c.')
32 7
32 7
33 % hg debugrevspec .a.b.c.-a
33 % hg debugrevspec .a.b.c.-a
34 ('minus', ('symbol', '.a.b.c.'), ('symbol', 'a'))
34 ('minus', ('symbol', '.a.b.c.'), ('symbol', 'a'))
35 7
35 7
36 % hg debugrevspec -- -a-b-c-
36 % hg debugrevspec -- -a-b-c-
37 hg: parse error at 7: not a prefix: end
37 hg: parse error at 7: not a prefix: end
38 % log '-a-b-c-'
38 % log '-a-b-c-'
39 4
39 4
40 % hg debugrevspec -- -a-b-c--a
40 % hg debugrevspec -- -a-b-c--a
41 ('minus', ('minus', ('minus', ('negate', ('symbol', 'a')), ('symbol', 'b')), ('symbol', 'c')), ('negate', ('symbol', 'a')))
41 ('minus', ('minus', ('minus', ('negate', ('symbol', 'a')), ('symbol', 'b')), ('symbol', 'c')), ('negate', ('symbol', 'a')))
42 abort: unknown revision '-a'!
42 abort: unknown revision '-a'!
43 % hg debugrevspec Γ©
43 % hg debugrevspec Γ©
44 ('symbol', '\xc3\xa9')
44 ('symbol', '\xc3\xa9')
45 9
45 9
46 % hg debugrevspec "-a-b-c-"-a
46 % hg debugrevspec "-a-b-c-"-a
47 ('minus', ('string', '-a-b-c-'), ('symbol', 'a'))
47 ('minus', ('string', '-a-b-c-'), ('symbol', 'a'))
48 4
48 4
49 % log '1 or 2'
49 % log '1 or 2'
50 1
50 1
51 2
51 2
52 % log '1|2'
52 % log '1|2'
53 1
53 1
54 2
54 2
55 % log '1 and 2'
55 % log '1 and 2'
56 % log '1&2'
56 % log '1&2'
57 % hg debugrevspec 1&2|3
57 % hg debugrevspec 1&2|3
58 ('or', ('and', ('symbol', '1'), ('symbol', '2')), ('symbol', '3'))
58 ('or', ('and', ('symbol', '1'), ('symbol', '2')), ('symbol', '3'))
59 3
59 3
60 % hg debugrevspec 1|2&3
60 % hg debugrevspec 1|2&3
61 ('or', ('symbol', '1'), ('and', ('symbol', '2'), ('symbol', '3')))
61 ('or', ('symbol', '1'), ('and', ('symbol', '2'), ('symbol', '3')))
62 1
62 1
63 % hg debugrevspec 1&2&3
63 % hg debugrevspec 1&2&3
64 ('and', ('and', ('symbol', '1'), ('symbol', '2')), ('symbol', '3'))
64 ('and', ('and', ('symbol', '1'), ('symbol', '2')), ('symbol', '3'))
65 % hg debugrevspec 1|(2|3)
65 % hg debugrevspec 1|(2|3)
66 ('or', ('symbol', '1'), ('group', ('or', ('symbol', '2'), ('symbol', '3'))))
66 ('or', ('symbol', '1'), ('group', ('or', ('symbol', '2'), ('symbol', '3'))))
67 1
67 1
68 2
68 2
69 3
69 3
70 % log '1.0'
70 % log '1.0'
71 6
71 6
72 % log 'a'
72 % log 'a'
73 0
73 0
74 % log '2785f51ee'
74 % log '2785f51ee'
75 0
75 0
76 % log 'date(2005)'
76 % log 'date(2005)'
77 4
77 4
78 % log 'date(this is a test)'
78 % log 'date(this is a test)'
79 hg: parse error at 10: unexpected token: symbol
79 hg: parse error at 10: unexpected token: symbol
80 % log 'date()'
80 % log 'date()'
81 hg: parse error: date wants a string
81 hg: parse error: date wants a string
82 % log 'date'
82 % log 'date'
83 hg: parse error: can't use date here
83 hg: parse error: can't use date here
84 % log 'date('
84 % log 'date('
85 hg: parse error at 5: not a prefix: end
85 hg: parse error at 5: not a prefix: end
86 % log 'date(tip)'
86 % log 'date(tip)'
87 abort: invalid date: 'tip'
87 abort: invalid date: 'tip'
88 % log '"date"'
88 % log '"date"'
89 abort: unknown revision 'date'!
89 abort: unknown revision 'date'!
90 % log 'date(2005) and 1::'
90 % log 'date(2005) and 1::'
91 4
91 4
92 % log 'ancestor(1)'
92 % log 'ancestor(1)'
93 hg: parse error: ancestor wants two arguments
93 hg: parse error: ancestor wants two arguments
94 % log 'ancestor(4,5)'
94 % log 'ancestor(4,5)'
95 1
95 1
96 % log 'ancestor(4,5) and 4'
96 % log 'ancestor(4,5) and 4'
97 % log 'ancestors(5)'
97 % log 'ancestors(5)'
98 0
98 0
99 1
99 1
100 3
100 3
101 5
101 5
102 % log 'author(bob)'
102 % log 'author(bob)'
103 2
103 2
104 % log 'branch(Γ©)'
104 % log 'branch(Γ©)'
105 8
105 8
106 9
106 9
107 % log 'children(ancestor(4,5))'
107 % log 'children(ancestor(4,5))'
108 2
108 2
109 3
109 3
110 % log 'closed()'
110 % log 'closed()'
111 % log 'contains(a)'
111 % log 'contains(a)'
112 0
112 0
113 1
113 1
114 3
114 3
115 5
115 5
116 % log 'descendants(2 or 3)'
116 % log 'descendants(2 or 3)'
117 2
117 2
118 3
118 3
119 4
119 4
120 5
120 5
121 6
121 6
122 7
122 7
123 8
123 8
124 9
124 9
125 % log 'file(b)'
125 % log 'file(b)'
126 1
126 1
127 4
127 4
128 % log 'follow()'
128 % log 'follow()'
129 0
129 0
130 1
130 1
131 2
131 2
132 4
132 4
133 8
133 8
134 9
134 9
135 % log 'grep("issue\d+")'
135 % log 'grep("issue\d+")'
136 6
136 6
137 % log 'head()'
137 % log 'head()'
138 0
138 0
139 1
139 1
140 2
140 2
141 3
141 3
142 4
142 4
143 5
143 5
144 6
144 6
145 7
145 7
146 9
146 9
147 % log 'heads(6::)'
147 % log 'heads(6::)'
148 7
148 7
149 % log 'keyword(issue)'
149 % log 'keyword(issue)'
150 6
150 6
151 % log 'limit(head(), 1)'
151 % log 'limit(head(), 1)'
152 0
152 0
153 % log 'max(contains(a))'
153 % log 'max(contains(a))'
154 5
154 5
155 % log 'merge()'
155 % log 'merge()'
156 6
156 6
157 % log 'modifies(b)'
157 % log 'modifies(b)'
158 4
158 4
159 % log 'outgoing()'
160 8
161 9
162 % log 'outgoing("../remote1")'
163 8
164 9
165 % log 'outgoing("../remote2")'
166 3
167 5
168 6
169 7
170 9
159 % log 'p1(merge())'
171 % log 'p1(merge())'
160 5
172 5
161 % log 'p2(merge())'
173 % log 'p2(merge())'
162 4
174 4
163 % log 'parents(merge())'
175 % log 'parents(merge())'
164 4
176 4
165 5
177 5
166 % log 'removes(a)'
178 % log 'removes(a)'
167 2
179 2
168 6
180 6
169 % log 'roots(all())'
181 % log 'roots(all())'
170 0
182 0
171 % log 'reverse(2 or 3 or 4 or 5)'
183 % log 'reverse(2 or 3 or 4 or 5)'
172 5
184 5
173 4
185 4
174 3
186 3
175 2
187 2
176 % log 'sort(limit(reverse(all()), 3))'
188 % log 'sort(limit(reverse(all()), 3))'
177 7
189 7
178 8
190 8
179 9
191 9
180 % log 'sort(2 or 3 or 4 or 5, date)'
192 % log 'sort(2 or 3 or 4 or 5, date)'
181 2
193 2
182 3
194 3
183 5
195 5
184 4
196 4
185 % log 'tagged()'
197 % log 'tagged()'
186 6
198 6
187 % log 'user(bob)'
199 % log 'user(bob)'
188 2
200 2
189 % log '4::8'
201 % log '4::8'
190 4
202 4
191 8
203 8
192 % log '4:8'
204 % log '4:8'
193 4
205 4
194 5
206 5
195 6
207 6
196 7
208 7
197 8
209 8
198 % log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
210 % log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
199 4
211 4
200 2
212 2
201 5
213 5
202 % log 'not 0 and 0:2'
214 % log 'not 0 and 0:2'
203 1
215 1
204 2
216 2
205 % log 'not 1 and 0:2'
217 % log 'not 1 and 0:2'
206 0
218 0
207 2
219 2
208 % log 'not 2 and 0:2'
220 % log 'not 2 and 0:2'
209 0
221 0
210 1
222 1
211 % log '(1 and 2)::'
223 % log '(1 and 2)::'
212 % log '(1 and 2):'
224 % log '(1 and 2):'
213 % log '(1 and 2):3'
225 % log '(1 and 2):3'
214 % log 'sort(head(), -rev)'
226 % log 'sort(head(), -rev)'
215 9
227 9
216 7
228 7
217 6
229 6
218 5
230 5
219 4
231 4
220 3
232 3
221 2
233 2
222 1
234 1
223 0
235 0
General Comments 0
You need to be logged in to leave comments. Login now