##// END OF EJS Templates
revset: wrap arguments of 'or' by 'list' node...
Yuya Nishihara -
r29929:b3845cab default
parent child Browse files
Show More
@@ -1,3731 +1,3738 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 heapq
10 import heapq
11 import re
11 import re
12
12
13 from .i18n import _
13 from .i18n import _
14 from . import (
14 from . import (
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 parser,
22 parser,
23 pathutil,
23 pathutil,
24 phases,
24 phases,
25 registrar,
25 registrar,
26 repoview,
26 repoview,
27 util,
27 util,
28 )
28 )
29
29
30 def _revancestors(repo, revs, followfirst):
30 def _revancestors(repo, revs, followfirst):
31 """Like revlog.ancestors(), but supports followfirst."""
31 """Like revlog.ancestors(), but supports followfirst."""
32 if followfirst:
32 if followfirst:
33 cut = 1
33 cut = 1
34 else:
34 else:
35 cut = None
35 cut = None
36 cl = repo.changelog
36 cl = repo.changelog
37
37
38 def iterate():
38 def iterate():
39 revs.sort(reverse=True)
39 revs.sort(reverse=True)
40 irevs = iter(revs)
40 irevs = iter(revs)
41 h = []
41 h = []
42
42
43 inputrev = next(irevs, None)
43 inputrev = next(irevs, None)
44 if inputrev is not None:
44 if inputrev is not None:
45 heapq.heappush(h, -inputrev)
45 heapq.heappush(h, -inputrev)
46
46
47 seen = set()
47 seen = set()
48 while h:
48 while h:
49 current = -heapq.heappop(h)
49 current = -heapq.heappop(h)
50 if current == inputrev:
50 if current == inputrev:
51 inputrev = next(irevs, None)
51 inputrev = next(irevs, None)
52 if inputrev is not None:
52 if inputrev is not None:
53 heapq.heappush(h, -inputrev)
53 heapq.heappush(h, -inputrev)
54 if current not in seen:
54 if current not in seen:
55 seen.add(current)
55 seen.add(current)
56 yield current
56 yield current
57 for parent in cl.parentrevs(current)[:cut]:
57 for parent in cl.parentrevs(current)[:cut]:
58 if parent != node.nullrev:
58 if parent != node.nullrev:
59 heapq.heappush(h, -parent)
59 heapq.heappush(h, -parent)
60
60
61 return generatorset(iterate(), iterasc=False)
61 return generatorset(iterate(), iterasc=False)
62
62
63 def _revdescendants(repo, revs, followfirst):
63 def _revdescendants(repo, revs, followfirst):
64 """Like revlog.descendants() but supports followfirst."""
64 """Like revlog.descendants() but supports followfirst."""
65 if followfirst:
65 if followfirst:
66 cut = 1
66 cut = 1
67 else:
67 else:
68 cut = None
68 cut = None
69
69
70 def iterate():
70 def iterate():
71 cl = repo.changelog
71 cl = repo.changelog
72 # XXX this should be 'parentset.min()' assuming 'parentset' is a
72 # XXX this should be 'parentset.min()' assuming 'parentset' is a
73 # smartset (and if it is not, it should.)
73 # smartset (and if it is not, it should.)
74 first = min(revs)
74 first = min(revs)
75 nullrev = node.nullrev
75 nullrev = node.nullrev
76 if first == nullrev:
76 if first == nullrev:
77 # Are there nodes with a null first parent and a non-null
77 # Are there nodes with a null first parent and a non-null
78 # second one? Maybe. Do we care? Probably not.
78 # second one? Maybe. Do we care? Probably not.
79 for i in cl:
79 for i in cl:
80 yield i
80 yield i
81 else:
81 else:
82 seen = set(revs)
82 seen = set(revs)
83 for i in cl.revs(first + 1):
83 for i in cl.revs(first + 1):
84 for x in cl.parentrevs(i)[:cut]:
84 for x in cl.parentrevs(i)[:cut]:
85 if x != nullrev and x in seen:
85 if x != nullrev and x in seen:
86 seen.add(i)
86 seen.add(i)
87 yield i
87 yield i
88 break
88 break
89
89
90 return generatorset(iterate(), iterasc=True)
90 return generatorset(iterate(), iterasc=True)
91
91
92 def _reachablerootspure(repo, minroot, roots, heads, includepath):
92 def _reachablerootspure(repo, minroot, roots, heads, includepath):
93 """return (heads(::<roots> and ::<heads>))
93 """return (heads(::<roots> and ::<heads>))
94
94
95 If includepath is True, return (<roots>::<heads>)."""
95 If includepath is True, return (<roots>::<heads>)."""
96 if not roots:
96 if not roots:
97 return []
97 return []
98 parentrevs = repo.changelog.parentrevs
98 parentrevs = repo.changelog.parentrevs
99 roots = set(roots)
99 roots = set(roots)
100 visit = list(heads)
100 visit = list(heads)
101 reachable = set()
101 reachable = set()
102 seen = {}
102 seen = {}
103 # prefetch all the things! (because python is slow)
103 # prefetch all the things! (because python is slow)
104 reached = reachable.add
104 reached = reachable.add
105 dovisit = visit.append
105 dovisit = visit.append
106 nextvisit = visit.pop
106 nextvisit = visit.pop
107 # open-code the post-order traversal due to the tiny size of
107 # open-code the post-order traversal due to the tiny size of
108 # sys.getrecursionlimit()
108 # sys.getrecursionlimit()
109 while visit:
109 while visit:
110 rev = nextvisit()
110 rev = nextvisit()
111 if rev in roots:
111 if rev in roots:
112 reached(rev)
112 reached(rev)
113 if not includepath:
113 if not includepath:
114 continue
114 continue
115 parents = parentrevs(rev)
115 parents = parentrevs(rev)
116 seen[rev] = parents
116 seen[rev] = parents
117 for parent in parents:
117 for parent in parents:
118 if parent >= minroot and parent not in seen:
118 if parent >= minroot and parent not in seen:
119 dovisit(parent)
119 dovisit(parent)
120 if not reachable:
120 if not reachable:
121 return baseset()
121 return baseset()
122 if not includepath:
122 if not includepath:
123 return reachable
123 return reachable
124 for rev in sorted(seen):
124 for rev in sorted(seen):
125 for parent in seen[rev]:
125 for parent in seen[rev]:
126 if parent in reachable:
126 if parent in reachable:
127 reached(rev)
127 reached(rev)
128 return reachable
128 return reachable
129
129
130 def reachableroots(repo, roots, heads, includepath=False):
130 def reachableroots(repo, roots, heads, includepath=False):
131 """return (heads(::<roots> and ::<heads>))
131 """return (heads(::<roots> and ::<heads>))
132
132
133 If includepath is True, return (<roots>::<heads>)."""
133 If includepath is True, return (<roots>::<heads>)."""
134 if not roots:
134 if not roots:
135 return baseset()
135 return baseset()
136 minroot = roots.min()
136 minroot = roots.min()
137 roots = list(roots)
137 roots = list(roots)
138 heads = list(heads)
138 heads = list(heads)
139 try:
139 try:
140 revs = repo.changelog.reachableroots(minroot, heads, roots, includepath)
140 revs = repo.changelog.reachableroots(minroot, heads, roots, includepath)
141 except AttributeError:
141 except AttributeError:
142 revs = _reachablerootspure(repo, minroot, roots, heads, includepath)
142 revs = _reachablerootspure(repo, minroot, roots, heads, includepath)
143 revs = baseset(revs)
143 revs = baseset(revs)
144 revs.sort()
144 revs.sort()
145 return revs
145 return revs
146
146
147 elements = {
147 elements = {
148 # token-type: binding-strength, primary, prefix, infix, suffix
148 # token-type: binding-strength, primary, prefix, infix, suffix
149 "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None),
149 "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None),
150 "##": (20, None, None, ("_concat", 20), None),
150 "##": (20, None, None, ("_concat", 20), None),
151 "~": (18, None, None, ("ancestor", 18), None),
151 "~": (18, None, None, ("ancestor", 18), None),
152 "^": (18, None, None, ("parent", 18), "parentpost"),
152 "^": (18, None, None, ("parent", 18), "parentpost"),
153 "-": (5, None, ("negate", 19), ("minus", 5), None),
153 "-": (5, None, ("negate", 19), ("minus", 5), None),
154 "::": (17, None, ("dagrangepre", 17), ("dagrange", 17), "dagrangepost"),
154 "::": (17, None, ("dagrangepre", 17), ("dagrange", 17), "dagrangepost"),
155 "..": (17, None, ("dagrangepre", 17), ("dagrange", 17), "dagrangepost"),
155 "..": (17, None, ("dagrangepre", 17), ("dagrange", 17), "dagrangepost"),
156 ":": (15, "rangeall", ("rangepre", 15), ("range", 15), "rangepost"),
156 ":": (15, "rangeall", ("rangepre", 15), ("range", 15), "rangepost"),
157 "not": (10, None, ("not", 10), None, None),
157 "not": (10, None, ("not", 10), None, None),
158 "!": (10, None, ("not", 10), None, None),
158 "!": (10, None, ("not", 10), None, None),
159 "and": (5, None, None, ("and", 5), None),
159 "and": (5, None, None, ("and", 5), None),
160 "&": (5, None, None, ("and", 5), None),
160 "&": (5, None, None, ("and", 5), None),
161 "%": (5, None, None, ("only", 5), "onlypost"),
161 "%": (5, None, None, ("only", 5), "onlypost"),
162 "or": (4, None, None, ("or", 4), None),
162 "or": (4, None, None, ("or", 4), None),
163 "|": (4, None, None, ("or", 4), None),
163 "|": (4, None, None, ("or", 4), None),
164 "+": (4, None, None, ("or", 4), None),
164 "+": (4, None, None, ("or", 4), None),
165 "=": (3, None, None, ("keyvalue", 3), None),
165 "=": (3, None, None, ("keyvalue", 3), None),
166 ",": (2, None, None, ("list", 2), None),
166 ",": (2, None, None, ("list", 2), None),
167 ")": (0, None, None, None, None),
167 ")": (0, None, None, None, None),
168 "symbol": (0, "symbol", None, None, None),
168 "symbol": (0, "symbol", None, None, None),
169 "string": (0, "string", None, None, None),
169 "string": (0, "string", None, None, None),
170 "end": (0, None, None, None, None),
170 "end": (0, None, None, None, None),
171 }
171 }
172
172
173 keywords = set(['and', 'or', 'not'])
173 keywords = set(['and', 'or', 'not'])
174
174
175 # default set of valid characters for the initial letter of symbols
175 # default set of valid characters for the initial letter of symbols
176 _syminitletters = set(c for c in [chr(i) for i in xrange(256)]
176 _syminitletters = set(c for c in [chr(i) for i in xrange(256)]
177 if c.isalnum() or c in '._@' or ord(c) > 127)
177 if c.isalnum() or c in '._@' or ord(c) > 127)
178
178
179 # default set of valid characters for non-initial letters of symbols
179 # default set of valid characters for non-initial letters of symbols
180 _symletters = set(c for c in [chr(i) for i in xrange(256)]
180 _symletters = set(c for c in [chr(i) for i in xrange(256)]
181 if c.isalnum() or c in '-._/@' or ord(c) > 127)
181 if c.isalnum() or c in '-._/@' or ord(c) > 127)
182
182
183 def tokenize(program, lookup=None, syminitletters=None, symletters=None):
183 def tokenize(program, lookup=None, syminitletters=None, symletters=None):
184 '''
184 '''
185 Parse a revset statement into a stream of tokens
185 Parse a revset statement into a stream of tokens
186
186
187 ``syminitletters`` is the set of valid characters for the initial
187 ``syminitletters`` is the set of valid characters for the initial
188 letter of symbols.
188 letter of symbols.
189
189
190 By default, character ``c`` is recognized as valid for initial
190 By default, character ``c`` is recognized as valid for initial
191 letter of symbols, if ``c.isalnum() or c in '._@' or ord(c) > 127``.
191 letter of symbols, if ``c.isalnum() or c in '._@' or ord(c) > 127``.
192
192
193 ``symletters`` is the set of valid characters for non-initial
193 ``symletters`` is the set of valid characters for non-initial
194 letters of symbols.
194 letters of symbols.
195
195
196 By default, character ``c`` is recognized as valid for non-initial
196 By default, character ``c`` is recognized as valid for non-initial
197 letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``.
197 letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``.
198
198
199 Check that @ is a valid unquoted token character (issue3686):
199 Check that @ is a valid unquoted token character (issue3686):
200 >>> list(tokenize("@::"))
200 >>> list(tokenize("@::"))
201 [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)]
201 [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)]
202
202
203 '''
203 '''
204 if syminitletters is None:
204 if syminitletters is None:
205 syminitletters = _syminitletters
205 syminitletters = _syminitletters
206 if symletters is None:
206 if symletters is None:
207 symletters = _symletters
207 symletters = _symletters
208
208
209 if program and lookup:
209 if program and lookup:
210 # attempt to parse old-style ranges first to deal with
210 # attempt to parse old-style ranges first to deal with
211 # things like old-tag which contain query metacharacters
211 # things like old-tag which contain query metacharacters
212 parts = program.split(':', 1)
212 parts = program.split(':', 1)
213 if all(lookup(sym) for sym in parts if sym):
213 if all(lookup(sym) for sym in parts if sym):
214 if parts[0]:
214 if parts[0]:
215 yield ('symbol', parts[0], 0)
215 yield ('symbol', parts[0], 0)
216 if len(parts) > 1:
216 if len(parts) > 1:
217 s = len(parts[0])
217 s = len(parts[0])
218 yield (':', None, s)
218 yield (':', None, s)
219 if parts[1]:
219 if parts[1]:
220 yield ('symbol', parts[1], s + 1)
220 yield ('symbol', parts[1], s + 1)
221 yield ('end', None, len(program))
221 yield ('end', None, len(program))
222 return
222 return
223
223
224 pos, l = 0, len(program)
224 pos, l = 0, len(program)
225 while pos < l:
225 while pos < l:
226 c = program[pos]
226 c = program[pos]
227 if c.isspace(): # skip inter-token whitespace
227 if c.isspace(): # skip inter-token whitespace
228 pass
228 pass
229 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
229 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
230 yield ('::', None, pos)
230 yield ('::', None, pos)
231 pos += 1 # skip ahead
231 pos += 1 # skip ahead
232 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
232 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
233 yield ('..', None, pos)
233 yield ('..', None, pos)
234 pos += 1 # skip ahead
234 pos += 1 # skip ahead
235 elif c == '#' and program[pos:pos + 2] == '##': # look ahead carefully
235 elif c == '#' and program[pos:pos + 2] == '##': # look ahead carefully
236 yield ('##', None, pos)
236 yield ('##', None, pos)
237 pos += 1 # skip ahead
237 pos += 1 # skip ahead
238 elif c in "():=,-|&+!~^%": # handle simple operators
238 elif c in "():=,-|&+!~^%": # handle simple operators
239 yield (c, None, pos)
239 yield (c, None, pos)
240 elif (c in '"\'' or c == 'r' and
240 elif (c in '"\'' or c == 'r' and
241 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
241 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
242 if c == 'r':
242 if c == 'r':
243 pos += 1
243 pos += 1
244 c = program[pos]
244 c = program[pos]
245 decode = lambda x: x
245 decode = lambda x: x
246 else:
246 else:
247 decode = parser.unescapestr
247 decode = parser.unescapestr
248 pos += 1
248 pos += 1
249 s = pos
249 s = pos
250 while pos < l: # find closing quote
250 while pos < l: # find closing quote
251 d = program[pos]
251 d = program[pos]
252 if d == '\\': # skip over escaped characters
252 if d == '\\': # skip over escaped characters
253 pos += 2
253 pos += 2
254 continue
254 continue
255 if d == c:
255 if d == c:
256 yield ('string', decode(program[s:pos]), s)
256 yield ('string', decode(program[s:pos]), s)
257 break
257 break
258 pos += 1
258 pos += 1
259 else:
259 else:
260 raise error.ParseError(_("unterminated string"), s)
260 raise error.ParseError(_("unterminated string"), s)
261 # gather up a symbol/keyword
261 # gather up a symbol/keyword
262 elif c in syminitletters:
262 elif c in syminitletters:
263 s = pos
263 s = pos
264 pos += 1
264 pos += 1
265 while pos < l: # find end of symbol
265 while pos < l: # find end of symbol
266 d = program[pos]
266 d = program[pos]
267 if d not in symletters:
267 if d not in symletters:
268 break
268 break
269 if d == '.' and program[pos - 1] == '.': # special case for ..
269 if d == '.' and program[pos - 1] == '.': # special case for ..
270 pos -= 1
270 pos -= 1
271 break
271 break
272 pos += 1
272 pos += 1
273 sym = program[s:pos]
273 sym = program[s:pos]
274 if sym in keywords: # operator keywords
274 if sym in keywords: # operator keywords
275 yield (sym, None, s)
275 yield (sym, None, s)
276 elif '-' in sym:
276 elif '-' in sym:
277 # some jerk gave us foo-bar-baz, try to check if it's a symbol
277 # some jerk gave us foo-bar-baz, try to check if it's a symbol
278 if lookup and lookup(sym):
278 if lookup and lookup(sym):
279 # looks like a real symbol
279 # looks like a real symbol
280 yield ('symbol', sym, s)
280 yield ('symbol', sym, s)
281 else:
281 else:
282 # looks like an expression
282 # looks like an expression
283 parts = sym.split('-')
283 parts = sym.split('-')
284 for p in parts[:-1]:
284 for p in parts[:-1]:
285 if p: # possible consecutive -
285 if p: # possible consecutive -
286 yield ('symbol', p, s)
286 yield ('symbol', p, s)
287 s += len(p)
287 s += len(p)
288 yield ('-', None, pos)
288 yield ('-', None, pos)
289 s += 1
289 s += 1
290 if parts[-1]: # possible trailing -
290 if parts[-1]: # possible trailing -
291 yield ('symbol', parts[-1], s)
291 yield ('symbol', parts[-1], s)
292 else:
292 else:
293 yield ('symbol', sym, s)
293 yield ('symbol', sym, s)
294 pos -= 1
294 pos -= 1
295 else:
295 else:
296 raise error.ParseError(_("syntax error in revset '%s'") %
296 raise error.ParseError(_("syntax error in revset '%s'") %
297 program, pos)
297 program, pos)
298 pos += 1
298 pos += 1
299 yield ('end', None, pos)
299 yield ('end', None, pos)
300
300
301 # helpers
301 # helpers
302
302
303 def getsymbol(x):
303 def getsymbol(x):
304 if x and x[0] == 'symbol':
304 if x and x[0] == 'symbol':
305 return x[1]
305 return x[1]
306 raise error.ParseError(_('not a symbol'))
306 raise error.ParseError(_('not a symbol'))
307
307
308 def getstring(x, err):
308 def getstring(x, err):
309 if x and (x[0] == 'string' or x[0] == 'symbol'):
309 if x and (x[0] == 'string' or x[0] == 'symbol'):
310 return x[1]
310 return x[1]
311 raise error.ParseError(err)
311 raise error.ParseError(err)
312
312
313 def getlist(x):
313 def getlist(x):
314 if not x:
314 if not x:
315 return []
315 return []
316 if x[0] == 'list':
316 if x[0] == 'list':
317 return list(x[1:])
317 return list(x[1:])
318 return [x]
318 return [x]
319
319
320 def getargs(x, min, max, err):
320 def getargs(x, min, max, err):
321 l = getlist(x)
321 l = getlist(x)
322 if len(l) < min or (max >= 0 and len(l) > max):
322 if len(l) < min or (max >= 0 and len(l) > max):
323 raise error.ParseError(err)
323 raise error.ParseError(err)
324 return l
324 return l
325
325
326 def getargsdict(x, funcname, keys):
326 def getargsdict(x, funcname, keys):
327 return parser.buildargsdict(getlist(x), funcname, keys.split(),
327 return parser.buildargsdict(getlist(x), funcname, keys.split(),
328 keyvaluenode='keyvalue', keynode='symbol')
328 keyvaluenode='keyvalue', keynode='symbol')
329
329
330 def getset(repo, subset, x):
330 def getset(repo, subset, x):
331 if not x:
331 if not x:
332 raise error.ParseError(_("missing argument"))
332 raise error.ParseError(_("missing argument"))
333 s = methods[x[0]](repo, subset, *x[1:])
333 s = methods[x[0]](repo, subset, *x[1:])
334 if util.safehasattr(s, 'isascending'):
334 if util.safehasattr(s, 'isascending'):
335 return s
335 return s
336 # else case should not happen, because all non-func are internal,
336 # else case should not happen, because all non-func are internal,
337 # ignoring for now.
337 # ignoring for now.
338 if x[0] == 'func' and x[1][0] == 'symbol' and x[1][1] in symbols:
338 if x[0] == 'func' and x[1][0] == 'symbol' and x[1][1] in symbols:
339 repo.ui.deprecwarn('revset "%s" uses list instead of smartset'
339 repo.ui.deprecwarn('revset "%s" uses list instead of smartset'
340 % x[1][1],
340 % x[1][1],
341 '3.9')
341 '3.9')
342 return baseset(s)
342 return baseset(s)
343
343
344 def _getrevsource(repo, r):
344 def _getrevsource(repo, r):
345 extra = repo[r].extra()
345 extra = repo[r].extra()
346 for label in ('source', 'transplant_source', 'rebase_source'):
346 for label in ('source', 'transplant_source', 'rebase_source'):
347 if label in extra:
347 if label in extra:
348 try:
348 try:
349 return repo[extra[label]].rev()
349 return repo[extra[label]].rev()
350 except error.RepoLookupError:
350 except error.RepoLookupError:
351 pass
351 pass
352 return None
352 return None
353
353
354 # operator methods
354 # operator methods
355
355
356 def stringset(repo, subset, x):
356 def stringset(repo, subset, x):
357 x = repo[x].rev()
357 x = repo[x].rev()
358 if (x in subset
358 if (x in subset
359 or x == node.nullrev and isinstance(subset, fullreposet)):
359 or x == node.nullrev and isinstance(subset, fullreposet)):
360 return baseset([x])
360 return baseset([x])
361 return baseset()
361 return baseset()
362
362
363 def rangeset(repo, subset, x, y):
363 def rangeset(repo, subset, x, y):
364 m = getset(repo, fullreposet(repo), x)
364 m = getset(repo, fullreposet(repo), x)
365 n = getset(repo, fullreposet(repo), y)
365 n = getset(repo, fullreposet(repo), y)
366
366
367 if not m or not n:
367 if not m or not n:
368 return baseset()
368 return baseset()
369 m, n = m.first(), n.last()
369 m, n = m.first(), n.last()
370
370
371 if m == n:
371 if m == n:
372 r = baseset([m])
372 r = baseset([m])
373 elif n == node.wdirrev:
373 elif n == node.wdirrev:
374 r = spanset(repo, m, len(repo)) + baseset([n])
374 r = spanset(repo, m, len(repo)) + baseset([n])
375 elif m == node.wdirrev:
375 elif m == node.wdirrev:
376 r = baseset([m]) + spanset(repo, len(repo) - 1, n - 1)
376 r = baseset([m]) + spanset(repo, len(repo) - 1, n - 1)
377 elif m < n:
377 elif m < n:
378 r = spanset(repo, m, n + 1)
378 r = spanset(repo, m, n + 1)
379 else:
379 else:
380 r = spanset(repo, m, n - 1)
380 r = spanset(repo, m, n - 1)
381 # XXX We should combine with subset first: 'subset & baseset(...)'. This is
381 # XXX We should combine with subset first: 'subset & baseset(...)'. This is
382 # necessary to ensure we preserve the order in subset.
382 # necessary to ensure we preserve the order in subset.
383 #
383 #
384 # This has performance implication, carrying the sorting over when possible
384 # This has performance implication, carrying the sorting over when possible
385 # would be more efficient.
385 # would be more efficient.
386 return r & subset
386 return r & subset
387
387
388 def dagrange(repo, subset, x, y):
388 def dagrange(repo, subset, x, y):
389 r = fullreposet(repo)
389 r = fullreposet(repo)
390 xs = reachableroots(repo, getset(repo, r, x), getset(repo, r, y),
390 xs = reachableroots(repo, getset(repo, r, x), getset(repo, r, y),
391 includepath=True)
391 includepath=True)
392 return subset & xs
392 return subset & xs
393
393
394 def andset(repo, subset, x, y):
394 def andset(repo, subset, x, y):
395 return getset(repo, getset(repo, subset, x), y)
395 return getset(repo, getset(repo, subset, x), y)
396
396
397 def differenceset(repo, subset, x, y):
397 def differenceset(repo, subset, x, y):
398 return getset(repo, subset, x) - getset(repo, subset, y)
398 return getset(repo, subset, x) - getset(repo, subset, y)
399
399
400 def orset(repo, subset, *xs):
400 def _orsetlist(repo, subset, xs):
401 assert xs
401 assert xs
402 if len(xs) == 1:
402 if len(xs) == 1:
403 return getset(repo, subset, xs[0])
403 return getset(repo, subset, xs[0])
404 p = len(xs) // 2
404 p = len(xs) // 2
405 a = orset(repo, subset, *xs[:p])
405 a = _orsetlist(repo, subset, xs[:p])
406 b = orset(repo, subset, *xs[p:])
406 b = _orsetlist(repo, subset, xs[p:])
407 return a + b
407 return a + b
408
408
409 def orset(repo, subset, x):
410 return _orsetlist(repo, subset, getlist(x))
411
409 def notset(repo, subset, x):
412 def notset(repo, subset, x):
410 return subset - getset(repo, subset, x)
413 return subset - getset(repo, subset, x)
411
414
412 def listset(repo, subset, *xs):
415 def listset(repo, subset, *xs):
413 raise error.ParseError(_("can't use a list in this context"),
416 raise error.ParseError(_("can't use a list in this context"),
414 hint=_('see hg help "revsets.x or y"'))
417 hint=_('see hg help "revsets.x or y"'))
415
418
416 def keyvaluepair(repo, subset, k, v):
419 def keyvaluepair(repo, subset, k, v):
417 raise error.ParseError(_("can't use a key-value pair in this context"))
420 raise error.ParseError(_("can't use a key-value pair in this context"))
418
421
419 def func(repo, subset, a, b):
422 def func(repo, subset, a, b):
420 f = getsymbol(a)
423 f = getsymbol(a)
421 if f in symbols:
424 if f in symbols:
422 return symbols[f](repo, subset, b)
425 return symbols[f](repo, subset, b)
423
426
424 keep = lambda fn: getattr(fn, '__doc__', None) is not None
427 keep = lambda fn: getattr(fn, '__doc__', None) is not None
425
428
426 syms = [s for (s, fn) in symbols.items() if keep(fn)]
429 syms = [s for (s, fn) in symbols.items() if keep(fn)]
427 raise error.UnknownIdentifier(f, syms)
430 raise error.UnknownIdentifier(f, syms)
428
431
429 # functions
432 # functions
430
433
431 # symbols are callables like:
434 # symbols are callables like:
432 # fn(repo, subset, x)
435 # fn(repo, subset, x)
433 # with:
436 # with:
434 # repo - current repository instance
437 # repo - current repository instance
435 # subset - of revisions to be examined
438 # subset - of revisions to be examined
436 # x - argument in tree form
439 # x - argument in tree form
437 symbols = {}
440 symbols = {}
438
441
439 # symbols which can't be used for a DoS attack for any given input
442 # symbols which can't be used for a DoS attack for any given input
440 # (e.g. those which accept regexes as plain strings shouldn't be included)
443 # (e.g. those which accept regexes as plain strings shouldn't be included)
441 # functions that just return a lot of changesets (like all) don't count here
444 # functions that just return a lot of changesets (like all) don't count here
442 safesymbols = set()
445 safesymbols = set()
443
446
444 predicate = registrar.revsetpredicate()
447 predicate = registrar.revsetpredicate()
445
448
446 @predicate('_destupdate')
449 @predicate('_destupdate')
447 def _destupdate(repo, subset, x):
450 def _destupdate(repo, subset, x):
448 # experimental revset for update destination
451 # experimental revset for update destination
449 args = getargsdict(x, 'limit', 'clean check')
452 args = getargsdict(x, 'limit', 'clean check')
450 return subset & baseset([destutil.destupdate(repo, **args)[0]])
453 return subset & baseset([destutil.destupdate(repo, **args)[0]])
451
454
452 @predicate('_destmerge')
455 @predicate('_destmerge')
453 def _destmerge(repo, subset, x):
456 def _destmerge(repo, subset, x):
454 # experimental revset for merge destination
457 # experimental revset for merge destination
455 sourceset = None
458 sourceset = None
456 if x is not None:
459 if x is not None:
457 sourceset = getset(repo, fullreposet(repo), x)
460 sourceset = getset(repo, fullreposet(repo), x)
458 return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)])
461 return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)])
459
462
460 @predicate('adds(pattern)', safe=True)
463 @predicate('adds(pattern)', safe=True)
461 def adds(repo, subset, x):
464 def adds(repo, subset, x):
462 """Changesets that add a file matching pattern.
465 """Changesets that add a file matching pattern.
463
466
464 The pattern without explicit kind like ``glob:`` is expected to be
467 The pattern without explicit kind like ``glob:`` is expected to be
465 relative to the current directory and match against a file or a
468 relative to the current directory and match against a file or a
466 directory.
469 directory.
467 """
470 """
468 # i18n: "adds" is a keyword
471 # i18n: "adds" is a keyword
469 pat = getstring(x, _("adds requires a pattern"))
472 pat = getstring(x, _("adds requires a pattern"))
470 return checkstatus(repo, subset, pat, 1)
473 return checkstatus(repo, subset, pat, 1)
471
474
472 @predicate('ancestor(*changeset)', safe=True)
475 @predicate('ancestor(*changeset)', safe=True)
473 def ancestor(repo, subset, x):
476 def ancestor(repo, subset, x):
474 """A greatest common ancestor of the changesets.
477 """A greatest common ancestor of the changesets.
475
478
476 Accepts 0 or more changesets.
479 Accepts 0 or more changesets.
477 Will return empty list when passed no args.
480 Will return empty list when passed no args.
478 Greatest common ancestor of a single changeset is that changeset.
481 Greatest common ancestor of a single changeset is that changeset.
479 """
482 """
480 # i18n: "ancestor" is a keyword
483 # i18n: "ancestor" is a keyword
481 l = getlist(x)
484 l = getlist(x)
482 rl = fullreposet(repo)
485 rl = fullreposet(repo)
483 anc = None
486 anc = None
484
487
485 # (getset(repo, rl, i) for i in l) generates a list of lists
488 # (getset(repo, rl, i) for i in l) generates a list of lists
486 for revs in (getset(repo, rl, i) for i in l):
489 for revs in (getset(repo, rl, i) for i in l):
487 for r in revs:
490 for r in revs:
488 if anc is None:
491 if anc is None:
489 anc = repo[r]
492 anc = repo[r]
490 else:
493 else:
491 anc = anc.ancestor(repo[r])
494 anc = anc.ancestor(repo[r])
492
495
493 if anc is not None and anc.rev() in subset:
496 if anc is not None and anc.rev() in subset:
494 return baseset([anc.rev()])
497 return baseset([anc.rev()])
495 return baseset()
498 return baseset()
496
499
497 def _ancestors(repo, subset, x, followfirst=False):
500 def _ancestors(repo, subset, x, followfirst=False):
498 heads = getset(repo, fullreposet(repo), x)
501 heads = getset(repo, fullreposet(repo), x)
499 if not heads:
502 if not heads:
500 return baseset()
503 return baseset()
501 s = _revancestors(repo, heads, followfirst)
504 s = _revancestors(repo, heads, followfirst)
502 return subset & s
505 return subset & s
503
506
504 @predicate('ancestors(set)', safe=True)
507 @predicate('ancestors(set)', safe=True)
505 def ancestors(repo, subset, x):
508 def ancestors(repo, subset, x):
506 """Changesets that are ancestors of a changeset in set.
509 """Changesets that are ancestors of a changeset in set.
507 """
510 """
508 return _ancestors(repo, subset, x)
511 return _ancestors(repo, subset, x)
509
512
510 @predicate('_firstancestors', safe=True)
513 @predicate('_firstancestors', safe=True)
511 def _firstancestors(repo, subset, x):
514 def _firstancestors(repo, subset, x):
512 # ``_firstancestors(set)``
515 # ``_firstancestors(set)``
513 # Like ``ancestors(set)`` but follows only the first parents.
516 # Like ``ancestors(set)`` but follows only the first parents.
514 return _ancestors(repo, subset, x, followfirst=True)
517 return _ancestors(repo, subset, x, followfirst=True)
515
518
516 def ancestorspec(repo, subset, x, n):
519 def ancestorspec(repo, subset, x, n):
517 """``set~n``
520 """``set~n``
518 Changesets that are the Nth ancestor (first parents only) of a changeset
521 Changesets that are the Nth ancestor (first parents only) of a changeset
519 in set.
522 in set.
520 """
523 """
521 try:
524 try:
522 n = int(n[1])
525 n = int(n[1])
523 except (TypeError, ValueError):
526 except (TypeError, ValueError):
524 raise error.ParseError(_("~ expects a number"))
527 raise error.ParseError(_("~ expects a number"))
525 ps = set()
528 ps = set()
526 cl = repo.changelog
529 cl = repo.changelog
527 for r in getset(repo, fullreposet(repo), x):
530 for r in getset(repo, fullreposet(repo), x):
528 for i in range(n):
531 for i in range(n):
529 r = cl.parentrevs(r)[0]
532 r = cl.parentrevs(r)[0]
530 ps.add(r)
533 ps.add(r)
531 return subset & ps
534 return subset & ps
532
535
533 @predicate('author(string)', safe=True)
536 @predicate('author(string)', safe=True)
534 def author(repo, subset, x):
537 def author(repo, subset, x):
535 """Alias for ``user(string)``.
538 """Alias for ``user(string)``.
536 """
539 """
537 # i18n: "author" is a keyword
540 # i18n: "author" is a keyword
538 n = encoding.lower(getstring(x, _("author requires a string")))
541 n = encoding.lower(getstring(x, _("author requires a string")))
539 kind, pattern, matcher = _substringmatcher(n)
542 kind, pattern, matcher = _substringmatcher(n)
540 return subset.filter(lambda x: matcher(encoding.lower(repo[x].user())),
543 return subset.filter(lambda x: matcher(encoding.lower(repo[x].user())),
541 condrepr=('<user %r>', n))
544 condrepr=('<user %r>', n))
542
545
543 @predicate('bisect(string)', safe=True)
546 @predicate('bisect(string)', safe=True)
544 def bisect(repo, subset, x):
547 def bisect(repo, subset, x):
545 """Changesets marked in the specified bisect status:
548 """Changesets marked in the specified bisect status:
546
549
547 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
550 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
548 - ``goods``, ``bads`` : csets topologically good/bad
551 - ``goods``, ``bads`` : csets topologically good/bad
549 - ``range`` : csets taking part in the bisection
552 - ``range`` : csets taking part in the bisection
550 - ``pruned`` : csets that are goods, bads or skipped
553 - ``pruned`` : csets that are goods, bads or skipped
551 - ``untested`` : csets whose fate is yet unknown
554 - ``untested`` : csets whose fate is yet unknown
552 - ``ignored`` : csets ignored due to DAG topology
555 - ``ignored`` : csets ignored due to DAG topology
553 - ``current`` : the cset currently being bisected
556 - ``current`` : the cset currently being bisected
554 """
557 """
555 # i18n: "bisect" is a keyword
558 # i18n: "bisect" is a keyword
556 status = getstring(x, _("bisect requires a string")).lower()
559 status = getstring(x, _("bisect requires a string")).lower()
557 state = set(hbisect.get(repo, status))
560 state = set(hbisect.get(repo, status))
558 return subset & state
561 return subset & state
559
562
560 # Backward-compatibility
563 # Backward-compatibility
561 # - no help entry so that we do not advertise it any more
564 # - no help entry so that we do not advertise it any more
562 @predicate('bisected', safe=True)
565 @predicate('bisected', safe=True)
563 def bisected(repo, subset, x):
566 def bisected(repo, subset, x):
564 return bisect(repo, subset, x)
567 return bisect(repo, subset, x)
565
568
566 @predicate('bookmark([name])', safe=True)
569 @predicate('bookmark([name])', safe=True)
567 def bookmark(repo, subset, x):
570 def bookmark(repo, subset, x):
568 """The named bookmark or all bookmarks.
571 """The named bookmark or all bookmarks.
569
572
570 If `name` starts with `re:`, the remainder of the name is treated as
573 If `name` starts with `re:`, the remainder of the name is treated as
571 a regular expression. To match a bookmark that actually starts with `re:`,
574 a regular expression. To match a bookmark that actually starts with `re:`,
572 use the prefix `literal:`.
575 use the prefix `literal:`.
573 """
576 """
574 # i18n: "bookmark" is a keyword
577 # i18n: "bookmark" is a keyword
575 args = getargs(x, 0, 1, _('bookmark takes one or no arguments'))
578 args = getargs(x, 0, 1, _('bookmark takes one or no arguments'))
576 if args:
579 if args:
577 bm = getstring(args[0],
580 bm = getstring(args[0],
578 # i18n: "bookmark" is a keyword
581 # i18n: "bookmark" is a keyword
579 _('the argument to bookmark must be a string'))
582 _('the argument to bookmark must be a string'))
580 kind, pattern, matcher = util.stringmatcher(bm)
583 kind, pattern, matcher = util.stringmatcher(bm)
581 bms = set()
584 bms = set()
582 if kind == 'literal':
585 if kind == 'literal':
583 bmrev = repo._bookmarks.get(pattern, None)
586 bmrev = repo._bookmarks.get(pattern, None)
584 if not bmrev:
587 if not bmrev:
585 raise error.RepoLookupError(_("bookmark '%s' does not exist")
588 raise error.RepoLookupError(_("bookmark '%s' does not exist")
586 % pattern)
589 % pattern)
587 bms.add(repo[bmrev].rev())
590 bms.add(repo[bmrev].rev())
588 else:
591 else:
589 matchrevs = set()
592 matchrevs = set()
590 for name, bmrev in repo._bookmarks.iteritems():
593 for name, bmrev in repo._bookmarks.iteritems():
591 if matcher(name):
594 if matcher(name):
592 matchrevs.add(bmrev)
595 matchrevs.add(bmrev)
593 if not matchrevs:
596 if not matchrevs:
594 raise error.RepoLookupError(_("no bookmarks exist"
597 raise error.RepoLookupError(_("no bookmarks exist"
595 " that match '%s'") % pattern)
598 " that match '%s'") % pattern)
596 for bmrev in matchrevs:
599 for bmrev in matchrevs:
597 bms.add(repo[bmrev].rev())
600 bms.add(repo[bmrev].rev())
598 else:
601 else:
599 bms = set([repo[r].rev()
602 bms = set([repo[r].rev()
600 for r in repo._bookmarks.values()])
603 for r in repo._bookmarks.values()])
601 bms -= set([node.nullrev])
604 bms -= set([node.nullrev])
602 return subset & bms
605 return subset & bms
603
606
604 @predicate('branch(string or set)', safe=True)
607 @predicate('branch(string or set)', safe=True)
605 def branch(repo, subset, x):
608 def branch(repo, subset, x):
606 """
609 """
607 All changesets belonging to the given branch or the branches of the given
610 All changesets belonging to the given branch or the branches of the given
608 changesets.
611 changesets.
609
612
610 If `string` starts with `re:`, the remainder of the name is treated as
613 If `string` starts with `re:`, the remainder of the name is treated as
611 a regular expression. To match a branch that actually starts with `re:`,
614 a regular expression. To match a branch that actually starts with `re:`,
612 use the prefix `literal:`.
615 use the prefix `literal:`.
613 """
616 """
614 getbi = repo.revbranchcache().branchinfo
617 getbi = repo.revbranchcache().branchinfo
615
618
616 try:
619 try:
617 b = getstring(x, '')
620 b = getstring(x, '')
618 except error.ParseError:
621 except error.ParseError:
619 # not a string, but another revspec, e.g. tip()
622 # not a string, but another revspec, e.g. tip()
620 pass
623 pass
621 else:
624 else:
622 kind, pattern, matcher = util.stringmatcher(b)
625 kind, pattern, matcher = util.stringmatcher(b)
623 if kind == 'literal':
626 if kind == 'literal':
624 # note: falls through to the revspec case if no branch with
627 # note: falls through to the revspec case if no branch with
625 # this name exists and pattern kind is not specified explicitly
628 # this name exists and pattern kind is not specified explicitly
626 if pattern in repo.branchmap():
629 if pattern in repo.branchmap():
627 return subset.filter(lambda r: matcher(getbi(r)[0]),
630 return subset.filter(lambda r: matcher(getbi(r)[0]),
628 condrepr=('<branch %r>', b))
631 condrepr=('<branch %r>', b))
629 if b.startswith('literal:'):
632 if b.startswith('literal:'):
630 raise error.RepoLookupError(_("branch '%s' does not exist")
633 raise error.RepoLookupError(_("branch '%s' does not exist")
631 % pattern)
634 % pattern)
632 else:
635 else:
633 return subset.filter(lambda r: matcher(getbi(r)[0]),
636 return subset.filter(lambda r: matcher(getbi(r)[0]),
634 condrepr=('<branch %r>', b))
637 condrepr=('<branch %r>', b))
635
638
636 s = getset(repo, fullreposet(repo), x)
639 s = getset(repo, fullreposet(repo), x)
637 b = set()
640 b = set()
638 for r in s:
641 for r in s:
639 b.add(getbi(r)[0])
642 b.add(getbi(r)[0])
640 c = s.__contains__
643 c = s.__contains__
641 return subset.filter(lambda r: c(r) or getbi(r)[0] in b,
644 return subset.filter(lambda r: c(r) or getbi(r)[0] in b,
642 condrepr=lambda: '<branch %r>' % sorted(b))
645 condrepr=lambda: '<branch %r>' % sorted(b))
643
646
644 @predicate('bumped()', safe=True)
647 @predicate('bumped()', safe=True)
645 def bumped(repo, subset, x):
648 def bumped(repo, subset, x):
646 """Mutable changesets marked as successors of public changesets.
649 """Mutable changesets marked as successors of public changesets.
647
650
648 Only non-public and non-obsolete changesets can be `bumped`.
651 Only non-public and non-obsolete changesets can be `bumped`.
649 """
652 """
650 # i18n: "bumped" is a keyword
653 # i18n: "bumped" is a keyword
651 getargs(x, 0, 0, _("bumped takes no arguments"))
654 getargs(x, 0, 0, _("bumped takes no arguments"))
652 bumped = obsmod.getrevs(repo, 'bumped')
655 bumped = obsmod.getrevs(repo, 'bumped')
653 return subset & bumped
656 return subset & bumped
654
657
655 @predicate('bundle()', safe=True)
658 @predicate('bundle()', safe=True)
656 def bundle(repo, subset, x):
659 def bundle(repo, subset, x):
657 """Changesets in the bundle.
660 """Changesets in the bundle.
658
661
659 Bundle must be specified by the -R option."""
662 Bundle must be specified by the -R option."""
660
663
661 try:
664 try:
662 bundlerevs = repo.changelog.bundlerevs
665 bundlerevs = repo.changelog.bundlerevs
663 except AttributeError:
666 except AttributeError:
664 raise error.Abort(_("no bundle provided - specify with -R"))
667 raise error.Abort(_("no bundle provided - specify with -R"))
665 return subset & bundlerevs
668 return subset & bundlerevs
666
669
667 def checkstatus(repo, subset, pat, field):
670 def checkstatus(repo, subset, pat, field):
668 hasset = matchmod.patkind(pat) == 'set'
671 hasset = matchmod.patkind(pat) == 'set'
669
672
670 mcache = [None]
673 mcache = [None]
671 def matches(x):
674 def matches(x):
672 c = repo[x]
675 c = repo[x]
673 if not mcache[0] or hasset:
676 if not mcache[0] or hasset:
674 mcache[0] = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
677 mcache[0] = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
675 m = mcache[0]
678 m = mcache[0]
676 fname = None
679 fname = None
677 if not m.anypats() and len(m.files()) == 1:
680 if not m.anypats() and len(m.files()) == 1:
678 fname = m.files()[0]
681 fname = m.files()[0]
679 if fname is not None:
682 if fname is not None:
680 if fname not in c.files():
683 if fname not in c.files():
681 return False
684 return False
682 else:
685 else:
683 for f in c.files():
686 for f in c.files():
684 if m(f):
687 if m(f):
685 break
688 break
686 else:
689 else:
687 return False
690 return False
688 files = repo.status(c.p1().node(), c.node())[field]
691 files = repo.status(c.p1().node(), c.node())[field]
689 if fname is not None:
692 if fname is not None:
690 if fname in files:
693 if fname in files:
691 return True
694 return True
692 else:
695 else:
693 for f in files:
696 for f in files:
694 if m(f):
697 if m(f):
695 return True
698 return True
696
699
697 return subset.filter(matches, condrepr=('<status[%r] %r>', field, pat))
700 return subset.filter(matches, condrepr=('<status[%r] %r>', field, pat))
698
701
699 def _children(repo, subset, parentset):
702 def _children(repo, subset, parentset):
700 if not parentset:
703 if not parentset:
701 return baseset()
704 return baseset()
702 cs = set()
705 cs = set()
703 pr = repo.changelog.parentrevs
706 pr = repo.changelog.parentrevs
704 minrev = parentset.min()
707 minrev = parentset.min()
705 for r in subset:
708 for r in subset:
706 if r <= minrev:
709 if r <= minrev:
707 continue
710 continue
708 for p in pr(r):
711 for p in pr(r):
709 if p in parentset:
712 if p in parentset:
710 cs.add(r)
713 cs.add(r)
711 return baseset(cs)
714 return baseset(cs)
712
715
713 @predicate('children(set)', safe=True)
716 @predicate('children(set)', safe=True)
714 def children(repo, subset, x):
717 def children(repo, subset, x):
715 """Child changesets of changesets in set.
718 """Child changesets of changesets in set.
716 """
719 """
717 s = getset(repo, fullreposet(repo), x)
720 s = getset(repo, fullreposet(repo), x)
718 cs = _children(repo, subset, s)
721 cs = _children(repo, subset, s)
719 return subset & cs
722 return subset & cs
720
723
721 @predicate('closed()', safe=True)
724 @predicate('closed()', safe=True)
722 def closed(repo, subset, x):
725 def closed(repo, subset, x):
723 """Changeset is closed.
726 """Changeset is closed.
724 """
727 """
725 # i18n: "closed" is a keyword
728 # i18n: "closed" is a keyword
726 getargs(x, 0, 0, _("closed takes no arguments"))
729 getargs(x, 0, 0, _("closed takes no arguments"))
727 return subset.filter(lambda r: repo[r].closesbranch(),
730 return subset.filter(lambda r: repo[r].closesbranch(),
728 condrepr='<branch closed>')
731 condrepr='<branch closed>')
729
732
730 @predicate('contains(pattern)')
733 @predicate('contains(pattern)')
731 def contains(repo, subset, x):
734 def contains(repo, subset, x):
732 """The revision's manifest contains a file matching pattern (but might not
735 """The revision's manifest contains a file matching pattern (but might not
733 modify it). See :hg:`help patterns` for information about file patterns.
736 modify it). See :hg:`help patterns` for information about file patterns.
734
737
735 The pattern without explicit kind like ``glob:`` is expected to be
738 The pattern without explicit kind like ``glob:`` is expected to be
736 relative to the current directory and match against a file exactly
739 relative to the current directory and match against a file exactly
737 for efficiency.
740 for efficiency.
738 """
741 """
739 # i18n: "contains" is a keyword
742 # i18n: "contains" is a keyword
740 pat = getstring(x, _("contains requires a pattern"))
743 pat = getstring(x, _("contains requires a pattern"))
741
744
742 def matches(x):
745 def matches(x):
743 if not matchmod.patkind(pat):
746 if not matchmod.patkind(pat):
744 pats = pathutil.canonpath(repo.root, repo.getcwd(), pat)
747 pats = pathutil.canonpath(repo.root, repo.getcwd(), pat)
745 if pats in repo[x]:
748 if pats in repo[x]:
746 return True
749 return True
747 else:
750 else:
748 c = repo[x]
751 c = repo[x]
749 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
752 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
750 for f in c.manifest():
753 for f in c.manifest():
751 if m(f):
754 if m(f):
752 return True
755 return True
753 return False
756 return False
754
757
755 return subset.filter(matches, condrepr=('<contains %r>', pat))
758 return subset.filter(matches, condrepr=('<contains %r>', pat))
756
759
757 @predicate('converted([id])', safe=True)
760 @predicate('converted([id])', safe=True)
758 def converted(repo, subset, x):
761 def converted(repo, subset, x):
759 """Changesets converted from the given identifier in the old repository if
762 """Changesets converted from the given identifier in the old repository if
760 present, or all converted changesets if no identifier is specified.
763 present, or all converted changesets if no identifier is specified.
761 """
764 """
762
765
763 # There is exactly no chance of resolving the revision, so do a simple
766 # There is exactly no chance of resolving the revision, so do a simple
764 # string compare and hope for the best
767 # string compare and hope for the best
765
768
766 rev = None
769 rev = None
767 # i18n: "converted" is a keyword
770 # i18n: "converted" is a keyword
768 l = getargs(x, 0, 1, _('converted takes one or no arguments'))
771 l = getargs(x, 0, 1, _('converted takes one or no arguments'))
769 if l:
772 if l:
770 # i18n: "converted" is a keyword
773 # i18n: "converted" is a keyword
771 rev = getstring(l[0], _('converted requires a revision'))
774 rev = getstring(l[0], _('converted requires a revision'))
772
775
773 def _matchvalue(r):
776 def _matchvalue(r):
774 source = repo[r].extra().get('convert_revision', None)
777 source = repo[r].extra().get('convert_revision', None)
775 return source is not None and (rev is None or source.startswith(rev))
778 return source is not None and (rev is None or source.startswith(rev))
776
779
777 return subset.filter(lambda r: _matchvalue(r),
780 return subset.filter(lambda r: _matchvalue(r),
778 condrepr=('<converted %r>', rev))
781 condrepr=('<converted %r>', rev))
779
782
780 @predicate('date(interval)', safe=True)
783 @predicate('date(interval)', safe=True)
781 def date(repo, subset, x):
784 def date(repo, subset, x):
782 """Changesets within the interval, see :hg:`help dates`.
785 """Changesets within the interval, see :hg:`help dates`.
783 """
786 """
784 # i18n: "date" is a keyword
787 # i18n: "date" is a keyword
785 ds = getstring(x, _("date requires a string"))
788 ds = getstring(x, _("date requires a string"))
786 dm = util.matchdate(ds)
789 dm = util.matchdate(ds)
787 return subset.filter(lambda x: dm(repo[x].date()[0]),
790 return subset.filter(lambda x: dm(repo[x].date()[0]),
788 condrepr=('<date %r>', ds))
791 condrepr=('<date %r>', ds))
789
792
790 @predicate('desc(string)', safe=True)
793 @predicate('desc(string)', safe=True)
791 def desc(repo, subset, x):
794 def desc(repo, subset, x):
792 """Search commit message for string. The match is case-insensitive.
795 """Search commit message for string. The match is case-insensitive.
793 """
796 """
794 # i18n: "desc" is a keyword
797 # i18n: "desc" is a keyword
795 ds = encoding.lower(getstring(x, _("desc requires a string")))
798 ds = encoding.lower(getstring(x, _("desc requires a string")))
796
799
797 def matches(x):
800 def matches(x):
798 c = repo[x]
801 c = repo[x]
799 return ds in encoding.lower(c.description())
802 return ds in encoding.lower(c.description())
800
803
801 return subset.filter(matches, condrepr=('<desc %r>', ds))
804 return subset.filter(matches, condrepr=('<desc %r>', ds))
802
805
803 def _descendants(repo, subset, x, followfirst=False):
806 def _descendants(repo, subset, x, followfirst=False):
804 roots = getset(repo, fullreposet(repo), x)
807 roots = getset(repo, fullreposet(repo), x)
805 if not roots:
808 if not roots:
806 return baseset()
809 return baseset()
807 s = _revdescendants(repo, roots, followfirst)
810 s = _revdescendants(repo, roots, followfirst)
808
811
809 # Both sets need to be ascending in order to lazily return the union
812 # Both sets need to be ascending in order to lazily return the union
810 # in the correct order.
813 # in the correct order.
811 base = subset & roots
814 base = subset & roots
812 desc = subset & s
815 desc = subset & s
813 result = base + desc
816 result = base + desc
814 if subset.isascending():
817 if subset.isascending():
815 result.sort()
818 result.sort()
816 elif subset.isdescending():
819 elif subset.isdescending():
817 result.sort(reverse=True)
820 result.sort(reverse=True)
818 else:
821 else:
819 result = subset & result
822 result = subset & result
820 return result
823 return result
821
824
822 @predicate('descendants(set)', safe=True)
825 @predicate('descendants(set)', safe=True)
823 def descendants(repo, subset, x):
826 def descendants(repo, subset, x):
824 """Changesets which are descendants of changesets in set.
827 """Changesets which are descendants of changesets in set.
825 """
828 """
826 return _descendants(repo, subset, x)
829 return _descendants(repo, subset, x)
827
830
828 @predicate('_firstdescendants', safe=True)
831 @predicate('_firstdescendants', safe=True)
829 def _firstdescendants(repo, subset, x):
832 def _firstdescendants(repo, subset, x):
830 # ``_firstdescendants(set)``
833 # ``_firstdescendants(set)``
831 # Like ``descendants(set)`` but follows only the first parents.
834 # Like ``descendants(set)`` but follows only the first parents.
832 return _descendants(repo, subset, x, followfirst=True)
835 return _descendants(repo, subset, x, followfirst=True)
833
836
834 @predicate('destination([set])', safe=True)
837 @predicate('destination([set])', safe=True)
835 def destination(repo, subset, x):
838 def destination(repo, subset, x):
836 """Changesets that were created by a graft, transplant or rebase operation,
839 """Changesets that were created by a graft, transplant or rebase operation,
837 with the given revisions specified as the source. Omitting the optional set
840 with the given revisions specified as the source. Omitting the optional set
838 is the same as passing all().
841 is the same as passing all().
839 """
842 """
840 if x is not None:
843 if x is not None:
841 sources = getset(repo, fullreposet(repo), x)
844 sources = getset(repo, fullreposet(repo), x)
842 else:
845 else:
843 sources = fullreposet(repo)
846 sources = fullreposet(repo)
844
847
845 dests = set()
848 dests = set()
846
849
847 # subset contains all of the possible destinations that can be returned, so
850 # subset contains all of the possible destinations that can be returned, so
848 # iterate over them and see if their source(s) were provided in the arg set.
851 # iterate over them and see if their source(s) were provided in the arg set.
849 # Even if the immediate src of r is not in the arg set, src's source (or
852 # Even if the immediate src of r is not in the arg set, src's source (or
850 # further back) may be. Scanning back further than the immediate src allows
853 # further back) may be. Scanning back further than the immediate src allows
851 # transitive transplants and rebases to yield the same results as transitive
854 # transitive transplants and rebases to yield the same results as transitive
852 # grafts.
855 # grafts.
853 for r in subset:
856 for r in subset:
854 src = _getrevsource(repo, r)
857 src = _getrevsource(repo, r)
855 lineage = None
858 lineage = None
856
859
857 while src is not None:
860 while src is not None:
858 if lineage is None:
861 if lineage is None:
859 lineage = list()
862 lineage = list()
860
863
861 lineage.append(r)
864 lineage.append(r)
862
865
863 # The visited lineage is a match if the current source is in the arg
866 # The visited lineage is a match if the current source is in the arg
864 # set. Since every candidate dest is visited by way of iterating
867 # set. Since every candidate dest is visited by way of iterating
865 # subset, any dests further back in the lineage will be tested by a
868 # subset, any dests further back in the lineage will be tested by a
866 # different iteration over subset. Likewise, if the src was already
869 # different iteration over subset. Likewise, if the src was already
867 # selected, the current lineage can be selected without going back
870 # selected, the current lineage can be selected without going back
868 # further.
871 # further.
869 if src in sources or src in dests:
872 if src in sources or src in dests:
870 dests.update(lineage)
873 dests.update(lineage)
871 break
874 break
872
875
873 r = src
876 r = src
874 src = _getrevsource(repo, r)
877 src = _getrevsource(repo, r)
875
878
876 return subset.filter(dests.__contains__,
879 return subset.filter(dests.__contains__,
877 condrepr=lambda: '<destination %r>' % sorted(dests))
880 condrepr=lambda: '<destination %r>' % sorted(dests))
878
881
879 @predicate('divergent()', safe=True)
882 @predicate('divergent()', safe=True)
880 def divergent(repo, subset, x):
883 def divergent(repo, subset, x):
881 """
884 """
882 Final successors of changesets with an alternative set of final successors.
885 Final successors of changesets with an alternative set of final successors.
883 """
886 """
884 # i18n: "divergent" is a keyword
887 # i18n: "divergent" is a keyword
885 getargs(x, 0, 0, _("divergent takes no arguments"))
888 getargs(x, 0, 0, _("divergent takes no arguments"))
886 divergent = obsmod.getrevs(repo, 'divergent')
889 divergent = obsmod.getrevs(repo, 'divergent')
887 return subset & divergent
890 return subset & divergent
888
891
889 @predicate('extinct()', safe=True)
892 @predicate('extinct()', safe=True)
890 def extinct(repo, subset, x):
893 def extinct(repo, subset, x):
891 """Obsolete changesets with obsolete descendants only.
894 """Obsolete changesets with obsolete descendants only.
892 """
895 """
893 # i18n: "extinct" is a keyword
896 # i18n: "extinct" is a keyword
894 getargs(x, 0, 0, _("extinct takes no arguments"))
897 getargs(x, 0, 0, _("extinct takes no arguments"))
895 extincts = obsmod.getrevs(repo, 'extinct')
898 extincts = obsmod.getrevs(repo, 'extinct')
896 return subset & extincts
899 return subset & extincts
897
900
898 @predicate('extra(label, [value])', safe=True)
901 @predicate('extra(label, [value])', safe=True)
899 def extra(repo, subset, x):
902 def extra(repo, subset, x):
900 """Changesets with the given label in the extra metadata, with the given
903 """Changesets with the given label in the extra metadata, with the given
901 optional value.
904 optional value.
902
905
903 If `value` starts with `re:`, the remainder of the value is treated as
906 If `value` starts with `re:`, the remainder of the value is treated as
904 a regular expression. To match a value that actually starts with `re:`,
907 a regular expression. To match a value that actually starts with `re:`,
905 use the prefix `literal:`.
908 use the prefix `literal:`.
906 """
909 """
907 args = getargsdict(x, 'extra', 'label value')
910 args = getargsdict(x, 'extra', 'label value')
908 if 'label' not in args:
911 if 'label' not in args:
909 # i18n: "extra" is a keyword
912 # i18n: "extra" is a keyword
910 raise error.ParseError(_('extra takes at least 1 argument'))
913 raise error.ParseError(_('extra takes at least 1 argument'))
911 # i18n: "extra" is a keyword
914 # i18n: "extra" is a keyword
912 label = getstring(args['label'], _('first argument to extra must be '
915 label = getstring(args['label'], _('first argument to extra must be '
913 'a string'))
916 'a string'))
914 value = None
917 value = None
915
918
916 if 'value' in args:
919 if 'value' in args:
917 # i18n: "extra" is a keyword
920 # i18n: "extra" is a keyword
918 value = getstring(args['value'], _('second argument to extra must be '
921 value = getstring(args['value'], _('second argument to extra must be '
919 'a string'))
922 'a string'))
920 kind, value, matcher = util.stringmatcher(value)
923 kind, value, matcher = util.stringmatcher(value)
921
924
922 def _matchvalue(r):
925 def _matchvalue(r):
923 extra = repo[r].extra()
926 extra = repo[r].extra()
924 return label in extra and (value is None or matcher(extra[label]))
927 return label in extra and (value is None or matcher(extra[label]))
925
928
926 return subset.filter(lambda r: _matchvalue(r),
929 return subset.filter(lambda r: _matchvalue(r),
927 condrepr=('<extra[%r] %r>', label, value))
930 condrepr=('<extra[%r] %r>', label, value))
928
931
929 @predicate('filelog(pattern)', safe=True)
932 @predicate('filelog(pattern)', safe=True)
930 def filelog(repo, subset, x):
933 def filelog(repo, subset, x):
931 """Changesets connected to the specified filelog.
934 """Changesets connected to the specified filelog.
932
935
933 For performance reasons, visits only revisions mentioned in the file-level
936 For performance reasons, visits only revisions mentioned in the file-level
934 filelog, rather than filtering through all changesets (much faster, but
937 filelog, rather than filtering through all changesets (much faster, but
935 doesn't include deletes or duplicate changes). For a slower, more accurate
938 doesn't include deletes or duplicate changes). For a slower, more accurate
936 result, use ``file()``.
939 result, use ``file()``.
937
940
938 The pattern without explicit kind like ``glob:`` is expected to be
941 The pattern without explicit kind like ``glob:`` is expected to be
939 relative to the current directory and match against a file exactly
942 relative to the current directory and match against a file exactly
940 for efficiency.
943 for efficiency.
941
944
942 If some linkrev points to revisions filtered by the current repoview, we'll
945 If some linkrev points to revisions filtered by the current repoview, we'll
943 work around it to return a non-filtered value.
946 work around it to return a non-filtered value.
944 """
947 """
945
948
946 # i18n: "filelog" is a keyword
949 # i18n: "filelog" is a keyword
947 pat = getstring(x, _("filelog requires a pattern"))
950 pat = getstring(x, _("filelog requires a pattern"))
948 s = set()
951 s = set()
949 cl = repo.changelog
952 cl = repo.changelog
950
953
951 if not matchmod.patkind(pat):
954 if not matchmod.patkind(pat):
952 f = pathutil.canonpath(repo.root, repo.getcwd(), pat)
955 f = pathutil.canonpath(repo.root, repo.getcwd(), pat)
953 files = [f]
956 files = [f]
954 else:
957 else:
955 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[None])
958 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[None])
956 files = (f for f in repo[None] if m(f))
959 files = (f for f in repo[None] if m(f))
957
960
958 for f in files:
961 for f in files:
959 fl = repo.file(f)
962 fl = repo.file(f)
960 known = {}
963 known = {}
961 scanpos = 0
964 scanpos = 0
962 for fr in list(fl):
965 for fr in list(fl):
963 fn = fl.node(fr)
966 fn = fl.node(fr)
964 if fn in known:
967 if fn in known:
965 s.add(known[fn])
968 s.add(known[fn])
966 continue
969 continue
967
970
968 lr = fl.linkrev(fr)
971 lr = fl.linkrev(fr)
969 if lr in cl:
972 if lr in cl:
970 s.add(lr)
973 s.add(lr)
971 elif scanpos is not None:
974 elif scanpos is not None:
972 # lowest matching changeset is filtered, scan further
975 # lowest matching changeset is filtered, scan further
973 # ahead in changelog
976 # ahead in changelog
974 start = max(lr, scanpos) + 1
977 start = max(lr, scanpos) + 1
975 scanpos = None
978 scanpos = None
976 for r in cl.revs(start):
979 for r in cl.revs(start):
977 # minimize parsing of non-matching entries
980 # minimize parsing of non-matching entries
978 if f in cl.revision(r) and f in cl.readfiles(r):
981 if f in cl.revision(r) and f in cl.readfiles(r):
979 try:
982 try:
980 # try to use manifest delta fastpath
983 # try to use manifest delta fastpath
981 n = repo[r].filenode(f)
984 n = repo[r].filenode(f)
982 if n not in known:
985 if n not in known:
983 if n == fn:
986 if n == fn:
984 s.add(r)
987 s.add(r)
985 scanpos = r
988 scanpos = r
986 break
989 break
987 else:
990 else:
988 known[n] = r
991 known[n] = r
989 except error.ManifestLookupError:
992 except error.ManifestLookupError:
990 # deletion in changelog
993 # deletion in changelog
991 continue
994 continue
992
995
993 return subset & s
996 return subset & s
994
997
995 @predicate('first(set, [n])', safe=True)
998 @predicate('first(set, [n])', safe=True)
996 def first(repo, subset, x):
999 def first(repo, subset, x):
997 """An alias for limit().
1000 """An alias for limit().
998 """
1001 """
999 return limit(repo, subset, x)
1002 return limit(repo, subset, x)
1000
1003
1001 def _follow(repo, subset, x, name, followfirst=False):
1004 def _follow(repo, subset, x, name, followfirst=False):
1002 l = getargs(x, 0, 2, _("%s takes no arguments or a pattern "
1005 l = getargs(x, 0, 2, _("%s takes no arguments or a pattern "
1003 "and an optional revset") % name)
1006 "and an optional revset") % name)
1004 c = repo['.']
1007 c = repo['.']
1005 if l:
1008 if l:
1006 x = getstring(l[0], _("%s expected a pattern") % name)
1009 x = getstring(l[0], _("%s expected a pattern") % name)
1007 rev = None
1010 rev = None
1008 if len(l) >= 2:
1011 if len(l) >= 2:
1009 rev = getset(repo, fullreposet(repo), l[1]).last()
1012 rev = getset(repo, fullreposet(repo), l[1]).last()
1010 if rev is None:
1013 if rev is None:
1011 raise error.RepoLookupError(
1014 raise error.RepoLookupError(
1012 _("%s: starting revision set cannot be empty") % name)
1015 _("%s: starting revision set cannot be empty") % name)
1013 c = repo[rev]
1016 c = repo[rev]
1014 matcher = matchmod.match(repo.root, repo.getcwd(), [x],
1017 matcher = matchmod.match(repo.root, repo.getcwd(), [x],
1015 ctx=repo[rev], default='path')
1018 ctx=repo[rev], default='path')
1016
1019
1017 files = c.manifest().walk(matcher)
1020 files = c.manifest().walk(matcher)
1018
1021
1019 s = set()
1022 s = set()
1020 for fname in files:
1023 for fname in files:
1021 fctx = c[fname]
1024 fctx = c[fname]
1022 s = s.union(set(c.rev() for c in fctx.ancestors(followfirst)))
1025 s = s.union(set(c.rev() for c in fctx.ancestors(followfirst)))
1023 # include the revision responsible for the most recent version
1026 # include the revision responsible for the most recent version
1024 s.add(fctx.introrev())
1027 s.add(fctx.introrev())
1025 else:
1028 else:
1026 s = _revancestors(repo, baseset([c.rev()]), followfirst)
1029 s = _revancestors(repo, baseset([c.rev()]), followfirst)
1027
1030
1028 return subset & s
1031 return subset & s
1029
1032
1030 @predicate('follow([pattern[, startrev]])', safe=True)
1033 @predicate('follow([pattern[, startrev]])', safe=True)
1031 def follow(repo, subset, x):
1034 def follow(repo, subset, x):
1032 """
1035 """
1033 An alias for ``::.`` (ancestors of the working directory's first parent).
1036 An alias for ``::.`` (ancestors of the working directory's first parent).
1034 If pattern is specified, the histories of files matching given
1037 If pattern is specified, the histories of files matching given
1035 pattern in the revision given by startrev are followed, including copies.
1038 pattern in the revision given by startrev are followed, including copies.
1036 """
1039 """
1037 return _follow(repo, subset, x, 'follow')
1040 return _follow(repo, subset, x, 'follow')
1038
1041
1039 @predicate('_followfirst', safe=True)
1042 @predicate('_followfirst', safe=True)
1040 def _followfirst(repo, subset, x):
1043 def _followfirst(repo, subset, x):
1041 # ``followfirst([pattern[, startrev]])``
1044 # ``followfirst([pattern[, startrev]])``
1042 # Like ``follow([pattern[, startrev]])`` but follows only the first parent
1045 # Like ``follow([pattern[, startrev]])`` but follows only the first parent
1043 # of every revisions or files revisions.
1046 # of every revisions or files revisions.
1044 return _follow(repo, subset, x, '_followfirst', followfirst=True)
1047 return _follow(repo, subset, x, '_followfirst', followfirst=True)
1045
1048
1046 @predicate('all()', safe=True)
1049 @predicate('all()', safe=True)
1047 def getall(repo, subset, x):
1050 def getall(repo, subset, x):
1048 """All changesets, the same as ``0:tip``.
1051 """All changesets, the same as ``0:tip``.
1049 """
1052 """
1050 # i18n: "all" is a keyword
1053 # i18n: "all" is a keyword
1051 getargs(x, 0, 0, _("all takes no arguments"))
1054 getargs(x, 0, 0, _("all takes no arguments"))
1052 return subset & spanset(repo) # drop "null" if any
1055 return subset & spanset(repo) # drop "null" if any
1053
1056
1054 @predicate('grep(regex)')
1057 @predicate('grep(regex)')
1055 def grep(repo, subset, x):
1058 def grep(repo, subset, x):
1056 """Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
1059 """Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
1057 to ensure special escape characters are handled correctly. Unlike
1060 to ensure special escape characters are handled correctly. Unlike
1058 ``keyword(string)``, the match is case-sensitive.
1061 ``keyword(string)``, the match is case-sensitive.
1059 """
1062 """
1060 try:
1063 try:
1061 # i18n: "grep" is a keyword
1064 # i18n: "grep" is a keyword
1062 gr = re.compile(getstring(x, _("grep requires a string")))
1065 gr = re.compile(getstring(x, _("grep requires a string")))
1063 except re.error as e:
1066 except re.error as e:
1064 raise error.ParseError(_('invalid match pattern: %s') % e)
1067 raise error.ParseError(_('invalid match pattern: %s') % e)
1065
1068
1066 def matches(x):
1069 def matches(x):
1067 c = repo[x]
1070 c = repo[x]
1068 for e in c.files() + [c.user(), c.description()]:
1071 for e in c.files() + [c.user(), c.description()]:
1069 if gr.search(e):
1072 if gr.search(e):
1070 return True
1073 return True
1071 return False
1074 return False
1072
1075
1073 return subset.filter(matches, condrepr=('<grep %r>', gr.pattern))
1076 return subset.filter(matches, condrepr=('<grep %r>', gr.pattern))
1074
1077
1075 @predicate('_matchfiles', safe=True)
1078 @predicate('_matchfiles', safe=True)
1076 def _matchfiles(repo, subset, x):
1079 def _matchfiles(repo, subset, x):
1077 # _matchfiles takes a revset list of prefixed arguments:
1080 # _matchfiles takes a revset list of prefixed arguments:
1078 #
1081 #
1079 # [p:foo, i:bar, x:baz]
1082 # [p:foo, i:bar, x:baz]
1080 #
1083 #
1081 # builds a match object from them and filters subset. Allowed
1084 # builds a match object from them and filters subset. Allowed
1082 # prefixes are 'p:' for regular patterns, 'i:' for include
1085 # prefixes are 'p:' for regular patterns, 'i:' for include
1083 # patterns and 'x:' for exclude patterns. Use 'r:' prefix to pass
1086 # patterns and 'x:' for exclude patterns. Use 'r:' prefix to pass
1084 # a revision identifier, or the empty string to reference the
1087 # a revision identifier, or the empty string to reference the
1085 # working directory, from which the match object is
1088 # working directory, from which the match object is
1086 # initialized. Use 'd:' to set the default matching mode, default
1089 # initialized. Use 'd:' to set the default matching mode, default
1087 # to 'glob'. At most one 'r:' and 'd:' argument can be passed.
1090 # to 'glob'. At most one 'r:' and 'd:' argument can be passed.
1088
1091
1089 l = getargs(x, 1, -1, "_matchfiles requires at least one argument")
1092 l = getargs(x, 1, -1, "_matchfiles requires at least one argument")
1090 pats, inc, exc = [], [], []
1093 pats, inc, exc = [], [], []
1091 rev, default = None, None
1094 rev, default = None, None
1092 for arg in l:
1095 for arg in l:
1093 s = getstring(arg, "_matchfiles requires string arguments")
1096 s = getstring(arg, "_matchfiles requires string arguments")
1094 prefix, value = s[:2], s[2:]
1097 prefix, value = s[:2], s[2:]
1095 if prefix == 'p:':
1098 if prefix == 'p:':
1096 pats.append(value)
1099 pats.append(value)
1097 elif prefix == 'i:':
1100 elif prefix == 'i:':
1098 inc.append(value)
1101 inc.append(value)
1099 elif prefix == 'x:':
1102 elif prefix == 'x:':
1100 exc.append(value)
1103 exc.append(value)
1101 elif prefix == 'r:':
1104 elif prefix == 'r:':
1102 if rev is not None:
1105 if rev is not None:
1103 raise error.ParseError('_matchfiles expected at most one '
1106 raise error.ParseError('_matchfiles expected at most one '
1104 'revision')
1107 'revision')
1105 if value != '': # empty means working directory; leave rev as None
1108 if value != '': # empty means working directory; leave rev as None
1106 rev = value
1109 rev = value
1107 elif prefix == 'd:':
1110 elif prefix == 'd:':
1108 if default is not None:
1111 if default is not None:
1109 raise error.ParseError('_matchfiles expected at most one '
1112 raise error.ParseError('_matchfiles expected at most one '
1110 'default mode')
1113 'default mode')
1111 default = value
1114 default = value
1112 else:
1115 else:
1113 raise error.ParseError('invalid _matchfiles prefix: %s' % prefix)
1116 raise error.ParseError('invalid _matchfiles prefix: %s' % prefix)
1114 if not default:
1117 if not default:
1115 default = 'glob'
1118 default = 'glob'
1116
1119
1117 m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc,
1120 m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc,
1118 exclude=exc, ctx=repo[rev], default=default)
1121 exclude=exc, ctx=repo[rev], default=default)
1119
1122
1120 # This directly read the changelog data as creating changectx for all
1123 # This directly read the changelog data as creating changectx for all
1121 # revisions is quite expensive.
1124 # revisions is quite expensive.
1122 getfiles = repo.changelog.readfiles
1125 getfiles = repo.changelog.readfiles
1123 wdirrev = node.wdirrev
1126 wdirrev = node.wdirrev
1124 def matches(x):
1127 def matches(x):
1125 if x == wdirrev:
1128 if x == wdirrev:
1126 files = repo[x].files()
1129 files = repo[x].files()
1127 else:
1130 else:
1128 files = getfiles(x)
1131 files = getfiles(x)
1129 for f in files:
1132 for f in files:
1130 if m(f):
1133 if m(f):
1131 return True
1134 return True
1132 return False
1135 return False
1133
1136
1134 return subset.filter(matches,
1137 return subset.filter(matches,
1135 condrepr=('<matchfiles patterns=%r, include=%r '
1138 condrepr=('<matchfiles patterns=%r, include=%r '
1136 'exclude=%r, default=%r, rev=%r>',
1139 'exclude=%r, default=%r, rev=%r>',
1137 pats, inc, exc, default, rev))
1140 pats, inc, exc, default, rev))
1138
1141
1139 @predicate('file(pattern)', safe=True)
1142 @predicate('file(pattern)', safe=True)
1140 def hasfile(repo, subset, x):
1143 def hasfile(repo, subset, x):
1141 """Changesets affecting files matched by pattern.
1144 """Changesets affecting files matched by pattern.
1142
1145
1143 For a faster but less accurate result, consider using ``filelog()``
1146 For a faster but less accurate result, consider using ``filelog()``
1144 instead.
1147 instead.
1145
1148
1146 This predicate uses ``glob:`` as the default kind of pattern.
1149 This predicate uses ``glob:`` as the default kind of pattern.
1147 """
1150 """
1148 # i18n: "file" is a keyword
1151 # i18n: "file" is a keyword
1149 pat = getstring(x, _("file requires a pattern"))
1152 pat = getstring(x, _("file requires a pattern"))
1150 return _matchfiles(repo, subset, ('string', 'p:' + pat))
1153 return _matchfiles(repo, subset, ('string', 'p:' + pat))
1151
1154
1152 @predicate('head()', safe=True)
1155 @predicate('head()', safe=True)
1153 def head(repo, subset, x):
1156 def head(repo, subset, x):
1154 """Changeset is a named branch head.
1157 """Changeset is a named branch head.
1155 """
1158 """
1156 # i18n: "head" is a keyword
1159 # i18n: "head" is a keyword
1157 getargs(x, 0, 0, _("head takes no arguments"))
1160 getargs(x, 0, 0, _("head takes no arguments"))
1158 hs = set()
1161 hs = set()
1159 cl = repo.changelog
1162 cl = repo.changelog
1160 for ls in repo.branchmap().itervalues():
1163 for ls in repo.branchmap().itervalues():
1161 hs.update(cl.rev(h) for h in ls)
1164 hs.update(cl.rev(h) for h in ls)
1162 return subset & baseset(hs)
1165 return subset & baseset(hs)
1163
1166
1164 @predicate('heads(set)', safe=True)
1167 @predicate('heads(set)', safe=True)
1165 def heads(repo, subset, x):
1168 def heads(repo, subset, x):
1166 """Members of set with no children in set.
1169 """Members of set with no children in set.
1167 """
1170 """
1168 s = getset(repo, subset, x)
1171 s = getset(repo, subset, x)
1169 ps = parents(repo, subset, x)
1172 ps = parents(repo, subset, x)
1170 return s - ps
1173 return s - ps
1171
1174
1172 @predicate('hidden()', safe=True)
1175 @predicate('hidden()', safe=True)
1173 def hidden(repo, subset, x):
1176 def hidden(repo, subset, x):
1174 """Hidden changesets.
1177 """Hidden changesets.
1175 """
1178 """
1176 # i18n: "hidden" is a keyword
1179 # i18n: "hidden" is a keyword
1177 getargs(x, 0, 0, _("hidden takes no arguments"))
1180 getargs(x, 0, 0, _("hidden takes no arguments"))
1178 hiddenrevs = repoview.filterrevs(repo, 'visible')
1181 hiddenrevs = repoview.filterrevs(repo, 'visible')
1179 return subset & hiddenrevs
1182 return subset & hiddenrevs
1180
1183
1181 @predicate('keyword(string)', safe=True)
1184 @predicate('keyword(string)', safe=True)
1182 def keyword(repo, subset, x):
1185 def keyword(repo, subset, x):
1183 """Search commit message, user name, and names of changed files for
1186 """Search commit message, user name, and names of changed files for
1184 string. The match is case-insensitive.
1187 string. The match is case-insensitive.
1185 """
1188 """
1186 # i18n: "keyword" is a keyword
1189 # i18n: "keyword" is a keyword
1187 kw = encoding.lower(getstring(x, _("keyword requires a string")))
1190 kw = encoding.lower(getstring(x, _("keyword requires a string")))
1188
1191
1189 def matches(r):
1192 def matches(r):
1190 c = repo[r]
1193 c = repo[r]
1191 return any(kw in encoding.lower(t)
1194 return any(kw in encoding.lower(t)
1192 for t in c.files() + [c.user(), c.description()])
1195 for t in c.files() + [c.user(), c.description()])
1193
1196
1194 return subset.filter(matches, condrepr=('<keyword %r>', kw))
1197 return subset.filter(matches, condrepr=('<keyword %r>', kw))
1195
1198
1196 @predicate('limit(set[, n[, offset]])', safe=True)
1199 @predicate('limit(set[, n[, offset]])', safe=True)
1197 def limit(repo, subset, x):
1200 def limit(repo, subset, x):
1198 """First n members of set, defaulting to 1, starting from offset.
1201 """First n members of set, defaulting to 1, starting from offset.
1199 """
1202 """
1200 args = getargsdict(x, 'limit', 'set n offset')
1203 args = getargsdict(x, 'limit', 'set n offset')
1201 if 'set' not in args:
1204 if 'set' not in args:
1202 # i18n: "limit" is a keyword
1205 # i18n: "limit" is a keyword
1203 raise error.ParseError(_("limit requires one to three arguments"))
1206 raise error.ParseError(_("limit requires one to three arguments"))
1204 try:
1207 try:
1205 lim, ofs = 1, 0
1208 lim, ofs = 1, 0
1206 if 'n' in args:
1209 if 'n' in args:
1207 # i18n: "limit" is a keyword
1210 # i18n: "limit" is a keyword
1208 lim = int(getstring(args['n'], _("limit requires a number")))
1211 lim = int(getstring(args['n'], _("limit requires a number")))
1209 if 'offset' in args:
1212 if 'offset' in args:
1210 # i18n: "limit" is a keyword
1213 # i18n: "limit" is a keyword
1211 ofs = int(getstring(args['offset'], _("limit requires a number")))
1214 ofs = int(getstring(args['offset'], _("limit requires a number")))
1212 if ofs < 0:
1215 if ofs < 0:
1213 raise error.ParseError(_("negative offset"))
1216 raise error.ParseError(_("negative offset"))
1214 except (TypeError, ValueError):
1217 except (TypeError, ValueError):
1215 # i18n: "limit" is a keyword
1218 # i18n: "limit" is a keyword
1216 raise error.ParseError(_("limit expects a number"))
1219 raise error.ParseError(_("limit expects a number"))
1217 os = getset(repo, fullreposet(repo), args['set'])
1220 os = getset(repo, fullreposet(repo), args['set'])
1218 result = []
1221 result = []
1219 it = iter(os)
1222 it = iter(os)
1220 for x in xrange(ofs):
1223 for x in xrange(ofs):
1221 y = next(it, None)
1224 y = next(it, None)
1222 if y is None:
1225 if y is None:
1223 break
1226 break
1224 for x in xrange(lim):
1227 for x in xrange(lim):
1225 y = next(it, None)
1228 y = next(it, None)
1226 if y is None:
1229 if y is None:
1227 break
1230 break
1228 elif y in subset:
1231 elif y in subset:
1229 result.append(y)
1232 result.append(y)
1230 return baseset(result, datarepr=('<limit n=%d, offset=%d, %r, %r>',
1233 return baseset(result, datarepr=('<limit n=%d, offset=%d, %r, %r>',
1231 lim, ofs, subset, os))
1234 lim, ofs, subset, os))
1232
1235
1233 @predicate('last(set, [n])', safe=True)
1236 @predicate('last(set, [n])', safe=True)
1234 def last(repo, subset, x):
1237 def last(repo, subset, x):
1235 """Last n members of set, defaulting to 1.
1238 """Last n members of set, defaulting to 1.
1236 """
1239 """
1237 # i18n: "last" is a keyword
1240 # i18n: "last" is a keyword
1238 l = getargs(x, 1, 2, _("last requires one or two arguments"))
1241 l = getargs(x, 1, 2, _("last requires one or two arguments"))
1239 try:
1242 try:
1240 lim = 1
1243 lim = 1
1241 if len(l) == 2:
1244 if len(l) == 2:
1242 # i18n: "last" is a keyword
1245 # i18n: "last" is a keyword
1243 lim = int(getstring(l[1], _("last requires a number")))
1246 lim = int(getstring(l[1], _("last requires a number")))
1244 except (TypeError, ValueError):
1247 except (TypeError, ValueError):
1245 # i18n: "last" is a keyword
1248 # i18n: "last" is a keyword
1246 raise error.ParseError(_("last expects a number"))
1249 raise error.ParseError(_("last expects a number"))
1247 os = getset(repo, fullreposet(repo), l[0])
1250 os = getset(repo, fullreposet(repo), l[0])
1248 os.reverse()
1251 os.reverse()
1249 result = []
1252 result = []
1250 it = iter(os)
1253 it = iter(os)
1251 for x in xrange(lim):
1254 for x in xrange(lim):
1252 y = next(it, None)
1255 y = next(it, None)
1253 if y is None:
1256 if y is None:
1254 break
1257 break
1255 elif y in subset:
1258 elif y in subset:
1256 result.append(y)
1259 result.append(y)
1257 return baseset(result, datarepr=('<last n=%d, %r, %r>', lim, subset, os))
1260 return baseset(result, datarepr=('<last n=%d, %r, %r>', lim, subset, os))
1258
1261
1259 @predicate('max(set)', safe=True)
1262 @predicate('max(set)', safe=True)
1260 def maxrev(repo, subset, x):
1263 def maxrev(repo, subset, x):
1261 """Changeset with highest revision number in set.
1264 """Changeset with highest revision number in set.
1262 """
1265 """
1263 os = getset(repo, fullreposet(repo), x)
1266 os = getset(repo, fullreposet(repo), x)
1264 try:
1267 try:
1265 m = os.max()
1268 m = os.max()
1266 if m in subset:
1269 if m in subset:
1267 return baseset([m], datarepr=('<max %r, %r>', subset, os))
1270 return baseset([m], datarepr=('<max %r, %r>', subset, os))
1268 except ValueError:
1271 except ValueError:
1269 # os.max() throws a ValueError when the collection is empty.
1272 # os.max() throws a ValueError when the collection is empty.
1270 # Same as python's max().
1273 # Same as python's max().
1271 pass
1274 pass
1272 return baseset(datarepr=('<max %r, %r>', subset, os))
1275 return baseset(datarepr=('<max %r, %r>', subset, os))
1273
1276
1274 @predicate('merge()', safe=True)
1277 @predicate('merge()', safe=True)
1275 def merge(repo, subset, x):
1278 def merge(repo, subset, x):
1276 """Changeset is a merge changeset.
1279 """Changeset is a merge changeset.
1277 """
1280 """
1278 # i18n: "merge" is a keyword
1281 # i18n: "merge" is a keyword
1279 getargs(x, 0, 0, _("merge takes no arguments"))
1282 getargs(x, 0, 0, _("merge takes no arguments"))
1280 cl = repo.changelog
1283 cl = repo.changelog
1281 return subset.filter(lambda r: cl.parentrevs(r)[1] != -1,
1284 return subset.filter(lambda r: cl.parentrevs(r)[1] != -1,
1282 condrepr='<merge>')
1285 condrepr='<merge>')
1283
1286
1284 @predicate('branchpoint()', safe=True)
1287 @predicate('branchpoint()', safe=True)
1285 def branchpoint(repo, subset, x):
1288 def branchpoint(repo, subset, x):
1286 """Changesets with more than one child.
1289 """Changesets with more than one child.
1287 """
1290 """
1288 # i18n: "branchpoint" is a keyword
1291 # i18n: "branchpoint" is a keyword
1289 getargs(x, 0, 0, _("branchpoint takes no arguments"))
1292 getargs(x, 0, 0, _("branchpoint takes no arguments"))
1290 cl = repo.changelog
1293 cl = repo.changelog
1291 if not subset:
1294 if not subset:
1292 return baseset()
1295 return baseset()
1293 # XXX this should be 'parentset.min()' assuming 'parentset' is a smartset
1296 # XXX this should be 'parentset.min()' assuming 'parentset' is a smartset
1294 # (and if it is not, it should.)
1297 # (and if it is not, it should.)
1295 baserev = min(subset)
1298 baserev = min(subset)
1296 parentscount = [0]*(len(repo) - baserev)
1299 parentscount = [0]*(len(repo) - baserev)
1297 for r in cl.revs(start=baserev + 1):
1300 for r in cl.revs(start=baserev + 1):
1298 for p in cl.parentrevs(r):
1301 for p in cl.parentrevs(r):
1299 if p >= baserev:
1302 if p >= baserev:
1300 parentscount[p - baserev] += 1
1303 parentscount[p - baserev] += 1
1301 return subset.filter(lambda r: parentscount[r - baserev] > 1,
1304 return subset.filter(lambda r: parentscount[r - baserev] > 1,
1302 condrepr='<branchpoint>')
1305 condrepr='<branchpoint>')
1303
1306
1304 @predicate('min(set)', safe=True)
1307 @predicate('min(set)', safe=True)
1305 def minrev(repo, subset, x):
1308 def minrev(repo, subset, x):
1306 """Changeset with lowest revision number in set.
1309 """Changeset with lowest revision number in set.
1307 """
1310 """
1308 os = getset(repo, fullreposet(repo), x)
1311 os = getset(repo, fullreposet(repo), x)
1309 try:
1312 try:
1310 m = os.min()
1313 m = os.min()
1311 if m in subset:
1314 if m in subset:
1312 return baseset([m], datarepr=('<min %r, %r>', subset, os))
1315 return baseset([m], datarepr=('<min %r, %r>', subset, os))
1313 except ValueError:
1316 except ValueError:
1314 # os.min() throws a ValueError when the collection is empty.
1317 # os.min() throws a ValueError when the collection is empty.
1315 # Same as python's min().
1318 # Same as python's min().
1316 pass
1319 pass
1317 return baseset(datarepr=('<min %r, %r>', subset, os))
1320 return baseset(datarepr=('<min %r, %r>', subset, os))
1318
1321
1319 @predicate('modifies(pattern)', safe=True)
1322 @predicate('modifies(pattern)', safe=True)
1320 def modifies(repo, subset, x):
1323 def modifies(repo, subset, x):
1321 """Changesets modifying files matched by pattern.
1324 """Changesets modifying files matched by pattern.
1322
1325
1323 The pattern without explicit kind like ``glob:`` is expected to be
1326 The pattern without explicit kind like ``glob:`` is expected to be
1324 relative to the current directory and match against a file or a
1327 relative to the current directory and match against a file or a
1325 directory.
1328 directory.
1326 """
1329 """
1327 # i18n: "modifies" is a keyword
1330 # i18n: "modifies" is a keyword
1328 pat = getstring(x, _("modifies requires a pattern"))
1331 pat = getstring(x, _("modifies requires a pattern"))
1329 return checkstatus(repo, subset, pat, 0)
1332 return checkstatus(repo, subset, pat, 0)
1330
1333
1331 @predicate('named(namespace)')
1334 @predicate('named(namespace)')
1332 def named(repo, subset, x):
1335 def named(repo, subset, x):
1333 """The changesets in a given namespace.
1336 """The changesets in a given namespace.
1334
1337
1335 If `namespace` starts with `re:`, the remainder of the string is treated as
1338 If `namespace` starts with `re:`, the remainder of the string is treated as
1336 a regular expression. To match a namespace that actually starts with `re:`,
1339 a regular expression. To match a namespace that actually starts with `re:`,
1337 use the prefix `literal:`.
1340 use the prefix `literal:`.
1338 """
1341 """
1339 # i18n: "named" is a keyword
1342 # i18n: "named" is a keyword
1340 args = getargs(x, 1, 1, _('named requires a namespace argument'))
1343 args = getargs(x, 1, 1, _('named requires a namespace argument'))
1341
1344
1342 ns = getstring(args[0],
1345 ns = getstring(args[0],
1343 # i18n: "named" is a keyword
1346 # i18n: "named" is a keyword
1344 _('the argument to named must be a string'))
1347 _('the argument to named must be a string'))
1345 kind, pattern, matcher = util.stringmatcher(ns)
1348 kind, pattern, matcher = util.stringmatcher(ns)
1346 namespaces = set()
1349 namespaces = set()
1347 if kind == 'literal':
1350 if kind == 'literal':
1348 if pattern not in repo.names:
1351 if pattern not in repo.names:
1349 raise error.RepoLookupError(_("namespace '%s' does not exist")
1352 raise error.RepoLookupError(_("namespace '%s' does not exist")
1350 % ns)
1353 % ns)
1351 namespaces.add(repo.names[pattern])
1354 namespaces.add(repo.names[pattern])
1352 else:
1355 else:
1353 for name, ns in repo.names.iteritems():
1356 for name, ns in repo.names.iteritems():
1354 if matcher(name):
1357 if matcher(name):
1355 namespaces.add(ns)
1358 namespaces.add(ns)
1356 if not namespaces:
1359 if not namespaces:
1357 raise error.RepoLookupError(_("no namespace exists"
1360 raise error.RepoLookupError(_("no namespace exists"
1358 " that match '%s'") % pattern)
1361 " that match '%s'") % pattern)
1359
1362
1360 names = set()
1363 names = set()
1361 for ns in namespaces:
1364 for ns in namespaces:
1362 for name in ns.listnames(repo):
1365 for name in ns.listnames(repo):
1363 if name not in ns.deprecated:
1366 if name not in ns.deprecated:
1364 names.update(repo[n].rev() for n in ns.nodes(repo, name))
1367 names.update(repo[n].rev() for n in ns.nodes(repo, name))
1365
1368
1366 names -= set([node.nullrev])
1369 names -= set([node.nullrev])
1367 return subset & names
1370 return subset & names
1368
1371
1369 @predicate('id(string)', safe=True)
1372 @predicate('id(string)', safe=True)
1370 def node_(repo, subset, x):
1373 def node_(repo, subset, x):
1371 """Revision non-ambiguously specified by the given hex string prefix.
1374 """Revision non-ambiguously specified by the given hex string prefix.
1372 """
1375 """
1373 # i18n: "id" is a keyword
1376 # i18n: "id" is a keyword
1374 l = getargs(x, 1, 1, _("id requires one argument"))
1377 l = getargs(x, 1, 1, _("id requires one argument"))
1375 # i18n: "id" is a keyword
1378 # i18n: "id" is a keyword
1376 n = getstring(l[0], _("id requires a string"))
1379 n = getstring(l[0], _("id requires a string"))
1377 if len(n) == 40:
1380 if len(n) == 40:
1378 try:
1381 try:
1379 rn = repo.changelog.rev(node.bin(n))
1382 rn = repo.changelog.rev(node.bin(n))
1380 except (LookupError, TypeError):
1383 except (LookupError, TypeError):
1381 rn = None
1384 rn = None
1382 else:
1385 else:
1383 rn = None
1386 rn = None
1384 pm = repo.changelog._partialmatch(n)
1387 pm = repo.changelog._partialmatch(n)
1385 if pm is not None:
1388 if pm is not None:
1386 rn = repo.changelog.rev(pm)
1389 rn = repo.changelog.rev(pm)
1387
1390
1388 if rn is None:
1391 if rn is None:
1389 return baseset()
1392 return baseset()
1390 result = baseset([rn])
1393 result = baseset([rn])
1391 return result & subset
1394 return result & subset
1392
1395
1393 @predicate('obsolete()', safe=True)
1396 @predicate('obsolete()', safe=True)
1394 def obsolete(repo, subset, x):
1397 def obsolete(repo, subset, x):
1395 """Mutable changeset with a newer version."""
1398 """Mutable changeset with a newer version."""
1396 # i18n: "obsolete" is a keyword
1399 # i18n: "obsolete" is a keyword
1397 getargs(x, 0, 0, _("obsolete takes no arguments"))
1400 getargs(x, 0, 0, _("obsolete takes no arguments"))
1398 obsoletes = obsmod.getrevs(repo, 'obsolete')
1401 obsoletes = obsmod.getrevs(repo, 'obsolete')
1399 return subset & obsoletes
1402 return subset & obsoletes
1400
1403
1401 @predicate('only(set, [set])', safe=True)
1404 @predicate('only(set, [set])', safe=True)
1402 def only(repo, subset, x):
1405 def only(repo, subset, x):
1403 """Changesets that are ancestors of the first set that are not ancestors
1406 """Changesets that are ancestors of the first set that are not ancestors
1404 of any other head in the repo. If a second set is specified, the result
1407 of any other head in the repo. If a second set is specified, the result
1405 is ancestors of the first set that are not ancestors of the second set
1408 is ancestors of the first set that are not ancestors of the second set
1406 (i.e. ::<set1> - ::<set2>).
1409 (i.e. ::<set1> - ::<set2>).
1407 """
1410 """
1408 cl = repo.changelog
1411 cl = repo.changelog
1409 # i18n: "only" is a keyword
1412 # i18n: "only" is a keyword
1410 args = getargs(x, 1, 2, _('only takes one or two arguments'))
1413 args = getargs(x, 1, 2, _('only takes one or two arguments'))
1411 include = getset(repo, fullreposet(repo), args[0])
1414 include = getset(repo, fullreposet(repo), args[0])
1412 if len(args) == 1:
1415 if len(args) == 1:
1413 if not include:
1416 if not include:
1414 return baseset()
1417 return baseset()
1415
1418
1416 descendants = set(_revdescendants(repo, include, False))
1419 descendants = set(_revdescendants(repo, include, False))
1417 exclude = [rev for rev in cl.headrevs()
1420 exclude = [rev for rev in cl.headrevs()
1418 if not rev in descendants and not rev in include]
1421 if not rev in descendants and not rev in include]
1419 else:
1422 else:
1420 exclude = getset(repo, fullreposet(repo), args[1])
1423 exclude = getset(repo, fullreposet(repo), args[1])
1421
1424
1422 results = set(cl.findmissingrevs(common=exclude, heads=include))
1425 results = set(cl.findmissingrevs(common=exclude, heads=include))
1423 # XXX we should turn this into a baseset instead of a set, smartset may do
1426 # XXX we should turn this into a baseset instead of a set, smartset may do
1424 # some optimisations from the fact this is a baseset.
1427 # some optimisations from the fact this is a baseset.
1425 return subset & results
1428 return subset & results
1426
1429
1427 @predicate('origin([set])', safe=True)
1430 @predicate('origin([set])', safe=True)
1428 def origin(repo, subset, x):
1431 def origin(repo, subset, x):
1429 """
1432 """
1430 Changesets that were specified as a source for the grafts, transplants or
1433 Changesets that were specified as a source for the grafts, transplants or
1431 rebases that created the given revisions. Omitting the optional set is the
1434 rebases that created the given revisions. Omitting the optional set is the
1432 same as passing all(). If a changeset created by these operations is itself
1435 same as passing all(). If a changeset created by these operations is itself
1433 specified as a source for one of these operations, only the source changeset
1436 specified as a source for one of these operations, only the source changeset
1434 for the first operation is selected.
1437 for the first operation is selected.
1435 """
1438 """
1436 if x is not None:
1439 if x is not None:
1437 dests = getset(repo, fullreposet(repo), x)
1440 dests = getset(repo, fullreposet(repo), x)
1438 else:
1441 else:
1439 dests = fullreposet(repo)
1442 dests = fullreposet(repo)
1440
1443
1441 def _firstsrc(rev):
1444 def _firstsrc(rev):
1442 src = _getrevsource(repo, rev)
1445 src = _getrevsource(repo, rev)
1443 if src is None:
1446 if src is None:
1444 return None
1447 return None
1445
1448
1446 while True:
1449 while True:
1447 prev = _getrevsource(repo, src)
1450 prev = _getrevsource(repo, src)
1448
1451
1449 if prev is None:
1452 if prev is None:
1450 return src
1453 return src
1451 src = prev
1454 src = prev
1452
1455
1453 o = set([_firstsrc(r) for r in dests])
1456 o = set([_firstsrc(r) for r in dests])
1454 o -= set([None])
1457 o -= set([None])
1455 # XXX we should turn this into a baseset instead of a set, smartset may do
1458 # XXX we should turn this into a baseset instead of a set, smartset may do
1456 # some optimisations from the fact this is a baseset.
1459 # some optimisations from the fact this is a baseset.
1457 return subset & o
1460 return subset & o
1458
1461
1459 @predicate('outgoing([path])', safe=True)
1462 @predicate('outgoing([path])', safe=True)
1460 def outgoing(repo, subset, x):
1463 def outgoing(repo, subset, x):
1461 """Changesets not found in the specified destination repository, or the
1464 """Changesets not found in the specified destination repository, or the
1462 default push location.
1465 default push location.
1463 """
1466 """
1464 # Avoid cycles.
1467 # Avoid cycles.
1465 from . import (
1468 from . import (
1466 discovery,
1469 discovery,
1467 hg,
1470 hg,
1468 )
1471 )
1469 # i18n: "outgoing" is a keyword
1472 # i18n: "outgoing" is a keyword
1470 l = getargs(x, 0, 1, _("outgoing takes one or no arguments"))
1473 l = getargs(x, 0, 1, _("outgoing takes one or no arguments"))
1471 # i18n: "outgoing" is a keyword
1474 # i18n: "outgoing" is a keyword
1472 dest = l and getstring(l[0], _("outgoing requires a repository path")) or ''
1475 dest = l and getstring(l[0], _("outgoing requires a repository path")) or ''
1473 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
1476 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
1474 dest, branches = hg.parseurl(dest)
1477 dest, branches = hg.parseurl(dest)
1475 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1478 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1476 if revs:
1479 if revs:
1477 revs = [repo.lookup(rev) for rev in revs]
1480 revs = [repo.lookup(rev) for rev in revs]
1478 other = hg.peer(repo, {}, dest)
1481 other = hg.peer(repo, {}, dest)
1479 repo.ui.pushbuffer()
1482 repo.ui.pushbuffer()
1480 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs)
1483 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs)
1481 repo.ui.popbuffer()
1484 repo.ui.popbuffer()
1482 cl = repo.changelog
1485 cl = repo.changelog
1483 o = set([cl.rev(r) for r in outgoing.missing])
1486 o = set([cl.rev(r) for r in outgoing.missing])
1484 return subset & o
1487 return subset & o
1485
1488
1486 @predicate('p1([set])', safe=True)
1489 @predicate('p1([set])', safe=True)
1487 def p1(repo, subset, x):
1490 def p1(repo, subset, x):
1488 """First parent of changesets in set, or the working directory.
1491 """First parent of changesets in set, or the working directory.
1489 """
1492 """
1490 if x is None:
1493 if x is None:
1491 p = repo[x].p1().rev()
1494 p = repo[x].p1().rev()
1492 if p >= 0:
1495 if p >= 0:
1493 return subset & baseset([p])
1496 return subset & baseset([p])
1494 return baseset()
1497 return baseset()
1495
1498
1496 ps = set()
1499 ps = set()
1497 cl = repo.changelog
1500 cl = repo.changelog
1498 for r in getset(repo, fullreposet(repo), x):
1501 for r in getset(repo, fullreposet(repo), x):
1499 ps.add(cl.parentrevs(r)[0])
1502 ps.add(cl.parentrevs(r)[0])
1500 ps -= set([node.nullrev])
1503 ps -= set([node.nullrev])
1501 # XXX we should turn this into a baseset instead of a set, smartset may do
1504 # XXX we should turn this into a baseset instead of a set, smartset may do
1502 # some optimisations from the fact this is a baseset.
1505 # some optimisations from the fact this is a baseset.
1503 return subset & ps
1506 return subset & ps
1504
1507
1505 @predicate('p2([set])', safe=True)
1508 @predicate('p2([set])', safe=True)
1506 def p2(repo, subset, x):
1509 def p2(repo, subset, x):
1507 """Second parent of changesets in set, or the working directory.
1510 """Second parent of changesets in set, or the working directory.
1508 """
1511 """
1509 if x is None:
1512 if x is None:
1510 ps = repo[x].parents()
1513 ps = repo[x].parents()
1511 try:
1514 try:
1512 p = ps[1].rev()
1515 p = ps[1].rev()
1513 if p >= 0:
1516 if p >= 0:
1514 return subset & baseset([p])
1517 return subset & baseset([p])
1515 return baseset()
1518 return baseset()
1516 except IndexError:
1519 except IndexError:
1517 return baseset()
1520 return baseset()
1518
1521
1519 ps = set()
1522 ps = set()
1520 cl = repo.changelog
1523 cl = repo.changelog
1521 for r in getset(repo, fullreposet(repo), x):
1524 for r in getset(repo, fullreposet(repo), x):
1522 ps.add(cl.parentrevs(r)[1])
1525 ps.add(cl.parentrevs(r)[1])
1523 ps -= set([node.nullrev])
1526 ps -= set([node.nullrev])
1524 # XXX we should turn this into a baseset instead of a set, smartset may do
1527 # XXX we should turn this into a baseset instead of a set, smartset may do
1525 # some optimisations from the fact this is a baseset.
1528 # some optimisations from the fact this is a baseset.
1526 return subset & ps
1529 return subset & ps
1527
1530
1528 @predicate('parents([set])', safe=True)
1531 @predicate('parents([set])', safe=True)
1529 def parents(repo, subset, x):
1532 def parents(repo, subset, x):
1530 """
1533 """
1531 The set of all parents for all changesets in set, or the working directory.
1534 The set of all parents for all changesets in set, or the working directory.
1532 """
1535 """
1533 if x is None:
1536 if x is None:
1534 ps = set(p.rev() for p in repo[x].parents())
1537 ps = set(p.rev() for p in repo[x].parents())
1535 else:
1538 else:
1536 ps = set()
1539 ps = set()
1537 cl = repo.changelog
1540 cl = repo.changelog
1538 up = ps.update
1541 up = ps.update
1539 parentrevs = cl.parentrevs
1542 parentrevs = cl.parentrevs
1540 for r in getset(repo, fullreposet(repo), x):
1543 for r in getset(repo, fullreposet(repo), x):
1541 if r == node.wdirrev:
1544 if r == node.wdirrev:
1542 up(p.rev() for p in repo[r].parents())
1545 up(p.rev() for p in repo[r].parents())
1543 else:
1546 else:
1544 up(parentrevs(r))
1547 up(parentrevs(r))
1545 ps -= set([node.nullrev])
1548 ps -= set([node.nullrev])
1546 return subset & ps
1549 return subset & ps
1547
1550
1548 def _phase(repo, subset, target):
1551 def _phase(repo, subset, target):
1549 """helper to select all rev in phase <target>"""
1552 """helper to select all rev in phase <target>"""
1550 repo._phasecache.loadphaserevs(repo) # ensure phase's sets are loaded
1553 repo._phasecache.loadphaserevs(repo) # ensure phase's sets are loaded
1551 if repo._phasecache._phasesets:
1554 if repo._phasecache._phasesets:
1552 s = repo._phasecache._phasesets[target] - repo.changelog.filteredrevs
1555 s = repo._phasecache._phasesets[target] - repo.changelog.filteredrevs
1553 s = baseset(s)
1556 s = baseset(s)
1554 s.sort() # set are non ordered, so we enforce ascending
1557 s.sort() # set are non ordered, so we enforce ascending
1555 return subset & s
1558 return subset & s
1556 else:
1559 else:
1557 phase = repo._phasecache.phase
1560 phase = repo._phasecache.phase
1558 condition = lambda r: phase(repo, r) == target
1561 condition = lambda r: phase(repo, r) == target
1559 return subset.filter(condition, condrepr=('<phase %r>', target),
1562 return subset.filter(condition, condrepr=('<phase %r>', target),
1560 cache=False)
1563 cache=False)
1561
1564
1562 @predicate('draft()', safe=True)
1565 @predicate('draft()', safe=True)
1563 def draft(repo, subset, x):
1566 def draft(repo, subset, x):
1564 """Changeset in draft phase."""
1567 """Changeset in draft phase."""
1565 # i18n: "draft" is a keyword
1568 # i18n: "draft" is a keyword
1566 getargs(x, 0, 0, _("draft takes no arguments"))
1569 getargs(x, 0, 0, _("draft takes no arguments"))
1567 target = phases.draft
1570 target = phases.draft
1568 return _phase(repo, subset, target)
1571 return _phase(repo, subset, target)
1569
1572
1570 @predicate('secret()', safe=True)
1573 @predicate('secret()', safe=True)
1571 def secret(repo, subset, x):
1574 def secret(repo, subset, x):
1572 """Changeset in secret phase."""
1575 """Changeset in secret phase."""
1573 # i18n: "secret" is a keyword
1576 # i18n: "secret" is a keyword
1574 getargs(x, 0, 0, _("secret takes no arguments"))
1577 getargs(x, 0, 0, _("secret takes no arguments"))
1575 target = phases.secret
1578 target = phases.secret
1576 return _phase(repo, subset, target)
1579 return _phase(repo, subset, target)
1577
1580
1578 def parentspec(repo, subset, x, n):
1581 def parentspec(repo, subset, x, n):
1579 """``set^0``
1582 """``set^0``
1580 The set.
1583 The set.
1581 ``set^1`` (or ``set^``), ``set^2``
1584 ``set^1`` (or ``set^``), ``set^2``
1582 First or second parent, respectively, of all changesets in set.
1585 First or second parent, respectively, of all changesets in set.
1583 """
1586 """
1584 try:
1587 try:
1585 n = int(n[1])
1588 n = int(n[1])
1586 if n not in (0, 1, 2):
1589 if n not in (0, 1, 2):
1587 raise ValueError
1590 raise ValueError
1588 except (TypeError, ValueError):
1591 except (TypeError, ValueError):
1589 raise error.ParseError(_("^ expects a number 0, 1, or 2"))
1592 raise error.ParseError(_("^ expects a number 0, 1, or 2"))
1590 ps = set()
1593 ps = set()
1591 cl = repo.changelog
1594 cl = repo.changelog
1592 for r in getset(repo, fullreposet(repo), x):
1595 for r in getset(repo, fullreposet(repo), x):
1593 if n == 0:
1596 if n == 0:
1594 ps.add(r)
1597 ps.add(r)
1595 elif n == 1:
1598 elif n == 1:
1596 ps.add(cl.parentrevs(r)[0])
1599 ps.add(cl.parentrevs(r)[0])
1597 elif n == 2:
1600 elif n == 2:
1598 parents = cl.parentrevs(r)
1601 parents = cl.parentrevs(r)
1599 if len(parents) > 1:
1602 if len(parents) > 1:
1600 ps.add(parents[1])
1603 ps.add(parents[1])
1601 return subset & ps
1604 return subset & ps
1602
1605
1603 @predicate('present(set)', safe=True)
1606 @predicate('present(set)', safe=True)
1604 def present(repo, subset, x):
1607 def present(repo, subset, x):
1605 """An empty set, if any revision in set isn't found; otherwise,
1608 """An empty set, if any revision in set isn't found; otherwise,
1606 all revisions in set.
1609 all revisions in set.
1607
1610
1608 If any of specified revisions is not present in the local repository,
1611 If any of specified revisions is not present in the local repository,
1609 the query is normally aborted. But this predicate allows the query
1612 the query is normally aborted. But this predicate allows the query
1610 to continue even in such cases.
1613 to continue even in such cases.
1611 """
1614 """
1612 try:
1615 try:
1613 return getset(repo, subset, x)
1616 return getset(repo, subset, x)
1614 except error.RepoLookupError:
1617 except error.RepoLookupError:
1615 return baseset()
1618 return baseset()
1616
1619
1617 # for internal use
1620 # for internal use
1618 @predicate('_notpublic', safe=True)
1621 @predicate('_notpublic', safe=True)
1619 def _notpublic(repo, subset, x):
1622 def _notpublic(repo, subset, x):
1620 getargs(x, 0, 0, "_notpublic takes no arguments")
1623 getargs(x, 0, 0, "_notpublic takes no arguments")
1621 repo._phasecache.loadphaserevs(repo) # ensure phase's sets are loaded
1624 repo._phasecache.loadphaserevs(repo) # ensure phase's sets are loaded
1622 if repo._phasecache._phasesets:
1625 if repo._phasecache._phasesets:
1623 s = set()
1626 s = set()
1624 for u in repo._phasecache._phasesets[1:]:
1627 for u in repo._phasecache._phasesets[1:]:
1625 s.update(u)
1628 s.update(u)
1626 s = baseset(s - repo.changelog.filteredrevs)
1629 s = baseset(s - repo.changelog.filteredrevs)
1627 s.sort()
1630 s.sort()
1628 return subset & s
1631 return subset & s
1629 else:
1632 else:
1630 phase = repo._phasecache.phase
1633 phase = repo._phasecache.phase
1631 target = phases.public
1634 target = phases.public
1632 condition = lambda r: phase(repo, r) != target
1635 condition = lambda r: phase(repo, r) != target
1633 return subset.filter(condition, condrepr=('<phase %r>', target),
1636 return subset.filter(condition, condrepr=('<phase %r>', target),
1634 cache=False)
1637 cache=False)
1635
1638
1636 @predicate('public()', safe=True)
1639 @predicate('public()', safe=True)
1637 def public(repo, subset, x):
1640 def public(repo, subset, x):
1638 """Changeset in public phase."""
1641 """Changeset in public phase."""
1639 # i18n: "public" is a keyword
1642 # i18n: "public" is a keyword
1640 getargs(x, 0, 0, _("public takes no arguments"))
1643 getargs(x, 0, 0, _("public takes no arguments"))
1641 phase = repo._phasecache.phase
1644 phase = repo._phasecache.phase
1642 target = phases.public
1645 target = phases.public
1643 condition = lambda r: phase(repo, r) == target
1646 condition = lambda r: phase(repo, r) == target
1644 return subset.filter(condition, condrepr=('<phase %r>', target),
1647 return subset.filter(condition, condrepr=('<phase %r>', target),
1645 cache=False)
1648 cache=False)
1646
1649
1647 @predicate('remote([id [,path]])', safe=True)
1650 @predicate('remote([id [,path]])', safe=True)
1648 def remote(repo, subset, x):
1651 def remote(repo, subset, x):
1649 """Local revision that corresponds to the given identifier in a
1652 """Local revision that corresponds to the given identifier in a
1650 remote repository, if present. Here, the '.' identifier is a
1653 remote repository, if present. Here, the '.' identifier is a
1651 synonym for the current local branch.
1654 synonym for the current local branch.
1652 """
1655 """
1653
1656
1654 from . import hg # avoid start-up nasties
1657 from . import hg # avoid start-up nasties
1655 # i18n: "remote" is a keyword
1658 # i18n: "remote" is a keyword
1656 l = getargs(x, 0, 2, _("remote takes zero, one, or two arguments"))
1659 l = getargs(x, 0, 2, _("remote takes zero, one, or two arguments"))
1657
1660
1658 q = '.'
1661 q = '.'
1659 if len(l) > 0:
1662 if len(l) > 0:
1660 # i18n: "remote" is a keyword
1663 # i18n: "remote" is a keyword
1661 q = getstring(l[0], _("remote requires a string id"))
1664 q = getstring(l[0], _("remote requires a string id"))
1662 if q == '.':
1665 if q == '.':
1663 q = repo['.'].branch()
1666 q = repo['.'].branch()
1664
1667
1665 dest = ''
1668 dest = ''
1666 if len(l) > 1:
1669 if len(l) > 1:
1667 # i18n: "remote" is a keyword
1670 # i18n: "remote" is a keyword
1668 dest = getstring(l[1], _("remote requires a repository path"))
1671 dest = getstring(l[1], _("remote requires a repository path"))
1669 dest = repo.ui.expandpath(dest or 'default')
1672 dest = repo.ui.expandpath(dest or 'default')
1670 dest, branches = hg.parseurl(dest)
1673 dest, branches = hg.parseurl(dest)
1671 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1674 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1672 if revs:
1675 if revs:
1673 revs = [repo.lookup(rev) for rev in revs]
1676 revs = [repo.lookup(rev) for rev in revs]
1674 other = hg.peer(repo, {}, dest)
1677 other = hg.peer(repo, {}, dest)
1675 n = other.lookup(q)
1678 n = other.lookup(q)
1676 if n in repo:
1679 if n in repo:
1677 r = repo[n].rev()
1680 r = repo[n].rev()
1678 if r in subset:
1681 if r in subset:
1679 return baseset([r])
1682 return baseset([r])
1680 return baseset()
1683 return baseset()
1681
1684
1682 @predicate('removes(pattern)', safe=True)
1685 @predicate('removes(pattern)', safe=True)
1683 def removes(repo, subset, x):
1686 def removes(repo, subset, x):
1684 """Changesets which remove files matching pattern.
1687 """Changesets which remove files matching pattern.
1685
1688
1686 The pattern without explicit kind like ``glob:`` is expected to be
1689 The pattern without explicit kind like ``glob:`` is expected to be
1687 relative to the current directory and match against a file or a
1690 relative to the current directory and match against a file or a
1688 directory.
1691 directory.
1689 """
1692 """
1690 # i18n: "removes" is a keyword
1693 # i18n: "removes" is a keyword
1691 pat = getstring(x, _("removes requires a pattern"))
1694 pat = getstring(x, _("removes requires a pattern"))
1692 return checkstatus(repo, subset, pat, 2)
1695 return checkstatus(repo, subset, pat, 2)
1693
1696
1694 @predicate('rev(number)', safe=True)
1697 @predicate('rev(number)', safe=True)
1695 def rev(repo, subset, x):
1698 def rev(repo, subset, x):
1696 """Revision with the given numeric identifier.
1699 """Revision with the given numeric identifier.
1697 """
1700 """
1698 # i18n: "rev" is a keyword
1701 # i18n: "rev" is a keyword
1699 l = getargs(x, 1, 1, _("rev requires one argument"))
1702 l = getargs(x, 1, 1, _("rev requires one argument"))
1700 try:
1703 try:
1701 # i18n: "rev" is a keyword
1704 # i18n: "rev" is a keyword
1702 l = int(getstring(l[0], _("rev requires a number")))
1705 l = int(getstring(l[0], _("rev requires a number")))
1703 except (TypeError, ValueError):
1706 except (TypeError, ValueError):
1704 # i18n: "rev" is a keyword
1707 # i18n: "rev" is a keyword
1705 raise error.ParseError(_("rev expects a number"))
1708 raise error.ParseError(_("rev expects a number"))
1706 if l not in repo.changelog and l != node.nullrev:
1709 if l not in repo.changelog and l != node.nullrev:
1707 return baseset()
1710 return baseset()
1708 return subset & baseset([l])
1711 return subset & baseset([l])
1709
1712
1710 @predicate('matching(revision [, field])', safe=True)
1713 @predicate('matching(revision [, field])', safe=True)
1711 def matching(repo, subset, x):
1714 def matching(repo, subset, x):
1712 """Changesets in which a given set of fields match the set of fields in the
1715 """Changesets in which a given set of fields match the set of fields in the
1713 selected revision or set.
1716 selected revision or set.
1714
1717
1715 To match more than one field pass the list of fields to match separated
1718 To match more than one field pass the list of fields to match separated
1716 by spaces (e.g. ``author description``).
1719 by spaces (e.g. ``author description``).
1717
1720
1718 Valid fields are most regular revision fields and some special fields.
1721 Valid fields are most regular revision fields and some special fields.
1719
1722
1720 Regular revision fields are ``description``, ``author``, ``branch``,
1723 Regular revision fields are ``description``, ``author``, ``branch``,
1721 ``date``, ``files``, ``phase``, ``parents``, ``substate``, ``user``
1724 ``date``, ``files``, ``phase``, ``parents``, ``substate``, ``user``
1722 and ``diff``.
1725 and ``diff``.
1723 Note that ``author`` and ``user`` are synonyms. ``diff`` refers to the
1726 Note that ``author`` and ``user`` are synonyms. ``diff`` refers to the
1724 contents of the revision. Two revisions matching their ``diff`` will
1727 contents of the revision. Two revisions matching their ``diff`` will
1725 also match their ``files``.
1728 also match their ``files``.
1726
1729
1727 Special fields are ``summary`` and ``metadata``:
1730 Special fields are ``summary`` and ``metadata``:
1728 ``summary`` matches the first line of the description.
1731 ``summary`` matches the first line of the description.
1729 ``metadata`` is equivalent to matching ``description user date``
1732 ``metadata`` is equivalent to matching ``description user date``
1730 (i.e. it matches the main metadata fields).
1733 (i.e. it matches the main metadata fields).
1731
1734
1732 ``metadata`` is the default field which is used when no fields are
1735 ``metadata`` is the default field which is used when no fields are
1733 specified. You can match more than one field at a time.
1736 specified. You can match more than one field at a time.
1734 """
1737 """
1735 # i18n: "matching" is a keyword
1738 # i18n: "matching" is a keyword
1736 l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
1739 l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
1737
1740
1738 revs = getset(repo, fullreposet(repo), l[0])
1741 revs = getset(repo, fullreposet(repo), l[0])
1739
1742
1740 fieldlist = ['metadata']
1743 fieldlist = ['metadata']
1741 if len(l) > 1:
1744 if len(l) > 1:
1742 fieldlist = getstring(l[1],
1745 fieldlist = getstring(l[1],
1743 # i18n: "matching" is a keyword
1746 # i18n: "matching" is a keyword
1744 _("matching requires a string "
1747 _("matching requires a string "
1745 "as its second argument")).split()
1748 "as its second argument")).split()
1746
1749
1747 # Make sure that there are no repeated fields,
1750 # Make sure that there are no repeated fields,
1748 # expand the 'special' 'metadata' field type
1751 # expand the 'special' 'metadata' field type
1749 # and check the 'files' whenever we check the 'diff'
1752 # and check the 'files' whenever we check the 'diff'
1750 fields = []
1753 fields = []
1751 for field in fieldlist:
1754 for field in fieldlist:
1752 if field == 'metadata':
1755 if field == 'metadata':
1753 fields += ['user', 'description', 'date']
1756 fields += ['user', 'description', 'date']
1754 elif field == 'diff':
1757 elif field == 'diff':
1755 # a revision matching the diff must also match the files
1758 # a revision matching the diff must also match the files
1756 # since matching the diff is very costly, make sure to
1759 # since matching the diff is very costly, make sure to
1757 # also match the files first
1760 # also match the files first
1758 fields += ['files', 'diff']
1761 fields += ['files', 'diff']
1759 else:
1762 else:
1760 if field == 'author':
1763 if field == 'author':
1761 field = 'user'
1764 field = 'user'
1762 fields.append(field)
1765 fields.append(field)
1763 fields = set(fields)
1766 fields = set(fields)
1764 if 'summary' in fields and 'description' in fields:
1767 if 'summary' in fields and 'description' in fields:
1765 # If a revision matches its description it also matches its summary
1768 # If a revision matches its description it also matches its summary
1766 fields.discard('summary')
1769 fields.discard('summary')
1767
1770
1768 # We may want to match more than one field
1771 # We may want to match more than one field
1769 # Not all fields take the same amount of time to be matched
1772 # Not all fields take the same amount of time to be matched
1770 # Sort the selected fields in order of increasing matching cost
1773 # Sort the selected fields in order of increasing matching cost
1771 fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary',
1774 fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary',
1772 'files', 'description', 'substate', 'diff']
1775 'files', 'description', 'substate', 'diff']
1773 def fieldkeyfunc(f):
1776 def fieldkeyfunc(f):
1774 try:
1777 try:
1775 return fieldorder.index(f)
1778 return fieldorder.index(f)
1776 except ValueError:
1779 except ValueError:
1777 # assume an unknown field is very costly
1780 # assume an unknown field is very costly
1778 return len(fieldorder)
1781 return len(fieldorder)
1779 fields = list(fields)
1782 fields = list(fields)
1780 fields.sort(key=fieldkeyfunc)
1783 fields.sort(key=fieldkeyfunc)
1781
1784
1782 # Each field will be matched with its own "getfield" function
1785 # Each field will be matched with its own "getfield" function
1783 # which will be added to the getfieldfuncs array of functions
1786 # which will be added to the getfieldfuncs array of functions
1784 getfieldfuncs = []
1787 getfieldfuncs = []
1785 _funcs = {
1788 _funcs = {
1786 'user': lambda r: repo[r].user(),
1789 'user': lambda r: repo[r].user(),
1787 'branch': lambda r: repo[r].branch(),
1790 'branch': lambda r: repo[r].branch(),
1788 'date': lambda r: repo[r].date(),
1791 'date': lambda r: repo[r].date(),
1789 'description': lambda r: repo[r].description(),
1792 'description': lambda r: repo[r].description(),
1790 'files': lambda r: repo[r].files(),
1793 'files': lambda r: repo[r].files(),
1791 'parents': lambda r: repo[r].parents(),
1794 'parents': lambda r: repo[r].parents(),
1792 'phase': lambda r: repo[r].phase(),
1795 'phase': lambda r: repo[r].phase(),
1793 'substate': lambda r: repo[r].substate,
1796 'substate': lambda r: repo[r].substate,
1794 'summary': lambda r: repo[r].description().splitlines()[0],
1797 'summary': lambda r: repo[r].description().splitlines()[0],
1795 'diff': lambda r: list(repo[r].diff(git=True),)
1798 'diff': lambda r: list(repo[r].diff(git=True),)
1796 }
1799 }
1797 for info in fields:
1800 for info in fields:
1798 getfield = _funcs.get(info, None)
1801 getfield = _funcs.get(info, None)
1799 if getfield is None:
1802 if getfield is None:
1800 raise error.ParseError(
1803 raise error.ParseError(
1801 # i18n: "matching" is a keyword
1804 # i18n: "matching" is a keyword
1802 _("unexpected field name passed to matching: %s") % info)
1805 _("unexpected field name passed to matching: %s") % info)
1803 getfieldfuncs.append(getfield)
1806 getfieldfuncs.append(getfield)
1804 # convert the getfield array of functions into a "getinfo" function
1807 # convert the getfield array of functions into a "getinfo" function
1805 # which returns an array of field values (or a single value if there
1808 # which returns an array of field values (or a single value if there
1806 # is only one field to match)
1809 # is only one field to match)
1807 getinfo = lambda r: [f(r) for f in getfieldfuncs]
1810 getinfo = lambda r: [f(r) for f in getfieldfuncs]
1808
1811
1809 def matches(x):
1812 def matches(x):
1810 for rev in revs:
1813 for rev in revs:
1811 target = getinfo(rev)
1814 target = getinfo(rev)
1812 match = True
1815 match = True
1813 for n, f in enumerate(getfieldfuncs):
1816 for n, f in enumerate(getfieldfuncs):
1814 if target[n] != f(x):
1817 if target[n] != f(x):
1815 match = False
1818 match = False
1816 if match:
1819 if match:
1817 return True
1820 return True
1818 return False
1821 return False
1819
1822
1820 return subset.filter(matches, condrepr=('<matching%r %r>', fields, revs))
1823 return subset.filter(matches, condrepr=('<matching%r %r>', fields, revs))
1821
1824
1822 @predicate('reverse(set)', safe=True)
1825 @predicate('reverse(set)', safe=True)
1823 def reverse(repo, subset, x):
1826 def reverse(repo, subset, x):
1824 """Reverse order of set.
1827 """Reverse order of set.
1825 """
1828 """
1826 l = getset(repo, subset, x)
1829 l = getset(repo, subset, x)
1827 l.reverse()
1830 l.reverse()
1828 return l
1831 return l
1829
1832
1830 @predicate('roots(set)', safe=True)
1833 @predicate('roots(set)', safe=True)
1831 def roots(repo, subset, x):
1834 def roots(repo, subset, x):
1832 """Changesets in set with no parent changeset in set.
1835 """Changesets in set with no parent changeset in set.
1833 """
1836 """
1834 s = getset(repo, fullreposet(repo), x)
1837 s = getset(repo, fullreposet(repo), x)
1835 parents = repo.changelog.parentrevs
1838 parents = repo.changelog.parentrevs
1836 def filter(r):
1839 def filter(r):
1837 for p in parents(r):
1840 for p in parents(r):
1838 if 0 <= p and p in s:
1841 if 0 <= p and p in s:
1839 return False
1842 return False
1840 return True
1843 return True
1841 return subset & s.filter(filter, condrepr='<roots>')
1844 return subset & s.filter(filter, condrepr='<roots>')
1842
1845
1843 _sortkeyfuncs = {
1846 _sortkeyfuncs = {
1844 'rev': lambda c: c.rev(),
1847 'rev': lambda c: c.rev(),
1845 'branch': lambda c: c.branch(),
1848 'branch': lambda c: c.branch(),
1846 'desc': lambda c: c.description(),
1849 'desc': lambda c: c.description(),
1847 'user': lambda c: c.user(),
1850 'user': lambda c: c.user(),
1848 'author': lambda c: c.user(),
1851 'author': lambda c: c.user(),
1849 'date': lambda c: c.date()[0],
1852 'date': lambda c: c.date()[0],
1850 }
1853 }
1851
1854
1852 def _getsortargs(x):
1855 def _getsortargs(x):
1853 """Parse sort options into (set, [(key, reverse)], opts)"""
1856 """Parse sort options into (set, [(key, reverse)], opts)"""
1854 args = getargsdict(x, 'sort', 'set keys topo.firstbranch')
1857 args = getargsdict(x, 'sort', 'set keys topo.firstbranch')
1855 if 'set' not in args:
1858 if 'set' not in args:
1856 # i18n: "sort" is a keyword
1859 # i18n: "sort" is a keyword
1857 raise error.ParseError(_('sort requires one or two arguments'))
1860 raise error.ParseError(_('sort requires one or two arguments'))
1858 keys = "rev"
1861 keys = "rev"
1859 if 'keys' in args:
1862 if 'keys' in args:
1860 # i18n: "sort" is a keyword
1863 # i18n: "sort" is a keyword
1861 keys = getstring(args['keys'], _("sort spec must be a string"))
1864 keys = getstring(args['keys'], _("sort spec must be a string"))
1862
1865
1863 keyflags = []
1866 keyflags = []
1864 for k in keys.split():
1867 for k in keys.split():
1865 fk = k
1868 fk = k
1866 reverse = (k[0] == '-')
1869 reverse = (k[0] == '-')
1867 if reverse:
1870 if reverse:
1868 k = k[1:]
1871 k = k[1:]
1869 if k not in _sortkeyfuncs and k != 'topo':
1872 if k not in _sortkeyfuncs and k != 'topo':
1870 raise error.ParseError(_("unknown sort key %r") % fk)
1873 raise error.ParseError(_("unknown sort key %r") % fk)
1871 keyflags.append((k, reverse))
1874 keyflags.append((k, reverse))
1872
1875
1873 if len(keyflags) > 1 and any(k == 'topo' for k, reverse in keyflags):
1876 if len(keyflags) > 1 and any(k == 'topo' for k, reverse in keyflags):
1874 # i18n: "topo" is a keyword
1877 # i18n: "topo" is a keyword
1875 raise error.ParseError(_('topo sort order cannot be combined '
1878 raise error.ParseError(_('topo sort order cannot be combined '
1876 'with other sort keys'))
1879 'with other sort keys'))
1877
1880
1878 opts = {}
1881 opts = {}
1879 if 'topo.firstbranch' in args:
1882 if 'topo.firstbranch' in args:
1880 if any(k == 'topo' for k, reverse in keyflags):
1883 if any(k == 'topo' for k, reverse in keyflags):
1881 opts['topo.firstbranch'] = args['topo.firstbranch']
1884 opts['topo.firstbranch'] = args['topo.firstbranch']
1882 else:
1885 else:
1883 # i18n: "topo" and "topo.firstbranch" are keywords
1886 # i18n: "topo" and "topo.firstbranch" are keywords
1884 raise error.ParseError(_('topo.firstbranch can only be used '
1887 raise error.ParseError(_('topo.firstbranch can only be used '
1885 'when using the topo sort key'))
1888 'when using the topo sort key'))
1886
1889
1887 return args['set'], keyflags, opts
1890 return args['set'], keyflags, opts
1888
1891
1889 @predicate('sort(set[, [-]key... [, ...]])', safe=True)
1892 @predicate('sort(set[, [-]key... [, ...]])', safe=True)
1890 def sort(repo, subset, x):
1893 def sort(repo, subset, x):
1891 """Sort set by keys. The default sort order is ascending, specify a key
1894 """Sort set by keys. The default sort order is ascending, specify a key
1892 as ``-key`` to sort in descending order.
1895 as ``-key`` to sort in descending order.
1893
1896
1894 The keys can be:
1897 The keys can be:
1895
1898
1896 - ``rev`` for the revision number,
1899 - ``rev`` for the revision number,
1897 - ``branch`` for the branch name,
1900 - ``branch`` for the branch name,
1898 - ``desc`` for the commit message (description),
1901 - ``desc`` for the commit message (description),
1899 - ``user`` for user name (``author`` can be used as an alias),
1902 - ``user`` for user name (``author`` can be used as an alias),
1900 - ``date`` for the commit date
1903 - ``date`` for the commit date
1901 - ``topo`` for a reverse topographical sort
1904 - ``topo`` for a reverse topographical sort
1902
1905
1903 The ``topo`` sort order cannot be combined with other sort keys. This sort
1906 The ``topo`` sort order cannot be combined with other sort keys. This sort
1904 takes one optional argument, ``topo.firstbranch``, which takes a revset that
1907 takes one optional argument, ``topo.firstbranch``, which takes a revset that
1905 specifies what topographical branches to prioritize in the sort.
1908 specifies what topographical branches to prioritize in the sort.
1906
1909
1907 """
1910 """
1908 s, keyflags, opts = _getsortargs(x)
1911 s, keyflags, opts = _getsortargs(x)
1909 revs = getset(repo, subset, s)
1912 revs = getset(repo, subset, s)
1910
1913
1911 if not keyflags:
1914 if not keyflags:
1912 return revs
1915 return revs
1913 if len(keyflags) == 1 and keyflags[0][0] == "rev":
1916 if len(keyflags) == 1 and keyflags[0][0] == "rev":
1914 revs.sort(reverse=keyflags[0][1])
1917 revs.sort(reverse=keyflags[0][1])
1915 return revs
1918 return revs
1916 elif keyflags[0][0] == "topo":
1919 elif keyflags[0][0] == "topo":
1917 firstbranch = ()
1920 firstbranch = ()
1918 if 'topo.firstbranch' in opts:
1921 if 'topo.firstbranch' in opts:
1919 firstbranch = getset(repo, subset, opts['topo.firstbranch'])
1922 firstbranch = getset(repo, subset, opts['topo.firstbranch'])
1920 revs = baseset(_toposort(revs, repo.changelog.parentrevs, firstbranch),
1923 revs = baseset(_toposort(revs, repo.changelog.parentrevs, firstbranch),
1921 istopo=True)
1924 istopo=True)
1922 if keyflags[0][1]:
1925 if keyflags[0][1]:
1923 revs.reverse()
1926 revs.reverse()
1924 return revs
1927 return revs
1925
1928
1926 # sort() is guaranteed to be stable
1929 # sort() is guaranteed to be stable
1927 ctxs = [repo[r] for r in revs]
1930 ctxs = [repo[r] for r in revs]
1928 for k, reverse in reversed(keyflags):
1931 for k, reverse in reversed(keyflags):
1929 ctxs.sort(key=_sortkeyfuncs[k], reverse=reverse)
1932 ctxs.sort(key=_sortkeyfuncs[k], reverse=reverse)
1930 return baseset([c.rev() for c in ctxs])
1933 return baseset([c.rev() for c in ctxs])
1931
1934
1932 def _toposort(revs, parentsfunc, firstbranch=()):
1935 def _toposort(revs, parentsfunc, firstbranch=()):
1933 """Yield revisions from heads to roots one (topo) branch at a time.
1936 """Yield revisions from heads to roots one (topo) branch at a time.
1934
1937
1935 This function aims to be used by a graph generator that wishes to minimize
1938 This function aims to be used by a graph generator that wishes to minimize
1936 the number of parallel branches and their interleaving.
1939 the number of parallel branches and their interleaving.
1937
1940
1938 Example iteration order (numbers show the "true" order in a changelog):
1941 Example iteration order (numbers show the "true" order in a changelog):
1939
1942
1940 o 4
1943 o 4
1941 |
1944 |
1942 o 1
1945 o 1
1943 |
1946 |
1944 | o 3
1947 | o 3
1945 | |
1948 | |
1946 | o 2
1949 | o 2
1947 |/
1950 |/
1948 o 0
1951 o 0
1949
1952
1950 Note that the ancestors of merges are understood by the current
1953 Note that the ancestors of merges are understood by the current
1951 algorithm to be on the same branch. This means no reordering will
1954 algorithm to be on the same branch. This means no reordering will
1952 occur behind a merge.
1955 occur behind a merge.
1953 """
1956 """
1954
1957
1955 ### Quick summary of the algorithm
1958 ### Quick summary of the algorithm
1956 #
1959 #
1957 # This function is based around a "retention" principle. We keep revisions
1960 # This function is based around a "retention" principle. We keep revisions
1958 # in memory until we are ready to emit a whole branch that immediately
1961 # in memory until we are ready to emit a whole branch that immediately
1959 # "merges" into an existing one. This reduces the number of parallel
1962 # "merges" into an existing one. This reduces the number of parallel
1960 # branches with interleaved revisions.
1963 # branches with interleaved revisions.
1961 #
1964 #
1962 # During iteration revs are split into two groups:
1965 # During iteration revs are split into two groups:
1963 # A) revision already emitted
1966 # A) revision already emitted
1964 # B) revision in "retention". They are stored as different subgroups.
1967 # B) revision in "retention". They are stored as different subgroups.
1965 #
1968 #
1966 # for each REV, we do the following logic:
1969 # for each REV, we do the following logic:
1967 #
1970 #
1968 # 1) if REV is a parent of (A), we will emit it. If there is a
1971 # 1) if REV is a parent of (A), we will emit it. If there is a
1969 # retention group ((B) above) that is blocked on REV being
1972 # retention group ((B) above) that is blocked on REV being
1970 # available, we emit all the revisions out of that retention
1973 # available, we emit all the revisions out of that retention
1971 # group first.
1974 # group first.
1972 #
1975 #
1973 # 2) else, we'll search for a subgroup in (B) awaiting for REV to be
1976 # 2) else, we'll search for a subgroup in (B) awaiting for REV to be
1974 # available, if such subgroup exist, we add REV to it and the subgroup is
1977 # available, if such subgroup exist, we add REV to it and the subgroup is
1975 # now awaiting for REV.parents() to be available.
1978 # now awaiting for REV.parents() to be available.
1976 #
1979 #
1977 # 3) finally if no such group existed in (B), we create a new subgroup.
1980 # 3) finally if no such group existed in (B), we create a new subgroup.
1978 #
1981 #
1979 #
1982 #
1980 # To bootstrap the algorithm, we emit the tipmost revision (which
1983 # To bootstrap the algorithm, we emit the tipmost revision (which
1981 # puts it in group (A) from above).
1984 # puts it in group (A) from above).
1982
1985
1983 revs.sort(reverse=True)
1986 revs.sort(reverse=True)
1984
1987
1985 # Set of parents of revision that have been emitted. They can be considered
1988 # Set of parents of revision that have been emitted. They can be considered
1986 # unblocked as the graph generator is already aware of them so there is no
1989 # unblocked as the graph generator is already aware of them so there is no
1987 # need to delay the revisions that reference them.
1990 # need to delay the revisions that reference them.
1988 #
1991 #
1989 # If someone wants to prioritize a branch over the others, pre-filling this
1992 # If someone wants to prioritize a branch over the others, pre-filling this
1990 # set will force all other branches to wait until this branch is ready to be
1993 # set will force all other branches to wait until this branch is ready to be
1991 # emitted.
1994 # emitted.
1992 unblocked = set(firstbranch)
1995 unblocked = set(firstbranch)
1993
1996
1994 # list of groups waiting to be displayed, each group is defined by:
1997 # list of groups waiting to be displayed, each group is defined by:
1995 #
1998 #
1996 # (revs: lists of revs waiting to be displayed,
1999 # (revs: lists of revs waiting to be displayed,
1997 # blocked: set of that cannot be displayed before those in 'revs')
2000 # blocked: set of that cannot be displayed before those in 'revs')
1998 #
2001 #
1999 # The second value ('blocked') correspond to parents of any revision in the
2002 # The second value ('blocked') correspond to parents of any revision in the
2000 # group ('revs') that is not itself contained in the group. The main idea
2003 # group ('revs') that is not itself contained in the group. The main idea
2001 # of this algorithm is to delay as much as possible the emission of any
2004 # of this algorithm is to delay as much as possible the emission of any
2002 # revision. This means waiting for the moment we are about to display
2005 # revision. This means waiting for the moment we are about to display
2003 # these parents to display the revs in a group.
2006 # these parents to display the revs in a group.
2004 #
2007 #
2005 # This first implementation is smart until it encounters a merge: it will
2008 # This first implementation is smart until it encounters a merge: it will
2006 # emit revs as soon as any parent is about to be emitted and can grow an
2009 # emit revs as soon as any parent is about to be emitted and can grow an
2007 # arbitrary number of revs in 'blocked'. In practice this mean we properly
2010 # arbitrary number of revs in 'blocked'. In practice this mean we properly
2008 # retains new branches but gives up on any special ordering for ancestors
2011 # retains new branches but gives up on any special ordering for ancestors
2009 # of merges. The implementation can be improved to handle this better.
2012 # of merges. The implementation can be improved to handle this better.
2010 #
2013 #
2011 # The first subgroup is special. It corresponds to all the revision that
2014 # The first subgroup is special. It corresponds to all the revision that
2012 # were already emitted. The 'revs' lists is expected to be empty and the
2015 # were already emitted. The 'revs' lists is expected to be empty and the
2013 # 'blocked' set contains the parents revisions of already emitted revision.
2016 # 'blocked' set contains the parents revisions of already emitted revision.
2014 #
2017 #
2015 # You could pre-seed the <parents> set of groups[0] to a specific
2018 # You could pre-seed the <parents> set of groups[0] to a specific
2016 # changesets to select what the first emitted branch should be.
2019 # changesets to select what the first emitted branch should be.
2017 groups = [([], unblocked)]
2020 groups = [([], unblocked)]
2018 pendingheap = []
2021 pendingheap = []
2019 pendingset = set()
2022 pendingset = set()
2020
2023
2021 heapq.heapify(pendingheap)
2024 heapq.heapify(pendingheap)
2022 heappop = heapq.heappop
2025 heappop = heapq.heappop
2023 heappush = heapq.heappush
2026 heappush = heapq.heappush
2024 for currentrev in revs:
2027 for currentrev in revs:
2025 # Heap works with smallest element, we want highest so we invert
2028 # Heap works with smallest element, we want highest so we invert
2026 if currentrev not in pendingset:
2029 if currentrev not in pendingset:
2027 heappush(pendingheap, -currentrev)
2030 heappush(pendingheap, -currentrev)
2028 pendingset.add(currentrev)
2031 pendingset.add(currentrev)
2029 # iterates on pending rev until after the current rev have been
2032 # iterates on pending rev until after the current rev have been
2030 # processed.
2033 # processed.
2031 rev = None
2034 rev = None
2032 while rev != currentrev:
2035 while rev != currentrev:
2033 rev = -heappop(pendingheap)
2036 rev = -heappop(pendingheap)
2034 pendingset.remove(rev)
2037 pendingset.remove(rev)
2035
2038
2036 # Seek for a subgroup blocked, waiting for the current revision.
2039 # Seek for a subgroup blocked, waiting for the current revision.
2037 matching = [i for i, g in enumerate(groups) if rev in g[1]]
2040 matching = [i for i, g in enumerate(groups) if rev in g[1]]
2038
2041
2039 if matching:
2042 if matching:
2040 # The main idea is to gather together all sets that are blocked
2043 # The main idea is to gather together all sets that are blocked
2041 # on the same revision.
2044 # on the same revision.
2042 #
2045 #
2043 # Groups are merged when a common blocking ancestor is
2046 # Groups are merged when a common blocking ancestor is
2044 # observed. For example, given two groups:
2047 # observed. For example, given two groups:
2045 #
2048 #
2046 # revs [5, 4] waiting for 1
2049 # revs [5, 4] waiting for 1
2047 # revs [3, 2] waiting for 1
2050 # revs [3, 2] waiting for 1
2048 #
2051 #
2049 # These two groups will be merged when we process
2052 # These two groups will be merged when we process
2050 # 1. In theory, we could have merged the groups when
2053 # 1. In theory, we could have merged the groups when
2051 # we added 2 to the group it is now in (we could have
2054 # we added 2 to the group it is now in (we could have
2052 # noticed the groups were both blocked on 1 then), but
2055 # noticed the groups were both blocked on 1 then), but
2053 # the way it works now makes the algorithm simpler.
2056 # the way it works now makes the algorithm simpler.
2054 #
2057 #
2055 # We also always keep the oldest subgroup first. We can
2058 # We also always keep the oldest subgroup first. We can
2056 # probably improve the behavior by having the longest set
2059 # probably improve the behavior by having the longest set
2057 # first. That way, graph algorithms could minimise the length
2060 # first. That way, graph algorithms could minimise the length
2058 # of parallel lines their drawing. This is currently not done.
2061 # of parallel lines their drawing. This is currently not done.
2059 targetidx = matching.pop(0)
2062 targetidx = matching.pop(0)
2060 trevs, tparents = groups[targetidx]
2063 trevs, tparents = groups[targetidx]
2061 for i in matching:
2064 for i in matching:
2062 gr = groups[i]
2065 gr = groups[i]
2063 trevs.extend(gr[0])
2066 trevs.extend(gr[0])
2064 tparents |= gr[1]
2067 tparents |= gr[1]
2065 # delete all merged subgroups (except the one we kept)
2068 # delete all merged subgroups (except the one we kept)
2066 # (starting from the last subgroup for performance and
2069 # (starting from the last subgroup for performance and
2067 # sanity reasons)
2070 # sanity reasons)
2068 for i in reversed(matching):
2071 for i in reversed(matching):
2069 del groups[i]
2072 del groups[i]
2070 else:
2073 else:
2071 # This is a new head. We create a new subgroup for it.
2074 # This is a new head. We create a new subgroup for it.
2072 targetidx = len(groups)
2075 targetidx = len(groups)
2073 groups.append(([], set([rev])))
2076 groups.append(([], set([rev])))
2074
2077
2075 gr = groups[targetidx]
2078 gr = groups[targetidx]
2076
2079
2077 # We now add the current nodes to this subgroups. This is done
2080 # We now add the current nodes to this subgroups. This is done
2078 # after the subgroup merging because all elements from a subgroup
2081 # after the subgroup merging because all elements from a subgroup
2079 # that relied on this rev must precede it.
2082 # that relied on this rev must precede it.
2080 #
2083 #
2081 # we also update the <parents> set to include the parents of the
2084 # we also update the <parents> set to include the parents of the
2082 # new nodes.
2085 # new nodes.
2083 if rev == currentrev: # only display stuff in rev
2086 if rev == currentrev: # only display stuff in rev
2084 gr[0].append(rev)
2087 gr[0].append(rev)
2085 gr[1].remove(rev)
2088 gr[1].remove(rev)
2086 parents = [p for p in parentsfunc(rev) if p > node.nullrev]
2089 parents = [p for p in parentsfunc(rev) if p > node.nullrev]
2087 gr[1].update(parents)
2090 gr[1].update(parents)
2088 for p in parents:
2091 for p in parents:
2089 if p not in pendingset:
2092 if p not in pendingset:
2090 pendingset.add(p)
2093 pendingset.add(p)
2091 heappush(pendingheap, -p)
2094 heappush(pendingheap, -p)
2092
2095
2093 # Look for a subgroup to display
2096 # Look for a subgroup to display
2094 #
2097 #
2095 # When unblocked is empty (if clause), we were not waiting for any
2098 # When unblocked is empty (if clause), we were not waiting for any
2096 # revisions during the first iteration (if no priority was given) or
2099 # revisions during the first iteration (if no priority was given) or
2097 # if we emitted a whole disconnected set of the graph (reached a
2100 # if we emitted a whole disconnected set of the graph (reached a
2098 # root). In that case we arbitrarily take the oldest known
2101 # root). In that case we arbitrarily take the oldest known
2099 # subgroup. The heuristic could probably be better.
2102 # subgroup. The heuristic could probably be better.
2100 #
2103 #
2101 # Otherwise (elif clause) if the subgroup is blocked on
2104 # Otherwise (elif clause) if the subgroup is blocked on
2102 # a revision we just emitted, we can safely emit it as
2105 # a revision we just emitted, we can safely emit it as
2103 # well.
2106 # well.
2104 if not unblocked:
2107 if not unblocked:
2105 if len(groups) > 1: # display other subset
2108 if len(groups) > 1: # display other subset
2106 targetidx = 1
2109 targetidx = 1
2107 gr = groups[1]
2110 gr = groups[1]
2108 elif not gr[1] & unblocked:
2111 elif not gr[1] & unblocked:
2109 gr = None
2112 gr = None
2110
2113
2111 if gr is not None:
2114 if gr is not None:
2112 # update the set of awaited revisions with the one from the
2115 # update the set of awaited revisions with the one from the
2113 # subgroup
2116 # subgroup
2114 unblocked |= gr[1]
2117 unblocked |= gr[1]
2115 # output all revisions in the subgroup
2118 # output all revisions in the subgroup
2116 for r in gr[0]:
2119 for r in gr[0]:
2117 yield r
2120 yield r
2118 # delete the subgroup that you just output
2121 # delete the subgroup that you just output
2119 # unless it is groups[0] in which case you just empty it.
2122 # unless it is groups[0] in which case you just empty it.
2120 if targetidx:
2123 if targetidx:
2121 del groups[targetidx]
2124 del groups[targetidx]
2122 else:
2125 else:
2123 gr[0][:] = []
2126 gr[0][:] = []
2124 # Check if we have some subgroup waiting for revisions we are not going to
2127 # Check if we have some subgroup waiting for revisions we are not going to
2125 # iterate over
2128 # iterate over
2126 for g in groups:
2129 for g in groups:
2127 for r in g[0]:
2130 for r in g[0]:
2128 yield r
2131 yield r
2129
2132
2130 @predicate('subrepo([pattern])')
2133 @predicate('subrepo([pattern])')
2131 def subrepo(repo, subset, x):
2134 def subrepo(repo, subset, x):
2132 """Changesets that add, modify or remove the given subrepo. If no subrepo
2135 """Changesets that add, modify or remove the given subrepo. If no subrepo
2133 pattern is named, any subrepo changes are returned.
2136 pattern is named, any subrepo changes are returned.
2134 """
2137 """
2135 # i18n: "subrepo" is a keyword
2138 # i18n: "subrepo" is a keyword
2136 args = getargs(x, 0, 1, _('subrepo takes at most one argument'))
2139 args = getargs(x, 0, 1, _('subrepo takes at most one argument'))
2137 pat = None
2140 pat = None
2138 if len(args) != 0:
2141 if len(args) != 0:
2139 pat = getstring(args[0], _("subrepo requires a pattern"))
2142 pat = getstring(args[0], _("subrepo requires a pattern"))
2140
2143
2141 m = matchmod.exact(repo.root, repo.root, ['.hgsubstate'])
2144 m = matchmod.exact(repo.root, repo.root, ['.hgsubstate'])
2142
2145
2143 def submatches(names):
2146 def submatches(names):
2144 k, p, m = util.stringmatcher(pat)
2147 k, p, m = util.stringmatcher(pat)
2145 for name in names:
2148 for name in names:
2146 if m(name):
2149 if m(name):
2147 yield name
2150 yield name
2148
2151
2149 def matches(x):
2152 def matches(x):
2150 c = repo[x]
2153 c = repo[x]
2151 s = repo.status(c.p1().node(), c.node(), match=m)
2154 s = repo.status(c.p1().node(), c.node(), match=m)
2152
2155
2153 if pat is None:
2156 if pat is None:
2154 return s.added or s.modified or s.removed
2157 return s.added or s.modified or s.removed
2155
2158
2156 if s.added:
2159 if s.added:
2157 return any(submatches(c.substate.keys()))
2160 return any(submatches(c.substate.keys()))
2158
2161
2159 if s.modified:
2162 if s.modified:
2160 subs = set(c.p1().substate.keys())
2163 subs = set(c.p1().substate.keys())
2161 subs.update(c.substate.keys())
2164 subs.update(c.substate.keys())
2162
2165
2163 for path in submatches(subs):
2166 for path in submatches(subs):
2164 if c.p1().substate.get(path) != c.substate.get(path):
2167 if c.p1().substate.get(path) != c.substate.get(path):
2165 return True
2168 return True
2166
2169
2167 if s.removed:
2170 if s.removed:
2168 return any(submatches(c.p1().substate.keys()))
2171 return any(submatches(c.p1().substate.keys()))
2169
2172
2170 return False
2173 return False
2171
2174
2172 return subset.filter(matches, condrepr=('<subrepo %r>', pat))
2175 return subset.filter(matches, condrepr=('<subrepo %r>', pat))
2173
2176
2174 def _substringmatcher(pattern):
2177 def _substringmatcher(pattern):
2175 kind, pattern, matcher = util.stringmatcher(pattern)
2178 kind, pattern, matcher = util.stringmatcher(pattern)
2176 if kind == 'literal':
2179 if kind == 'literal':
2177 matcher = lambda s: pattern in s
2180 matcher = lambda s: pattern in s
2178 return kind, pattern, matcher
2181 return kind, pattern, matcher
2179
2182
2180 @predicate('tag([name])', safe=True)
2183 @predicate('tag([name])', safe=True)
2181 def tag(repo, subset, x):
2184 def tag(repo, subset, x):
2182 """The specified tag by name, or all tagged revisions if no name is given.
2185 """The specified tag by name, or all tagged revisions if no name is given.
2183
2186
2184 If `name` starts with `re:`, the remainder of the name is treated as
2187 If `name` starts with `re:`, the remainder of the name is treated as
2185 a regular expression. To match a tag that actually starts with `re:`,
2188 a regular expression. To match a tag that actually starts with `re:`,
2186 use the prefix `literal:`.
2189 use the prefix `literal:`.
2187 """
2190 """
2188 # i18n: "tag" is a keyword
2191 # i18n: "tag" is a keyword
2189 args = getargs(x, 0, 1, _("tag takes one or no arguments"))
2192 args = getargs(x, 0, 1, _("tag takes one or no arguments"))
2190 cl = repo.changelog
2193 cl = repo.changelog
2191 if args:
2194 if args:
2192 pattern = getstring(args[0],
2195 pattern = getstring(args[0],
2193 # i18n: "tag" is a keyword
2196 # i18n: "tag" is a keyword
2194 _('the argument to tag must be a string'))
2197 _('the argument to tag must be a string'))
2195 kind, pattern, matcher = util.stringmatcher(pattern)
2198 kind, pattern, matcher = util.stringmatcher(pattern)
2196 if kind == 'literal':
2199 if kind == 'literal':
2197 # avoid resolving all tags
2200 # avoid resolving all tags
2198 tn = repo._tagscache.tags.get(pattern, None)
2201 tn = repo._tagscache.tags.get(pattern, None)
2199 if tn is None:
2202 if tn is None:
2200 raise error.RepoLookupError(_("tag '%s' does not exist")
2203 raise error.RepoLookupError(_("tag '%s' does not exist")
2201 % pattern)
2204 % pattern)
2202 s = set([repo[tn].rev()])
2205 s = set([repo[tn].rev()])
2203 else:
2206 else:
2204 s = set([cl.rev(n) for t, n in repo.tagslist() if matcher(t)])
2207 s = set([cl.rev(n) for t, n in repo.tagslist() if matcher(t)])
2205 else:
2208 else:
2206 s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
2209 s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
2207 return subset & s
2210 return subset & s
2208
2211
2209 @predicate('tagged', safe=True)
2212 @predicate('tagged', safe=True)
2210 def tagged(repo, subset, x):
2213 def tagged(repo, subset, x):
2211 return tag(repo, subset, x)
2214 return tag(repo, subset, x)
2212
2215
2213 @predicate('unstable()', safe=True)
2216 @predicate('unstable()', safe=True)
2214 def unstable(repo, subset, x):
2217 def unstable(repo, subset, x):
2215 """Non-obsolete changesets with obsolete ancestors.
2218 """Non-obsolete changesets with obsolete ancestors.
2216 """
2219 """
2217 # i18n: "unstable" is a keyword
2220 # i18n: "unstable" is a keyword
2218 getargs(x, 0, 0, _("unstable takes no arguments"))
2221 getargs(x, 0, 0, _("unstable takes no arguments"))
2219 unstables = obsmod.getrevs(repo, 'unstable')
2222 unstables = obsmod.getrevs(repo, 'unstable')
2220 return subset & unstables
2223 return subset & unstables
2221
2224
2222
2225
2223 @predicate('user(string)', safe=True)
2226 @predicate('user(string)', safe=True)
2224 def user(repo, subset, x):
2227 def user(repo, subset, x):
2225 """User name contains string. The match is case-insensitive.
2228 """User name contains string. The match is case-insensitive.
2226
2229
2227 If `string` starts with `re:`, the remainder of the string is treated as
2230 If `string` starts with `re:`, the remainder of the string is treated as
2228 a regular expression. To match a user that actually contains `re:`, use
2231 a regular expression. To match a user that actually contains `re:`, use
2229 the prefix `literal:`.
2232 the prefix `literal:`.
2230 """
2233 """
2231 return author(repo, subset, x)
2234 return author(repo, subset, x)
2232
2235
2233 # experimental
2236 # experimental
2234 @predicate('wdir', safe=True)
2237 @predicate('wdir', safe=True)
2235 def wdir(repo, subset, x):
2238 def wdir(repo, subset, x):
2236 # i18n: "wdir" is a keyword
2239 # i18n: "wdir" is a keyword
2237 getargs(x, 0, 0, _("wdir takes no arguments"))
2240 getargs(x, 0, 0, _("wdir takes no arguments"))
2238 if node.wdirrev in subset or isinstance(subset, fullreposet):
2241 if node.wdirrev in subset or isinstance(subset, fullreposet):
2239 return baseset([node.wdirrev])
2242 return baseset([node.wdirrev])
2240 return baseset()
2243 return baseset()
2241
2244
2242 # for internal use
2245 # for internal use
2243 @predicate('_list', safe=True)
2246 @predicate('_list', safe=True)
2244 def _list(repo, subset, x):
2247 def _list(repo, subset, x):
2245 s = getstring(x, "internal error")
2248 s = getstring(x, "internal error")
2246 if not s:
2249 if not s:
2247 return baseset()
2250 return baseset()
2248 # remove duplicates here. it's difficult for caller to deduplicate sets
2251 # remove duplicates here. it's difficult for caller to deduplicate sets
2249 # because different symbols can point to the same rev.
2252 # because different symbols can point to the same rev.
2250 cl = repo.changelog
2253 cl = repo.changelog
2251 ls = []
2254 ls = []
2252 seen = set()
2255 seen = set()
2253 for t in s.split('\0'):
2256 for t in s.split('\0'):
2254 try:
2257 try:
2255 # fast path for integer revision
2258 # fast path for integer revision
2256 r = int(t)
2259 r = int(t)
2257 if str(r) != t or r not in cl:
2260 if str(r) != t or r not in cl:
2258 raise ValueError
2261 raise ValueError
2259 revs = [r]
2262 revs = [r]
2260 except ValueError:
2263 except ValueError:
2261 revs = stringset(repo, subset, t)
2264 revs = stringset(repo, subset, t)
2262
2265
2263 for r in revs:
2266 for r in revs:
2264 if r in seen:
2267 if r in seen:
2265 continue
2268 continue
2266 if (r in subset
2269 if (r in subset
2267 or r == node.nullrev and isinstance(subset, fullreposet)):
2270 or r == node.nullrev and isinstance(subset, fullreposet)):
2268 ls.append(r)
2271 ls.append(r)
2269 seen.add(r)
2272 seen.add(r)
2270 return baseset(ls)
2273 return baseset(ls)
2271
2274
2272 # for internal use
2275 # for internal use
2273 @predicate('_intlist', safe=True)
2276 @predicate('_intlist', safe=True)
2274 def _intlist(repo, subset, x):
2277 def _intlist(repo, subset, x):
2275 s = getstring(x, "internal error")
2278 s = getstring(x, "internal error")
2276 if not s:
2279 if not s:
2277 return baseset()
2280 return baseset()
2278 ls = [int(r) for r in s.split('\0')]
2281 ls = [int(r) for r in s.split('\0')]
2279 s = subset
2282 s = subset
2280 return baseset([r for r in ls if r in s])
2283 return baseset([r for r in ls if r in s])
2281
2284
2282 # for internal use
2285 # for internal use
2283 @predicate('_hexlist', safe=True)
2286 @predicate('_hexlist', safe=True)
2284 def _hexlist(repo, subset, x):
2287 def _hexlist(repo, subset, x):
2285 s = getstring(x, "internal error")
2288 s = getstring(x, "internal error")
2286 if not s:
2289 if not s:
2287 return baseset()
2290 return baseset()
2288 cl = repo.changelog
2291 cl = repo.changelog
2289 ls = [cl.rev(node.bin(r)) for r in s.split('\0')]
2292 ls = [cl.rev(node.bin(r)) for r in s.split('\0')]
2290 s = subset
2293 s = subset
2291 return baseset([r for r in ls if r in s])
2294 return baseset([r for r in ls if r in s])
2292
2295
2293 methods = {
2296 methods = {
2294 "range": rangeset,
2297 "range": rangeset,
2295 "dagrange": dagrange,
2298 "dagrange": dagrange,
2296 "string": stringset,
2299 "string": stringset,
2297 "symbol": stringset,
2300 "symbol": stringset,
2298 "and": andset,
2301 "and": andset,
2299 "or": orset,
2302 "or": orset,
2300 "not": notset,
2303 "not": notset,
2301 "difference": differenceset,
2304 "difference": differenceset,
2302 "list": listset,
2305 "list": listset,
2303 "keyvalue": keyvaluepair,
2306 "keyvalue": keyvaluepair,
2304 "func": func,
2307 "func": func,
2305 "ancestor": ancestorspec,
2308 "ancestor": ancestorspec,
2306 "parent": parentspec,
2309 "parent": parentspec,
2307 "parentpost": p1,
2310 "parentpost": p1,
2308 }
2311 }
2309
2312
2310 def _matchonly(revs, bases):
2313 def _matchonly(revs, bases):
2311 """
2314 """
2312 >>> f = lambda *args: _matchonly(*map(parse, args))
2315 >>> f = lambda *args: _matchonly(*map(parse, args))
2313 >>> f('ancestors(A)', 'not ancestors(B)')
2316 >>> f('ancestors(A)', 'not ancestors(B)')
2314 ('list', ('symbol', 'A'), ('symbol', 'B'))
2317 ('list', ('symbol', 'A'), ('symbol', 'B'))
2315 """
2318 """
2316 if (revs is not None
2319 if (revs is not None
2317 and revs[0] == 'func'
2320 and revs[0] == 'func'
2318 and getsymbol(revs[1]) == 'ancestors'
2321 and getsymbol(revs[1]) == 'ancestors'
2319 and bases is not None
2322 and bases is not None
2320 and bases[0] == 'not'
2323 and bases[0] == 'not'
2321 and bases[1][0] == 'func'
2324 and bases[1][0] == 'func'
2322 and getsymbol(bases[1][1]) == 'ancestors'):
2325 and getsymbol(bases[1][1]) == 'ancestors'):
2323 return ('list', revs[2], bases[1][2])
2326 return ('list', revs[2], bases[1][2])
2324
2327
2325 def _fixops(x):
2328 def _fixops(x):
2326 """Rewrite raw parsed tree to resolve ambiguous syntax which cannot be
2329 """Rewrite raw parsed tree to resolve ambiguous syntax which cannot be
2327 handled well by our simple top-down parser"""
2330 handled well by our simple top-down parser"""
2328 if not isinstance(x, tuple):
2331 if not isinstance(x, tuple):
2329 return x
2332 return x
2330
2333
2331 op = x[0]
2334 op = x[0]
2332 if op == 'parent':
2335 if op == 'parent':
2333 # x^:y means (x^) : y, not x ^ (:y)
2336 # x^:y means (x^) : y, not x ^ (:y)
2334 # x^: means (x^) :, not x ^ (:)
2337 # x^: means (x^) :, not x ^ (:)
2335 post = ('parentpost', x[1])
2338 post = ('parentpost', x[1])
2336 if x[2][0] == 'dagrangepre':
2339 if x[2][0] == 'dagrangepre':
2337 return _fixops(('dagrange', post, x[2][1]))
2340 return _fixops(('dagrange', post, x[2][1]))
2338 elif x[2][0] == 'rangepre':
2341 elif x[2][0] == 'rangepre':
2339 return _fixops(('range', post, x[2][1]))
2342 return _fixops(('range', post, x[2][1]))
2340 elif x[2][0] == 'rangeall':
2343 elif x[2][0] == 'rangeall':
2341 return _fixops(('rangepost', post))
2344 return _fixops(('rangepost', post))
2345 elif op == 'or':
2346 # make number of arguments deterministic:
2347 # x + y + z -> (or x y z) -> (or (list x y z))
2348 return (op, _fixops(('list',) + x[1:]))
2342
2349
2343 return (op,) + tuple(_fixops(y) for y in x[1:])
2350 return (op,) + tuple(_fixops(y) for y in x[1:])
2344
2351
2345 def _analyze(x):
2352 def _analyze(x):
2346 if x is None:
2353 if x is None:
2347 return x
2354 return x
2348
2355
2349 op = x[0]
2356 op = x[0]
2350 if op == 'minus':
2357 if op == 'minus':
2351 return _analyze(('and', x[1], ('not', x[2])))
2358 return _analyze(('and', x[1], ('not', x[2])))
2352 elif op == 'only':
2359 elif op == 'only':
2353 t = ('func', ('symbol', 'only'), ('list', x[1], x[2]))
2360 t = ('func', ('symbol', 'only'), ('list', x[1], x[2]))
2354 return _analyze(t)
2361 return _analyze(t)
2355 elif op == 'onlypost':
2362 elif op == 'onlypost':
2356 return _analyze(('func', ('symbol', 'only'), x[1]))
2363 return _analyze(('func', ('symbol', 'only'), x[1]))
2357 elif op == 'dagrangepre':
2364 elif op == 'dagrangepre':
2358 return _analyze(('func', ('symbol', 'ancestors'), x[1]))
2365 return _analyze(('func', ('symbol', 'ancestors'), x[1]))
2359 elif op == 'dagrangepost':
2366 elif op == 'dagrangepost':
2360 return _analyze(('func', ('symbol', 'descendants'), x[1]))
2367 return _analyze(('func', ('symbol', 'descendants'), x[1]))
2361 elif op == 'rangeall':
2368 elif op == 'rangeall':
2362 return _analyze(('range', ('string', '0'), ('string', 'tip')))
2369 return _analyze(('range', ('string', '0'), ('string', 'tip')))
2363 elif op == 'rangepre':
2370 elif op == 'rangepre':
2364 return _analyze(('range', ('string', '0'), x[1]))
2371 return _analyze(('range', ('string', '0'), x[1]))
2365 elif op == 'rangepost':
2372 elif op == 'rangepost':
2366 return _analyze(('range', x[1], ('string', 'tip')))
2373 return _analyze(('range', x[1], ('string', 'tip')))
2367 elif op == 'negate':
2374 elif op == 'negate':
2368 s = getstring(x[1], _("can't negate that"))
2375 s = getstring(x[1], _("can't negate that"))
2369 return _analyze(('string', '-' + s))
2376 return _analyze(('string', '-' + s))
2370 elif op in ('string', 'symbol'):
2377 elif op in ('string', 'symbol'):
2371 return x
2378 return x
2372 elif op == 'and':
2379 elif op == 'and':
2373 ta = _analyze(x[1])
2380 ta = _analyze(x[1])
2374 tb = _analyze(x[2])
2381 tb = _analyze(x[2])
2375 return (op, ta, tb)
2382 return (op, ta, tb)
2376 elif op == 'or':
2383 elif op == 'or':
2377 return (op,) + tuple(_analyze(y) for y in x[1:])
2384 return (op, _analyze(x[1]))
2378 elif op == 'not':
2385 elif op == 'not':
2379 return (op, _analyze(x[1]))
2386 return (op, _analyze(x[1]))
2380 elif op == 'parentpost':
2387 elif op == 'parentpost':
2381 return (op, _analyze(x[1]))
2388 return (op, _analyze(x[1]))
2382 elif op == 'group':
2389 elif op == 'group':
2383 return _analyze(x[1])
2390 return _analyze(x[1])
2384 elif op in ('dagrange', 'range', 'parent', 'ancestor'):
2391 elif op in ('dagrange', 'range', 'parent', 'ancestor'):
2385 ta = _analyze(x[1])
2392 ta = _analyze(x[1])
2386 tb = _analyze(x[2])
2393 tb = _analyze(x[2])
2387 return (op, ta, tb)
2394 return (op, ta, tb)
2388 elif op == 'list':
2395 elif op == 'list':
2389 return (op,) + tuple(_analyze(y) for y in x[1:])
2396 return (op,) + tuple(_analyze(y) for y in x[1:])
2390 elif op == 'keyvalue':
2397 elif op == 'keyvalue':
2391 return (op, x[1], _analyze(x[2]))
2398 return (op, x[1], _analyze(x[2]))
2392 elif op == 'func':
2399 elif op == 'func':
2393 return (op, x[1], _analyze(x[2]))
2400 return (op, x[1], _analyze(x[2]))
2394 raise ValueError('invalid operator %r' % op)
2401 raise ValueError('invalid operator %r' % op)
2395
2402
2396 def analyze(x):
2403 def analyze(x):
2397 """Transform raw parsed tree to evaluatable tree which can be fed to
2404 """Transform raw parsed tree to evaluatable tree which can be fed to
2398 optimize() or getset()
2405 optimize() or getset()
2399
2406
2400 All pseudo operations should be mapped to real operations or functions
2407 All pseudo operations should be mapped to real operations or functions
2401 defined in methods or symbols table respectively.
2408 defined in methods or symbols table respectively.
2402 """
2409 """
2403 return _analyze(x)
2410 return _analyze(x)
2404
2411
2405 def _optimize(x, small):
2412 def _optimize(x, small):
2406 if x is None:
2413 if x is None:
2407 return 0, x
2414 return 0, x
2408
2415
2409 smallbonus = 1
2416 smallbonus = 1
2410 if small:
2417 if small:
2411 smallbonus = .5
2418 smallbonus = .5
2412
2419
2413 op = x[0]
2420 op = x[0]
2414 if op in ('string', 'symbol'):
2421 if op in ('string', 'symbol'):
2415 return smallbonus, x # single revisions are small
2422 return smallbonus, x # single revisions are small
2416 elif op == 'and':
2423 elif op == 'and':
2417 wa, ta = _optimize(x[1], True)
2424 wa, ta = _optimize(x[1], True)
2418 wb, tb = _optimize(x[2], True)
2425 wb, tb = _optimize(x[2], True)
2419 w = min(wa, wb)
2426 w = min(wa, wb)
2420
2427
2421 # (::x and not ::y)/(not ::y and ::x) have a fast path
2428 # (::x and not ::y)/(not ::y and ::x) have a fast path
2422 tm = _matchonly(ta, tb) or _matchonly(tb, ta)
2429 tm = _matchonly(ta, tb) or _matchonly(tb, ta)
2423 if tm:
2430 if tm:
2424 return w, ('func', ('symbol', 'only'), tm)
2431 return w, ('func', ('symbol', 'only'), tm)
2425
2432
2426 if tb is not None and tb[0] == 'not':
2433 if tb is not None and tb[0] == 'not':
2427 return wa, ('difference', ta, tb[1])
2434 return wa, ('difference', ta, tb[1])
2428
2435
2429 if wa > wb:
2436 if wa > wb:
2430 return w, (op, tb, ta)
2437 return w, (op, tb, ta)
2431 return w, (op, ta, tb)
2438 return w, (op, ta, tb)
2432 elif op == 'or':
2439 elif op == 'or':
2433 # fast path for machine-generated expression, that is likely to have
2440 # fast path for machine-generated expression, that is likely to have
2434 # lots of trivial revisions: 'a + b + c()' to '_list(a b) + c()'
2441 # lots of trivial revisions: 'a + b + c()' to '_list(a b) + c()'
2435 ws, ts, ss = [], [], []
2442 ws, ts, ss = [], [], []
2436 def flushss():
2443 def flushss():
2437 if not ss:
2444 if not ss:
2438 return
2445 return
2439 if len(ss) == 1:
2446 if len(ss) == 1:
2440 w, t = ss[0]
2447 w, t = ss[0]
2441 else:
2448 else:
2442 s = '\0'.join(t[1] for w, t in ss)
2449 s = '\0'.join(t[1] for w, t in ss)
2443 y = ('func', ('symbol', '_list'), ('string', s))
2450 y = ('func', ('symbol', '_list'), ('string', s))
2444 w, t = _optimize(y, False)
2451 w, t = _optimize(y, False)
2445 ws.append(w)
2452 ws.append(w)
2446 ts.append(t)
2453 ts.append(t)
2447 del ss[:]
2454 del ss[:]
2448 for y in x[1:]:
2455 for y in getlist(x[1]):
2449 w, t = _optimize(y, False)
2456 w, t = _optimize(y, False)
2450 if t is not None and (t[0] == 'string' or t[0] == 'symbol'):
2457 if t is not None and (t[0] == 'string' or t[0] == 'symbol'):
2451 ss.append((w, t))
2458 ss.append((w, t))
2452 continue
2459 continue
2453 flushss()
2460 flushss()
2454 ws.append(w)
2461 ws.append(w)
2455 ts.append(t)
2462 ts.append(t)
2456 flushss()
2463 flushss()
2457 if len(ts) == 1:
2464 if len(ts) == 1:
2458 return ws[0], ts[0] # 'or' operation is fully optimized out
2465 return ws[0], ts[0] # 'or' operation is fully optimized out
2459 # we can't reorder trees by weight because it would change the order.
2466 # we can't reorder trees by weight because it would change the order.
2460 # ("sort(a + b)" == "sort(b + a)", but "a + b" != "b + a")
2467 # ("sort(a + b)" == "sort(b + a)", but "a + b" != "b + a")
2461 # ts = tuple(t for w, t in sorted(zip(ws, ts), key=lambda wt: wt[0]))
2468 # ts = tuple(t for w, t in sorted(zip(ws, ts), key=lambda wt: wt[0]))
2462 return max(ws), (op,) + tuple(ts)
2469 return max(ws), (op, ('list',) + tuple(ts))
2463 elif op == 'not':
2470 elif op == 'not':
2464 # Optimize not public() to _notpublic() because we have a fast version
2471 # Optimize not public() to _notpublic() because we have a fast version
2465 if x[1] == ('func', ('symbol', 'public'), None):
2472 if x[1] == ('func', ('symbol', 'public'), None):
2466 newsym = ('func', ('symbol', '_notpublic'), None)
2473 newsym = ('func', ('symbol', '_notpublic'), None)
2467 o = _optimize(newsym, not small)
2474 o = _optimize(newsym, not small)
2468 return o[0], o[1]
2475 return o[0], o[1]
2469 else:
2476 else:
2470 o = _optimize(x[1], not small)
2477 o = _optimize(x[1], not small)
2471 return o[0], (op, o[1])
2478 return o[0], (op, o[1])
2472 elif op == 'parentpost':
2479 elif op == 'parentpost':
2473 o = _optimize(x[1], small)
2480 o = _optimize(x[1], small)
2474 return o[0], (op, o[1])
2481 return o[0], (op, o[1])
2475 elif op in ('dagrange', 'range', 'parent', 'ancestor'):
2482 elif op in ('dagrange', 'range', 'parent', 'ancestor'):
2476 wa, ta = _optimize(x[1], small)
2483 wa, ta = _optimize(x[1], small)
2477 wb, tb = _optimize(x[2], small)
2484 wb, tb = _optimize(x[2], small)
2478 return wa + wb, (op, ta, tb)
2485 return wa + wb, (op, ta, tb)
2479 elif op == 'list':
2486 elif op == 'list':
2480 ws, ts = zip(*(_optimize(y, small) for y in x[1:]))
2487 ws, ts = zip(*(_optimize(y, small) for y in x[1:]))
2481 return sum(ws), (op,) + ts
2488 return sum(ws), (op,) + ts
2482 elif op == 'keyvalue':
2489 elif op == 'keyvalue':
2483 w, t = _optimize(x[2], small)
2490 w, t = _optimize(x[2], small)
2484 return w, (op, x[1], t)
2491 return w, (op, x[1], t)
2485 elif op == 'func':
2492 elif op == 'func':
2486 f = getsymbol(x[1])
2493 f = getsymbol(x[1])
2487 wa, ta = _optimize(x[2], small)
2494 wa, ta = _optimize(x[2], small)
2488 if f in ('author', 'branch', 'closed', 'date', 'desc', 'file', 'grep',
2495 if f in ('author', 'branch', 'closed', 'date', 'desc', 'file', 'grep',
2489 'keyword', 'outgoing', 'user'):
2496 'keyword', 'outgoing', 'user'):
2490 w = 10 # slow
2497 w = 10 # slow
2491 elif f in ('modifies', 'adds', 'removes'):
2498 elif f in ('modifies', 'adds', 'removes'):
2492 w = 30 # slower
2499 w = 30 # slower
2493 elif f == "contains":
2500 elif f == "contains":
2494 w = 100 # very slow
2501 w = 100 # very slow
2495 elif f == "ancestor":
2502 elif f == "ancestor":
2496 w = 1 * smallbonus
2503 w = 1 * smallbonus
2497 elif f in ('reverse', 'limit', 'first', '_intlist'):
2504 elif f in ('reverse', 'limit', 'first', '_intlist'):
2498 w = 0
2505 w = 0
2499 elif f == "sort":
2506 elif f == "sort":
2500 w = 10 # assume most sorts look at changelog
2507 w = 10 # assume most sorts look at changelog
2501 else:
2508 else:
2502 w = 1
2509 w = 1
2503 return w + wa, (op, x[1], ta)
2510 return w + wa, (op, x[1], ta)
2504 raise ValueError('invalid operator %r' % op)
2511 raise ValueError('invalid operator %r' % op)
2505
2512
2506 def optimize(tree):
2513 def optimize(tree):
2507 """Optimize evaluatable tree
2514 """Optimize evaluatable tree
2508
2515
2509 All pseudo operations should be transformed beforehand.
2516 All pseudo operations should be transformed beforehand.
2510 """
2517 """
2511 _weight, newtree = _optimize(tree, small=True)
2518 _weight, newtree = _optimize(tree, small=True)
2512 return newtree
2519 return newtree
2513
2520
2514 # the set of valid characters for the initial letter of symbols in
2521 # the set of valid characters for the initial letter of symbols in
2515 # alias declarations and definitions
2522 # alias declarations and definitions
2516 _aliassyminitletters = set(c for c in [chr(i) for i in xrange(256)]
2523 _aliassyminitletters = set(c for c in [chr(i) for i in xrange(256)]
2517 if c.isalnum() or c in '._@$' or ord(c) > 127)
2524 if c.isalnum() or c in '._@$' or ord(c) > 127)
2518
2525
2519 def _parsewith(spec, lookup=None, syminitletters=None):
2526 def _parsewith(spec, lookup=None, syminitletters=None):
2520 """Generate a parse tree of given spec with given tokenizing options
2527 """Generate a parse tree of given spec with given tokenizing options
2521
2528
2522 >>> _parsewith('foo($1)', syminitletters=_aliassyminitletters)
2529 >>> _parsewith('foo($1)', syminitletters=_aliassyminitletters)
2523 ('func', ('symbol', 'foo'), ('symbol', '$1'))
2530 ('func', ('symbol', 'foo'), ('symbol', '$1'))
2524 >>> _parsewith('$1')
2531 >>> _parsewith('$1')
2525 Traceback (most recent call last):
2532 Traceback (most recent call last):
2526 ...
2533 ...
2527 ParseError: ("syntax error in revset '$1'", 0)
2534 ParseError: ("syntax error in revset '$1'", 0)
2528 >>> _parsewith('foo bar')
2535 >>> _parsewith('foo bar')
2529 Traceback (most recent call last):
2536 Traceback (most recent call last):
2530 ...
2537 ...
2531 ParseError: ('invalid token', 4)
2538 ParseError: ('invalid token', 4)
2532 """
2539 """
2533 p = parser.parser(elements)
2540 p = parser.parser(elements)
2534 tree, pos = p.parse(tokenize(spec, lookup=lookup,
2541 tree, pos = p.parse(tokenize(spec, lookup=lookup,
2535 syminitletters=syminitletters))
2542 syminitletters=syminitletters))
2536 if pos != len(spec):
2543 if pos != len(spec):
2537 raise error.ParseError(_('invalid token'), pos)
2544 raise error.ParseError(_('invalid token'), pos)
2538 return _fixops(parser.simplifyinfixops(tree, ('list', 'or')))
2545 return _fixops(parser.simplifyinfixops(tree, ('list', 'or')))
2539
2546
2540 class _aliasrules(parser.basealiasrules):
2547 class _aliasrules(parser.basealiasrules):
2541 """Parsing and expansion rule set of revset aliases"""
2548 """Parsing and expansion rule set of revset aliases"""
2542 _section = _('revset alias')
2549 _section = _('revset alias')
2543
2550
2544 @staticmethod
2551 @staticmethod
2545 def _parse(spec):
2552 def _parse(spec):
2546 """Parse alias declaration/definition ``spec``
2553 """Parse alias declaration/definition ``spec``
2547
2554
2548 This allows symbol names to use also ``$`` as an initial letter
2555 This allows symbol names to use also ``$`` as an initial letter
2549 (for backward compatibility), and callers of this function should
2556 (for backward compatibility), and callers of this function should
2550 examine whether ``$`` is used also for unexpected symbols or not.
2557 examine whether ``$`` is used also for unexpected symbols or not.
2551 """
2558 """
2552 return _parsewith(spec, syminitletters=_aliassyminitletters)
2559 return _parsewith(spec, syminitletters=_aliassyminitletters)
2553
2560
2554 @staticmethod
2561 @staticmethod
2555 def _trygetfunc(tree):
2562 def _trygetfunc(tree):
2556 if tree[0] == 'func' and tree[1][0] == 'symbol':
2563 if tree[0] == 'func' and tree[1][0] == 'symbol':
2557 return tree[1][1], getlist(tree[2])
2564 return tree[1][1], getlist(tree[2])
2558
2565
2559 def expandaliases(ui, tree):
2566 def expandaliases(ui, tree):
2560 aliases = _aliasrules.buildmap(ui.configitems('revsetalias'))
2567 aliases = _aliasrules.buildmap(ui.configitems('revsetalias'))
2561 tree = _aliasrules.expand(aliases, tree)
2568 tree = _aliasrules.expand(aliases, tree)
2562 # warn about problematic (but not referred) aliases
2569 # warn about problematic (but not referred) aliases
2563 for name, alias in sorted(aliases.iteritems()):
2570 for name, alias in sorted(aliases.iteritems()):
2564 if alias.error and not alias.warned:
2571 if alias.error and not alias.warned:
2565 ui.warn(_('warning: %s\n') % (alias.error))
2572 ui.warn(_('warning: %s\n') % (alias.error))
2566 alias.warned = True
2573 alias.warned = True
2567 return tree
2574 return tree
2568
2575
2569 def foldconcat(tree):
2576 def foldconcat(tree):
2570 """Fold elements to be concatenated by `##`
2577 """Fold elements to be concatenated by `##`
2571 """
2578 """
2572 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
2579 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
2573 return tree
2580 return tree
2574 if tree[0] == '_concat':
2581 if tree[0] == '_concat':
2575 pending = [tree]
2582 pending = [tree]
2576 l = []
2583 l = []
2577 while pending:
2584 while pending:
2578 e = pending.pop()
2585 e = pending.pop()
2579 if e[0] == '_concat':
2586 if e[0] == '_concat':
2580 pending.extend(reversed(e[1:]))
2587 pending.extend(reversed(e[1:]))
2581 elif e[0] in ('string', 'symbol'):
2588 elif e[0] in ('string', 'symbol'):
2582 l.append(e[1])
2589 l.append(e[1])
2583 else:
2590 else:
2584 msg = _("\"##\" can't concatenate \"%s\" element") % (e[0])
2591 msg = _("\"##\" can't concatenate \"%s\" element") % (e[0])
2585 raise error.ParseError(msg)
2592 raise error.ParseError(msg)
2586 return ('string', ''.join(l))
2593 return ('string', ''.join(l))
2587 else:
2594 else:
2588 return tuple(foldconcat(t) for t in tree)
2595 return tuple(foldconcat(t) for t in tree)
2589
2596
2590 def parse(spec, lookup=None):
2597 def parse(spec, lookup=None):
2591 return _parsewith(spec, lookup=lookup)
2598 return _parsewith(spec, lookup=lookup)
2592
2599
2593 def posttreebuilthook(tree, repo):
2600 def posttreebuilthook(tree, repo):
2594 # hook for extensions to execute code on the optimized tree
2601 # hook for extensions to execute code on the optimized tree
2595 pass
2602 pass
2596
2603
2597 def match(ui, spec, repo=None):
2604 def match(ui, spec, repo=None):
2598 """Create a matcher for a single revision spec."""
2605 """Create a matcher for a single revision spec."""
2599 return matchany(ui, [spec], repo=repo)
2606 return matchany(ui, [spec], repo=repo)
2600
2607
2601 def matchany(ui, specs, repo=None):
2608 def matchany(ui, specs, repo=None):
2602 """Create a matcher that will include any revisions matching one of the
2609 """Create a matcher that will include any revisions matching one of the
2603 given specs"""
2610 given specs"""
2604 if not specs:
2611 if not specs:
2605 def mfunc(repo, subset=None):
2612 def mfunc(repo, subset=None):
2606 return baseset()
2613 return baseset()
2607 return mfunc
2614 return mfunc
2608 if not all(specs):
2615 if not all(specs):
2609 raise error.ParseError(_("empty query"))
2616 raise error.ParseError(_("empty query"))
2610 lookup = None
2617 lookup = None
2611 if repo:
2618 if repo:
2612 lookup = repo.__contains__
2619 lookup = repo.__contains__
2613 if len(specs) == 1:
2620 if len(specs) == 1:
2614 tree = parse(specs[0], lookup)
2621 tree = parse(specs[0], lookup)
2615 else:
2622 else:
2616 tree = ('or',) + tuple(parse(s, lookup) for s in specs)
2623 tree = ('or', ('list',) + tuple(parse(s, lookup) for s in specs))
2617
2624
2618 if ui:
2625 if ui:
2619 tree = expandaliases(ui, tree)
2626 tree = expandaliases(ui, tree)
2620 tree = foldconcat(tree)
2627 tree = foldconcat(tree)
2621 tree = analyze(tree)
2628 tree = analyze(tree)
2622 tree = optimize(tree)
2629 tree = optimize(tree)
2623 posttreebuilthook(tree, repo)
2630 posttreebuilthook(tree, repo)
2624 return makematcher(tree)
2631 return makematcher(tree)
2625
2632
2626 def makematcher(tree):
2633 def makematcher(tree):
2627 """Create a matcher from an evaluatable tree"""
2634 """Create a matcher from an evaluatable tree"""
2628 def mfunc(repo, subset=None):
2635 def mfunc(repo, subset=None):
2629 if subset is None:
2636 if subset is None:
2630 subset = fullreposet(repo)
2637 subset = fullreposet(repo)
2631 if util.safehasattr(subset, 'isascending'):
2638 if util.safehasattr(subset, 'isascending'):
2632 result = getset(repo, subset, tree)
2639 result = getset(repo, subset, tree)
2633 else:
2640 else:
2634 result = getset(repo, baseset(subset), tree)
2641 result = getset(repo, baseset(subset), tree)
2635 return result
2642 return result
2636 return mfunc
2643 return mfunc
2637
2644
2638 def formatspec(expr, *args):
2645 def formatspec(expr, *args):
2639 '''
2646 '''
2640 This is a convenience function for using revsets internally, and
2647 This is a convenience function for using revsets internally, and
2641 escapes arguments appropriately. Aliases are intentionally ignored
2648 escapes arguments appropriately. Aliases are intentionally ignored
2642 so that intended expression behavior isn't accidentally subverted.
2649 so that intended expression behavior isn't accidentally subverted.
2643
2650
2644 Supported arguments:
2651 Supported arguments:
2645
2652
2646 %r = revset expression, parenthesized
2653 %r = revset expression, parenthesized
2647 %d = int(arg), no quoting
2654 %d = int(arg), no quoting
2648 %s = string(arg), escaped and single-quoted
2655 %s = string(arg), escaped and single-quoted
2649 %b = arg.branch(), escaped and single-quoted
2656 %b = arg.branch(), escaped and single-quoted
2650 %n = hex(arg), single-quoted
2657 %n = hex(arg), single-quoted
2651 %% = a literal '%'
2658 %% = a literal '%'
2652
2659
2653 Prefixing the type with 'l' specifies a parenthesized list of that type.
2660 Prefixing the type with 'l' specifies a parenthesized list of that type.
2654
2661
2655 >>> formatspec('%r:: and %lr', '10 or 11', ("this()", "that()"))
2662 >>> formatspec('%r:: and %lr', '10 or 11', ("this()", "that()"))
2656 '(10 or 11):: and ((this()) or (that()))'
2663 '(10 or 11):: and ((this()) or (that()))'
2657 >>> formatspec('%d:: and not %d::', 10, 20)
2664 >>> formatspec('%d:: and not %d::', 10, 20)
2658 '10:: and not 20::'
2665 '10:: and not 20::'
2659 >>> formatspec('%ld or %ld', [], [1])
2666 >>> formatspec('%ld or %ld', [], [1])
2660 "_list('') or 1"
2667 "_list('') or 1"
2661 >>> formatspec('keyword(%s)', 'foo\\xe9')
2668 >>> formatspec('keyword(%s)', 'foo\\xe9')
2662 "keyword('foo\\\\xe9')"
2669 "keyword('foo\\\\xe9')"
2663 >>> b = lambda: 'default'
2670 >>> b = lambda: 'default'
2664 >>> b.branch = b
2671 >>> b.branch = b
2665 >>> formatspec('branch(%b)', b)
2672 >>> formatspec('branch(%b)', b)
2666 "branch('default')"
2673 "branch('default')"
2667 >>> formatspec('root(%ls)', ['a', 'b', 'c', 'd'])
2674 >>> formatspec('root(%ls)', ['a', 'b', 'c', 'd'])
2668 "root(_list('a\\x00b\\x00c\\x00d'))"
2675 "root(_list('a\\x00b\\x00c\\x00d'))"
2669 '''
2676 '''
2670
2677
2671 def quote(s):
2678 def quote(s):
2672 return repr(str(s))
2679 return repr(str(s))
2673
2680
2674 def argtype(c, arg):
2681 def argtype(c, arg):
2675 if c == 'd':
2682 if c == 'd':
2676 return str(int(arg))
2683 return str(int(arg))
2677 elif c == 's':
2684 elif c == 's':
2678 return quote(arg)
2685 return quote(arg)
2679 elif c == 'r':
2686 elif c == 'r':
2680 parse(arg) # make sure syntax errors are confined
2687 parse(arg) # make sure syntax errors are confined
2681 return '(%s)' % arg
2688 return '(%s)' % arg
2682 elif c == 'n':
2689 elif c == 'n':
2683 return quote(node.hex(arg))
2690 return quote(node.hex(arg))
2684 elif c == 'b':
2691 elif c == 'b':
2685 return quote(arg.branch())
2692 return quote(arg.branch())
2686
2693
2687 def listexp(s, t):
2694 def listexp(s, t):
2688 l = len(s)
2695 l = len(s)
2689 if l == 0:
2696 if l == 0:
2690 return "_list('')"
2697 return "_list('')"
2691 elif l == 1:
2698 elif l == 1:
2692 return argtype(t, s[0])
2699 return argtype(t, s[0])
2693 elif t == 'd':
2700 elif t == 'd':
2694 return "_intlist('%s')" % "\0".join(str(int(a)) for a in s)
2701 return "_intlist('%s')" % "\0".join(str(int(a)) for a in s)
2695 elif t == 's':
2702 elif t == 's':
2696 return "_list('%s')" % "\0".join(s)
2703 return "_list('%s')" % "\0".join(s)
2697 elif t == 'n':
2704 elif t == 'n':
2698 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s)
2705 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s)
2699 elif t == 'b':
2706 elif t == 'b':
2700 return "_list('%s')" % "\0".join(a.branch() for a in s)
2707 return "_list('%s')" % "\0".join(a.branch() for a in s)
2701
2708
2702 m = l // 2
2709 m = l // 2
2703 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t))
2710 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t))
2704
2711
2705 ret = ''
2712 ret = ''
2706 pos = 0
2713 pos = 0
2707 arg = 0
2714 arg = 0
2708 while pos < len(expr):
2715 while pos < len(expr):
2709 c = expr[pos]
2716 c = expr[pos]
2710 if c == '%':
2717 if c == '%':
2711 pos += 1
2718 pos += 1
2712 d = expr[pos]
2719 d = expr[pos]
2713 if d == '%':
2720 if d == '%':
2714 ret += d
2721 ret += d
2715 elif d in 'dsnbr':
2722 elif d in 'dsnbr':
2716 ret += argtype(d, args[arg])
2723 ret += argtype(d, args[arg])
2717 arg += 1
2724 arg += 1
2718 elif d == 'l':
2725 elif d == 'l':
2719 # a list of some type
2726 # a list of some type
2720 pos += 1
2727 pos += 1
2721 d = expr[pos]
2728 d = expr[pos]
2722 ret += listexp(list(args[arg]), d)
2729 ret += listexp(list(args[arg]), d)
2723 arg += 1
2730 arg += 1
2724 else:
2731 else:
2725 raise error.Abort(_('unexpected revspec format character %s')
2732 raise error.Abort(_('unexpected revspec format character %s')
2726 % d)
2733 % d)
2727 else:
2734 else:
2728 ret += c
2735 ret += c
2729 pos += 1
2736 pos += 1
2730
2737
2731 return ret
2738 return ret
2732
2739
2733 def prettyformat(tree):
2740 def prettyformat(tree):
2734 return parser.prettyformat(tree, ('string', 'symbol'))
2741 return parser.prettyformat(tree, ('string', 'symbol'))
2735
2742
2736 def depth(tree):
2743 def depth(tree):
2737 if isinstance(tree, tuple):
2744 if isinstance(tree, tuple):
2738 return max(map(depth, tree)) + 1
2745 return max(map(depth, tree)) + 1
2739 else:
2746 else:
2740 return 0
2747 return 0
2741
2748
2742 def funcsused(tree):
2749 def funcsused(tree):
2743 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
2750 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
2744 return set()
2751 return set()
2745 else:
2752 else:
2746 funcs = set()
2753 funcs = set()
2747 for s in tree[1:]:
2754 for s in tree[1:]:
2748 funcs |= funcsused(s)
2755 funcs |= funcsused(s)
2749 if tree[0] == 'func':
2756 if tree[0] == 'func':
2750 funcs.add(tree[1][1])
2757 funcs.add(tree[1][1])
2751 return funcs
2758 return funcs
2752
2759
2753 def _formatsetrepr(r):
2760 def _formatsetrepr(r):
2754 """Format an optional printable representation of a set
2761 """Format an optional printable representation of a set
2755
2762
2756 ======== =================================
2763 ======== =================================
2757 type(r) example
2764 type(r) example
2758 ======== =================================
2765 ======== =================================
2759 tuple ('<not %r>', other)
2766 tuple ('<not %r>', other)
2760 str '<branch closed>'
2767 str '<branch closed>'
2761 callable lambda: '<branch %r>' % sorted(b)
2768 callable lambda: '<branch %r>' % sorted(b)
2762 object other
2769 object other
2763 ======== =================================
2770 ======== =================================
2764 """
2771 """
2765 if r is None:
2772 if r is None:
2766 return ''
2773 return ''
2767 elif isinstance(r, tuple):
2774 elif isinstance(r, tuple):
2768 return r[0] % r[1:]
2775 return r[0] % r[1:]
2769 elif isinstance(r, str):
2776 elif isinstance(r, str):
2770 return r
2777 return r
2771 elif callable(r):
2778 elif callable(r):
2772 return r()
2779 return r()
2773 else:
2780 else:
2774 return repr(r)
2781 return repr(r)
2775
2782
2776 class abstractsmartset(object):
2783 class abstractsmartset(object):
2777
2784
2778 def __nonzero__(self):
2785 def __nonzero__(self):
2779 """True if the smartset is not empty"""
2786 """True if the smartset is not empty"""
2780 raise NotImplementedError()
2787 raise NotImplementedError()
2781
2788
2782 def __contains__(self, rev):
2789 def __contains__(self, rev):
2783 """provide fast membership testing"""
2790 """provide fast membership testing"""
2784 raise NotImplementedError()
2791 raise NotImplementedError()
2785
2792
2786 def __iter__(self):
2793 def __iter__(self):
2787 """iterate the set in the order it is supposed to be iterated"""
2794 """iterate the set in the order it is supposed to be iterated"""
2788 raise NotImplementedError()
2795 raise NotImplementedError()
2789
2796
2790 # Attributes containing a function to perform a fast iteration in a given
2797 # Attributes containing a function to perform a fast iteration in a given
2791 # direction. A smartset can have none, one, or both defined.
2798 # direction. A smartset can have none, one, or both defined.
2792 #
2799 #
2793 # Default value is None instead of a function returning None to avoid
2800 # Default value is None instead of a function returning None to avoid
2794 # initializing an iterator just for testing if a fast method exists.
2801 # initializing an iterator just for testing if a fast method exists.
2795 fastasc = None
2802 fastasc = None
2796 fastdesc = None
2803 fastdesc = None
2797
2804
2798 def isascending(self):
2805 def isascending(self):
2799 """True if the set will iterate in ascending order"""
2806 """True if the set will iterate in ascending order"""
2800 raise NotImplementedError()
2807 raise NotImplementedError()
2801
2808
2802 def isdescending(self):
2809 def isdescending(self):
2803 """True if the set will iterate in descending order"""
2810 """True if the set will iterate in descending order"""
2804 raise NotImplementedError()
2811 raise NotImplementedError()
2805
2812
2806 def istopo(self):
2813 def istopo(self):
2807 """True if the set will iterate in topographical order"""
2814 """True if the set will iterate in topographical order"""
2808 raise NotImplementedError()
2815 raise NotImplementedError()
2809
2816
2810 @util.cachefunc
2817 @util.cachefunc
2811 def min(self):
2818 def min(self):
2812 """return the minimum element in the set"""
2819 """return the minimum element in the set"""
2813 if self.fastasc is not None:
2820 if self.fastasc is not None:
2814 for r in self.fastasc():
2821 for r in self.fastasc():
2815 return r
2822 return r
2816 raise ValueError('arg is an empty sequence')
2823 raise ValueError('arg is an empty sequence')
2817 return min(self)
2824 return min(self)
2818
2825
2819 @util.cachefunc
2826 @util.cachefunc
2820 def max(self):
2827 def max(self):
2821 """return the maximum element in the set"""
2828 """return the maximum element in the set"""
2822 if self.fastdesc is not None:
2829 if self.fastdesc is not None:
2823 for r in self.fastdesc():
2830 for r in self.fastdesc():
2824 return r
2831 return r
2825 raise ValueError('arg is an empty sequence')
2832 raise ValueError('arg is an empty sequence')
2826 return max(self)
2833 return max(self)
2827
2834
2828 def first(self):
2835 def first(self):
2829 """return the first element in the set (user iteration perspective)
2836 """return the first element in the set (user iteration perspective)
2830
2837
2831 Return None if the set is empty"""
2838 Return None if the set is empty"""
2832 raise NotImplementedError()
2839 raise NotImplementedError()
2833
2840
2834 def last(self):
2841 def last(self):
2835 """return the last element in the set (user iteration perspective)
2842 """return the last element in the set (user iteration perspective)
2836
2843
2837 Return None if the set is empty"""
2844 Return None if the set is empty"""
2838 raise NotImplementedError()
2845 raise NotImplementedError()
2839
2846
2840 def __len__(self):
2847 def __len__(self):
2841 """return the length of the smartsets
2848 """return the length of the smartsets
2842
2849
2843 This can be expensive on smartset that could be lazy otherwise."""
2850 This can be expensive on smartset that could be lazy otherwise."""
2844 raise NotImplementedError()
2851 raise NotImplementedError()
2845
2852
2846 def reverse(self):
2853 def reverse(self):
2847 """reverse the expected iteration order"""
2854 """reverse the expected iteration order"""
2848 raise NotImplementedError()
2855 raise NotImplementedError()
2849
2856
2850 def sort(self, reverse=True):
2857 def sort(self, reverse=True):
2851 """get the set to iterate in an ascending or descending order"""
2858 """get the set to iterate in an ascending or descending order"""
2852 raise NotImplementedError()
2859 raise NotImplementedError()
2853
2860
2854 def __and__(self, other):
2861 def __and__(self, other):
2855 """Returns a new object with the intersection of the two collections.
2862 """Returns a new object with the intersection of the two collections.
2856
2863
2857 This is part of the mandatory API for smartset."""
2864 This is part of the mandatory API for smartset."""
2858 if isinstance(other, fullreposet):
2865 if isinstance(other, fullreposet):
2859 return self
2866 return self
2860 return self.filter(other.__contains__, condrepr=other, cache=False)
2867 return self.filter(other.__contains__, condrepr=other, cache=False)
2861
2868
2862 def __add__(self, other):
2869 def __add__(self, other):
2863 """Returns a new object with the union of the two collections.
2870 """Returns a new object with the union of the two collections.
2864
2871
2865 This is part of the mandatory API for smartset."""
2872 This is part of the mandatory API for smartset."""
2866 return addset(self, other)
2873 return addset(self, other)
2867
2874
2868 def __sub__(self, other):
2875 def __sub__(self, other):
2869 """Returns a new object with the substraction of the two collections.
2876 """Returns a new object with the substraction of the two collections.
2870
2877
2871 This is part of the mandatory API for smartset."""
2878 This is part of the mandatory API for smartset."""
2872 c = other.__contains__
2879 c = other.__contains__
2873 return self.filter(lambda r: not c(r), condrepr=('<not %r>', other),
2880 return self.filter(lambda r: not c(r), condrepr=('<not %r>', other),
2874 cache=False)
2881 cache=False)
2875
2882
2876 def filter(self, condition, condrepr=None, cache=True):
2883 def filter(self, condition, condrepr=None, cache=True):
2877 """Returns this smartset filtered by condition as a new smartset.
2884 """Returns this smartset filtered by condition as a new smartset.
2878
2885
2879 `condition` is a callable which takes a revision number and returns a
2886 `condition` is a callable which takes a revision number and returns a
2880 boolean. Optional `condrepr` provides a printable representation of
2887 boolean. Optional `condrepr` provides a printable representation of
2881 the given `condition`.
2888 the given `condition`.
2882
2889
2883 This is part of the mandatory API for smartset."""
2890 This is part of the mandatory API for smartset."""
2884 # builtin cannot be cached. but do not needs to
2891 # builtin cannot be cached. but do not needs to
2885 if cache and util.safehasattr(condition, 'func_code'):
2892 if cache and util.safehasattr(condition, 'func_code'):
2886 condition = util.cachefunc(condition)
2893 condition = util.cachefunc(condition)
2887 return filteredset(self, condition, condrepr)
2894 return filteredset(self, condition, condrepr)
2888
2895
2889 class baseset(abstractsmartset):
2896 class baseset(abstractsmartset):
2890 """Basic data structure that represents a revset and contains the basic
2897 """Basic data structure that represents a revset and contains the basic
2891 operation that it should be able to perform.
2898 operation that it should be able to perform.
2892
2899
2893 Every method in this class should be implemented by any smartset class.
2900 Every method in this class should be implemented by any smartset class.
2894 """
2901 """
2895 def __init__(self, data=(), datarepr=None, istopo=False):
2902 def __init__(self, data=(), datarepr=None, istopo=False):
2896 """
2903 """
2897 datarepr: a tuple of (format, obj, ...), a function or an object that
2904 datarepr: a tuple of (format, obj, ...), a function or an object that
2898 provides a printable representation of the given data.
2905 provides a printable representation of the given data.
2899 """
2906 """
2900 self._ascending = None
2907 self._ascending = None
2901 self._istopo = istopo
2908 self._istopo = istopo
2902 if not isinstance(data, list):
2909 if not isinstance(data, list):
2903 if isinstance(data, set):
2910 if isinstance(data, set):
2904 self._set = data
2911 self._set = data
2905 # set has no order we pick one for stability purpose
2912 # set has no order we pick one for stability purpose
2906 self._ascending = True
2913 self._ascending = True
2907 data = list(data)
2914 data = list(data)
2908 self._list = data
2915 self._list = data
2909 self._datarepr = datarepr
2916 self._datarepr = datarepr
2910
2917
2911 @util.propertycache
2918 @util.propertycache
2912 def _set(self):
2919 def _set(self):
2913 return set(self._list)
2920 return set(self._list)
2914
2921
2915 @util.propertycache
2922 @util.propertycache
2916 def _asclist(self):
2923 def _asclist(self):
2917 asclist = self._list[:]
2924 asclist = self._list[:]
2918 asclist.sort()
2925 asclist.sort()
2919 return asclist
2926 return asclist
2920
2927
2921 def __iter__(self):
2928 def __iter__(self):
2922 if self._ascending is None:
2929 if self._ascending is None:
2923 return iter(self._list)
2930 return iter(self._list)
2924 elif self._ascending:
2931 elif self._ascending:
2925 return iter(self._asclist)
2932 return iter(self._asclist)
2926 else:
2933 else:
2927 return reversed(self._asclist)
2934 return reversed(self._asclist)
2928
2935
2929 def fastasc(self):
2936 def fastasc(self):
2930 return iter(self._asclist)
2937 return iter(self._asclist)
2931
2938
2932 def fastdesc(self):
2939 def fastdesc(self):
2933 return reversed(self._asclist)
2940 return reversed(self._asclist)
2934
2941
2935 @util.propertycache
2942 @util.propertycache
2936 def __contains__(self):
2943 def __contains__(self):
2937 return self._set.__contains__
2944 return self._set.__contains__
2938
2945
2939 def __nonzero__(self):
2946 def __nonzero__(self):
2940 return bool(self._list)
2947 return bool(self._list)
2941
2948
2942 def sort(self, reverse=False):
2949 def sort(self, reverse=False):
2943 self._ascending = not bool(reverse)
2950 self._ascending = not bool(reverse)
2944 self._istopo = False
2951 self._istopo = False
2945
2952
2946 def reverse(self):
2953 def reverse(self):
2947 if self._ascending is None:
2954 if self._ascending is None:
2948 self._list.reverse()
2955 self._list.reverse()
2949 else:
2956 else:
2950 self._ascending = not self._ascending
2957 self._ascending = not self._ascending
2951 self._istopo = False
2958 self._istopo = False
2952
2959
2953 def __len__(self):
2960 def __len__(self):
2954 return len(self._list)
2961 return len(self._list)
2955
2962
2956 def isascending(self):
2963 def isascending(self):
2957 """Returns True if the collection is ascending order, False if not.
2964 """Returns True if the collection is ascending order, False if not.
2958
2965
2959 This is part of the mandatory API for smartset."""
2966 This is part of the mandatory API for smartset."""
2960 if len(self) <= 1:
2967 if len(self) <= 1:
2961 return True
2968 return True
2962 return self._ascending is not None and self._ascending
2969 return self._ascending is not None and self._ascending
2963
2970
2964 def isdescending(self):
2971 def isdescending(self):
2965 """Returns True if the collection is descending order, False if not.
2972 """Returns True if the collection is descending order, False if not.
2966
2973
2967 This is part of the mandatory API for smartset."""
2974 This is part of the mandatory API for smartset."""
2968 if len(self) <= 1:
2975 if len(self) <= 1:
2969 return True
2976 return True
2970 return self._ascending is not None and not self._ascending
2977 return self._ascending is not None and not self._ascending
2971
2978
2972 def istopo(self):
2979 def istopo(self):
2973 """Is the collection is in topographical order or not.
2980 """Is the collection is in topographical order or not.
2974
2981
2975 This is part of the mandatory API for smartset."""
2982 This is part of the mandatory API for smartset."""
2976 if len(self) <= 1:
2983 if len(self) <= 1:
2977 return True
2984 return True
2978 return self._istopo
2985 return self._istopo
2979
2986
2980 def first(self):
2987 def first(self):
2981 if self:
2988 if self:
2982 if self._ascending is None:
2989 if self._ascending is None:
2983 return self._list[0]
2990 return self._list[0]
2984 elif self._ascending:
2991 elif self._ascending:
2985 return self._asclist[0]
2992 return self._asclist[0]
2986 else:
2993 else:
2987 return self._asclist[-1]
2994 return self._asclist[-1]
2988 return None
2995 return None
2989
2996
2990 def last(self):
2997 def last(self):
2991 if self:
2998 if self:
2992 if self._ascending is None:
2999 if self._ascending is None:
2993 return self._list[-1]
3000 return self._list[-1]
2994 elif self._ascending:
3001 elif self._ascending:
2995 return self._asclist[-1]
3002 return self._asclist[-1]
2996 else:
3003 else:
2997 return self._asclist[0]
3004 return self._asclist[0]
2998 return None
3005 return None
2999
3006
3000 def __repr__(self):
3007 def __repr__(self):
3001 d = {None: '', False: '-', True: '+'}[self._ascending]
3008 d = {None: '', False: '-', True: '+'}[self._ascending]
3002 s = _formatsetrepr(self._datarepr)
3009 s = _formatsetrepr(self._datarepr)
3003 if not s:
3010 if not s:
3004 l = self._list
3011 l = self._list
3005 # if _list has been built from a set, it might have a different
3012 # if _list has been built from a set, it might have a different
3006 # order from one python implementation to another.
3013 # order from one python implementation to another.
3007 # We fallback to the sorted version for a stable output.
3014 # We fallback to the sorted version for a stable output.
3008 if self._ascending is not None:
3015 if self._ascending is not None:
3009 l = self._asclist
3016 l = self._asclist
3010 s = repr(l)
3017 s = repr(l)
3011 return '<%s%s %s>' % (type(self).__name__, d, s)
3018 return '<%s%s %s>' % (type(self).__name__, d, s)
3012
3019
3013 class filteredset(abstractsmartset):
3020 class filteredset(abstractsmartset):
3014 """Duck type for baseset class which iterates lazily over the revisions in
3021 """Duck type for baseset class which iterates lazily over the revisions in
3015 the subset and contains a function which tests for membership in the
3022 the subset and contains a function which tests for membership in the
3016 revset
3023 revset
3017 """
3024 """
3018 def __init__(self, subset, condition=lambda x: True, condrepr=None):
3025 def __init__(self, subset, condition=lambda x: True, condrepr=None):
3019 """
3026 """
3020 condition: a function that decide whether a revision in the subset
3027 condition: a function that decide whether a revision in the subset
3021 belongs to the revset or not.
3028 belongs to the revset or not.
3022 condrepr: a tuple of (format, obj, ...), a function or an object that
3029 condrepr: a tuple of (format, obj, ...), a function or an object that
3023 provides a printable representation of the given condition.
3030 provides a printable representation of the given condition.
3024 """
3031 """
3025 self._subset = subset
3032 self._subset = subset
3026 self._condition = condition
3033 self._condition = condition
3027 self._condrepr = condrepr
3034 self._condrepr = condrepr
3028
3035
3029 def __contains__(self, x):
3036 def __contains__(self, x):
3030 return x in self._subset and self._condition(x)
3037 return x in self._subset and self._condition(x)
3031
3038
3032 def __iter__(self):
3039 def __iter__(self):
3033 return self._iterfilter(self._subset)
3040 return self._iterfilter(self._subset)
3034
3041
3035 def _iterfilter(self, it):
3042 def _iterfilter(self, it):
3036 cond = self._condition
3043 cond = self._condition
3037 for x in it:
3044 for x in it:
3038 if cond(x):
3045 if cond(x):
3039 yield x
3046 yield x
3040
3047
3041 @property
3048 @property
3042 def fastasc(self):
3049 def fastasc(self):
3043 it = self._subset.fastasc
3050 it = self._subset.fastasc
3044 if it is None:
3051 if it is None:
3045 return None
3052 return None
3046 return lambda: self._iterfilter(it())
3053 return lambda: self._iterfilter(it())
3047
3054
3048 @property
3055 @property
3049 def fastdesc(self):
3056 def fastdesc(self):
3050 it = self._subset.fastdesc
3057 it = self._subset.fastdesc
3051 if it is None:
3058 if it is None:
3052 return None
3059 return None
3053 return lambda: self._iterfilter(it())
3060 return lambda: self._iterfilter(it())
3054
3061
3055 def __nonzero__(self):
3062 def __nonzero__(self):
3056 fast = None
3063 fast = None
3057 candidates = [self.fastasc if self.isascending() else None,
3064 candidates = [self.fastasc if self.isascending() else None,
3058 self.fastdesc if self.isdescending() else None,
3065 self.fastdesc if self.isdescending() else None,
3059 self.fastasc,
3066 self.fastasc,
3060 self.fastdesc]
3067 self.fastdesc]
3061 for candidate in candidates:
3068 for candidate in candidates:
3062 if candidate is not None:
3069 if candidate is not None:
3063 fast = candidate
3070 fast = candidate
3064 break
3071 break
3065
3072
3066 if fast is not None:
3073 if fast is not None:
3067 it = fast()
3074 it = fast()
3068 else:
3075 else:
3069 it = self
3076 it = self
3070
3077
3071 for r in it:
3078 for r in it:
3072 return True
3079 return True
3073 return False
3080 return False
3074
3081
3075 def __len__(self):
3082 def __len__(self):
3076 # Basic implementation to be changed in future patches.
3083 # Basic implementation to be changed in future patches.
3077 # until this gets improved, we use generator expression
3084 # until this gets improved, we use generator expression
3078 # here, since list compr is free to call __len__ again
3085 # here, since list compr is free to call __len__ again
3079 # causing infinite recursion
3086 # causing infinite recursion
3080 l = baseset(r for r in self)
3087 l = baseset(r for r in self)
3081 return len(l)
3088 return len(l)
3082
3089
3083 def sort(self, reverse=False):
3090 def sort(self, reverse=False):
3084 self._subset.sort(reverse=reverse)
3091 self._subset.sort(reverse=reverse)
3085
3092
3086 def reverse(self):
3093 def reverse(self):
3087 self._subset.reverse()
3094 self._subset.reverse()
3088
3095
3089 def isascending(self):
3096 def isascending(self):
3090 return self._subset.isascending()
3097 return self._subset.isascending()
3091
3098
3092 def isdescending(self):
3099 def isdescending(self):
3093 return self._subset.isdescending()
3100 return self._subset.isdescending()
3094
3101
3095 def istopo(self):
3102 def istopo(self):
3096 return self._subset.istopo()
3103 return self._subset.istopo()
3097
3104
3098 def first(self):
3105 def first(self):
3099 for x in self:
3106 for x in self:
3100 return x
3107 return x
3101 return None
3108 return None
3102
3109
3103 def last(self):
3110 def last(self):
3104 it = None
3111 it = None
3105 if self.isascending():
3112 if self.isascending():
3106 it = self.fastdesc
3113 it = self.fastdesc
3107 elif self.isdescending():
3114 elif self.isdescending():
3108 it = self.fastasc
3115 it = self.fastasc
3109 if it is not None:
3116 if it is not None:
3110 for x in it():
3117 for x in it():
3111 return x
3118 return x
3112 return None #empty case
3119 return None #empty case
3113 else:
3120 else:
3114 x = None
3121 x = None
3115 for x in self:
3122 for x in self:
3116 pass
3123 pass
3117 return x
3124 return x
3118
3125
3119 def __repr__(self):
3126 def __repr__(self):
3120 xs = [repr(self._subset)]
3127 xs = [repr(self._subset)]
3121 s = _formatsetrepr(self._condrepr)
3128 s = _formatsetrepr(self._condrepr)
3122 if s:
3129 if s:
3123 xs.append(s)
3130 xs.append(s)
3124 return '<%s %s>' % (type(self).__name__, ', '.join(xs))
3131 return '<%s %s>' % (type(self).__name__, ', '.join(xs))
3125
3132
3126 def _iterordered(ascending, iter1, iter2):
3133 def _iterordered(ascending, iter1, iter2):
3127 """produce an ordered iteration from two iterators with the same order
3134 """produce an ordered iteration from two iterators with the same order
3128
3135
3129 The ascending is used to indicated the iteration direction.
3136 The ascending is used to indicated the iteration direction.
3130 """
3137 """
3131 choice = max
3138 choice = max
3132 if ascending:
3139 if ascending:
3133 choice = min
3140 choice = min
3134
3141
3135 val1 = None
3142 val1 = None
3136 val2 = None
3143 val2 = None
3137 try:
3144 try:
3138 # Consume both iterators in an ordered way until one is empty
3145 # Consume both iterators in an ordered way until one is empty
3139 while True:
3146 while True:
3140 if val1 is None:
3147 if val1 is None:
3141 val1 = next(iter1)
3148 val1 = next(iter1)
3142 if val2 is None:
3149 if val2 is None:
3143 val2 = next(iter2)
3150 val2 = next(iter2)
3144 n = choice(val1, val2)
3151 n = choice(val1, val2)
3145 yield n
3152 yield n
3146 if val1 == n:
3153 if val1 == n:
3147 val1 = None
3154 val1 = None
3148 if val2 == n:
3155 if val2 == n:
3149 val2 = None
3156 val2 = None
3150 except StopIteration:
3157 except StopIteration:
3151 # Flush any remaining values and consume the other one
3158 # Flush any remaining values and consume the other one
3152 it = iter2
3159 it = iter2
3153 if val1 is not None:
3160 if val1 is not None:
3154 yield val1
3161 yield val1
3155 it = iter1
3162 it = iter1
3156 elif val2 is not None:
3163 elif val2 is not None:
3157 # might have been equality and both are empty
3164 # might have been equality and both are empty
3158 yield val2
3165 yield val2
3159 for val in it:
3166 for val in it:
3160 yield val
3167 yield val
3161
3168
3162 class addset(abstractsmartset):
3169 class addset(abstractsmartset):
3163 """Represent the addition of two sets
3170 """Represent the addition of two sets
3164
3171
3165 Wrapper structure for lazily adding two structures without losing much
3172 Wrapper structure for lazily adding two structures without losing much
3166 performance on the __contains__ method
3173 performance on the __contains__ method
3167
3174
3168 If the ascending attribute is set, that means the two structures are
3175 If the ascending attribute is set, that means the two structures are
3169 ordered in either an ascending or descending way. Therefore, we can add
3176 ordered in either an ascending or descending way. Therefore, we can add
3170 them maintaining the order by iterating over both at the same time
3177 them maintaining the order by iterating over both at the same time
3171
3178
3172 >>> xs = baseset([0, 3, 2])
3179 >>> xs = baseset([0, 3, 2])
3173 >>> ys = baseset([5, 2, 4])
3180 >>> ys = baseset([5, 2, 4])
3174
3181
3175 >>> rs = addset(xs, ys)
3182 >>> rs = addset(xs, ys)
3176 >>> bool(rs), 0 in rs, 1 in rs, 5 in rs, rs.first(), rs.last()
3183 >>> bool(rs), 0 in rs, 1 in rs, 5 in rs, rs.first(), rs.last()
3177 (True, True, False, True, 0, 4)
3184 (True, True, False, True, 0, 4)
3178 >>> rs = addset(xs, baseset([]))
3185 >>> rs = addset(xs, baseset([]))
3179 >>> bool(rs), 0 in rs, 1 in rs, rs.first(), rs.last()
3186 >>> bool(rs), 0 in rs, 1 in rs, rs.first(), rs.last()
3180 (True, True, False, 0, 2)
3187 (True, True, False, 0, 2)
3181 >>> rs = addset(baseset([]), baseset([]))
3188 >>> rs = addset(baseset([]), baseset([]))
3182 >>> bool(rs), 0 in rs, rs.first(), rs.last()
3189 >>> bool(rs), 0 in rs, rs.first(), rs.last()
3183 (False, False, None, None)
3190 (False, False, None, None)
3184
3191
3185 iterate unsorted:
3192 iterate unsorted:
3186 >>> rs = addset(xs, ys)
3193 >>> rs = addset(xs, ys)
3187 >>> # (use generator because pypy could call len())
3194 >>> # (use generator because pypy could call len())
3188 >>> list(x for x in rs) # without _genlist
3195 >>> list(x for x in rs) # without _genlist
3189 [0, 3, 2, 5, 4]
3196 [0, 3, 2, 5, 4]
3190 >>> assert not rs._genlist
3197 >>> assert not rs._genlist
3191 >>> len(rs)
3198 >>> len(rs)
3192 5
3199 5
3193 >>> [x for x in rs] # with _genlist
3200 >>> [x for x in rs] # with _genlist
3194 [0, 3, 2, 5, 4]
3201 [0, 3, 2, 5, 4]
3195 >>> assert rs._genlist
3202 >>> assert rs._genlist
3196
3203
3197 iterate ascending:
3204 iterate ascending:
3198 >>> rs = addset(xs, ys, ascending=True)
3205 >>> rs = addset(xs, ys, ascending=True)
3199 >>> # (use generator because pypy could call len())
3206 >>> # (use generator because pypy could call len())
3200 >>> list(x for x in rs), list(x for x in rs.fastasc()) # without _asclist
3207 >>> list(x for x in rs), list(x for x in rs.fastasc()) # without _asclist
3201 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5])
3208 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5])
3202 >>> assert not rs._asclist
3209 >>> assert not rs._asclist
3203 >>> len(rs)
3210 >>> len(rs)
3204 5
3211 5
3205 >>> [x for x in rs], [x for x in rs.fastasc()]
3212 >>> [x for x in rs], [x for x in rs.fastasc()]
3206 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5])
3213 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5])
3207 >>> assert rs._asclist
3214 >>> assert rs._asclist
3208
3215
3209 iterate descending:
3216 iterate descending:
3210 >>> rs = addset(xs, ys, ascending=False)
3217 >>> rs = addset(xs, ys, ascending=False)
3211 >>> # (use generator because pypy could call len())
3218 >>> # (use generator because pypy could call len())
3212 >>> list(x for x in rs), list(x for x in rs.fastdesc()) # without _asclist
3219 >>> list(x for x in rs), list(x for x in rs.fastdesc()) # without _asclist
3213 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0])
3220 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0])
3214 >>> assert not rs._asclist
3221 >>> assert not rs._asclist
3215 >>> len(rs)
3222 >>> len(rs)
3216 5
3223 5
3217 >>> [x for x in rs], [x for x in rs.fastdesc()]
3224 >>> [x for x in rs], [x for x in rs.fastdesc()]
3218 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0])
3225 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0])
3219 >>> assert rs._asclist
3226 >>> assert rs._asclist
3220
3227
3221 iterate ascending without fastasc:
3228 iterate ascending without fastasc:
3222 >>> rs = addset(xs, generatorset(ys), ascending=True)
3229 >>> rs = addset(xs, generatorset(ys), ascending=True)
3223 >>> assert rs.fastasc is None
3230 >>> assert rs.fastasc is None
3224 >>> [x for x in rs]
3231 >>> [x for x in rs]
3225 [0, 2, 3, 4, 5]
3232 [0, 2, 3, 4, 5]
3226
3233
3227 iterate descending without fastdesc:
3234 iterate descending without fastdesc:
3228 >>> rs = addset(generatorset(xs), ys, ascending=False)
3235 >>> rs = addset(generatorset(xs), ys, ascending=False)
3229 >>> assert rs.fastdesc is None
3236 >>> assert rs.fastdesc is None
3230 >>> [x for x in rs]
3237 >>> [x for x in rs]
3231 [5, 4, 3, 2, 0]
3238 [5, 4, 3, 2, 0]
3232 """
3239 """
3233 def __init__(self, revs1, revs2, ascending=None):
3240 def __init__(self, revs1, revs2, ascending=None):
3234 self._r1 = revs1
3241 self._r1 = revs1
3235 self._r2 = revs2
3242 self._r2 = revs2
3236 self._iter = None
3243 self._iter = None
3237 self._ascending = ascending
3244 self._ascending = ascending
3238 self._genlist = None
3245 self._genlist = None
3239 self._asclist = None
3246 self._asclist = None
3240
3247
3241 def __len__(self):
3248 def __len__(self):
3242 return len(self._list)
3249 return len(self._list)
3243
3250
3244 def __nonzero__(self):
3251 def __nonzero__(self):
3245 return bool(self._r1) or bool(self._r2)
3252 return bool(self._r1) or bool(self._r2)
3246
3253
3247 @util.propertycache
3254 @util.propertycache
3248 def _list(self):
3255 def _list(self):
3249 if not self._genlist:
3256 if not self._genlist:
3250 self._genlist = baseset(iter(self))
3257 self._genlist = baseset(iter(self))
3251 return self._genlist
3258 return self._genlist
3252
3259
3253 def __iter__(self):
3260 def __iter__(self):
3254 """Iterate over both collections without repeating elements
3261 """Iterate over both collections without repeating elements
3255
3262
3256 If the ascending attribute is not set, iterate over the first one and
3263 If the ascending attribute is not set, iterate over the first one and
3257 then over the second one checking for membership on the first one so we
3264 then over the second one checking for membership on the first one so we
3258 dont yield any duplicates.
3265 dont yield any duplicates.
3259
3266
3260 If the ascending attribute is set, iterate over both collections at the
3267 If the ascending attribute is set, iterate over both collections at the
3261 same time, yielding only one value at a time in the given order.
3268 same time, yielding only one value at a time in the given order.
3262 """
3269 """
3263 if self._ascending is None:
3270 if self._ascending is None:
3264 if self._genlist:
3271 if self._genlist:
3265 return iter(self._genlist)
3272 return iter(self._genlist)
3266 def arbitraryordergen():
3273 def arbitraryordergen():
3267 for r in self._r1:
3274 for r in self._r1:
3268 yield r
3275 yield r
3269 inr1 = self._r1.__contains__
3276 inr1 = self._r1.__contains__
3270 for r in self._r2:
3277 for r in self._r2:
3271 if not inr1(r):
3278 if not inr1(r):
3272 yield r
3279 yield r
3273 return arbitraryordergen()
3280 return arbitraryordergen()
3274 # try to use our own fast iterator if it exists
3281 # try to use our own fast iterator if it exists
3275 self._trysetasclist()
3282 self._trysetasclist()
3276 if self._ascending:
3283 if self._ascending:
3277 attr = 'fastasc'
3284 attr = 'fastasc'
3278 else:
3285 else:
3279 attr = 'fastdesc'
3286 attr = 'fastdesc'
3280 it = getattr(self, attr)
3287 it = getattr(self, attr)
3281 if it is not None:
3288 if it is not None:
3282 return it()
3289 return it()
3283 # maybe half of the component supports fast
3290 # maybe half of the component supports fast
3284 # get iterator for _r1
3291 # get iterator for _r1
3285 iter1 = getattr(self._r1, attr)
3292 iter1 = getattr(self._r1, attr)
3286 if iter1 is None:
3293 if iter1 is None:
3287 # let's avoid side effect (not sure it matters)
3294 # let's avoid side effect (not sure it matters)
3288 iter1 = iter(sorted(self._r1, reverse=not self._ascending))
3295 iter1 = iter(sorted(self._r1, reverse=not self._ascending))
3289 else:
3296 else:
3290 iter1 = iter1()
3297 iter1 = iter1()
3291 # get iterator for _r2
3298 # get iterator for _r2
3292 iter2 = getattr(self._r2, attr)
3299 iter2 = getattr(self._r2, attr)
3293 if iter2 is None:
3300 if iter2 is None:
3294 # let's avoid side effect (not sure it matters)
3301 # let's avoid side effect (not sure it matters)
3295 iter2 = iter(sorted(self._r2, reverse=not self._ascending))
3302 iter2 = iter(sorted(self._r2, reverse=not self._ascending))
3296 else:
3303 else:
3297 iter2 = iter2()
3304 iter2 = iter2()
3298 return _iterordered(self._ascending, iter1, iter2)
3305 return _iterordered(self._ascending, iter1, iter2)
3299
3306
3300 def _trysetasclist(self):
3307 def _trysetasclist(self):
3301 """populate the _asclist attribute if possible and necessary"""
3308 """populate the _asclist attribute if possible and necessary"""
3302 if self._genlist is not None and self._asclist is None:
3309 if self._genlist is not None and self._asclist is None:
3303 self._asclist = sorted(self._genlist)
3310 self._asclist = sorted(self._genlist)
3304
3311
3305 @property
3312 @property
3306 def fastasc(self):
3313 def fastasc(self):
3307 self._trysetasclist()
3314 self._trysetasclist()
3308 if self._asclist is not None:
3315 if self._asclist is not None:
3309 return self._asclist.__iter__
3316 return self._asclist.__iter__
3310 iter1 = self._r1.fastasc
3317 iter1 = self._r1.fastasc
3311 iter2 = self._r2.fastasc
3318 iter2 = self._r2.fastasc
3312 if None in (iter1, iter2):
3319 if None in (iter1, iter2):
3313 return None
3320 return None
3314 return lambda: _iterordered(True, iter1(), iter2())
3321 return lambda: _iterordered(True, iter1(), iter2())
3315
3322
3316 @property
3323 @property
3317 def fastdesc(self):
3324 def fastdesc(self):
3318 self._trysetasclist()
3325 self._trysetasclist()
3319 if self._asclist is not None:
3326 if self._asclist is not None:
3320 return self._asclist.__reversed__
3327 return self._asclist.__reversed__
3321 iter1 = self._r1.fastdesc
3328 iter1 = self._r1.fastdesc
3322 iter2 = self._r2.fastdesc
3329 iter2 = self._r2.fastdesc
3323 if None in (iter1, iter2):
3330 if None in (iter1, iter2):
3324 return None
3331 return None
3325 return lambda: _iterordered(False, iter1(), iter2())
3332 return lambda: _iterordered(False, iter1(), iter2())
3326
3333
3327 def __contains__(self, x):
3334 def __contains__(self, x):
3328 return x in self._r1 or x in self._r2
3335 return x in self._r1 or x in self._r2
3329
3336
3330 def sort(self, reverse=False):
3337 def sort(self, reverse=False):
3331 """Sort the added set
3338 """Sort the added set
3332
3339
3333 For this we use the cached list with all the generated values and if we
3340 For this we use the cached list with all the generated values and if we
3334 know they are ascending or descending we can sort them in a smart way.
3341 know they are ascending or descending we can sort them in a smart way.
3335 """
3342 """
3336 self._ascending = not reverse
3343 self._ascending = not reverse
3337
3344
3338 def isascending(self):
3345 def isascending(self):
3339 return self._ascending is not None and self._ascending
3346 return self._ascending is not None and self._ascending
3340
3347
3341 def isdescending(self):
3348 def isdescending(self):
3342 return self._ascending is not None and not self._ascending
3349 return self._ascending is not None and not self._ascending
3343
3350
3344 def istopo(self):
3351 def istopo(self):
3345 # not worth the trouble asserting if the two sets combined are still
3352 # not worth the trouble asserting if the two sets combined are still
3346 # in topographical order. Use the sort() predicate to explicitly sort
3353 # in topographical order. Use the sort() predicate to explicitly sort
3347 # again instead.
3354 # again instead.
3348 return False
3355 return False
3349
3356
3350 def reverse(self):
3357 def reverse(self):
3351 if self._ascending is None:
3358 if self._ascending is None:
3352 self._list.reverse()
3359 self._list.reverse()
3353 else:
3360 else:
3354 self._ascending = not self._ascending
3361 self._ascending = not self._ascending
3355
3362
3356 def first(self):
3363 def first(self):
3357 for x in self:
3364 for x in self:
3358 return x
3365 return x
3359 return None
3366 return None
3360
3367
3361 def last(self):
3368 def last(self):
3362 self.reverse()
3369 self.reverse()
3363 val = self.first()
3370 val = self.first()
3364 self.reverse()
3371 self.reverse()
3365 return val
3372 return val
3366
3373
3367 def __repr__(self):
3374 def __repr__(self):
3368 d = {None: '', False: '-', True: '+'}[self._ascending]
3375 d = {None: '', False: '-', True: '+'}[self._ascending]
3369 return '<%s%s %r, %r>' % (type(self).__name__, d, self._r1, self._r2)
3376 return '<%s%s %r, %r>' % (type(self).__name__, d, self._r1, self._r2)
3370
3377
3371 class generatorset(abstractsmartset):
3378 class generatorset(abstractsmartset):
3372 """Wrap a generator for lazy iteration
3379 """Wrap a generator for lazy iteration
3373
3380
3374 Wrapper structure for generators that provides lazy membership and can
3381 Wrapper structure for generators that provides lazy membership and can
3375 be iterated more than once.
3382 be iterated more than once.
3376 When asked for membership it generates values until either it finds the
3383 When asked for membership it generates values until either it finds the
3377 requested one or has gone through all the elements in the generator
3384 requested one or has gone through all the elements in the generator
3378 """
3385 """
3379 def __init__(self, gen, iterasc=None):
3386 def __init__(self, gen, iterasc=None):
3380 """
3387 """
3381 gen: a generator producing the values for the generatorset.
3388 gen: a generator producing the values for the generatorset.
3382 """
3389 """
3383 self._gen = gen
3390 self._gen = gen
3384 self._asclist = None
3391 self._asclist = None
3385 self._cache = {}
3392 self._cache = {}
3386 self._genlist = []
3393 self._genlist = []
3387 self._finished = False
3394 self._finished = False
3388 self._ascending = True
3395 self._ascending = True
3389 if iterasc is not None:
3396 if iterasc is not None:
3390 if iterasc:
3397 if iterasc:
3391 self.fastasc = self._iterator
3398 self.fastasc = self._iterator
3392 self.__contains__ = self._asccontains
3399 self.__contains__ = self._asccontains
3393 else:
3400 else:
3394 self.fastdesc = self._iterator
3401 self.fastdesc = self._iterator
3395 self.__contains__ = self._desccontains
3402 self.__contains__ = self._desccontains
3396
3403
3397 def __nonzero__(self):
3404 def __nonzero__(self):
3398 # Do not use 'for r in self' because it will enforce the iteration
3405 # Do not use 'for r in self' because it will enforce the iteration
3399 # order (default ascending), possibly unrolling a whole descending
3406 # order (default ascending), possibly unrolling a whole descending
3400 # iterator.
3407 # iterator.
3401 if self._genlist:
3408 if self._genlist:
3402 return True
3409 return True
3403 for r in self._consumegen():
3410 for r in self._consumegen():
3404 return True
3411 return True
3405 return False
3412 return False
3406
3413
3407 def __contains__(self, x):
3414 def __contains__(self, x):
3408 if x in self._cache:
3415 if x in self._cache:
3409 return self._cache[x]
3416 return self._cache[x]
3410
3417
3411 # Use new values only, as existing values would be cached.
3418 # Use new values only, as existing values would be cached.
3412 for l in self._consumegen():
3419 for l in self._consumegen():
3413 if l == x:
3420 if l == x:
3414 return True
3421 return True
3415
3422
3416 self._cache[x] = False
3423 self._cache[x] = False
3417 return False
3424 return False
3418
3425
3419 def _asccontains(self, x):
3426 def _asccontains(self, x):
3420 """version of contains optimised for ascending generator"""
3427 """version of contains optimised for ascending generator"""
3421 if x in self._cache:
3428 if x in self._cache:
3422 return self._cache[x]
3429 return self._cache[x]
3423
3430
3424 # Use new values only, as existing values would be cached.
3431 # Use new values only, as existing values would be cached.
3425 for l in self._consumegen():
3432 for l in self._consumegen():
3426 if l == x:
3433 if l == x:
3427 return True
3434 return True
3428 if l > x:
3435 if l > x:
3429 break
3436 break
3430
3437
3431 self._cache[x] = False
3438 self._cache[x] = False
3432 return False
3439 return False
3433
3440
3434 def _desccontains(self, x):
3441 def _desccontains(self, x):
3435 """version of contains optimised for descending generator"""
3442 """version of contains optimised for descending generator"""
3436 if x in self._cache:
3443 if x in self._cache:
3437 return self._cache[x]
3444 return self._cache[x]
3438
3445
3439 # Use new values only, as existing values would be cached.
3446 # Use new values only, as existing values would be cached.
3440 for l in self._consumegen():
3447 for l in self._consumegen():
3441 if l == x:
3448 if l == x:
3442 return True
3449 return True
3443 if l < x:
3450 if l < x:
3444 break
3451 break
3445
3452
3446 self._cache[x] = False
3453 self._cache[x] = False
3447 return False
3454 return False
3448
3455
3449 def __iter__(self):
3456 def __iter__(self):
3450 if self._ascending:
3457 if self._ascending:
3451 it = self.fastasc
3458 it = self.fastasc
3452 else:
3459 else:
3453 it = self.fastdesc
3460 it = self.fastdesc
3454 if it is not None:
3461 if it is not None:
3455 return it()
3462 return it()
3456 # we need to consume the iterator
3463 # we need to consume the iterator
3457 for x in self._consumegen():
3464 for x in self._consumegen():
3458 pass
3465 pass
3459 # recall the same code
3466 # recall the same code
3460 return iter(self)
3467 return iter(self)
3461
3468
3462 def _iterator(self):
3469 def _iterator(self):
3463 if self._finished:
3470 if self._finished:
3464 return iter(self._genlist)
3471 return iter(self._genlist)
3465
3472
3466 # We have to use this complex iteration strategy to allow multiple
3473 # We have to use this complex iteration strategy to allow multiple
3467 # iterations at the same time. We need to be able to catch revision
3474 # iterations at the same time. We need to be able to catch revision
3468 # removed from _consumegen and added to genlist in another instance.
3475 # removed from _consumegen and added to genlist in another instance.
3469 #
3476 #
3470 # Getting rid of it would provide an about 15% speed up on this
3477 # Getting rid of it would provide an about 15% speed up on this
3471 # iteration.
3478 # iteration.
3472 genlist = self._genlist
3479 genlist = self._genlist
3473 nextrev = self._consumegen().next
3480 nextrev = self._consumegen().next
3474 _len = len # cache global lookup
3481 _len = len # cache global lookup
3475 def gen():
3482 def gen():
3476 i = 0
3483 i = 0
3477 while True:
3484 while True:
3478 if i < _len(genlist):
3485 if i < _len(genlist):
3479 yield genlist[i]
3486 yield genlist[i]
3480 else:
3487 else:
3481 yield nextrev()
3488 yield nextrev()
3482 i += 1
3489 i += 1
3483 return gen()
3490 return gen()
3484
3491
3485 def _consumegen(self):
3492 def _consumegen(self):
3486 cache = self._cache
3493 cache = self._cache
3487 genlist = self._genlist.append
3494 genlist = self._genlist.append
3488 for item in self._gen:
3495 for item in self._gen:
3489 cache[item] = True
3496 cache[item] = True
3490 genlist(item)
3497 genlist(item)
3491 yield item
3498 yield item
3492 if not self._finished:
3499 if not self._finished:
3493 self._finished = True
3500 self._finished = True
3494 asc = self._genlist[:]
3501 asc = self._genlist[:]
3495 asc.sort()
3502 asc.sort()
3496 self._asclist = asc
3503 self._asclist = asc
3497 self.fastasc = asc.__iter__
3504 self.fastasc = asc.__iter__
3498 self.fastdesc = asc.__reversed__
3505 self.fastdesc = asc.__reversed__
3499
3506
3500 def __len__(self):
3507 def __len__(self):
3501 for x in self._consumegen():
3508 for x in self._consumegen():
3502 pass
3509 pass
3503 return len(self._genlist)
3510 return len(self._genlist)
3504
3511
3505 def sort(self, reverse=False):
3512 def sort(self, reverse=False):
3506 self._ascending = not reverse
3513 self._ascending = not reverse
3507
3514
3508 def reverse(self):
3515 def reverse(self):
3509 self._ascending = not self._ascending
3516 self._ascending = not self._ascending
3510
3517
3511 def isascending(self):
3518 def isascending(self):
3512 return self._ascending
3519 return self._ascending
3513
3520
3514 def isdescending(self):
3521 def isdescending(self):
3515 return not self._ascending
3522 return not self._ascending
3516
3523
3517 def istopo(self):
3524 def istopo(self):
3518 # not worth the trouble asserting if the two sets combined are still
3525 # not worth the trouble asserting if the two sets combined are still
3519 # in topographical order. Use the sort() predicate to explicitly sort
3526 # in topographical order. Use the sort() predicate to explicitly sort
3520 # again instead.
3527 # again instead.
3521 return False
3528 return False
3522
3529
3523 def first(self):
3530 def first(self):
3524 if self._ascending:
3531 if self._ascending:
3525 it = self.fastasc
3532 it = self.fastasc
3526 else:
3533 else:
3527 it = self.fastdesc
3534 it = self.fastdesc
3528 if it is None:
3535 if it is None:
3529 # we need to consume all and try again
3536 # we need to consume all and try again
3530 for x in self._consumegen():
3537 for x in self._consumegen():
3531 pass
3538 pass
3532 return self.first()
3539 return self.first()
3533 return next(it(), None)
3540 return next(it(), None)
3534
3541
3535 def last(self):
3542 def last(self):
3536 if self._ascending:
3543 if self._ascending:
3537 it = self.fastdesc
3544 it = self.fastdesc
3538 else:
3545 else:
3539 it = self.fastasc
3546 it = self.fastasc
3540 if it is None:
3547 if it is None:
3541 # we need to consume all and try again
3548 # we need to consume all and try again
3542 for x in self._consumegen():
3549 for x in self._consumegen():
3543 pass
3550 pass
3544 return self.first()
3551 return self.first()
3545 return next(it(), None)
3552 return next(it(), None)
3546
3553
3547 def __repr__(self):
3554 def __repr__(self):
3548 d = {False: '-', True: '+'}[self._ascending]
3555 d = {False: '-', True: '+'}[self._ascending]
3549 return '<%s%s>' % (type(self).__name__, d)
3556 return '<%s%s>' % (type(self).__name__, d)
3550
3557
3551 class spanset(abstractsmartset):
3558 class spanset(abstractsmartset):
3552 """Duck type for baseset class which represents a range of revisions and
3559 """Duck type for baseset class which represents a range of revisions and
3553 can work lazily and without having all the range in memory
3560 can work lazily and without having all the range in memory
3554
3561
3555 Note that spanset(x, y) behave almost like xrange(x, y) except for two
3562 Note that spanset(x, y) behave almost like xrange(x, y) except for two
3556 notable points:
3563 notable points:
3557 - when x < y it will be automatically descending,
3564 - when x < y it will be automatically descending,
3558 - revision filtered with this repoview will be skipped.
3565 - revision filtered with this repoview will be skipped.
3559
3566
3560 """
3567 """
3561 def __init__(self, repo, start=0, end=None):
3568 def __init__(self, repo, start=0, end=None):
3562 """
3569 """
3563 start: first revision included the set
3570 start: first revision included the set
3564 (default to 0)
3571 (default to 0)
3565 end: first revision excluded (last+1)
3572 end: first revision excluded (last+1)
3566 (default to len(repo)
3573 (default to len(repo)
3567
3574
3568 Spanset will be descending if `end` < `start`.
3575 Spanset will be descending if `end` < `start`.
3569 """
3576 """
3570 if end is None:
3577 if end is None:
3571 end = len(repo)
3578 end = len(repo)
3572 self._ascending = start <= end
3579 self._ascending = start <= end
3573 if not self._ascending:
3580 if not self._ascending:
3574 start, end = end + 1, start +1
3581 start, end = end + 1, start +1
3575 self._start = start
3582 self._start = start
3576 self._end = end
3583 self._end = end
3577 self._hiddenrevs = repo.changelog.filteredrevs
3584 self._hiddenrevs = repo.changelog.filteredrevs
3578
3585
3579 def sort(self, reverse=False):
3586 def sort(self, reverse=False):
3580 self._ascending = not reverse
3587 self._ascending = not reverse
3581
3588
3582 def reverse(self):
3589 def reverse(self):
3583 self._ascending = not self._ascending
3590 self._ascending = not self._ascending
3584
3591
3585 def istopo(self):
3592 def istopo(self):
3586 # not worth the trouble asserting if the two sets combined are still
3593 # not worth the trouble asserting if the two sets combined are still
3587 # in topographical order. Use the sort() predicate to explicitly sort
3594 # in topographical order. Use the sort() predicate to explicitly sort
3588 # again instead.
3595 # again instead.
3589 return False
3596 return False
3590
3597
3591 def _iterfilter(self, iterrange):
3598 def _iterfilter(self, iterrange):
3592 s = self._hiddenrevs
3599 s = self._hiddenrevs
3593 for r in iterrange:
3600 for r in iterrange:
3594 if r not in s:
3601 if r not in s:
3595 yield r
3602 yield r
3596
3603
3597 def __iter__(self):
3604 def __iter__(self):
3598 if self._ascending:
3605 if self._ascending:
3599 return self.fastasc()
3606 return self.fastasc()
3600 else:
3607 else:
3601 return self.fastdesc()
3608 return self.fastdesc()
3602
3609
3603 def fastasc(self):
3610 def fastasc(self):
3604 iterrange = xrange(self._start, self._end)
3611 iterrange = xrange(self._start, self._end)
3605 if self._hiddenrevs:
3612 if self._hiddenrevs:
3606 return self._iterfilter(iterrange)
3613 return self._iterfilter(iterrange)
3607 return iter(iterrange)
3614 return iter(iterrange)
3608
3615
3609 def fastdesc(self):
3616 def fastdesc(self):
3610 iterrange = xrange(self._end - 1, self._start - 1, -1)
3617 iterrange = xrange(self._end - 1, self._start - 1, -1)
3611 if self._hiddenrevs:
3618 if self._hiddenrevs:
3612 return self._iterfilter(iterrange)
3619 return self._iterfilter(iterrange)
3613 return iter(iterrange)
3620 return iter(iterrange)
3614
3621
3615 def __contains__(self, rev):
3622 def __contains__(self, rev):
3616 hidden = self._hiddenrevs
3623 hidden = self._hiddenrevs
3617 return ((self._start <= rev < self._end)
3624 return ((self._start <= rev < self._end)
3618 and not (hidden and rev in hidden))
3625 and not (hidden and rev in hidden))
3619
3626
3620 def __nonzero__(self):
3627 def __nonzero__(self):
3621 for r in self:
3628 for r in self:
3622 return True
3629 return True
3623 return False
3630 return False
3624
3631
3625 def __len__(self):
3632 def __len__(self):
3626 if not self._hiddenrevs:
3633 if not self._hiddenrevs:
3627 return abs(self._end - self._start)
3634 return abs(self._end - self._start)
3628 else:
3635 else:
3629 count = 0
3636 count = 0
3630 start = self._start
3637 start = self._start
3631 end = self._end
3638 end = self._end
3632 for rev in self._hiddenrevs:
3639 for rev in self._hiddenrevs:
3633 if (end < rev <= start) or (start <= rev < end):
3640 if (end < rev <= start) or (start <= rev < end):
3634 count += 1
3641 count += 1
3635 return abs(self._end - self._start) - count
3642 return abs(self._end - self._start) - count
3636
3643
3637 def isascending(self):
3644 def isascending(self):
3638 return self._ascending
3645 return self._ascending
3639
3646
3640 def isdescending(self):
3647 def isdescending(self):
3641 return not self._ascending
3648 return not self._ascending
3642
3649
3643 def first(self):
3650 def first(self):
3644 if self._ascending:
3651 if self._ascending:
3645 it = self.fastasc
3652 it = self.fastasc
3646 else:
3653 else:
3647 it = self.fastdesc
3654 it = self.fastdesc
3648 for x in it():
3655 for x in it():
3649 return x
3656 return x
3650 return None
3657 return None
3651
3658
3652 def last(self):
3659 def last(self):
3653 if self._ascending:
3660 if self._ascending:
3654 it = self.fastdesc
3661 it = self.fastdesc
3655 else:
3662 else:
3656 it = self.fastasc
3663 it = self.fastasc
3657 for x in it():
3664 for x in it():
3658 return x
3665 return x
3659 return None
3666 return None
3660
3667
3661 def __repr__(self):
3668 def __repr__(self):
3662 d = {False: '-', True: '+'}[self._ascending]
3669 d = {False: '-', True: '+'}[self._ascending]
3663 return '<%s%s %d:%d>' % (type(self).__name__, d,
3670 return '<%s%s %d:%d>' % (type(self).__name__, d,
3664 self._start, self._end - 1)
3671 self._start, self._end - 1)
3665
3672
3666 class fullreposet(spanset):
3673 class fullreposet(spanset):
3667 """a set containing all revisions in the repo
3674 """a set containing all revisions in the repo
3668
3675
3669 This class exists to host special optimization and magic to handle virtual
3676 This class exists to host special optimization and magic to handle virtual
3670 revisions such as "null".
3677 revisions such as "null".
3671 """
3678 """
3672
3679
3673 def __init__(self, repo):
3680 def __init__(self, repo):
3674 super(fullreposet, self).__init__(repo)
3681 super(fullreposet, self).__init__(repo)
3675
3682
3676 def __and__(self, other):
3683 def __and__(self, other):
3677 """As self contains the whole repo, all of the other set should also be
3684 """As self contains the whole repo, all of the other set should also be
3678 in self. Therefore `self & other = other`.
3685 in self. Therefore `self & other = other`.
3679
3686
3680 This boldly assumes the other contains valid revs only.
3687 This boldly assumes the other contains valid revs only.
3681 """
3688 """
3682 # other not a smartset, make is so
3689 # other not a smartset, make is so
3683 if not util.safehasattr(other, 'isascending'):
3690 if not util.safehasattr(other, 'isascending'):
3684 # filter out hidden revision
3691 # filter out hidden revision
3685 # (this boldly assumes all smartset are pure)
3692 # (this boldly assumes all smartset are pure)
3686 #
3693 #
3687 # `other` was used with "&", let's assume this is a set like
3694 # `other` was used with "&", let's assume this is a set like
3688 # object.
3695 # object.
3689 other = baseset(other - self._hiddenrevs)
3696 other = baseset(other - self._hiddenrevs)
3690
3697
3691 # XXX As fullreposet is also used as bootstrap, this is wrong.
3698 # XXX As fullreposet is also used as bootstrap, this is wrong.
3692 #
3699 #
3693 # With a giveme312() revset returning [3,1,2], this makes
3700 # With a giveme312() revset returning [3,1,2], this makes
3694 # 'hg log -r "giveme312()"' -> 1, 2, 3 (wrong)
3701 # 'hg log -r "giveme312()"' -> 1, 2, 3 (wrong)
3695 # We cannot just drop it because other usage still need to sort it:
3702 # We cannot just drop it because other usage still need to sort it:
3696 # 'hg log -r "all() and giveme312()"' -> 1, 2, 3 (right)
3703 # 'hg log -r "all() and giveme312()"' -> 1, 2, 3 (right)
3697 #
3704 #
3698 # There is also some faulty revset implementations that rely on it
3705 # There is also some faulty revset implementations that rely on it
3699 # (eg: children as of its state in e8075329c5fb)
3706 # (eg: children as of its state in e8075329c5fb)
3700 #
3707 #
3701 # When we fix the two points above we can move this into the if clause
3708 # When we fix the two points above we can move this into the if clause
3702 other.sort(reverse=self.isdescending())
3709 other.sort(reverse=self.isdescending())
3703 return other
3710 return other
3704
3711
3705 def prettyformatset(revs):
3712 def prettyformatset(revs):
3706 lines = []
3713 lines = []
3707 rs = repr(revs)
3714 rs = repr(revs)
3708 p = 0
3715 p = 0
3709 while p < len(rs):
3716 while p < len(rs):
3710 q = rs.find('<', p + 1)
3717 q = rs.find('<', p + 1)
3711 if q < 0:
3718 if q < 0:
3712 q = len(rs)
3719 q = len(rs)
3713 l = rs.count('<', 0, p) - rs.count('>', 0, p)
3720 l = rs.count('<', 0, p) - rs.count('>', 0, p)
3714 assert l >= 0
3721 assert l >= 0
3715 lines.append((l, rs[p:q].rstrip()))
3722 lines.append((l, rs[p:q].rstrip()))
3716 p = q
3723 p = q
3717 return '\n'.join(' ' * l + s for l, s in lines)
3724 return '\n'.join(' ' * l + s for l, s in lines)
3718
3725
3719 def loadpredicate(ui, extname, registrarobj):
3726 def loadpredicate(ui, extname, registrarobj):
3720 """Load revset predicates from specified registrarobj
3727 """Load revset predicates from specified registrarobj
3721 """
3728 """
3722 for name, func in registrarobj._table.iteritems():
3729 for name, func in registrarobj._table.iteritems():
3723 symbols[name] = func
3730 symbols[name] = func
3724 if func._safe:
3731 if func._safe:
3725 safesymbols.add(name)
3732 safesymbols.add(name)
3726
3733
3727 # load built-in predicates explicitly to setup safesymbols
3734 # load built-in predicates explicitly to setup safesymbols
3728 loadpredicate(None, None, predicate)
3735 loadpredicate(None, None, predicate)
3729
3736
3730 # tell hggettext to extract docstrings from these functions:
3737 # tell hggettext to extract docstrings from these functions:
3731 i18nfunctions = symbols.values()
3738 i18nfunctions = symbols.values()
@@ -1,3419 +1,3426 b''
1 @ (34) head
1 @ (34) head
2 |
2 |
3 | o (33) head
3 | o (33) head
4 | |
4 | |
5 o | (32) expand
5 o | (32) expand
6 |\ \
6 |\ \
7 | o \ (31) expand
7 | o \ (31) expand
8 | |\ \
8 | |\ \
9 | | o \ (30) expand
9 | | o \ (30) expand
10 | | |\ \
10 | | |\ \
11 | | | o | (29) regular commit
11 | | | o | (29) regular commit
12 | | | | |
12 | | | | |
13 | | o | | (28) merge zero known
13 | | o | | (28) merge zero known
14 | | |\ \ \
14 | | |\ \ \
15 o | | | | | (27) collapse
15 o | | | | | (27) collapse
16 |/ / / / /
16 |/ / / / /
17 | | o---+ (26) merge one known; far right
17 | | o---+ (26) merge one known; far right
18 | | | | |
18 | | | | |
19 +---o | | (25) merge one known; far left
19 +---o | | (25) merge one known; far left
20 | | | | |
20 | | | | |
21 | | o | | (24) merge one known; immediate right
21 | | o | | (24) merge one known; immediate right
22 | | |\| |
22 | | |\| |
23 | | o | | (23) merge one known; immediate left
23 | | o | | (23) merge one known; immediate left
24 | |/| | |
24 | |/| | |
25 +---o---+ (22) merge two known; one far left, one far right
25 +---o---+ (22) merge two known; one far left, one far right
26 | | / /
26 | | / /
27 o | | | (21) expand
27 o | | | (21) expand
28 |\ \ \ \
28 |\ \ \ \
29 | o---+-+ (20) merge two known; two far right
29 | o---+-+ (20) merge two known; two far right
30 | / / /
30 | / / /
31 o | | | (19) expand
31 o | | | (19) expand
32 |\ \ \ \
32 |\ \ \ \
33 +---+---o (18) merge two known; two far left
33 +---+---o (18) merge two known; two far left
34 | | | |
34 | | | |
35 | o | | (17) expand
35 | o | | (17) expand
36 | |\ \ \
36 | |\ \ \
37 | | o---+ (16) merge two known; one immediate right, one near right
37 | | o---+ (16) merge two known; one immediate right, one near right
38 | | |/ /
38 | | |/ /
39 o | | | (15) expand
39 o | | | (15) expand
40 |\ \ \ \
40 |\ \ \ \
41 | o-----+ (14) merge two known; one immediate right, one far right
41 | o-----+ (14) merge two known; one immediate right, one far right
42 | |/ / /
42 | |/ / /
43 o | | | (13) expand
43 o | | | (13) expand
44 |\ \ \ \
44 |\ \ \ \
45 +---o | | (12) merge two known; one immediate right, one far left
45 +---o | | (12) merge two known; one immediate right, one far left
46 | | |/ /
46 | | |/ /
47 | o | | (11) expand
47 | o | | (11) expand
48 | |\ \ \
48 | |\ \ \
49 | | o---+ (10) merge two known; one immediate left, one near right
49 | | o---+ (10) merge two known; one immediate left, one near right
50 | |/ / /
50 | |/ / /
51 o | | | (9) expand
51 o | | | (9) expand
52 |\ \ \ \
52 |\ \ \ \
53 | o-----+ (8) merge two known; one immediate left, one far right
53 | o-----+ (8) merge two known; one immediate left, one far right
54 |/ / / /
54 |/ / / /
55 o | | | (7) expand
55 o | | | (7) expand
56 |\ \ \ \
56 |\ \ \ \
57 +---o | | (6) merge two known; one immediate left, one far left
57 +---o | | (6) merge two known; one immediate left, one far left
58 | |/ / /
58 | |/ / /
59 | o | | (5) expand
59 | o | | (5) expand
60 | |\ \ \
60 | |\ \ \
61 | | o | | (4) merge two known; one immediate left, one immediate right
61 | | o | | (4) merge two known; one immediate left, one immediate right
62 | |/|/ /
62 | |/|/ /
63 | o / / (3) collapse
63 | o / / (3) collapse
64 |/ / /
64 |/ / /
65 o / / (2) collapse
65 o / / (2) collapse
66 |/ /
66 |/ /
67 o / (1) collapse
67 o / (1) collapse
68 |/
68 |/
69 o (0) root
69 o (0) root
70
70
71
71
72 $ commit()
72 $ commit()
73 > {
73 > {
74 > rev=$1
74 > rev=$1
75 > msg=$2
75 > msg=$2
76 > shift 2
76 > shift 2
77 > if [ "$#" -gt 0 ]; then
77 > if [ "$#" -gt 0 ]; then
78 > hg debugsetparents "$@"
78 > hg debugsetparents "$@"
79 > fi
79 > fi
80 > echo $rev > a
80 > echo $rev > a
81 > hg commit -Aqd "$rev 0" -m "($rev) $msg"
81 > hg commit -Aqd "$rev 0" -m "($rev) $msg"
82 > }
82 > }
83
83
84 $ cat > printrevset.py <<EOF
84 $ cat > printrevset.py <<EOF
85 > from mercurial import extensions, revset, commands, cmdutil
85 > from mercurial import extensions, revset, commands, cmdutil
86 >
86 >
87 > def uisetup(ui):
87 > def uisetup(ui):
88 > def printrevset(orig, ui, repo, *pats, **opts):
88 > def printrevset(orig, ui, repo, *pats, **opts):
89 > if opts.get('print_revset'):
89 > if opts.get('print_revset'):
90 > expr = cmdutil.getgraphlogrevs(repo, pats, opts)[1]
90 > expr = cmdutil.getgraphlogrevs(repo, pats, opts)[1]
91 > if expr:
91 > if expr:
92 > tree = revset.parse(expr)
92 > tree = revset.parse(expr)
93 > else:
93 > else:
94 > tree = []
94 > tree = []
95 > ui.write('%r\n' % (opts.get('rev', []),))
95 > ui.write('%r\n' % (opts.get('rev', []),))
96 > ui.write(revset.prettyformat(tree) + '\n')
96 > ui.write(revset.prettyformat(tree) + '\n')
97 > return 0
97 > return 0
98 > return orig(ui, repo, *pats, **opts)
98 > return orig(ui, repo, *pats, **opts)
99 > entry = extensions.wrapcommand(commands.table, 'log', printrevset)
99 > entry = extensions.wrapcommand(commands.table, 'log', printrevset)
100 > entry[1].append(('', 'print-revset', False,
100 > entry[1].append(('', 'print-revset', False,
101 > 'print generated revset and exit (DEPRECATED)'))
101 > 'print generated revset and exit (DEPRECATED)'))
102 > EOF
102 > EOF
103
103
104 $ echo "[extensions]" >> $HGRCPATH
104 $ echo "[extensions]" >> $HGRCPATH
105 $ echo "printrevset=`pwd`/printrevset.py" >> $HGRCPATH
105 $ echo "printrevset=`pwd`/printrevset.py" >> $HGRCPATH
106
106
107 $ hg init repo
107 $ hg init repo
108 $ cd repo
108 $ cd repo
109
109
110 Empty repo:
110 Empty repo:
111
111
112 $ hg log -G
112 $ hg log -G
113
113
114
114
115 Building DAG:
115 Building DAG:
116
116
117 $ commit 0 "root"
117 $ commit 0 "root"
118 $ commit 1 "collapse" 0
118 $ commit 1 "collapse" 0
119 $ commit 2 "collapse" 1
119 $ commit 2 "collapse" 1
120 $ commit 3 "collapse" 2
120 $ commit 3 "collapse" 2
121 $ commit 4 "merge two known; one immediate left, one immediate right" 1 3
121 $ commit 4 "merge two known; one immediate left, one immediate right" 1 3
122 $ commit 5 "expand" 3 4
122 $ commit 5 "expand" 3 4
123 $ commit 6 "merge two known; one immediate left, one far left" 2 5
123 $ commit 6 "merge two known; one immediate left, one far left" 2 5
124 $ commit 7 "expand" 2 5
124 $ commit 7 "expand" 2 5
125 $ commit 8 "merge two known; one immediate left, one far right" 0 7
125 $ commit 8 "merge two known; one immediate left, one far right" 0 7
126 $ commit 9 "expand" 7 8
126 $ commit 9 "expand" 7 8
127 $ commit 10 "merge two known; one immediate left, one near right" 0 6
127 $ commit 10 "merge two known; one immediate left, one near right" 0 6
128 $ commit 11 "expand" 6 10
128 $ commit 11 "expand" 6 10
129 $ commit 12 "merge two known; one immediate right, one far left" 1 9
129 $ commit 12 "merge two known; one immediate right, one far left" 1 9
130 $ commit 13 "expand" 9 11
130 $ commit 13 "expand" 9 11
131 $ commit 14 "merge two known; one immediate right, one far right" 0 12
131 $ commit 14 "merge two known; one immediate right, one far right" 0 12
132 $ commit 15 "expand" 13 14
132 $ commit 15 "expand" 13 14
133 $ commit 16 "merge two known; one immediate right, one near right" 0 1
133 $ commit 16 "merge two known; one immediate right, one near right" 0 1
134 $ commit 17 "expand" 12 16
134 $ commit 17 "expand" 12 16
135 $ commit 18 "merge two known; two far left" 1 15
135 $ commit 18 "merge two known; two far left" 1 15
136 $ commit 19 "expand" 15 17
136 $ commit 19 "expand" 15 17
137 $ commit 20 "merge two known; two far right" 0 18
137 $ commit 20 "merge two known; two far right" 0 18
138 $ commit 21 "expand" 19 20
138 $ commit 21 "expand" 19 20
139 $ commit 22 "merge two known; one far left, one far right" 18 21
139 $ commit 22 "merge two known; one far left, one far right" 18 21
140 $ commit 23 "merge one known; immediate left" 1 22
140 $ commit 23 "merge one known; immediate left" 1 22
141 $ commit 24 "merge one known; immediate right" 0 23
141 $ commit 24 "merge one known; immediate right" 0 23
142 $ commit 25 "merge one known; far left" 21 24
142 $ commit 25 "merge one known; far left" 21 24
143 $ commit 26 "merge one known; far right" 18 25
143 $ commit 26 "merge one known; far right" 18 25
144 $ commit 27 "collapse" 21
144 $ commit 27 "collapse" 21
145 $ commit 28 "merge zero known" 1 26
145 $ commit 28 "merge zero known" 1 26
146 $ commit 29 "regular commit" 0
146 $ commit 29 "regular commit" 0
147 $ commit 30 "expand" 28 29
147 $ commit 30 "expand" 28 29
148 $ commit 31 "expand" 21 30
148 $ commit 31 "expand" 21 30
149 $ commit 32 "expand" 27 31
149 $ commit 32 "expand" 27 31
150 $ commit 33 "head" 18
150 $ commit 33 "head" 18
151 $ commit 34 "head" 32
151 $ commit 34 "head" 32
152
152
153
153
154 $ hg log -G -q
154 $ hg log -G -q
155 @ 34:fea3ac5810e0
155 @ 34:fea3ac5810e0
156 |
156 |
157 | o 33:68608f5145f9
157 | o 33:68608f5145f9
158 | |
158 | |
159 o | 32:d06dffa21a31
159 o | 32:d06dffa21a31
160 |\ \
160 |\ \
161 | o \ 31:621d83e11f67
161 | o \ 31:621d83e11f67
162 | |\ \
162 | |\ \
163 | | o \ 30:6e11cd4b648f
163 | | o \ 30:6e11cd4b648f
164 | | |\ \
164 | | |\ \
165 | | | o | 29:cd9bb2be7593
165 | | | o | 29:cd9bb2be7593
166 | | | | |
166 | | | | |
167 | | o | | 28:44ecd0b9ae99
167 | | o | | 28:44ecd0b9ae99
168 | | |\ \ \
168 | | |\ \ \
169 o | | | | | 27:886ed638191b
169 o | | | | | 27:886ed638191b
170 |/ / / / /
170 |/ / / / /
171 | | o---+ 26:7f25b6c2f0b9
171 | | o---+ 26:7f25b6c2f0b9
172 | | | | |
172 | | | | |
173 +---o | | 25:91da8ed57247
173 +---o | | 25:91da8ed57247
174 | | | | |
174 | | | | |
175 | | o | | 24:a9c19a3d96b7
175 | | o | | 24:a9c19a3d96b7
176 | | |\| |
176 | | |\| |
177 | | o | | 23:a01cddf0766d
177 | | o | | 23:a01cddf0766d
178 | |/| | |
178 | |/| | |
179 +---o---+ 22:e0d9cccacb5d
179 +---o---+ 22:e0d9cccacb5d
180 | | / /
180 | | / /
181 o | | | 21:d42a756af44d
181 o | | | 21:d42a756af44d
182 |\ \ \ \
182 |\ \ \ \
183 | o---+-+ 20:d30ed6450e32
183 | o---+-+ 20:d30ed6450e32
184 | / / /
184 | / / /
185 o | | | 19:31ddc2c1573b
185 o | | | 19:31ddc2c1573b
186 |\ \ \ \
186 |\ \ \ \
187 +---+---o 18:1aa84d96232a
187 +---+---o 18:1aa84d96232a
188 | | | |
188 | | | |
189 | o | | 17:44765d7c06e0
189 | o | | 17:44765d7c06e0
190 | |\ \ \
190 | |\ \ \
191 | | o---+ 16:3677d192927d
191 | | o---+ 16:3677d192927d
192 | | |/ /
192 | | |/ /
193 o | | | 15:1dda3f72782d
193 o | | | 15:1dda3f72782d
194 |\ \ \ \
194 |\ \ \ \
195 | o-----+ 14:8eac370358ef
195 | o-----+ 14:8eac370358ef
196 | |/ / /
196 | |/ / /
197 o | | | 13:22d8966a97e3
197 o | | | 13:22d8966a97e3
198 |\ \ \ \
198 |\ \ \ \
199 +---o | | 12:86b91144a6e9
199 +---o | | 12:86b91144a6e9
200 | | |/ /
200 | | |/ /
201 | o | | 11:832d76e6bdf2
201 | o | | 11:832d76e6bdf2
202 | |\ \ \
202 | |\ \ \
203 | | o---+ 10:74c64d036d72
203 | | o---+ 10:74c64d036d72
204 | |/ / /
204 | |/ / /
205 o | | | 9:7010c0af0a35
205 o | | | 9:7010c0af0a35
206 |\ \ \ \
206 |\ \ \ \
207 | o-----+ 8:7a0b11f71937
207 | o-----+ 8:7a0b11f71937
208 |/ / / /
208 |/ / / /
209 o | | | 7:b632bb1b1224
209 o | | | 7:b632bb1b1224
210 |\ \ \ \
210 |\ \ \ \
211 +---o | | 6:b105a072e251
211 +---o | | 6:b105a072e251
212 | |/ / /
212 | |/ / /
213 | o | | 5:4409d547b708
213 | o | | 5:4409d547b708
214 | |\ \ \
214 | |\ \ \
215 | | o | | 4:26a8bac39d9f
215 | | o | | 4:26a8bac39d9f
216 | |/|/ /
216 | |/|/ /
217 | o / / 3:27eef8ed80b4
217 | o / / 3:27eef8ed80b4
218 |/ / /
218 |/ / /
219 o / / 2:3d9a33b8d1e1
219 o / / 2:3d9a33b8d1e1
220 |/ /
220 |/ /
221 o / 1:6db2ef61d156
221 o / 1:6db2ef61d156
222 |/
222 |/
223 o 0:e6eb3150255d
223 o 0:e6eb3150255d
224
224
225
225
226 $ hg log -G
226 $ hg log -G
227 @ changeset: 34:fea3ac5810e0
227 @ changeset: 34:fea3ac5810e0
228 | tag: tip
228 | tag: tip
229 | parent: 32:d06dffa21a31
229 | parent: 32:d06dffa21a31
230 | user: test
230 | user: test
231 | date: Thu Jan 01 00:00:34 1970 +0000
231 | date: Thu Jan 01 00:00:34 1970 +0000
232 | summary: (34) head
232 | summary: (34) head
233 |
233 |
234 | o changeset: 33:68608f5145f9
234 | o changeset: 33:68608f5145f9
235 | | parent: 18:1aa84d96232a
235 | | parent: 18:1aa84d96232a
236 | | user: test
236 | | user: test
237 | | date: Thu Jan 01 00:00:33 1970 +0000
237 | | date: Thu Jan 01 00:00:33 1970 +0000
238 | | summary: (33) head
238 | | summary: (33) head
239 | |
239 | |
240 o | changeset: 32:d06dffa21a31
240 o | changeset: 32:d06dffa21a31
241 |\ \ parent: 27:886ed638191b
241 |\ \ parent: 27:886ed638191b
242 | | | parent: 31:621d83e11f67
242 | | | parent: 31:621d83e11f67
243 | | | user: test
243 | | | user: test
244 | | | date: Thu Jan 01 00:00:32 1970 +0000
244 | | | date: Thu Jan 01 00:00:32 1970 +0000
245 | | | summary: (32) expand
245 | | | summary: (32) expand
246 | | |
246 | | |
247 | o | changeset: 31:621d83e11f67
247 | o | changeset: 31:621d83e11f67
248 | |\ \ parent: 21:d42a756af44d
248 | |\ \ parent: 21:d42a756af44d
249 | | | | parent: 30:6e11cd4b648f
249 | | | | parent: 30:6e11cd4b648f
250 | | | | user: test
250 | | | | user: test
251 | | | | date: Thu Jan 01 00:00:31 1970 +0000
251 | | | | date: Thu Jan 01 00:00:31 1970 +0000
252 | | | | summary: (31) expand
252 | | | | summary: (31) expand
253 | | | |
253 | | | |
254 | | o | changeset: 30:6e11cd4b648f
254 | | o | changeset: 30:6e11cd4b648f
255 | | |\ \ parent: 28:44ecd0b9ae99
255 | | |\ \ parent: 28:44ecd0b9ae99
256 | | | | | parent: 29:cd9bb2be7593
256 | | | | | parent: 29:cd9bb2be7593
257 | | | | | user: test
257 | | | | | user: test
258 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
258 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
259 | | | | | summary: (30) expand
259 | | | | | summary: (30) expand
260 | | | | |
260 | | | | |
261 | | | o | changeset: 29:cd9bb2be7593
261 | | | o | changeset: 29:cd9bb2be7593
262 | | | | | parent: 0:e6eb3150255d
262 | | | | | parent: 0:e6eb3150255d
263 | | | | | user: test
263 | | | | | user: test
264 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
264 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
265 | | | | | summary: (29) regular commit
265 | | | | | summary: (29) regular commit
266 | | | | |
266 | | | | |
267 | | o | | changeset: 28:44ecd0b9ae99
267 | | o | | changeset: 28:44ecd0b9ae99
268 | | |\ \ \ parent: 1:6db2ef61d156
268 | | |\ \ \ parent: 1:6db2ef61d156
269 | | | | | | parent: 26:7f25b6c2f0b9
269 | | | | | | parent: 26:7f25b6c2f0b9
270 | | | | | | user: test
270 | | | | | | user: test
271 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
271 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
272 | | | | | | summary: (28) merge zero known
272 | | | | | | summary: (28) merge zero known
273 | | | | | |
273 | | | | | |
274 o | | | | | changeset: 27:886ed638191b
274 o | | | | | changeset: 27:886ed638191b
275 |/ / / / / parent: 21:d42a756af44d
275 |/ / / / / parent: 21:d42a756af44d
276 | | | | | user: test
276 | | | | | user: test
277 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
277 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
278 | | | | | summary: (27) collapse
278 | | | | | summary: (27) collapse
279 | | | | |
279 | | | | |
280 | | o---+ changeset: 26:7f25b6c2f0b9
280 | | o---+ changeset: 26:7f25b6c2f0b9
281 | | | | | parent: 18:1aa84d96232a
281 | | | | | parent: 18:1aa84d96232a
282 | | | | | parent: 25:91da8ed57247
282 | | | | | parent: 25:91da8ed57247
283 | | | | | user: test
283 | | | | | user: test
284 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
284 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
285 | | | | | summary: (26) merge one known; far right
285 | | | | | summary: (26) merge one known; far right
286 | | | | |
286 | | | | |
287 +---o | | changeset: 25:91da8ed57247
287 +---o | | changeset: 25:91da8ed57247
288 | | | | | parent: 21:d42a756af44d
288 | | | | | parent: 21:d42a756af44d
289 | | | | | parent: 24:a9c19a3d96b7
289 | | | | | parent: 24:a9c19a3d96b7
290 | | | | | user: test
290 | | | | | user: test
291 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
291 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
292 | | | | | summary: (25) merge one known; far left
292 | | | | | summary: (25) merge one known; far left
293 | | | | |
293 | | | | |
294 | | o | | changeset: 24:a9c19a3d96b7
294 | | o | | changeset: 24:a9c19a3d96b7
295 | | |\| | parent: 0:e6eb3150255d
295 | | |\| | parent: 0:e6eb3150255d
296 | | | | | parent: 23:a01cddf0766d
296 | | | | | parent: 23:a01cddf0766d
297 | | | | | user: test
297 | | | | | user: test
298 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
298 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
299 | | | | | summary: (24) merge one known; immediate right
299 | | | | | summary: (24) merge one known; immediate right
300 | | | | |
300 | | | | |
301 | | o | | changeset: 23:a01cddf0766d
301 | | o | | changeset: 23:a01cddf0766d
302 | |/| | | parent: 1:6db2ef61d156
302 | |/| | | parent: 1:6db2ef61d156
303 | | | | | parent: 22:e0d9cccacb5d
303 | | | | | parent: 22:e0d9cccacb5d
304 | | | | | user: test
304 | | | | | user: test
305 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
305 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
306 | | | | | summary: (23) merge one known; immediate left
306 | | | | | summary: (23) merge one known; immediate left
307 | | | | |
307 | | | | |
308 +---o---+ changeset: 22:e0d9cccacb5d
308 +---o---+ changeset: 22:e0d9cccacb5d
309 | | | | parent: 18:1aa84d96232a
309 | | | | parent: 18:1aa84d96232a
310 | | / / parent: 21:d42a756af44d
310 | | / / parent: 21:d42a756af44d
311 | | | | user: test
311 | | | | user: test
312 | | | | date: Thu Jan 01 00:00:22 1970 +0000
312 | | | | date: Thu Jan 01 00:00:22 1970 +0000
313 | | | | summary: (22) merge two known; one far left, one far right
313 | | | | summary: (22) merge two known; one far left, one far right
314 | | | |
314 | | | |
315 o | | | changeset: 21:d42a756af44d
315 o | | | changeset: 21:d42a756af44d
316 |\ \ \ \ parent: 19:31ddc2c1573b
316 |\ \ \ \ parent: 19:31ddc2c1573b
317 | | | | | parent: 20:d30ed6450e32
317 | | | | | parent: 20:d30ed6450e32
318 | | | | | user: test
318 | | | | | user: test
319 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
319 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
320 | | | | | summary: (21) expand
320 | | | | | summary: (21) expand
321 | | | | |
321 | | | | |
322 | o---+-+ changeset: 20:d30ed6450e32
322 | o---+-+ changeset: 20:d30ed6450e32
323 | | | | parent: 0:e6eb3150255d
323 | | | | parent: 0:e6eb3150255d
324 | / / / parent: 18:1aa84d96232a
324 | / / / parent: 18:1aa84d96232a
325 | | | | user: test
325 | | | | user: test
326 | | | | date: Thu Jan 01 00:00:20 1970 +0000
326 | | | | date: Thu Jan 01 00:00:20 1970 +0000
327 | | | | summary: (20) merge two known; two far right
327 | | | | summary: (20) merge two known; two far right
328 | | | |
328 | | | |
329 o | | | changeset: 19:31ddc2c1573b
329 o | | | changeset: 19:31ddc2c1573b
330 |\ \ \ \ parent: 15:1dda3f72782d
330 |\ \ \ \ parent: 15:1dda3f72782d
331 | | | | | parent: 17:44765d7c06e0
331 | | | | | parent: 17:44765d7c06e0
332 | | | | | user: test
332 | | | | | user: test
333 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
333 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
334 | | | | | summary: (19) expand
334 | | | | | summary: (19) expand
335 | | | | |
335 | | | | |
336 +---+---o changeset: 18:1aa84d96232a
336 +---+---o changeset: 18:1aa84d96232a
337 | | | | parent: 1:6db2ef61d156
337 | | | | parent: 1:6db2ef61d156
338 | | | | parent: 15:1dda3f72782d
338 | | | | parent: 15:1dda3f72782d
339 | | | | user: test
339 | | | | user: test
340 | | | | date: Thu Jan 01 00:00:18 1970 +0000
340 | | | | date: Thu Jan 01 00:00:18 1970 +0000
341 | | | | summary: (18) merge two known; two far left
341 | | | | summary: (18) merge two known; two far left
342 | | | |
342 | | | |
343 | o | | changeset: 17:44765d7c06e0
343 | o | | changeset: 17:44765d7c06e0
344 | |\ \ \ parent: 12:86b91144a6e9
344 | |\ \ \ parent: 12:86b91144a6e9
345 | | | | | parent: 16:3677d192927d
345 | | | | | parent: 16:3677d192927d
346 | | | | | user: test
346 | | | | | user: test
347 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
347 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
348 | | | | | summary: (17) expand
348 | | | | | summary: (17) expand
349 | | | | |
349 | | | | |
350 | | o---+ changeset: 16:3677d192927d
350 | | o---+ changeset: 16:3677d192927d
351 | | | | | parent: 0:e6eb3150255d
351 | | | | | parent: 0:e6eb3150255d
352 | | |/ / parent: 1:6db2ef61d156
352 | | |/ / parent: 1:6db2ef61d156
353 | | | | user: test
353 | | | | user: test
354 | | | | date: Thu Jan 01 00:00:16 1970 +0000
354 | | | | date: Thu Jan 01 00:00:16 1970 +0000
355 | | | | summary: (16) merge two known; one immediate right, one near right
355 | | | | summary: (16) merge two known; one immediate right, one near right
356 | | | |
356 | | | |
357 o | | | changeset: 15:1dda3f72782d
357 o | | | changeset: 15:1dda3f72782d
358 |\ \ \ \ parent: 13:22d8966a97e3
358 |\ \ \ \ parent: 13:22d8966a97e3
359 | | | | | parent: 14:8eac370358ef
359 | | | | | parent: 14:8eac370358ef
360 | | | | | user: test
360 | | | | | user: test
361 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
361 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
362 | | | | | summary: (15) expand
362 | | | | | summary: (15) expand
363 | | | | |
363 | | | | |
364 | o-----+ changeset: 14:8eac370358ef
364 | o-----+ changeset: 14:8eac370358ef
365 | | | | | parent: 0:e6eb3150255d
365 | | | | | parent: 0:e6eb3150255d
366 | |/ / / parent: 12:86b91144a6e9
366 | |/ / / parent: 12:86b91144a6e9
367 | | | | user: test
367 | | | | user: test
368 | | | | date: Thu Jan 01 00:00:14 1970 +0000
368 | | | | date: Thu Jan 01 00:00:14 1970 +0000
369 | | | | summary: (14) merge two known; one immediate right, one far right
369 | | | | summary: (14) merge two known; one immediate right, one far right
370 | | | |
370 | | | |
371 o | | | changeset: 13:22d8966a97e3
371 o | | | changeset: 13:22d8966a97e3
372 |\ \ \ \ parent: 9:7010c0af0a35
372 |\ \ \ \ parent: 9:7010c0af0a35
373 | | | | | parent: 11:832d76e6bdf2
373 | | | | | parent: 11:832d76e6bdf2
374 | | | | | user: test
374 | | | | | user: test
375 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
375 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
376 | | | | | summary: (13) expand
376 | | | | | summary: (13) expand
377 | | | | |
377 | | | | |
378 +---o | | changeset: 12:86b91144a6e9
378 +---o | | changeset: 12:86b91144a6e9
379 | | |/ / parent: 1:6db2ef61d156
379 | | |/ / parent: 1:6db2ef61d156
380 | | | | parent: 9:7010c0af0a35
380 | | | | parent: 9:7010c0af0a35
381 | | | | user: test
381 | | | | user: test
382 | | | | date: Thu Jan 01 00:00:12 1970 +0000
382 | | | | date: Thu Jan 01 00:00:12 1970 +0000
383 | | | | summary: (12) merge two known; one immediate right, one far left
383 | | | | summary: (12) merge two known; one immediate right, one far left
384 | | | |
384 | | | |
385 | o | | changeset: 11:832d76e6bdf2
385 | o | | changeset: 11:832d76e6bdf2
386 | |\ \ \ parent: 6:b105a072e251
386 | |\ \ \ parent: 6:b105a072e251
387 | | | | | parent: 10:74c64d036d72
387 | | | | | parent: 10:74c64d036d72
388 | | | | | user: test
388 | | | | | user: test
389 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
389 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
390 | | | | | summary: (11) expand
390 | | | | | summary: (11) expand
391 | | | | |
391 | | | | |
392 | | o---+ changeset: 10:74c64d036d72
392 | | o---+ changeset: 10:74c64d036d72
393 | | | | | parent: 0:e6eb3150255d
393 | | | | | parent: 0:e6eb3150255d
394 | |/ / / parent: 6:b105a072e251
394 | |/ / / parent: 6:b105a072e251
395 | | | | user: test
395 | | | | user: test
396 | | | | date: Thu Jan 01 00:00:10 1970 +0000
396 | | | | date: Thu Jan 01 00:00:10 1970 +0000
397 | | | | summary: (10) merge two known; one immediate left, one near right
397 | | | | summary: (10) merge two known; one immediate left, one near right
398 | | | |
398 | | | |
399 o | | | changeset: 9:7010c0af0a35
399 o | | | changeset: 9:7010c0af0a35
400 |\ \ \ \ parent: 7:b632bb1b1224
400 |\ \ \ \ parent: 7:b632bb1b1224
401 | | | | | parent: 8:7a0b11f71937
401 | | | | | parent: 8:7a0b11f71937
402 | | | | | user: test
402 | | | | | user: test
403 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
403 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
404 | | | | | summary: (9) expand
404 | | | | | summary: (9) expand
405 | | | | |
405 | | | | |
406 | o-----+ changeset: 8:7a0b11f71937
406 | o-----+ changeset: 8:7a0b11f71937
407 | | | | | parent: 0:e6eb3150255d
407 | | | | | parent: 0:e6eb3150255d
408 |/ / / / parent: 7:b632bb1b1224
408 |/ / / / parent: 7:b632bb1b1224
409 | | | | user: test
409 | | | | user: test
410 | | | | date: Thu Jan 01 00:00:08 1970 +0000
410 | | | | date: Thu Jan 01 00:00:08 1970 +0000
411 | | | | summary: (8) merge two known; one immediate left, one far right
411 | | | | summary: (8) merge two known; one immediate left, one far right
412 | | | |
412 | | | |
413 o | | | changeset: 7:b632bb1b1224
413 o | | | changeset: 7:b632bb1b1224
414 |\ \ \ \ parent: 2:3d9a33b8d1e1
414 |\ \ \ \ parent: 2:3d9a33b8d1e1
415 | | | | | parent: 5:4409d547b708
415 | | | | | parent: 5:4409d547b708
416 | | | | | user: test
416 | | | | | user: test
417 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
417 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
418 | | | | | summary: (7) expand
418 | | | | | summary: (7) expand
419 | | | | |
419 | | | | |
420 +---o | | changeset: 6:b105a072e251
420 +---o | | changeset: 6:b105a072e251
421 | |/ / / parent: 2:3d9a33b8d1e1
421 | |/ / / parent: 2:3d9a33b8d1e1
422 | | | | parent: 5:4409d547b708
422 | | | | parent: 5:4409d547b708
423 | | | | user: test
423 | | | | user: test
424 | | | | date: Thu Jan 01 00:00:06 1970 +0000
424 | | | | date: Thu Jan 01 00:00:06 1970 +0000
425 | | | | summary: (6) merge two known; one immediate left, one far left
425 | | | | summary: (6) merge two known; one immediate left, one far left
426 | | | |
426 | | | |
427 | o | | changeset: 5:4409d547b708
427 | o | | changeset: 5:4409d547b708
428 | |\ \ \ parent: 3:27eef8ed80b4
428 | |\ \ \ parent: 3:27eef8ed80b4
429 | | | | | parent: 4:26a8bac39d9f
429 | | | | | parent: 4:26a8bac39d9f
430 | | | | | user: test
430 | | | | | user: test
431 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
431 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
432 | | | | | summary: (5) expand
432 | | | | | summary: (5) expand
433 | | | | |
433 | | | | |
434 | | o | | changeset: 4:26a8bac39d9f
434 | | o | | changeset: 4:26a8bac39d9f
435 | |/|/ / parent: 1:6db2ef61d156
435 | |/|/ / parent: 1:6db2ef61d156
436 | | | | parent: 3:27eef8ed80b4
436 | | | | parent: 3:27eef8ed80b4
437 | | | | user: test
437 | | | | user: test
438 | | | | date: Thu Jan 01 00:00:04 1970 +0000
438 | | | | date: Thu Jan 01 00:00:04 1970 +0000
439 | | | | summary: (4) merge two known; one immediate left, one immediate right
439 | | | | summary: (4) merge two known; one immediate left, one immediate right
440 | | | |
440 | | | |
441 | o | | changeset: 3:27eef8ed80b4
441 | o | | changeset: 3:27eef8ed80b4
442 |/ / / user: test
442 |/ / / user: test
443 | | | date: Thu Jan 01 00:00:03 1970 +0000
443 | | | date: Thu Jan 01 00:00:03 1970 +0000
444 | | | summary: (3) collapse
444 | | | summary: (3) collapse
445 | | |
445 | | |
446 o | | changeset: 2:3d9a33b8d1e1
446 o | | changeset: 2:3d9a33b8d1e1
447 |/ / user: test
447 |/ / user: test
448 | | date: Thu Jan 01 00:00:02 1970 +0000
448 | | date: Thu Jan 01 00:00:02 1970 +0000
449 | | summary: (2) collapse
449 | | summary: (2) collapse
450 | |
450 | |
451 o | changeset: 1:6db2ef61d156
451 o | changeset: 1:6db2ef61d156
452 |/ user: test
452 |/ user: test
453 | date: Thu Jan 01 00:00:01 1970 +0000
453 | date: Thu Jan 01 00:00:01 1970 +0000
454 | summary: (1) collapse
454 | summary: (1) collapse
455 |
455 |
456 o changeset: 0:e6eb3150255d
456 o changeset: 0:e6eb3150255d
457 user: test
457 user: test
458 date: Thu Jan 01 00:00:00 1970 +0000
458 date: Thu Jan 01 00:00:00 1970 +0000
459 summary: (0) root
459 summary: (0) root
460
460
461
461
462 File glog:
462 File glog:
463 $ hg log -G a
463 $ hg log -G a
464 @ changeset: 34:fea3ac5810e0
464 @ changeset: 34:fea3ac5810e0
465 | tag: tip
465 | tag: tip
466 | parent: 32:d06dffa21a31
466 | parent: 32:d06dffa21a31
467 | user: test
467 | user: test
468 | date: Thu Jan 01 00:00:34 1970 +0000
468 | date: Thu Jan 01 00:00:34 1970 +0000
469 | summary: (34) head
469 | summary: (34) head
470 |
470 |
471 | o changeset: 33:68608f5145f9
471 | o changeset: 33:68608f5145f9
472 | | parent: 18:1aa84d96232a
472 | | parent: 18:1aa84d96232a
473 | | user: test
473 | | user: test
474 | | date: Thu Jan 01 00:00:33 1970 +0000
474 | | date: Thu Jan 01 00:00:33 1970 +0000
475 | | summary: (33) head
475 | | summary: (33) head
476 | |
476 | |
477 o | changeset: 32:d06dffa21a31
477 o | changeset: 32:d06dffa21a31
478 |\ \ parent: 27:886ed638191b
478 |\ \ parent: 27:886ed638191b
479 | | | parent: 31:621d83e11f67
479 | | | parent: 31:621d83e11f67
480 | | | user: test
480 | | | user: test
481 | | | date: Thu Jan 01 00:00:32 1970 +0000
481 | | | date: Thu Jan 01 00:00:32 1970 +0000
482 | | | summary: (32) expand
482 | | | summary: (32) expand
483 | | |
483 | | |
484 | o | changeset: 31:621d83e11f67
484 | o | changeset: 31:621d83e11f67
485 | |\ \ parent: 21:d42a756af44d
485 | |\ \ parent: 21:d42a756af44d
486 | | | | parent: 30:6e11cd4b648f
486 | | | | parent: 30:6e11cd4b648f
487 | | | | user: test
487 | | | | user: test
488 | | | | date: Thu Jan 01 00:00:31 1970 +0000
488 | | | | date: Thu Jan 01 00:00:31 1970 +0000
489 | | | | summary: (31) expand
489 | | | | summary: (31) expand
490 | | | |
490 | | | |
491 | | o | changeset: 30:6e11cd4b648f
491 | | o | changeset: 30:6e11cd4b648f
492 | | |\ \ parent: 28:44ecd0b9ae99
492 | | |\ \ parent: 28:44ecd0b9ae99
493 | | | | | parent: 29:cd9bb2be7593
493 | | | | | parent: 29:cd9bb2be7593
494 | | | | | user: test
494 | | | | | user: test
495 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
495 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
496 | | | | | summary: (30) expand
496 | | | | | summary: (30) expand
497 | | | | |
497 | | | | |
498 | | | o | changeset: 29:cd9bb2be7593
498 | | | o | changeset: 29:cd9bb2be7593
499 | | | | | parent: 0:e6eb3150255d
499 | | | | | parent: 0:e6eb3150255d
500 | | | | | user: test
500 | | | | | user: test
501 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
501 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
502 | | | | | summary: (29) regular commit
502 | | | | | summary: (29) regular commit
503 | | | | |
503 | | | | |
504 | | o | | changeset: 28:44ecd0b9ae99
504 | | o | | changeset: 28:44ecd0b9ae99
505 | | |\ \ \ parent: 1:6db2ef61d156
505 | | |\ \ \ parent: 1:6db2ef61d156
506 | | | | | | parent: 26:7f25b6c2f0b9
506 | | | | | | parent: 26:7f25b6c2f0b9
507 | | | | | | user: test
507 | | | | | | user: test
508 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
508 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
509 | | | | | | summary: (28) merge zero known
509 | | | | | | summary: (28) merge zero known
510 | | | | | |
510 | | | | | |
511 o | | | | | changeset: 27:886ed638191b
511 o | | | | | changeset: 27:886ed638191b
512 |/ / / / / parent: 21:d42a756af44d
512 |/ / / / / parent: 21:d42a756af44d
513 | | | | | user: test
513 | | | | | user: test
514 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
514 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
515 | | | | | summary: (27) collapse
515 | | | | | summary: (27) collapse
516 | | | | |
516 | | | | |
517 | | o---+ changeset: 26:7f25b6c2f0b9
517 | | o---+ changeset: 26:7f25b6c2f0b9
518 | | | | | parent: 18:1aa84d96232a
518 | | | | | parent: 18:1aa84d96232a
519 | | | | | parent: 25:91da8ed57247
519 | | | | | parent: 25:91da8ed57247
520 | | | | | user: test
520 | | | | | user: test
521 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
521 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
522 | | | | | summary: (26) merge one known; far right
522 | | | | | summary: (26) merge one known; far right
523 | | | | |
523 | | | | |
524 +---o | | changeset: 25:91da8ed57247
524 +---o | | changeset: 25:91da8ed57247
525 | | | | | parent: 21:d42a756af44d
525 | | | | | parent: 21:d42a756af44d
526 | | | | | parent: 24:a9c19a3d96b7
526 | | | | | parent: 24:a9c19a3d96b7
527 | | | | | user: test
527 | | | | | user: test
528 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
528 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
529 | | | | | summary: (25) merge one known; far left
529 | | | | | summary: (25) merge one known; far left
530 | | | | |
530 | | | | |
531 | | o | | changeset: 24:a9c19a3d96b7
531 | | o | | changeset: 24:a9c19a3d96b7
532 | | |\| | parent: 0:e6eb3150255d
532 | | |\| | parent: 0:e6eb3150255d
533 | | | | | parent: 23:a01cddf0766d
533 | | | | | parent: 23:a01cddf0766d
534 | | | | | user: test
534 | | | | | user: test
535 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
535 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
536 | | | | | summary: (24) merge one known; immediate right
536 | | | | | summary: (24) merge one known; immediate right
537 | | | | |
537 | | | | |
538 | | o | | changeset: 23:a01cddf0766d
538 | | o | | changeset: 23:a01cddf0766d
539 | |/| | | parent: 1:6db2ef61d156
539 | |/| | | parent: 1:6db2ef61d156
540 | | | | | parent: 22:e0d9cccacb5d
540 | | | | | parent: 22:e0d9cccacb5d
541 | | | | | user: test
541 | | | | | user: test
542 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
542 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
543 | | | | | summary: (23) merge one known; immediate left
543 | | | | | summary: (23) merge one known; immediate left
544 | | | | |
544 | | | | |
545 +---o---+ changeset: 22:e0d9cccacb5d
545 +---o---+ changeset: 22:e0d9cccacb5d
546 | | | | parent: 18:1aa84d96232a
546 | | | | parent: 18:1aa84d96232a
547 | | / / parent: 21:d42a756af44d
547 | | / / parent: 21:d42a756af44d
548 | | | | user: test
548 | | | | user: test
549 | | | | date: Thu Jan 01 00:00:22 1970 +0000
549 | | | | date: Thu Jan 01 00:00:22 1970 +0000
550 | | | | summary: (22) merge two known; one far left, one far right
550 | | | | summary: (22) merge two known; one far left, one far right
551 | | | |
551 | | | |
552 o | | | changeset: 21:d42a756af44d
552 o | | | changeset: 21:d42a756af44d
553 |\ \ \ \ parent: 19:31ddc2c1573b
553 |\ \ \ \ parent: 19:31ddc2c1573b
554 | | | | | parent: 20:d30ed6450e32
554 | | | | | parent: 20:d30ed6450e32
555 | | | | | user: test
555 | | | | | user: test
556 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
556 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
557 | | | | | summary: (21) expand
557 | | | | | summary: (21) expand
558 | | | | |
558 | | | | |
559 | o---+-+ changeset: 20:d30ed6450e32
559 | o---+-+ changeset: 20:d30ed6450e32
560 | | | | parent: 0:e6eb3150255d
560 | | | | parent: 0:e6eb3150255d
561 | / / / parent: 18:1aa84d96232a
561 | / / / parent: 18:1aa84d96232a
562 | | | | user: test
562 | | | | user: test
563 | | | | date: Thu Jan 01 00:00:20 1970 +0000
563 | | | | date: Thu Jan 01 00:00:20 1970 +0000
564 | | | | summary: (20) merge two known; two far right
564 | | | | summary: (20) merge two known; two far right
565 | | | |
565 | | | |
566 o | | | changeset: 19:31ddc2c1573b
566 o | | | changeset: 19:31ddc2c1573b
567 |\ \ \ \ parent: 15:1dda3f72782d
567 |\ \ \ \ parent: 15:1dda3f72782d
568 | | | | | parent: 17:44765d7c06e0
568 | | | | | parent: 17:44765d7c06e0
569 | | | | | user: test
569 | | | | | user: test
570 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
570 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
571 | | | | | summary: (19) expand
571 | | | | | summary: (19) expand
572 | | | | |
572 | | | | |
573 +---+---o changeset: 18:1aa84d96232a
573 +---+---o changeset: 18:1aa84d96232a
574 | | | | parent: 1:6db2ef61d156
574 | | | | parent: 1:6db2ef61d156
575 | | | | parent: 15:1dda3f72782d
575 | | | | parent: 15:1dda3f72782d
576 | | | | user: test
576 | | | | user: test
577 | | | | date: Thu Jan 01 00:00:18 1970 +0000
577 | | | | date: Thu Jan 01 00:00:18 1970 +0000
578 | | | | summary: (18) merge two known; two far left
578 | | | | summary: (18) merge two known; two far left
579 | | | |
579 | | | |
580 | o | | changeset: 17:44765d7c06e0
580 | o | | changeset: 17:44765d7c06e0
581 | |\ \ \ parent: 12:86b91144a6e9
581 | |\ \ \ parent: 12:86b91144a6e9
582 | | | | | parent: 16:3677d192927d
582 | | | | | parent: 16:3677d192927d
583 | | | | | user: test
583 | | | | | user: test
584 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
584 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
585 | | | | | summary: (17) expand
585 | | | | | summary: (17) expand
586 | | | | |
586 | | | | |
587 | | o---+ changeset: 16:3677d192927d
587 | | o---+ changeset: 16:3677d192927d
588 | | | | | parent: 0:e6eb3150255d
588 | | | | | parent: 0:e6eb3150255d
589 | | |/ / parent: 1:6db2ef61d156
589 | | |/ / parent: 1:6db2ef61d156
590 | | | | user: test
590 | | | | user: test
591 | | | | date: Thu Jan 01 00:00:16 1970 +0000
591 | | | | date: Thu Jan 01 00:00:16 1970 +0000
592 | | | | summary: (16) merge two known; one immediate right, one near right
592 | | | | summary: (16) merge two known; one immediate right, one near right
593 | | | |
593 | | | |
594 o | | | changeset: 15:1dda3f72782d
594 o | | | changeset: 15:1dda3f72782d
595 |\ \ \ \ parent: 13:22d8966a97e3
595 |\ \ \ \ parent: 13:22d8966a97e3
596 | | | | | parent: 14:8eac370358ef
596 | | | | | parent: 14:8eac370358ef
597 | | | | | user: test
597 | | | | | user: test
598 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
598 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
599 | | | | | summary: (15) expand
599 | | | | | summary: (15) expand
600 | | | | |
600 | | | | |
601 | o-----+ changeset: 14:8eac370358ef
601 | o-----+ changeset: 14:8eac370358ef
602 | | | | | parent: 0:e6eb3150255d
602 | | | | | parent: 0:e6eb3150255d
603 | |/ / / parent: 12:86b91144a6e9
603 | |/ / / parent: 12:86b91144a6e9
604 | | | | user: test
604 | | | | user: test
605 | | | | date: Thu Jan 01 00:00:14 1970 +0000
605 | | | | date: Thu Jan 01 00:00:14 1970 +0000
606 | | | | summary: (14) merge two known; one immediate right, one far right
606 | | | | summary: (14) merge two known; one immediate right, one far right
607 | | | |
607 | | | |
608 o | | | changeset: 13:22d8966a97e3
608 o | | | changeset: 13:22d8966a97e3
609 |\ \ \ \ parent: 9:7010c0af0a35
609 |\ \ \ \ parent: 9:7010c0af0a35
610 | | | | | parent: 11:832d76e6bdf2
610 | | | | | parent: 11:832d76e6bdf2
611 | | | | | user: test
611 | | | | | user: test
612 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
612 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
613 | | | | | summary: (13) expand
613 | | | | | summary: (13) expand
614 | | | | |
614 | | | | |
615 +---o | | changeset: 12:86b91144a6e9
615 +---o | | changeset: 12:86b91144a6e9
616 | | |/ / parent: 1:6db2ef61d156
616 | | |/ / parent: 1:6db2ef61d156
617 | | | | parent: 9:7010c0af0a35
617 | | | | parent: 9:7010c0af0a35
618 | | | | user: test
618 | | | | user: test
619 | | | | date: Thu Jan 01 00:00:12 1970 +0000
619 | | | | date: Thu Jan 01 00:00:12 1970 +0000
620 | | | | summary: (12) merge two known; one immediate right, one far left
620 | | | | summary: (12) merge two known; one immediate right, one far left
621 | | | |
621 | | | |
622 | o | | changeset: 11:832d76e6bdf2
622 | o | | changeset: 11:832d76e6bdf2
623 | |\ \ \ parent: 6:b105a072e251
623 | |\ \ \ parent: 6:b105a072e251
624 | | | | | parent: 10:74c64d036d72
624 | | | | | parent: 10:74c64d036d72
625 | | | | | user: test
625 | | | | | user: test
626 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
626 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
627 | | | | | summary: (11) expand
627 | | | | | summary: (11) expand
628 | | | | |
628 | | | | |
629 | | o---+ changeset: 10:74c64d036d72
629 | | o---+ changeset: 10:74c64d036d72
630 | | | | | parent: 0:e6eb3150255d
630 | | | | | parent: 0:e6eb3150255d
631 | |/ / / parent: 6:b105a072e251
631 | |/ / / parent: 6:b105a072e251
632 | | | | user: test
632 | | | | user: test
633 | | | | date: Thu Jan 01 00:00:10 1970 +0000
633 | | | | date: Thu Jan 01 00:00:10 1970 +0000
634 | | | | summary: (10) merge two known; one immediate left, one near right
634 | | | | summary: (10) merge two known; one immediate left, one near right
635 | | | |
635 | | | |
636 o | | | changeset: 9:7010c0af0a35
636 o | | | changeset: 9:7010c0af0a35
637 |\ \ \ \ parent: 7:b632bb1b1224
637 |\ \ \ \ parent: 7:b632bb1b1224
638 | | | | | parent: 8:7a0b11f71937
638 | | | | | parent: 8:7a0b11f71937
639 | | | | | user: test
639 | | | | | user: test
640 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
640 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
641 | | | | | summary: (9) expand
641 | | | | | summary: (9) expand
642 | | | | |
642 | | | | |
643 | o-----+ changeset: 8:7a0b11f71937
643 | o-----+ changeset: 8:7a0b11f71937
644 | | | | | parent: 0:e6eb3150255d
644 | | | | | parent: 0:e6eb3150255d
645 |/ / / / parent: 7:b632bb1b1224
645 |/ / / / parent: 7:b632bb1b1224
646 | | | | user: test
646 | | | | user: test
647 | | | | date: Thu Jan 01 00:00:08 1970 +0000
647 | | | | date: Thu Jan 01 00:00:08 1970 +0000
648 | | | | summary: (8) merge two known; one immediate left, one far right
648 | | | | summary: (8) merge two known; one immediate left, one far right
649 | | | |
649 | | | |
650 o | | | changeset: 7:b632bb1b1224
650 o | | | changeset: 7:b632bb1b1224
651 |\ \ \ \ parent: 2:3d9a33b8d1e1
651 |\ \ \ \ parent: 2:3d9a33b8d1e1
652 | | | | | parent: 5:4409d547b708
652 | | | | | parent: 5:4409d547b708
653 | | | | | user: test
653 | | | | | user: test
654 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
654 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
655 | | | | | summary: (7) expand
655 | | | | | summary: (7) expand
656 | | | | |
656 | | | | |
657 +---o | | changeset: 6:b105a072e251
657 +---o | | changeset: 6:b105a072e251
658 | |/ / / parent: 2:3d9a33b8d1e1
658 | |/ / / parent: 2:3d9a33b8d1e1
659 | | | | parent: 5:4409d547b708
659 | | | | parent: 5:4409d547b708
660 | | | | user: test
660 | | | | user: test
661 | | | | date: Thu Jan 01 00:00:06 1970 +0000
661 | | | | date: Thu Jan 01 00:00:06 1970 +0000
662 | | | | summary: (6) merge two known; one immediate left, one far left
662 | | | | summary: (6) merge two known; one immediate left, one far left
663 | | | |
663 | | | |
664 | o | | changeset: 5:4409d547b708
664 | o | | changeset: 5:4409d547b708
665 | |\ \ \ parent: 3:27eef8ed80b4
665 | |\ \ \ parent: 3:27eef8ed80b4
666 | | | | | parent: 4:26a8bac39d9f
666 | | | | | parent: 4:26a8bac39d9f
667 | | | | | user: test
667 | | | | | user: test
668 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
668 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
669 | | | | | summary: (5) expand
669 | | | | | summary: (5) expand
670 | | | | |
670 | | | | |
671 | | o | | changeset: 4:26a8bac39d9f
671 | | o | | changeset: 4:26a8bac39d9f
672 | |/|/ / parent: 1:6db2ef61d156
672 | |/|/ / parent: 1:6db2ef61d156
673 | | | | parent: 3:27eef8ed80b4
673 | | | | parent: 3:27eef8ed80b4
674 | | | | user: test
674 | | | | user: test
675 | | | | date: Thu Jan 01 00:00:04 1970 +0000
675 | | | | date: Thu Jan 01 00:00:04 1970 +0000
676 | | | | summary: (4) merge two known; one immediate left, one immediate right
676 | | | | summary: (4) merge two known; one immediate left, one immediate right
677 | | | |
677 | | | |
678 | o | | changeset: 3:27eef8ed80b4
678 | o | | changeset: 3:27eef8ed80b4
679 |/ / / user: test
679 |/ / / user: test
680 | | | date: Thu Jan 01 00:00:03 1970 +0000
680 | | | date: Thu Jan 01 00:00:03 1970 +0000
681 | | | summary: (3) collapse
681 | | | summary: (3) collapse
682 | | |
682 | | |
683 o | | changeset: 2:3d9a33b8d1e1
683 o | | changeset: 2:3d9a33b8d1e1
684 |/ / user: test
684 |/ / user: test
685 | | date: Thu Jan 01 00:00:02 1970 +0000
685 | | date: Thu Jan 01 00:00:02 1970 +0000
686 | | summary: (2) collapse
686 | | summary: (2) collapse
687 | |
687 | |
688 o | changeset: 1:6db2ef61d156
688 o | changeset: 1:6db2ef61d156
689 |/ user: test
689 |/ user: test
690 | date: Thu Jan 01 00:00:01 1970 +0000
690 | date: Thu Jan 01 00:00:01 1970 +0000
691 | summary: (1) collapse
691 | summary: (1) collapse
692 |
692 |
693 o changeset: 0:e6eb3150255d
693 o changeset: 0:e6eb3150255d
694 user: test
694 user: test
695 date: Thu Jan 01 00:00:00 1970 +0000
695 date: Thu Jan 01 00:00:00 1970 +0000
696 summary: (0) root
696 summary: (0) root
697
697
698
698
699 File glog per revset:
699 File glog per revset:
700
700
701 $ hg log -G -r 'file("a")'
701 $ hg log -G -r 'file("a")'
702 @ changeset: 34:fea3ac5810e0
702 @ changeset: 34:fea3ac5810e0
703 | tag: tip
703 | tag: tip
704 | parent: 32:d06dffa21a31
704 | parent: 32:d06dffa21a31
705 | user: test
705 | user: test
706 | date: Thu Jan 01 00:00:34 1970 +0000
706 | date: Thu Jan 01 00:00:34 1970 +0000
707 | summary: (34) head
707 | summary: (34) head
708 |
708 |
709 | o changeset: 33:68608f5145f9
709 | o changeset: 33:68608f5145f9
710 | | parent: 18:1aa84d96232a
710 | | parent: 18:1aa84d96232a
711 | | user: test
711 | | user: test
712 | | date: Thu Jan 01 00:00:33 1970 +0000
712 | | date: Thu Jan 01 00:00:33 1970 +0000
713 | | summary: (33) head
713 | | summary: (33) head
714 | |
714 | |
715 o | changeset: 32:d06dffa21a31
715 o | changeset: 32:d06dffa21a31
716 |\ \ parent: 27:886ed638191b
716 |\ \ parent: 27:886ed638191b
717 | | | parent: 31:621d83e11f67
717 | | | parent: 31:621d83e11f67
718 | | | user: test
718 | | | user: test
719 | | | date: Thu Jan 01 00:00:32 1970 +0000
719 | | | date: Thu Jan 01 00:00:32 1970 +0000
720 | | | summary: (32) expand
720 | | | summary: (32) expand
721 | | |
721 | | |
722 | o | changeset: 31:621d83e11f67
722 | o | changeset: 31:621d83e11f67
723 | |\ \ parent: 21:d42a756af44d
723 | |\ \ parent: 21:d42a756af44d
724 | | | | parent: 30:6e11cd4b648f
724 | | | | parent: 30:6e11cd4b648f
725 | | | | user: test
725 | | | | user: test
726 | | | | date: Thu Jan 01 00:00:31 1970 +0000
726 | | | | date: Thu Jan 01 00:00:31 1970 +0000
727 | | | | summary: (31) expand
727 | | | | summary: (31) expand
728 | | | |
728 | | | |
729 | | o | changeset: 30:6e11cd4b648f
729 | | o | changeset: 30:6e11cd4b648f
730 | | |\ \ parent: 28:44ecd0b9ae99
730 | | |\ \ parent: 28:44ecd0b9ae99
731 | | | | | parent: 29:cd9bb2be7593
731 | | | | | parent: 29:cd9bb2be7593
732 | | | | | user: test
732 | | | | | user: test
733 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
733 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
734 | | | | | summary: (30) expand
734 | | | | | summary: (30) expand
735 | | | | |
735 | | | | |
736 | | | o | changeset: 29:cd9bb2be7593
736 | | | o | changeset: 29:cd9bb2be7593
737 | | | | | parent: 0:e6eb3150255d
737 | | | | | parent: 0:e6eb3150255d
738 | | | | | user: test
738 | | | | | user: test
739 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
739 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
740 | | | | | summary: (29) regular commit
740 | | | | | summary: (29) regular commit
741 | | | | |
741 | | | | |
742 | | o | | changeset: 28:44ecd0b9ae99
742 | | o | | changeset: 28:44ecd0b9ae99
743 | | |\ \ \ parent: 1:6db2ef61d156
743 | | |\ \ \ parent: 1:6db2ef61d156
744 | | | | | | parent: 26:7f25b6c2f0b9
744 | | | | | | parent: 26:7f25b6c2f0b9
745 | | | | | | user: test
745 | | | | | | user: test
746 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
746 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
747 | | | | | | summary: (28) merge zero known
747 | | | | | | summary: (28) merge zero known
748 | | | | | |
748 | | | | | |
749 o | | | | | changeset: 27:886ed638191b
749 o | | | | | changeset: 27:886ed638191b
750 |/ / / / / parent: 21:d42a756af44d
750 |/ / / / / parent: 21:d42a756af44d
751 | | | | | user: test
751 | | | | | user: test
752 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
752 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
753 | | | | | summary: (27) collapse
753 | | | | | summary: (27) collapse
754 | | | | |
754 | | | | |
755 | | o---+ changeset: 26:7f25b6c2f0b9
755 | | o---+ changeset: 26:7f25b6c2f0b9
756 | | | | | parent: 18:1aa84d96232a
756 | | | | | parent: 18:1aa84d96232a
757 | | | | | parent: 25:91da8ed57247
757 | | | | | parent: 25:91da8ed57247
758 | | | | | user: test
758 | | | | | user: test
759 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
759 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
760 | | | | | summary: (26) merge one known; far right
760 | | | | | summary: (26) merge one known; far right
761 | | | | |
761 | | | | |
762 +---o | | changeset: 25:91da8ed57247
762 +---o | | changeset: 25:91da8ed57247
763 | | | | | parent: 21:d42a756af44d
763 | | | | | parent: 21:d42a756af44d
764 | | | | | parent: 24:a9c19a3d96b7
764 | | | | | parent: 24:a9c19a3d96b7
765 | | | | | user: test
765 | | | | | user: test
766 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
766 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
767 | | | | | summary: (25) merge one known; far left
767 | | | | | summary: (25) merge one known; far left
768 | | | | |
768 | | | | |
769 | | o | | changeset: 24:a9c19a3d96b7
769 | | o | | changeset: 24:a9c19a3d96b7
770 | | |\| | parent: 0:e6eb3150255d
770 | | |\| | parent: 0:e6eb3150255d
771 | | | | | parent: 23:a01cddf0766d
771 | | | | | parent: 23:a01cddf0766d
772 | | | | | user: test
772 | | | | | user: test
773 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
773 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
774 | | | | | summary: (24) merge one known; immediate right
774 | | | | | summary: (24) merge one known; immediate right
775 | | | | |
775 | | | | |
776 | | o | | changeset: 23:a01cddf0766d
776 | | o | | changeset: 23:a01cddf0766d
777 | |/| | | parent: 1:6db2ef61d156
777 | |/| | | parent: 1:6db2ef61d156
778 | | | | | parent: 22:e0d9cccacb5d
778 | | | | | parent: 22:e0d9cccacb5d
779 | | | | | user: test
779 | | | | | user: test
780 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
780 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
781 | | | | | summary: (23) merge one known; immediate left
781 | | | | | summary: (23) merge one known; immediate left
782 | | | | |
782 | | | | |
783 +---o---+ changeset: 22:e0d9cccacb5d
783 +---o---+ changeset: 22:e0d9cccacb5d
784 | | | | parent: 18:1aa84d96232a
784 | | | | parent: 18:1aa84d96232a
785 | | / / parent: 21:d42a756af44d
785 | | / / parent: 21:d42a756af44d
786 | | | | user: test
786 | | | | user: test
787 | | | | date: Thu Jan 01 00:00:22 1970 +0000
787 | | | | date: Thu Jan 01 00:00:22 1970 +0000
788 | | | | summary: (22) merge two known; one far left, one far right
788 | | | | summary: (22) merge two known; one far left, one far right
789 | | | |
789 | | | |
790 o | | | changeset: 21:d42a756af44d
790 o | | | changeset: 21:d42a756af44d
791 |\ \ \ \ parent: 19:31ddc2c1573b
791 |\ \ \ \ parent: 19:31ddc2c1573b
792 | | | | | parent: 20:d30ed6450e32
792 | | | | | parent: 20:d30ed6450e32
793 | | | | | user: test
793 | | | | | user: test
794 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
794 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
795 | | | | | summary: (21) expand
795 | | | | | summary: (21) expand
796 | | | | |
796 | | | | |
797 | o---+-+ changeset: 20:d30ed6450e32
797 | o---+-+ changeset: 20:d30ed6450e32
798 | | | | parent: 0:e6eb3150255d
798 | | | | parent: 0:e6eb3150255d
799 | / / / parent: 18:1aa84d96232a
799 | / / / parent: 18:1aa84d96232a
800 | | | | user: test
800 | | | | user: test
801 | | | | date: Thu Jan 01 00:00:20 1970 +0000
801 | | | | date: Thu Jan 01 00:00:20 1970 +0000
802 | | | | summary: (20) merge two known; two far right
802 | | | | summary: (20) merge two known; two far right
803 | | | |
803 | | | |
804 o | | | changeset: 19:31ddc2c1573b
804 o | | | changeset: 19:31ddc2c1573b
805 |\ \ \ \ parent: 15:1dda3f72782d
805 |\ \ \ \ parent: 15:1dda3f72782d
806 | | | | | parent: 17:44765d7c06e0
806 | | | | | parent: 17:44765d7c06e0
807 | | | | | user: test
807 | | | | | user: test
808 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
808 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
809 | | | | | summary: (19) expand
809 | | | | | summary: (19) expand
810 | | | | |
810 | | | | |
811 +---+---o changeset: 18:1aa84d96232a
811 +---+---o changeset: 18:1aa84d96232a
812 | | | | parent: 1:6db2ef61d156
812 | | | | parent: 1:6db2ef61d156
813 | | | | parent: 15:1dda3f72782d
813 | | | | parent: 15:1dda3f72782d
814 | | | | user: test
814 | | | | user: test
815 | | | | date: Thu Jan 01 00:00:18 1970 +0000
815 | | | | date: Thu Jan 01 00:00:18 1970 +0000
816 | | | | summary: (18) merge two known; two far left
816 | | | | summary: (18) merge two known; two far left
817 | | | |
817 | | | |
818 | o | | changeset: 17:44765d7c06e0
818 | o | | changeset: 17:44765d7c06e0
819 | |\ \ \ parent: 12:86b91144a6e9
819 | |\ \ \ parent: 12:86b91144a6e9
820 | | | | | parent: 16:3677d192927d
820 | | | | | parent: 16:3677d192927d
821 | | | | | user: test
821 | | | | | user: test
822 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
822 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
823 | | | | | summary: (17) expand
823 | | | | | summary: (17) expand
824 | | | | |
824 | | | | |
825 | | o---+ changeset: 16:3677d192927d
825 | | o---+ changeset: 16:3677d192927d
826 | | | | | parent: 0:e6eb3150255d
826 | | | | | parent: 0:e6eb3150255d
827 | | |/ / parent: 1:6db2ef61d156
827 | | |/ / parent: 1:6db2ef61d156
828 | | | | user: test
828 | | | | user: test
829 | | | | date: Thu Jan 01 00:00:16 1970 +0000
829 | | | | date: Thu Jan 01 00:00:16 1970 +0000
830 | | | | summary: (16) merge two known; one immediate right, one near right
830 | | | | summary: (16) merge two known; one immediate right, one near right
831 | | | |
831 | | | |
832 o | | | changeset: 15:1dda3f72782d
832 o | | | changeset: 15:1dda3f72782d
833 |\ \ \ \ parent: 13:22d8966a97e3
833 |\ \ \ \ parent: 13:22d8966a97e3
834 | | | | | parent: 14:8eac370358ef
834 | | | | | parent: 14:8eac370358ef
835 | | | | | user: test
835 | | | | | user: test
836 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
836 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
837 | | | | | summary: (15) expand
837 | | | | | summary: (15) expand
838 | | | | |
838 | | | | |
839 | o-----+ changeset: 14:8eac370358ef
839 | o-----+ changeset: 14:8eac370358ef
840 | | | | | parent: 0:e6eb3150255d
840 | | | | | parent: 0:e6eb3150255d
841 | |/ / / parent: 12:86b91144a6e9
841 | |/ / / parent: 12:86b91144a6e9
842 | | | | user: test
842 | | | | user: test
843 | | | | date: Thu Jan 01 00:00:14 1970 +0000
843 | | | | date: Thu Jan 01 00:00:14 1970 +0000
844 | | | | summary: (14) merge two known; one immediate right, one far right
844 | | | | summary: (14) merge two known; one immediate right, one far right
845 | | | |
845 | | | |
846 o | | | changeset: 13:22d8966a97e3
846 o | | | changeset: 13:22d8966a97e3
847 |\ \ \ \ parent: 9:7010c0af0a35
847 |\ \ \ \ parent: 9:7010c0af0a35
848 | | | | | parent: 11:832d76e6bdf2
848 | | | | | parent: 11:832d76e6bdf2
849 | | | | | user: test
849 | | | | | user: test
850 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
850 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
851 | | | | | summary: (13) expand
851 | | | | | summary: (13) expand
852 | | | | |
852 | | | | |
853 +---o | | changeset: 12:86b91144a6e9
853 +---o | | changeset: 12:86b91144a6e9
854 | | |/ / parent: 1:6db2ef61d156
854 | | |/ / parent: 1:6db2ef61d156
855 | | | | parent: 9:7010c0af0a35
855 | | | | parent: 9:7010c0af0a35
856 | | | | user: test
856 | | | | user: test
857 | | | | date: Thu Jan 01 00:00:12 1970 +0000
857 | | | | date: Thu Jan 01 00:00:12 1970 +0000
858 | | | | summary: (12) merge two known; one immediate right, one far left
858 | | | | summary: (12) merge two known; one immediate right, one far left
859 | | | |
859 | | | |
860 | o | | changeset: 11:832d76e6bdf2
860 | o | | changeset: 11:832d76e6bdf2
861 | |\ \ \ parent: 6:b105a072e251
861 | |\ \ \ parent: 6:b105a072e251
862 | | | | | parent: 10:74c64d036d72
862 | | | | | parent: 10:74c64d036d72
863 | | | | | user: test
863 | | | | | user: test
864 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
864 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
865 | | | | | summary: (11) expand
865 | | | | | summary: (11) expand
866 | | | | |
866 | | | | |
867 | | o---+ changeset: 10:74c64d036d72
867 | | o---+ changeset: 10:74c64d036d72
868 | | | | | parent: 0:e6eb3150255d
868 | | | | | parent: 0:e6eb3150255d
869 | |/ / / parent: 6:b105a072e251
869 | |/ / / parent: 6:b105a072e251
870 | | | | user: test
870 | | | | user: test
871 | | | | date: Thu Jan 01 00:00:10 1970 +0000
871 | | | | date: Thu Jan 01 00:00:10 1970 +0000
872 | | | | summary: (10) merge two known; one immediate left, one near right
872 | | | | summary: (10) merge two known; one immediate left, one near right
873 | | | |
873 | | | |
874 o | | | changeset: 9:7010c0af0a35
874 o | | | changeset: 9:7010c0af0a35
875 |\ \ \ \ parent: 7:b632bb1b1224
875 |\ \ \ \ parent: 7:b632bb1b1224
876 | | | | | parent: 8:7a0b11f71937
876 | | | | | parent: 8:7a0b11f71937
877 | | | | | user: test
877 | | | | | user: test
878 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
878 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
879 | | | | | summary: (9) expand
879 | | | | | summary: (9) expand
880 | | | | |
880 | | | | |
881 | o-----+ changeset: 8:7a0b11f71937
881 | o-----+ changeset: 8:7a0b11f71937
882 | | | | | parent: 0:e6eb3150255d
882 | | | | | parent: 0:e6eb3150255d
883 |/ / / / parent: 7:b632bb1b1224
883 |/ / / / parent: 7:b632bb1b1224
884 | | | | user: test
884 | | | | user: test
885 | | | | date: Thu Jan 01 00:00:08 1970 +0000
885 | | | | date: Thu Jan 01 00:00:08 1970 +0000
886 | | | | summary: (8) merge two known; one immediate left, one far right
886 | | | | summary: (8) merge two known; one immediate left, one far right
887 | | | |
887 | | | |
888 o | | | changeset: 7:b632bb1b1224
888 o | | | changeset: 7:b632bb1b1224
889 |\ \ \ \ parent: 2:3d9a33b8d1e1
889 |\ \ \ \ parent: 2:3d9a33b8d1e1
890 | | | | | parent: 5:4409d547b708
890 | | | | | parent: 5:4409d547b708
891 | | | | | user: test
891 | | | | | user: test
892 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
892 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
893 | | | | | summary: (7) expand
893 | | | | | summary: (7) expand
894 | | | | |
894 | | | | |
895 +---o | | changeset: 6:b105a072e251
895 +---o | | changeset: 6:b105a072e251
896 | |/ / / parent: 2:3d9a33b8d1e1
896 | |/ / / parent: 2:3d9a33b8d1e1
897 | | | | parent: 5:4409d547b708
897 | | | | parent: 5:4409d547b708
898 | | | | user: test
898 | | | | user: test
899 | | | | date: Thu Jan 01 00:00:06 1970 +0000
899 | | | | date: Thu Jan 01 00:00:06 1970 +0000
900 | | | | summary: (6) merge two known; one immediate left, one far left
900 | | | | summary: (6) merge two known; one immediate left, one far left
901 | | | |
901 | | | |
902 | o | | changeset: 5:4409d547b708
902 | o | | changeset: 5:4409d547b708
903 | |\ \ \ parent: 3:27eef8ed80b4
903 | |\ \ \ parent: 3:27eef8ed80b4
904 | | | | | parent: 4:26a8bac39d9f
904 | | | | | parent: 4:26a8bac39d9f
905 | | | | | user: test
905 | | | | | user: test
906 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
906 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
907 | | | | | summary: (5) expand
907 | | | | | summary: (5) expand
908 | | | | |
908 | | | | |
909 | | o | | changeset: 4:26a8bac39d9f
909 | | o | | changeset: 4:26a8bac39d9f
910 | |/|/ / parent: 1:6db2ef61d156
910 | |/|/ / parent: 1:6db2ef61d156
911 | | | | parent: 3:27eef8ed80b4
911 | | | | parent: 3:27eef8ed80b4
912 | | | | user: test
912 | | | | user: test
913 | | | | date: Thu Jan 01 00:00:04 1970 +0000
913 | | | | date: Thu Jan 01 00:00:04 1970 +0000
914 | | | | summary: (4) merge two known; one immediate left, one immediate right
914 | | | | summary: (4) merge two known; one immediate left, one immediate right
915 | | | |
915 | | | |
916 | o | | changeset: 3:27eef8ed80b4
916 | o | | changeset: 3:27eef8ed80b4
917 |/ / / user: test
917 |/ / / user: test
918 | | | date: Thu Jan 01 00:00:03 1970 +0000
918 | | | date: Thu Jan 01 00:00:03 1970 +0000
919 | | | summary: (3) collapse
919 | | | summary: (3) collapse
920 | | |
920 | | |
921 o | | changeset: 2:3d9a33b8d1e1
921 o | | changeset: 2:3d9a33b8d1e1
922 |/ / user: test
922 |/ / user: test
923 | | date: Thu Jan 01 00:00:02 1970 +0000
923 | | date: Thu Jan 01 00:00:02 1970 +0000
924 | | summary: (2) collapse
924 | | summary: (2) collapse
925 | |
925 | |
926 o | changeset: 1:6db2ef61d156
926 o | changeset: 1:6db2ef61d156
927 |/ user: test
927 |/ user: test
928 | date: Thu Jan 01 00:00:01 1970 +0000
928 | date: Thu Jan 01 00:00:01 1970 +0000
929 | summary: (1) collapse
929 | summary: (1) collapse
930 |
930 |
931 o changeset: 0:e6eb3150255d
931 o changeset: 0:e6eb3150255d
932 user: test
932 user: test
933 date: Thu Jan 01 00:00:00 1970 +0000
933 date: Thu Jan 01 00:00:00 1970 +0000
934 summary: (0) root
934 summary: (0) root
935
935
936
936
937
937
938 File glog per revset (only merges):
938 File glog per revset (only merges):
939
939
940 $ hg log -G -r 'file("a")' -m
940 $ hg log -G -r 'file("a")' -m
941 o changeset: 32:d06dffa21a31
941 o changeset: 32:d06dffa21a31
942 |\ parent: 27:886ed638191b
942 |\ parent: 27:886ed638191b
943 | : parent: 31:621d83e11f67
943 | : parent: 31:621d83e11f67
944 | : user: test
944 | : user: test
945 | : date: Thu Jan 01 00:00:32 1970 +0000
945 | : date: Thu Jan 01 00:00:32 1970 +0000
946 | : summary: (32) expand
946 | : summary: (32) expand
947 | :
947 | :
948 o : changeset: 31:621d83e11f67
948 o : changeset: 31:621d83e11f67
949 |\: parent: 21:d42a756af44d
949 |\: parent: 21:d42a756af44d
950 | : parent: 30:6e11cd4b648f
950 | : parent: 30:6e11cd4b648f
951 | : user: test
951 | : user: test
952 | : date: Thu Jan 01 00:00:31 1970 +0000
952 | : date: Thu Jan 01 00:00:31 1970 +0000
953 | : summary: (31) expand
953 | : summary: (31) expand
954 | :
954 | :
955 o : changeset: 30:6e11cd4b648f
955 o : changeset: 30:6e11cd4b648f
956 |\ \ parent: 28:44ecd0b9ae99
956 |\ \ parent: 28:44ecd0b9ae99
957 | ~ : parent: 29:cd9bb2be7593
957 | ~ : parent: 29:cd9bb2be7593
958 | : user: test
958 | : user: test
959 | : date: Thu Jan 01 00:00:30 1970 +0000
959 | : date: Thu Jan 01 00:00:30 1970 +0000
960 | : summary: (30) expand
960 | : summary: (30) expand
961 | /
961 | /
962 o : changeset: 28:44ecd0b9ae99
962 o : changeset: 28:44ecd0b9ae99
963 |\ \ parent: 1:6db2ef61d156
963 |\ \ parent: 1:6db2ef61d156
964 | ~ : parent: 26:7f25b6c2f0b9
964 | ~ : parent: 26:7f25b6c2f0b9
965 | : user: test
965 | : user: test
966 | : date: Thu Jan 01 00:00:28 1970 +0000
966 | : date: Thu Jan 01 00:00:28 1970 +0000
967 | : summary: (28) merge zero known
967 | : summary: (28) merge zero known
968 | /
968 | /
969 o : changeset: 26:7f25b6c2f0b9
969 o : changeset: 26:7f25b6c2f0b9
970 |\ \ parent: 18:1aa84d96232a
970 |\ \ parent: 18:1aa84d96232a
971 | | : parent: 25:91da8ed57247
971 | | : parent: 25:91da8ed57247
972 | | : user: test
972 | | : user: test
973 | | : date: Thu Jan 01 00:00:26 1970 +0000
973 | | : date: Thu Jan 01 00:00:26 1970 +0000
974 | | : summary: (26) merge one known; far right
974 | | : summary: (26) merge one known; far right
975 | | :
975 | | :
976 | o : changeset: 25:91da8ed57247
976 | o : changeset: 25:91da8ed57247
977 | |\: parent: 21:d42a756af44d
977 | |\: parent: 21:d42a756af44d
978 | | : parent: 24:a9c19a3d96b7
978 | | : parent: 24:a9c19a3d96b7
979 | | : user: test
979 | | : user: test
980 | | : date: Thu Jan 01 00:00:25 1970 +0000
980 | | : date: Thu Jan 01 00:00:25 1970 +0000
981 | | : summary: (25) merge one known; far left
981 | | : summary: (25) merge one known; far left
982 | | :
982 | | :
983 | o : changeset: 24:a9c19a3d96b7
983 | o : changeset: 24:a9c19a3d96b7
984 | |\ \ parent: 0:e6eb3150255d
984 | |\ \ parent: 0:e6eb3150255d
985 | | ~ : parent: 23:a01cddf0766d
985 | | ~ : parent: 23:a01cddf0766d
986 | | : user: test
986 | | : user: test
987 | | : date: Thu Jan 01 00:00:24 1970 +0000
987 | | : date: Thu Jan 01 00:00:24 1970 +0000
988 | | : summary: (24) merge one known; immediate right
988 | | : summary: (24) merge one known; immediate right
989 | | /
989 | | /
990 | o : changeset: 23:a01cddf0766d
990 | o : changeset: 23:a01cddf0766d
991 | |\ \ parent: 1:6db2ef61d156
991 | |\ \ parent: 1:6db2ef61d156
992 | | ~ : parent: 22:e0d9cccacb5d
992 | | ~ : parent: 22:e0d9cccacb5d
993 | | : user: test
993 | | : user: test
994 | | : date: Thu Jan 01 00:00:23 1970 +0000
994 | | : date: Thu Jan 01 00:00:23 1970 +0000
995 | | : summary: (23) merge one known; immediate left
995 | | : summary: (23) merge one known; immediate left
996 | | /
996 | | /
997 | o : changeset: 22:e0d9cccacb5d
997 | o : changeset: 22:e0d9cccacb5d
998 |/:/ parent: 18:1aa84d96232a
998 |/:/ parent: 18:1aa84d96232a
999 | : parent: 21:d42a756af44d
999 | : parent: 21:d42a756af44d
1000 | : user: test
1000 | : user: test
1001 | : date: Thu Jan 01 00:00:22 1970 +0000
1001 | : date: Thu Jan 01 00:00:22 1970 +0000
1002 | : summary: (22) merge two known; one far left, one far right
1002 | : summary: (22) merge two known; one far left, one far right
1003 | :
1003 | :
1004 | o changeset: 21:d42a756af44d
1004 | o changeset: 21:d42a756af44d
1005 | |\ parent: 19:31ddc2c1573b
1005 | |\ parent: 19:31ddc2c1573b
1006 | | | parent: 20:d30ed6450e32
1006 | | | parent: 20:d30ed6450e32
1007 | | | user: test
1007 | | | user: test
1008 | | | date: Thu Jan 01 00:00:21 1970 +0000
1008 | | | date: Thu Jan 01 00:00:21 1970 +0000
1009 | | | summary: (21) expand
1009 | | | summary: (21) expand
1010 | | |
1010 | | |
1011 +---o changeset: 20:d30ed6450e32
1011 +---o changeset: 20:d30ed6450e32
1012 | | | parent: 0:e6eb3150255d
1012 | | | parent: 0:e6eb3150255d
1013 | | ~ parent: 18:1aa84d96232a
1013 | | ~ parent: 18:1aa84d96232a
1014 | | user: test
1014 | | user: test
1015 | | date: Thu Jan 01 00:00:20 1970 +0000
1015 | | date: Thu Jan 01 00:00:20 1970 +0000
1016 | | summary: (20) merge two known; two far right
1016 | | summary: (20) merge two known; two far right
1017 | |
1017 | |
1018 | o changeset: 19:31ddc2c1573b
1018 | o changeset: 19:31ddc2c1573b
1019 | |\ parent: 15:1dda3f72782d
1019 | |\ parent: 15:1dda3f72782d
1020 | | | parent: 17:44765d7c06e0
1020 | | | parent: 17:44765d7c06e0
1021 | | | user: test
1021 | | | user: test
1022 | | | date: Thu Jan 01 00:00:19 1970 +0000
1022 | | | date: Thu Jan 01 00:00:19 1970 +0000
1023 | | | summary: (19) expand
1023 | | | summary: (19) expand
1024 | | |
1024 | | |
1025 o | | changeset: 18:1aa84d96232a
1025 o | | changeset: 18:1aa84d96232a
1026 |\| | parent: 1:6db2ef61d156
1026 |\| | parent: 1:6db2ef61d156
1027 ~ | | parent: 15:1dda3f72782d
1027 ~ | | parent: 15:1dda3f72782d
1028 | | user: test
1028 | | user: test
1029 | | date: Thu Jan 01 00:00:18 1970 +0000
1029 | | date: Thu Jan 01 00:00:18 1970 +0000
1030 | | summary: (18) merge two known; two far left
1030 | | summary: (18) merge two known; two far left
1031 / /
1031 / /
1032 | o changeset: 17:44765d7c06e0
1032 | o changeset: 17:44765d7c06e0
1033 | |\ parent: 12:86b91144a6e9
1033 | |\ parent: 12:86b91144a6e9
1034 | | | parent: 16:3677d192927d
1034 | | | parent: 16:3677d192927d
1035 | | | user: test
1035 | | | user: test
1036 | | | date: Thu Jan 01 00:00:17 1970 +0000
1036 | | | date: Thu Jan 01 00:00:17 1970 +0000
1037 | | | summary: (17) expand
1037 | | | summary: (17) expand
1038 | | |
1038 | | |
1039 | | o changeset: 16:3677d192927d
1039 | | o changeset: 16:3677d192927d
1040 | | |\ parent: 0:e6eb3150255d
1040 | | |\ parent: 0:e6eb3150255d
1041 | | ~ ~ parent: 1:6db2ef61d156
1041 | | ~ ~ parent: 1:6db2ef61d156
1042 | | user: test
1042 | | user: test
1043 | | date: Thu Jan 01 00:00:16 1970 +0000
1043 | | date: Thu Jan 01 00:00:16 1970 +0000
1044 | | summary: (16) merge two known; one immediate right, one near right
1044 | | summary: (16) merge two known; one immediate right, one near right
1045 | |
1045 | |
1046 o | changeset: 15:1dda3f72782d
1046 o | changeset: 15:1dda3f72782d
1047 |\ \ parent: 13:22d8966a97e3
1047 |\ \ parent: 13:22d8966a97e3
1048 | | | parent: 14:8eac370358ef
1048 | | | parent: 14:8eac370358ef
1049 | | | user: test
1049 | | | user: test
1050 | | | date: Thu Jan 01 00:00:15 1970 +0000
1050 | | | date: Thu Jan 01 00:00:15 1970 +0000
1051 | | | summary: (15) expand
1051 | | | summary: (15) expand
1052 | | |
1052 | | |
1053 | o | changeset: 14:8eac370358ef
1053 | o | changeset: 14:8eac370358ef
1054 | |\| parent: 0:e6eb3150255d
1054 | |\| parent: 0:e6eb3150255d
1055 | ~ | parent: 12:86b91144a6e9
1055 | ~ | parent: 12:86b91144a6e9
1056 | | user: test
1056 | | user: test
1057 | | date: Thu Jan 01 00:00:14 1970 +0000
1057 | | date: Thu Jan 01 00:00:14 1970 +0000
1058 | | summary: (14) merge two known; one immediate right, one far right
1058 | | summary: (14) merge two known; one immediate right, one far right
1059 | /
1059 | /
1060 o | changeset: 13:22d8966a97e3
1060 o | changeset: 13:22d8966a97e3
1061 |\ \ parent: 9:7010c0af0a35
1061 |\ \ parent: 9:7010c0af0a35
1062 | | | parent: 11:832d76e6bdf2
1062 | | | parent: 11:832d76e6bdf2
1063 | | | user: test
1063 | | | user: test
1064 | | | date: Thu Jan 01 00:00:13 1970 +0000
1064 | | | date: Thu Jan 01 00:00:13 1970 +0000
1065 | | | summary: (13) expand
1065 | | | summary: (13) expand
1066 | | |
1066 | | |
1067 +---o changeset: 12:86b91144a6e9
1067 +---o changeset: 12:86b91144a6e9
1068 | | | parent: 1:6db2ef61d156
1068 | | | parent: 1:6db2ef61d156
1069 | | ~ parent: 9:7010c0af0a35
1069 | | ~ parent: 9:7010c0af0a35
1070 | | user: test
1070 | | user: test
1071 | | date: Thu Jan 01 00:00:12 1970 +0000
1071 | | date: Thu Jan 01 00:00:12 1970 +0000
1072 | | summary: (12) merge two known; one immediate right, one far left
1072 | | summary: (12) merge two known; one immediate right, one far left
1073 | |
1073 | |
1074 | o changeset: 11:832d76e6bdf2
1074 | o changeset: 11:832d76e6bdf2
1075 | |\ parent: 6:b105a072e251
1075 | |\ parent: 6:b105a072e251
1076 | | | parent: 10:74c64d036d72
1076 | | | parent: 10:74c64d036d72
1077 | | | user: test
1077 | | | user: test
1078 | | | date: Thu Jan 01 00:00:11 1970 +0000
1078 | | | date: Thu Jan 01 00:00:11 1970 +0000
1079 | | | summary: (11) expand
1079 | | | summary: (11) expand
1080 | | |
1080 | | |
1081 | | o changeset: 10:74c64d036d72
1081 | | o changeset: 10:74c64d036d72
1082 | |/| parent: 0:e6eb3150255d
1082 | |/| parent: 0:e6eb3150255d
1083 | | ~ parent: 6:b105a072e251
1083 | | ~ parent: 6:b105a072e251
1084 | | user: test
1084 | | user: test
1085 | | date: Thu Jan 01 00:00:10 1970 +0000
1085 | | date: Thu Jan 01 00:00:10 1970 +0000
1086 | | summary: (10) merge two known; one immediate left, one near right
1086 | | summary: (10) merge two known; one immediate left, one near right
1087 | |
1087 | |
1088 o | changeset: 9:7010c0af0a35
1088 o | changeset: 9:7010c0af0a35
1089 |\ \ parent: 7:b632bb1b1224
1089 |\ \ parent: 7:b632bb1b1224
1090 | | | parent: 8:7a0b11f71937
1090 | | | parent: 8:7a0b11f71937
1091 | | | user: test
1091 | | | user: test
1092 | | | date: Thu Jan 01 00:00:09 1970 +0000
1092 | | | date: Thu Jan 01 00:00:09 1970 +0000
1093 | | | summary: (9) expand
1093 | | | summary: (9) expand
1094 | | |
1094 | | |
1095 | o | changeset: 8:7a0b11f71937
1095 | o | changeset: 8:7a0b11f71937
1096 |/| | parent: 0:e6eb3150255d
1096 |/| | parent: 0:e6eb3150255d
1097 | ~ | parent: 7:b632bb1b1224
1097 | ~ | parent: 7:b632bb1b1224
1098 | | user: test
1098 | | user: test
1099 | | date: Thu Jan 01 00:00:08 1970 +0000
1099 | | date: Thu Jan 01 00:00:08 1970 +0000
1100 | | summary: (8) merge two known; one immediate left, one far right
1100 | | summary: (8) merge two known; one immediate left, one far right
1101 | /
1101 | /
1102 o | changeset: 7:b632bb1b1224
1102 o | changeset: 7:b632bb1b1224
1103 |\ \ parent: 2:3d9a33b8d1e1
1103 |\ \ parent: 2:3d9a33b8d1e1
1104 | ~ | parent: 5:4409d547b708
1104 | ~ | parent: 5:4409d547b708
1105 | | user: test
1105 | | user: test
1106 | | date: Thu Jan 01 00:00:07 1970 +0000
1106 | | date: Thu Jan 01 00:00:07 1970 +0000
1107 | | summary: (7) expand
1107 | | summary: (7) expand
1108 | /
1108 | /
1109 | o changeset: 6:b105a072e251
1109 | o changeset: 6:b105a072e251
1110 |/| parent: 2:3d9a33b8d1e1
1110 |/| parent: 2:3d9a33b8d1e1
1111 | ~ parent: 5:4409d547b708
1111 | ~ parent: 5:4409d547b708
1112 | user: test
1112 | user: test
1113 | date: Thu Jan 01 00:00:06 1970 +0000
1113 | date: Thu Jan 01 00:00:06 1970 +0000
1114 | summary: (6) merge two known; one immediate left, one far left
1114 | summary: (6) merge two known; one immediate left, one far left
1115 |
1115 |
1116 o changeset: 5:4409d547b708
1116 o changeset: 5:4409d547b708
1117 |\ parent: 3:27eef8ed80b4
1117 |\ parent: 3:27eef8ed80b4
1118 | ~ parent: 4:26a8bac39d9f
1118 | ~ parent: 4:26a8bac39d9f
1119 | user: test
1119 | user: test
1120 | date: Thu Jan 01 00:00:05 1970 +0000
1120 | date: Thu Jan 01 00:00:05 1970 +0000
1121 | summary: (5) expand
1121 | summary: (5) expand
1122 |
1122 |
1123 o changeset: 4:26a8bac39d9f
1123 o changeset: 4:26a8bac39d9f
1124 |\ parent: 1:6db2ef61d156
1124 |\ parent: 1:6db2ef61d156
1125 ~ ~ parent: 3:27eef8ed80b4
1125 ~ ~ parent: 3:27eef8ed80b4
1126 user: test
1126 user: test
1127 date: Thu Jan 01 00:00:04 1970 +0000
1127 date: Thu Jan 01 00:00:04 1970 +0000
1128 summary: (4) merge two known; one immediate left, one immediate right
1128 summary: (4) merge two known; one immediate left, one immediate right
1129
1129
1130
1130
1131
1131
1132 Empty revision range - display nothing:
1132 Empty revision range - display nothing:
1133 $ hg log -G -r 1..0
1133 $ hg log -G -r 1..0
1134
1134
1135 $ cd ..
1135 $ cd ..
1136
1136
1137 #if no-outer-repo
1137 #if no-outer-repo
1138
1138
1139 From outer space:
1139 From outer space:
1140 $ hg log -G -l1 repo
1140 $ hg log -G -l1 repo
1141 @ changeset: 34:fea3ac5810e0
1141 @ changeset: 34:fea3ac5810e0
1142 | tag: tip
1142 | tag: tip
1143 ~ parent: 32:d06dffa21a31
1143 ~ parent: 32:d06dffa21a31
1144 user: test
1144 user: test
1145 date: Thu Jan 01 00:00:34 1970 +0000
1145 date: Thu Jan 01 00:00:34 1970 +0000
1146 summary: (34) head
1146 summary: (34) head
1147
1147
1148 $ hg log -G -l1 repo/a
1148 $ hg log -G -l1 repo/a
1149 @ changeset: 34:fea3ac5810e0
1149 @ changeset: 34:fea3ac5810e0
1150 | tag: tip
1150 | tag: tip
1151 ~ parent: 32:d06dffa21a31
1151 ~ parent: 32:d06dffa21a31
1152 user: test
1152 user: test
1153 date: Thu Jan 01 00:00:34 1970 +0000
1153 date: Thu Jan 01 00:00:34 1970 +0000
1154 summary: (34) head
1154 summary: (34) head
1155
1155
1156 $ hg log -G -l1 repo/missing
1156 $ hg log -G -l1 repo/missing
1157
1157
1158 #endif
1158 #endif
1159
1159
1160 File log with revs != cset revs:
1160 File log with revs != cset revs:
1161 $ hg init flog
1161 $ hg init flog
1162 $ cd flog
1162 $ cd flog
1163 $ echo one >one
1163 $ echo one >one
1164 $ hg add one
1164 $ hg add one
1165 $ hg commit -mone
1165 $ hg commit -mone
1166 $ echo two >two
1166 $ echo two >two
1167 $ hg add two
1167 $ hg add two
1168 $ hg commit -mtwo
1168 $ hg commit -mtwo
1169 $ echo more >two
1169 $ echo more >two
1170 $ hg commit -mmore
1170 $ hg commit -mmore
1171 $ hg log -G two
1171 $ hg log -G two
1172 @ changeset: 2:12c28321755b
1172 @ changeset: 2:12c28321755b
1173 | tag: tip
1173 | tag: tip
1174 | user: test
1174 | user: test
1175 | date: Thu Jan 01 00:00:00 1970 +0000
1175 | date: Thu Jan 01 00:00:00 1970 +0000
1176 | summary: more
1176 | summary: more
1177 |
1177 |
1178 o changeset: 1:5ac72c0599bf
1178 o changeset: 1:5ac72c0599bf
1179 | user: test
1179 | user: test
1180 ~ date: Thu Jan 01 00:00:00 1970 +0000
1180 ~ date: Thu Jan 01 00:00:00 1970 +0000
1181 summary: two
1181 summary: two
1182
1182
1183
1183
1184 Issue1896: File log with explicit style
1184 Issue1896: File log with explicit style
1185 $ hg log -G --style=default one
1185 $ hg log -G --style=default one
1186 o changeset: 0:3d578b4a1f53
1186 o changeset: 0:3d578b4a1f53
1187 user: test
1187 user: test
1188 date: Thu Jan 01 00:00:00 1970 +0000
1188 date: Thu Jan 01 00:00:00 1970 +0000
1189 summary: one
1189 summary: one
1190
1190
1191 Issue2395: glog --style header and footer
1191 Issue2395: glog --style header and footer
1192 $ hg log -G --style=xml one
1192 $ hg log -G --style=xml one
1193 <?xml version="1.0"?>
1193 <?xml version="1.0"?>
1194 <log>
1194 <log>
1195 o <logentry revision="0" node="3d578b4a1f537d5fcf7301bfa9c0b97adfaa6fb1">
1195 o <logentry revision="0" node="3d578b4a1f537d5fcf7301bfa9c0b97adfaa6fb1">
1196 <author email="test">test</author>
1196 <author email="test">test</author>
1197 <date>1970-01-01T00:00:00+00:00</date>
1197 <date>1970-01-01T00:00:00+00:00</date>
1198 <msg xml:space="preserve">one</msg>
1198 <msg xml:space="preserve">one</msg>
1199 </logentry>
1199 </logentry>
1200 </log>
1200 </log>
1201
1201
1202 $ cd ..
1202 $ cd ..
1203
1203
1204 Incoming and outgoing:
1204 Incoming and outgoing:
1205
1205
1206 $ hg clone -U -r31 repo repo2
1206 $ hg clone -U -r31 repo repo2
1207 adding changesets
1207 adding changesets
1208 adding manifests
1208 adding manifests
1209 adding file changes
1209 adding file changes
1210 added 31 changesets with 31 changes to 1 files
1210 added 31 changesets with 31 changes to 1 files
1211 $ cd repo2
1211 $ cd repo2
1212
1212
1213 $ hg incoming --graph ../repo
1213 $ hg incoming --graph ../repo
1214 comparing with ../repo
1214 comparing with ../repo
1215 searching for changes
1215 searching for changes
1216 o changeset: 34:fea3ac5810e0
1216 o changeset: 34:fea3ac5810e0
1217 | tag: tip
1217 | tag: tip
1218 | parent: 32:d06dffa21a31
1218 | parent: 32:d06dffa21a31
1219 | user: test
1219 | user: test
1220 | date: Thu Jan 01 00:00:34 1970 +0000
1220 | date: Thu Jan 01 00:00:34 1970 +0000
1221 | summary: (34) head
1221 | summary: (34) head
1222 |
1222 |
1223 | o changeset: 33:68608f5145f9
1223 | o changeset: 33:68608f5145f9
1224 | parent: 18:1aa84d96232a
1224 | parent: 18:1aa84d96232a
1225 | user: test
1225 | user: test
1226 | date: Thu Jan 01 00:00:33 1970 +0000
1226 | date: Thu Jan 01 00:00:33 1970 +0000
1227 | summary: (33) head
1227 | summary: (33) head
1228 |
1228 |
1229 o changeset: 32:d06dffa21a31
1229 o changeset: 32:d06dffa21a31
1230 | parent: 27:886ed638191b
1230 | parent: 27:886ed638191b
1231 | parent: 31:621d83e11f67
1231 | parent: 31:621d83e11f67
1232 | user: test
1232 | user: test
1233 | date: Thu Jan 01 00:00:32 1970 +0000
1233 | date: Thu Jan 01 00:00:32 1970 +0000
1234 | summary: (32) expand
1234 | summary: (32) expand
1235 |
1235 |
1236 o changeset: 27:886ed638191b
1236 o changeset: 27:886ed638191b
1237 parent: 21:d42a756af44d
1237 parent: 21:d42a756af44d
1238 user: test
1238 user: test
1239 date: Thu Jan 01 00:00:27 1970 +0000
1239 date: Thu Jan 01 00:00:27 1970 +0000
1240 summary: (27) collapse
1240 summary: (27) collapse
1241
1241
1242 $ cd ..
1242 $ cd ..
1243
1243
1244 $ hg -R repo outgoing --graph repo2
1244 $ hg -R repo outgoing --graph repo2
1245 comparing with repo2
1245 comparing with repo2
1246 searching for changes
1246 searching for changes
1247 @ changeset: 34:fea3ac5810e0
1247 @ changeset: 34:fea3ac5810e0
1248 | tag: tip
1248 | tag: tip
1249 | parent: 32:d06dffa21a31
1249 | parent: 32:d06dffa21a31
1250 | user: test
1250 | user: test
1251 | date: Thu Jan 01 00:00:34 1970 +0000
1251 | date: Thu Jan 01 00:00:34 1970 +0000
1252 | summary: (34) head
1252 | summary: (34) head
1253 |
1253 |
1254 | o changeset: 33:68608f5145f9
1254 | o changeset: 33:68608f5145f9
1255 | parent: 18:1aa84d96232a
1255 | parent: 18:1aa84d96232a
1256 | user: test
1256 | user: test
1257 | date: Thu Jan 01 00:00:33 1970 +0000
1257 | date: Thu Jan 01 00:00:33 1970 +0000
1258 | summary: (33) head
1258 | summary: (33) head
1259 |
1259 |
1260 o changeset: 32:d06dffa21a31
1260 o changeset: 32:d06dffa21a31
1261 | parent: 27:886ed638191b
1261 | parent: 27:886ed638191b
1262 | parent: 31:621d83e11f67
1262 | parent: 31:621d83e11f67
1263 | user: test
1263 | user: test
1264 | date: Thu Jan 01 00:00:32 1970 +0000
1264 | date: Thu Jan 01 00:00:32 1970 +0000
1265 | summary: (32) expand
1265 | summary: (32) expand
1266 |
1266 |
1267 o changeset: 27:886ed638191b
1267 o changeset: 27:886ed638191b
1268 parent: 21:d42a756af44d
1268 parent: 21:d42a756af44d
1269 user: test
1269 user: test
1270 date: Thu Jan 01 00:00:27 1970 +0000
1270 date: Thu Jan 01 00:00:27 1970 +0000
1271 summary: (27) collapse
1271 summary: (27) collapse
1272
1272
1273
1273
1274 File + limit with revs != cset revs:
1274 File + limit with revs != cset revs:
1275 $ cd repo
1275 $ cd repo
1276 $ touch b
1276 $ touch b
1277 $ hg ci -Aqm0
1277 $ hg ci -Aqm0
1278 $ hg log -G -l2 a
1278 $ hg log -G -l2 a
1279 o changeset: 34:fea3ac5810e0
1279 o changeset: 34:fea3ac5810e0
1280 | parent: 32:d06dffa21a31
1280 | parent: 32:d06dffa21a31
1281 ~ user: test
1281 ~ user: test
1282 date: Thu Jan 01 00:00:34 1970 +0000
1282 date: Thu Jan 01 00:00:34 1970 +0000
1283 summary: (34) head
1283 summary: (34) head
1284
1284
1285 o changeset: 33:68608f5145f9
1285 o changeset: 33:68608f5145f9
1286 | parent: 18:1aa84d96232a
1286 | parent: 18:1aa84d96232a
1287 ~ user: test
1287 ~ user: test
1288 date: Thu Jan 01 00:00:33 1970 +0000
1288 date: Thu Jan 01 00:00:33 1970 +0000
1289 summary: (33) head
1289 summary: (33) head
1290
1290
1291
1291
1292 File + limit + -ra:b, (b - a) < limit:
1292 File + limit + -ra:b, (b - a) < limit:
1293 $ hg log -G -l3000 -r32:tip a
1293 $ hg log -G -l3000 -r32:tip a
1294 o changeset: 34:fea3ac5810e0
1294 o changeset: 34:fea3ac5810e0
1295 | parent: 32:d06dffa21a31
1295 | parent: 32:d06dffa21a31
1296 | user: test
1296 | user: test
1297 | date: Thu Jan 01 00:00:34 1970 +0000
1297 | date: Thu Jan 01 00:00:34 1970 +0000
1298 | summary: (34) head
1298 | summary: (34) head
1299 |
1299 |
1300 | o changeset: 33:68608f5145f9
1300 | o changeset: 33:68608f5145f9
1301 | | parent: 18:1aa84d96232a
1301 | | parent: 18:1aa84d96232a
1302 | ~ user: test
1302 | ~ user: test
1303 | date: Thu Jan 01 00:00:33 1970 +0000
1303 | date: Thu Jan 01 00:00:33 1970 +0000
1304 | summary: (33) head
1304 | summary: (33) head
1305 |
1305 |
1306 o changeset: 32:d06dffa21a31
1306 o changeset: 32:d06dffa21a31
1307 |\ parent: 27:886ed638191b
1307 |\ parent: 27:886ed638191b
1308 ~ ~ parent: 31:621d83e11f67
1308 ~ ~ parent: 31:621d83e11f67
1309 user: test
1309 user: test
1310 date: Thu Jan 01 00:00:32 1970 +0000
1310 date: Thu Jan 01 00:00:32 1970 +0000
1311 summary: (32) expand
1311 summary: (32) expand
1312
1312
1313
1313
1314 Point out a common and an uncommon unshown parent
1314 Point out a common and an uncommon unshown parent
1315
1315
1316 $ hg log -G -r 'rev(8) or rev(9)'
1316 $ hg log -G -r 'rev(8) or rev(9)'
1317 o changeset: 9:7010c0af0a35
1317 o changeset: 9:7010c0af0a35
1318 |\ parent: 7:b632bb1b1224
1318 |\ parent: 7:b632bb1b1224
1319 | ~ parent: 8:7a0b11f71937
1319 | ~ parent: 8:7a0b11f71937
1320 | user: test
1320 | user: test
1321 | date: Thu Jan 01 00:00:09 1970 +0000
1321 | date: Thu Jan 01 00:00:09 1970 +0000
1322 | summary: (9) expand
1322 | summary: (9) expand
1323 |
1323 |
1324 o changeset: 8:7a0b11f71937
1324 o changeset: 8:7a0b11f71937
1325 |\ parent: 0:e6eb3150255d
1325 |\ parent: 0:e6eb3150255d
1326 ~ ~ parent: 7:b632bb1b1224
1326 ~ ~ parent: 7:b632bb1b1224
1327 user: test
1327 user: test
1328 date: Thu Jan 01 00:00:08 1970 +0000
1328 date: Thu Jan 01 00:00:08 1970 +0000
1329 summary: (8) merge two known; one immediate left, one far right
1329 summary: (8) merge two known; one immediate left, one far right
1330
1330
1331
1331
1332 File + limit + -ra:b, b < tip:
1332 File + limit + -ra:b, b < tip:
1333
1333
1334 $ hg log -G -l1 -r32:34 a
1334 $ hg log -G -l1 -r32:34 a
1335 o changeset: 34:fea3ac5810e0
1335 o changeset: 34:fea3ac5810e0
1336 | parent: 32:d06dffa21a31
1336 | parent: 32:d06dffa21a31
1337 ~ user: test
1337 ~ user: test
1338 date: Thu Jan 01 00:00:34 1970 +0000
1338 date: Thu Jan 01 00:00:34 1970 +0000
1339 summary: (34) head
1339 summary: (34) head
1340
1340
1341
1341
1342 file(File) + limit + -ra:b, b < tip:
1342 file(File) + limit + -ra:b, b < tip:
1343
1343
1344 $ hg log -G -l1 -r32:34 -r 'file("a")'
1344 $ hg log -G -l1 -r32:34 -r 'file("a")'
1345 o changeset: 34:fea3ac5810e0
1345 o changeset: 34:fea3ac5810e0
1346 | parent: 32:d06dffa21a31
1346 | parent: 32:d06dffa21a31
1347 ~ user: test
1347 ~ user: test
1348 date: Thu Jan 01 00:00:34 1970 +0000
1348 date: Thu Jan 01 00:00:34 1970 +0000
1349 summary: (34) head
1349 summary: (34) head
1350
1350
1351
1351
1352 limit(file(File) and a::b), b < tip:
1352 limit(file(File) and a::b), b < tip:
1353
1353
1354 $ hg log -G -r 'limit(file("a") and 32::34, 1)'
1354 $ hg log -G -r 'limit(file("a") and 32::34, 1)'
1355 o changeset: 32:d06dffa21a31
1355 o changeset: 32:d06dffa21a31
1356 |\ parent: 27:886ed638191b
1356 |\ parent: 27:886ed638191b
1357 ~ ~ parent: 31:621d83e11f67
1357 ~ ~ parent: 31:621d83e11f67
1358 user: test
1358 user: test
1359 date: Thu Jan 01 00:00:32 1970 +0000
1359 date: Thu Jan 01 00:00:32 1970 +0000
1360 summary: (32) expand
1360 summary: (32) expand
1361
1361
1362
1362
1363 File + limit + -ra:b, b < tip:
1363 File + limit + -ra:b, b < tip:
1364
1364
1365 $ hg log -G -r 'limit(file("a") and 34::32, 1)'
1365 $ hg log -G -r 'limit(file("a") and 34::32, 1)'
1366
1366
1367 File + limit + -ra:b, b < tip, (b - a) < limit:
1367 File + limit + -ra:b, b < tip, (b - a) < limit:
1368
1368
1369 $ hg log -G -l10 -r33:34 a
1369 $ hg log -G -l10 -r33:34 a
1370 o changeset: 34:fea3ac5810e0
1370 o changeset: 34:fea3ac5810e0
1371 | parent: 32:d06dffa21a31
1371 | parent: 32:d06dffa21a31
1372 ~ user: test
1372 ~ user: test
1373 date: Thu Jan 01 00:00:34 1970 +0000
1373 date: Thu Jan 01 00:00:34 1970 +0000
1374 summary: (34) head
1374 summary: (34) head
1375
1375
1376 o changeset: 33:68608f5145f9
1376 o changeset: 33:68608f5145f9
1377 | parent: 18:1aa84d96232a
1377 | parent: 18:1aa84d96232a
1378 ~ user: test
1378 ~ user: test
1379 date: Thu Jan 01 00:00:33 1970 +0000
1379 date: Thu Jan 01 00:00:33 1970 +0000
1380 summary: (33) head
1380 summary: (33) head
1381
1381
1382
1382
1383 Do not crash or produce strange graphs if history is buggy
1383 Do not crash or produce strange graphs if history is buggy
1384
1384
1385 $ hg branch branch
1385 $ hg branch branch
1386 marked working directory as branch branch
1386 marked working directory as branch branch
1387 (branches are permanent and global, did you want a bookmark?)
1387 (branches are permanent and global, did you want a bookmark?)
1388 $ commit 36 "buggy merge: identical parents" 35 35
1388 $ commit 36 "buggy merge: identical parents" 35 35
1389 $ hg log -G -l5
1389 $ hg log -G -l5
1390 @ changeset: 36:08a19a744424
1390 @ changeset: 36:08a19a744424
1391 | branch: branch
1391 | branch: branch
1392 | tag: tip
1392 | tag: tip
1393 | parent: 35:9159c3644c5e
1393 | parent: 35:9159c3644c5e
1394 | parent: 35:9159c3644c5e
1394 | parent: 35:9159c3644c5e
1395 | user: test
1395 | user: test
1396 | date: Thu Jan 01 00:00:36 1970 +0000
1396 | date: Thu Jan 01 00:00:36 1970 +0000
1397 | summary: (36) buggy merge: identical parents
1397 | summary: (36) buggy merge: identical parents
1398 |
1398 |
1399 o changeset: 35:9159c3644c5e
1399 o changeset: 35:9159c3644c5e
1400 | user: test
1400 | user: test
1401 | date: Thu Jan 01 00:00:00 1970 +0000
1401 | date: Thu Jan 01 00:00:00 1970 +0000
1402 | summary: 0
1402 | summary: 0
1403 |
1403 |
1404 o changeset: 34:fea3ac5810e0
1404 o changeset: 34:fea3ac5810e0
1405 | parent: 32:d06dffa21a31
1405 | parent: 32:d06dffa21a31
1406 | user: test
1406 | user: test
1407 | date: Thu Jan 01 00:00:34 1970 +0000
1407 | date: Thu Jan 01 00:00:34 1970 +0000
1408 | summary: (34) head
1408 | summary: (34) head
1409 |
1409 |
1410 | o changeset: 33:68608f5145f9
1410 | o changeset: 33:68608f5145f9
1411 | | parent: 18:1aa84d96232a
1411 | | parent: 18:1aa84d96232a
1412 | ~ user: test
1412 | ~ user: test
1413 | date: Thu Jan 01 00:00:33 1970 +0000
1413 | date: Thu Jan 01 00:00:33 1970 +0000
1414 | summary: (33) head
1414 | summary: (33) head
1415 |
1415 |
1416 o changeset: 32:d06dffa21a31
1416 o changeset: 32:d06dffa21a31
1417 |\ parent: 27:886ed638191b
1417 |\ parent: 27:886ed638191b
1418 ~ ~ parent: 31:621d83e11f67
1418 ~ ~ parent: 31:621d83e11f67
1419 user: test
1419 user: test
1420 date: Thu Jan 01 00:00:32 1970 +0000
1420 date: Thu Jan 01 00:00:32 1970 +0000
1421 summary: (32) expand
1421 summary: (32) expand
1422
1422
1423
1423
1424 Test log -G options
1424 Test log -G options
1425
1425
1426 $ testlog() {
1426 $ testlog() {
1427 > hg log -G --print-revset "$@"
1427 > hg log -G --print-revset "$@"
1428 > hg log --template 'nodetag {rev}\n' "$@" | grep nodetag \
1428 > hg log --template 'nodetag {rev}\n' "$@" | grep nodetag \
1429 > | sed 's/.*nodetag/nodetag/' > log.nodes
1429 > | sed 's/.*nodetag/nodetag/' > log.nodes
1430 > hg log -G --template 'nodetag {rev}\n' "$@" | grep nodetag \
1430 > hg log -G --template 'nodetag {rev}\n' "$@" | grep nodetag \
1431 > | sed 's/.*nodetag/nodetag/' > glog.nodes
1431 > | sed 's/.*nodetag/nodetag/' > glog.nodes
1432 > (cmp log.nodes glog.nodes || diff -u log.nodes glog.nodes) \
1432 > (cmp log.nodes glog.nodes || diff -u log.nodes glog.nodes) \
1433 > | grep '^[-+@ ]' || :
1433 > | grep '^[-+@ ]' || :
1434 > }
1434 > }
1435
1435
1436 glog always reorders nodes which explains the difference with log
1436 glog always reorders nodes which explains the difference with log
1437
1437
1438 $ testlog -r 27 -r 25 -r 21 -r 34 -r 32 -r 31
1438 $ testlog -r 27 -r 25 -r 21 -r 34 -r 32 -r 31
1439 ['27', '25', '21', '34', '32', '31']
1439 ['27', '25', '21', '34', '32', '31']
1440 []
1440 []
1441 --- log.nodes * (glob)
1441 --- log.nodes * (glob)
1442 +++ glog.nodes * (glob)
1442 +++ glog.nodes * (glob)
1443 @@ -1,6 +1,6 @@
1443 @@ -1,6 +1,6 @@
1444 -nodetag 27
1444 -nodetag 27
1445 -nodetag 25
1445 -nodetag 25
1446 -nodetag 21
1446 -nodetag 21
1447 nodetag 34
1447 nodetag 34
1448 nodetag 32
1448 nodetag 32
1449 nodetag 31
1449 nodetag 31
1450 +nodetag 27
1450 +nodetag 27
1451 +nodetag 25
1451 +nodetag 25
1452 +nodetag 21
1452 +nodetag 21
1453 $ testlog -u test -u not-a-user
1453 $ testlog -u test -u not-a-user
1454 []
1454 []
1455 (group
1455 (group
1456 (group
1456 (group
1457 (or
1457 (or
1458 (func
1458 (list
1459 ('symbol', 'user')
1459 (func
1460 ('string', 'test'))
1460 ('symbol', 'user')
1461 (func
1461 ('string', 'test'))
1462 ('symbol', 'user')
1462 (func
1463 ('string', 'not-a-user')))))
1463 ('symbol', 'user')
1464 ('string', 'not-a-user'))))))
1464 $ testlog -b not-a-branch
1465 $ testlog -b not-a-branch
1465 abort: unknown revision 'not-a-branch'!
1466 abort: unknown revision 'not-a-branch'!
1466 abort: unknown revision 'not-a-branch'!
1467 abort: unknown revision 'not-a-branch'!
1467 abort: unknown revision 'not-a-branch'!
1468 abort: unknown revision 'not-a-branch'!
1468 $ testlog -b 35 -b 36 --only-branch branch
1469 $ testlog -b 35 -b 36 --only-branch branch
1469 []
1470 []
1470 (group
1471 (group
1471 (group
1472 (group
1472 (or
1473 (or
1473 (func
1474 (list
1474 ('symbol', 'branch')
1475 (func
1475 ('string', 'default'))
1476 ('symbol', 'branch')
1476 (func
1477 ('string', 'default'))
1477 ('symbol', 'branch')
1478 (func
1478 ('string', 'branch'))
1479 ('symbol', 'branch')
1479 (func
1480 ('string', 'branch'))
1480 ('symbol', 'branch')
1481 (func
1481 ('string', 'branch')))))
1482 ('symbol', 'branch')
1483 ('string', 'branch'))))))
1482 $ testlog -k expand -k merge
1484 $ testlog -k expand -k merge
1483 []
1485 []
1484 (group
1486 (group
1485 (group
1487 (group
1486 (or
1488 (or
1487 (func
1489 (list
1488 ('symbol', 'keyword')
1490 (func
1489 ('string', 'expand'))
1491 ('symbol', 'keyword')
1490 (func
1492 ('string', 'expand'))
1491 ('symbol', 'keyword')
1493 (func
1492 ('string', 'merge')))))
1494 ('symbol', 'keyword')
1495 ('string', 'merge'))))))
1493 $ testlog --only-merges
1496 $ testlog --only-merges
1494 []
1497 []
1495 (group
1498 (group
1496 (func
1499 (func
1497 ('symbol', 'merge')
1500 ('symbol', 'merge')
1498 None))
1501 None))
1499 $ testlog --no-merges
1502 $ testlog --no-merges
1500 []
1503 []
1501 (group
1504 (group
1502 (not
1505 (not
1503 (func
1506 (func
1504 ('symbol', 'merge')
1507 ('symbol', 'merge')
1505 None)))
1508 None)))
1506 $ testlog --date '2 0 to 4 0'
1509 $ testlog --date '2 0 to 4 0'
1507 []
1510 []
1508 (group
1511 (group
1509 (func
1512 (func
1510 ('symbol', 'date')
1513 ('symbol', 'date')
1511 ('string', '2 0 to 4 0')))
1514 ('string', '2 0 to 4 0')))
1512 $ hg log -G -d 'brace ) in a date'
1515 $ hg log -G -d 'brace ) in a date'
1513 abort: invalid date: 'brace ) in a date'
1516 abort: invalid date: 'brace ) in a date'
1514 [255]
1517 [255]
1515 $ testlog --prune 31 --prune 32
1518 $ testlog --prune 31 --prune 32
1516 []
1519 []
1517 (group
1520 (group
1518 (group
1521 (group
1519 (and
1522 (and
1520 (not
1523 (not
1521 (group
1524 (group
1522 (or
1525 (or
1523 ('string', '31')
1526 (list
1524 (func
1527 ('string', '31')
1525 ('symbol', 'ancestors')
1528 (func
1526 ('string', '31')))))
1529 ('symbol', 'ancestors')
1530 ('string', '31'))))))
1527 (not
1531 (not
1528 (group
1532 (group
1529 (or
1533 (or
1530 ('string', '32')
1534 (list
1531 (func
1535 ('string', '32')
1532 ('symbol', 'ancestors')
1536 (func
1533 ('string', '32'))))))))
1537 ('symbol', 'ancestors')
1538 ('string', '32')))))))))
1534
1539
1535 Dedicated repo for --follow and paths filtering. The g is crafted to
1540 Dedicated repo for --follow and paths filtering. The g is crafted to
1536 have 2 filelog topological heads in a linear changeset graph.
1541 have 2 filelog topological heads in a linear changeset graph.
1537
1542
1538 $ cd ..
1543 $ cd ..
1539 $ hg init follow
1544 $ hg init follow
1540 $ cd follow
1545 $ cd follow
1541 $ testlog --follow
1546 $ testlog --follow
1542 []
1547 []
1543 []
1548 []
1544 $ testlog -rnull
1549 $ testlog -rnull
1545 ['null']
1550 ['null']
1546 []
1551 []
1547 $ echo a > a
1552 $ echo a > a
1548 $ echo aa > aa
1553 $ echo aa > aa
1549 $ echo f > f
1554 $ echo f > f
1550 $ hg ci -Am "add a" a aa f
1555 $ hg ci -Am "add a" a aa f
1551 $ hg cp a b
1556 $ hg cp a b
1552 $ hg cp f g
1557 $ hg cp f g
1553 $ hg ci -m "copy a b"
1558 $ hg ci -m "copy a b"
1554 $ mkdir dir
1559 $ mkdir dir
1555 $ hg mv b dir
1560 $ hg mv b dir
1556 $ echo g >> g
1561 $ echo g >> g
1557 $ echo f >> f
1562 $ echo f >> f
1558 $ hg ci -m "mv b dir/b"
1563 $ hg ci -m "mv b dir/b"
1559 $ hg mv a b
1564 $ hg mv a b
1560 $ hg cp -f f g
1565 $ hg cp -f f g
1561 $ echo a > d
1566 $ echo a > d
1562 $ hg add d
1567 $ hg add d
1563 $ hg ci -m "mv a b; add d"
1568 $ hg ci -m "mv a b; add d"
1564 $ hg mv dir/b e
1569 $ hg mv dir/b e
1565 $ hg ci -m "mv dir/b e"
1570 $ hg ci -m "mv dir/b e"
1566 $ hg log -G --template '({rev}) {desc|firstline}\n'
1571 $ hg log -G --template '({rev}) {desc|firstline}\n'
1567 @ (4) mv dir/b e
1572 @ (4) mv dir/b e
1568 |
1573 |
1569 o (3) mv a b; add d
1574 o (3) mv a b; add d
1570 |
1575 |
1571 o (2) mv b dir/b
1576 o (2) mv b dir/b
1572 |
1577 |
1573 o (1) copy a b
1578 o (1) copy a b
1574 |
1579 |
1575 o (0) add a
1580 o (0) add a
1576
1581
1577
1582
1578 $ testlog a
1583 $ testlog a
1579 []
1584 []
1580 (group
1585 (group
1581 (group
1586 (group
1582 (func
1587 (func
1583 ('symbol', 'filelog')
1588 ('symbol', 'filelog')
1584 ('string', 'a'))))
1589 ('string', 'a'))))
1585 $ testlog a b
1590 $ testlog a b
1586 []
1591 []
1587 (group
1592 (group
1588 (group
1593 (group
1589 (or
1594 (or
1590 (func
1595 (list
1591 ('symbol', 'filelog')
1596 (func
1592 ('string', 'a'))
1597 ('symbol', 'filelog')
1593 (func
1598 ('string', 'a'))
1594 ('symbol', 'filelog')
1599 (func
1595 ('string', 'b')))))
1600 ('symbol', 'filelog')
1601 ('string', 'b'))))))
1596
1602
1597 Test falling back to slow path for non-existing files
1603 Test falling back to slow path for non-existing files
1598
1604
1599 $ testlog a c
1605 $ testlog a c
1600 []
1606 []
1601 (group
1607 (group
1602 (func
1608 (func
1603 ('symbol', '_matchfiles')
1609 ('symbol', '_matchfiles')
1604 (list
1610 (list
1605 ('string', 'r:')
1611 ('string', 'r:')
1606 ('string', 'd:relpath')
1612 ('string', 'd:relpath')
1607 ('string', 'p:a')
1613 ('string', 'p:a')
1608 ('string', 'p:c'))))
1614 ('string', 'p:c'))))
1609
1615
1610 Test multiple --include/--exclude/paths
1616 Test multiple --include/--exclude/paths
1611
1617
1612 $ testlog --include a --include e --exclude b --exclude e a e
1618 $ testlog --include a --include e --exclude b --exclude e a e
1613 []
1619 []
1614 (group
1620 (group
1615 (func
1621 (func
1616 ('symbol', '_matchfiles')
1622 ('symbol', '_matchfiles')
1617 (list
1623 (list
1618 ('string', 'r:')
1624 ('string', 'r:')
1619 ('string', 'd:relpath')
1625 ('string', 'd:relpath')
1620 ('string', 'p:a')
1626 ('string', 'p:a')
1621 ('string', 'p:e')
1627 ('string', 'p:e')
1622 ('string', 'i:a')
1628 ('string', 'i:a')
1623 ('string', 'i:e')
1629 ('string', 'i:e')
1624 ('string', 'x:b')
1630 ('string', 'x:b')
1625 ('string', 'x:e'))))
1631 ('string', 'x:e'))))
1626
1632
1627 Test glob expansion of pats
1633 Test glob expansion of pats
1628
1634
1629 $ expandglobs=`$PYTHON -c "import mercurial.util; \
1635 $ expandglobs=`$PYTHON -c "import mercurial.util; \
1630 > print mercurial.util.expandglobs and 'true' or 'false'"`
1636 > print mercurial.util.expandglobs and 'true' or 'false'"`
1631 $ if [ $expandglobs = "true" ]; then
1637 $ if [ $expandglobs = "true" ]; then
1632 > testlog 'a*';
1638 > testlog 'a*';
1633 > else
1639 > else
1634 > testlog a*;
1640 > testlog a*;
1635 > fi;
1641 > fi;
1636 []
1642 []
1637 (group
1643 (group
1638 (group
1644 (group
1639 (func
1645 (func
1640 ('symbol', 'filelog')
1646 ('symbol', 'filelog')
1641 ('string', 'aa'))))
1647 ('string', 'aa'))))
1642
1648
1643 Test --follow on a non-existent directory
1649 Test --follow on a non-existent directory
1644
1650
1645 $ testlog -f dir
1651 $ testlog -f dir
1646 abort: cannot follow file not in parent revision: "dir"
1652 abort: cannot follow file not in parent revision: "dir"
1647 abort: cannot follow file not in parent revision: "dir"
1653 abort: cannot follow file not in parent revision: "dir"
1648 abort: cannot follow file not in parent revision: "dir"
1654 abort: cannot follow file not in parent revision: "dir"
1649
1655
1650 Test --follow on a directory
1656 Test --follow on a directory
1651
1657
1652 $ hg up -q '.^'
1658 $ hg up -q '.^'
1653 $ testlog -f dir
1659 $ testlog -f dir
1654 []
1660 []
1655 (group
1661 (group
1656 (and
1662 (and
1657 (func
1663 (func
1658 ('symbol', 'ancestors')
1664 ('symbol', 'ancestors')
1659 ('symbol', '.'))
1665 ('symbol', '.'))
1660 (func
1666 (func
1661 ('symbol', '_matchfiles')
1667 ('symbol', '_matchfiles')
1662 (list
1668 (list
1663 ('string', 'r:')
1669 ('string', 'r:')
1664 ('string', 'd:relpath')
1670 ('string', 'd:relpath')
1665 ('string', 'p:dir')))))
1671 ('string', 'p:dir')))))
1666 $ hg up -q tip
1672 $ hg up -q tip
1667
1673
1668 Test --follow on file not in parent revision
1674 Test --follow on file not in parent revision
1669
1675
1670 $ testlog -f a
1676 $ testlog -f a
1671 abort: cannot follow file not in parent revision: "a"
1677 abort: cannot follow file not in parent revision: "a"
1672 abort: cannot follow file not in parent revision: "a"
1678 abort: cannot follow file not in parent revision: "a"
1673 abort: cannot follow file not in parent revision: "a"
1679 abort: cannot follow file not in parent revision: "a"
1674
1680
1675 Test --follow and patterns
1681 Test --follow and patterns
1676
1682
1677 $ testlog -f 'glob:*'
1683 $ testlog -f 'glob:*'
1678 []
1684 []
1679 (group
1685 (group
1680 (and
1686 (and
1681 (func
1687 (func
1682 ('symbol', 'ancestors')
1688 ('symbol', 'ancestors')
1683 ('symbol', '.'))
1689 ('symbol', '.'))
1684 (func
1690 (func
1685 ('symbol', '_matchfiles')
1691 ('symbol', '_matchfiles')
1686 (list
1692 (list
1687 ('string', 'r:')
1693 ('string', 'r:')
1688 ('string', 'd:relpath')
1694 ('string', 'd:relpath')
1689 ('string', 'p:glob:*')))))
1695 ('string', 'p:glob:*')))))
1690
1696
1691 Test --follow on a single rename
1697 Test --follow on a single rename
1692
1698
1693 $ hg up -q 2
1699 $ hg up -q 2
1694 $ testlog -f a
1700 $ testlog -f a
1695 []
1701 []
1696 (group
1702 (group
1697 (group
1703 (group
1698 (func
1704 (func
1699 ('symbol', 'follow')
1705 ('symbol', 'follow')
1700 ('string', 'a'))))
1706 ('string', 'a'))))
1701
1707
1702 Test --follow and multiple renames
1708 Test --follow and multiple renames
1703
1709
1704 $ hg up -q tip
1710 $ hg up -q tip
1705 $ testlog -f e
1711 $ testlog -f e
1706 []
1712 []
1707 (group
1713 (group
1708 (group
1714 (group
1709 (func
1715 (func
1710 ('symbol', 'follow')
1716 ('symbol', 'follow')
1711 ('string', 'e'))))
1717 ('string', 'e'))))
1712
1718
1713 Test --follow and multiple filelog heads
1719 Test --follow and multiple filelog heads
1714
1720
1715 $ hg up -q 2
1721 $ hg up -q 2
1716 $ testlog -f g
1722 $ testlog -f g
1717 []
1723 []
1718 (group
1724 (group
1719 (group
1725 (group
1720 (func
1726 (func
1721 ('symbol', 'follow')
1727 ('symbol', 'follow')
1722 ('string', 'g'))))
1728 ('string', 'g'))))
1723 $ cat log.nodes
1729 $ cat log.nodes
1724 nodetag 2
1730 nodetag 2
1725 nodetag 1
1731 nodetag 1
1726 nodetag 0
1732 nodetag 0
1727 $ hg up -q tip
1733 $ hg up -q tip
1728 $ testlog -f g
1734 $ testlog -f g
1729 []
1735 []
1730 (group
1736 (group
1731 (group
1737 (group
1732 (func
1738 (func
1733 ('symbol', 'follow')
1739 ('symbol', 'follow')
1734 ('string', 'g'))))
1740 ('string', 'g'))))
1735 $ cat log.nodes
1741 $ cat log.nodes
1736 nodetag 3
1742 nodetag 3
1737 nodetag 2
1743 nodetag 2
1738 nodetag 0
1744 nodetag 0
1739
1745
1740 Test --follow and multiple files
1746 Test --follow and multiple files
1741
1747
1742 $ testlog -f g e
1748 $ testlog -f g e
1743 []
1749 []
1744 (group
1750 (group
1745 (group
1751 (group
1746 (or
1752 (or
1747 (func
1753 (list
1748 ('symbol', 'follow')
1754 (func
1749 ('string', 'g'))
1755 ('symbol', 'follow')
1750 (func
1756 ('string', 'g'))
1751 ('symbol', 'follow')
1757 (func
1752 ('string', 'e')))))
1758 ('symbol', 'follow')
1759 ('string', 'e'))))))
1753 $ cat log.nodes
1760 $ cat log.nodes
1754 nodetag 4
1761 nodetag 4
1755 nodetag 3
1762 nodetag 3
1756 nodetag 2
1763 nodetag 2
1757 nodetag 1
1764 nodetag 1
1758 nodetag 0
1765 nodetag 0
1759
1766
1760 Test --follow null parent
1767 Test --follow null parent
1761
1768
1762 $ hg up -q null
1769 $ hg up -q null
1763 $ testlog -f
1770 $ testlog -f
1764 []
1771 []
1765 []
1772 []
1766
1773
1767 Test --follow-first
1774 Test --follow-first
1768
1775
1769 $ hg up -q 3
1776 $ hg up -q 3
1770 $ echo ee > e
1777 $ echo ee > e
1771 $ hg ci -Am "add another e" e
1778 $ hg ci -Am "add another e" e
1772 created new head
1779 created new head
1773 $ hg merge --tool internal:other 4
1780 $ hg merge --tool internal:other 4
1774 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
1781 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
1775 (branch merge, don't forget to commit)
1782 (branch merge, don't forget to commit)
1776 $ echo merge > e
1783 $ echo merge > e
1777 $ hg ci -m "merge 5 and 4"
1784 $ hg ci -m "merge 5 and 4"
1778 $ testlog --follow-first
1785 $ testlog --follow-first
1779 []
1786 []
1780 (group
1787 (group
1781 (func
1788 (func
1782 ('symbol', '_firstancestors')
1789 ('symbol', '_firstancestors')
1783 (func
1790 (func
1784 ('symbol', 'rev')
1791 ('symbol', 'rev')
1785 ('symbol', '6'))))
1792 ('symbol', '6'))))
1786
1793
1787 Cannot compare with log --follow-first FILE as it never worked
1794 Cannot compare with log --follow-first FILE as it never worked
1788
1795
1789 $ hg log -G --print-revset --follow-first e
1796 $ hg log -G --print-revset --follow-first e
1790 []
1797 []
1791 (group
1798 (group
1792 (group
1799 (group
1793 (func
1800 (func
1794 ('symbol', '_followfirst')
1801 ('symbol', '_followfirst')
1795 ('string', 'e'))))
1802 ('string', 'e'))))
1796 $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n'
1803 $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n'
1797 @ 6 merge 5 and 4
1804 @ 6 merge 5 and 4
1798 |\
1805 |\
1799 | ~
1806 | ~
1800 o 5 add another e
1807 o 5 add another e
1801 |
1808 |
1802 ~
1809 ~
1803
1810
1804 Test --copies
1811 Test --copies
1805
1812
1806 $ hg log -G --copies --template "{rev} {desc|firstline} \
1813 $ hg log -G --copies --template "{rev} {desc|firstline} \
1807 > copies: {file_copies_switch}\n"
1814 > copies: {file_copies_switch}\n"
1808 @ 6 merge 5 and 4 copies:
1815 @ 6 merge 5 and 4 copies:
1809 |\
1816 |\
1810 | o 5 add another e copies:
1817 | o 5 add another e copies:
1811 | |
1818 | |
1812 o | 4 mv dir/b e copies: e (dir/b)
1819 o | 4 mv dir/b e copies: e (dir/b)
1813 |/
1820 |/
1814 o 3 mv a b; add d copies: b (a)g (f)
1821 o 3 mv a b; add d copies: b (a)g (f)
1815 |
1822 |
1816 o 2 mv b dir/b copies: dir/b (b)
1823 o 2 mv b dir/b copies: dir/b (b)
1817 |
1824 |
1818 o 1 copy a b copies: b (a)g (f)
1825 o 1 copy a b copies: b (a)g (f)
1819 |
1826 |
1820 o 0 add a copies:
1827 o 0 add a copies:
1821
1828
1822 Test "set:..." and parent revision
1829 Test "set:..." and parent revision
1823
1830
1824 $ hg up -q 4
1831 $ hg up -q 4
1825 $ testlog "set:copied()"
1832 $ testlog "set:copied()"
1826 []
1833 []
1827 (group
1834 (group
1828 (func
1835 (func
1829 ('symbol', '_matchfiles')
1836 ('symbol', '_matchfiles')
1830 (list
1837 (list
1831 ('string', 'r:')
1838 ('string', 'r:')
1832 ('string', 'd:relpath')
1839 ('string', 'd:relpath')
1833 ('string', 'p:set:copied()'))))
1840 ('string', 'p:set:copied()'))))
1834 $ testlog --include "set:copied()"
1841 $ testlog --include "set:copied()"
1835 []
1842 []
1836 (group
1843 (group
1837 (func
1844 (func
1838 ('symbol', '_matchfiles')
1845 ('symbol', '_matchfiles')
1839 (list
1846 (list
1840 ('string', 'r:')
1847 ('string', 'r:')
1841 ('string', 'd:relpath')
1848 ('string', 'd:relpath')
1842 ('string', 'i:set:copied()'))))
1849 ('string', 'i:set:copied()'))))
1843 $ testlog -r "sort(file('set:copied()'), -rev)"
1850 $ testlog -r "sort(file('set:copied()'), -rev)"
1844 ["sort(file('set:copied()'), -rev)"]
1851 ["sort(file('set:copied()'), -rev)"]
1845 []
1852 []
1846
1853
1847 Test --removed
1854 Test --removed
1848
1855
1849 $ testlog --removed
1856 $ testlog --removed
1850 []
1857 []
1851 []
1858 []
1852 $ testlog --removed a
1859 $ testlog --removed a
1853 []
1860 []
1854 (group
1861 (group
1855 (func
1862 (func
1856 ('symbol', '_matchfiles')
1863 ('symbol', '_matchfiles')
1857 (list
1864 (list
1858 ('string', 'r:')
1865 ('string', 'r:')
1859 ('string', 'd:relpath')
1866 ('string', 'd:relpath')
1860 ('string', 'p:a'))))
1867 ('string', 'p:a'))))
1861 $ testlog --removed --follow a
1868 $ testlog --removed --follow a
1862 []
1869 []
1863 (group
1870 (group
1864 (and
1871 (and
1865 (func
1872 (func
1866 ('symbol', 'ancestors')
1873 ('symbol', 'ancestors')
1867 ('symbol', '.'))
1874 ('symbol', '.'))
1868 (func
1875 (func
1869 ('symbol', '_matchfiles')
1876 ('symbol', '_matchfiles')
1870 (list
1877 (list
1871 ('string', 'r:')
1878 ('string', 'r:')
1872 ('string', 'd:relpath')
1879 ('string', 'd:relpath')
1873 ('string', 'p:a')))))
1880 ('string', 'p:a')))))
1874
1881
1875 Test --patch and --stat with --follow and --follow-first
1882 Test --patch and --stat with --follow and --follow-first
1876
1883
1877 $ hg up -q 3
1884 $ hg up -q 3
1878 $ hg log -G --git --patch b
1885 $ hg log -G --git --patch b
1879 o changeset: 1:216d4c92cf98
1886 o changeset: 1:216d4c92cf98
1880 | user: test
1887 | user: test
1881 ~ date: Thu Jan 01 00:00:00 1970 +0000
1888 ~ date: Thu Jan 01 00:00:00 1970 +0000
1882 summary: copy a b
1889 summary: copy a b
1883
1890
1884 diff --git a/a b/b
1891 diff --git a/a b/b
1885 copy from a
1892 copy from a
1886 copy to b
1893 copy to b
1887
1894
1888
1895
1889 $ hg log -G --git --stat b
1896 $ hg log -G --git --stat b
1890 o changeset: 1:216d4c92cf98
1897 o changeset: 1:216d4c92cf98
1891 | user: test
1898 | user: test
1892 ~ date: Thu Jan 01 00:00:00 1970 +0000
1899 ~ date: Thu Jan 01 00:00:00 1970 +0000
1893 summary: copy a b
1900 summary: copy a b
1894
1901
1895 b | 0
1902 b | 0
1896 1 files changed, 0 insertions(+), 0 deletions(-)
1903 1 files changed, 0 insertions(+), 0 deletions(-)
1897
1904
1898
1905
1899 $ hg log -G --git --patch --follow b
1906 $ hg log -G --git --patch --follow b
1900 o changeset: 1:216d4c92cf98
1907 o changeset: 1:216d4c92cf98
1901 | user: test
1908 | user: test
1902 | date: Thu Jan 01 00:00:00 1970 +0000
1909 | date: Thu Jan 01 00:00:00 1970 +0000
1903 | summary: copy a b
1910 | summary: copy a b
1904 |
1911 |
1905 | diff --git a/a b/b
1912 | diff --git a/a b/b
1906 | copy from a
1913 | copy from a
1907 | copy to b
1914 | copy to b
1908 |
1915 |
1909 o changeset: 0:f8035bb17114
1916 o changeset: 0:f8035bb17114
1910 user: test
1917 user: test
1911 date: Thu Jan 01 00:00:00 1970 +0000
1918 date: Thu Jan 01 00:00:00 1970 +0000
1912 summary: add a
1919 summary: add a
1913
1920
1914 diff --git a/a b/a
1921 diff --git a/a b/a
1915 new file mode 100644
1922 new file mode 100644
1916 --- /dev/null
1923 --- /dev/null
1917 +++ b/a
1924 +++ b/a
1918 @@ -0,0 +1,1 @@
1925 @@ -0,0 +1,1 @@
1919 +a
1926 +a
1920
1927
1921
1928
1922 $ hg log -G --git --stat --follow b
1929 $ hg log -G --git --stat --follow b
1923 o changeset: 1:216d4c92cf98
1930 o changeset: 1:216d4c92cf98
1924 | user: test
1931 | user: test
1925 | date: Thu Jan 01 00:00:00 1970 +0000
1932 | date: Thu Jan 01 00:00:00 1970 +0000
1926 | summary: copy a b
1933 | summary: copy a b
1927 |
1934 |
1928 | b | 0
1935 | b | 0
1929 | 1 files changed, 0 insertions(+), 0 deletions(-)
1936 | 1 files changed, 0 insertions(+), 0 deletions(-)
1930 |
1937 |
1931 o changeset: 0:f8035bb17114
1938 o changeset: 0:f8035bb17114
1932 user: test
1939 user: test
1933 date: Thu Jan 01 00:00:00 1970 +0000
1940 date: Thu Jan 01 00:00:00 1970 +0000
1934 summary: add a
1941 summary: add a
1935
1942
1936 a | 1 +
1943 a | 1 +
1937 1 files changed, 1 insertions(+), 0 deletions(-)
1944 1 files changed, 1 insertions(+), 0 deletions(-)
1938
1945
1939
1946
1940 $ hg up -q 6
1947 $ hg up -q 6
1941 $ hg log -G --git --patch --follow-first e
1948 $ hg log -G --git --patch --follow-first e
1942 @ changeset: 6:fc281d8ff18d
1949 @ changeset: 6:fc281d8ff18d
1943 |\ tag: tip
1950 |\ tag: tip
1944 | ~ parent: 5:99b31f1c2782
1951 | ~ parent: 5:99b31f1c2782
1945 | parent: 4:17d952250a9d
1952 | parent: 4:17d952250a9d
1946 | user: test
1953 | user: test
1947 | date: Thu Jan 01 00:00:00 1970 +0000
1954 | date: Thu Jan 01 00:00:00 1970 +0000
1948 | summary: merge 5 and 4
1955 | summary: merge 5 and 4
1949 |
1956 |
1950 | diff --git a/e b/e
1957 | diff --git a/e b/e
1951 | --- a/e
1958 | --- a/e
1952 | +++ b/e
1959 | +++ b/e
1953 | @@ -1,1 +1,1 @@
1960 | @@ -1,1 +1,1 @@
1954 | -ee
1961 | -ee
1955 | +merge
1962 | +merge
1956 |
1963 |
1957 o changeset: 5:99b31f1c2782
1964 o changeset: 5:99b31f1c2782
1958 | parent: 3:5918b8d165d1
1965 | parent: 3:5918b8d165d1
1959 ~ user: test
1966 ~ user: test
1960 date: Thu Jan 01 00:00:00 1970 +0000
1967 date: Thu Jan 01 00:00:00 1970 +0000
1961 summary: add another e
1968 summary: add another e
1962
1969
1963 diff --git a/e b/e
1970 diff --git a/e b/e
1964 new file mode 100644
1971 new file mode 100644
1965 --- /dev/null
1972 --- /dev/null
1966 +++ b/e
1973 +++ b/e
1967 @@ -0,0 +1,1 @@
1974 @@ -0,0 +1,1 @@
1968 +ee
1975 +ee
1969
1976
1970
1977
1971 Test old-style --rev
1978 Test old-style --rev
1972
1979
1973 $ hg tag 'foo-bar'
1980 $ hg tag 'foo-bar'
1974 $ testlog -r 'foo-bar'
1981 $ testlog -r 'foo-bar'
1975 ['foo-bar']
1982 ['foo-bar']
1976 []
1983 []
1977
1984
1978 Test --follow and forward --rev
1985 Test --follow and forward --rev
1979
1986
1980 $ hg up -q 6
1987 $ hg up -q 6
1981 $ echo g > g
1988 $ echo g > g
1982 $ hg ci -Am 'add g' g
1989 $ hg ci -Am 'add g' g
1983 created new head
1990 created new head
1984 $ hg up -q 2
1991 $ hg up -q 2
1985 $ hg log -G --template "{rev} {desc|firstline}\n"
1992 $ hg log -G --template "{rev} {desc|firstline}\n"
1986 o 8 add g
1993 o 8 add g
1987 |
1994 |
1988 | o 7 Added tag foo-bar for changeset fc281d8ff18d
1995 | o 7 Added tag foo-bar for changeset fc281d8ff18d
1989 |/
1996 |/
1990 o 6 merge 5 and 4
1997 o 6 merge 5 and 4
1991 |\
1998 |\
1992 | o 5 add another e
1999 | o 5 add another e
1993 | |
2000 | |
1994 o | 4 mv dir/b e
2001 o | 4 mv dir/b e
1995 |/
2002 |/
1996 o 3 mv a b; add d
2003 o 3 mv a b; add d
1997 |
2004 |
1998 @ 2 mv b dir/b
2005 @ 2 mv b dir/b
1999 |
2006 |
2000 o 1 copy a b
2007 o 1 copy a b
2001 |
2008 |
2002 o 0 add a
2009 o 0 add a
2003
2010
2004 $ hg archive -r 7 archive
2011 $ hg archive -r 7 archive
2005 $ grep changessincelatesttag archive/.hg_archival.txt
2012 $ grep changessincelatesttag archive/.hg_archival.txt
2006 changessincelatesttag: 1
2013 changessincelatesttag: 1
2007 $ rm -r archive
2014 $ rm -r archive
2008
2015
2009 changessincelatesttag with no prior tag
2016 changessincelatesttag with no prior tag
2010 $ hg archive -r 4 archive
2017 $ hg archive -r 4 archive
2011 $ grep changessincelatesttag archive/.hg_archival.txt
2018 $ grep changessincelatesttag archive/.hg_archival.txt
2012 changessincelatesttag: 5
2019 changessincelatesttag: 5
2013
2020
2014 $ hg export 'all()'
2021 $ hg export 'all()'
2015 # HG changeset patch
2022 # HG changeset patch
2016 # User test
2023 # User test
2017 # Date 0 0
2024 # Date 0 0
2018 # Thu Jan 01 00:00:00 1970 +0000
2025 # Thu Jan 01 00:00:00 1970 +0000
2019 # Node ID f8035bb17114da16215af3436ec5222428ace8ee
2026 # Node ID f8035bb17114da16215af3436ec5222428ace8ee
2020 # Parent 0000000000000000000000000000000000000000
2027 # Parent 0000000000000000000000000000000000000000
2021 add a
2028 add a
2022
2029
2023 diff -r 000000000000 -r f8035bb17114 a
2030 diff -r 000000000000 -r f8035bb17114 a
2024 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2031 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2025 +++ b/a Thu Jan 01 00:00:00 1970 +0000
2032 +++ b/a Thu Jan 01 00:00:00 1970 +0000
2026 @@ -0,0 +1,1 @@
2033 @@ -0,0 +1,1 @@
2027 +a
2034 +a
2028 diff -r 000000000000 -r f8035bb17114 aa
2035 diff -r 000000000000 -r f8035bb17114 aa
2029 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2036 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2030 +++ b/aa Thu Jan 01 00:00:00 1970 +0000
2037 +++ b/aa Thu Jan 01 00:00:00 1970 +0000
2031 @@ -0,0 +1,1 @@
2038 @@ -0,0 +1,1 @@
2032 +aa
2039 +aa
2033 diff -r 000000000000 -r f8035bb17114 f
2040 diff -r 000000000000 -r f8035bb17114 f
2034 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2041 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2035 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2042 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2036 @@ -0,0 +1,1 @@
2043 @@ -0,0 +1,1 @@
2037 +f
2044 +f
2038 # HG changeset patch
2045 # HG changeset patch
2039 # User test
2046 # User test
2040 # Date 0 0
2047 # Date 0 0
2041 # Thu Jan 01 00:00:00 1970 +0000
2048 # Thu Jan 01 00:00:00 1970 +0000
2042 # Node ID 216d4c92cf98ff2b4641d508b76b529f3d424c92
2049 # Node ID 216d4c92cf98ff2b4641d508b76b529f3d424c92
2043 # Parent f8035bb17114da16215af3436ec5222428ace8ee
2050 # Parent f8035bb17114da16215af3436ec5222428ace8ee
2044 copy a b
2051 copy a b
2045
2052
2046 diff -r f8035bb17114 -r 216d4c92cf98 b
2053 diff -r f8035bb17114 -r 216d4c92cf98 b
2047 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2054 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2048 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2055 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2049 @@ -0,0 +1,1 @@
2056 @@ -0,0 +1,1 @@
2050 +a
2057 +a
2051 diff -r f8035bb17114 -r 216d4c92cf98 g
2058 diff -r f8035bb17114 -r 216d4c92cf98 g
2052 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2059 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2053 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2060 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2054 @@ -0,0 +1,1 @@
2061 @@ -0,0 +1,1 @@
2055 +f
2062 +f
2056 # HG changeset patch
2063 # HG changeset patch
2057 # User test
2064 # User test
2058 # Date 0 0
2065 # Date 0 0
2059 # Thu Jan 01 00:00:00 1970 +0000
2066 # Thu Jan 01 00:00:00 1970 +0000
2060 # Node ID bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2067 # Node ID bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2061 # Parent 216d4c92cf98ff2b4641d508b76b529f3d424c92
2068 # Parent 216d4c92cf98ff2b4641d508b76b529f3d424c92
2062 mv b dir/b
2069 mv b dir/b
2063
2070
2064 diff -r 216d4c92cf98 -r bb573313a9e8 b
2071 diff -r 216d4c92cf98 -r bb573313a9e8 b
2065 --- a/b Thu Jan 01 00:00:00 1970 +0000
2072 --- a/b Thu Jan 01 00:00:00 1970 +0000
2066 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2073 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2067 @@ -1,1 +0,0 @@
2074 @@ -1,1 +0,0 @@
2068 -a
2075 -a
2069 diff -r 216d4c92cf98 -r bb573313a9e8 dir/b
2076 diff -r 216d4c92cf98 -r bb573313a9e8 dir/b
2070 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2077 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2071 +++ b/dir/b Thu Jan 01 00:00:00 1970 +0000
2078 +++ b/dir/b Thu Jan 01 00:00:00 1970 +0000
2072 @@ -0,0 +1,1 @@
2079 @@ -0,0 +1,1 @@
2073 +a
2080 +a
2074 diff -r 216d4c92cf98 -r bb573313a9e8 f
2081 diff -r 216d4c92cf98 -r bb573313a9e8 f
2075 --- a/f Thu Jan 01 00:00:00 1970 +0000
2082 --- a/f Thu Jan 01 00:00:00 1970 +0000
2076 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2083 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2077 @@ -1,1 +1,2 @@
2084 @@ -1,1 +1,2 @@
2078 f
2085 f
2079 +f
2086 +f
2080 diff -r 216d4c92cf98 -r bb573313a9e8 g
2087 diff -r 216d4c92cf98 -r bb573313a9e8 g
2081 --- a/g Thu Jan 01 00:00:00 1970 +0000
2088 --- a/g Thu Jan 01 00:00:00 1970 +0000
2082 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2089 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2083 @@ -1,1 +1,2 @@
2090 @@ -1,1 +1,2 @@
2084 f
2091 f
2085 +g
2092 +g
2086 # HG changeset patch
2093 # HG changeset patch
2087 # User test
2094 # User test
2088 # Date 0 0
2095 # Date 0 0
2089 # Thu Jan 01 00:00:00 1970 +0000
2096 # Thu Jan 01 00:00:00 1970 +0000
2090 # Node ID 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2097 # Node ID 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2091 # Parent bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2098 # Parent bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2092 mv a b; add d
2099 mv a b; add d
2093
2100
2094 diff -r bb573313a9e8 -r 5918b8d165d1 a
2101 diff -r bb573313a9e8 -r 5918b8d165d1 a
2095 --- a/a Thu Jan 01 00:00:00 1970 +0000
2102 --- a/a Thu Jan 01 00:00:00 1970 +0000
2096 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2103 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2097 @@ -1,1 +0,0 @@
2104 @@ -1,1 +0,0 @@
2098 -a
2105 -a
2099 diff -r bb573313a9e8 -r 5918b8d165d1 b
2106 diff -r bb573313a9e8 -r 5918b8d165d1 b
2100 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2107 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2101 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2108 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2102 @@ -0,0 +1,1 @@
2109 @@ -0,0 +1,1 @@
2103 +a
2110 +a
2104 diff -r bb573313a9e8 -r 5918b8d165d1 d
2111 diff -r bb573313a9e8 -r 5918b8d165d1 d
2105 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2112 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2106 +++ b/d Thu Jan 01 00:00:00 1970 +0000
2113 +++ b/d Thu Jan 01 00:00:00 1970 +0000
2107 @@ -0,0 +1,1 @@
2114 @@ -0,0 +1,1 @@
2108 +a
2115 +a
2109 diff -r bb573313a9e8 -r 5918b8d165d1 g
2116 diff -r bb573313a9e8 -r 5918b8d165d1 g
2110 --- a/g Thu Jan 01 00:00:00 1970 +0000
2117 --- a/g Thu Jan 01 00:00:00 1970 +0000
2111 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2118 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2112 @@ -1,2 +1,2 @@
2119 @@ -1,2 +1,2 @@
2113 f
2120 f
2114 -g
2121 -g
2115 +f
2122 +f
2116 # HG changeset patch
2123 # HG changeset patch
2117 # User test
2124 # User test
2118 # Date 0 0
2125 # Date 0 0
2119 # Thu Jan 01 00:00:00 1970 +0000
2126 # Thu Jan 01 00:00:00 1970 +0000
2120 # Node ID 17d952250a9d03cc3dc77b199ab60e959b9b0260
2127 # Node ID 17d952250a9d03cc3dc77b199ab60e959b9b0260
2121 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2128 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2122 mv dir/b e
2129 mv dir/b e
2123
2130
2124 diff -r 5918b8d165d1 -r 17d952250a9d dir/b
2131 diff -r 5918b8d165d1 -r 17d952250a9d dir/b
2125 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2132 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2126 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2133 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2127 @@ -1,1 +0,0 @@
2134 @@ -1,1 +0,0 @@
2128 -a
2135 -a
2129 diff -r 5918b8d165d1 -r 17d952250a9d e
2136 diff -r 5918b8d165d1 -r 17d952250a9d e
2130 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2137 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2131 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2138 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2132 @@ -0,0 +1,1 @@
2139 @@ -0,0 +1,1 @@
2133 +a
2140 +a
2134 # HG changeset patch
2141 # HG changeset patch
2135 # User test
2142 # User test
2136 # Date 0 0
2143 # Date 0 0
2137 # Thu Jan 01 00:00:00 1970 +0000
2144 # Thu Jan 01 00:00:00 1970 +0000
2138 # Node ID 99b31f1c2782e2deb1723cef08930f70fc84b37b
2145 # Node ID 99b31f1c2782e2deb1723cef08930f70fc84b37b
2139 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2146 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2140 add another e
2147 add another e
2141
2148
2142 diff -r 5918b8d165d1 -r 99b31f1c2782 e
2149 diff -r 5918b8d165d1 -r 99b31f1c2782 e
2143 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2150 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2144 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2151 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2145 @@ -0,0 +1,1 @@
2152 @@ -0,0 +1,1 @@
2146 +ee
2153 +ee
2147 # HG changeset patch
2154 # HG changeset patch
2148 # User test
2155 # User test
2149 # Date 0 0
2156 # Date 0 0
2150 # Thu Jan 01 00:00:00 1970 +0000
2157 # Thu Jan 01 00:00:00 1970 +0000
2151 # Node ID fc281d8ff18d999ad6497b3d27390bcd695dcc73
2158 # Node ID fc281d8ff18d999ad6497b3d27390bcd695dcc73
2152 # Parent 99b31f1c2782e2deb1723cef08930f70fc84b37b
2159 # Parent 99b31f1c2782e2deb1723cef08930f70fc84b37b
2153 # Parent 17d952250a9d03cc3dc77b199ab60e959b9b0260
2160 # Parent 17d952250a9d03cc3dc77b199ab60e959b9b0260
2154 merge 5 and 4
2161 merge 5 and 4
2155
2162
2156 diff -r 99b31f1c2782 -r fc281d8ff18d dir/b
2163 diff -r 99b31f1c2782 -r fc281d8ff18d dir/b
2157 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2164 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2158 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2165 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2159 @@ -1,1 +0,0 @@
2166 @@ -1,1 +0,0 @@
2160 -a
2167 -a
2161 diff -r 99b31f1c2782 -r fc281d8ff18d e
2168 diff -r 99b31f1c2782 -r fc281d8ff18d e
2162 --- a/e Thu Jan 01 00:00:00 1970 +0000
2169 --- a/e Thu Jan 01 00:00:00 1970 +0000
2163 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2170 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2164 @@ -1,1 +1,1 @@
2171 @@ -1,1 +1,1 @@
2165 -ee
2172 -ee
2166 +merge
2173 +merge
2167 # HG changeset patch
2174 # HG changeset patch
2168 # User test
2175 # User test
2169 # Date 0 0
2176 # Date 0 0
2170 # Thu Jan 01 00:00:00 1970 +0000
2177 # Thu Jan 01 00:00:00 1970 +0000
2171 # Node ID 02dbb8e276b8ab7abfd07cab50c901647e75c2dd
2178 # Node ID 02dbb8e276b8ab7abfd07cab50c901647e75c2dd
2172 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2179 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2173 Added tag foo-bar for changeset fc281d8ff18d
2180 Added tag foo-bar for changeset fc281d8ff18d
2174
2181
2175 diff -r fc281d8ff18d -r 02dbb8e276b8 .hgtags
2182 diff -r fc281d8ff18d -r 02dbb8e276b8 .hgtags
2176 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2183 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2177 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2184 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2178 @@ -0,0 +1,1 @@
2185 @@ -0,0 +1,1 @@
2179 +fc281d8ff18d999ad6497b3d27390bcd695dcc73 foo-bar
2186 +fc281d8ff18d999ad6497b3d27390bcd695dcc73 foo-bar
2180 # HG changeset patch
2187 # HG changeset patch
2181 # User test
2188 # User test
2182 # Date 0 0
2189 # Date 0 0
2183 # Thu Jan 01 00:00:00 1970 +0000
2190 # Thu Jan 01 00:00:00 1970 +0000
2184 # Node ID 24c2e826ddebf80f9dcd60b856bdb8e6715c5449
2191 # Node ID 24c2e826ddebf80f9dcd60b856bdb8e6715c5449
2185 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2192 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2186 add g
2193 add g
2187
2194
2188 diff -r fc281d8ff18d -r 24c2e826ddeb g
2195 diff -r fc281d8ff18d -r 24c2e826ddeb g
2189 --- a/g Thu Jan 01 00:00:00 1970 +0000
2196 --- a/g Thu Jan 01 00:00:00 1970 +0000
2190 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2197 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2191 @@ -1,2 +1,1 @@
2198 @@ -1,2 +1,1 @@
2192 -f
2199 -f
2193 -f
2200 -f
2194 +g
2201 +g
2195 $ testlog --follow -r6 -r8 -r5 -r7 -r4
2202 $ testlog --follow -r6 -r8 -r5 -r7 -r4
2196 ['6', '8', '5', '7', '4']
2203 ['6', '8', '5', '7', '4']
2197 (group
2204 (group
2198 (func
2205 (func
2199 ('symbol', 'descendants')
2206 ('symbol', 'descendants')
2200 (func
2207 (func
2201 ('symbol', 'rev')
2208 ('symbol', 'rev')
2202 ('symbol', '6'))))
2209 ('symbol', '6'))))
2203
2210
2204 Test --follow-first and forward --rev
2211 Test --follow-first and forward --rev
2205
2212
2206 $ testlog --follow-first -r6 -r8 -r5 -r7 -r4
2213 $ testlog --follow-first -r6 -r8 -r5 -r7 -r4
2207 ['6', '8', '5', '7', '4']
2214 ['6', '8', '5', '7', '4']
2208 (group
2215 (group
2209 (func
2216 (func
2210 ('symbol', '_firstdescendants')
2217 ('symbol', '_firstdescendants')
2211 (func
2218 (func
2212 ('symbol', 'rev')
2219 ('symbol', 'rev')
2213 ('symbol', '6'))))
2220 ('symbol', '6'))))
2214 --- log.nodes * (glob)
2221 --- log.nodes * (glob)
2215 +++ glog.nodes * (glob)
2222 +++ glog.nodes * (glob)
2216 @@ -1,3 +1,3 @@
2223 @@ -1,3 +1,3 @@
2217 -nodetag 6
2224 -nodetag 6
2218 nodetag 8
2225 nodetag 8
2219 nodetag 7
2226 nodetag 7
2220 +nodetag 6
2227 +nodetag 6
2221
2228
2222 Test --follow and backward --rev
2229 Test --follow and backward --rev
2223
2230
2224 $ testlog --follow -r6 -r5 -r7 -r8 -r4
2231 $ testlog --follow -r6 -r5 -r7 -r8 -r4
2225 ['6', '5', '7', '8', '4']
2232 ['6', '5', '7', '8', '4']
2226 (group
2233 (group
2227 (func
2234 (func
2228 ('symbol', 'ancestors')
2235 ('symbol', 'ancestors')
2229 (func
2236 (func
2230 ('symbol', 'rev')
2237 ('symbol', 'rev')
2231 ('symbol', '6'))))
2238 ('symbol', '6'))))
2232
2239
2233 Test --follow-first and backward --rev
2240 Test --follow-first and backward --rev
2234
2241
2235 $ testlog --follow-first -r6 -r5 -r7 -r8 -r4
2242 $ testlog --follow-first -r6 -r5 -r7 -r8 -r4
2236 ['6', '5', '7', '8', '4']
2243 ['6', '5', '7', '8', '4']
2237 (group
2244 (group
2238 (func
2245 (func
2239 ('symbol', '_firstancestors')
2246 ('symbol', '_firstancestors')
2240 (func
2247 (func
2241 ('symbol', 'rev')
2248 ('symbol', 'rev')
2242 ('symbol', '6'))))
2249 ('symbol', '6'))))
2243
2250
2244 Test --follow with --rev of graphlog extension
2251 Test --follow with --rev of graphlog extension
2245
2252
2246 $ hg --config extensions.graphlog= glog -qfr1
2253 $ hg --config extensions.graphlog= glog -qfr1
2247 o 1:216d4c92cf98
2254 o 1:216d4c92cf98
2248 |
2255 |
2249 o 0:f8035bb17114
2256 o 0:f8035bb17114
2250
2257
2251
2258
2252 Test subdir
2259 Test subdir
2253
2260
2254 $ hg up -q 3
2261 $ hg up -q 3
2255 $ cd dir
2262 $ cd dir
2256 $ testlog .
2263 $ testlog .
2257 []
2264 []
2258 (group
2265 (group
2259 (func
2266 (func
2260 ('symbol', '_matchfiles')
2267 ('symbol', '_matchfiles')
2261 (list
2268 (list
2262 ('string', 'r:')
2269 ('string', 'r:')
2263 ('string', 'd:relpath')
2270 ('string', 'd:relpath')
2264 ('string', 'p:.'))))
2271 ('string', 'p:.'))))
2265 $ testlog ../b
2272 $ testlog ../b
2266 []
2273 []
2267 (group
2274 (group
2268 (group
2275 (group
2269 (func
2276 (func
2270 ('symbol', 'filelog')
2277 ('symbol', 'filelog')
2271 ('string', '../b'))))
2278 ('string', '../b'))))
2272 $ testlog -f ../b
2279 $ testlog -f ../b
2273 []
2280 []
2274 (group
2281 (group
2275 (group
2282 (group
2276 (func
2283 (func
2277 ('symbol', 'follow')
2284 ('symbol', 'follow')
2278 ('string', 'b'))))
2285 ('string', 'b'))))
2279 $ cd ..
2286 $ cd ..
2280
2287
2281 Test --hidden
2288 Test --hidden
2282 (enable obsolete)
2289 (enable obsolete)
2283
2290
2284 $ cat >> $HGRCPATH << EOF
2291 $ cat >> $HGRCPATH << EOF
2285 > [experimental]
2292 > [experimental]
2286 > evolution=createmarkers
2293 > evolution=createmarkers
2287 > EOF
2294 > EOF
2288
2295
2289 $ hg debugobsolete `hg id --debug -i -r 8`
2296 $ hg debugobsolete `hg id --debug -i -r 8`
2290 $ testlog
2297 $ testlog
2291 []
2298 []
2292 []
2299 []
2293 $ testlog --hidden
2300 $ testlog --hidden
2294 []
2301 []
2295 []
2302 []
2296 $ hg log -G --template '{rev} {desc}\n'
2303 $ hg log -G --template '{rev} {desc}\n'
2297 o 7 Added tag foo-bar for changeset fc281d8ff18d
2304 o 7 Added tag foo-bar for changeset fc281d8ff18d
2298 |
2305 |
2299 o 6 merge 5 and 4
2306 o 6 merge 5 and 4
2300 |\
2307 |\
2301 | o 5 add another e
2308 | o 5 add another e
2302 | |
2309 | |
2303 o | 4 mv dir/b e
2310 o | 4 mv dir/b e
2304 |/
2311 |/
2305 @ 3 mv a b; add d
2312 @ 3 mv a b; add d
2306 |
2313 |
2307 o 2 mv b dir/b
2314 o 2 mv b dir/b
2308 |
2315 |
2309 o 1 copy a b
2316 o 1 copy a b
2310 |
2317 |
2311 o 0 add a
2318 o 0 add a
2312
2319
2313
2320
2314 A template without trailing newline should do something sane
2321 A template without trailing newline should do something sane
2315
2322
2316 $ hg log -G -r ::2 --template '{rev} {desc}'
2323 $ hg log -G -r ::2 --template '{rev} {desc}'
2317 o 2 mv b dir/b
2324 o 2 mv b dir/b
2318 |
2325 |
2319 o 1 copy a b
2326 o 1 copy a b
2320 |
2327 |
2321 o 0 add a
2328 o 0 add a
2322
2329
2323
2330
2324 Extra newlines must be preserved
2331 Extra newlines must be preserved
2325
2332
2326 $ hg log -G -r ::2 --template '\n{rev} {desc}\n\n'
2333 $ hg log -G -r ::2 --template '\n{rev} {desc}\n\n'
2327 o
2334 o
2328 | 2 mv b dir/b
2335 | 2 mv b dir/b
2329 |
2336 |
2330 o
2337 o
2331 | 1 copy a b
2338 | 1 copy a b
2332 |
2339 |
2333 o
2340 o
2334 0 add a
2341 0 add a
2335
2342
2336
2343
2337 The almost-empty template should do something sane too ...
2344 The almost-empty template should do something sane too ...
2338
2345
2339 $ hg log -G -r ::2 --template '\n'
2346 $ hg log -G -r ::2 --template '\n'
2340 o
2347 o
2341 |
2348 |
2342 o
2349 o
2343 |
2350 |
2344 o
2351 o
2345
2352
2346
2353
2347 issue3772
2354 issue3772
2348
2355
2349 $ hg log -G -r :null
2356 $ hg log -G -r :null
2350 o changeset: 0:f8035bb17114
2357 o changeset: 0:f8035bb17114
2351 | user: test
2358 | user: test
2352 | date: Thu Jan 01 00:00:00 1970 +0000
2359 | date: Thu Jan 01 00:00:00 1970 +0000
2353 | summary: add a
2360 | summary: add a
2354 |
2361 |
2355 o changeset: -1:000000000000
2362 o changeset: -1:000000000000
2356 user:
2363 user:
2357 date: Thu Jan 01 00:00:00 1970 +0000
2364 date: Thu Jan 01 00:00:00 1970 +0000
2358
2365
2359 $ hg log -G -r null:null
2366 $ hg log -G -r null:null
2360 o changeset: -1:000000000000
2367 o changeset: -1:000000000000
2361 user:
2368 user:
2362 date: Thu Jan 01 00:00:00 1970 +0000
2369 date: Thu Jan 01 00:00:00 1970 +0000
2363
2370
2364
2371
2365 should not draw line down to null due to the magic of fullreposet
2372 should not draw line down to null due to the magic of fullreposet
2366
2373
2367 $ hg log -G -r 'all()' | tail -6
2374 $ hg log -G -r 'all()' | tail -6
2368 |
2375 |
2369 o changeset: 0:f8035bb17114
2376 o changeset: 0:f8035bb17114
2370 user: test
2377 user: test
2371 date: Thu Jan 01 00:00:00 1970 +0000
2378 date: Thu Jan 01 00:00:00 1970 +0000
2372 summary: add a
2379 summary: add a
2373
2380
2374
2381
2375 $ hg log -G -r 'branch(default)' | tail -6
2382 $ hg log -G -r 'branch(default)' | tail -6
2376 |
2383 |
2377 o changeset: 0:f8035bb17114
2384 o changeset: 0:f8035bb17114
2378 user: test
2385 user: test
2379 date: Thu Jan 01 00:00:00 1970 +0000
2386 date: Thu Jan 01 00:00:00 1970 +0000
2380 summary: add a
2387 summary: add a
2381
2388
2382
2389
2383 working-directory revision
2390 working-directory revision
2384
2391
2385 $ hg log -G -qr '. + wdir()'
2392 $ hg log -G -qr '. + wdir()'
2386 o 2147483647:ffffffffffff
2393 o 2147483647:ffffffffffff
2387 |
2394 |
2388 @ 3:5918b8d165d1
2395 @ 3:5918b8d165d1
2389 |
2396 |
2390 ~
2397 ~
2391
2398
2392 node template with changeset_printer:
2399 node template with changeset_printer:
2393
2400
2394 $ hg log -Gqr 5:7 --config ui.graphnodetemplate='{rev}'
2401 $ hg log -Gqr 5:7 --config ui.graphnodetemplate='{rev}'
2395 7 7:02dbb8e276b8
2402 7 7:02dbb8e276b8
2396 |
2403 |
2397 6 6:fc281d8ff18d
2404 6 6:fc281d8ff18d
2398 |\
2405 |\
2399 | ~
2406 | ~
2400 5 5:99b31f1c2782
2407 5 5:99b31f1c2782
2401 |
2408 |
2402 ~
2409 ~
2403
2410
2404 node template with changeset_templater (shared cache variable):
2411 node template with changeset_templater (shared cache variable):
2405
2412
2406 $ hg log -Gr 5:7 -T '{latesttag % "{rev} {tag}+{distance}"}\n' \
2413 $ hg log -Gr 5:7 -T '{latesttag % "{rev} {tag}+{distance}"}\n' \
2407 > --config ui.graphnodetemplate='{ifeq(latesttagdistance, 0, "#", graphnode)}'
2414 > --config ui.graphnodetemplate='{ifeq(latesttagdistance, 0, "#", graphnode)}'
2408 o 7 foo-bar+1
2415 o 7 foo-bar+1
2409 |
2416 |
2410 # 6 foo-bar+0
2417 # 6 foo-bar+0
2411 |\
2418 |\
2412 | ~
2419 | ~
2413 o 5 null+5
2420 o 5 null+5
2414 |
2421 |
2415 ~
2422 ~
2416
2423
2417 label() should just work in node template:
2424 label() should just work in node template:
2418
2425
2419 $ hg log -Gqr 7 --config extensions.color= --color=debug \
2426 $ hg log -Gqr 7 --config extensions.color= --color=debug \
2420 > --config ui.graphnodetemplate='{label("branch.{branch}", rev)}'
2427 > --config ui.graphnodetemplate='{label("branch.{branch}", rev)}'
2421 [branch.default|7] [log.node|7:02dbb8e276b8]
2428 [branch.default|7] [log.node|7:02dbb8e276b8]
2422 |
2429 |
2423 ~
2430 ~
2424
2431
2425 $ cd ..
2432 $ cd ..
2426
2433
2427 change graph edge styling
2434 change graph edge styling
2428
2435
2429 $ cd repo
2436 $ cd repo
2430 $ cat << EOF >> $HGRCPATH
2437 $ cat << EOF >> $HGRCPATH
2431 > [experimental]
2438 > [experimental]
2432 > graphstyle.parent = |
2439 > graphstyle.parent = |
2433 > graphstyle.grandparent = :
2440 > graphstyle.grandparent = :
2434 > graphstyle.missing =
2441 > graphstyle.missing =
2435 > EOF
2442 > EOF
2436 $ hg log -G -r 'file("a")' -m
2443 $ hg log -G -r 'file("a")' -m
2437 @ changeset: 36:08a19a744424
2444 @ changeset: 36:08a19a744424
2438 : branch: branch
2445 : branch: branch
2439 : tag: tip
2446 : tag: tip
2440 : parent: 35:9159c3644c5e
2447 : parent: 35:9159c3644c5e
2441 : parent: 35:9159c3644c5e
2448 : parent: 35:9159c3644c5e
2442 : user: test
2449 : user: test
2443 : date: Thu Jan 01 00:00:36 1970 +0000
2450 : date: Thu Jan 01 00:00:36 1970 +0000
2444 : summary: (36) buggy merge: identical parents
2451 : summary: (36) buggy merge: identical parents
2445 :
2452 :
2446 o changeset: 32:d06dffa21a31
2453 o changeset: 32:d06dffa21a31
2447 |\ parent: 27:886ed638191b
2454 |\ parent: 27:886ed638191b
2448 | : parent: 31:621d83e11f67
2455 | : parent: 31:621d83e11f67
2449 | : user: test
2456 | : user: test
2450 | : date: Thu Jan 01 00:00:32 1970 +0000
2457 | : date: Thu Jan 01 00:00:32 1970 +0000
2451 | : summary: (32) expand
2458 | : summary: (32) expand
2452 | :
2459 | :
2453 o : changeset: 31:621d83e11f67
2460 o : changeset: 31:621d83e11f67
2454 |\: parent: 21:d42a756af44d
2461 |\: parent: 21:d42a756af44d
2455 | : parent: 30:6e11cd4b648f
2462 | : parent: 30:6e11cd4b648f
2456 | : user: test
2463 | : user: test
2457 | : date: Thu Jan 01 00:00:31 1970 +0000
2464 | : date: Thu Jan 01 00:00:31 1970 +0000
2458 | : summary: (31) expand
2465 | : summary: (31) expand
2459 | :
2466 | :
2460 o : changeset: 30:6e11cd4b648f
2467 o : changeset: 30:6e11cd4b648f
2461 |\ \ parent: 28:44ecd0b9ae99
2468 |\ \ parent: 28:44ecd0b9ae99
2462 | ~ : parent: 29:cd9bb2be7593
2469 | ~ : parent: 29:cd9bb2be7593
2463 | : user: test
2470 | : user: test
2464 | : date: Thu Jan 01 00:00:30 1970 +0000
2471 | : date: Thu Jan 01 00:00:30 1970 +0000
2465 | : summary: (30) expand
2472 | : summary: (30) expand
2466 | /
2473 | /
2467 o : changeset: 28:44ecd0b9ae99
2474 o : changeset: 28:44ecd0b9ae99
2468 |\ \ parent: 1:6db2ef61d156
2475 |\ \ parent: 1:6db2ef61d156
2469 | ~ : parent: 26:7f25b6c2f0b9
2476 | ~ : parent: 26:7f25b6c2f0b9
2470 | : user: test
2477 | : user: test
2471 | : date: Thu Jan 01 00:00:28 1970 +0000
2478 | : date: Thu Jan 01 00:00:28 1970 +0000
2472 | : summary: (28) merge zero known
2479 | : summary: (28) merge zero known
2473 | /
2480 | /
2474 o : changeset: 26:7f25b6c2f0b9
2481 o : changeset: 26:7f25b6c2f0b9
2475 |\ \ parent: 18:1aa84d96232a
2482 |\ \ parent: 18:1aa84d96232a
2476 | | : parent: 25:91da8ed57247
2483 | | : parent: 25:91da8ed57247
2477 | | : user: test
2484 | | : user: test
2478 | | : date: Thu Jan 01 00:00:26 1970 +0000
2485 | | : date: Thu Jan 01 00:00:26 1970 +0000
2479 | | : summary: (26) merge one known; far right
2486 | | : summary: (26) merge one known; far right
2480 | | :
2487 | | :
2481 | o : changeset: 25:91da8ed57247
2488 | o : changeset: 25:91da8ed57247
2482 | |\: parent: 21:d42a756af44d
2489 | |\: parent: 21:d42a756af44d
2483 | | : parent: 24:a9c19a3d96b7
2490 | | : parent: 24:a9c19a3d96b7
2484 | | : user: test
2491 | | : user: test
2485 | | : date: Thu Jan 01 00:00:25 1970 +0000
2492 | | : date: Thu Jan 01 00:00:25 1970 +0000
2486 | | : summary: (25) merge one known; far left
2493 | | : summary: (25) merge one known; far left
2487 | | :
2494 | | :
2488 | o : changeset: 24:a9c19a3d96b7
2495 | o : changeset: 24:a9c19a3d96b7
2489 | |\ \ parent: 0:e6eb3150255d
2496 | |\ \ parent: 0:e6eb3150255d
2490 | | ~ : parent: 23:a01cddf0766d
2497 | | ~ : parent: 23:a01cddf0766d
2491 | | : user: test
2498 | | : user: test
2492 | | : date: Thu Jan 01 00:00:24 1970 +0000
2499 | | : date: Thu Jan 01 00:00:24 1970 +0000
2493 | | : summary: (24) merge one known; immediate right
2500 | | : summary: (24) merge one known; immediate right
2494 | | /
2501 | | /
2495 | o : changeset: 23:a01cddf0766d
2502 | o : changeset: 23:a01cddf0766d
2496 | |\ \ parent: 1:6db2ef61d156
2503 | |\ \ parent: 1:6db2ef61d156
2497 | | ~ : parent: 22:e0d9cccacb5d
2504 | | ~ : parent: 22:e0d9cccacb5d
2498 | | : user: test
2505 | | : user: test
2499 | | : date: Thu Jan 01 00:00:23 1970 +0000
2506 | | : date: Thu Jan 01 00:00:23 1970 +0000
2500 | | : summary: (23) merge one known; immediate left
2507 | | : summary: (23) merge one known; immediate left
2501 | | /
2508 | | /
2502 | o : changeset: 22:e0d9cccacb5d
2509 | o : changeset: 22:e0d9cccacb5d
2503 |/:/ parent: 18:1aa84d96232a
2510 |/:/ parent: 18:1aa84d96232a
2504 | : parent: 21:d42a756af44d
2511 | : parent: 21:d42a756af44d
2505 | : user: test
2512 | : user: test
2506 | : date: Thu Jan 01 00:00:22 1970 +0000
2513 | : date: Thu Jan 01 00:00:22 1970 +0000
2507 | : summary: (22) merge two known; one far left, one far right
2514 | : summary: (22) merge two known; one far left, one far right
2508 | :
2515 | :
2509 | o changeset: 21:d42a756af44d
2516 | o changeset: 21:d42a756af44d
2510 | |\ parent: 19:31ddc2c1573b
2517 | |\ parent: 19:31ddc2c1573b
2511 | | | parent: 20:d30ed6450e32
2518 | | | parent: 20:d30ed6450e32
2512 | | | user: test
2519 | | | user: test
2513 | | | date: Thu Jan 01 00:00:21 1970 +0000
2520 | | | date: Thu Jan 01 00:00:21 1970 +0000
2514 | | | summary: (21) expand
2521 | | | summary: (21) expand
2515 | | |
2522 | | |
2516 +---o changeset: 20:d30ed6450e32
2523 +---o changeset: 20:d30ed6450e32
2517 | | | parent: 0:e6eb3150255d
2524 | | | parent: 0:e6eb3150255d
2518 | | ~ parent: 18:1aa84d96232a
2525 | | ~ parent: 18:1aa84d96232a
2519 | | user: test
2526 | | user: test
2520 | | date: Thu Jan 01 00:00:20 1970 +0000
2527 | | date: Thu Jan 01 00:00:20 1970 +0000
2521 | | summary: (20) merge two known; two far right
2528 | | summary: (20) merge two known; two far right
2522 | |
2529 | |
2523 | o changeset: 19:31ddc2c1573b
2530 | o changeset: 19:31ddc2c1573b
2524 | |\ parent: 15:1dda3f72782d
2531 | |\ parent: 15:1dda3f72782d
2525 | | | parent: 17:44765d7c06e0
2532 | | | parent: 17:44765d7c06e0
2526 | | | user: test
2533 | | | user: test
2527 | | | date: Thu Jan 01 00:00:19 1970 +0000
2534 | | | date: Thu Jan 01 00:00:19 1970 +0000
2528 | | | summary: (19) expand
2535 | | | summary: (19) expand
2529 | | |
2536 | | |
2530 o | | changeset: 18:1aa84d96232a
2537 o | | changeset: 18:1aa84d96232a
2531 |\| | parent: 1:6db2ef61d156
2538 |\| | parent: 1:6db2ef61d156
2532 ~ | | parent: 15:1dda3f72782d
2539 ~ | | parent: 15:1dda3f72782d
2533 | | user: test
2540 | | user: test
2534 | | date: Thu Jan 01 00:00:18 1970 +0000
2541 | | date: Thu Jan 01 00:00:18 1970 +0000
2535 | | summary: (18) merge two known; two far left
2542 | | summary: (18) merge two known; two far left
2536 / /
2543 / /
2537 | o changeset: 17:44765d7c06e0
2544 | o changeset: 17:44765d7c06e0
2538 | |\ parent: 12:86b91144a6e9
2545 | |\ parent: 12:86b91144a6e9
2539 | | | parent: 16:3677d192927d
2546 | | | parent: 16:3677d192927d
2540 | | | user: test
2547 | | | user: test
2541 | | | date: Thu Jan 01 00:00:17 1970 +0000
2548 | | | date: Thu Jan 01 00:00:17 1970 +0000
2542 | | | summary: (17) expand
2549 | | | summary: (17) expand
2543 | | |
2550 | | |
2544 | | o changeset: 16:3677d192927d
2551 | | o changeset: 16:3677d192927d
2545 | | |\ parent: 0:e6eb3150255d
2552 | | |\ parent: 0:e6eb3150255d
2546 | | ~ ~ parent: 1:6db2ef61d156
2553 | | ~ ~ parent: 1:6db2ef61d156
2547 | | user: test
2554 | | user: test
2548 | | date: Thu Jan 01 00:00:16 1970 +0000
2555 | | date: Thu Jan 01 00:00:16 1970 +0000
2549 | | summary: (16) merge two known; one immediate right, one near right
2556 | | summary: (16) merge two known; one immediate right, one near right
2550 | |
2557 | |
2551 o | changeset: 15:1dda3f72782d
2558 o | changeset: 15:1dda3f72782d
2552 |\ \ parent: 13:22d8966a97e3
2559 |\ \ parent: 13:22d8966a97e3
2553 | | | parent: 14:8eac370358ef
2560 | | | parent: 14:8eac370358ef
2554 | | | user: test
2561 | | | user: test
2555 | | | date: Thu Jan 01 00:00:15 1970 +0000
2562 | | | date: Thu Jan 01 00:00:15 1970 +0000
2556 | | | summary: (15) expand
2563 | | | summary: (15) expand
2557 | | |
2564 | | |
2558 | o | changeset: 14:8eac370358ef
2565 | o | changeset: 14:8eac370358ef
2559 | |\| parent: 0:e6eb3150255d
2566 | |\| parent: 0:e6eb3150255d
2560 | ~ | parent: 12:86b91144a6e9
2567 | ~ | parent: 12:86b91144a6e9
2561 | | user: test
2568 | | user: test
2562 | | date: Thu Jan 01 00:00:14 1970 +0000
2569 | | date: Thu Jan 01 00:00:14 1970 +0000
2563 | | summary: (14) merge two known; one immediate right, one far right
2570 | | summary: (14) merge two known; one immediate right, one far right
2564 | /
2571 | /
2565 o | changeset: 13:22d8966a97e3
2572 o | changeset: 13:22d8966a97e3
2566 |\ \ parent: 9:7010c0af0a35
2573 |\ \ parent: 9:7010c0af0a35
2567 | | | parent: 11:832d76e6bdf2
2574 | | | parent: 11:832d76e6bdf2
2568 | | | user: test
2575 | | | user: test
2569 | | | date: Thu Jan 01 00:00:13 1970 +0000
2576 | | | date: Thu Jan 01 00:00:13 1970 +0000
2570 | | | summary: (13) expand
2577 | | | summary: (13) expand
2571 | | |
2578 | | |
2572 +---o changeset: 12:86b91144a6e9
2579 +---o changeset: 12:86b91144a6e9
2573 | | | parent: 1:6db2ef61d156
2580 | | | parent: 1:6db2ef61d156
2574 | | ~ parent: 9:7010c0af0a35
2581 | | ~ parent: 9:7010c0af0a35
2575 | | user: test
2582 | | user: test
2576 | | date: Thu Jan 01 00:00:12 1970 +0000
2583 | | date: Thu Jan 01 00:00:12 1970 +0000
2577 | | summary: (12) merge two known; one immediate right, one far left
2584 | | summary: (12) merge two known; one immediate right, one far left
2578 | |
2585 | |
2579 | o changeset: 11:832d76e6bdf2
2586 | o changeset: 11:832d76e6bdf2
2580 | |\ parent: 6:b105a072e251
2587 | |\ parent: 6:b105a072e251
2581 | | | parent: 10:74c64d036d72
2588 | | | parent: 10:74c64d036d72
2582 | | | user: test
2589 | | | user: test
2583 | | | date: Thu Jan 01 00:00:11 1970 +0000
2590 | | | date: Thu Jan 01 00:00:11 1970 +0000
2584 | | | summary: (11) expand
2591 | | | summary: (11) expand
2585 | | |
2592 | | |
2586 | | o changeset: 10:74c64d036d72
2593 | | o changeset: 10:74c64d036d72
2587 | |/| parent: 0:e6eb3150255d
2594 | |/| parent: 0:e6eb3150255d
2588 | | ~ parent: 6:b105a072e251
2595 | | ~ parent: 6:b105a072e251
2589 | | user: test
2596 | | user: test
2590 | | date: Thu Jan 01 00:00:10 1970 +0000
2597 | | date: Thu Jan 01 00:00:10 1970 +0000
2591 | | summary: (10) merge two known; one immediate left, one near right
2598 | | summary: (10) merge two known; one immediate left, one near right
2592 | |
2599 | |
2593 o | changeset: 9:7010c0af0a35
2600 o | changeset: 9:7010c0af0a35
2594 |\ \ parent: 7:b632bb1b1224
2601 |\ \ parent: 7:b632bb1b1224
2595 | | | parent: 8:7a0b11f71937
2602 | | | parent: 8:7a0b11f71937
2596 | | | user: test
2603 | | | user: test
2597 | | | date: Thu Jan 01 00:00:09 1970 +0000
2604 | | | date: Thu Jan 01 00:00:09 1970 +0000
2598 | | | summary: (9) expand
2605 | | | summary: (9) expand
2599 | | |
2606 | | |
2600 | o | changeset: 8:7a0b11f71937
2607 | o | changeset: 8:7a0b11f71937
2601 |/| | parent: 0:e6eb3150255d
2608 |/| | parent: 0:e6eb3150255d
2602 | ~ | parent: 7:b632bb1b1224
2609 | ~ | parent: 7:b632bb1b1224
2603 | | user: test
2610 | | user: test
2604 | | date: Thu Jan 01 00:00:08 1970 +0000
2611 | | date: Thu Jan 01 00:00:08 1970 +0000
2605 | | summary: (8) merge two known; one immediate left, one far right
2612 | | summary: (8) merge two known; one immediate left, one far right
2606 | /
2613 | /
2607 o | changeset: 7:b632bb1b1224
2614 o | changeset: 7:b632bb1b1224
2608 |\ \ parent: 2:3d9a33b8d1e1
2615 |\ \ parent: 2:3d9a33b8d1e1
2609 | ~ | parent: 5:4409d547b708
2616 | ~ | parent: 5:4409d547b708
2610 | | user: test
2617 | | user: test
2611 | | date: Thu Jan 01 00:00:07 1970 +0000
2618 | | date: Thu Jan 01 00:00:07 1970 +0000
2612 | | summary: (7) expand
2619 | | summary: (7) expand
2613 | /
2620 | /
2614 | o changeset: 6:b105a072e251
2621 | o changeset: 6:b105a072e251
2615 |/| parent: 2:3d9a33b8d1e1
2622 |/| parent: 2:3d9a33b8d1e1
2616 | ~ parent: 5:4409d547b708
2623 | ~ parent: 5:4409d547b708
2617 | user: test
2624 | user: test
2618 | date: Thu Jan 01 00:00:06 1970 +0000
2625 | date: Thu Jan 01 00:00:06 1970 +0000
2619 | summary: (6) merge two known; one immediate left, one far left
2626 | summary: (6) merge two known; one immediate left, one far left
2620 |
2627 |
2621 o changeset: 5:4409d547b708
2628 o changeset: 5:4409d547b708
2622 |\ parent: 3:27eef8ed80b4
2629 |\ parent: 3:27eef8ed80b4
2623 | ~ parent: 4:26a8bac39d9f
2630 | ~ parent: 4:26a8bac39d9f
2624 | user: test
2631 | user: test
2625 | date: Thu Jan 01 00:00:05 1970 +0000
2632 | date: Thu Jan 01 00:00:05 1970 +0000
2626 | summary: (5) expand
2633 | summary: (5) expand
2627 |
2634 |
2628 o changeset: 4:26a8bac39d9f
2635 o changeset: 4:26a8bac39d9f
2629 |\ parent: 1:6db2ef61d156
2636 |\ parent: 1:6db2ef61d156
2630 ~ ~ parent: 3:27eef8ed80b4
2637 ~ ~ parent: 3:27eef8ed80b4
2631 user: test
2638 user: test
2632 date: Thu Jan 01 00:00:04 1970 +0000
2639 date: Thu Jan 01 00:00:04 1970 +0000
2633 summary: (4) merge two known; one immediate left, one immediate right
2640 summary: (4) merge two known; one immediate left, one immediate right
2634
2641
2635
2642
2636 Setting HGPLAIN ignores graphmod styling:
2643 Setting HGPLAIN ignores graphmod styling:
2637
2644
2638 $ HGPLAIN=1 hg log -G -r 'file("a")' -m
2645 $ HGPLAIN=1 hg log -G -r 'file("a")' -m
2639 @ changeset: 36:08a19a744424
2646 @ changeset: 36:08a19a744424
2640 | branch: branch
2647 | branch: branch
2641 | tag: tip
2648 | tag: tip
2642 | parent: 35:9159c3644c5e
2649 | parent: 35:9159c3644c5e
2643 | parent: 35:9159c3644c5e
2650 | parent: 35:9159c3644c5e
2644 | user: test
2651 | user: test
2645 | date: Thu Jan 01 00:00:36 1970 +0000
2652 | date: Thu Jan 01 00:00:36 1970 +0000
2646 | summary: (36) buggy merge: identical parents
2653 | summary: (36) buggy merge: identical parents
2647 |
2654 |
2648 o changeset: 32:d06dffa21a31
2655 o changeset: 32:d06dffa21a31
2649 |\ parent: 27:886ed638191b
2656 |\ parent: 27:886ed638191b
2650 | | parent: 31:621d83e11f67
2657 | | parent: 31:621d83e11f67
2651 | | user: test
2658 | | user: test
2652 | | date: Thu Jan 01 00:00:32 1970 +0000
2659 | | date: Thu Jan 01 00:00:32 1970 +0000
2653 | | summary: (32) expand
2660 | | summary: (32) expand
2654 | |
2661 | |
2655 o | changeset: 31:621d83e11f67
2662 o | changeset: 31:621d83e11f67
2656 |\| parent: 21:d42a756af44d
2663 |\| parent: 21:d42a756af44d
2657 | | parent: 30:6e11cd4b648f
2664 | | parent: 30:6e11cd4b648f
2658 | | user: test
2665 | | user: test
2659 | | date: Thu Jan 01 00:00:31 1970 +0000
2666 | | date: Thu Jan 01 00:00:31 1970 +0000
2660 | | summary: (31) expand
2667 | | summary: (31) expand
2661 | |
2668 | |
2662 o | changeset: 30:6e11cd4b648f
2669 o | changeset: 30:6e11cd4b648f
2663 |\ \ parent: 28:44ecd0b9ae99
2670 |\ \ parent: 28:44ecd0b9ae99
2664 | | | parent: 29:cd9bb2be7593
2671 | | | parent: 29:cd9bb2be7593
2665 | | | user: test
2672 | | | user: test
2666 | | | date: Thu Jan 01 00:00:30 1970 +0000
2673 | | | date: Thu Jan 01 00:00:30 1970 +0000
2667 | | | summary: (30) expand
2674 | | | summary: (30) expand
2668 | | |
2675 | | |
2669 o | | changeset: 28:44ecd0b9ae99
2676 o | | changeset: 28:44ecd0b9ae99
2670 |\ \ \ parent: 1:6db2ef61d156
2677 |\ \ \ parent: 1:6db2ef61d156
2671 | | | | parent: 26:7f25b6c2f0b9
2678 | | | | parent: 26:7f25b6c2f0b9
2672 | | | | user: test
2679 | | | | user: test
2673 | | | | date: Thu Jan 01 00:00:28 1970 +0000
2680 | | | | date: Thu Jan 01 00:00:28 1970 +0000
2674 | | | | summary: (28) merge zero known
2681 | | | | summary: (28) merge zero known
2675 | | | |
2682 | | | |
2676 o | | | changeset: 26:7f25b6c2f0b9
2683 o | | | changeset: 26:7f25b6c2f0b9
2677 |\ \ \ \ parent: 18:1aa84d96232a
2684 |\ \ \ \ parent: 18:1aa84d96232a
2678 | | | | | parent: 25:91da8ed57247
2685 | | | | | parent: 25:91da8ed57247
2679 | | | | | user: test
2686 | | | | | user: test
2680 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
2687 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
2681 | | | | | summary: (26) merge one known; far right
2688 | | | | | summary: (26) merge one known; far right
2682 | | | | |
2689 | | | | |
2683 | o-----+ changeset: 25:91da8ed57247
2690 | o-----+ changeset: 25:91da8ed57247
2684 | | | | | parent: 21:d42a756af44d
2691 | | | | | parent: 21:d42a756af44d
2685 | | | | | parent: 24:a9c19a3d96b7
2692 | | | | | parent: 24:a9c19a3d96b7
2686 | | | | | user: test
2693 | | | | | user: test
2687 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
2694 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
2688 | | | | | summary: (25) merge one known; far left
2695 | | | | | summary: (25) merge one known; far left
2689 | | | | |
2696 | | | | |
2690 | o | | | changeset: 24:a9c19a3d96b7
2697 | o | | | changeset: 24:a9c19a3d96b7
2691 | |\ \ \ \ parent: 0:e6eb3150255d
2698 | |\ \ \ \ parent: 0:e6eb3150255d
2692 | | | | | | parent: 23:a01cddf0766d
2699 | | | | | | parent: 23:a01cddf0766d
2693 | | | | | | user: test
2700 | | | | | | user: test
2694 | | | | | | date: Thu Jan 01 00:00:24 1970 +0000
2701 | | | | | | date: Thu Jan 01 00:00:24 1970 +0000
2695 | | | | | | summary: (24) merge one known; immediate right
2702 | | | | | | summary: (24) merge one known; immediate right
2696 | | | | | |
2703 | | | | | |
2697 | o---+ | | changeset: 23:a01cddf0766d
2704 | o---+ | | changeset: 23:a01cddf0766d
2698 | | | | | | parent: 1:6db2ef61d156
2705 | | | | | | parent: 1:6db2ef61d156
2699 | | | | | | parent: 22:e0d9cccacb5d
2706 | | | | | | parent: 22:e0d9cccacb5d
2700 | | | | | | user: test
2707 | | | | | | user: test
2701 | | | | | | date: Thu Jan 01 00:00:23 1970 +0000
2708 | | | | | | date: Thu Jan 01 00:00:23 1970 +0000
2702 | | | | | | summary: (23) merge one known; immediate left
2709 | | | | | | summary: (23) merge one known; immediate left
2703 | | | | | |
2710 | | | | | |
2704 | o-------+ changeset: 22:e0d9cccacb5d
2711 | o-------+ changeset: 22:e0d9cccacb5d
2705 | | | | | | parent: 18:1aa84d96232a
2712 | | | | | | parent: 18:1aa84d96232a
2706 |/ / / / / parent: 21:d42a756af44d
2713 |/ / / / / parent: 21:d42a756af44d
2707 | | | | | user: test
2714 | | | | | user: test
2708 | | | | | date: Thu Jan 01 00:00:22 1970 +0000
2715 | | | | | date: Thu Jan 01 00:00:22 1970 +0000
2709 | | | | | summary: (22) merge two known; one far left, one far right
2716 | | | | | summary: (22) merge two known; one far left, one far right
2710 | | | | |
2717 | | | | |
2711 | | | | o changeset: 21:d42a756af44d
2718 | | | | o changeset: 21:d42a756af44d
2712 | | | | |\ parent: 19:31ddc2c1573b
2719 | | | | |\ parent: 19:31ddc2c1573b
2713 | | | | | | parent: 20:d30ed6450e32
2720 | | | | | | parent: 20:d30ed6450e32
2714 | | | | | | user: test
2721 | | | | | | user: test
2715 | | | | | | date: Thu Jan 01 00:00:21 1970 +0000
2722 | | | | | | date: Thu Jan 01 00:00:21 1970 +0000
2716 | | | | | | summary: (21) expand
2723 | | | | | | summary: (21) expand
2717 | | | | | |
2724 | | | | | |
2718 +-+-------o changeset: 20:d30ed6450e32
2725 +-+-------o changeset: 20:d30ed6450e32
2719 | | | | | parent: 0:e6eb3150255d
2726 | | | | | parent: 0:e6eb3150255d
2720 | | | | | parent: 18:1aa84d96232a
2727 | | | | | parent: 18:1aa84d96232a
2721 | | | | | user: test
2728 | | | | | user: test
2722 | | | | | date: Thu Jan 01 00:00:20 1970 +0000
2729 | | | | | date: Thu Jan 01 00:00:20 1970 +0000
2723 | | | | | summary: (20) merge two known; two far right
2730 | | | | | summary: (20) merge two known; two far right
2724 | | | | |
2731 | | | | |
2725 | | | | o changeset: 19:31ddc2c1573b
2732 | | | | o changeset: 19:31ddc2c1573b
2726 | | | | |\ parent: 15:1dda3f72782d
2733 | | | | |\ parent: 15:1dda3f72782d
2727 | | | | | | parent: 17:44765d7c06e0
2734 | | | | | | parent: 17:44765d7c06e0
2728 | | | | | | user: test
2735 | | | | | | user: test
2729 | | | | | | date: Thu Jan 01 00:00:19 1970 +0000
2736 | | | | | | date: Thu Jan 01 00:00:19 1970 +0000
2730 | | | | | | summary: (19) expand
2737 | | | | | | summary: (19) expand
2731 | | | | | |
2738 | | | | | |
2732 o---+---+ | changeset: 18:1aa84d96232a
2739 o---+---+ | changeset: 18:1aa84d96232a
2733 | | | | | parent: 1:6db2ef61d156
2740 | | | | | parent: 1:6db2ef61d156
2734 / / / / / parent: 15:1dda3f72782d
2741 / / / / / parent: 15:1dda3f72782d
2735 | | | | | user: test
2742 | | | | | user: test
2736 | | | | | date: Thu Jan 01 00:00:18 1970 +0000
2743 | | | | | date: Thu Jan 01 00:00:18 1970 +0000
2737 | | | | | summary: (18) merge two known; two far left
2744 | | | | | summary: (18) merge two known; two far left
2738 | | | | |
2745 | | | | |
2739 | | | | o changeset: 17:44765d7c06e0
2746 | | | | o changeset: 17:44765d7c06e0
2740 | | | | |\ parent: 12:86b91144a6e9
2747 | | | | |\ parent: 12:86b91144a6e9
2741 | | | | | | parent: 16:3677d192927d
2748 | | | | | | parent: 16:3677d192927d
2742 | | | | | | user: test
2749 | | | | | | user: test
2743 | | | | | | date: Thu Jan 01 00:00:17 1970 +0000
2750 | | | | | | date: Thu Jan 01 00:00:17 1970 +0000
2744 | | | | | | summary: (17) expand
2751 | | | | | | summary: (17) expand
2745 | | | | | |
2752 | | | | | |
2746 +-+-------o changeset: 16:3677d192927d
2753 +-+-------o changeset: 16:3677d192927d
2747 | | | | | parent: 0:e6eb3150255d
2754 | | | | | parent: 0:e6eb3150255d
2748 | | | | | parent: 1:6db2ef61d156
2755 | | | | | parent: 1:6db2ef61d156
2749 | | | | | user: test
2756 | | | | | user: test
2750 | | | | | date: Thu Jan 01 00:00:16 1970 +0000
2757 | | | | | date: Thu Jan 01 00:00:16 1970 +0000
2751 | | | | | summary: (16) merge two known; one immediate right, one near right
2758 | | | | | summary: (16) merge two known; one immediate right, one near right
2752 | | | | |
2759 | | | | |
2753 | | | o | changeset: 15:1dda3f72782d
2760 | | | o | changeset: 15:1dda3f72782d
2754 | | | |\ \ parent: 13:22d8966a97e3
2761 | | | |\ \ parent: 13:22d8966a97e3
2755 | | | | | | parent: 14:8eac370358ef
2762 | | | | | | parent: 14:8eac370358ef
2756 | | | | | | user: test
2763 | | | | | | user: test
2757 | | | | | | date: Thu Jan 01 00:00:15 1970 +0000
2764 | | | | | | date: Thu Jan 01 00:00:15 1970 +0000
2758 | | | | | | summary: (15) expand
2765 | | | | | | summary: (15) expand
2759 | | | | | |
2766 | | | | | |
2760 +-------o | changeset: 14:8eac370358ef
2767 +-------o | changeset: 14:8eac370358ef
2761 | | | | |/ parent: 0:e6eb3150255d
2768 | | | | |/ parent: 0:e6eb3150255d
2762 | | | | | parent: 12:86b91144a6e9
2769 | | | | | parent: 12:86b91144a6e9
2763 | | | | | user: test
2770 | | | | | user: test
2764 | | | | | date: Thu Jan 01 00:00:14 1970 +0000
2771 | | | | | date: Thu Jan 01 00:00:14 1970 +0000
2765 | | | | | summary: (14) merge two known; one immediate right, one far right
2772 | | | | | summary: (14) merge two known; one immediate right, one far right
2766 | | | | |
2773 | | | | |
2767 | | | o | changeset: 13:22d8966a97e3
2774 | | | o | changeset: 13:22d8966a97e3
2768 | | | |\ \ parent: 9:7010c0af0a35
2775 | | | |\ \ parent: 9:7010c0af0a35
2769 | | | | | | parent: 11:832d76e6bdf2
2776 | | | | | | parent: 11:832d76e6bdf2
2770 | | | | | | user: test
2777 | | | | | | user: test
2771 | | | | | | date: Thu Jan 01 00:00:13 1970 +0000
2778 | | | | | | date: Thu Jan 01 00:00:13 1970 +0000
2772 | | | | | | summary: (13) expand
2779 | | | | | | summary: (13) expand
2773 | | | | | |
2780 | | | | | |
2774 | +---+---o changeset: 12:86b91144a6e9
2781 | +---+---o changeset: 12:86b91144a6e9
2775 | | | | | parent: 1:6db2ef61d156
2782 | | | | | parent: 1:6db2ef61d156
2776 | | | | | parent: 9:7010c0af0a35
2783 | | | | | parent: 9:7010c0af0a35
2777 | | | | | user: test
2784 | | | | | user: test
2778 | | | | | date: Thu Jan 01 00:00:12 1970 +0000
2785 | | | | | date: Thu Jan 01 00:00:12 1970 +0000
2779 | | | | | summary: (12) merge two known; one immediate right, one far left
2786 | | | | | summary: (12) merge two known; one immediate right, one far left
2780 | | | | |
2787 | | | | |
2781 | | | | o changeset: 11:832d76e6bdf2
2788 | | | | o changeset: 11:832d76e6bdf2
2782 | | | | |\ parent: 6:b105a072e251
2789 | | | | |\ parent: 6:b105a072e251
2783 | | | | | | parent: 10:74c64d036d72
2790 | | | | | | parent: 10:74c64d036d72
2784 | | | | | | user: test
2791 | | | | | | user: test
2785 | | | | | | date: Thu Jan 01 00:00:11 1970 +0000
2792 | | | | | | date: Thu Jan 01 00:00:11 1970 +0000
2786 | | | | | | summary: (11) expand
2793 | | | | | | summary: (11) expand
2787 | | | | | |
2794 | | | | | |
2788 +---------o changeset: 10:74c64d036d72
2795 +---------o changeset: 10:74c64d036d72
2789 | | | | |/ parent: 0:e6eb3150255d
2796 | | | | |/ parent: 0:e6eb3150255d
2790 | | | | | parent: 6:b105a072e251
2797 | | | | | parent: 6:b105a072e251
2791 | | | | | user: test
2798 | | | | | user: test
2792 | | | | | date: Thu Jan 01 00:00:10 1970 +0000
2799 | | | | | date: Thu Jan 01 00:00:10 1970 +0000
2793 | | | | | summary: (10) merge two known; one immediate left, one near right
2800 | | | | | summary: (10) merge two known; one immediate left, one near right
2794 | | | | |
2801 | | | | |
2795 | | | o | changeset: 9:7010c0af0a35
2802 | | | o | changeset: 9:7010c0af0a35
2796 | | | |\ \ parent: 7:b632bb1b1224
2803 | | | |\ \ parent: 7:b632bb1b1224
2797 | | | | | | parent: 8:7a0b11f71937
2804 | | | | | | parent: 8:7a0b11f71937
2798 | | | | | | user: test
2805 | | | | | | user: test
2799 | | | | | | date: Thu Jan 01 00:00:09 1970 +0000
2806 | | | | | | date: Thu Jan 01 00:00:09 1970 +0000
2800 | | | | | | summary: (9) expand
2807 | | | | | | summary: (9) expand
2801 | | | | | |
2808 | | | | | |
2802 +-------o | changeset: 8:7a0b11f71937
2809 +-------o | changeset: 8:7a0b11f71937
2803 | | | |/ / parent: 0:e6eb3150255d
2810 | | | |/ / parent: 0:e6eb3150255d
2804 | | | | | parent: 7:b632bb1b1224
2811 | | | | | parent: 7:b632bb1b1224
2805 | | | | | user: test
2812 | | | | | user: test
2806 | | | | | date: Thu Jan 01 00:00:08 1970 +0000
2813 | | | | | date: Thu Jan 01 00:00:08 1970 +0000
2807 | | | | | summary: (8) merge two known; one immediate left, one far right
2814 | | | | | summary: (8) merge two known; one immediate left, one far right
2808 | | | | |
2815 | | | | |
2809 | | | o | changeset: 7:b632bb1b1224
2816 | | | o | changeset: 7:b632bb1b1224
2810 | | | |\ \ parent: 2:3d9a33b8d1e1
2817 | | | |\ \ parent: 2:3d9a33b8d1e1
2811 | | | | | | parent: 5:4409d547b708
2818 | | | | | | parent: 5:4409d547b708
2812 | | | | | | user: test
2819 | | | | | | user: test
2813 | | | | | | date: Thu Jan 01 00:00:07 1970 +0000
2820 | | | | | | date: Thu Jan 01 00:00:07 1970 +0000
2814 | | | | | | summary: (7) expand
2821 | | | | | | summary: (7) expand
2815 | | | | | |
2822 | | | | | |
2816 | | | +---o changeset: 6:b105a072e251
2823 | | | +---o changeset: 6:b105a072e251
2817 | | | | |/ parent: 2:3d9a33b8d1e1
2824 | | | | |/ parent: 2:3d9a33b8d1e1
2818 | | | | | parent: 5:4409d547b708
2825 | | | | | parent: 5:4409d547b708
2819 | | | | | user: test
2826 | | | | | user: test
2820 | | | | | date: Thu Jan 01 00:00:06 1970 +0000
2827 | | | | | date: Thu Jan 01 00:00:06 1970 +0000
2821 | | | | | summary: (6) merge two known; one immediate left, one far left
2828 | | | | | summary: (6) merge two known; one immediate left, one far left
2822 | | | | |
2829 | | | | |
2823 | | | o | changeset: 5:4409d547b708
2830 | | | o | changeset: 5:4409d547b708
2824 | | | |\ \ parent: 3:27eef8ed80b4
2831 | | | |\ \ parent: 3:27eef8ed80b4
2825 | | | | | | parent: 4:26a8bac39d9f
2832 | | | | | | parent: 4:26a8bac39d9f
2826 | | | | | | user: test
2833 | | | | | | user: test
2827 | | | | | | date: Thu Jan 01 00:00:05 1970 +0000
2834 | | | | | | date: Thu Jan 01 00:00:05 1970 +0000
2828 | | | | | | summary: (5) expand
2835 | | | | | | summary: (5) expand
2829 | | | | | |
2836 | | | | | |
2830 | +---o | | changeset: 4:26a8bac39d9f
2837 | +---o | | changeset: 4:26a8bac39d9f
2831 | | | |/ / parent: 1:6db2ef61d156
2838 | | | |/ / parent: 1:6db2ef61d156
2832 | | | | | parent: 3:27eef8ed80b4
2839 | | | | | parent: 3:27eef8ed80b4
2833 | | | | | user: test
2840 | | | | | user: test
2834 | | | | | date: Thu Jan 01 00:00:04 1970 +0000
2841 | | | | | date: Thu Jan 01 00:00:04 1970 +0000
2835 | | | | | summary: (4) merge two known; one immediate left, one immediate right
2842 | | | | | summary: (4) merge two known; one immediate left, one immediate right
2836 | | | | |
2843 | | | | |
2837
2844
2838 .. unless HGPLAINEXCEPT=graph is set:
2845 .. unless HGPLAINEXCEPT=graph is set:
2839
2846
2840 $ HGPLAIN=1 HGPLAINEXCEPT=graph hg log -G -r 'file("a")' -m
2847 $ HGPLAIN=1 HGPLAINEXCEPT=graph hg log -G -r 'file("a")' -m
2841 @ changeset: 36:08a19a744424
2848 @ changeset: 36:08a19a744424
2842 : branch: branch
2849 : branch: branch
2843 : tag: tip
2850 : tag: tip
2844 : parent: 35:9159c3644c5e
2851 : parent: 35:9159c3644c5e
2845 : parent: 35:9159c3644c5e
2852 : parent: 35:9159c3644c5e
2846 : user: test
2853 : user: test
2847 : date: Thu Jan 01 00:00:36 1970 +0000
2854 : date: Thu Jan 01 00:00:36 1970 +0000
2848 : summary: (36) buggy merge: identical parents
2855 : summary: (36) buggy merge: identical parents
2849 :
2856 :
2850 o changeset: 32:d06dffa21a31
2857 o changeset: 32:d06dffa21a31
2851 |\ parent: 27:886ed638191b
2858 |\ parent: 27:886ed638191b
2852 | : parent: 31:621d83e11f67
2859 | : parent: 31:621d83e11f67
2853 | : user: test
2860 | : user: test
2854 | : date: Thu Jan 01 00:00:32 1970 +0000
2861 | : date: Thu Jan 01 00:00:32 1970 +0000
2855 | : summary: (32) expand
2862 | : summary: (32) expand
2856 | :
2863 | :
2857 o : changeset: 31:621d83e11f67
2864 o : changeset: 31:621d83e11f67
2858 |\: parent: 21:d42a756af44d
2865 |\: parent: 21:d42a756af44d
2859 | : parent: 30:6e11cd4b648f
2866 | : parent: 30:6e11cd4b648f
2860 | : user: test
2867 | : user: test
2861 | : date: Thu Jan 01 00:00:31 1970 +0000
2868 | : date: Thu Jan 01 00:00:31 1970 +0000
2862 | : summary: (31) expand
2869 | : summary: (31) expand
2863 | :
2870 | :
2864 o : changeset: 30:6e11cd4b648f
2871 o : changeset: 30:6e11cd4b648f
2865 |\ \ parent: 28:44ecd0b9ae99
2872 |\ \ parent: 28:44ecd0b9ae99
2866 | ~ : parent: 29:cd9bb2be7593
2873 | ~ : parent: 29:cd9bb2be7593
2867 | : user: test
2874 | : user: test
2868 | : date: Thu Jan 01 00:00:30 1970 +0000
2875 | : date: Thu Jan 01 00:00:30 1970 +0000
2869 | : summary: (30) expand
2876 | : summary: (30) expand
2870 | /
2877 | /
2871 o : changeset: 28:44ecd0b9ae99
2878 o : changeset: 28:44ecd0b9ae99
2872 |\ \ parent: 1:6db2ef61d156
2879 |\ \ parent: 1:6db2ef61d156
2873 | ~ : parent: 26:7f25b6c2f0b9
2880 | ~ : parent: 26:7f25b6c2f0b9
2874 | : user: test
2881 | : user: test
2875 | : date: Thu Jan 01 00:00:28 1970 +0000
2882 | : date: Thu Jan 01 00:00:28 1970 +0000
2876 | : summary: (28) merge zero known
2883 | : summary: (28) merge zero known
2877 | /
2884 | /
2878 o : changeset: 26:7f25b6c2f0b9
2885 o : changeset: 26:7f25b6c2f0b9
2879 |\ \ parent: 18:1aa84d96232a
2886 |\ \ parent: 18:1aa84d96232a
2880 | | : parent: 25:91da8ed57247
2887 | | : parent: 25:91da8ed57247
2881 | | : user: test
2888 | | : user: test
2882 | | : date: Thu Jan 01 00:00:26 1970 +0000
2889 | | : date: Thu Jan 01 00:00:26 1970 +0000
2883 | | : summary: (26) merge one known; far right
2890 | | : summary: (26) merge one known; far right
2884 | | :
2891 | | :
2885 | o : changeset: 25:91da8ed57247
2892 | o : changeset: 25:91da8ed57247
2886 | |\: parent: 21:d42a756af44d
2893 | |\: parent: 21:d42a756af44d
2887 | | : parent: 24:a9c19a3d96b7
2894 | | : parent: 24:a9c19a3d96b7
2888 | | : user: test
2895 | | : user: test
2889 | | : date: Thu Jan 01 00:00:25 1970 +0000
2896 | | : date: Thu Jan 01 00:00:25 1970 +0000
2890 | | : summary: (25) merge one known; far left
2897 | | : summary: (25) merge one known; far left
2891 | | :
2898 | | :
2892 | o : changeset: 24:a9c19a3d96b7
2899 | o : changeset: 24:a9c19a3d96b7
2893 | |\ \ parent: 0:e6eb3150255d
2900 | |\ \ parent: 0:e6eb3150255d
2894 | | ~ : parent: 23:a01cddf0766d
2901 | | ~ : parent: 23:a01cddf0766d
2895 | | : user: test
2902 | | : user: test
2896 | | : date: Thu Jan 01 00:00:24 1970 +0000
2903 | | : date: Thu Jan 01 00:00:24 1970 +0000
2897 | | : summary: (24) merge one known; immediate right
2904 | | : summary: (24) merge one known; immediate right
2898 | | /
2905 | | /
2899 | o : changeset: 23:a01cddf0766d
2906 | o : changeset: 23:a01cddf0766d
2900 | |\ \ parent: 1:6db2ef61d156
2907 | |\ \ parent: 1:6db2ef61d156
2901 | | ~ : parent: 22:e0d9cccacb5d
2908 | | ~ : parent: 22:e0d9cccacb5d
2902 | | : user: test
2909 | | : user: test
2903 | | : date: Thu Jan 01 00:00:23 1970 +0000
2910 | | : date: Thu Jan 01 00:00:23 1970 +0000
2904 | | : summary: (23) merge one known; immediate left
2911 | | : summary: (23) merge one known; immediate left
2905 | | /
2912 | | /
2906 | o : changeset: 22:e0d9cccacb5d
2913 | o : changeset: 22:e0d9cccacb5d
2907 |/:/ parent: 18:1aa84d96232a
2914 |/:/ parent: 18:1aa84d96232a
2908 | : parent: 21:d42a756af44d
2915 | : parent: 21:d42a756af44d
2909 | : user: test
2916 | : user: test
2910 | : date: Thu Jan 01 00:00:22 1970 +0000
2917 | : date: Thu Jan 01 00:00:22 1970 +0000
2911 | : summary: (22) merge two known; one far left, one far right
2918 | : summary: (22) merge two known; one far left, one far right
2912 | :
2919 | :
2913 | o changeset: 21:d42a756af44d
2920 | o changeset: 21:d42a756af44d
2914 | |\ parent: 19:31ddc2c1573b
2921 | |\ parent: 19:31ddc2c1573b
2915 | | | parent: 20:d30ed6450e32
2922 | | | parent: 20:d30ed6450e32
2916 | | | user: test
2923 | | | user: test
2917 | | | date: Thu Jan 01 00:00:21 1970 +0000
2924 | | | date: Thu Jan 01 00:00:21 1970 +0000
2918 | | | summary: (21) expand
2925 | | | summary: (21) expand
2919 | | |
2926 | | |
2920 +---o changeset: 20:d30ed6450e32
2927 +---o changeset: 20:d30ed6450e32
2921 | | | parent: 0:e6eb3150255d
2928 | | | parent: 0:e6eb3150255d
2922 | | ~ parent: 18:1aa84d96232a
2929 | | ~ parent: 18:1aa84d96232a
2923 | | user: test
2930 | | user: test
2924 | | date: Thu Jan 01 00:00:20 1970 +0000
2931 | | date: Thu Jan 01 00:00:20 1970 +0000
2925 | | summary: (20) merge two known; two far right
2932 | | summary: (20) merge two known; two far right
2926 | |
2933 | |
2927 | o changeset: 19:31ddc2c1573b
2934 | o changeset: 19:31ddc2c1573b
2928 | |\ parent: 15:1dda3f72782d
2935 | |\ parent: 15:1dda3f72782d
2929 | | | parent: 17:44765d7c06e0
2936 | | | parent: 17:44765d7c06e0
2930 | | | user: test
2937 | | | user: test
2931 | | | date: Thu Jan 01 00:00:19 1970 +0000
2938 | | | date: Thu Jan 01 00:00:19 1970 +0000
2932 | | | summary: (19) expand
2939 | | | summary: (19) expand
2933 | | |
2940 | | |
2934 o | | changeset: 18:1aa84d96232a
2941 o | | changeset: 18:1aa84d96232a
2935 |\| | parent: 1:6db2ef61d156
2942 |\| | parent: 1:6db2ef61d156
2936 ~ | | parent: 15:1dda3f72782d
2943 ~ | | parent: 15:1dda3f72782d
2937 | | user: test
2944 | | user: test
2938 | | date: Thu Jan 01 00:00:18 1970 +0000
2945 | | date: Thu Jan 01 00:00:18 1970 +0000
2939 | | summary: (18) merge two known; two far left
2946 | | summary: (18) merge two known; two far left
2940 / /
2947 / /
2941 | o changeset: 17:44765d7c06e0
2948 | o changeset: 17:44765d7c06e0
2942 | |\ parent: 12:86b91144a6e9
2949 | |\ parent: 12:86b91144a6e9
2943 | | | parent: 16:3677d192927d
2950 | | | parent: 16:3677d192927d
2944 | | | user: test
2951 | | | user: test
2945 | | | date: Thu Jan 01 00:00:17 1970 +0000
2952 | | | date: Thu Jan 01 00:00:17 1970 +0000
2946 | | | summary: (17) expand
2953 | | | summary: (17) expand
2947 | | |
2954 | | |
2948 | | o changeset: 16:3677d192927d
2955 | | o changeset: 16:3677d192927d
2949 | | |\ parent: 0:e6eb3150255d
2956 | | |\ parent: 0:e6eb3150255d
2950 | | ~ ~ parent: 1:6db2ef61d156
2957 | | ~ ~ parent: 1:6db2ef61d156
2951 | | user: test
2958 | | user: test
2952 | | date: Thu Jan 01 00:00:16 1970 +0000
2959 | | date: Thu Jan 01 00:00:16 1970 +0000
2953 | | summary: (16) merge two known; one immediate right, one near right
2960 | | summary: (16) merge two known; one immediate right, one near right
2954 | |
2961 | |
2955 o | changeset: 15:1dda3f72782d
2962 o | changeset: 15:1dda3f72782d
2956 |\ \ parent: 13:22d8966a97e3
2963 |\ \ parent: 13:22d8966a97e3
2957 | | | parent: 14:8eac370358ef
2964 | | | parent: 14:8eac370358ef
2958 | | | user: test
2965 | | | user: test
2959 | | | date: Thu Jan 01 00:00:15 1970 +0000
2966 | | | date: Thu Jan 01 00:00:15 1970 +0000
2960 | | | summary: (15) expand
2967 | | | summary: (15) expand
2961 | | |
2968 | | |
2962 | o | changeset: 14:8eac370358ef
2969 | o | changeset: 14:8eac370358ef
2963 | |\| parent: 0:e6eb3150255d
2970 | |\| parent: 0:e6eb3150255d
2964 | ~ | parent: 12:86b91144a6e9
2971 | ~ | parent: 12:86b91144a6e9
2965 | | user: test
2972 | | user: test
2966 | | date: Thu Jan 01 00:00:14 1970 +0000
2973 | | date: Thu Jan 01 00:00:14 1970 +0000
2967 | | summary: (14) merge two known; one immediate right, one far right
2974 | | summary: (14) merge two known; one immediate right, one far right
2968 | /
2975 | /
2969 o | changeset: 13:22d8966a97e3
2976 o | changeset: 13:22d8966a97e3
2970 |\ \ parent: 9:7010c0af0a35
2977 |\ \ parent: 9:7010c0af0a35
2971 | | | parent: 11:832d76e6bdf2
2978 | | | parent: 11:832d76e6bdf2
2972 | | | user: test
2979 | | | user: test
2973 | | | date: Thu Jan 01 00:00:13 1970 +0000
2980 | | | date: Thu Jan 01 00:00:13 1970 +0000
2974 | | | summary: (13) expand
2981 | | | summary: (13) expand
2975 | | |
2982 | | |
2976 +---o changeset: 12:86b91144a6e9
2983 +---o changeset: 12:86b91144a6e9
2977 | | | parent: 1:6db2ef61d156
2984 | | | parent: 1:6db2ef61d156
2978 | | ~ parent: 9:7010c0af0a35
2985 | | ~ parent: 9:7010c0af0a35
2979 | | user: test
2986 | | user: test
2980 | | date: Thu Jan 01 00:00:12 1970 +0000
2987 | | date: Thu Jan 01 00:00:12 1970 +0000
2981 | | summary: (12) merge two known; one immediate right, one far left
2988 | | summary: (12) merge two known; one immediate right, one far left
2982 | |
2989 | |
2983 | o changeset: 11:832d76e6bdf2
2990 | o changeset: 11:832d76e6bdf2
2984 | |\ parent: 6:b105a072e251
2991 | |\ parent: 6:b105a072e251
2985 | | | parent: 10:74c64d036d72
2992 | | | parent: 10:74c64d036d72
2986 | | | user: test
2993 | | | user: test
2987 | | | date: Thu Jan 01 00:00:11 1970 +0000
2994 | | | date: Thu Jan 01 00:00:11 1970 +0000
2988 | | | summary: (11) expand
2995 | | | summary: (11) expand
2989 | | |
2996 | | |
2990 | | o changeset: 10:74c64d036d72
2997 | | o changeset: 10:74c64d036d72
2991 | |/| parent: 0:e6eb3150255d
2998 | |/| parent: 0:e6eb3150255d
2992 | | ~ parent: 6:b105a072e251
2999 | | ~ parent: 6:b105a072e251
2993 | | user: test
3000 | | user: test
2994 | | date: Thu Jan 01 00:00:10 1970 +0000
3001 | | date: Thu Jan 01 00:00:10 1970 +0000
2995 | | summary: (10) merge two known; one immediate left, one near right
3002 | | summary: (10) merge two known; one immediate left, one near right
2996 | |
3003 | |
2997 o | changeset: 9:7010c0af0a35
3004 o | changeset: 9:7010c0af0a35
2998 |\ \ parent: 7:b632bb1b1224
3005 |\ \ parent: 7:b632bb1b1224
2999 | | | parent: 8:7a0b11f71937
3006 | | | parent: 8:7a0b11f71937
3000 | | | user: test
3007 | | | user: test
3001 | | | date: Thu Jan 01 00:00:09 1970 +0000
3008 | | | date: Thu Jan 01 00:00:09 1970 +0000
3002 | | | summary: (9) expand
3009 | | | summary: (9) expand
3003 | | |
3010 | | |
3004 | o | changeset: 8:7a0b11f71937
3011 | o | changeset: 8:7a0b11f71937
3005 |/| | parent: 0:e6eb3150255d
3012 |/| | parent: 0:e6eb3150255d
3006 | ~ | parent: 7:b632bb1b1224
3013 | ~ | parent: 7:b632bb1b1224
3007 | | user: test
3014 | | user: test
3008 | | date: Thu Jan 01 00:00:08 1970 +0000
3015 | | date: Thu Jan 01 00:00:08 1970 +0000
3009 | | summary: (8) merge two known; one immediate left, one far right
3016 | | summary: (8) merge two known; one immediate left, one far right
3010 | /
3017 | /
3011 o | changeset: 7:b632bb1b1224
3018 o | changeset: 7:b632bb1b1224
3012 |\ \ parent: 2:3d9a33b8d1e1
3019 |\ \ parent: 2:3d9a33b8d1e1
3013 | ~ | parent: 5:4409d547b708
3020 | ~ | parent: 5:4409d547b708
3014 | | user: test
3021 | | user: test
3015 | | date: Thu Jan 01 00:00:07 1970 +0000
3022 | | date: Thu Jan 01 00:00:07 1970 +0000
3016 | | summary: (7) expand
3023 | | summary: (7) expand
3017 | /
3024 | /
3018 | o changeset: 6:b105a072e251
3025 | o changeset: 6:b105a072e251
3019 |/| parent: 2:3d9a33b8d1e1
3026 |/| parent: 2:3d9a33b8d1e1
3020 | ~ parent: 5:4409d547b708
3027 | ~ parent: 5:4409d547b708
3021 | user: test
3028 | user: test
3022 | date: Thu Jan 01 00:00:06 1970 +0000
3029 | date: Thu Jan 01 00:00:06 1970 +0000
3023 | summary: (6) merge two known; one immediate left, one far left
3030 | summary: (6) merge two known; one immediate left, one far left
3024 |
3031 |
3025 o changeset: 5:4409d547b708
3032 o changeset: 5:4409d547b708
3026 |\ parent: 3:27eef8ed80b4
3033 |\ parent: 3:27eef8ed80b4
3027 | ~ parent: 4:26a8bac39d9f
3034 | ~ parent: 4:26a8bac39d9f
3028 | user: test
3035 | user: test
3029 | date: Thu Jan 01 00:00:05 1970 +0000
3036 | date: Thu Jan 01 00:00:05 1970 +0000
3030 | summary: (5) expand
3037 | summary: (5) expand
3031 |
3038 |
3032 o changeset: 4:26a8bac39d9f
3039 o changeset: 4:26a8bac39d9f
3033 |\ parent: 1:6db2ef61d156
3040 |\ parent: 1:6db2ef61d156
3034 ~ ~ parent: 3:27eef8ed80b4
3041 ~ ~ parent: 3:27eef8ed80b4
3035 user: test
3042 user: test
3036 date: Thu Jan 01 00:00:04 1970 +0000
3043 date: Thu Jan 01 00:00:04 1970 +0000
3037 summary: (4) merge two known; one immediate left, one immediate right
3044 summary: (4) merge two known; one immediate left, one immediate right
3038
3045
3039 Draw only part of a grandparent line differently with "<N><char>"; only the
3046 Draw only part of a grandparent line differently with "<N><char>"; only the
3040 last N lines (for positive N) or everything but the first N lines (for
3047 last N lines (for positive N) or everything but the first N lines (for
3041 negative N) along the current node use the style, the rest of the edge uses
3048 negative N) along the current node use the style, the rest of the edge uses
3042 the parent edge styling.
3049 the parent edge styling.
3043
3050
3044 Last 3 lines:
3051 Last 3 lines:
3045
3052
3046 $ cat << EOF >> $HGRCPATH
3053 $ cat << EOF >> $HGRCPATH
3047 > [experimental]
3054 > [experimental]
3048 > graphstyle.parent = !
3055 > graphstyle.parent = !
3049 > graphstyle.grandparent = 3.
3056 > graphstyle.grandparent = 3.
3050 > graphstyle.missing =
3057 > graphstyle.missing =
3051 > EOF
3058 > EOF
3052 $ hg log -G -r '36:18 & file("a")' -m
3059 $ hg log -G -r '36:18 & file("a")' -m
3053 @ changeset: 36:08a19a744424
3060 @ changeset: 36:08a19a744424
3054 ! branch: branch
3061 ! branch: branch
3055 ! tag: tip
3062 ! tag: tip
3056 ! parent: 35:9159c3644c5e
3063 ! parent: 35:9159c3644c5e
3057 ! parent: 35:9159c3644c5e
3064 ! parent: 35:9159c3644c5e
3058 ! user: test
3065 ! user: test
3059 . date: Thu Jan 01 00:00:36 1970 +0000
3066 . date: Thu Jan 01 00:00:36 1970 +0000
3060 . summary: (36) buggy merge: identical parents
3067 . summary: (36) buggy merge: identical parents
3061 .
3068 .
3062 o changeset: 32:d06dffa21a31
3069 o changeset: 32:d06dffa21a31
3063 !\ parent: 27:886ed638191b
3070 !\ parent: 27:886ed638191b
3064 ! ! parent: 31:621d83e11f67
3071 ! ! parent: 31:621d83e11f67
3065 ! ! user: test
3072 ! ! user: test
3066 ! . date: Thu Jan 01 00:00:32 1970 +0000
3073 ! . date: Thu Jan 01 00:00:32 1970 +0000
3067 ! . summary: (32) expand
3074 ! . summary: (32) expand
3068 ! .
3075 ! .
3069 o ! changeset: 31:621d83e11f67
3076 o ! changeset: 31:621d83e11f67
3070 !\! parent: 21:d42a756af44d
3077 !\! parent: 21:d42a756af44d
3071 ! ! parent: 30:6e11cd4b648f
3078 ! ! parent: 30:6e11cd4b648f
3072 ! ! user: test
3079 ! ! user: test
3073 ! ! date: Thu Jan 01 00:00:31 1970 +0000
3080 ! ! date: Thu Jan 01 00:00:31 1970 +0000
3074 ! ! summary: (31) expand
3081 ! ! summary: (31) expand
3075 ! !
3082 ! !
3076 o ! changeset: 30:6e11cd4b648f
3083 o ! changeset: 30:6e11cd4b648f
3077 !\ \ parent: 28:44ecd0b9ae99
3084 !\ \ parent: 28:44ecd0b9ae99
3078 ! ~ ! parent: 29:cd9bb2be7593
3085 ! ~ ! parent: 29:cd9bb2be7593
3079 ! ! user: test
3086 ! ! user: test
3080 ! ! date: Thu Jan 01 00:00:30 1970 +0000
3087 ! ! date: Thu Jan 01 00:00:30 1970 +0000
3081 ! ! summary: (30) expand
3088 ! ! summary: (30) expand
3082 ! /
3089 ! /
3083 o ! changeset: 28:44ecd0b9ae99
3090 o ! changeset: 28:44ecd0b9ae99
3084 !\ \ parent: 1:6db2ef61d156
3091 !\ \ parent: 1:6db2ef61d156
3085 ! ~ ! parent: 26:7f25b6c2f0b9
3092 ! ~ ! parent: 26:7f25b6c2f0b9
3086 ! ! user: test
3093 ! ! user: test
3087 ! ! date: Thu Jan 01 00:00:28 1970 +0000
3094 ! ! date: Thu Jan 01 00:00:28 1970 +0000
3088 ! ! summary: (28) merge zero known
3095 ! ! summary: (28) merge zero known
3089 ! /
3096 ! /
3090 o ! changeset: 26:7f25b6c2f0b9
3097 o ! changeset: 26:7f25b6c2f0b9
3091 !\ \ parent: 18:1aa84d96232a
3098 !\ \ parent: 18:1aa84d96232a
3092 ! ! ! parent: 25:91da8ed57247
3099 ! ! ! parent: 25:91da8ed57247
3093 ! ! ! user: test
3100 ! ! ! user: test
3094 ! ! ! date: Thu Jan 01 00:00:26 1970 +0000
3101 ! ! ! date: Thu Jan 01 00:00:26 1970 +0000
3095 ! ! ! summary: (26) merge one known; far right
3102 ! ! ! summary: (26) merge one known; far right
3096 ! ! !
3103 ! ! !
3097 ! o ! changeset: 25:91da8ed57247
3104 ! o ! changeset: 25:91da8ed57247
3098 ! !\! parent: 21:d42a756af44d
3105 ! !\! parent: 21:d42a756af44d
3099 ! ! ! parent: 24:a9c19a3d96b7
3106 ! ! ! parent: 24:a9c19a3d96b7
3100 ! ! ! user: test
3107 ! ! ! user: test
3101 ! ! ! date: Thu Jan 01 00:00:25 1970 +0000
3108 ! ! ! date: Thu Jan 01 00:00:25 1970 +0000
3102 ! ! ! summary: (25) merge one known; far left
3109 ! ! ! summary: (25) merge one known; far left
3103 ! ! !
3110 ! ! !
3104 ! o ! changeset: 24:a9c19a3d96b7
3111 ! o ! changeset: 24:a9c19a3d96b7
3105 ! !\ \ parent: 0:e6eb3150255d
3112 ! !\ \ parent: 0:e6eb3150255d
3106 ! ! ~ ! parent: 23:a01cddf0766d
3113 ! ! ~ ! parent: 23:a01cddf0766d
3107 ! ! ! user: test
3114 ! ! ! user: test
3108 ! ! ! date: Thu Jan 01 00:00:24 1970 +0000
3115 ! ! ! date: Thu Jan 01 00:00:24 1970 +0000
3109 ! ! ! summary: (24) merge one known; immediate right
3116 ! ! ! summary: (24) merge one known; immediate right
3110 ! ! /
3117 ! ! /
3111 ! o ! changeset: 23:a01cddf0766d
3118 ! o ! changeset: 23:a01cddf0766d
3112 ! !\ \ parent: 1:6db2ef61d156
3119 ! !\ \ parent: 1:6db2ef61d156
3113 ! ! ~ ! parent: 22:e0d9cccacb5d
3120 ! ! ~ ! parent: 22:e0d9cccacb5d
3114 ! ! ! user: test
3121 ! ! ! user: test
3115 ! ! ! date: Thu Jan 01 00:00:23 1970 +0000
3122 ! ! ! date: Thu Jan 01 00:00:23 1970 +0000
3116 ! ! ! summary: (23) merge one known; immediate left
3123 ! ! ! summary: (23) merge one known; immediate left
3117 ! ! /
3124 ! ! /
3118 ! o ! changeset: 22:e0d9cccacb5d
3125 ! o ! changeset: 22:e0d9cccacb5d
3119 !/!/ parent: 18:1aa84d96232a
3126 !/!/ parent: 18:1aa84d96232a
3120 ! ! parent: 21:d42a756af44d
3127 ! ! parent: 21:d42a756af44d
3121 ! ! user: test
3128 ! ! user: test
3122 ! ! date: Thu Jan 01 00:00:22 1970 +0000
3129 ! ! date: Thu Jan 01 00:00:22 1970 +0000
3123 ! ! summary: (22) merge two known; one far left, one far right
3130 ! ! summary: (22) merge two known; one far left, one far right
3124 ! !
3131 ! !
3125 ! o changeset: 21:d42a756af44d
3132 ! o changeset: 21:d42a756af44d
3126 ! !\ parent: 19:31ddc2c1573b
3133 ! !\ parent: 19:31ddc2c1573b
3127 ! ! ! parent: 20:d30ed6450e32
3134 ! ! ! parent: 20:d30ed6450e32
3128 ! ! ! user: test
3135 ! ! ! user: test
3129 ! ! ! date: Thu Jan 01 00:00:21 1970 +0000
3136 ! ! ! date: Thu Jan 01 00:00:21 1970 +0000
3130 ! ! ! summary: (21) expand
3137 ! ! ! summary: (21) expand
3131 ! ! !
3138 ! ! !
3132 +---o changeset: 20:d30ed6450e32
3139 +---o changeset: 20:d30ed6450e32
3133 ! ! | parent: 0:e6eb3150255d
3140 ! ! | parent: 0:e6eb3150255d
3134 ! ! ~ parent: 18:1aa84d96232a
3141 ! ! ~ parent: 18:1aa84d96232a
3135 ! ! user: test
3142 ! ! user: test
3136 ! ! date: Thu Jan 01 00:00:20 1970 +0000
3143 ! ! date: Thu Jan 01 00:00:20 1970 +0000
3137 ! ! summary: (20) merge two known; two far right
3144 ! ! summary: (20) merge two known; two far right
3138 ! !
3145 ! !
3139 ! o changeset: 19:31ddc2c1573b
3146 ! o changeset: 19:31ddc2c1573b
3140 ! |\ parent: 15:1dda3f72782d
3147 ! |\ parent: 15:1dda3f72782d
3141 ! ~ ~ parent: 17:44765d7c06e0
3148 ! ~ ~ parent: 17:44765d7c06e0
3142 ! user: test
3149 ! user: test
3143 ! date: Thu Jan 01 00:00:19 1970 +0000
3150 ! date: Thu Jan 01 00:00:19 1970 +0000
3144 ! summary: (19) expand
3151 ! summary: (19) expand
3145 !
3152 !
3146 o changeset: 18:1aa84d96232a
3153 o changeset: 18:1aa84d96232a
3147 |\ parent: 1:6db2ef61d156
3154 |\ parent: 1:6db2ef61d156
3148 ~ ~ parent: 15:1dda3f72782d
3155 ~ ~ parent: 15:1dda3f72782d
3149 user: test
3156 user: test
3150 date: Thu Jan 01 00:00:18 1970 +0000
3157 date: Thu Jan 01 00:00:18 1970 +0000
3151 summary: (18) merge two known; two far left
3158 summary: (18) merge two known; two far left
3152
3159
3153 All but the first 3 lines:
3160 All but the first 3 lines:
3154
3161
3155 $ cat << EOF >> $HGRCPATH
3162 $ cat << EOF >> $HGRCPATH
3156 > [experimental]
3163 > [experimental]
3157 > graphstyle.parent = !
3164 > graphstyle.parent = !
3158 > graphstyle.grandparent = -3.
3165 > graphstyle.grandparent = -3.
3159 > graphstyle.missing =
3166 > graphstyle.missing =
3160 > EOF
3167 > EOF
3161 $ hg log -G -r '36:18 & file("a")' -m
3168 $ hg log -G -r '36:18 & file("a")' -m
3162 @ changeset: 36:08a19a744424
3169 @ changeset: 36:08a19a744424
3163 ! branch: branch
3170 ! branch: branch
3164 ! tag: tip
3171 ! tag: tip
3165 . parent: 35:9159c3644c5e
3172 . parent: 35:9159c3644c5e
3166 . parent: 35:9159c3644c5e
3173 . parent: 35:9159c3644c5e
3167 . user: test
3174 . user: test
3168 . date: Thu Jan 01 00:00:36 1970 +0000
3175 . date: Thu Jan 01 00:00:36 1970 +0000
3169 . summary: (36) buggy merge: identical parents
3176 . summary: (36) buggy merge: identical parents
3170 .
3177 .
3171 o changeset: 32:d06dffa21a31
3178 o changeset: 32:d06dffa21a31
3172 !\ parent: 27:886ed638191b
3179 !\ parent: 27:886ed638191b
3173 ! ! parent: 31:621d83e11f67
3180 ! ! parent: 31:621d83e11f67
3174 ! . user: test
3181 ! . user: test
3175 ! . date: Thu Jan 01 00:00:32 1970 +0000
3182 ! . date: Thu Jan 01 00:00:32 1970 +0000
3176 ! . summary: (32) expand
3183 ! . summary: (32) expand
3177 ! .
3184 ! .
3178 o ! changeset: 31:621d83e11f67
3185 o ! changeset: 31:621d83e11f67
3179 !\! parent: 21:d42a756af44d
3186 !\! parent: 21:d42a756af44d
3180 ! ! parent: 30:6e11cd4b648f
3187 ! ! parent: 30:6e11cd4b648f
3181 ! ! user: test
3188 ! ! user: test
3182 ! ! date: Thu Jan 01 00:00:31 1970 +0000
3189 ! ! date: Thu Jan 01 00:00:31 1970 +0000
3183 ! ! summary: (31) expand
3190 ! ! summary: (31) expand
3184 ! !
3191 ! !
3185 o ! changeset: 30:6e11cd4b648f
3192 o ! changeset: 30:6e11cd4b648f
3186 !\ \ parent: 28:44ecd0b9ae99
3193 !\ \ parent: 28:44ecd0b9ae99
3187 ! ~ ! parent: 29:cd9bb2be7593
3194 ! ~ ! parent: 29:cd9bb2be7593
3188 ! ! user: test
3195 ! ! user: test
3189 ! ! date: Thu Jan 01 00:00:30 1970 +0000
3196 ! ! date: Thu Jan 01 00:00:30 1970 +0000
3190 ! ! summary: (30) expand
3197 ! ! summary: (30) expand
3191 ! /
3198 ! /
3192 o ! changeset: 28:44ecd0b9ae99
3199 o ! changeset: 28:44ecd0b9ae99
3193 !\ \ parent: 1:6db2ef61d156
3200 !\ \ parent: 1:6db2ef61d156
3194 ! ~ ! parent: 26:7f25b6c2f0b9
3201 ! ~ ! parent: 26:7f25b6c2f0b9
3195 ! ! user: test
3202 ! ! user: test
3196 ! ! date: Thu Jan 01 00:00:28 1970 +0000
3203 ! ! date: Thu Jan 01 00:00:28 1970 +0000
3197 ! ! summary: (28) merge zero known
3204 ! ! summary: (28) merge zero known
3198 ! /
3205 ! /
3199 o ! changeset: 26:7f25b6c2f0b9
3206 o ! changeset: 26:7f25b6c2f0b9
3200 !\ \ parent: 18:1aa84d96232a
3207 !\ \ parent: 18:1aa84d96232a
3201 ! ! ! parent: 25:91da8ed57247
3208 ! ! ! parent: 25:91da8ed57247
3202 ! ! ! user: test
3209 ! ! ! user: test
3203 ! ! ! date: Thu Jan 01 00:00:26 1970 +0000
3210 ! ! ! date: Thu Jan 01 00:00:26 1970 +0000
3204 ! ! ! summary: (26) merge one known; far right
3211 ! ! ! summary: (26) merge one known; far right
3205 ! ! !
3212 ! ! !
3206 ! o ! changeset: 25:91da8ed57247
3213 ! o ! changeset: 25:91da8ed57247
3207 ! !\! parent: 21:d42a756af44d
3214 ! !\! parent: 21:d42a756af44d
3208 ! ! ! parent: 24:a9c19a3d96b7
3215 ! ! ! parent: 24:a9c19a3d96b7
3209 ! ! ! user: test
3216 ! ! ! user: test
3210 ! ! ! date: Thu Jan 01 00:00:25 1970 +0000
3217 ! ! ! date: Thu Jan 01 00:00:25 1970 +0000
3211 ! ! ! summary: (25) merge one known; far left
3218 ! ! ! summary: (25) merge one known; far left
3212 ! ! !
3219 ! ! !
3213 ! o ! changeset: 24:a9c19a3d96b7
3220 ! o ! changeset: 24:a9c19a3d96b7
3214 ! !\ \ parent: 0:e6eb3150255d
3221 ! !\ \ parent: 0:e6eb3150255d
3215 ! ! ~ ! parent: 23:a01cddf0766d
3222 ! ! ~ ! parent: 23:a01cddf0766d
3216 ! ! ! user: test
3223 ! ! ! user: test
3217 ! ! ! date: Thu Jan 01 00:00:24 1970 +0000
3224 ! ! ! date: Thu Jan 01 00:00:24 1970 +0000
3218 ! ! ! summary: (24) merge one known; immediate right
3225 ! ! ! summary: (24) merge one known; immediate right
3219 ! ! /
3226 ! ! /
3220 ! o ! changeset: 23:a01cddf0766d
3227 ! o ! changeset: 23:a01cddf0766d
3221 ! !\ \ parent: 1:6db2ef61d156
3228 ! !\ \ parent: 1:6db2ef61d156
3222 ! ! ~ ! parent: 22:e0d9cccacb5d
3229 ! ! ~ ! parent: 22:e0d9cccacb5d
3223 ! ! ! user: test
3230 ! ! ! user: test
3224 ! ! ! date: Thu Jan 01 00:00:23 1970 +0000
3231 ! ! ! date: Thu Jan 01 00:00:23 1970 +0000
3225 ! ! ! summary: (23) merge one known; immediate left
3232 ! ! ! summary: (23) merge one known; immediate left
3226 ! ! /
3233 ! ! /
3227 ! o ! changeset: 22:e0d9cccacb5d
3234 ! o ! changeset: 22:e0d9cccacb5d
3228 !/!/ parent: 18:1aa84d96232a
3235 !/!/ parent: 18:1aa84d96232a
3229 ! ! parent: 21:d42a756af44d
3236 ! ! parent: 21:d42a756af44d
3230 ! ! user: test
3237 ! ! user: test
3231 ! ! date: Thu Jan 01 00:00:22 1970 +0000
3238 ! ! date: Thu Jan 01 00:00:22 1970 +0000
3232 ! ! summary: (22) merge two known; one far left, one far right
3239 ! ! summary: (22) merge two known; one far left, one far right
3233 ! !
3240 ! !
3234 ! o changeset: 21:d42a756af44d
3241 ! o changeset: 21:d42a756af44d
3235 ! !\ parent: 19:31ddc2c1573b
3242 ! !\ parent: 19:31ddc2c1573b
3236 ! ! ! parent: 20:d30ed6450e32
3243 ! ! ! parent: 20:d30ed6450e32
3237 ! ! ! user: test
3244 ! ! ! user: test
3238 ! ! ! date: Thu Jan 01 00:00:21 1970 +0000
3245 ! ! ! date: Thu Jan 01 00:00:21 1970 +0000
3239 ! ! ! summary: (21) expand
3246 ! ! ! summary: (21) expand
3240 ! ! !
3247 ! ! !
3241 +---o changeset: 20:d30ed6450e32
3248 +---o changeset: 20:d30ed6450e32
3242 ! ! | parent: 0:e6eb3150255d
3249 ! ! | parent: 0:e6eb3150255d
3243 ! ! ~ parent: 18:1aa84d96232a
3250 ! ! ~ parent: 18:1aa84d96232a
3244 ! ! user: test
3251 ! ! user: test
3245 ! ! date: Thu Jan 01 00:00:20 1970 +0000
3252 ! ! date: Thu Jan 01 00:00:20 1970 +0000
3246 ! ! summary: (20) merge two known; two far right
3253 ! ! summary: (20) merge two known; two far right
3247 ! !
3254 ! !
3248 ! o changeset: 19:31ddc2c1573b
3255 ! o changeset: 19:31ddc2c1573b
3249 ! |\ parent: 15:1dda3f72782d
3256 ! |\ parent: 15:1dda3f72782d
3250 ! ~ ~ parent: 17:44765d7c06e0
3257 ! ~ ~ parent: 17:44765d7c06e0
3251 ! user: test
3258 ! user: test
3252 ! date: Thu Jan 01 00:00:19 1970 +0000
3259 ! date: Thu Jan 01 00:00:19 1970 +0000
3253 ! summary: (19) expand
3260 ! summary: (19) expand
3254 !
3261 !
3255 o changeset: 18:1aa84d96232a
3262 o changeset: 18:1aa84d96232a
3256 |\ parent: 1:6db2ef61d156
3263 |\ parent: 1:6db2ef61d156
3257 ~ ~ parent: 15:1dda3f72782d
3264 ~ ~ parent: 15:1dda3f72782d
3258 user: test
3265 user: test
3259 date: Thu Jan 01 00:00:18 1970 +0000
3266 date: Thu Jan 01 00:00:18 1970 +0000
3260 summary: (18) merge two known; two far left
3267 summary: (18) merge two known; two far left
3261
3268
3262 $ cd ..
3269 $ cd ..
3263
3270
3264 Change graph shorten, test better with graphstyle.missing not none
3271 Change graph shorten, test better with graphstyle.missing not none
3265
3272
3266 $ cd repo
3273 $ cd repo
3267 $ cat << EOF >> $HGRCPATH
3274 $ cat << EOF >> $HGRCPATH
3268 > [experimental]
3275 > [experimental]
3269 > graphstyle.parent = |
3276 > graphstyle.parent = |
3270 > graphstyle.grandparent = :
3277 > graphstyle.grandparent = :
3271 > graphstyle.missing = '
3278 > graphstyle.missing = '
3272 > graphshorten = true
3279 > graphshorten = true
3273 > EOF
3280 > EOF
3274 $ hg log -G -r 'file("a")' -m -T '{rev} {desc}'
3281 $ hg log -G -r 'file("a")' -m -T '{rev} {desc}'
3275 @ 36 (36) buggy merge: identical parents
3282 @ 36 (36) buggy merge: identical parents
3276 o 32 (32) expand
3283 o 32 (32) expand
3277 |\
3284 |\
3278 o : 31 (31) expand
3285 o : 31 (31) expand
3279 |\:
3286 |\:
3280 o : 30 (30) expand
3287 o : 30 (30) expand
3281 |\ \
3288 |\ \
3282 o \ \ 28 (28) merge zero known
3289 o \ \ 28 (28) merge zero known
3283 |\ \ \
3290 |\ \ \
3284 o \ \ \ 26 (26) merge one known; far right
3291 o \ \ \ 26 (26) merge one known; far right
3285 |\ \ \ \
3292 |\ \ \ \
3286 | o-----+ 25 (25) merge one known; far left
3293 | o-----+ 25 (25) merge one known; far left
3287 | o ' ' : 24 (24) merge one known; immediate right
3294 | o ' ' : 24 (24) merge one known; immediate right
3288 | |\ \ \ \
3295 | |\ \ \ \
3289 | o---+ ' : 23 (23) merge one known; immediate left
3296 | o---+ ' : 23 (23) merge one known; immediate left
3290 | o-------+ 22 (22) merge two known; one far left, one far right
3297 | o-------+ 22 (22) merge two known; one far left, one far right
3291 |/ / / / /
3298 |/ / / / /
3292 | ' ' ' o 21 (21) expand
3299 | ' ' ' o 21 (21) expand
3293 | ' ' ' |\
3300 | ' ' ' |\
3294 +-+-------o 20 (20) merge two known; two far right
3301 +-+-------o 20 (20) merge two known; two far right
3295 | ' ' ' o 19 (19) expand
3302 | ' ' ' o 19 (19) expand
3296 | ' ' ' |\
3303 | ' ' ' |\
3297 o---+---+ | 18 (18) merge two known; two far left
3304 o---+---+ | 18 (18) merge two known; two far left
3298 / / / / /
3305 / / / / /
3299 ' ' ' | o 17 (17) expand
3306 ' ' ' | o 17 (17) expand
3300 ' ' ' | |\
3307 ' ' ' | |\
3301 +-+-------o 16 (16) merge two known; one immediate right, one near right
3308 +-+-------o 16 (16) merge two known; one immediate right, one near right
3302 ' ' ' o | 15 (15) expand
3309 ' ' ' o | 15 (15) expand
3303 ' ' ' |\ \
3310 ' ' ' |\ \
3304 +-------o | 14 (14) merge two known; one immediate right, one far right
3311 +-------o | 14 (14) merge two known; one immediate right, one far right
3305 ' ' ' | |/
3312 ' ' ' | |/
3306 ' ' ' o | 13 (13) expand
3313 ' ' ' o | 13 (13) expand
3307 ' ' ' |\ \
3314 ' ' ' |\ \
3308 ' +---+---o 12 (12) merge two known; one immediate right, one far left
3315 ' +---+---o 12 (12) merge two known; one immediate right, one far left
3309 ' ' ' | o 11 (11) expand
3316 ' ' ' | o 11 (11) expand
3310 ' ' ' | |\
3317 ' ' ' | |\
3311 +---------o 10 (10) merge two known; one immediate left, one near right
3318 +---------o 10 (10) merge two known; one immediate left, one near right
3312 ' ' ' | |/
3319 ' ' ' | |/
3313 ' ' ' o | 9 (9) expand
3320 ' ' ' o | 9 (9) expand
3314 ' ' ' |\ \
3321 ' ' ' |\ \
3315 +-------o | 8 (8) merge two known; one immediate left, one far right
3322 +-------o | 8 (8) merge two known; one immediate left, one far right
3316 ' ' ' |/ /
3323 ' ' ' |/ /
3317 ' ' ' o | 7 (7) expand
3324 ' ' ' o | 7 (7) expand
3318 ' ' ' |\ \
3325 ' ' ' |\ \
3319 ' ' ' +---o 6 (6) merge two known; one immediate left, one far left
3326 ' ' ' +---o 6 (6) merge two known; one immediate left, one far left
3320 ' ' ' | '/
3327 ' ' ' | '/
3321 ' ' ' o ' 5 (5) expand
3328 ' ' ' o ' 5 (5) expand
3322 ' ' ' |\ \
3329 ' ' ' |\ \
3323 ' +---o ' ' 4 (4) merge two known; one immediate left, one immediate right
3330 ' +---o ' ' 4 (4) merge two known; one immediate left, one immediate right
3324 ' ' ' '/ /
3331 ' ' ' '/ /
3325
3332
3326 behavior with newlines
3333 behavior with newlines
3327
3334
3328 $ hg log -G -r ::2 -T '{rev} {desc}'
3335 $ hg log -G -r ::2 -T '{rev} {desc}'
3329 o 2 (2) collapse
3336 o 2 (2) collapse
3330 o 1 (1) collapse
3337 o 1 (1) collapse
3331 o 0 (0) root
3338 o 0 (0) root
3332
3339
3333 $ hg log -G -r ::2 -T '{rev} {desc}\n'
3340 $ hg log -G -r ::2 -T '{rev} {desc}\n'
3334 o 2 (2) collapse
3341 o 2 (2) collapse
3335 o 1 (1) collapse
3342 o 1 (1) collapse
3336 o 0 (0) root
3343 o 0 (0) root
3337
3344
3338 $ hg log -G -r ::2 -T '{rev} {desc}\n\n'
3345 $ hg log -G -r ::2 -T '{rev} {desc}\n\n'
3339 o 2 (2) collapse
3346 o 2 (2) collapse
3340 |
3347 |
3341 o 1 (1) collapse
3348 o 1 (1) collapse
3342 |
3349 |
3343 o 0 (0) root
3350 o 0 (0) root
3344
3351
3345
3352
3346 $ hg log -G -r ::2 -T '\n{rev} {desc}'
3353 $ hg log -G -r ::2 -T '\n{rev} {desc}'
3347 o
3354 o
3348 | 2 (2) collapse
3355 | 2 (2) collapse
3349 o
3356 o
3350 | 1 (1) collapse
3357 | 1 (1) collapse
3351 o
3358 o
3352 0 (0) root
3359 0 (0) root
3353
3360
3354 $ hg log -G -r ::2 -T '{rev} {desc}\n\n\n'
3361 $ hg log -G -r ::2 -T '{rev} {desc}\n\n\n'
3355 o 2 (2) collapse
3362 o 2 (2) collapse
3356 |
3363 |
3357 |
3364 |
3358 o 1 (1) collapse
3365 o 1 (1) collapse
3359 |
3366 |
3360 |
3367 |
3361 o 0 (0) root
3368 o 0 (0) root
3362
3369
3363
3370
3364 $ cd ..
3371 $ cd ..
3365
3372
3366 When inserting extra line nodes to handle more than 2 parents, ensure that
3373 When inserting extra line nodes to handle more than 2 parents, ensure that
3367 the right node styles are used (issue5174):
3374 the right node styles are used (issue5174):
3368
3375
3369 $ hg init repo-issue5174
3376 $ hg init repo-issue5174
3370 $ cd repo-issue5174
3377 $ cd repo-issue5174
3371 $ echo a > f0
3378 $ echo a > f0
3372 $ hg ci -Aqm 0
3379 $ hg ci -Aqm 0
3373 $ echo a > f1
3380 $ echo a > f1
3374 $ hg ci -Aqm 1
3381 $ hg ci -Aqm 1
3375 $ echo a > f2
3382 $ echo a > f2
3376 $ hg ci -Aqm 2
3383 $ hg ci -Aqm 2
3377 $ hg co ".^"
3384 $ hg co ".^"
3378 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
3385 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
3379 $ echo a > f3
3386 $ echo a > f3
3380 $ hg ci -Aqm 3
3387 $ hg ci -Aqm 3
3381 $ hg co ".^^"
3388 $ hg co ".^^"
3382 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
3389 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
3383 $ echo a > f4
3390 $ echo a > f4
3384 $ hg ci -Aqm 4
3391 $ hg ci -Aqm 4
3385 $ hg merge -r 2
3392 $ hg merge -r 2
3386 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
3393 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
3387 (branch merge, don't forget to commit)
3394 (branch merge, don't forget to commit)
3388 $ hg ci -qm 5
3395 $ hg ci -qm 5
3389 $ hg merge -r 3
3396 $ hg merge -r 3
3390 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3397 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3391 (branch merge, don't forget to commit)
3398 (branch merge, don't forget to commit)
3392 $ hg ci -qm 6
3399 $ hg ci -qm 6
3393 $ hg log -G -r '0 | 1 | 2 | 6'
3400 $ hg log -G -r '0 | 1 | 2 | 6'
3394 @ changeset: 6:851fe89689ad
3401 @ changeset: 6:851fe89689ad
3395 :\ tag: tip
3402 :\ tag: tip
3396 : : parent: 5:4f1e3cf15f5d
3403 : : parent: 5:4f1e3cf15f5d
3397 : : parent: 3:b74ba7084d2d
3404 : : parent: 3:b74ba7084d2d
3398 : : user: test
3405 : : user: test
3399 : : date: Thu Jan 01 00:00:00 1970 +0000
3406 : : date: Thu Jan 01 00:00:00 1970 +0000
3400 : : summary: 6
3407 : : summary: 6
3401 : :
3408 : :
3402 : \
3409 : \
3403 : :\
3410 : :\
3404 : o : changeset: 2:3e6599df4cce
3411 : o : changeset: 2:3e6599df4cce
3405 : :/ user: test
3412 : :/ user: test
3406 : : date: Thu Jan 01 00:00:00 1970 +0000
3413 : : date: Thu Jan 01 00:00:00 1970 +0000
3407 : : summary: 2
3414 : : summary: 2
3408 : :
3415 : :
3409 : o changeset: 1:bd9a55143933
3416 : o changeset: 1:bd9a55143933
3410 :/ user: test
3417 :/ user: test
3411 : date: Thu Jan 01 00:00:00 1970 +0000
3418 : date: Thu Jan 01 00:00:00 1970 +0000
3412 : summary: 1
3419 : summary: 1
3413 :
3420 :
3414 o changeset: 0:870a5edc339c
3421 o changeset: 0:870a5edc339c
3415 user: test
3422 user: test
3416 date: Thu Jan 01 00:00:00 1970 +0000
3423 date: Thu Jan 01 00:00:00 1970 +0000
3417 summary: 0
3424 summary: 0
3418
3425
3419
3426
@@ -1,3350 +1,3391 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 > testrevset=$TESTTMP/testrevset.py
23 > testrevset=$TESTTMP/testrevset.py
24 > EOF
24 > EOF
25
25
26 $ try() {
26 $ try() {
27 > hg debugrevspec --debug "$@"
27 > hg debugrevspec --debug "$@"
28 > }
28 > }
29
29
30 $ log() {
30 $ log() {
31 > hg log --template '{rev}\n' -r "$1"
31 > hg log --template '{rev}\n' -r "$1"
32 > }
32 > }
33
33
34 extension to build '_intlist()' and '_hexlist()', which is necessary because
34 extension to build '_intlist()' and '_hexlist()', which is necessary because
35 these predicates use '\0' as a separator:
35 these predicates use '\0' as a separator:
36
36
37 $ cat <<EOF > debugrevlistspec.py
37 $ cat <<EOF > debugrevlistspec.py
38 > from __future__ import absolute_import
38 > from __future__ import absolute_import
39 > from mercurial import (
39 > from mercurial import (
40 > cmdutil,
40 > cmdutil,
41 > node as nodemod,
41 > node as nodemod,
42 > revset,
42 > revset,
43 > )
43 > )
44 > cmdtable = {}
44 > cmdtable = {}
45 > command = cmdutil.command(cmdtable)
45 > command = cmdutil.command(cmdtable)
46 > @command('debugrevlistspec',
46 > @command('debugrevlistspec',
47 > [('', 'optimize', None, 'print parsed tree after optimizing'),
47 > [('', 'optimize', None, 'print parsed tree after optimizing'),
48 > ('', 'bin', None, 'unhexlify arguments')])
48 > ('', 'bin', None, 'unhexlify arguments')])
49 > def debugrevlistspec(ui, repo, fmt, *args, **opts):
49 > def debugrevlistspec(ui, repo, fmt, *args, **opts):
50 > if opts['bin']:
50 > if opts['bin']:
51 > args = map(nodemod.bin, args)
51 > args = map(nodemod.bin, args)
52 > expr = revset.formatspec(fmt, list(args))
52 > expr = revset.formatspec(fmt, list(args))
53 > if ui.verbose:
53 > if ui.verbose:
54 > tree = revset.parse(expr, lookup=repo.__contains__)
54 > tree = revset.parse(expr, lookup=repo.__contains__)
55 > ui.note(revset.prettyformat(tree), "\n")
55 > ui.note(revset.prettyformat(tree), "\n")
56 > if opts["optimize"]:
56 > if opts["optimize"]:
57 > opttree = revset.optimize(revset.analyze(tree))
57 > opttree = revset.optimize(revset.analyze(tree))
58 > ui.note("* optimized:\n", revset.prettyformat(opttree), "\n")
58 > ui.note("* optimized:\n", revset.prettyformat(opttree), "\n")
59 > func = revset.match(ui, expr, repo)
59 > func = revset.match(ui, expr, repo)
60 > revs = func(repo)
60 > revs = func(repo)
61 > if ui.verbose:
61 > if ui.verbose:
62 > ui.note("* set:\n", revset.prettyformatset(revs), "\n")
62 > ui.note("* set:\n", revset.prettyformatset(revs), "\n")
63 > for c in revs:
63 > for c in revs:
64 > ui.write("%s\n" % c)
64 > ui.write("%s\n" % c)
65 > EOF
65 > EOF
66 $ cat <<EOF >> $HGRCPATH
66 $ cat <<EOF >> $HGRCPATH
67 > [extensions]
67 > [extensions]
68 > debugrevlistspec = $TESTTMP/debugrevlistspec.py
68 > debugrevlistspec = $TESTTMP/debugrevlistspec.py
69 > EOF
69 > EOF
70 $ trylist() {
70 $ trylist() {
71 > hg debugrevlistspec --debug "$@"
71 > hg debugrevlistspec --debug "$@"
72 > }
72 > }
73
73
74 $ hg init repo
74 $ hg init repo
75 $ cd repo
75 $ cd repo
76
76
77 $ echo a > a
77 $ echo a > a
78 $ hg branch a
78 $ hg branch a
79 marked working directory as branch a
79 marked working directory as branch a
80 (branches are permanent and global, did you want a bookmark?)
80 (branches are permanent and global, did you want a bookmark?)
81 $ hg ci -Aqm0
81 $ hg ci -Aqm0
82
82
83 $ echo b > b
83 $ echo b > b
84 $ hg branch b
84 $ hg branch b
85 marked working directory as branch b
85 marked working directory as branch b
86 $ hg ci -Aqm1
86 $ hg ci -Aqm1
87
87
88 $ rm a
88 $ rm a
89 $ hg branch a-b-c-
89 $ hg branch a-b-c-
90 marked working directory as branch a-b-c-
90 marked working directory as branch a-b-c-
91 $ hg ci -Aqm2 -u Bob
91 $ hg ci -Aqm2 -u Bob
92
92
93 $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
93 $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
94 2
94 2
95 $ hg log -r "extra('branch')" --template '{rev}\n'
95 $ hg log -r "extra('branch')" --template '{rev}\n'
96 0
96 0
97 1
97 1
98 2
98 2
99 $ hg log -r "extra('branch', 're:a')" --template '{rev} {branch}\n'
99 $ hg log -r "extra('branch', 're:a')" --template '{rev} {branch}\n'
100 0 a
100 0 a
101 2 a-b-c-
101 2 a-b-c-
102
102
103 $ hg co 1
103 $ hg co 1
104 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
104 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
105 $ hg branch +a+b+c+
105 $ hg branch +a+b+c+
106 marked working directory as branch +a+b+c+
106 marked working directory as branch +a+b+c+
107 $ hg ci -Aqm3
107 $ hg ci -Aqm3
108
108
109 $ hg co 2 # interleave
109 $ hg co 2 # interleave
110 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
110 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
111 $ echo bb > b
111 $ echo bb > b
112 $ hg branch -- -a-b-c-
112 $ hg branch -- -a-b-c-
113 marked working directory as branch -a-b-c-
113 marked working directory as branch -a-b-c-
114 $ hg ci -Aqm4 -d "May 12 2005"
114 $ hg ci -Aqm4 -d "May 12 2005"
115
115
116 $ hg co 3
116 $ hg co 3
117 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
118 $ hg branch !a/b/c/
118 $ hg branch !a/b/c/
119 marked working directory as branch !a/b/c/
119 marked working directory as branch !a/b/c/
120 $ hg ci -Aqm"5 bug"
120 $ hg ci -Aqm"5 bug"
121
121
122 $ hg merge 4
122 $ hg merge 4
123 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
123 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
124 (branch merge, don't forget to commit)
124 (branch merge, don't forget to commit)
125 $ hg branch _a_b_c_
125 $ hg branch _a_b_c_
126 marked working directory as branch _a_b_c_
126 marked working directory as branch _a_b_c_
127 $ hg ci -Aqm"6 issue619"
127 $ hg ci -Aqm"6 issue619"
128
128
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 -Aqm7
131 $ hg ci -Aqm7
132
132
133 $ hg branch all
133 $ hg branch all
134 marked working directory as branch all
134 marked working directory as branch all
135
135
136 $ hg co 4
136 $ hg co 4
137 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
138 $ hg branch Γ©
138 $ hg branch Γ©
139 marked working directory as branch \xc3\xa9 (esc)
139 marked working directory as branch \xc3\xa9 (esc)
140 $ hg ci -Aqm9
140 $ hg ci -Aqm9
141
141
142 $ hg tag -r6 1.0
142 $ hg tag -r6 1.0
143 $ hg bookmark -r6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
143 $ hg bookmark -r6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
144
144
145 $ hg clone --quiet -U -r 7 . ../remote1
145 $ hg clone --quiet -U -r 7 . ../remote1
146 $ hg clone --quiet -U -r 8 . ../remote2
146 $ hg clone --quiet -U -r 8 . ../remote2
147 $ echo "[paths]" >> .hg/hgrc
147 $ echo "[paths]" >> .hg/hgrc
148 $ echo "default = ../remote1" >> .hg/hgrc
148 $ echo "default = ../remote1" >> .hg/hgrc
149
149
150 trivial
150 trivial
151
151
152 $ try 0:1
152 $ try 0:1
153 (range
153 (range
154 ('symbol', '0')
154 ('symbol', '0')
155 ('symbol', '1'))
155 ('symbol', '1'))
156 * set:
156 * set:
157 <spanset+ 0:1>
157 <spanset+ 0:1>
158 0
158 0
159 1
159 1
160 $ try --optimize :
160 $ try --optimize :
161 (rangeall
161 (rangeall
162 None)
162 None)
163 * optimized:
163 * optimized:
164 (range
164 (range
165 ('string', '0')
165 ('string', '0')
166 ('string', 'tip'))
166 ('string', 'tip'))
167 * set:
167 * set:
168 <spanset+ 0:9>
168 <spanset+ 0:9>
169 0
169 0
170 1
170 1
171 2
171 2
172 3
172 3
173 4
173 4
174 5
174 5
175 6
175 6
176 7
176 7
177 8
177 8
178 9
178 9
179 $ try 3::6
179 $ try 3::6
180 (dagrange
180 (dagrange
181 ('symbol', '3')
181 ('symbol', '3')
182 ('symbol', '6'))
182 ('symbol', '6'))
183 * set:
183 * set:
184 <baseset+ [3, 5, 6]>
184 <baseset+ [3, 5, 6]>
185 3
185 3
186 5
186 5
187 6
187 6
188 $ try '0|1|2'
188 $ try '0|1|2'
189 (or
189 (or
190 ('symbol', '0')
190 (list
191 ('symbol', '1')
191 ('symbol', '0')
192 ('symbol', '2'))
192 ('symbol', '1')
193 ('symbol', '2')))
193 * set:
194 * set:
194 <baseset [0, 1, 2]>
195 <baseset [0, 1, 2]>
195 0
196 0
196 1
197 1
197 2
198 2
198
199
199 names that should work without quoting
200 names that should work without quoting
200
201
201 $ try a
202 $ try a
202 ('symbol', 'a')
203 ('symbol', 'a')
203 * set:
204 * set:
204 <baseset [0]>
205 <baseset [0]>
205 0
206 0
206 $ try b-a
207 $ try b-a
207 (minus
208 (minus
208 ('symbol', 'b')
209 ('symbol', 'b')
209 ('symbol', 'a'))
210 ('symbol', 'a'))
210 * set:
211 * set:
211 <filteredset
212 <filteredset
212 <baseset [1]>,
213 <baseset [1]>,
213 <not
214 <not
214 <baseset [0]>>>
215 <baseset [0]>>>
215 1
216 1
216 $ try _a_b_c_
217 $ try _a_b_c_
217 ('symbol', '_a_b_c_')
218 ('symbol', '_a_b_c_')
218 * set:
219 * set:
219 <baseset [6]>
220 <baseset [6]>
220 6
221 6
221 $ try _a_b_c_-a
222 $ try _a_b_c_-a
222 (minus
223 (minus
223 ('symbol', '_a_b_c_')
224 ('symbol', '_a_b_c_')
224 ('symbol', 'a'))
225 ('symbol', 'a'))
225 * set:
226 * set:
226 <filteredset
227 <filteredset
227 <baseset [6]>,
228 <baseset [6]>,
228 <not
229 <not
229 <baseset [0]>>>
230 <baseset [0]>>>
230 6
231 6
231 $ try .a.b.c.
232 $ try .a.b.c.
232 ('symbol', '.a.b.c.')
233 ('symbol', '.a.b.c.')
233 * set:
234 * set:
234 <baseset [7]>
235 <baseset [7]>
235 7
236 7
236 $ try .a.b.c.-a
237 $ try .a.b.c.-a
237 (minus
238 (minus
238 ('symbol', '.a.b.c.')
239 ('symbol', '.a.b.c.')
239 ('symbol', 'a'))
240 ('symbol', 'a'))
240 * set:
241 * set:
241 <filteredset
242 <filteredset
242 <baseset [7]>,
243 <baseset [7]>,
243 <not
244 <not
244 <baseset [0]>>>
245 <baseset [0]>>>
245 7
246 7
246
247
247 names that should be caught by fallback mechanism
248 names that should be caught by fallback mechanism
248
249
249 $ try -- '-a-b-c-'
250 $ try -- '-a-b-c-'
250 ('symbol', '-a-b-c-')
251 ('symbol', '-a-b-c-')
251 * set:
252 * set:
252 <baseset [4]>
253 <baseset [4]>
253 4
254 4
254 $ log -a-b-c-
255 $ log -a-b-c-
255 4
256 4
256 $ try '+a+b+c+'
257 $ try '+a+b+c+'
257 ('symbol', '+a+b+c+')
258 ('symbol', '+a+b+c+')
258 * set:
259 * set:
259 <baseset [3]>
260 <baseset [3]>
260 3
261 3
261 $ try '+a+b+c+:'
262 $ try '+a+b+c+:'
262 (rangepost
263 (rangepost
263 ('symbol', '+a+b+c+'))
264 ('symbol', '+a+b+c+'))
264 * set:
265 * set:
265 <spanset+ 3:9>
266 <spanset+ 3:9>
266 3
267 3
267 4
268 4
268 5
269 5
269 6
270 6
270 7
271 7
271 8
272 8
272 9
273 9
273 $ try ':+a+b+c+'
274 $ try ':+a+b+c+'
274 (rangepre
275 (rangepre
275 ('symbol', '+a+b+c+'))
276 ('symbol', '+a+b+c+'))
276 * set:
277 * set:
277 <spanset+ 0:3>
278 <spanset+ 0:3>
278 0
279 0
279 1
280 1
280 2
281 2
281 3
282 3
282 $ try -- '-a-b-c-:+a+b+c+'
283 $ try -- '-a-b-c-:+a+b+c+'
283 (range
284 (range
284 ('symbol', '-a-b-c-')
285 ('symbol', '-a-b-c-')
285 ('symbol', '+a+b+c+'))
286 ('symbol', '+a+b+c+'))
286 * set:
287 * set:
287 <spanset- 3:4>
288 <spanset- 3:4>
288 4
289 4
289 3
290 3
290 $ log '-a-b-c-:+a+b+c+'
291 $ log '-a-b-c-:+a+b+c+'
291 4
292 4
292 3
293 3
293
294
294 $ try -- -a-b-c--a # complains
295 $ try -- -a-b-c--a # complains
295 (minus
296 (minus
296 (minus
297 (minus
297 (minus
298 (minus
298 (negate
299 (negate
299 ('symbol', 'a'))
300 ('symbol', 'a'))
300 ('symbol', 'b'))
301 ('symbol', 'b'))
301 ('symbol', 'c'))
302 ('symbol', 'c'))
302 (negate
303 (negate
303 ('symbol', 'a')))
304 ('symbol', 'a')))
304 abort: unknown revision '-a'!
305 abort: unknown revision '-a'!
305 [255]
306 [255]
306 $ try Γ©
307 $ try Γ©
307 ('symbol', '\xc3\xa9')
308 ('symbol', '\xc3\xa9')
308 * set:
309 * set:
309 <baseset [9]>
310 <baseset [9]>
310 9
311 9
311
312
312 no quoting needed
313 no quoting needed
313
314
314 $ log ::a-b-c-
315 $ log ::a-b-c-
315 0
316 0
316 1
317 1
317 2
318 2
318
319
319 quoting needed
320 quoting needed
320
321
321 $ try '"-a-b-c-"-a'
322 $ try '"-a-b-c-"-a'
322 (minus
323 (minus
323 ('string', '-a-b-c-')
324 ('string', '-a-b-c-')
324 ('symbol', 'a'))
325 ('symbol', 'a'))
325 * set:
326 * set:
326 <filteredset
327 <filteredset
327 <baseset [4]>,
328 <baseset [4]>,
328 <not
329 <not
329 <baseset [0]>>>
330 <baseset [0]>>>
330 4
331 4
331
332
332 $ log '1 or 2'
333 $ log '1 or 2'
333 1
334 1
334 2
335 2
335 $ log '1|2'
336 $ log '1|2'
336 1
337 1
337 2
338 2
338 $ log '1 and 2'
339 $ log '1 and 2'
339 $ log '1&2'
340 $ log '1&2'
340 $ try '1&2|3' # precedence - and is higher
341 $ try '1&2|3' # precedence - and is higher
341 (or
342 (or
342 (and
343 (list
343 ('symbol', '1')
344 (and
344 ('symbol', '2'))
345 ('symbol', '1')
345 ('symbol', '3'))
346 ('symbol', '2'))
347 ('symbol', '3')))
346 * set:
348 * set:
347 <addset
349 <addset
348 <baseset []>,
350 <baseset []>,
349 <baseset [3]>>
351 <baseset [3]>>
350 3
352 3
351 $ try '1|2&3'
353 $ try '1|2&3'
352 (or
354 (or
353 ('symbol', '1')
355 (list
354 (and
356 ('symbol', '1')
355 ('symbol', '2')
357 (and
356 ('symbol', '3')))
358 ('symbol', '2')
359 ('symbol', '3'))))
357 * set:
360 * set:
358 <addset
361 <addset
359 <baseset [1]>,
362 <baseset [1]>,
360 <baseset []>>
363 <baseset []>>
361 1
364 1
362 $ try '1&2&3' # associativity
365 $ try '1&2&3' # associativity
363 (and
366 (and
364 (and
367 (and
365 ('symbol', '1')
368 ('symbol', '1')
366 ('symbol', '2'))
369 ('symbol', '2'))
367 ('symbol', '3'))
370 ('symbol', '3'))
368 * set:
371 * set:
369 <baseset []>
372 <baseset []>
370 $ try '1|(2|3)'
373 $ try '1|(2|3)'
371 (or
374 (or
372 ('symbol', '1')
375 (list
373 (group
376 ('symbol', '1')
374 (or
377 (group
375 ('symbol', '2')
378 (or
376 ('symbol', '3'))))
379 (list
380 ('symbol', '2')
381 ('symbol', '3'))))))
377 * set:
382 * set:
378 <addset
383 <addset
379 <baseset [1]>,
384 <baseset [1]>,
380 <baseset [2, 3]>>
385 <baseset [2, 3]>>
381 1
386 1
382 2
387 2
383 3
388 3
384 $ log '1.0' # tag
389 $ log '1.0' # tag
385 6
390 6
386 $ log 'a' # branch
391 $ log 'a' # branch
387 0
392 0
388 $ log '2785f51ee'
393 $ log '2785f51ee'
389 0
394 0
390 $ log 'date(2005)'
395 $ log 'date(2005)'
391 4
396 4
392 $ log 'date(this is a test)'
397 $ log 'date(this is a test)'
393 hg: parse error at 10: unexpected token: symbol
398 hg: parse error at 10: unexpected token: symbol
394 [255]
399 [255]
395 $ log 'date()'
400 $ log 'date()'
396 hg: parse error: date requires a string
401 hg: parse error: date requires a string
397 [255]
402 [255]
398 $ log 'date'
403 $ log 'date'
399 abort: unknown revision 'date'!
404 abort: unknown revision 'date'!
400 [255]
405 [255]
401 $ log 'date('
406 $ log 'date('
402 hg: parse error at 5: not a prefix: end
407 hg: parse error at 5: not a prefix: end
403 [255]
408 [255]
404 $ log 'date("\xy")'
409 $ log 'date("\xy")'
405 hg: parse error: invalid \x escape
410 hg: parse error: invalid \x escape
406 [255]
411 [255]
407 $ log 'date(tip)'
412 $ log 'date(tip)'
408 abort: invalid date: 'tip'
413 abort: invalid date: 'tip'
409 [255]
414 [255]
410 $ log '0:date'
415 $ log '0:date'
411 abort: unknown revision 'date'!
416 abort: unknown revision 'date'!
412 [255]
417 [255]
413 $ log '::"date"'
418 $ log '::"date"'
414 abort: unknown revision 'date'!
419 abort: unknown revision 'date'!
415 [255]
420 [255]
416 $ hg book date -r 4
421 $ hg book date -r 4
417 $ log '0:date'
422 $ log '0:date'
418 0
423 0
419 1
424 1
420 2
425 2
421 3
426 3
422 4
427 4
423 $ log '::date'
428 $ log '::date'
424 0
429 0
425 1
430 1
426 2
431 2
427 4
432 4
428 $ log '::"date"'
433 $ log '::"date"'
429 0
434 0
430 1
435 1
431 2
436 2
432 4
437 4
433 $ log 'date(2005) and 1::'
438 $ log 'date(2005) and 1::'
434 4
439 4
435 $ hg book -d date
440 $ hg book -d date
436
441
437 function name should be a symbol
442 function name should be a symbol
438
443
439 $ log '"date"(2005)'
444 $ log '"date"(2005)'
440 hg: parse error: not a symbol
445 hg: parse error: not a symbol
441 [255]
446 [255]
442
447
443 keyword arguments
448 keyword arguments
444
449
445 $ log 'extra(branch, value=a)'
450 $ log 'extra(branch, value=a)'
446 0
451 0
447
452
448 $ log 'extra(branch, a, b)'
453 $ log 'extra(branch, a, b)'
449 hg: parse error: extra takes at most 2 arguments
454 hg: parse error: extra takes at most 2 arguments
450 [255]
455 [255]
451 $ log 'extra(a, label=b)'
456 $ log 'extra(a, label=b)'
452 hg: parse error: extra got multiple values for keyword argument 'label'
457 hg: parse error: extra got multiple values for keyword argument 'label'
453 [255]
458 [255]
454 $ log 'extra(label=branch, default)'
459 $ log 'extra(label=branch, default)'
455 hg: parse error: extra got an invalid argument
460 hg: parse error: extra got an invalid argument
456 [255]
461 [255]
457 $ log 'extra(branch, foo+bar=baz)'
462 $ log 'extra(branch, foo+bar=baz)'
458 hg: parse error: extra got an invalid argument
463 hg: parse error: extra got an invalid argument
459 [255]
464 [255]
460 $ log 'extra(unknown=branch)'
465 $ log 'extra(unknown=branch)'
461 hg: parse error: extra got an unexpected keyword argument 'unknown'
466 hg: parse error: extra got an unexpected keyword argument 'unknown'
462 [255]
467 [255]
463
468
464 $ try 'foo=bar|baz'
469 $ try 'foo=bar|baz'
465 (keyvalue
470 (keyvalue
466 ('symbol', 'foo')
471 ('symbol', 'foo')
467 (or
472 (or
468 ('symbol', 'bar')
473 (list
469 ('symbol', 'baz')))
474 ('symbol', 'bar')
475 ('symbol', 'baz'))))
470 hg: parse error: can't use a key-value pair in this context
476 hg: parse error: can't use a key-value pair in this context
471 [255]
477 [255]
472
478
473 right-hand side should be optimized recursively
479 right-hand side should be optimized recursively
474
480
475 $ try --optimize 'foo=(not public())'
481 $ try --optimize 'foo=(not public())'
476 (keyvalue
482 (keyvalue
477 ('symbol', 'foo')
483 ('symbol', 'foo')
478 (group
484 (group
479 (not
485 (not
480 (func
486 (func
481 ('symbol', 'public')
487 ('symbol', 'public')
482 None))))
488 None))))
483 * optimized:
489 * optimized:
484 (keyvalue
490 (keyvalue
485 ('symbol', 'foo')
491 ('symbol', 'foo')
486 (func
492 (func
487 ('symbol', '_notpublic')
493 ('symbol', '_notpublic')
488 None))
494 None))
489 hg: parse error: can't use a key-value pair in this context
495 hg: parse error: can't use a key-value pair in this context
490 [255]
496 [255]
491
497
492 parsed tree at stages:
498 parsed tree at stages:
493
499
494 $ hg debugrevspec -p all '()'
500 $ hg debugrevspec -p all '()'
495 * parsed:
501 * parsed:
496 (group
502 (group
497 None)
503 None)
498 * expanded:
504 * expanded:
499 (group
505 (group
500 None)
506 None)
501 * concatenated:
507 * concatenated:
502 (group
508 (group
503 None)
509 None)
504 * analyzed:
510 * analyzed:
505 None
511 None
506 * optimized:
512 * optimized:
507 None
513 None
508 hg: parse error: missing argument
514 hg: parse error: missing argument
509 [255]
515 [255]
510
516
511 $ hg debugrevspec --no-optimized -p all '()'
517 $ hg debugrevspec --no-optimized -p all '()'
512 * parsed:
518 * parsed:
513 (group
519 (group
514 None)
520 None)
515 * expanded:
521 * expanded:
516 (group
522 (group
517 None)
523 None)
518 * concatenated:
524 * concatenated:
519 (group
525 (group
520 None)
526 None)
521 * analyzed:
527 * analyzed:
522 None
528 None
523 hg: parse error: missing argument
529 hg: parse error: missing argument
524 [255]
530 [255]
525
531
526 $ hg debugrevspec -p parsed -p analyzed -p optimized '(0|1)-1'
532 $ hg debugrevspec -p parsed -p analyzed -p optimized '(0|1)-1'
527 * parsed:
533 * parsed:
528 (minus
534 (minus
529 (group
535 (group
530 (or
536 (or
531 ('symbol', '0')
537 (list
532 ('symbol', '1')))
538 ('symbol', '0')
539 ('symbol', '1'))))
533 ('symbol', '1'))
540 ('symbol', '1'))
534 * analyzed:
541 * analyzed:
535 (and
542 (and
536 (or
543 (or
537 ('symbol', '0')
544 (list
538 ('symbol', '1'))
545 ('symbol', '0')
546 ('symbol', '1')))
539 (not
547 (not
540 ('symbol', '1')))
548 ('symbol', '1')))
541 * optimized:
549 * optimized:
542 (difference
550 (difference
543 (func
551 (func
544 ('symbol', '_list')
552 ('symbol', '_list')
545 ('string', '0\x001'))
553 ('string', '0\x001'))
546 ('symbol', '1'))
554 ('symbol', '1'))
547 0
555 0
548
556
549 $ hg debugrevspec -p unknown '0'
557 $ hg debugrevspec -p unknown '0'
550 abort: invalid stage name: unknown
558 abort: invalid stage name: unknown
551 [255]
559 [255]
552
560
553 $ hg debugrevspec -p all --optimize '0'
561 $ hg debugrevspec -p all --optimize '0'
554 abort: cannot use --optimize with --show-stage
562 abort: cannot use --optimize with --show-stage
555 [255]
563 [255]
556
564
557 verify optimized tree:
565 verify optimized tree:
558
566
559 $ hg debugrevspec --verify '0|1'
567 $ hg debugrevspec --verify '0|1'
560
568
561 $ hg debugrevspec --verify -v -p analyzed -p optimized 'r3232() & 2'
569 $ hg debugrevspec --verify -v -p analyzed -p optimized 'r3232() & 2'
562 * analyzed:
570 * analyzed:
563 (and
571 (and
564 (func
572 (func
565 ('symbol', 'r3232')
573 ('symbol', 'r3232')
566 None)
574 None)
567 ('symbol', '2'))
575 ('symbol', '2'))
568 * optimized:
576 * optimized:
569 (and
577 (and
570 ('symbol', '2')
578 ('symbol', '2')
571 (func
579 (func
572 ('symbol', 'r3232')
580 ('symbol', 'r3232')
573 None))
581 None))
574 * analyzed set:
582 * analyzed set:
575 <baseset [2]>
583 <baseset [2]>
576 * optimized set:
584 * optimized set:
577 <baseset [2, 2]>
585 <baseset [2, 2]>
578 --- analyzed
586 --- analyzed
579 +++ optimized
587 +++ optimized
580 2
588 2
581 +2
589 +2
582 [1]
590 [1]
583
591
584 $ hg debugrevspec --no-optimized --verify-optimized '0'
592 $ hg debugrevspec --no-optimized --verify-optimized '0'
585 abort: cannot use --verify-optimized with --no-optimized
593 abort: cannot use --verify-optimized with --no-optimized
586 [255]
594 [255]
587
595
588 Test that symbols only get parsed as functions if there's an opening
596 Test that symbols only get parsed as functions if there's an opening
589 parenthesis.
597 parenthesis.
590
598
591 $ hg book only -r 9
599 $ hg book only -r 9
592 $ log 'only(only)' # Outer "only" is a function, inner "only" is the bookmark
600 $ log 'only(only)' # Outer "only" is a function, inner "only" is the bookmark
593 8
601 8
594 9
602 9
595
603
596 infix/suffix resolution of ^ operator (issue2884):
604 infix/suffix resolution of ^ operator (issue2884):
597
605
598 x^:y means (x^):y
606 x^:y means (x^):y
599
607
600 $ try '1^:2'
608 $ try '1^:2'
601 (range
609 (range
602 (parentpost
610 (parentpost
603 ('symbol', '1'))
611 ('symbol', '1'))
604 ('symbol', '2'))
612 ('symbol', '2'))
605 * set:
613 * set:
606 <spanset+ 0:2>
614 <spanset+ 0:2>
607 0
615 0
608 1
616 1
609 2
617 2
610
618
611 $ try '1^::2'
619 $ try '1^::2'
612 (dagrange
620 (dagrange
613 (parentpost
621 (parentpost
614 ('symbol', '1'))
622 ('symbol', '1'))
615 ('symbol', '2'))
623 ('symbol', '2'))
616 * set:
624 * set:
617 <baseset+ [0, 1, 2]>
625 <baseset+ [0, 1, 2]>
618 0
626 0
619 1
627 1
620 2
628 2
621
629
622 $ try '9^:'
630 $ try '9^:'
623 (rangepost
631 (rangepost
624 (parentpost
632 (parentpost
625 ('symbol', '9')))
633 ('symbol', '9')))
626 * set:
634 * set:
627 <spanset+ 8:9>
635 <spanset+ 8:9>
628 8
636 8
629 9
637 9
630
638
631 x^:y should be resolved before omitting group operators
639 x^:y should be resolved before omitting group operators
632
640
633 $ try '1^(:2)'
641 $ try '1^(:2)'
634 (parent
642 (parent
635 ('symbol', '1')
643 ('symbol', '1')
636 (group
644 (group
637 (rangepre
645 (rangepre
638 ('symbol', '2'))))
646 ('symbol', '2'))))
639 hg: parse error: ^ expects a number 0, 1, or 2
647 hg: parse error: ^ expects a number 0, 1, or 2
640 [255]
648 [255]
641
649
642 x^:y should be resolved recursively
650 x^:y should be resolved recursively
643
651
644 $ try 'sort(1^:2)'
652 $ try 'sort(1^:2)'
645 (func
653 (func
646 ('symbol', 'sort')
654 ('symbol', 'sort')
647 (range
655 (range
648 (parentpost
656 (parentpost
649 ('symbol', '1'))
657 ('symbol', '1'))
650 ('symbol', '2')))
658 ('symbol', '2')))
651 * set:
659 * set:
652 <spanset+ 0:2>
660 <spanset+ 0:2>
653 0
661 0
654 1
662 1
655 2
663 2
656
664
657 $ try '(3^:4)^:2'
665 $ try '(3^:4)^:2'
658 (range
666 (range
659 (parentpost
667 (parentpost
660 (group
668 (group
661 (range
669 (range
662 (parentpost
670 (parentpost
663 ('symbol', '3'))
671 ('symbol', '3'))
664 ('symbol', '4'))))
672 ('symbol', '4'))))
665 ('symbol', '2'))
673 ('symbol', '2'))
666 * set:
674 * set:
667 <spanset+ 0:2>
675 <spanset+ 0:2>
668 0
676 0
669 1
677 1
670 2
678 2
671
679
672 $ try '(3^::4)^::2'
680 $ try '(3^::4)^::2'
673 (dagrange
681 (dagrange
674 (parentpost
682 (parentpost
675 (group
683 (group
676 (dagrange
684 (dagrange
677 (parentpost
685 (parentpost
678 ('symbol', '3'))
686 ('symbol', '3'))
679 ('symbol', '4'))))
687 ('symbol', '4'))))
680 ('symbol', '2'))
688 ('symbol', '2'))
681 * set:
689 * set:
682 <baseset+ [0, 1, 2]>
690 <baseset+ [0, 1, 2]>
683 0
691 0
684 1
692 1
685 2
693 2
686
694
687 $ try '(9^:)^:'
695 $ try '(9^:)^:'
688 (rangepost
696 (rangepost
689 (parentpost
697 (parentpost
690 (group
698 (group
691 (rangepost
699 (rangepost
692 (parentpost
700 (parentpost
693 ('symbol', '9'))))))
701 ('symbol', '9'))))))
694 * set:
702 * set:
695 <spanset+ 4:9>
703 <spanset+ 4:9>
696 4
704 4
697 5
705 5
698 6
706 6
699 7
707 7
700 8
708 8
701 9
709 9
702
710
703 x^ in alias should also be resolved
711 x^ in alias should also be resolved
704
712
705 $ try 'A' --config 'revsetalias.A=1^:2'
713 $ try 'A' --config 'revsetalias.A=1^:2'
706 ('symbol', 'A')
714 ('symbol', 'A')
707 * expanded:
715 * expanded:
708 (range
716 (range
709 (parentpost
717 (parentpost
710 ('symbol', '1'))
718 ('symbol', '1'))
711 ('symbol', '2'))
719 ('symbol', '2'))
712 * set:
720 * set:
713 <spanset+ 0:2>
721 <spanset+ 0:2>
714 0
722 0
715 1
723 1
716 2
724 2
717
725
718 $ try 'A:2' --config 'revsetalias.A=1^'
726 $ try 'A:2' --config 'revsetalias.A=1^'
719 (range
727 (range
720 ('symbol', 'A')
728 ('symbol', 'A')
721 ('symbol', '2'))
729 ('symbol', '2'))
722 * expanded:
730 * expanded:
723 (range
731 (range
724 (parentpost
732 (parentpost
725 ('symbol', '1'))
733 ('symbol', '1'))
726 ('symbol', '2'))
734 ('symbol', '2'))
727 * set:
735 * set:
728 <spanset+ 0:2>
736 <spanset+ 0:2>
729 0
737 0
730 1
738 1
731 2
739 2
732
740
733 but not beyond the boundary of alias expansion, because the resolution should
741 but not beyond the boundary of alias expansion, because the resolution should
734 be made at the parsing stage
742 be made at the parsing stage
735
743
736 $ try '1^A' --config 'revsetalias.A=:2'
744 $ try '1^A' --config 'revsetalias.A=:2'
737 (parent
745 (parent
738 ('symbol', '1')
746 ('symbol', '1')
739 ('symbol', 'A'))
747 ('symbol', 'A'))
740 * expanded:
748 * expanded:
741 (parent
749 (parent
742 ('symbol', '1')
750 ('symbol', '1')
743 (rangepre
751 (rangepre
744 ('symbol', '2')))
752 ('symbol', '2')))
745 hg: parse error: ^ expects a number 0, 1, or 2
753 hg: parse error: ^ expects a number 0, 1, or 2
746 [255]
754 [255]
747
755
748 ancestor can accept 0 or more arguments
756 ancestor can accept 0 or more arguments
749
757
750 $ log 'ancestor()'
758 $ log 'ancestor()'
751 $ log 'ancestor(1)'
759 $ log 'ancestor(1)'
752 1
760 1
753 $ log 'ancestor(4,5)'
761 $ log 'ancestor(4,5)'
754 1
762 1
755 $ log 'ancestor(4,5) and 4'
763 $ log 'ancestor(4,5) and 4'
756 $ log 'ancestor(0,0,1,3)'
764 $ log 'ancestor(0,0,1,3)'
757 0
765 0
758 $ log 'ancestor(3,1,5,3,5,1)'
766 $ log 'ancestor(3,1,5,3,5,1)'
759 1
767 1
760 $ log 'ancestor(0,1,3,5)'
768 $ log 'ancestor(0,1,3,5)'
761 0
769 0
762 $ log 'ancestor(1,2,3,4,5)'
770 $ log 'ancestor(1,2,3,4,5)'
763 1
771 1
764
772
765 test ancestors
773 test ancestors
766
774
767 $ log 'ancestors(5)'
775 $ log 'ancestors(5)'
768 0
776 0
769 1
777 1
770 3
778 3
771 5
779 5
772 $ log 'ancestor(ancestors(5))'
780 $ log 'ancestor(ancestors(5))'
773 0
781 0
774 $ log '::r3232()'
782 $ log '::r3232()'
775 0
783 0
776 1
784 1
777 2
785 2
778 3
786 3
779
787
780 $ log 'author(bob)'
788 $ log 'author(bob)'
781 2
789 2
782 $ log 'author("re:bob|test")'
790 $ log 'author("re:bob|test")'
783 0
791 0
784 1
792 1
785 2
793 2
786 3
794 3
787 4
795 4
788 5
796 5
789 6
797 6
790 7
798 7
791 8
799 8
792 9
800 9
793 $ log 'branch(Γ©)'
801 $ log 'branch(Γ©)'
794 8
802 8
795 9
803 9
796 $ log 'branch(a)'
804 $ log 'branch(a)'
797 0
805 0
798 $ hg log -r 'branch("re:a")' --template '{rev} {branch}\n'
806 $ hg log -r 'branch("re:a")' --template '{rev} {branch}\n'
799 0 a
807 0 a
800 2 a-b-c-
808 2 a-b-c-
801 3 +a+b+c+
809 3 +a+b+c+
802 4 -a-b-c-
810 4 -a-b-c-
803 5 !a/b/c/
811 5 !a/b/c/
804 6 _a_b_c_
812 6 _a_b_c_
805 7 .a.b.c.
813 7 .a.b.c.
806 $ log 'children(ancestor(4,5))'
814 $ log 'children(ancestor(4,5))'
807 2
815 2
808 3
816 3
809 $ log 'closed()'
817 $ log 'closed()'
810 $ log 'contains(a)'
818 $ log 'contains(a)'
811 0
819 0
812 1
820 1
813 3
821 3
814 5
822 5
815 $ log 'contains("../repo/a")'
823 $ log 'contains("../repo/a")'
816 0
824 0
817 1
825 1
818 3
826 3
819 5
827 5
820 $ log 'desc(B)'
828 $ log 'desc(B)'
821 5
829 5
822 $ log 'descendants(2 or 3)'
830 $ log 'descendants(2 or 3)'
823 2
831 2
824 3
832 3
825 4
833 4
826 5
834 5
827 6
835 6
828 7
836 7
829 8
837 8
830 9
838 9
831 $ log 'file("b*")'
839 $ log 'file("b*")'
832 1
840 1
833 4
841 4
834 $ log 'filelog("b")'
842 $ log 'filelog("b")'
835 1
843 1
836 4
844 4
837 $ log 'filelog("../repo/b")'
845 $ log 'filelog("../repo/b")'
838 1
846 1
839 4
847 4
840 $ log 'follow()'
848 $ log 'follow()'
841 0
849 0
842 1
850 1
843 2
851 2
844 4
852 4
845 8
853 8
846 9
854 9
847 $ log 'grep("issue\d+")'
855 $ log 'grep("issue\d+")'
848 6
856 6
849 $ try 'grep("(")' # invalid regular expression
857 $ try 'grep("(")' # invalid regular expression
850 (func
858 (func
851 ('symbol', 'grep')
859 ('symbol', 'grep')
852 ('string', '('))
860 ('string', '('))
853 hg: parse error: invalid match pattern: unbalanced parenthesis
861 hg: parse error: invalid match pattern: unbalanced parenthesis
854 [255]
862 [255]
855 $ try 'grep("\bissue\d+")'
863 $ try 'grep("\bissue\d+")'
856 (func
864 (func
857 ('symbol', 'grep')
865 ('symbol', 'grep')
858 ('string', '\x08issue\\d+'))
866 ('string', '\x08issue\\d+'))
859 * set:
867 * set:
860 <filteredset
868 <filteredset
861 <fullreposet+ 0:9>,
869 <fullreposet+ 0:9>,
862 <grep '\x08issue\\d+'>>
870 <grep '\x08issue\\d+'>>
863 $ try 'grep(r"\bissue\d+")'
871 $ try 'grep(r"\bissue\d+")'
864 (func
872 (func
865 ('symbol', 'grep')
873 ('symbol', 'grep')
866 ('string', '\\bissue\\d+'))
874 ('string', '\\bissue\\d+'))
867 * set:
875 * set:
868 <filteredset
876 <filteredset
869 <fullreposet+ 0:9>,
877 <fullreposet+ 0:9>,
870 <grep '\\bissue\\d+'>>
878 <grep '\\bissue\\d+'>>
871 6
879 6
872 $ try 'grep(r"\")'
880 $ try 'grep(r"\")'
873 hg: parse error at 7: unterminated string
881 hg: parse error at 7: unterminated string
874 [255]
882 [255]
875 $ log 'head()'
883 $ log 'head()'
876 0
884 0
877 1
885 1
878 2
886 2
879 3
887 3
880 4
888 4
881 5
889 5
882 6
890 6
883 7
891 7
884 9
892 9
885 $ log 'heads(6::)'
893 $ log 'heads(6::)'
886 7
894 7
887 $ log 'keyword(issue)'
895 $ log 'keyword(issue)'
888 6
896 6
889 $ log 'keyword("test a")'
897 $ log 'keyword("test a")'
890 $ log 'limit(head(), 1)'
898 $ log 'limit(head(), 1)'
891 0
899 0
892 $ log 'limit(author("re:bob|test"), 3, 5)'
900 $ log 'limit(author("re:bob|test"), 3, 5)'
893 5
901 5
894 6
902 6
895 7
903 7
896 $ log 'limit(author("re:bob|test"), offset=6)'
904 $ log 'limit(author("re:bob|test"), offset=6)'
897 6
905 6
898 $ log 'limit(author("re:bob|test"), offset=10)'
906 $ log 'limit(author("re:bob|test"), offset=10)'
899 $ log 'limit(all(), 1, -1)'
907 $ log 'limit(all(), 1, -1)'
900 hg: parse error: negative offset
908 hg: parse error: negative offset
901 [255]
909 [255]
902 $ log 'matching(6)'
910 $ log 'matching(6)'
903 6
911 6
904 $ log 'matching(6:7, "phase parents user date branch summary files description substate")'
912 $ log 'matching(6:7, "phase parents user date branch summary files description substate")'
905 6
913 6
906 7
914 7
907
915
908 Testing min and max
916 Testing min and max
909
917
910 max: simple
918 max: simple
911
919
912 $ log 'max(contains(a))'
920 $ log 'max(contains(a))'
913 5
921 5
914
922
915 max: simple on unordered set)
923 max: simple on unordered set)
916
924
917 $ log 'max((4+0+2+5+7) and contains(a))'
925 $ log 'max((4+0+2+5+7) and contains(a))'
918 5
926 5
919
927
920 max: no result
928 max: no result
921
929
922 $ log 'max(contains(stringthatdoesnotappearanywhere))'
930 $ log 'max(contains(stringthatdoesnotappearanywhere))'
923
931
924 max: no result on unordered set
932 max: no result on unordered set
925
933
926 $ log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
934 $ log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
927
935
928 min: simple
936 min: simple
929
937
930 $ log 'min(contains(a))'
938 $ log 'min(contains(a))'
931 0
939 0
932
940
933 min: simple on unordered set
941 min: simple on unordered set
934
942
935 $ log 'min((4+0+2+5+7) and contains(a))'
943 $ log 'min((4+0+2+5+7) and contains(a))'
936 0
944 0
937
945
938 min: empty
946 min: empty
939
947
940 $ log 'min(contains(stringthatdoesnotappearanywhere))'
948 $ log 'min(contains(stringthatdoesnotappearanywhere))'
941
949
942 min: empty on unordered set
950 min: empty on unordered set
943
951
944 $ log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
952 $ log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
945
953
946
954
947 $ log 'merge()'
955 $ log 'merge()'
948 6
956 6
949 $ log 'branchpoint()'
957 $ log 'branchpoint()'
950 1
958 1
951 4
959 4
952 $ log 'modifies(b)'
960 $ log 'modifies(b)'
953 4
961 4
954 $ log 'modifies("path:b")'
962 $ log 'modifies("path:b")'
955 4
963 4
956 $ log 'modifies("*")'
964 $ log 'modifies("*")'
957 4
965 4
958 6
966 6
959 $ log 'modifies("set:modified()")'
967 $ log 'modifies("set:modified()")'
960 4
968 4
961 $ log 'id(5)'
969 $ log 'id(5)'
962 2
970 2
963 $ log 'only(9)'
971 $ log 'only(9)'
964 8
972 8
965 9
973 9
966 $ log 'only(8)'
974 $ log 'only(8)'
967 8
975 8
968 $ log 'only(9, 5)'
976 $ log 'only(9, 5)'
969 2
977 2
970 4
978 4
971 8
979 8
972 9
980 9
973 $ log 'only(7 + 9, 5 + 2)'
981 $ log 'only(7 + 9, 5 + 2)'
974 4
982 4
975 6
983 6
976 7
984 7
977 8
985 8
978 9
986 9
979
987
980 Test empty set input
988 Test empty set input
981 $ log 'only(p2())'
989 $ log 'only(p2())'
982 $ log 'only(p1(), p2())'
990 $ log 'only(p1(), p2())'
983 0
991 0
984 1
992 1
985 2
993 2
986 4
994 4
987 8
995 8
988 9
996 9
989
997
990 Test '%' operator
998 Test '%' operator
991
999
992 $ log '9%'
1000 $ log '9%'
993 8
1001 8
994 9
1002 9
995 $ log '9%5'
1003 $ log '9%5'
996 2
1004 2
997 4
1005 4
998 8
1006 8
999 9
1007 9
1000 $ log '(7 + 9)%(5 + 2)'
1008 $ log '(7 + 9)%(5 + 2)'
1001 4
1009 4
1002 6
1010 6
1003 7
1011 7
1004 8
1012 8
1005 9
1013 9
1006
1014
1007 Test opreand of '%' is optimized recursively (issue4670)
1015 Test opreand of '%' is optimized recursively (issue4670)
1008
1016
1009 $ try --optimize '8:9-8%'
1017 $ try --optimize '8:9-8%'
1010 (onlypost
1018 (onlypost
1011 (minus
1019 (minus
1012 (range
1020 (range
1013 ('symbol', '8')
1021 ('symbol', '8')
1014 ('symbol', '9'))
1022 ('symbol', '9'))
1015 ('symbol', '8')))
1023 ('symbol', '8')))
1016 * optimized:
1024 * optimized:
1017 (func
1025 (func
1018 ('symbol', 'only')
1026 ('symbol', 'only')
1019 (difference
1027 (difference
1020 (range
1028 (range
1021 ('symbol', '8')
1029 ('symbol', '8')
1022 ('symbol', '9'))
1030 ('symbol', '9'))
1023 ('symbol', '8')))
1031 ('symbol', '8')))
1024 * set:
1032 * set:
1025 <baseset+ [8, 9]>
1033 <baseset+ [8, 9]>
1026 8
1034 8
1027 9
1035 9
1028 $ try --optimize '(9)%(5)'
1036 $ try --optimize '(9)%(5)'
1029 (only
1037 (only
1030 (group
1038 (group
1031 ('symbol', '9'))
1039 ('symbol', '9'))
1032 (group
1040 (group
1033 ('symbol', '5')))
1041 ('symbol', '5')))
1034 * optimized:
1042 * optimized:
1035 (func
1043 (func
1036 ('symbol', 'only')
1044 ('symbol', 'only')
1037 (list
1045 (list
1038 ('symbol', '9')
1046 ('symbol', '9')
1039 ('symbol', '5')))
1047 ('symbol', '5')))
1040 * set:
1048 * set:
1041 <baseset+ [2, 4, 8, 9]>
1049 <baseset+ [2, 4, 8, 9]>
1042 2
1050 2
1043 4
1051 4
1044 8
1052 8
1045 9
1053 9
1046
1054
1047 Test the order of operations
1055 Test the order of operations
1048
1056
1049 $ log '7 + 9%5 + 2'
1057 $ log '7 + 9%5 + 2'
1050 7
1058 7
1051 2
1059 2
1052 4
1060 4
1053 8
1061 8
1054 9
1062 9
1055
1063
1056 Test explicit numeric revision
1064 Test explicit numeric revision
1057 $ log 'rev(-2)'
1065 $ log 'rev(-2)'
1058 $ log 'rev(-1)'
1066 $ log 'rev(-1)'
1059 -1
1067 -1
1060 $ log 'rev(0)'
1068 $ log 'rev(0)'
1061 0
1069 0
1062 $ log 'rev(9)'
1070 $ log 'rev(9)'
1063 9
1071 9
1064 $ log 'rev(10)'
1072 $ log 'rev(10)'
1065 $ log 'rev(tip)'
1073 $ log 'rev(tip)'
1066 hg: parse error: rev expects a number
1074 hg: parse error: rev expects a number
1067 [255]
1075 [255]
1068
1076
1069 Test hexadecimal revision
1077 Test hexadecimal revision
1070 $ log 'id(2)'
1078 $ log 'id(2)'
1071 abort: 00changelog.i@2: ambiguous identifier!
1079 abort: 00changelog.i@2: ambiguous identifier!
1072 [255]
1080 [255]
1073 $ log 'id(23268)'
1081 $ log 'id(23268)'
1074 4
1082 4
1075 $ log 'id(2785f51eece)'
1083 $ log 'id(2785f51eece)'
1076 0
1084 0
1077 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c)'
1085 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c)'
1078 8
1086 8
1079 $ log 'id(d5d0dcbdc4a)'
1087 $ log 'id(d5d0dcbdc4a)'
1080 $ log 'id(d5d0dcbdc4w)'
1088 $ log 'id(d5d0dcbdc4w)'
1081 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532d)'
1089 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532d)'
1082 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532q)'
1090 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532q)'
1083 $ log 'id(1.0)'
1091 $ log 'id(1.0)'
1084 $ log 'id(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)'
1092 $ log 'id(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)'
1085
1093
1086 Test null revision
1094 Test null revision
1087 $ log '(null)'
1095 $ log '(null)'
1088 -1
1096 -1
1089 $ log '(null:0)'
1097 $ log '(null:0)'
1090 -1
1098 -1
1091 0
1099 0
1092 $ log '(0:null)'
1100 $ log '(0:null)'
1093 0
1101 0
1094 -1
1102 -1
1095 $ log 'null::0'
1103 $ log 'null::0'
1096 -1
1104 -1
1097 0
1105 0
1098 $ log 'null:tip - 0:'
1106 $ log 'null:tip - 0:'
1099 -1
1107 -1
1100 $ log 'null: and null::' | head -1
1108 $ log 'null: and null::' | head -1
1101 -1
1109 -1
1102 $ log 'null: or 0:' | head -2
1110 $ log 'null: or 0:' | head -2
1103 -1
1111 -1
1104 0
1112 0
1105 $ log 'ancestors(null)'
1113 $ log 'ancestors(null)'
1106 -1
1114 -1
1107 $ log 'reverse(null:)' | tail -2
1115 $ log 'reverse(null:)' | tail -2
1108 0
1116 0
1109 -1
1117 -1
1110 BROKEN: should be '-1'
1118 BROKEN: should be '-1'
1111 $ log 'first(null:)'
1119 $ log 'first(null:)'
1112 BROKEN: should be '-1'
1120 BROKEN: should be '-1'
1113 $ log 'min(null:)'
1121 $ log 'min(null:)'
1114 $ log 'tip:null and all()' | tail -2
1122 $ log 'tip:null and all()' | tail -2
1115 1
1123 1
1116 0
1124 0
1117
1125
1118 Test working-directory revision
1126 Test working-directory revision
1119 $ hg debugrevspec 'wdir()'
1127 $ hg debugrevspec 'wdir()'
1120 2147483647
1128 2147483647
1121 $ hg debugrevspec 'tip or wdir()'
1129 $ hg debugrevspec 'tip or wdir()'
1122 9
1130 9
1123 2147483647
1131 2147483647
1124 $ hg debugrevspec '0:tip and wdir()'
1132 $ hg debugrevspec '0:tip and wdir()'
1125 $ log '0:wdir()' | tail -3
1133 $ log '0:wdir()' | tail -3
1126 8
1134 8
1127 9
1135 9
1128 2147483647
1136 2147483647
1129 $ log 'wdir():0' | head -3
1137 $ log 'wdir():0' | head -3
1130 2147483647
1138 2147483647
1131 9
1139 9
1132 8
1140 8
1133 $ log 'wdir():wdir()'
1141 $ log 'wdir():wdir()'
1134 2147483647
1142 2147483647
1135 $ log '(all() + wdir()) & min(. + wdir())'
1143 $ log '(all() + wdir()) & min(. + wdir())'
1136 9
1144 9
1137 $ log '(all() + wdir()) & max(. + wdir())'
1145 $ log '(all() + wdir()) & max(. + wdir())'
1138 2147483647
1146 2147483647
1139 $ log '(all() + wdir()) & first(wdir() + .)'
1147 $ log '(all() + wdir()) & first(wdir() + .)'
1140 2147483647
1148 2147483647
1141 $ log '(all() + wdir()) & last(. + wdir())'
1149 $ log '(all() + wdir()) & last(. + wdir())'
1142 2147483647
1150 2147483647
1143
1151
1144 $ log 'outgoing()'
1152 $ log 'outgoing()'
1145 8
1153 8
1146 9
1154 9
1147 $ log 'outgoing("../remote1")'
1155 $ log 'outgoing("../remote1")'
1148 8
1156 8
1149 9
1157 9
1150 $ log 'outgoing("../remote2")'
1158 $ log 'outgoing("../remote2")'
1151 3
1159 3
1152 5
1160 5
1153 6
1161 6
1154 7
1162 7
1155 9
1163 9
1156 $ log 'p1(merge())'
1164 $ log 'p1(merge())'
1157 5
1165 5
1158 $ log 'p2(merge())'
1166 $ log 'p2(merge())'
1159 4
1167 4
1160 $ log 'parents(merge())'
1168 $ log 'parents(merge())'
1161 4
1169 4
1162 5
1170 5
1163 $ log 'p1(branchpoint())'
1171 $ log 'p1(branchpoint())'
1164 0
1172 0
1165 2
1173 2
1166 $ log 'p2(branchpoint())'
1174 $ log 'p2(branchpoint())'
1167 $ log 'parents(branchpoint())'
1175 $ log 'parents(branchpoint())'
1168 0
1176 0
1169 2
1177 2
1170 $ log 'removes(a)'
1178 $ log 'removes(a)'
1171 2
1179 2
1172 6
1180 6
1173 $ log 'roots(all())'
1181 $ log 'roots(all())'
1174 0
1182 0
1175 $ log 'reverse(2 or 3 or 4 or 5)'
1183 $ log 'reverse(2 or 3 or 4 or 5)'
1176 5
1184 5
1177 4
1185 4
1178 3
1186 3
1179 2
1187 2
1180 $ log 'reverse(all())'
1188 $ log 'reverse(all())'
1181 9
1189 9
1182 8
1190 8
1183 7
1191 7
1184 6
1192 6
1185 5
1193 5
1186 4
1194 4
1187 3
1195 3
1188 2
1196 2
1189 1
1197 1
1190 0
1198 0
1191 $ log 'reverse(all()) & filelog(b)'
1199 $ log 'reverse(all()) & filelog(b)'
1192 4
1200 4
1193 1
1201 1
1194 $ log 'rev(5)'
1202 $ log 'rev(5)'
1195 5
1203 5
1196 $ log 'sort(limit(reverse(all()), 3))'
1204 $ log 'sort(limit(reverse(all()), 3))'
1197 7
1205 7
1198 8
1206 8
1199 9
1207 9
1200 $ log 'sort(2 or 3 or 4 or 5, date)'
1208 $ log 'sort(2 or 3 or 4 or 5, date)'
1201 2
1209 2
1202 3
1210 3
1203 5
1211 5
1204 4
1212 4
1205 $ log 'tagged()'
1213 $ log 'tagged()'
1206 6
1214 6
1207 $ log 'tag()'
1215 $ log 'tag()'
1208 6
1216 6
1209 $ log 'tag(1.0)'
1217 $ log 'tag(1.0)'
1210 6
1218 6
1211 $ log 'tag(tip)'
1219 $ log 'tag(tip)'
1212 9
1220 9
1213
1221
1214 Test order of revisions in compound expression
1222 Test order of revisions in compound expression
1215 ----------------------------------------------
1223 ----------------------------------------------
1216
1224
1217 The general rule is that only the outermost (= leftmost) predicate can
1225 The general rule is that only the outermost (= leftmost) predicate can
1218 enforce its ordering requirement. The other predicates should take the
1226 enforce its ordering requirement. The other predicates should take the
1219 ordering defined by it.
1227 ordering defined by it.
1220
1228
1221 'A & B' should follow the order of 'A':
1229 'A & B' should follow the order of 'A':
1222
1230
1223 $ log '2:0 & 0::2'
1231 $ log '2:0 & 0::2'
1224 2
1232 2
1225 1
1233 1
1226 0
1234 0
1227
1235
1228 'head()' combines sets in right order:
1236 'head()' combines sets in right order:
1229
1237
1230 $ log '2:0 & head()'
1238 $ log '2:0 & head()'
1231 2
1239 2
1232 1
1240 1
1233 0
1241 0
1234
1242
1235 'a + b', which is optimized to '_list(a b)', should take the ordering of
1243 'a + b', which is optimized to '_list(a b)', should take the ordering of
1236 the left expression:
1244 the left expression:
1237
1245
1238 $ try --optimize '2:0 & (0 + 1 + 2)'
1246 $ try --optimize '2:0 & (0 + 1 + 2)'
1239 (and
1247 (and
1240 (range
1248 (range
1241 ('symbol', '2')
1249 ('symbol', '2')
1242 ('symbol', '0'))
1250 ('symbol', '0'))
1243 (group
1251 (group
1244 (or
1252 (or
1245 ('symbol', '0')
1253 (list
1246 ('symbol', '1')
1254 ('symbol', '0')
1247 ('symbol', '2'))))
1255 ('symbol', '1')
1256 ('symbol', '2')))))
1248 * optimized:
1257 * optimized:
1249 (and
1258 (and
1250 (range
1259 (range
1251 ('symbol', '2')
1260 ('symbol', '2')
1252 ('symbol', '0'))
1261 ('symbol', '0'))
1253 (func
1262 (func
1254 ('symbol', '_list')
1263 ('symbol', '_list')
1255 ('string', '0\x001\x002')))
1264 ('string', '0\x001\x002')))
1256 * set:
1265 * set:
1257 <baseset [0, 1, 2]>
1266 <baseset [0, 1, 2]>
1258 0
1267 0
1259 1
1268 1
1260 2
1269 2
1261 BROKEN: should be '2 1 0'
1270 BROKEN: should be '2 1 0'
1262
1271
1263 'A + B' should take the ordering of the left expression:
1272 'A + B' should take the ordering of the left expression:
1264
1273
1265 $ try --optimize '2:0 & (0:1 + 2)'
1274 $ try --optimize '2:0 & (0:1 + 2)'
1266 (and
1275 (and
1267 (range
1276 (range
1268 ('symbol', '2')
1277 ('symbol', '2')
1269 ('symbol', '0'))
1278 ('symbol', '0'))
1270 (group
1279 (group
1271 (or
1280 (or
1272 (range
1281 (list
1273 ('symbol', '0')
1282 (range
1274 ('symbol', '1'))
1283 ('symbol', '0')
1275 ('symbol', '2'))))
1284 ('symbol', '1'))
1285 ('symbol', '2')))))
1276 * optimized:
1286 * optimized:
1277 (and
1287 (and
1278 (range
1288 (range
1279 ('symbol', '2')
1289 ('symbol', '2')
1280 ('symbol', '0'))
1290 ('symbol', '0'))
1281 (or
1291 (or
1282 (range
1292 (list
1283 ('symbol', '0')
1293 (range
1284 ('symbol', '1'))
1294 ('symbol', '0')
1285 ('symbol', '2')))
1295 ('symbol', '1'))
1296 ('symbol', '2'))))
1286 * set:
1297 * set:
1287 <addset
1298 <addset
1288 <filteredset
1299 <filteredset
1289 <spanset+ 0:1>,
1300 <spanset+ 0:1>,
1290 <spanset- 0:2>>,
1301 <spanset- 0:2>>,
1291 <baseset [2]>>
1302 <baseset [2]>>
1292 0
1303 0
1293 1
1304 1
1294 2
1305 2
1295 BROKEN: should be '2 1 0'
1306 BROKEN: should be '2 1 0'
1296
1307
1297 '_intlist(a b)' should behave like 'a + b':
1308 '_intlist(a b)' should behave like 'a + b':
1298
1309
1299 $ trylist --optimize '2:0 & %ld' 0 1 2
1310 $ trylist --optimize '2:0 & %ld' 0 1 2
1300 (and
1311 (and
1301 (range
1312 (range
1302 ('symbol', '2')
1313 ('symbol', '2')
1303 ('symbol', '0'))
1314 ('symbol', '0'))
1304 (func
1315 (func
1305 ('symbol', '_intlist')
1316 ('symbol', '_intlist')
1306 ('string', '0\x001\x002')))
1317 ('string', '0\x001\x002')))
1307 * optimized:
1318 * optimized:
1308 (and
1319 (and
1309 (func
1320 (func
1310 ('symbol', '_intlist')
1321 ('symbol', '_intlist')
1311 ('string', '0\x001\x002'))
1322 ('string', '0\x001\x002'))
1312 (range
1323 (range
1313 ('symbol', '2')
1324 ('symbol', '2')
1314 ('symbol', '0')))
1325 ('symbol', '0')))
1315 * set:
1326 * set:
1316 <filteredset
1327 <filteredset
1317 <spanset- 0:2>,
1328 <spanset- 0:2>,
1318 <baseset [0, 1, 2]>>
1329 <baseset [0, 1, 2]>>
1319 2
1330 2
1320 1
1331 1
1321 0
1332 0
1322
1333
1323 $ trylist --optimize '%ld & 2:0' 0 2 1
1334 $ trylist --optimize '%ld & 2:0' 0 2 1
1324 (and
1335 (and
1325 (func
1336 (func
1326 ('symbol', '_intlist')
1337 ('symbol', '_intlist')
1327 ('string', '0\x002\x001'))
1338 ('string', '0\x002\x001'))
1328 (range
1339 (range
1329 ('symbol', '2')
1340 ('symbol', '2')
1330 ('symbol', '0')))
1341 ('symbol', '0')))
1331 * optimized:
1342 * optimized:
1332 (and
1343 (and
1333 (func
1344 (func
1334 ('symbol', '_intlist')
1345 ('symbol', '_intlist')
1335 ('string', '0\x002\x001'))
1346 ('string', '0\x002\x001'))
1336 (range
1347 (range
1337 ('symbol', '2')
1348 ('symbol', '2')
1338 ('symbol', '0')))
1349 ('symbol', '0')))
1339 * set:
1350 * set:
1340 <filteredset
1351 <filteredset
1341 <spanset- 0:2>,
1352 <spanset- 0:2>,
1342 <baseset [0, 2, 1]>>
1353 <baseset [0, 2, 1]>>
1343 2
1354 2
1344 1
1355 1
1345 0
1356 0
1346 BROKEN: should be '0 2 1'
1357 BROKEN: should be '0 2 1'
1347
1358
1348 '_hexlist(a b)' should behave like 'a + b':
1359 '_hexlist(a b)' should behave like 'a + b':
1349
1360
1350 $ trylist --optimize --bin '2:0 & %ln' `hg log -T '{node} ' -r0:2`
1361 $ trylist --optimize --bin '2:0 & %ln' `hg log -T '{node} ' -r0:2`
1351 (and
1362 (and
1352 (range
1363 (range
1353 ('symbol', '2')
1364 ('symbol', '2')
1354 ('symbol', '0'))
1365 ('symbol', '0'))
1355 (func
1366 (func
1356 ('symbol', '_hexlist')
1367 ('symbol', '_hexlist')
1357 ('string', '*'))) (glob)
1368 ('string', '*'))) (glob)
1358 * optimized:
1369 * optimized:
1359 (and
1370 (and
1360 (range
1371 (range
1361 ('symbol', '2')
1372 ('symbol', '2')
1362 ('symbol', '0'))
1373 ('symbol', '0'))
1363 (func
1374 (func
1364 ('symbol', '_hexlist')
1375 ('symbol', '_hexlist')
1365 ('string', '*'))) (glob)
1376 ('string', '*'))) (glob)
1366 * set:
1377 * set:
1367 <baseset [0, 1, 2]>
1378 <baseset [0, 1, 2]>
1368 0
1379 0
1369 1
1380 1
1370 2
1381 2
1371 BROKEN: should be '2 1 0'
1382 BROKEN: should be '2 1 0'
1372
1383
1373 $ trylist --optimize --bin '%ln & 2:0' `hg log -T '{node} ' -r0+2+1`
1384 $ trylist --optimize --bin '%ln & 2:0' `hg log -T '{node} ' -r0+2+1`
1374 (and
1385 (and
1375 (func
1386 (func
1376 ('symbol', '_hexlist')
1387 ('symbol', '_hexlist')
1377 ('string', '*')) (glob)
1388 ('string', '*')) (glob)
1378 (range
1389 (range
1379 ('symbol', '2')
1390 ('symbol', '2')
1380 ('symbol', '0')))
1391 ('symbol', '0')))
1381 * optimized:
1392 * optimized:
1382 (and
1393 (and
1383 (range
1394 (range
1384 ('symbol', '2')
1395 ('symbol', '2')
1385 ('symbol', '0'))
1396 ('symbol', '0'))
1386 (func
1397 (func
1387 ('symbol', '_hexlist')
1398 ('symbol', '_hexlist')
1388 ('string', '*'))) (glob)
1399 ('string', '*'))) (glob)
1389 * set:
1400 * set:
1390 <baseset [0, 2, 1]>
1401 <baseset [0, 2, 1]>
1391 0
1402 0
1392 2
1403 2
1393 1
1404 1
1394
1405
1395 'present()' should do nothing other than suppressing an error:
1406 'present()' should do nothing other than suppressing an error:
1396
1407
1397 $ try --optimize '2:0 & present(0 + 1 + 2)'
1408 $ try --optimize '2:0 & present(0 + 1 + 2)'
1398 (and
1409 (and
1399 (range
1410 (range
1400 ('symbol', '2')
1411 ('symbol', '2')
1401 ('symbol', '0'))
1412 ('symbol', '0'))
1402 (func
1413 (func
1403 ('symbol', 'present')
1414 ('symbol', 'present')
1404 (or
1415 (or
1405 ('symbol', '0')
1416 (list
1406 ('symbol', '1')
1417 ('symbol', '0')
1407 ('symbol', '2'))))
1418 ('symbol', '1')
1419 ('symbol', '2')))))
1408 * optimized:
1420 * optimized:
1409 (and
1421 (and
1410 (range
1422 (range
1411 ('symbol', '2')
1423 ('symbol', '2')
1412 ('symbol', '0'))
1424 ('symbol', '0'))
1413 (func
1425 (func
1414 ('symbol', 'present')
1426 ('symbol', 'present')
1415 (func
1427 (func
1416 ('symbol', '_list')
1428 ('symbol', '_list')
1417 ('string', '0\x001\x002'))))
1429 ('string', '0\x001\x002'))))
1418 * set:
1430 * set:
1419 <baseset [0, 1, 2]>
1431 <baseset [0, 1, 2]>
1420 0
1432 0
1421 1
1433 1
1422 2
1434 2
1423 BROKEN: should be '2 1 0'
1435 BROKEN: should be '2 1 0'
1424
1436
1425 'reverse()' should take effect only if it is the outermost expression:
1437 'reverse()' should take effect only if it is the outermost expression:
1426
1438
1427 $ try --optimize '0:2 & reverse(all())'
1439 $ try --optimize '0:2 & reverse(all())'
1428 (and
1440 (and
1429 (range
1441 (range
1430 ('symbol', '0')
1442 ('symbol', '0')
1431 ('symbol', '2'))
1443 ('symbol', '2'))
1432 (func
1444 (func
1433 ('symbol', 'reverse')
1445 ('symbol', 'reverse')
1434 (func
1446 (func
1435 ('symbol', 'all')
1447 ('symbol', 'all')
1436 None)))
1448 None)))
1437 * optimized:
1449 * optimized:
1438 (and
1450 (and
1439 (range
1451 (range
1440 ('symbol', '0')
1452 ('symbol', '0')
1441 ('symbol', '2'))
1453 ('symbol', '2'))
1442 (func
1454 (func
1443 ('symbol', 'reverse')
1455 ('symbol', 'reverse')
1444 (func
1456 (func
1445 ('symbol', 'all')
1457 ('symbol', 'all')
1446 None)))
1458 None)))
1447 * set:
1459 * set:
1448 <filteredset
1460 <filteredset
1449 <spanset- 0:2>,
1461 <spanset- 0:2>,
1450 <spanset+ 0:9>>
1462 <spanset+ 0:9>>
1451 2
1463 2
1452 1
1464 1
1453 0
1465 0
1454 BROKEN: should be '0 1 2'
1466 BROKEN: should be '0 1 2'
1455
1467
1456 'sort()' should take effect only if it is the outermost expression:
1468 'sort()' should take effect only if it is the outermost expression:
1457
1469
1458 $ try --optimize '0:2 & sort(all(), -rev)'
1470 $ try --optimize '0:2 & sort(all(), -rev)'
1459 (and
1471 (and
1460 (range
1472 (range
1461 ('symbol', '0')
1473 ('symbol', '0')
1462 ('symbol', '2'))
1474 ('symbol', '2'))
1463 (func
1475 (func
1464 ('symbol', 'sort')
1476 ('symbol', 'sort')
1465 (list
1477 (list
1466 (func
1478 (func
1467 ('symbol', 'all')
1479 ('symbol', 'all')
1468 None)
1480 None)
1469 (negate
1481 (negate
1470 ('symbol', 'rev')))))
1482 ('symbol', 'rev')))))
1471 * optimized:
1483 * optimized:
1472 (and
1484 (and
1473 (range
1485 (range
1474 ('symbol', '0')
1486 ('symbol', '0')
1475 ('symbol', '2'))
1487 ('symbol', '2'))
1476 (func
1488 (func
1477 ('symbol', 'sort')
1489 ('symbol', 'sort')
1478 (list
1490 (list
1479 (func
1491 (func
1480 ('symbol', 'all')
1492 ('symbol', 'all')
1481 None)
1493 None)
1482 ('string', '-rev'))))
1494 ('string', '-rev'))))
1483 * set:
1495 * set:
1484 <filteredset
1496 <filteredset
1485 <spanset- 0:2>,
1497 <spanset- 0:2>,
1486 <spanset+ 0:9>>
1498 <spanset+ 0:9>>
1487 2
1499 2
1488 1
1500 1
1489 0
1501 0
1490 BROKEN: should be '0 1 2'
1502 BROKEN: should be '0 1 2'
1491
1503
1492 for 'A & f(B)', 'B' should not be affected by the order of 'A':
1504 for 'A & f(B)', 'B' should not be affected by the order of 'A':
1493
1505
1494 $ try --optimize '2:0 & first(1 + 0 + 2)'
1506 $ try --optimize '2:0 & first(1 + 0 + 2)'
1495 (and
1507 (and
1496 (range
1508 (range
1497 ('symbol', '2')
1509 ('symbol', '2')
1498 ('symbol', '0'))
1510 ('symbol', '0'))
1499 (func
1511 (func
1500 ('symbol', 'first')
1512 ('symbol', 'first')
1501 (or
1513 (or
1502 ('symbol', '1')
1514 (list
1503 ('symbol', '0')
1515 ('symbol', '1')
1504 ('symbol', '2'))))
1516 ('symbol', '0')
1517 ('symbol', '2')))))
1505 * optimized:
1518 * optimized:
1506 (and
1519 (and
1507 (range
1520 (range
1508 ('symbol', '2')
1521 ('symbol', '2')
1509 ('symbol', '0'))
1522 ('symbol', '0'))
1510 (func
1523 (func
1511 ('symbol', 'first')
1524 ('symbol', 'first')
1512 (func
1525 (func
1513 ('symbol', '_list')
1526 ('symbol', '_list')
1514 ('string', '1\x000\x002'))))
1527 ('string', '1\x000\x002'))))
1515 * set:
1528 * set:
1516 <baseset
1529 <baseset
1517 <limit n=1, offset=0,
1530 <limit n=1, offset=0,
1518 <spanset- 0:2>,
1531 <spanset- 0:2>,
1519 <baseset [1, 0, 2]>>>
1532 <baseset [1, 0, 2]>>>
1520 1
1533 1
1521
1534
1522 $ try --optimize '2:0 & not last(0 + 2 + 1)'
1535 $ try --optimize '2:0 & not last(0 + 2 + 1)'
1523 (and
1536 (and
1524 (range
1537 (range
1525 ('symbol', '2')
1538 ('symbol', '2')
1526 ('symbol', '0'))
1539 ('symbol', '0'))
1527 (not
1540 (not
1528 (func
1541 (func
1529 ('symbol', 'last')
1542 ('symbol', 'last')
1530 (or
1543 (or
1531 ('symbol', '0')
1544 (list
1532 ('symbol', '2')
1545 ('symbol', '0')
1533 ('symbol', '1')))))
1546 ('symbol', '2')
1547 ('symbol', '1'))))))
1534 * optimized:
1548 * optimized:
1535 (difference
1549 (difference
1536 (range
1550 (range
1537 ('symbol', '2')
1551 ('symbol', '2')
1538 ('symbol', '0'))
1552 ('symbol', '0'))
1539 (func
1553 (func
1540 ('symbol', 'last')
1554 ('symbol', 'last')
1541 (func
1555 (func
1542 ('symbol', '_list')
1556 ('symbol', '_list')
1543 ('string', '0\x002\x001'))))
1557 ('string', '0\x002\x001'))))
1544 * set:
1558 * set:
1545 <filteredset
1559 <filteredset
1546 <spanset- 0:2>,
1560 <spanset- 0:2>,
1547 <not
1561 <not
1548 <baseset
1562 <baseset
1549 <last n=1,
1563 <last n=1,
1550 <fullreposet+ 0:9>,
1564 <fullreposet+ 0:9>,
1551 <baseset [1, 2, 0]>>>>>
1565 <baseset [1, 2, 0]>>>>>
1552 2
1566 2
1553 0
1567 0
1554
1568
1555 for 'A & (op)(B)', 'B' should not be affected by the order of 'A':
1569 for 'A & (op)(B)', 'B' should not be affected by the order of 'A':
1556
1570
1557 $ try --optimize '2:0 & (1 + 0 + 2):(0 + 2 + 1)'
1571 $ try --optimize '2:0 & (1 + 0 + 2):(0 + 2 + 1)'
1558 (and
1572 (and
1559 (range
1573 (range
1560 ('symbol', '2')
1574 ('symbol', '2')
1561 ('symbol', '0'))
1575 ('symbol', '0'))
1562 (range
1576 (range
1563 (group
1577 (group
1564 (or
1578 (or
1565 ('symbol', '1')
1579 (list
1566 ('symbol', '0')
1580 ('symbol', '1')
1567 ('symbol', '2')))
1581 ('symbol', '0')
1582 ('symbol', '2'))))
1568 (group
1583 (group
1569 (or
1584 (or
1570 ('symbol', '0')
1585 (list
1571 ('symbol', '2')
1586 ('symbol', '0')
1572 ('symbol', '1')))))
1587 ('symbol', '2')
1588 ('symbol', '1'))))))
1573 * optimized:
1589 * optimized:
1574 (and
1590 (and
1575 (range
1591 (range
1576 ('symbol', '2')
1592 ('symbol', '2')
1577 ('symbol', '0'))
1593 ('symbol', '0'))
1578 (range
1594 (range
1579 (func
1595 (func
1580 ('symbol', '_list')
1596 ('symbol', '_list')
1581 ('string', '1\x000\x002'))
1597 ('string', '1\x000\x002'))
1582 (func
1598 (func
1583 ('symbol', '_list')
1599 ('symbol', '_list')
1584 ('string', '0\x002\x001'))))
1600 ('string', '0\x002\x001'))))
1585 * set:
1601 * set:
1586 <filteredset
1602 <filteredset
1587 <baseset [1]>,
1603 <baseset [1]>,
1588 <spanset- 0:2>>
1604 <spanset- 0:2>>
1589 1
1605 1
1590
1606
1591 'A & B' can be rewritten as 'B & A' by weight, but the ordering rule should
1607 'A & B' can be rewritten as 'B & A' by weight, but the ordering rule should
1592 be determined before the optimization (i.e. 'B' should take the ordering of
1608 be determined before the optimization (i.e. 'B' should take the ordering of
1593 'A'):
1609 'A'):
1594
1610
1595 $ try --optimize 'contains("glob:*") & (2 + 0 + 1)'
1611 $ try --optimize 'contains("glob:*") & (2 + 0 + 1)'
1596 (and
1612 (and
1597 (func
1613 (func
1598 ('symbol', 'contains')
1614 ('symbol', 'contains')
1599 ('string', 'glob:*'))
1615 ('string', 'glob:*'))
1600 (group
1616 (group
1601 (or
1617 (or
1602 ('symbol', '2')
1618 (list
1603 ('symbol', '0')
1619 ('symbol', '2')
1604 ('symbol', '1'))))
1620 ('symbol', '0')
1621 ('symbol', '1')))))
1605 * optimized:
1622 * optimized:
1606 (and
1623 (and
1607 (func
1624 (func
1608 ('symbol', '_list')
1625 ('symbol', '_list')
1609 ('string', '2\x000\x001'))
1626 ('string', '2\x000\x001'))
1610 (func
1627 (func
1611 ('symbol', 'contains')
1628 ('symbol', 'contains')
1612 ('string', 'glob:*')))
1629 ('string', 'glob:*')))
1613 * set:
1630 * set:
1614 <filteredset
1631 <filteredset
1615 <baseset [2, 0, 1]>,
1632 <baseset [2, 0, 1]>,
1616 <contains 'glob:*'>>
1633 <contains 'glob:*'>>
1617 2
1634 2
1618 0
1635 0
1619 1
1636 1
1620 BROKEN: should be '0 1 2'
1637 BROKEN: should be '0 1 2'
1621
1638
1622 $ try --optimize 'reverse(contains("glob:*")) & (0 + 2 + 1)'
1639 $ try --optimize 'reverse(contains("glob:*")) & (0 + 2 + 1)'
1623 (and
1640 (and
1624 (func
1641 (func
1625 ('symbol', 'reverse')
1642 ('symbol', 'reverse')
1626 (func
1643 (func
1627 ('symbol', 'contains')
1644 ('symbol', 'contains')
1628 ('string', 'glob:*')))
1645 ('string', 'glob:*')))
1629 (group
1646 (group
1630 (or
1647 (or
1631 ('symbol', '0')
1648 (list
1632 ('symbol', '2')
1649 ('symbol', '0')
1633 ('symbol', '1'))))
1650 ('symbol', '2')
1651 ('symbol', '1')))))
1634 * optimized:
1652 * optimized:
1635 (and
1653 (and
1636 (func
1654 (func
1637 ('symbol', '_list')
1655 ('symbol', '_list')
1638 ('string', '0\x002\x001'))
1656 ('string', '0\x002\x001'))
1639 (func
1657 (func
1640 ('symbol', 'reverse')
1658 ('symbol', 'reverse')
1641 (func
1659 (func
1642 ('symbol', 'contains')
1660 ('symbol', 'contains')
1643 ('string', 'glob:*'))))
1661 ('string', 'glob:*'))))
1644 * set:
1662 * set:
1645 <filteredset
1663 <filteredset
1646 <baseset [1, 2, 0]>,
1664 <baseset [1, 2, 0]>,
1647 <contains 'glob:*'>>
1665 <contains 'glob:*'>>
1648 1
1666 1
1649 2
1667 2
1650 0
1668 0
1651 BROKEN: should be '2 1 0'
1669 BROKEN: should be '2 1 0'
1652
1670
1653 test sort revset
1671 test sort revset
1654 --------------------------------------------
1672 --------------------------------------------
1655
1673
1656 test when adding two unordered revsets
1674 test when adding two unordered revsets
1657
1675
1658 $ log 'sort(keyword(issue) or modifies(b))'
1676 $ log 'sort(keyword(issue) or modifies(b))'
1659 4
1677 4
1660 6
1678 6
1661
1679
1662 test when sorting a reversed collection in the same way it is
1680 test when sorting a reversed collection in the same way it is
1663
1681
1664 $ log 'sort(reverse(all()), -rev)'
1682 $ log 'sort(reverse(all()), -rev)'
1665 9
1683 9
1666 8
1684 8
1667 7
1685 7
1668 6
1686 6
1669 5
1687 5
1670 4
1688 4
1671 3
1689 3
1672 2
1690 2
1673 1
1691 1
1674 0
1692 0
1675
1693
1676 test when sorting a reversed collection
1694 test when sorting a reversed collection
1677
1695
1678 $ log 'sort(reverse(all()), rev)'
1696 $ log 'sort(reverse(all()), rev)'
1679 0
1697 0
1680 1
1698 1
1681 2
1699 2
1682 3
1700 3
1683 4
1701 4
1684 5
1702 5
1685 6
1703 6
1686 7
1704 7
1687 8
1705 8
1688 9
1706 9
1689
1707
1690
1708
1691 test sorting two sorted collections in different orders
1709 test sorting two sorted collections in different orders
1692
1710
1693 $ log 'sort(outgoing() or reverse(removes(a)), rev)'
1711 $ log 'sort(outgoing() or reverse(removes(a)), rev)'
1694 2
1712 2
1695 6
1713 6
1696 8
1714 8
1697 9
1715 9
1698
1716
1699 test sorting two sorted collections in different orders backwards
1717 test sorting two sorted collections in different orders backwards
1700
1718
1701 $ log 'sort(outgoing() or reverse(removes(a)), -rev)'
1719 $ log 'sort(outgoing() or reverse(removes(a)), -rev)'
1702 9
1720 9
1703 8
1721 8
1704 6
1722 6
1705 2
1723 2
1706
1724
1707 test empty sort key which is noop
1725 test empty sort key which is noop
1708
1726
1709 $ log 'sort(0 + 2 + 1, "")'
1727 $ log 'sort(0 + 2 + 1, "")'
1710 0
1728 0
1711 2
1729 2
1712 1
1730 1
1713
1731
1714 test invalid sort keys
1732 test invalid sort keys
1715
1733
1716 $ log 'sort(all(), -invalid)'
1734 $ log 'sort(all(), -invalid)'
1717 hg: parse error: unknown sort key '-invalid'
1735 hg: parse error: unknown sort key '-invalid'
1718 [255]
1736 [255]
1719
1737
1720 $ cd ..
1738 $ cd ..
1721
1739
1722 test sorting by multiple keys including variable-length strings
1740 test sorting by multiple keys including variable-length strings
1723
1741
1724 $ hg init sorting
1742 $ hg init sorting
1725 $ cd sorting
1743 $ cd sorting
1726 $ cat <<EOF >> .hg/hgrc
1744 $ cat <<EOF >> .hg/hgrc
1727 > [ui]
1745 > [ui]
1728 > logtemplate = '{rev} {branch|p5}{desc|p5}{author|p5}{date|hgdate}\n'
1746 > logtemplate = '{rev} {branch|p5}{desc|p5}{author|p5}{date|hgdate}\n'
1729 > [templatealias]
1747 > [templatealias]
1730 > p5(s) = pad(s, 5)
1748 > p5(s) = pad(s, 5)
1731 > EOF
1749 > EOF
1732 $ hg branch -qf b12
1750 $ hg branch -qf b12
1733 $ hg ci -m m111 -u u112 -d '111 10800'
1751 $ hg ci -m m111 -u u112 -d '111 10800'
1734 $ hg branch -qf b11
1752 $ hg branch -qf b11
1735 $ hg ci -m m12 -u u111 -d '112 7200'
1753 $ hg ci -m m12 -u u111 -d '112 7200'
1736 $ hg branch -qf b111
1754 $ hg branch -qf b111
1737 $ hg ci -m m11 -u u12 -d '111 3600'
1755 $ hg ci -m m11 -u u12 -d '111 3600'
1738 $ hg branch -qf b112
1756 $ hg branch -qf b112
1739 $ hg ci -m m111 -u u11 -d '120 0'
1757 $ hg ci -m m111 -u u11 -d '120 0'
1740 $ hg branch -qf b111
1758 $ hg branch -qf b111
1741 $ hg ci -m m112 -u u111 -d '110 14400'
1759 $ hg ci -m m112 -u u111 -d '110 14400'
1742 created new head
1760 created new head
1743
1761
1744 compare revisions (has fast path):
1762 compare revisions (has fast path):
1745
1763
1746 $ hg log -r 'sort(all(), rev)'
1764 $ hg log -r 'sort(all(), rev)'
1747 0 b12 m111 u112 111 10800
1765 0 b12 m111 u112 111 10800
1748 1 b11 m12 u111 112 7200
1766 1 b11 m12 u111 112 7200
1749 2 b111 m11 u12 111 3600
1767 2 b111 m11 u12 111 3600
1750 3 b112 m111 u11 120 0
1768 3 b112 m111 u11 120 0
1751 4 b111 m112 u111 110 14400
1769 4 b111 m112 u111 110 14400
1752
1770
1753 $ hg log -r 'sort(all(), -rev)'
1771 $ hg log -r 'sort(all(), -rev)'
1754 4 b111 m112 u111 110 14400
1772 4 b111 m112 u111 110 14400
1755 3 b112 m111 u11 120 0
1773 3 b112 m111 u11 120 0
1756 2 b111 m11 u12 111 3600
1774 2 b111 m11 u12 111 3600
1757 1 b11 m12 u111 112 7200
1775 1 b11 m12 u111 112 7200
1758 0 b12 m111 u112 111 10800
1776 0 b12 m111 u112 111 10800
1759
1777
1760 compare variable-length strings (issue5218):
1778 compare variable-length strings (issue5218):
1761
1779
1762 $ hg log -r 'sort(all(), branch)'
1780 $ hg log -r 'sort(all(), branch)'
1763 1 b11 m12 u111 112 7200
1781 1 b11 m12 u111 112 7200
1764 2 b111 m11 u12 111 3600
1782 2 b111 m11 u12 111 3600
1765 4 b111 m112 u111 110 14400
1783 4 b111 m112 u111 110 14400
1766 3 b112 m111 u11 120 0
1784 3 b112 m111 u11 120 0
1767 0 b12 m111 u112 111 10800
1785 0 b12 m111 u112 111 10800
1768
1786
1769 $ hg log -r 'sort(all(), -branch)'
1787 $ hg log -r 'sort(all(), -branch)'
1770 0 b12 m111 u112 111 10800
1788 0 b12 m111 u112 111 10800
1771 3 b112 m111 u11 120 0
1789 3 b112 m111 u11 120 0
1772 2 b111 m11 u12 111 3600
1790 2 b111 m11 u12 111 3600
1773 4 b111 m112 u111 110 14400
1791 4 b111 m112 u111 110 14400
1774 1 b11 m12 u111 112 7200
1792 1 b11 m12 u111 112 7200
1775
1793
1776 $ hg log -r 'sort(all(), desc)'
1794 $ hg log -r 'sort(all(), desc)'
1777 2 b111 m11 u12 111 3600
1795 2 b111 m11 u12 111 3600
1778 0 b12 m111 u112 111 10800
1796 0 b12 m111 u112 111 10800
1779 3 b112 m111 u11 120 0
1797 3 b112 m111 u11 120 0
1780 4 b111 m112 u111 110 14400
1798 4 b111 m112 u111 110 14400
1781 1 b11 m12 u111 112 7200
1799 1 b11 m12 u111 112 7200
1782
1800
1783 $ hg log -r 'sort(all(), -desc)'
1801 $ hg log -r 'sort(all(), -desc)'
1784 1 b11 m12 u111 112 7200
1802 1 b11 m12 u111 112 7200
1785 4 b111 m112 u111 110 14400
1803 4 b111 m112 u111 110 14400
1786 0 b12 m111 u112 111 10800
1804 0 b12 m111 u112 111 10800
1787 3 b112 m111 u11 120 0
1805 3 b112 m111 u11 120 0
1788 2 b111 m11 u12 111 3600
1806 2 b111 m11 u12 111 3600
1789
1807
1790 $ hg log -r 'sort(all(), user)'
1808 $ hg log -r 'sort(all(), user)'
1791 3 b112 m111 u11 120 0
1809 3 b112 m111 u11 120 0
1792 1 b11 m12 u111 112 7200
1810 1 b11 m12 u111 112 7200
1793 4 b111 m112 u111 110 14400
1811 4 b111 m112 u111 110 14400
1794 0 b12 m111 u112 111 10800
1812 0 b12 m111 u112 111 10800
1795 2 b111 m11 u12 111 3600
1813 2 b111 m11 u12 111 3600
1796
1814
1797 $ hg log -r 'sort(all(), -user)'
1815 $ hg log -r 'sort(all(), -user)'
1798 2 b111 m11 u12 111 3600
1816 2 b111 m11 u12 111 3600
1799 0 b12 m111 u112 111 10800
1817 0 b12 m111 u112 111 10800
1800 1 b11 m12 u111 112 7200
1818 1 b11 m12 u111 112 7200
1801 4 b111 m112 u111 110 14400
1819 4 b111 m112 u111 110 14400
1802 3 b112 m111 u11 120 0
1820 3 b112 m111 u11 120 0
1803
1821
1804 compare dates (tz offset should have no effect):
1822 compare dates (tz offset should have no effect):
1805
1823
1806 $ hg log -r 'sort(all(), date)'
1824 $ hg log -r 'sort(all(), date)'
1807 4 b111 m112 u111 110 14400
1825 4 b111 m112 u111 110 14400
1808 0 b12 m111 u112 111 10800
1826 0 b12 m111 u112 111 10800
1809 2 b111 m11 u12 111 3600
1827 2 b111 m11 u12 111 3600
1810 1 b11 m12 u111 112 7200
1828 1 b11 m12 u111 112 7200
1811 3 b112 m111 u11 120 0
1829 3 b112 m111 u11 120 0
1812
1830
1813 $ hg log -r 'sort(all(), -date)'
1831 $ hg log -r 'sort(all(), -date)'
1814 3 b112 m111 u11 120 0
1832 3 b112 m111 u11 120 0
1815 1 b11 m12 u111 112 7200
1833 1 b11 m12 u111 112 7200
1816 0 b12 m111 u112 111 10800
1834 0 b12 m111 u112 111 10800
1817 2 b111 m11 u12 111 3600
1835 2 b111 m11 u12 111 3600
1818 4 b111 m112 u111 110 14400
1836 4 b111 m112 u111 110 14400
1819
1837
1820 be aware that 'sort(x, -k)' is not exactly the same as 'reverse(sort(x, k))'
1838 be aware that 'sort(x, -k)' is not exactly the same as 'reverse(sort(x, k))'
1821 because '-k' reverses the comparison, not the list itself:
1839 because '-k' reverses the comparison, not the list itself:
1822
1840
1823 $ hg log -r 'sort(0 + 2, date)'
1841 $ hg log -r 'sort(0 + 2, date)'
1824 0 b12 m111 u112 111 10800
1842 0 b12 m111 u112 111 10800
1825 2 b111 m11 u12 111 3600
1843 2 b111 m11 u12 111 3600
1826
1844
1827 $ hg log -r 'sort(0 + 2, -date)'
1845 $ hg log -r 'sort(0 + 2, -date)'
1828 0 b12 m111 u112 111 10800
1846 0 b12 m111 u112 111 10800
1829 2 b111 m11 u12 111 3600
1847 2 b111 m11 u12 111 3600
1830
1848
1831 $ hg log -r 'reverse(sort(0 + 2, date))'
1849 $ hg log -r 'reverse(sort(0 + 2, date))'
1832 2 b111 m11 u12 111 3600
1850 2 b111 m11 u12 111 3600
1833 0 b12 m111 u112 111 10800
1851 0 b12 m111 u112 111 10800
1834
1852
1835 sort by multiple keys:
1853 sort by multiple keys:
1836
1854
1837 $ hg log -r 'sort(all(), "branch -rev")'
1855 $ hg log -r 'sort(all(), "branch -rev")'
1838 1 b11 m12 u111 112 7200
1856 1 b11 m12 u111 112 7200
1839 4 b111 m112 u111 110 14400
1857 4 b111 m112 u111 110 14400
1840 2 b111 m11 u12 111 3600
1858 2 b111 m11 u12 111 3600
1841 3 b112 m111 u11 120 0
1859 3 b112 m111 u11 120 0
1842 0 b12 m111 u112 111 10800
1860 0 b12 m111 u112 111 10800
1843
1861
1844 $ hg log -r 'sort(all(), "-desc -date")'
1862 $ hg log -r 'sort(all(), "-desc -date")'
1845 1 b11 m12 u111 112 7200
1863 1 b11 m12 u111 112 7200
1846 4 b111 m112 u111 110 14400
1864 4 b111 m112 u111 110 14400
1847 3 b112 m111 u11 120 0
1865 3 b112 m111 u11 120 0
1848 0 b12 m111 u112 111 10800
1866 0 b12 m111 u112 111 10800
1849 2 b111 m11 u12 111 3600
1867 2 b111 m11 u12 111 3600
1850
1868
1851 $ hg log -r 'sort(all(), "user -branch date rev")'
1869 $ hg log -r 'sort(all(), "user -branch date rev")'
1852 3 b112 m111 u11 120 0
1870 3 b112 m111 u11 120 0
1853 4 b111 m112 u111 110 14400
1871 4 b111 m112 u111 110 14400
1854 1 b11 m12 u111 112 7200
1872 1 b11 m12 u111 112 7200
1855 0 b12 m111 u112 111 10800
1873 0 b12 m111 u112 111 10800
1856 2 b111 m11 u12 111 3600
1874 2 b111 m11 u12 111 3600
1857
1875
1858 toposort prioritises graph branches
1876 toposort prioritises graph branches
1859
1877
1860 $ hg up 2
1878 $ hg up 2
1861 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1879 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1862 $ touch a
1880 $ touch a
1863 $ hg addremove
1881 $ hg addremove
1864 adding a
1882 adding a
1865 $ hg ci -m 't1' -u 'tu' -d '130 0'
1883 $ hg ci -m 't1' -u 'tu' -d '130 0'
1866 created new head
1884 created new head
1867 $ echo 'a' >> a
1885 $ echo 'a' >> a
1868 $ hg ci -m 't2' -u 'tu' -d '130 0'
1886 $ hg ci -m 't2' -u 'tu' -d '130 0'
1869 $ hg book book1
1887 $ hg book book1
1870 $ hg up 4
1888 $ hg up 4
1871 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1889 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1872 (leaving bookmark book1)
1890 (leaving bookmark book1)
1873 $ touch a
1891 $ touch a
1874 $ hg addremove
1892 $ hg addremove
1875 adding a
1893 adding a
1876 $ hg ci -m 't3' -u 'tu' -d '130 0'
1894 $ hg ci -m 't3' -u 'tu' -d '130 0'
1877
1895
1878 $ hg log -r 'sort(all(), topo)'
1896 $ hg log -r 'sort(all(), topo)'
1879 7 b111 t3 tu 130 0
1897 7 b111 t3 tu 130 0
1880 4 b111 m112 u111 110 14400
1898 4 b111 m112 u111 110 14400
1881 3 b112 m111 u11 120 0
1899 3 b112 m111 u11 120 0
1882 6 b111 t2 tu 130 0
1900 6 b111 t2 tu 130 0
1883 5 b111 t1 tu 130 0
1901 5 b111 t1 tu 130 0
1884 2 b111 m11 u12 111 3600
1902 2 b111 m11 u12 111 3600
1885 1 b11 m12 u111 112 7200
1903 1 b11 m12 u111 112 7200
1886 0 b12 m111 u112 111 10800
1904 0 b12 m111 u112 111 10800
1887
1905
1888 $ hg log -r 'sort(all(), -topo)'
1906 $ hg log -r 'sort(all(), -topo)'
1889 0 b12 m111 u112 111 10800
1907 0 b12 m111 u112 111 10800
1890 1 b11 m12 u111 112 7200
1908 1 b11 m12 u111 112 7200
1891 2 b111 m11 u12 111 3600
1909 2 b111 m11 u12 111 3600
1892 5 b111 t1 tu 130 0
1910 5 b111 t1 tu 130 0
1893 6 b111 t2 tu 130 0
1911 6 b111 t2 tu 130 0
1894 3 b112 m111 u11 120 0
1912 3 b112 m111 u11 120 0
1895 4 b111 m112 u111 110 14400
1913 4 b111 m112 u111 110 14400
1896 7 b111 t3 tu 130 0
1914 7 b111 t3 tu 130 0
1897
1915
1898 $ hg log -r 'sort(all(), topo, topo.firstbranch=book1)'
1916 $ hg log -r 'sort(all(), topo, topo.firstbranch=book1)'
1899 6 b111 t2 tu 130 0
1917 6 b111 t2 tu 130 0
1900 5 b111 t1 tu 130 0
1918 5 b111 t1 tu 130 0
1901 7 b111 t3 tu 130 0
1919 7 b111 t3 tu 130 0
1902 4 b111 m112 u111 110 14400
1920 4 b111 m112 u111 110 14400
1903 3 b112 m111 u11 120 0
1921 3 b112 m111 u11 120 0
1904 2 b111 m11 u12 111 3600
1922 2 b111 m11 u12 111 3600
1905 1 b11 m12 u111 112 7200
1923 1 b11 m12 u111 112 7200
1906 0 b12 m111 u112 111 10800
1924 0 b12 m111 u112 111 10800
1907
1925
1908 topographical sorting can't be combined with other sort keys, and you can't
1926 topographical sorting can't be combined with other sort keys, and you can't
1909 use the topo.firstbranch option when topo sort is not active:
1927 use the topo.firstbranch option when topo sort is not active:
1910
1928
1911 $ hg log -r 'sort(all(), "topo user")'
1929 $ hg log -r 'sort(all(), "topo user")'
1912 hg: parse error: topo sort order cannot be combined with other sort keys
1930 hg: parse error: topo sort order cannot be combined with other sort keys
1913 [255]
1931 [255]
1914
1932
1915 $ hg log -r 'sort(all(), user, topo.firstbranch=book1)'
1933 $ hg log -r 'sort(all(), user, topo.firstbranch=book1)'
1916 hg: parse error: topo.firstbranch can only be used when using the topo sort key
1934 hg: parse error: topo.firstbranch can only be used when using the topo sort key
1917 [255]
1935 [255]
1918
1936
1919 topo.firstbranch should accept any kind of expressions:
1937 topo.firstbranch should accept any kind of expressions:
1920
1938
1921 $ hg log -r 'sort(0, topo, topo.firstbranch=(book1))'
1939 $ hg log -r 'sort(0, topo, topo.firstbranch=(book1))'
1922 0 b12 m111 u112 111 10800
1940 0 b12 m111 u112 111 10800
1923
1941
1924 $ cd ..
1942 $ cd ..
1925 $ cd repo
1943 $ cd repo
1926
1944
1927 test subtracting something from an addset
1945 test subtracting something from an addset
1928
1946
1929 $ log '(outgoing() or removes(a)) - removes(a)'
1947 $ log '(outgoing() or removes(a)) - removes(a)'
1930 8
1948 8
1931 9
1949 9
1932
1950
1933 test intersecting something with an addset
1951 test intersecting something with an addset
1934
1952
1935 $ log 'parents(outgoing() or removes(a))'
1953 $ log 'parents(outgoing() or removes(a))'
1936 1
1954 1
1937 4
1955 4
1938 5
1956 5
1939 8
1957 8
1940
1958
1941 test that `or` operation combines elements in the right order:
1959 test that `or` operation combines elements in the right order:
1942
1960
1943 $ log '3:4 or 2:5'
1961 $ log '3:4 or 2:5'
1944 3
1962 3
1945 4
1963 4
1946 2
1964 2
1947 5
1965 5
1948 $ log '3:4 or 5:2'
1966 $ log '3:4 or 5:2'
1949 3
1967 3
1950 4
1968 4
1951 5
1969 5
1952 2
1970 2
1953 $ log 'sort(3:4 or 2:5)'
1971 $ log 'sort(3:4 or 2:5)'
1954 2
1972 2
1955 3
1973 3
1956 4
1974 4
1957 5
1975 5
1958 $ log 'sort(3:4 or 5:2)'
1976 $ log 'sort(3:4 or 5:2)'
1959 2
1977 2
1960 3
1978 3
1961 4
1979 4
1962 5
1980 5
1963
1981
1964 test that more than one `-r`s are combined in the right order and deduplicated:
1982 test that more than one `-r`s are combined in the right order and deduplicated:
1965
1983
1966 $ hg log -T '{rev}\n' -r 3 -r 3 -r 4 -r 5:2 -r 'ancestors(4)'
1984 $ hg log -T '{rev}\n' -r 3 -r 3 -r 4 -r 5:2 -r 'ancestors(4)'
1967 3
1985 3
1968 4
1986 4
1969 5
1987 5
1970 2
1988 2
1971 0
1989 0
1972 1
1990 1
1973
1991
1974 test that `or` operation skips duplicated revisions from right-hand side
1992 test that `or` operation skips duplicated revisions from right-hand side
1975
1993
1976 $ try 'reverse(1::5) or ancestors(4)'
1994 $ try 'reverse(1::5) or ancestors(4)'
1977 (or
1995 (or
1978 (func
1996 (list
1979 ('symbol', 'reverse')
1997 (func
1980 (dagrange
1998 ('symbol', 'reverse')
1981 ('symbol', '1')
1999 (dagrange
1982 ('symbol', '5')))
2000 ('symbol', '1')
1983 (func
2001 ('symbol', '5')))
1984 ('symbol', 'ancestors')
2002 (func
1985 ('symbol', '4')))
2003 ('symbol', 'ancestors')
2004 ('symbol', '4'))))
1986 * set:
2005 * set:
1987 <addset
2006 <addset
1988 <baseset- [1, 3, 5]>,
2007 <baseset- [1, 3, 5]>,
1989 <generatorset+>>
2008 <generatorset+>>
1990 5
2009 5
1991 3
2010 3
1992 1
2011 1
1993 0
2012 0
1994 2
2013 2
1995 4
2014 4
1996 $ try 'sort(ancestors(4) or reverse(1::5))'
2015 $ try 'sort(ancestors(4) or reverse(1::5))'
1997 (func
2016 (func
1998 ('symbol', 'sort')
2017 ('symbol', 'sort')
1999 (or
2018 (or
2000 (func
2019 (list
2001 ('symbol', 'ancestors')
2020 (func
2002 ('symbol', '4'))
2021 ('symbol', 'ancestors')
2003 (func
2022 ('symbol', '4'))
2004 ('symbol', 'reverse')
2023 (func
2005 (dagrange
2024 ('symbol', 'reverse')
2006 ('symbol', '1')
2025 (dagrange
2007 ('symbol', '5')))))
2026 ('symbol', '1')
2027 ('symbol', '5'))))))
2008 * set:
2028 * set:
2009 <addset+
2029 <addset+
2010 <generatorset+>,
2030 <generatorset+>,
2011 <baseset- [1, 3, 5]>>
2031 <baseset- [1, 3, 5]>>
2012 0
2032 0
2013 1
2033 1
2014 2
2034 2
2015 3
2035 3
2016 4
2036 4
2017 5
2037 5
2018
2038
2019 test optimization of trivial `or` operation
2039 test optimization of trivial `or` operation
2020
2040
2021 $ try --optimize '0|(1)|"2"|-2|tip|null'
2041 $ try --optimize '0|(1)|"2"|-2|tip|null'
2022 (or
2042 (or
2023 ('symbol', '0')
2043 (list
2024 (group
2044 ('symbol', '0')
2025 ('symbol', '1'))
2045 (group
2026 ('string', '2')
2046 ('symbol', '1'))
2027 (negate
2047 ('string', '2')
2028 ('symbol', '2'))
2048 (negate
2029 ('symbol', 'tip')
2049 ('symbol', '2'))
2030 ('symbol', 'null'))
2050 ('symbol', 'tip')
2051 ('symbol', 'null')))
2031 * optimized:
2052 * optimized:
2032 (func
2053 (func
2033 ('symbol', '_list')
2054 ('symbol', '_list')
2034 ('string', '0\x001\x002\x00-2\x00tip\x00null'))
2055 ('string', '0\x001\x002\x00-2\x00tip\x00null'))
2035 * set:
2056 * set:
2036 <baseset [0, 1, 2, 8, 9, -1]>
2057 <baseset [0, 1, 2, 8, 9, -1]>
2037 0
2058 0
2038 1
2059 1
2039 2
2060 2
2040 8
2061 8
2041 9
2062 9
2042 -1
2063 -1
2043
2064
2044 $ try --optimize '0|1|2:3'
2065 $ try --optimize '0|1|2:3'
2045 (or
2066 (or
2046 ('symbol', '0')
2067 (list
2047 ('symbol', '1')
2068 ('symbol', '0')
2048 (range
2069 ('symbol', '1')
2049 ('symbol', '2')
2070 (range
2050 ('symbol', '3')))
2071 ('symbol', '2')
2072 ('symbol', '3'))))
2051 * optimized:
2073 * optimized:
2052 (or
2074 (or
2053 (func
2075 (list
2054 ('symbol', '_list')
2076 (func
2055 ('string', '0\x001'))
2077 ('symbol', '_list')
2056 (range
2078 ('string', '0\x001'))
2057 ('symbol', '2')
2079 (range
2058 ('symbol', '3')))
2080 ('symbol', '2')
2081 ('symbol', '3'))))
2059 * set:
2082 * set:
2060 <addset
2083 <addset
2061 <baseset [0, 1]>,
2084 <baseset [0, 1]>,
2062 <spanset+ 2:3>>
2085 <spanset+ 2:3>>
2063 0
2086 0
2064 1
2087 1
2065 2
2088 2
2066 3
2089 3
2067
2090
2068 $ try --optimize '0:1|2|3:4|5|6'
2091 $ try --optimize '0:1|2|3:4|5|6'
2069 (or
2092 (or
2070 (range
2093 (list
2071 ('symbol', '0')
2094 (range
2072 ('symbol', '1'))
2095 ('symbol', '0')
2073 ('symbol', '2')
2096 ('symbol', '1'))
2074 (range
2097 ('symbol', '2')
2075 ('symbol', '3')
2098 (range
2076 ('symbol', '4'))
2099 ('symbol', '3')
2077 ('symbol', '5')
2100 ('symbol', '4'))
2078 ('symbol', '6'))
2101 ('symbol', '5')
2102 ('symbol', '6')))
2079 * optimized:
2103 * optimized:
2080 (or
2104 (or
2081 (range
2105 (list
2082 ('symbol', '0')
2106 (range
2083 ('symbol', '1'))
2107 ('symbol', '0')
2084 ('symbol', '2')
2108 ('symbol', '1'))
2085 (range
2109 ('symbol', '2')
2086 ('symbol', '3')
2110 (range
2087 ('symbol', '4'))
2111 ('symbol', '3')
2088 (func
2112 ('symbol', '4'))
2089 ('symbol', '_list')
2113 (func
2090 ('string', '5\x006')))
2114 ('symbol', '_list')
2115 ('string', '5\x006'))))
2091 * set:
2116 * set:
2092 <addset
2117 <addset
2093 <addset
2118 <addset
2094 <spanset+ 0:1>,
2119 <spanset+ 0:1>,
2095 <baseset [2]>>,
2120 <baseset [2]>>,
2096 <addset
2121 <addset
2097 <spanset+ 3:4>,
2122 <spanset+ 3:4>,
2098 <baseset [5, 6]>>>
2123 <baseset [5, 6]>>>
2099 0
2124 0
2100 1
2125 1
2101 2
2126 2
2102 3
2127 3
2103 4
2128 4
2104 5
2129 5
2105 6
2130 6
2106
2131
2107 unoptimized `or` looks like this
2132 unoptimized `or` looks like this
2108
2133
2109 $ try --no-optimized -p analyzed '0|1|2|3|4'
2134 $ try --no-optimized -p analyzed '0|1|2|3|4'
2110 * analyzed:
2135 * analyzed:
2111 (or
2136 (or
2112 ('symbol', '0')
2137 (list
2113 ('symbol', '1')
2138 ('symbol', '0')
2114 ('symbol', '2')
2139 ('symbol', '1')
2115 ('symbol', '3')
2140 ('symbol', '2')
2116 ('symbol', '4'))
2141 ('symbol', '3')
2142 ('symbol', '4')))
2117 * set:
2143 * set:
2118 <addset
2144 <addset
2119 <addset
2145 <addset
2120 <baseset [0]>,
2146 <baseset [0]>,
2121 <baseset [1]>>,
2147 <baseset [1]>>,
2122 <addset
2148 <addset
2123 <baseset [2]>,
2149 <baseset [2]>,
2124 <addset
2150 <addset
2125 <baseset [3]>,
2151 <baseset [3]>,
2126 <baseset [4]>>>>
2152 <baseset [4]>>>>
2127 0
2153 0
2128 1
2154 1
2129 2
2155 2
2130 3
2156 3
2131 4
2157 4
2132
2158
2133 test that `_list` should be narrowed by provided `subset`
2159 test that `_list` should be narrowed by provided `subset`
2134
2160
2135 $ log '0:2 and (null|1|2|3)'
2161 $ log '0:2 and (null|1|2|3)'
2136 1
2162 1
2137 2
2163 2
2138
2164
2139 test that `_list` should remove duplicates
2165 test that `_list` should remove duplicates
2140
2166
2141 $ log '0|1|2|1|2|-1|tip'
2167 $ log '0|1|2|1|2|-1|tip'
2142 0
2168 0
2143 1
2169 1
2144 2
2170 2
2145 9
2171 9
2146
2172
2147 test unknown revision in `_list`
2173 test unknown revision in `_list`
2148
2174
2149 $ log '0|unknown'
2175 $ log '0|unknown'
2150 abort: unknown revision 'unknown'!
2176 abort: unknown revision 'unknown'!
2151 [255]
2177 [255]
2152
2178
2153 test integer range in `_list`
2179 test integer range in `_list`
2154
2180
2155 $ log '-1|-10'
2181 $ log '-1|-10'
2156 9
2182 9
2157 0
2183 0
2158
2184
2159 $ log '-10|-11'
2185 $ log '-10|-11'
2160 abort: unknown revision '-11'!
2186 abort: unknown revision '-11'!
2161 [255]
2187 [255]
2162
2188
2163 $ log '9|10'
2189 $ log '9|10'
2164 abort: unknown revision '10'!
2190 abort: unknown revision '10'!
2165 [255]
2191 [255]
2166
2192
2167 test '0000' != '0' in `_list`
2193 test '0000' != '0' in `_list`
2168
2194
2169 $ log '0|0000'
2195 $ log '0|0000'
2170 0
2196 0
2171 -1
2197 -1
2172
2198
2173 test ',' in `_list`
2199 test ',' in `_list`
2174 $ log '0,1'
2200 $ log '0,1'
2175 hg: parse error: can't use a list in this context
2201 hg: parse error: can't use a list in this context
2176 (see hg help "revsets.x or y")
2202 (see hg help "revsets.x or y")
2177 [255]
2203 [255]
2178 $ try '0,1,2'
2204 $ try '0,1,2'
2179 (list
2205 (list
2180 ('symbol', '0')
2206 ('symbol', '0')
2181 ('symbol', '1')
2207 ('symbol', '1')
2182 ('symbol', '2'))
2208 ('symbol', '2'))
2183 hg: parse error: can't use a list in this context
2209 hg: parse error: can't use a list in this context
2184 (see hg help "revsets.x or y")
2210 (see hg help "revsets.x or y")
2185 [255]
2211 [255]
2186
2212
2187 test that chained `or` operations make balanced addsets
2213 test that chained `or` operations make balanced addsets
2188
2214
2189 $ try '0:1|1:2|2:3|3:4|4:5'
2215 $ try '0:1|1:2|2:3|3:4|4:5'
2190 (or
2216 (or
2191 (range
2217 (list
2192 ('symbol', '0')
2218 (range
2193 ('symbol', '1'))
2219 ('symbol', '0')
2194 (range
2220 ('symbol', '1'))
2195 ('symbol', '1')
2221 (range
2196 ('symbol', '2'))
2222 ('symbol', '1')
2197 (range
2223 ('symbol', '2'))
2198 ('symbol', '2')
2224 (range
2199 ('symbol', '3'))
2225 ('symbol', '2')
2200 (range
2226 ('symbol', '3'))
2201 ('symbol', '3')
2227 (range
2202 ('symbol', '4'))
2228 ('symbol', '3')
2203 (range
2229 ('symbol', '4'))
2204 ('symbol', '4')
2230 (range
2205 ('symbol', '5')))
2231 ('symbol', '4')
2232 ('symbol', '5'))))
2206 * set:
2233 * set:
2207 <addset
2234 <addset
2208 <addset
2235 <addset
2209 <spanset+ 0:1>,
2236 <spanset+ 0:1>,
2210 <spanset+ 1:2>>,
2237 <spanset+ 1:2>>,
2211 <addset
2238 <addset
2212 <spanset+ 2:3>,
2239 <spanset+ 2:3>,
2213 <addset
2240 <addset
2214 <spanset+ 3:4>,
2241 <spanset+ 3:4>,
2215 <spanset+ 4:5>>>>
2242 <spanset+ 4:5>>>>
2216 0
2243 0
2217 1
2244 1
2218 2
2245 2
2219 3
2246 3
2220 4
2247 4
2221 5
2248 5
2222
2249
2223 no crash by empty group "()" while optimizing `or` operations
2250 no crash by empty group "()" while optimizing `or` operations
2224
2251
2225 $ try --optimize '0|()'
2252 $ try --optimize '0|()'
2226 (or
2253 (or
2227 ('symbol', '0')
2254 (list
2228 (group
2255 ('symbol', '0')
2229 None))
2256 (group
2257 None)))
2230 * optimized:
2258 * optimized:
2231 (or
2259 (or
2232 ('symbol', '0')
2260 (list
2233 None)
2261 ('symbol', '0')
2262 None))
2234 hg: parse error: missing argument
2263 hg: parse error: missing argument
2235 [255]
2264 [255]
2236
2265
2237 test that chained `or` operations never eat up stack (issue4624)
2266 test that chained `or` operations never eat up stack (issue4624)
2238 (uses `0:1` instead of `0` to avoid future optimization of trivial revisions)
2267 (uses `0:1` instead of `0` to avoid future optimization of trivial revisions)
2239
2268
2240 $ hg log -T '{rev}\n' -r `python -c "print '+'.join(['0:1'] * 500)"`
2269 $ hg log -T '{rev}\n' -r `python -c "print '+'.join(['0:1'] * 500)"`
2241 0
2270 0
2242 1
2271 1
2243
2272
2244 test that repeated `-r` options never eat up stack (issue4565)
2273 test that repeated `-r` options never eat up stack (issue4565)
2245 (uses `-r 0::1` to avoid possible optimization at old-style parser)
2274 (uses `-r 0::1` to avoid possible optimization at old-style parser)
2246
2275
2247 $ hg log -T '{rev}\n' `python -c "for i in xrange(500): print '-r 0::1 ',"`
2276 $ hg log -T '{rev}\n' `python -c "for i in xrange(500): print '-r 0::1 ',"`
2248 0
2277 0
2249 1
2278 1
2250
2279
2251 check that conversion to only works
2280 check that conversion to only works
2252 $ try --optimize '::3 - ::1'
2281 $ try --optimize '::3 - ::1'
2253 (minus
2282 (minus
2254 (dagrangepre
2283 (dagrangepre
2255 ('symbol', '3'))
2284 ('symbol', '3'))
2256 (dagrangepre
2285 (dagrangepre
2257 ('symbol', '1')))
2286 ('symbol', '1')))
2258 * optimized:
2287 * optimized:
2259 (func
2288 (func
2260 ('symbol', 'only')
2289 ('symbol', 'only')
2261 (list
2290 (list
2262 ('symbol', '3')
2291 ('symbol', '3')
2263 ('symbol', '1')))
2292 ('symbol', '1')))
2264 * set:
2293 * set:
2265 <baseset+ [3]>
2294 <baseset+ [3]>
2266 3
2295 3
2267 $ try --optimize 'ancestors(1) - ancestors(3)'
2296 $ try --optimize 'ancestors(1) - ancestors(3)'
2268 (minus
2297 (minus
2269 (func
2298 (func
2270 ('symbol', 'ancestors')
2299 ('symbol', 'ancestors')
2271 ('symbol', '1'))
2300 ('symbol', '1'))
2272 (func
2301 (func
2273 ('symbol', 'ancestors')
2302 ('symbol', 'ancestors')
2274 ('symbol', '3')))
2303 ('symbol', '3')))
2275 * optimized:
2304 * optimized:
2276 (func
2305 (func
2277 ('symbol', 'only')
2306 ('symbol', 'only')
2278 (list
2307 (list
2279 ('symbol', '1')
2308 ('symbol', '1')
2280 ('symbol', '3')))
2309 ('symbol', '3')))
2281 * set:
2310 * set:
2282 <baseset+ []>
2311 <baseset+ []>
2283 $ try --optimize 'not ::2 and ::6'
2312 $ try --optimize 'not ::2 and ::6'
2284 (and
2313 (and
2285 (not
2314 (not
2286 (dagrangepre
2315 (dagrangepre
2287 ('symbol', '2')))
2316 ('symbol', '2')))
2288 (dagrangepre
2317 (dagrangepre
2289 ('symbol', '6')))
2318 ('symbol', '6')))
2290 * optimized:
2319 * optimized:
2291 (func
2320 (func
2292 ('symbol', 'only')
2321 ('symbol', 'only')
2293 (list
2322 (list
2294 ('symbol', '6')
2323 ('symbol', '6')
2295 ('symbol', '2')))
2324 ('symbol', '2')))
2296 * set:
2325 * set:
2297 <baseset+ [3, 4, 5, 6]>
2326 <baseset+ [3, 4, 5, 6]>
2298 3
2327 3
2299 4
2328 4
2300 5
2329 5
2301 6
2330 6
2302 $ try --optimize 'ancestors(6) and not ancestors(4)'
2331 $ try --optimize 'ancestors(6) and not ancestors(4)'
2303 (and
2332 (and
2304 (func
2333 (func
2305 ('symbol', 'ancestors')
2334 ('symbol', 'ancestors')
2306 ('symbol', '6'))
2335 ('symbol', '6'))
2307 (not
2336 (not
2308 (func
2337 (func
2309 ('symbol', 'ancestors')
2338 ('symbol', 'ancestors')
2310 ('symbol', '4'))))
2339 ('symbol', '4'))))
2311 * optimized:
2340 * optimized:
2312 (func
2341 (func
2313 ('symbol', 'only')
2342 ('symbol', 'only')
2314 (list
2343 (list
2315 ('symbol', '6')
2344 ('symbol', '6')
2316 ('symbol', '4')))
2345 ('symbol', '4')))
2317 * set:
2346 * set:
2318 <baseset+ [3, 5, 6]>
2347 <baseset+ [3, 5, 6]>
2319 3
2348 3
2320 5
2349 5
2321 6
2350 6
2322
2351
2323 no crash by empty group "()" while optimizing to "only()"
2352 no crash by empty group "()" while optimizing to "only()"
2324
2353
2325 $ try --optimize '::1 and ()'
2354 $ try --optimize '::1 and ()'
2326 (and
2355 (and
2327 (dagrangepre
2356 (dagrangepre
2328 ('symbol', '1'))
2357 ('symbol', '1'))
2329 (group
2358 (group
2330 None))
2359 None))
2331 * optimized:
2360 * optimized:
2332 (and
2361 (and
2333 None
2362 None
2334 (func
2363 (func
2335 ('symbol', 'ancestors')
2364 ('symbol', 'ancestors')
2336 ('symbol', '1')))
2365 ('symbol', '1')))
2337 hg: parse error: missing argument
2366 hg: parse error: missing argument
2338 [255]
2367 [255]
2339
2368
2340 invalid function call should not be optimized to only()
2369 invalid function call should not be optimized to only()
2341
2370
2342 $ log '"ancestors"(6) and not ancestors(4)'
2371 $ log '"ancestors"(6) and not ancestors(4)'
2343 hg: parse error: not a symbol
2372 hg: parse error: not a symbol
2344 [255]
2373 [255]
2345
2374
2346 $ log 'ancestors(6) and not "ancestors"(4)'
2375 $ log 'ancestors(6) and not "ancestors"(4)'
2347 hg: parse error: not a symbol
2376 hg: parse error: not a symbol
2348 [255]
2377 [255]
2349
2378
2350 we can use patterns when searching for tags
2379 we can use patterns when searching for tags
2351
2380
2352 $ log 'tag("1..*")'
2381 $ log 'tag("1..*")'
2353 abort: tag '1..*' does not exist!
2382 abort: tag '1..*' does not exist!
2354 [255]
2383 [255]
2355 $ log 'tag("re:1..*")'
2384 $ log 'tag("re:1..*")'
2356 6
2385 6
2357 $ log 'tag("re:[0-9].[0-9]")'
2386 $ log 'tag("re:[0-9].[0-9]")'
2358 6
2387 6
2359 $ log 'tag("literal:1.0")'
2388 $ log 'tag("literal:1.0")'
2360 6
2389 6
2361 $ log 'tag("re:0..*")'
2390 $ log 'tag("re:0..*")'
2362
2391
2363 $ log 'tag(unknown)'
2392 $ log 'tag(unknown)'
2364 abort: tag 'unknown' does not exist!
2393 abort: tag 'unknown' does not exist!
2365 [255]
2394 [255]
2366 $ log 'tag("re:unknown")'
2395 $ log 'tag("re:unknown")'
2367 $ log 'present(tag("unknown"))'
2396 $ log 'present(tag("unknown"))'
2368 $ log 'present(tag("re:unknown"))'
2397 $ log 'present(tag("re:unknown"))'
2369 $ log 'branch(unknown)'
2398 $ log 'branch(unknown)'
2370 abort: unknown revision 'unknown'!
2399 abort: unknown revision 'unknown'!
2371 [255]
2400 [255]
2372 $ log 'branch("literal:unknown")'
2401 $ log 'branch("literal:unknown")'
2373 abort: branch 'unknown' does not exist!
2402 abort: branch 'unknown' does not exist!
2374 [255]
2403 [255]
2375 $ log 'branch("re:unknown")'
2404 $ log 'branch("re:unknown")'
2376 $ log 'present(branch("unknown"))'
2405 $ log 'present(branch("unknown"))'
2377 $ log 'present(branch("re:unknown"))'
2406 $ log 'present(branch("re:unknown"))'
2378 $ log 'user(bob)'
2407 $ log 'user(bob)'
2379 2
2408 2
2380
2409
2381 $ log '4::8'
2410 $ log '4::8'
2382 4
2411 4
2383 8
2412 8
2384 $ log '4:8'
2413 $ log '4:8'
2385 4
2414 4
2386 5
2415 5
2387 6
2416 6
2388 7
2417 7
2389 8
2418 8
2390
2419
2391 $ log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
2420 $ log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
2392 4
2421 4
2393 2
2422 2
2394 5
2423 5
2395
2424
2396 $ log 'not 0 and 0:2'
2425 $ log 'not 0 and 0:2'
2397 1
2426 1
2398 2
2427 2
2399 $ log 'not 1 and 0:2'
2428 $ log 'not 1 and 0:2'
2400 0
2429 0
2401 2
2430 2
2402 $ log 'not 2 and 0:2'
2431 $ log 'not 2 and 0:2'
2403 0
2432 0
2404 1
2433 1
2405 $ log '(1 and 2)::'
2434 $ log '(1 and 2)::'
2406 $ log '(1 and 2):'
2435 $ log '(1 and 2):'
2407 $ log '(1 and 2):3'
2436 $ log '(1 and 2):3'
2408 $ log 'sort(head(), -rev)'
2437 $ log 'sort(head(), -rev)'
2409 9
2438 9
2410 7
2439 7
2411 6
2440 6
2412 5
2441 5
2413 4
2442 4
2414 3
2443 3
2415 2
2444 2
2416 1
2445 1
2417 0
2446 0
2418 $ log '4::8 - 8'
2447 $ log '4::8 - 8'
2419 4
2448 4
2420
2449
2421 matching() should preserve the order of the input set:
2450 matching() should preserve the order of the input set:
2422
2451
2423 $ log '(2 or 3 or 1) and matching(1 or 2 or 3)'
2452 $ log '(2 or 3 or 1) and matching(1 or 2 or 3)'
2424 2
2453 2
2425 3
2454 3
2426 1
2455 1
2427
2456
2428 $ log 'named("unknown")'
2457 $ log 'named("unknown")'
2429 abort: namespace 'unknown' does not exist!
2458 abort: namespace 'unknown' does not exist!
2430 [255]
2459 [255]
2431 $ log 'named("re:unknown")'
2460 $ log 'named("re:unknown")'
2432 abort: no namespace exists that match 'unknown'!
2461 abort: no namespace exists that match 'unknown'!
2433 [255]
2462 [255]
2434 $ log 'present(named("unknown"))'
2463 $ log 'present(named("unknown"))'
2435 $ log 'present(named("re:unknown"))'
2464 $ log 'present(named("re:unknown"))'
2436
2465
2437 $ log 'tag()'
2466 $ log 'tag()'
2438 6
2467 6
2439 $ log 'named("tags")'
2468 $ log 'named("tags")'
2440 6
2469 6
2441
2470
2442 issue2437
2471 issue2437
2443
2472
2444 $ log '3 and p1(5)'
2473 $ log '3 and p1(5)'
2445 3
2474 3
2446 $ log '4 and p2(6)'
2475 $ log '4 and p2(6)'
2447 4
2476 4
2448 $ log '1 and parents(:2)'
2477 $ log '1 and parents(:2)'
2449 1
2478 1
2450 $ log '2 and children(1:)'
2479 $ log '2 and children(1:)'
2451 2
2480 2
2452 $ log 'roots(all()) or roots(all())'
2481 $ log 'roots(all()) or roots(all())'
2453 0
2482 0
2454 $ hg debugrevspec 'roots(all()) or roots(all())'
2483 $ hg debugrevspec 'roots(all()) or roots(all())'
2455 0
2484 0
2456 $ log 'heads(branch(Γ©)) or heads(branch(Γ©))'
2485 $ log 'heads(branch(Γ©)) or heads(branch(Γ©))'
2457 9
2486 9
2458 $ log 'ancestors(8) and (heads(branch("-a-b-c-")) or heads(branch(Γ©)))'
2487 $ log 'ancestors(8) and (heads(branch("-a-b-c-")) or heads(branch(Γ©)))'
2459 4
2488 4
2460
2489
2461 issue2654: report a parse error if the revset was not completely parsed
2490 issue2654: report a parse error if the revset was not completely parsed
2462
2491
2463 $ log '1 OR 2'
2492 $ log '1 OR 2'
2464 hg: parse error at 2: invalid token
2493 hg: parse error at 2: invalid token
2465 [255]
2494 [255]
2466
2495
2467 or operator should preserve ordering:
2496 or operator should preserve ordering:
2468 $ log 'reverse(2::4) or tip'
2497 $ log 'reverse(2::4) or tip'
2469 4
2498 4
2470 2
2499 2
2471 9
2500 9
2472
2501
2473 parentrevspec
2502 parentrevspec
2474
2503
2475 $ log 'merge()^0'
2504 $ log 'merge()^0'
2476 6
2505 6
2477 $ log 'merge()^'
2506 $ log 'merge()^'
2478 5
2507 5
2479 $ log 'merge()^1'
2508 $ log 'merge()^1'
2480 5
2509 5
2481 $ log 'merge()^2'
2510 $ log 'merge()^2'
2482 4
2511 4
2483 $ log 'merge()^^'
2512 $ log 'merge()^^'
2484 3
2513 3
2485 $ log 'merge()^1^'
2514 $ log 'merge()^1^'
2486 3
2515 3
2487 $ log 'merge()^^^'
2516 $ log 'merge()^^^'
2488 1
2517 1
2489
2518
2490 $ log 'merge()~0'
2519 $ log 'merge()~0'
2491 6
2520 6
2492 $ log 'merge()~1'
2521 $ log 'merge()~1'
2493 5
2522 5
2494 $ log 'merge()~2'
2523 $ log 'merge()~2'
2495 3
2524 3
2496 $ log 'merge()~2^1'
2525 $ log 'merge()~2^1'
2497 1
2526 1
2498 $ log 'merge()~3'
2527 $ log 'merge()~3'
2499 1
2528 1
2500
2529
2501 $ log '(-3:tip)^'
2530 $ log '(-3:tip)^'
2502 4
2531 4
2503 6
2532 6
2504 8
2533 8
2505
2534
2506 $ log 'tip^foo'
2535 $ log 'tip^foo'
2507 hg: parse error: ^ expects a number 0, 1, or 2
2536 hg: parse error: ^ expects a number 0, 1, or 2
2508 [255]
2537 [255]
2509
2538
2510 Bogus function gets suggestions
2539 Bogus function gets suggestions
2511 $ log 'add()'
2540 $ log 'add()'
2512 hg: parse error: unknown identifier: add
2541 hg: parse error: unknown identifier: add
2513 (did you mean adds?)
2542 (did you mean adds?)
2514 [255]
2543 [255]
2515 $ log 'added()'
2544 $ log 'added()'
2516 hg: parse error: unknown identifier: added
2545 hg: parse error: unknown identifier: added
2517 (did you mean adds?)
2546 (did you mean adds?)
2518 [255]
2547 [255]
2519 $ log 'remo()'
2548 $ log 'remo()'
2520 hg: parse error: unknown identifier: remo
2549 hg: parse error: unknown identifier: remo
2521 (did you mean one of remote, removes?)
2550 (did you mean one of remote, removes?)
2522 [255]
2551 [255]
2523 $ log 'babar()'
2552 $ log 'babar()'
2524 hg: parse error: unknown identifier: babar
2553 hg: parse error: unknown identifier: babar
2525 [255]
2554 [255]
2526
2555
2527 Bogus function with a similar internal name doesn't suggest the internal name
2556 Bogus function with a similar internal name doesn't suggest the internal name
2528 $ log 'matches()'
2557 $ log 'matches()'
2529 hg: parse error: unknown identifier: matches
2558 hg: parse error: unknown identifier: matches
2530 (did you mean matching?)
2559 (did you mean matching?)
2531 [255]
2560 [255]
2532
2561
2533 Undocumented functions aren't suggested as similar either
2562 Undocumented functions aren't suggested as similar either
2534 $ log 'wdir2()'
2563 $ log 'wdir2()'
2535 hg: parse error: unknown identifier: wdir2
2564 hg: parse error: unknown identifier: wdir2
2536 [255]
2565 [255]
2537
2566
2538 multiple revspecs
2567 multiple revspecs
2539
2568
2540 $ hg log -r 'tip~1:tip' -r 'tip~2:tip~1' --template '{rev}\n'
2569 $ hg log -r 'tip~1:tip' -r 'tip~2:tip~1' --template '{rev}\n'
2541 8
2570 8
2542 9
2571 9
2543 4
2572 4
2544 5
2573 5
2545 6
2574 6
2546 7
2575 7
2547
2576
2548 test usage in revpair (with "+")
2577 test usage in revpair (with "+")
2549
2578
2550 (real pair)
2579 (real pair)
2551
2580
2552 $ hg diff -r 'tip^^' -r 'tip'
2581 $ hg diff -r 'tip^^' -r 'tip'
2553 diff -r 2326846efdab -r 24286f4ae135 .hgtags
2582 diff -r 2326846efdab -r 24286f4ae135 .hgtags
2554 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2583 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2555 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2584 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2556 @@ -0,0 +1,1 @@
2585 @@ -0,0 +1,1 @@
2557 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
2586 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
2558 $ hg diff -r 'tip^^::tip'
2587 $ hg diff -r 'tip^^::tip'
2559 diff -r 2326846efdab -r 24286f4ae135 .hgtags
2588 diff -r 2326846efdab -r 24286f4ae135 .hgtags
2560 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2589 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2561 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2590 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2562 @@ -0,0 +1,1 @@
2591 @@ -0,0 +1,1 @@
2563 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
2592 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
2564
2593
2565 (single rev)
2594 (single rev)
2566
2595
2567 $ hg diff -r 'tip^' -r 'tip^'
2596 $ hg diff -r 'tip^' -r 'tip^'
2568 $ hg diff -r 'tip^:tip^'
2597 $ hg diff -r 'tip^:tip^'
2569
2598
2570 (single rev that does not looks like a range)
2599 (single rev that does not looks like a range)
2571
2600
2572 $ hg diff -r 'tip^::tip^ or tip^'
2601 $ hg diff -r 'tip^::tip^ or tip^'
2573 diff -r d5d0dcbdc4d9 .hgtags
2602 diff -r d5d0dcbdc4d9 .hgtags
2574 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2603 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2575 +++ b/.hgtags * (glob)
2604 +++ b/.hgtags * (glob)
2576 @@ -0,0 +1,1 @@
2605 @@ -0,0 +1,1 @@
2577 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
2606 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
2578 $ hg diff -r 'tip^ or tip^'
2607 $ hg diff -r 'tip^ or tip^'
2579 diff -r d5d0dcbdc4d9 .hgtags
2608 diff -r d5d0dcbdc4d9 .hgtags
2580 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2609 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2581 +++ b/.hgtags * (glob)
2610 +++ b/.hgtags * (glob)
2582 @@ -0,0 +1,1 @@
2611 @@ -0,0 +1,1 @@
2583 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
2612 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
2584
2613
2585 (no rev)
2614 (no rev)
2586
2615
2587 $ hg diff -r 'author("babar") or author("celeste")'
2616 $ hg diff -r 'author("babar") or author("celeste")'
2588 abort: empty revision range
2617 abort: empty revision range
2589 [255]
2618 [255]
2590
2619
2591 aliases:
2620 aliases:
2592
2621
2593 $ echo '[revsetalias]' >> .hg/hgrc
2622 $ echo '[revsetalias]' >> .hg/hgrc
2594 $ echo 'm = merge()' >> .hg/hgrc
2623 $ echo 'm = merge()' >> .hg/hgrc
2595 (revset aliases can override builtin revsets)
2624 (revset aliases can override builtin revsets)
2596 $ echo 'p2($1) = p1($1)' >> .hg/hgrc
2625 $ echo 'p2($1) = p1($1)' >> .hg/hgrc
2597 $ echo 'sincem = descendants(m)' >> .hg/hgrc
2626 $ echo 'sincem = descendants(m)' >> .hg/hgrc
2598 $ echo 'd($1) = reverse(sort($1, date))' >> .hg/hgrc
2627 $ echo 'd($1) = reverse(sort($1, date))' >> .hg/hgrc
2599 $ echo 'rs(ARG1, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
2628 $ echo 'rs(ARG1, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
2600 $ echo 'rs4(ARG1, ARGA, ARGB, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
2629 $ echo 'rs4(ARG1, ARGA, ARGB, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
2601
2630
2602 $ try m
2631 $ try m
2603 ('symbol', 'm')
2632 ('symbol', 'm')
2604 * expanded:
2633 * expanded:
2605 (func
2634 (func
2606 ('symbol', 'merge')
2635 ('symbol', 'merge')
2607 None)
2636 None)
2608 * set:
2637 * set:
2609 <filteredset
2638 <filteredset
2610 <fullreposet+ 0:9>,
2639 <fullreposet+ 0:9>,
2611 <merge>>
2640 <merge>>
2612 6
2641 6
2613
2642
2614 $ HGPLAIN=1
2643 $ HGPLAIN=1
2615 $ export HGPLAIN
2644 $ export HGPLAIN
2616 $ try m
2645 $ try m
2617 ('symbol', 'm')
2646 ('symbol', 'm')
2618 abort: unknown revision 'm'!
2647 abort: unknown revision 'm'!
2619 [255]
2648 [255]
2620
2649
2621 $ HGPLAINEXCEPT=revsetalias
2650 $ HGPLAINEXCEPT=revsetalias
2622 $ export HGPLAINEXCEPT
2651 $ export HGPLAINEXCEPT
2623 $ try m
2652 $ try m
2624 ('symbol', 'm')
2653 ('symbol', 'm')
2625 * expanded:
2654 * expanded:
2626 (func
2655 (func
2627 ('symbol', 'merge')
2656 ('symbol', 'merge')
2628 None)
2657 None)
2629 * set:
2658 * set:
2630 <filteredset
2659 <filteredset
2631 <fullreposet+ 0:9>,
2660 <fullreposet+ 0:9>,
2632 <merge>>
2661 <merge>>
2633 6
2662 6
2634
2663
2635 $ unset HGPLAIN
2664 $ unset HGPLAIN
2636 $ unset HGPLAINEXCEPT
2665 $ unset HGPLAINEXCEPT
2637
2666
2638 $ try 'p2(.)'
2667 $ try 'p2(.)'
2639 (func
2668 (func
2640 ('symbol', 'p2')
2669 ('symbol', 'p2')
2641 ('symbol', '.'))
2670 ('symbol', '.'))
2642 * expanded:
2671 * expanded:
2643 (func
2672 (func
2644 ('symbol', 'p1')
2673 ('symbol', 'p1')
2645 ('symbol', '.'))
2674 ('symbol', '.'))
2646 * set:
2675 * set:
2647 <baseset+ [8]>
2676 <baseset+ [8]>
2648 8
2677 8
2649
2678
2650 $ HGPLAIN=1
2679 $ HGPLAIN=1
2651 $ export HGPLAIN
2680 $ export HGPLAIN
2652 $ try 'p2(.)'
2681 $ try 'p2(.)'
2653 (func
2682 (func
2654 ('symbol', 'p2')
2683 ('symbol', 'p2')
2655 ('symbol', '.'))
2684 ('symbol', '.'))
2656 * set:
2685 * set:
2657 <baseset+ []>
2686 <baseset+ []>
2658
2687
2659 $ HGPLAINEXCEPT=revsetalias
2688 $ HGPLAINEXCEPT=revsetalias
2660 $ export HGPLAINEXCEPT
2689 $ export HGPLAINEXCEPT
2661 $ try 'p2(.)'
2690 $ try 'p2(.)'
2662 (func
2691 (func
2663 ('symbol', 'p2')
2692 ('symbol', 'p2')
2664 ('symbol', '.'))
2693 ('symbol', '.'))
2665 * expanded:
2694 * expanded:
2666 (func
2695 (func
2667 ('symbol', 'p1')
2696 ('symbol', 'p1')
2668 ('symbol', '.'))
2697 ('symbol', '.'))
2669 * set:
2698 * set:
2670 <baseset+ [8]>
2699 <baseset+ [8]>
2671 8
2700 8
2672
2701
2673 $ unset HGPLAIN
2702 $ unset HGPLAIN
2674 $ unset HGPLAINEXCEPT
2703 $ unset HGPLAINEXCEPT
2675
2704
2676 test alias recursion
2705 test alias recursion
2677
2706
2678 $ try sincem
2707 $ try sincem
2679 ('symbol', 'sincem')
2708 ('symbol', 'sincem')
2680 * expanded:
2709 * expanded:
2681 (func
2710 (func
2682 ('symbol', 'descendants')
2711 ('symbol', 'descendants')
2683 (func
2712 (func
2684 ('symbol', 'merge')
2713 ('symbol', 'merge')
2685 None))
2714 None))
2686 * set:
2715 * set:
2687 <addset+
2716 <addset+
2688 <filteredset
2717 <filteredset
2689 <fullreposet+ 0:9>,
2718 <fullreposet+ 0:9>,
2690 <merge>>,
2719 <merge>>,
2691 <generatorset+>>
2720 <generatorset+>>
2692 6
2721 6
2693 7
2722 7
2694
2723
2695 test infinite recursion
2724 test infinite recursion
2696
2725
2697 $ echo 'recurse1 = recurse2' >> .hg/hgrc
2726 $ echo 'recurse1 = recurse2' >> .hg/hgrc
2698 $ echo 'recurse2 = recurse1' >> .hg/hgrc
2727 $ echo 'recurse2 = recurse1' >> .hg/hgrc
2699 $ try recurse1
2728 $ try recurse1
2700 ('symbol', 'recurse1')
2729 ('symbol', 'recurse1')
2701 hg: parse error: infinite expansion of revset alias "recurse1" detected
2730 hg: parse error: infinite expansion of revset alias "recurse1" detected
2702 [255]
2731 [255]
2703
2732
2704 $ echo 'level1($1, $2) = $1 or $2' >> .hg/hgrc
2733 $ echo 'level1($1, $2) = $1 or $2' >> .hg/hgrc
2705 $ echo 'level2($1, $2) = level1($2, $1)' >> .hg/hgrc
2734 $ echo 'level2($1, $2) = level1($2, $1)' >> .hg/hgrc
2706 $ try "level2(level1(1, 2), 3)"
2735 $ try "level2(level1(1, 2), 3)"
2707 (func
2736 (func
2708 ('symbol', 'level2')
2737 ('symbol', 'level2')
2709 (list
2738 (list
2710 (func
2739 (func
2711 ('symbol', 'level1')
2740 ('symbol', 'level1')
2712 (list
2741 (list
2713 ('symbol', '1')
2742 ('symbol', '1')
2714 ('symbol', '2')))
2743 ('symbol', '2')))
2715 ('symbol', '3')))
2744 ('symbol', '3')))
2716 * expanded:
2745 * expanded:
2717 (or
2746 (or
2718 ('symbol', '3')
2747 (list
2719 (or
2748 ('symbol', '3')
2720 ('symbol', '1')
2749 (or
2721 ('symbol', '2')))
2750 (list
2751 ('symbol', '1')
2752 ('symbol', '2')))))
2722 * set:
2753 * set:
2723 <addset
2754 <addset
2724 <baseset [3]>,
2755 <baseset [3]>,
2725 <baseset [1, 2]>>
2756 <baseset [1, 2]>>
2726 3
2757 3
2727 1
2758 1
2728 2
2759 2
2729
2760
2730 test nesting and variable passing
2761 test nesting and variable passing
2731
2762
2732 $ echo 'nested($1) = nested2($1)' >> .hg/hgrc
2763 $ echo 'nested($1) = nested2($1)' >> .hg/hgrc
2733 $ echo 'nested2($1) = nested3($1)' >> .hg/hgrc
2764 $ echo 'nested2($1) = nested3($1)' >> .hg/hgrc
2734 $ echo 'nested3($1) = max($1)' >> .hg/hgrc
2765 $ echo 'nested3($1) = max($1)' >> .hg/hgrc
2735 $ try 'nested(2:5)'
2766 $ try 'nested(2:5)'
2736 (func
2767 (func
2737 ('symbol', 'nested')
2768 ('symbol', 'nested')
2738 (range
2769 (range
2739 ('symbol', '2')
2770 ('symbol', '2')
2740 ('symbol', '5')))
2771 ('symbol', '5')))
2741 * expanded:
2772 * expanded:
2742 (func
2773 (func
2743 ('symbol', 'max')
2774 ('symbol', 'max')
2744 (range
2775 (range
2745 ('symbol', '2')
2776 ('symbol', '2')
2746 ('symbol', '5')))
2777 ('symbol', '5')))
2747 * set:
2778 * set:
2748 <baseset
2779 <baseset
2749 <max
2780 <max
2750 <fullreposet+ 0:9>,
2781 <fullreposet+ 0:9>,
2751 <spanset+ 2:5>>>
2782 <spanset+ 2:5>>>
2752 5
2783 5
2753
2784
2754 test chained `or` operations are flattened at parsing phase
2785 test chained `or` operations are flattened at parsing phase
2755
2786
2756 $ echo 'chainedorops($1, $2, $3) = $1|$2|$3' >> .hg/hgrc
2787 $ echo 'chainedorops($1, $2, $3) = $1|$2|$3' >> .hg/hgrc
2757 $ try 'chainedorops(0:1, 1:2, 2:3)'
2788 $ try 'chainedorops(0:1, 1:2, 2:3)'
2758 (func
2789 (func
2759 ('symbol', 'chainedorops')
2790 ('symbol', 'chainedorops')
2760 (list
2791 (list
2761 (range
2792 (range
2762 ('symbol', '0')
2793 ('symbol', '0')
2763 ('symbol', '1'))
2794 ('symbol', '1'))
2764 (range
2795 (range
2765 ('symbol', '1')
2796 ('symbol', '1')
2766 ('symbol', '2'))
2797 ('symbol', '2'))
2767 (range
2798 (range
2768 ('symbol', '2')
2799 ('symbol', '2')
2769 ('symbol', '3'))))
2800 ('symbol', '3'))))
2770 * expanded:
2801 * expanded:
2771 (or
2802 (or
2772 (range
2803 (list
2773 ('symbol', '0')
2804 (range
2774 ('symbol', '1'))
2805 ('symbol', '0')
2775 (range
2806 ('symbol', '1'))
2776 ('symbol', '1')
2807 (range
2777 ('symbol', '2'))
2808 ('symbol', '1')
2778 (range
2809 ('symbol', '2'))
2779 ('symbol', '2')
2810 (range
2780 ('symbol', '3')))
2811 ('symbol', '2')
2812 ('symbol', '3'))))
2781 * set:
2813 * set:
2782 <addset
2814 <addset
2783 <spanset+ 0:1>,
2815 <spanset+ 0:1>,
2784 <addset
2816 <addset
2785 <spanset+ 1:2>,
2817 <spanset+ 1:2>,
2786 <spanset+ 2:3>>>
2818 <spanset+ 2:3>>>
2787 0
2819 0
2788 1
2820 1
2789 2
2821 2
2790 3
2822 3
2791
2823
2792 test variable isolation, variable placeholders are rewritten as string
2824 test variable isolation, variable placeholders are rewritten as string
2793 then parsed and matched again as string. Check they do not leak too
2825 then parsed and matched again as string. Check they do not leak too
2794 far away.
2826 far away.
2795
2827
2796 $ echo 'injectparamasstring = max("$1")' >> .hg/hgrc
2828 $ echo 'injectparamasstring = max("$1")' >> .hg/hgrc
2797 $ echo 'callinjection($1) = descendants(injectparamasstring)' >> .hg/hgrc
2829 $ echo 'callinjection($1) = descendants(injectparamasstring)' >> .hg/hgrc
2798 $ try 'callinjection(2:5)'
2830 $ try 'callinjection(2:5)'
2799 (func
2831 (func
2800 ('symbol', 'callinjection')
2832 ('symbol', 'callinjection')
2801 (range
2833 (range
2802 ('symbol', '2')
2834 ('symbol', '2')
2803 ('symbol', '5')))
2835 ('symbol', '5')))
2804 * expanded:
2836 * expanded:
2805 (func
2837 (func
2806 ('symbol', 'descendants')
2838 ('symbol', 'descendants')
2807 (func
2839 (func
2808 ('symbol', 'max')
2840 ('symbol', 'max')
2809 ('string', '$1')))
2841 ('string', '$1')))
2810 abort: unknown revision '$1'!
2842 abort: unknown revision '$1'!
2811 [255]
2843 [255]
2812
2844
2813 test scope of alias expansion: 'universe' is expanded prior to 'shadowall(0)',
2845 test scope of alias expansion: 'universe' is expanded prior to 'shadowall(0)',
2814 but 'all()' should never be substituded to '0()'.
2846 but 'all()' should never be substituded to '0()'.
2815
2847
2816 $ echo 'universe = all()' >> .hg/hgrc
2848 $ echo 'universe = all()' >> .hg/hgrc
2817 $ echo 'shadowall(all) = all and universe' >> .hg/hgrc
2849 $ echo 'shadowall(all) = all and universe' >> .hg/hgrc
2818 $ try 'shadowall(0)'
2850 $ try 'shadowall(0)'
2819 (func
2851 (func
2820 ('symbol', 'shadowall')
2852 ('symbol', 'shadowall')
2821 ('symbol', '0'))
2853 ('symbol', '0'))
2822 * expanded:
2854 * expanded:
2823 (and
2855 (and
2824 ('symbol', '0')
2856 ('symbol', '0')
2825 (func
2857 (func
2826 ('symbol', 'all')
2858 ('symbol', 'all')
2827 None))
2859 None))
2828 * set:
2860 * set:
2829 <filteredset
2861 <filteredset
2830 <baseset [0]>,
2862 <baseset [0]>,
2831 <spanset+ 0:9>>
2863 <spanset+ 0:9>>
2832 0
2864 0
2833
2865
2834 test unknown reference:
2866 test unknown reference:
2835
2867
2836 $ try "unknownref(0)" --config 'revsetalias.unknownref($1)=$1:$2'
2868 $ try "unknownref(0)" --config 'revsetalias.unknownref($1)=$1:$2'
2837 (func
2869 (func
2838 ('symbol', 'unknownref')
2870 ('symbol', 'unknownref')
2839 ('symbol', '0'))
2871 ('symbol', '0'))
2840 abort: bad definition of revset alias "unknownref": invalid symbol '$2'
2872 abort: bad definition of revset alias "unknownref": invalid symbol '$2'
2841 [255]
2873 [255]
2842
2874
2843 $ hg debugrevspec --debug --config revsetalias.anotherbadone='branch(' "tip"
2875 $ hg debugrevspec --debug --config revsetalias.anotherbadone='branch(' "tip"
2844 ('symbol', 'tip')
2876 ('symbol', 'tip')
2845 warning: bad definition of revset alias "anotherbadone": at 7: not a prefix: end
2877 warning: bad definition of revset alias "anotherbadone": at 7: not a prefix: end
2846 * set:
2878 * set:
2847 <baseset [9]>
2879 <baseset [9]>
2848 9
2880 9
2849
2881
2850 $ try 'tip'
2882 $ try 'tip'
2851 ('symbol', 'tip')
2883 ('symbol', 'tip')
2852 * set:
2884 * set:
2853 <baseset [9]>
2885 <baseset [9]>
2854 9
2886 9
2855
2887
2856 $ hg debugrevspec --debug --config revsetalias.'bad name'='tip' "tip"
2888 $ hg debugrevspec --debug --config revsetalias.'bad name'='tip' "tip"
2857 ('symbol', 'tip')
2889 ('symbol', 'tip')
2858 warning: bad declaration of revset alias "bad name": at 4: invalid token
2890 warning: bad declaration of revset alias "bad name": at 4: invalid token
2859 * set:
2891 * set:
2860 <baseset [9]>
2892 <baseset [9]>
2861 9
2893 9
2862 $ echo 'strictreplacing($1, $10) = $10 or desc("$1")' >> .hg/hgrc
2894 $ echo 'strictreplacing($1, $10) = $10 or desc("$1")' >> .hg/hgrc
2863 $ try 'strictreplacing("foo", tip)'
2895 $ try 'strictreplacing("foo", tip)'
2864 (func
2896 (func
2865 ('symbol', 'strictreplacing')
2897 ('symbol', 'strictreplacing')
2866 (list
2898 (list
2867 ('string', 'foo')
2899 ('string', 'foo')
2868 ('symbol', 'tip')))
2900 ('symbol', 'tip')))
2869 * expanded:
2901 * expanded:
2870 (or
2902 (or
2871 ('symbol', 'tip')
2903 (list
2872 (func
2904 ('symbol', 'tip')
2873 ('symbol', 'desc')
2905 (func
2874 ('string', '$1')))
2906 ('symbol', 'desc')
2907 ('string', '$1'))))
2875 * set:
2908 * set:
2876 <addset
2909 <addset
2877 <baseset [9]>,
2910 <baseset [9]>,
2878 <filteredset
2911 <filteredset
2879 <fullreposet+ 0:9>,
2912 <fullreposet+ 0:9>,
2880 <desc '$1'>>>
2913 <desc '$1'>>>
2881 9
2914 9
2882
2915
2883 $ try 'd(2:5)'
2916 $ try 'd(2:5)'
2884 (func
2917 (func
2885 ('symbol', 'd')
2918 ('symbol', 'd')
2886 (range
2919 (range
2887 ('symbol', '2')
2920 ('symbol', '2')
2888 ('symbol', '5')))
2921 ('symbol', '5')))
2889 * expanded:
2922 * expanded:
2890 (func
2923 (func
2891 ('symbol', 'reverse')
2924 ('symbol', 'reverse')
2892 (func
2925 (func
2893 ('symbol', 'sort')
2926 ('symbol', 'sort')
2894 (list
2927 (list
2895 (range
2928 (range
2896 ('symbol', '2')
2929 ('symbol', '2')
2897 ('symbol', '5'))
2930 ('symbol', '5'))
2898 ('symbol', 'date'))))
2931 ('symbol', 'date'))))
2899 * set:
2932 * set:
2900 <baseset [4, 5, 3, 2]>
2933 <baseset [4, 5, 3, 2]>
2901 4
2934 4
2902 5
2935 5
2903 3
2936 3
2904 2
2937 2
2905 $ try 'rs(2 or 3, date)'
2938 $ try 'rs(2 or 3, date)'
2906 (func
2939 (func
2907 ('symbol', 'rs')
2940 ('symbol', 'rs')
2908 (list
2941 (list
2909 (or
2942 (or
2910 ('symbol', '2')
2943 (list
2911 ('symbol', '3'))
2944 ('symbol', '2')
2945 ('symbol', '3')))
2912 ('symbol', 'date')))
2946 ('symbol', 'date')))
2913 * expanded:
2947 * expanded:
2914 (func
2948 (func
2915 ('symbol', 'reverse')
2949 ('symbol', 'reverse')
2916 (func
2950 (func
2917 ('symbol', 'sort')
2951 ('symbol', 'sort')
2918 (list
2952 (list
2919 (or
2953 (or
2920 ('symbol', '2')
2954 (list
2921 ('symbol', '3'))
2955 ('symbol', '2')
2956 ('symbol', '3')))
2922 ('symbol', 'date'))))
2957 ('symbol', 'date'))))
2923 * set:
2958 * set:
2924 <baseset [3, 2]>
2959 <baseset [3, 2]>
2925 3
2960 3
2926 2
2961 2
2927 $ try 'rs()'
2962 $ try 'rs()'
2928 (func
2963 (func
2929 ('symbol', 'rs')
2964 ('symbol', 'rs')
2930 None)
2965 None)
2931 hg: parse error: invalid number of arguments: 0
2966 hg: parse error: invalid number of arguments: 0
2932 [255]
2967 [255]
2933 $ try 'rs(2)'
2968 $ try 'rs(2)'
2934 (func
2969 (func
2935 ('symbol', 'rs')
2970 ('symbol', 'rs')
2936 ('symbol', '2'))
2971 ('symbol', '2'))
2937 hg: parse error: invalid number of arguments: 1
2972 hg: parse error: invalid number of arguments: 1
2938 [255]
2973 [255]
2939 $ try 'rs(2, data, 7)'
2974 $ try 'rs(2, data, 7)'
2940 (func
2975 (func
2941 ('symbol', 'rs')
2976 ('symbol', 'rs')
2942 (list
2977 (list
2943 ('symbol', '2')
2978 ('symbol', '2')
2944 ('symbol', 'data')
2979 ('symbol', 'data')
2945 ('symbol', '7')))
2980 ('symbol', '7')))
2946 hg: parse error: invalid number of arguments: 3
2981 hg: parse error: invalid number of arguments: 3
2947 [255]
2982 [255]
2948 $ try 'rs4(2 or 3, x, x, date)'
2983 $ try 'rs4(2 or 3, x, x, date)'
2949 (func
2984 (func
2950 ('symbol', 'rs4')
2985 ('symbol', 'rs4')
2951 (list
2986 (list
2952 (or
2987 (or
2953 ('symbol', '2')
2988 (list
2954 ('symbol', '3'))
2989 ('symbol', '2')
2990 ('symbol', '3')))
2955 ('symbol', 'x')
2991 ('symbol', 'x')
2956 ('symbol', 'x')
2992 ('symbol', 'x')
2957 ('symbol', 'date')))
2993 ('symbol', 'date')))
2958 * expanded:
2994 * expanded:
2959 (func
2995 (func
2960 ('symbol', 'reverse')
2996 ('symbol', 'reverse')
2961 (func
2997 (func
2962 ('symbol', 'sort')
2998 ('symbol', 'sort')
2963 (list
2999 (list
2964 (or
3000 (or
2965 ('symbol', '2')
3001 (list
2966 ('symbol', '3'))
3002 ('symbol', '2')
3003 ('symbol', '3')))
2967 ('symbol', 'date'))))
3004 ('symbol', 'date'))))
2968 * set:
3005 * set:
2969 <baseset [3, 2]>
3006 <baseset [3, 2]>
2970 3
3007 3
2971 2
3008 2
2972
3009
2973 issue4553: check that revset aliases override existing hash prefix
3010 issue4553: check that revset aliases override existing hash prefix
2974
3011
2975 $ hg log -qr e
3012 $ hg log -qr e
2976 6:e0cc66ef77e8
3013 6:e0cc66ef77e8
2977
3014
2978 $ hg log -qr e --config revsetalias.e="all()"
3015 $ hg log -qr e --config revsetalias.e="all()"
2979 0:2785f51eece5
3016 0:2785f51eece5
2980 1:d75937da8da0
3017 1:d75937da8da0
2981 2:5ed5505e9f1c
3018 2:5ed5505e9f1c
2982 3:8528aa5637f2
3019 3:8528aa5637f2
2983 4:2326846efdab
3020 4:2326846efdab
2984 5:904fa392b941
3021 5:904fa392b941
2985 6:e0cc66ef77e8
3022 6:e0cc66ef77e8
2986 7:013af1973af4
3023 7:013af1973af4
2987 8:d5d0dcbdc4d9
3024 8:d5d0dcbdc4d9
2988 9:24286f4ae135
3025 9:24286f4ae135
2989
3026
2990 $ hg log -qr e: --config revsetalias.e="0"
3027 $ hg log -qr e: --config revsetalias.e="0"
2991 0:2785f51eece5
3028 0:2785f51eece5
2992 1:d75937da8da0
3029 1:d75937da8da0
2993 2:5ed5505e9f1c
3030 2:5ed5505e9f1c
2994 3:8528aa5637f2
3031 3:8528aa5637f2
2995 4:2326846efdab
3032 4:2326846efdab
2996 5:904fa392b941
3033 5:904fa392b941
2997 6:e0cc66ef77e8
3034 6:e0cc66ef77e8
2998 7:013af1973af4
3035 7:013af1973af4
2999 8:d5d0dcbdc4d9
3036 8:d5d0dcbdc4d9
3000 9:24286f4ae135
3037 9:24286f4ae135
3001
3038
3002 $ hg log -qr :e --config revsetalias.e="9"
3039 $ hg log -qr :e --config revsetalias.e="9"
3003 0:2785f51eece5
3040 0:2785f51eece5
3004 1:d75937da8da0
3041 1:d75937da8da0
3005 2:5ed5505e9f1c
3042 2:5ed5505e9f1c
3006 3:8528aa5637f2
3043 3:8528aa5637f2
3007 4:2326846efdab
3044 4:2326846efdab
3008 5:904fa392b941
3045 5:904fa392b941
3009 6:e0cc66ef77e8
3046 6:e0cc66ef77e8
3010 7:013af1973af4
3047 7:013af1973af4
3011 8:d5d0dcbdc4d9
3048 8:d5d0dcbdc4d9
3012 9:24286f4ae135
3049 9:24286f4ae135
3013
3050
3014 $ hg log -qr e:
3051 $ hg log -qr e:
3015 6:e0cc66ef77e8
3052 6:e0cc66ef77e8
3016 7:013af1973af4
3053 7:013af1973af4
3017 8:d5d0dcbdc4d9
3054 8:d5d0dcbdc4d9
3018 9:24286f4ae135
3055 9:24286f4ae135
3019
3056
3020 $ hg log -qr :e
3057 $ hg log -qr :e
3021 0:2785f51eece5
3058 0:2785f51eece5
3022 1:d75937da8da0
3059 1:d75937da8da0
3023 2:5ed5505e9f1c
3060 2:5ed5505e9f1c
3024 3:8528aa5637f2
3061 3:8528aa5637f2
3025 4:2326846efdab
3062 4:2326846efdab
3026 5:904fa392b941
3063 5:904fa392b941
3027 6:e0cc66ef77e8
3064 6:e0cc66ef77e8
3028
3065
3029 issue2549 - correct optimizations
3066 issue2549 - correct optimizations
3030
3067
3031 $ try 'limit(1 or 2 or 3, 2) and not 2'
3068 $ try 'limit(1 or 2 or 3, 2) and not 2'
3032 (and
3069 (and
3033 (func
3070 (func
3034 ('symbol', 'limit')
3071 ('symbol', 'limit')
3035 (list
3072 (list
3036 (or
3073 (or
3037 ('symbol', '1')
3074 (list
3038 ('symbol', '2')
3075 ('symbol', '1')
3039 ('symbol', '3'))
3076 ('symbol', '2')
3077 ('symbol', '3')))
3040 ('symbol', '2')))
3078 ('symbol', '2')))
3041 (not
3079 (not
3042 ('symbol', '2')))
3080 ('symbol', '2')))
3043 * set:
3081 * set:
3044 <filteredset
3082 <filteredset
3045 <baseset
3083 <baseset
3046 <limit n=2, offset=0,
3084 <limit n=2, offset=0,
3047 <fullreposet+ 0:9>,
3085 <fullreposet+ 0:9>,
3048 <baseset [1, 2, 3]>>>,
3086 <baseset [1, 2, 3]>>>,
3049 <not
3087 <not
3050 <baseset [2]>>>
3088 <baseset [2]>>>
3051 1
3089 1
3052 $ try 'max(1 or 2) and not 2'
3090 $ try 'max(1 or 2) and not 2'
3053 (and
3091 (and
3054 (func
3092 (func
3055 ('symbol', 'max')
3093 ('symbol', 'max')
3056 (or
3094 (or
3057 ('symbol', '1')
3095 (list
3058 ('symbol', '2')))
3096 ('symbol', '1')
3097 ('symbol', '2'))))
3059 (not
3098 (not
3060 ('symbol', '2')))
3099 ('symbol', '2')))
3061 * set:
3100 * set:
3062 <filteredset
3101 <filteredset
3063 <baseset
3102 <baseset
3064 <max
3103 <max
3065 <fullreposet+ 0:9>,
3104 <fullreposet+ 0:9>,
3066 <baseset [1, 2]>>>,
3105 <baseset [1, 2]>>>,
3067 <not
3106 <not
3068 <baseset [2]>>>
3107 <baseset [2]>>>
3069 $ try 'min(1 or 2) and not 1'
3108 $ try 'min(1 or 2) and not 1'
3070 (and
3109 (and
3071 (func
3110 (func
3072 ('symbol', 'min')
3111 ('symbol', 'min')
3073 (or
3112 (or
3074 ('symbol', '1')
3113 (list
3075 ('symbol', '2')))
3114 ('symbol', '1')
3115 ('symbol', '2'))))
3076 (not
3116 (not
3077 ('symbol', '1')))
3117 ('symbol', '1')))
3078 * set:
3118 * set:
3079 <filteredset
3119 <filteredset
3080 <baseset
3120 <baseset
3081 <min
3121 <min
3082 <fullreposet+ 0:9>,
3122 <fullreposet+ 0:9>,
3083 <baseset [1, 2]>>>,
3123 <baseset [1, 2]>>>,
3084 <not
3124 <not
3085 <baseset [1]>>>
3125 <baseset [1]>>>
3086 $ try 'last(1 or 2, 1) and not 2'
3126 $ try 'last(1 or 2, 1) and not 2'
3087 (and
3127 (and
3088 (func
3128 (func
3089 ('symbol', 'last')
3129 ('symbol', 'last')
3090 (list
3130 (list
3091 (or
3131 (or
3092 ('symbol', '1')
3132 (list
3093 ('symbol', '2'))
3133 ('symbol', '1')
3134 ('symbol', '2')))
3094 ('symbol', '1')))
3135 ('symbol', '1')))
3095 (not
3136 (not
3096 ('symbol', '2')))
3137 ('symbol', '2')))
3097 * set:
3138 * set:
3098 <filteredset
3139 <filteredset
3099 <baseset
3140 <baseset
3100 <last n=1,
3141 <last n=1,
3101 <fullreposet+ 0:9>,
3142 <fullreposet+ 0:9>,
3102 <baseset [2, 1]>>>,
3143 <baseset [2, 1]>>>,
3103 <not
3144 <not
3104 <baseset [2]>>>
3145 <baseset [2]>>>
3105
3146
3106 issue4289 - ordering of built-ins
3147 issue4289 - ordering of built-ins
3107 $ hg log -M -q -r 3:2
3148 $ hg log -M -q -r 3:2
3108 3:8528aa5637f2
3149 3:8528aa5637f2
3109 2:5ed5505e9f1c
3150 2:5ed5505e9f1c
3110
3151
3111 test revsets started with 40-chars hash (issue3669)
3152 test revsets started with 40-chars hash (issue3669)
3112
3153
3113 $ ISSUE3669_TIP=`hg tip --template '{node}'`
3154 $ ISSUE3669_TIP=`hg tip --template '{node}'`
3114 $ hg log -r "${ISSUE3669_TIP}" --template '{rev}\n'
3155 $ hg log -r "${ISSUE3669_TIP}" --template '{rev}\n'
3115 9
3156 9
3116 $ hg log -r "${ISSUE3669_TIP}^" --template '{rev}\n'
3157 $ hg log -r "${ISSUE3669_TIP}^" --template '{rev}\n'
3117 8
3158 8
3118
3159
3119 test or-ed indirect predicates (issue3775)
3160 test or-ed indirect predicates (issue3775)
3120
3161
3121 $ log '6 or 6^1' | sort
3162 $ log '6 or 6^1' | sort
3122 5
3163 5
3123 6
3164 6
3124 $ log '6^1 or 6' | sort
3165 $ log '6^1 or 6' | sort
3125 5
3166 5
3126 6
3167 6
3127 $ log '4 or 4~1' | sort
3168 $ log '4 or 4~1' | sort
3128 2
3169 2
3129 4
3170 4
3130 $ log '4~1 or 4' | sort
3171 $ log '4~1 or 4' | sort
3131 2
3172 2
3132 4
3173 4
3133 $ log '(0 or 2):(4 or 6) or 0 or 6' | sort
3174 $ log '(0 or 2):(4 or 6) or 0 or 6' | sort
3134 0
3175 0
3135 1
3176 1
3136 2
3177 2
3137 3
3178 3
3138 4
3179 4
3139 5
3180 5
3140 6
3181 6
3141 $ log '0 or 6 or (0 or 2):(4 or 6)' | sort
3182 $ log '0 or 6 or (0 or 2):(4 or 6)' | sort
3142 0
3183 0
3143 1
3184 1
3144 2
3185 2
3145 3
3186 3
3146 4
3187 4
3147 5
3188 5
3148 6
3189 6
3149
3190
3150 tests for 'remote()' predicate:
3191 tests for 'remote()' predicate:
3151 #. (csets in remote) (id) (remote)
3192 #. (csets in remote) (id) (remote)
3152 1. less than local current branch "default"
3193 1. less than local current branch "default"
3153 2. same with local specified "default"
3194 2. same with local specified "default"
3154 3. more than local specified specified
3195 3. more than local specified specified
3155
3196
3156 $ hg clone --quiet -U . ../remote3
3197 $ hg clone --quiet -U . ../remote3
3157 $ cd ../remote3
3198 $ cd ../remote3
3158 $ hg update -q 7
3199 $ hg update -q 7
3159 $ echo r > r
3200 $ echo r > r
3160 $ hg ci -Aqm 10
3201 $ hg ci -Aqm 10
3161 $ log 'remote()'
3202 $ log 'remote()'
3162 7
3203 7
3163 $ log 'remote("a-b-c-")'
3204 $ log 'remote("a-b-c-")'
3164 2
3205 2
3165 $ cd ../repo
3206 $ cd ../repo
3166 $ log 'remote(".a.b.c.", "../remote3")'
3207 $ log 'remote(".a.b.c.", "../remote3")'
3167
3208
3168 tests for concatenation of strings/symbols by "##"
3209 tests for concatenation of strings/symbols by "##"
3169
3210
3170 $ try "278 ## '5f5' ## 1ee ## 'ce5'"
3211 $ try "278 ## '5f5' ## 1ee ## 'ce5'"
3171 (_concat
3212 (_concat
3172 (_concat
3213 (_concat
3173 (_concat
3214 (_concat
3174 ('symbol', '278')
3215 ('symbol', '278')
3175 ('string', '5f5'))
3216 ('string', '5f5'))
3176 ('symbol', '1ee'))
3217 ('symbol', '1ee'))
3177 ('string', 'ce5'))
3218 ('string', 'ce5'))
3178 * concatenated:
3219 * concatenated:
3179 ('string', '2785f51eece5')
3220 ('string', '2785f51eece5')
3180 * set:
3221 * set:
3181 <baseset [0]>
3222 <baseset [0]>
3182 0
3223 0
3183
3224
3184 $ echo 'cat4($1, $2, $3, $4) = $1 ## $2 ## $3 ## $4' >> .hg/hgrc
3225 $ echo 'cat4($1, $2, $3, $4) = $1 ## $2 ## $3 ## $4' >> .hg/hgrc
3185 $ try "cat4(278, '5f5', 1ee, 'ce5')"
3226 $ try "cat4(278, '5f5', 1ee, 'ce5')"
3186 (func
3227 (func
3187 ('symbol', 'cat4')
3228 ('symbol', 'cat4')
3188 (list
3229 (list
3189 ('symbol', '278')
3230 ('symbol', '278')
3190 ('string', '5f5')
3231 ('string', '5f5')
3191 ('symbol', '1ee')
3232 ('symbol', '1ee')
3192 ('string', 'ce5')))
3233 ('string', 'ce5')))
3193 * expanded:
3234 * expanded:
3194 (_concat
3235 (_concat
3195 (_concat
3236 (_concat
3196 (_concat
3237 (_concat
3197 ('symbol', '278')
3238 ('symbol', '278')
3198 ('string', '5f5'))
3239 ('string', '5f5'))
3199 ('symbol', '1ee'))
3240 ('symbol', '1ee'))
3200 ('string', 'ce5'))
3241 ('string', 'ce5'))
3201 * concatenated:
3242 * concatenated:
3202 ('string', '2785f51eece5')
3243 ('string', '2785f51eece5')
3203 * set:
3244 * set:
3204 <baseset [0]>
3245 <baseset [0]>
3205 0
3246 0
3206
3247
3207 (check concatenation in alias nesting)
3248 (check concatenation in alias nesting)
3208
3249
3209 $ echo 'cat2($1, $2) = $1 ## $2' >> .hg/hgrc
3250 $ echo 'cat2($1, $2) = $1 ## $2' >> .hg/hgrc
3210 $ echo 'cat2x2($1, $2, $3, $4) = cat2($1 ## $2, $3 ## $4)' >> .hg/hgrc
3251 $ echo 'cat2x2($1, $2, $3, $4) = cat2($1 ## $2, $3 ## $4)' >> .hg/hgrc
3211 $ log "cat2x2(278, '5f5', 1ee, 'ce5')"
3252 $ log "cat2x2(278, '5f5', 1ee, 'ce5')"
3212 0
3253 0
3213
3254
3214 (check operator priority)
3255 (check operator priority)
3215
3256
3216 $ echo 'cat2n2($1, $2, $3, $4) = $1 ## $2 or $3 ## $4~2' >> .hg/hgrc
3257 $ echo 'cat2n2($1, $2, $3, $4) = $1 ## $2 or $3 ## $4~2' >> .hg/hgrc
3217 $ log "cat2n2(2785f5, 1eece5, 24286f, 4ae135)"
3258 $ log "cat2n2(2785f5, 1eece5, 24286f, 4ae135)"
3218 0
3259 0
3219 4
3260 4
3220
3261
3221 $ cd ..
3262 $ cd ..
3222
3263
3223 prepare repository that has "default" branches of multiple roots
3264 prepare repository that has "default" branches of multiple roots
3224
3265
3225 $ hg init namedbranch
3266 $ hg init namedbranch
3226 $ cd namedbranch
3267 $ cd namedbranch
3227
3268
3228 $ echo default0 >> a
3269 $ echo default0 >> a
3229 $ hg ci -Aqm0
3270 $ hg ci -Aqm0
3230 $ echo default1 >> a
3271 $ echo default1 >> a
3231 $ hg ci -m1
3272 $ hg ci -m1
3232
3273
3233 $ hg branch -q stable
3274 $ hg branch -q stable
3234 $ echo stable2 >> a
3275 $ echo stable2 >> a
3235 $ hg ci -m2
3276 $ hg ci -m2
3236 $ echo stable3 >> a
3277 $ echo stable3 >> a
3237 $ hg ci -m3
3278 $ hg ci -m3
3238
3279
3239 $ hg update -q null
3280 $ hg update -q null
3240 $ echo default4 >> a
3281 $ echo default4 >> a
3241 $ hg ci -Aqm4
3282 $ hg ci -Aqm4
3242 $ echo default5 >> a
3283 $ echo default5 >> a
3243 $ hg ci -m5
3284 $ hg ci -m5
3244
3285
3245 "null" revision belongs to "default" branch (issue4683)
3286 "null" revision belongs to "default" branch (issue4683)
3246
3287
3247 $ log 'branch(null)'
3288 $ log 'branch(null)'
3248 0
3289 0
3249 1
3290 1
3250 4
3291 4
3251 5
3292 5
3252
3293
3253 "null" revision belongs to "default" branch, but it shouldn't appear in set
3294 "null" revision belongs to "default" branch, but it shouldn't appear in set
3254 unless explicitly specified (issue4682)
3295 unless explicitly specified (issue4682)
3255
3296
3256 $ log 'children(branch(default))'
3297 $ log 'children(branch(default))'
3257 1
3298 1
3258 2
3299 2
3259 5
3300 5
3260
3301
3261 $ cd ..
3302 $ cd ..
3262
3303
3263 test author/desc/keyword in problematic encoding
3304 test author/desc/keyword in problematic encoding
3264 # unicode: cp932:
3305 # unicode: cp932:
3265 # u30A2 0x83 0x41(= 'A')
3306 # u30A2 0x83 0x41(= 'A')
3266 # u30C2 0x83 0x61(= 'a')
3307 # u30C2 0x83 0x61(= 'a')
3267
3308
3268 $ hg init problematicencoding
3309 $ hg init problematicencoding
3269 $ cd problematicencoding
3310 $ cd problematicencoding
3270
3311
3271 $ python > setup.sh <<EOF
3312 $ python > setup.sh <<EOF
3272 > print u'''
3313 > print u'''
3273 > echo a > text
3314 > echo a > text
3274 > hg add text
3315 > hg add text
3275 > hg --encoding utf-8 commit -u '\u30A2' -m none
3316 > hg --encoding utf-8 commit -u '\u30A2' -m none
3276 > echo b > text
3317 > echo b > text
3277 > hg --encoding utf-8 commit -u '\u30C2' -m none
3318 > hg --encoding utf-8 commit -u '\u30C2' -m none
3278 > echo c > text
3319 > echo c > text
3279 > hg --encoding utf-8 commit -u none -m '\u30A2'
3320 > hg --encoding utf-8 commit -u none -m '\u30A2'
3280 > echo d > text
3321 > echo d > text
3281 > hg --encoding utf-8 commit -u none -m '\u30C2'
3322 > hg --encoding utf-8 commit -u none -m '\u30C2'
3282 > '''.encode('utf-8')
3323 > '''.encode('utf-8')
3283 > EOF
3324 > EOF
3284 $ sh < setup.sh
3325 $ sh < setup.sh
3285
3326
3286 test in problematic encoding
3327 test in problematic encoding
3287 $ python > test.sh <<EOF
3328 $ python > test.sh <<EOF
3288 > print u'''
3329 > print u'''
3289 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30A2)'
3330 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30A2)'
3290 > echo ====
3331 > echo ====
3291 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30C2)'
3332 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30C2)'
3292 > echo ====
3333 > echo ====
3293 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30A2)'
3334 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30A2)'
3294 > echo ====
3335 > echo ====
3295 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30C2)'
3336 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30C2)'
3296 > echo ====
3337 > echo ====
3297 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30A2)'
3338 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30A2)'
3298 > echo ====
3339 > echo ====
3299 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30C2)'
3340 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30C2)'
3300 > '''.encode('cp932')
3341 > '''.encode('cp932')
3301 > EOF
3342 > EOF
3302 $ sh < test.sh
3343 $ sh < test.sh
3303 0
3344 0
3304 ====
3345 ====
3305 1
3346 1
3306 ====
3347 ====
3307 2
3348 2
3308 ====
3349 ====
3309 3
3350 3
3310 ====
3351 ====
3311 0
3352 0
3312 2
3353 2
3313 ====
3354 ====
3314 1
3355 1
3315 3
3356 3
3316
3357
3317 test error message of bad revset
3358 test error message of bad revset
3318 $ hg log -r 'foo\\'
3359 $ hg log -r 'foo\\'
3319 hg: parse error at 3: syntax error in revset 'foo\\'
3360 hg: parse error at 3: syntax error in revset 'foo\\'
3320 [255]
3361 [255]
3321
3362
3322 $ cd ..
3363 $ cd ..
3323
3364
3324 Test that revset predicate of extension isn't loaded at failure of
3365 Test that revset predicate of extension isn't loaded at failure of
3325 loading it
3366 loading it
3326
3367
3327 $ cd repo
3368 $ cd repo
3328
3369
3329 $ cat <<EOF > $TESTTMP/custompredicate.py
3370 $ cat <<EOF > $TESTTMP/custompredicate.py
3330 > from mercurial import error, registrar, revset
3371 > from mercurial import error, registrar, revset
3331 >
3372 >
3332 > revsetpredicate = registrar.revsetpredicate()
3373 > revsetpredicate = registrar.revsetpredicate()
3333 >
3374 >
3334 > @revsetpredicate('custom1()')
3375 > @revsetpredicate('custom1()')
3335 > def custom1(repo, subset, x):
3376 > def custom1(repo, subset, x):
3336 > return revset.baseset([1])
3377 > return revset.baseset([1])
3337 >
3378 >
3338 > raise error.Abort('intentional failure of loading extension')
3379 > raise error.Abort('intentional failure of loading extension')
3339 > EOF
3380 > EOF
3340 $ cat <<EOF > .hg/hgrc
3381 $ cat <<EOF > .hg/hgrc
3341 > [extensions]
3382 > [extensions]
3342 > custompredicate = $TESTTMP/custompredicate.py
3383 > custompredicate = $TESTTMP/custompredicate.py
3343 > EOF
3384 > EOF
3344
3385
3345 $ hg debugrevspec "custom1()"
3386 $ hg debugrevspec "custom1()"
3346 *** failed to import extension custompredicate from $TESTTMP/custompredicate.py: intentional failure of loading extension
3387 *** failed to import extension custompredicate from $TESTTMP/custompredicate.py: intentional failure of loading extension
3347 hg: parse error: unknown identifier: custom1
3388 hg: parse error: unknown identifier: custom1
3348 [255]
3389 [255]
3349
3390
3350 $ cd ..
3391 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now