##// END OF EJS Templates
revset: have all() filter out null revision...
Yuya Nishihara -
r24202:2de9ee01 default
parent child Browse files
Show More
@@ -1,3340 +1,3340 b''
1 # revset.py - revision set queries for mercurial
1 # revset.py - revision set queries for mercurial
2 #
2 #
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import re
8 import re
9 import parser, util, error, discovery, hbisect, phases
9 import parser, util, error, discovery, hbisect, phases
10 import node
10 import node
11 import heapq
11 import heapq
12 import match as matchmod
12 import match as matchmod
13 from i18n import _
13 from i18n import _
14 import encoding
14 import encoding
15 import obsolete as obsmod
15 import obsolete as obsmod
16 import pathutil
16 import pathutil
17 import repoview
17 import repoview
18
18
19 def _revancestors(repo, revs, followfirst):
19 def _revancestors(repo, revs, followfirst):
20 """Like revlog.ancestors(), but supports followfirst."""
20 """Like revlog.ancestors(), but supports followfirst."""
21 cut = followfirst and 1 or None
21 cut = followfirst and 1 or None
22 cl = repo.changelog
22 cl = repo.changelog
23
23
24 def iterate():
24 def iterate():
25 revqueue, revsnode = None, None
25 revqueue, revsnode = None, None
26 h = []
26 h = []
27
27
28 revs.sort(reverse=True)
28 revs.sort(reverse=True)
29 revqueue = util.deque(revs)
29 revqueue = util.deque(revs)
30 if revqueue:
30 if revqueue:
31 revsnode = revqueue.popleft()
31 revsnode = revqueue.popleft()
32 heapq.heappush(h, -revsnode)
32 heapq.heappush(h, -revsnode)
33
33
34 seen = set()
34 seen = set()
35 while h:
35 while h:
36 current = -heapq.heappop(h)
36 current = -heapq.heappop(h)
37 if current not in seen:
37 if current not in seen:
38 if revsnode and current == revsnode:
38 if revsnode and current == revsnode:
39 if revqueue:
39 if revqueue:
40 revsnode = revqueue.popleft()
40 revsnode = revqueue.popleft()
41 heapq.heappush(h, -revsnode)
41 heapq.heappush(h, -revsnode)
42 seen.add(current)
42 seen.add(current)
43 yield current
43 yield current
44 for parent in cl.parentrevs(current)[:cut]:
44 for parent in cl.parentrevs(current)[:cut]:
45 if parent != node.nullrev:
45 if parent != node.nullrev:
46 heapq.heappush(h, -parent)
46 heapq.heappush(h, -parent)
47
47
48 return generatorset(iterate(), iterasc=False)
48 return generatorset(iterate(), iterasc=False)
49
49
50 def _revdescendants(repo, revs, followfirst):
50 def _revdescendants(repo, revs, followfirst):
51 """Like revlog.descendants() but supports followfirst."""
51 """Like revlog.descendants() but supports followfirst."""
52 cut = followfirst and 1 or None
52 cut = followfirst and 1 or None
53
53
54 def iterate():
54 def iterate():
55 cl = repo.changelog
55 cl = repo.changelog
56 first = min(revs)
56 first = min(revs)
57 nullrev = node.nullrev
57 nullrev = node.nullrev
58 if first == nullrev:
58 if first == nullrev:
59 # Are there nodes with a null first parent and a non-null
59 # Are there nodes with a null first parent and a non-null
60 # second one? Maybe. Do we care? Probably not.
60 # second one? Maybe. Do we care? Probably not.
61 for i in cl:
61 for i in cl:
62 yield i
62 yield i
63 else:
63 else:
64 seen = set(revs)
64 seen = set(revs)
65 for i in cl.revs(first + 1):
65 for i in cl.revs(first + 1):
66 for x in cl.parentrevs(i)[:cut]:
66 for x in cl.parentrevs(i)[:cut]:
67 if x != nullrev and x in seen:
67 if x != nullrev and x in seen:
68 seen.add(i)
68 seen.add(i)
69 yield i
69 yield i
70 break
70 break
71
71
72 return generatorset(iterate(), iterasc=True)
72 return generatorset(iterate(), iterasc=True)
73
73
74 def _revsbetween(repo, roots, heads):
74 def _revsbetween(repo, roots, heads):
75 """Return all paths between roots and heads, inclusive of both endpoint
75 """Return all paths between roots and heads, inclusive of both endpoint
76 sets."""
76 sets."""
77 if not roots:
77 if not roots:
78 return baseset()
78 return baseset()
79 parentrevs = repo.changelog.parentrevs
79 parentrevs = repo.changelog.parentrevs
80 visit = list(heads)
80 visit = list(heads)
81 reachable = set()
81 reachable = set()
82 seen = {}
82 seen = {}
83 minroot = min(roots)
83 minroot = min(roots)
84 roots = set(roots)
84 roots = set(roots)
85 # open-code the post-order traversal due to the tiny size of
85 # open-code the post-order traversal due to the tiny size of
86 # sys.getrecursionlimit()
86 # sys.getrecursionlimit()
87 while visit:
87 while visit:
88 rev = visit.pop()
88 rev = visit.pop()
89 if rev in roots:
89 if rev in roots:
90 reachable.add(rev)
90 reachable.add(rev)
91 parents = parentrevs(rev)
91 parents = parentrevs(rev)
92 seen[rev] = parents
92 seen[rev] = parents
93 for parent in parents:
93 for parent in parents:
94 if parent >= minroot and parent not in seen:
94 if parent >= minroot and parent not in seen:
95 visit.append(parent)
95 visit.append(parent)
96 if not reachable:
96 if not reachable:
97 return baseset()
97 return baseset()
98 for rev in sorted(seen):
98 for rev in sorted(seen):
99 for parent in seen[rev]:
99 for parent in seen[rev]:
100 if parent in reachable:
100 if parent in reachable:
101 reachable.add(rev)
101 reachable.add(rev)
102 return baseset(sorted(reachable))
102 return baseset(sorted(reachable))
103
103
104 elements = {
104 elements = {
105 "(": (21, ("group", 1, ")"), ("func", 1, ")")),
105 "(": (21, ("group", 1, ")"), ("func", 1, ")")),
106 "##": (20, None, ("_concat", 20)),
106 "##": (20, None, ("_concat", 20)),
107 "~": (18, None, ("ancestor", 18)),
107 "~": (18, None, ("ancestor", 18)),
108 "^": (18, None, ("parent", 18), ("parentpost", 18)),
108 "^": (18, None, ("parent", 18), ("parentpost", 18)),
109 "-": (5, ("negate", 19), ("minus", 5)),
109 "-": (5, ("negate", 19), ("minus", 5)),
110 "::": (17, ("dagrangepre", 17), ("dagrange", 17),
110 "::": (17, ("dagrangepre", 17), ("dagrange", 17),
111 ("dagrangepost", 17)),
111 ("dagrangepost", 17)),
112 "..": (17, ("dagrangepre", 17), ("dagrange", 17),
112 "..": (17, ("dagrangepre", 17), ("dagrange", 17),
113 ("dagrangepost", 17)),
113 ("dagrangepost", 17)),
114 ":": (15, ("rangepre", 15), ("range", 15), ("rangepost", 15)),
114 ":": (15, ("rangepre", 15), ("range", 15), ("rangepost", 15)),
115 "not": (10, ("not", 10)),
115 "not": (10, ("not", 10)),
116 "!": (10, ("not", 10)),
116 "!": (10, ("not", 10)),
117 "and": (5, None, ("and", 5)),
117 "and": (5, None, ("and", 5)),
118 "&": (5, None, ("and", 5)),
118 "&": (5, None, ("and", 5)),
119 "%": (5, None, ("only", 5), ("onlypost", 5)),
119 "%": (5, None, ("only", 5), ("onlypost", 5)),
120 "or": (4, None, ("or", 4)),
120 "or": (4, None, ("or", 4)),
121 "|": (4, None, ("or", 4)),
121 "|": (4, None, ("or", 4)),
122 "+": (4, None, ("or", 4)),
122 "+": (4, None, ("or", 4)),
123 ",": (2, None, ("list", 2)),
123 ",": (2, None, ("list", 2)),
124 ")": (0, None, None),
124 ")": (0, None, None),
125 "symbol": (0, ("symbol",), None),
125 "symbol": (0, ("symbol",), None),
126 "string": (0, ("string",), None),
126 "string": (0, ("string",), None),
127 "end": (0, None, None),
127 "end": (0, None, None),
128 }
128 }
129
129
130 keywords = set(['and', 'or', 'not'])
130 keywords = set(['and', 'or', 'not'])
131
131
132 # default set of valid characters for the initial letter of symbols
132 # default set of valid characters for the initial letter of symbols
133 _syminitletters = set(c for c in [chr(i) for i in xrange(256)]
133 _syminitletters = set(c for c in [chr(i) for i in xrange(256)]
134 if c.isalnum() or c in '._@' or ord(c) > 127)
134 if c.isalnum() or c in '._@' or ord(c) > 127)
135
135
136 # default set of valid characters for non-initial letters of symbols
136 # default set of valid characters for non-initial letters of symbols
137 _symletters = set(c for c in [chr(i) for i in xrange(256)]
137 _symletters = set(c for c in [chr(i) for i in xrange(256)]
138 if c.isalnum() or c in '-._/@' or ord(c) > 127)
138 if c.isalnum() or c in '-._/@' or ord(c) > 127)
139
139
140 def tokenize(program, lookup=None, syminitletters=None, symletters=None):
140 def tokenize(program, lookup=None, syminitletters=None, symletters=None):
141 '''
141 '''
142 Parse a revset statement into a stream of tokens
142 Parse a revset statement into a stream of tokens
143
143
144 ``syminitletters`` is the set of valid characters for the initial
144 ``syminitletters`` is the set of valid characters for the initial
145 letter of symbols.
145 letter of symbols.
146
146
147 By default, character ``c`` is recognized as valid for initial
147 By default, character ``c`` is recognized as valid for initial
148 letter of symbols, if ``c.isalnum() or c in '._@' or ord(c) > 127``.
148 letter of symbols, if ``c.isalnum() or c in '._@' or ord(c) > 127``.
149
149
150 ``symletters`` is the set of valid characters for non-initial
150 ``symletters`` is the set of valid characters for non-initial
151 letters of symbols.
151 letters of symbols.
152
152
153 By default, character ``c`` is recognized as valid for non-initial
153 By default, character ``c`` is recognized as valid for non-initial
154 letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``.
154 letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``.
155
155
156 Check that @ is a valid unquoted token character (issue3686):
156 Check that @ is a valid unquoted token character (issue3686):
157 >>> list(tokenize("@::"))
157 >>> list(tokenize("@::"))
158 [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)]
158 [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)]
159
159
160 '''
160 '''
161 if syminitletters is None:
161 if syminitletters is None:
162 syminitletters = _syminitletters
162 syminitletters = _syminitletters
163 if symletters is None:
163 if symletters is None:
164 symletters = _symletters
164 symletters = _symletters
165
165
166 pos, l = 0, len(program)
166 pos, l = 0, len(program)
167 while pos < l:
167 while pos < l:
168 c = program[pos]
168 c = program[pos]
169 if c.isspace(): # skip inter-token whitespace
169 if c.isspace(): # skip inter-token whitespace
170 pass
170 pass
171 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
171 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
172 yield ('::', None, pos)
172 yield ('::', None, pos)
173 pos += 1 # skip ahead
173 pos += 1 # skip ahead
174 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
174 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
175 yield ('..', None, pos)
175 yield ('..', None, pos)
176 pos += 1 # skip ahead
176 pos += 1 # skip ahead
177 elif c == '#' and program[pos:pos + 2] == '##': # look ahead carefully
177 elif c == '#' and program[pos:pos + 2] == '##': # look ahead carefully
178 yield ('##', None, pos)
178 yield ('##', None, pos)
179 pos += 1 # skip ahead
179 pos += 1 # skip ahead
180 elif c in "():,-|&+!~^%": # handle simple operators
180 elif c in "():,-|&+!~^%": # handle simple operators
181 yield (c, None, pos)
181 yield (c, None, pos)
182 elif (c in '"\'' or c == 'r' and
182 elif (c in '"\'' or c == 'r' and
183 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
183 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
184 if c == 'r':
184 if c == 'r':
185 pos += 1
185 pos += 1
186 c = program[pos]
186 c = program[pos]
187 decode = lambda x: x
187 decode = lambda x: x
188 else:
188 else:
189 decode = lambda x: x.decode('string-escape')
189 decode = lambda x: x.decode('string-escape')
190 pos += 1
190 pos += 1
191 s = pos
191 s = pos
192 while pos < l: # find closing quote
192 while pos < l: # find closing quote
193 d = program[pos]
193 d = program[pos]
194 if d == '\\': # skip over escaped characters
194 if d == '\\': # skip over escaped characters
195 pos += 2
195 pos += 2
196 continue
196 continue
197 if d == c:
197 if d == c:
198 yield ('string', decode(program[s:pos]), s)
198 yield ('string', decode(program[s:pos]), s)
199 break
199 break
200 pos += 1
200 pos += 1
201 else:
201 else:
202 raise error.ParseError(_("unterminated string"), s)
202 raise error.ParseError(_("unterminated string"), s)
203 # gather up a symbol/keyword
203 # gather up a symbol/keyword
204 elif c in syminitletters:
204 elif c in syminitletters:
205 s = pos
205 s = pos
206 pos += 1
206 pos += 1
207 while pos < l: # find end of symbol
207 while pos < l: # find end of symbol
208 d = program[pos]
208 d = program[pos]
209 if d not in symletters:
209 if d not in symletters:
210 break
210 break
211 if d == '.' and program[pos - 1] == '.': # special case for ..
211 if d == '.' and program[pos - 1] == '.': # special case for ..
212 pos -= 1
212 pos -= 1
213 break
213 break
214 pos += 1
214 pos += 1
215 sym = program[s:pos]
215 sym = program[s:pos]
216 if sym in keywords: # operator keywords
216 if sym in keywords: # operator keywords
217 yield (sym, None, s)
217 yield (sym, None, s)
218 elif '-' in sym:
218 elif '-' in sym:
219 # some jerk gave us foo-bar-baz, try to check if it's a symbol
219 # some jerk gave us foo-bar-baz, try to check if it's a symbol
220 if lookup and lookup(sym):
220 if lookup and lookup(sym):
221 # looks like a real symbol
221 # looks like a real symbol
222 yield ('symbol', sym, s)
222 yield ('symbol', sym, s)
223 else:
223 else:
224 # looks like an expression
224 # looks like an expression
225 parts = sym.split('-')
225 parts = sym.split('-')
226 for p in parts[:-1]:
226 for p in parts[:-1]:
227 if p: # possible consecutive -
227 if p: # possible consecutive -
228 yield ('symbol', p, s)
228 yield ('symbol', p, s)
229 s += len(p)
229 s += len(p)
230 yield ('-', None, pos)
230 yield ('-', None, pos)
231 s += 1
231 s += 1
232 if parts[-1]: # possible trailing -
232 if parts[-1]: # possible trailing -
233 yield ('symbol', parts[-1], s)
233 yield ('symbol', parts[-1], s)
234 else:
234 else:
235 yield ('symbol', sym, s)
235 yield ('symbol', sym, s)
236 pos -= 1
236 pos -= 1
237 else:
237 else:
238 raise error.ParseError(_("syntax error"), pos)
238 raise error.ParseError(_("syntax error"), pos)
239 pos += 1
239 pos += 1
240 yield ('end', None, pos)
240 yield ('end', None, pos)
241
241
242 def parseerrordetail(inst):
242 def parseerrordetail(inst):
243 """Compose error message from specified ParseError object
243 """Compose error message from specified ParseError object
244 """
244 """
245 if len(inst.args) > 1:
245 if len(inst.args) > 1:
246 return _('at %s: %s') % (inst.args[1], inst.args[0])
246 return _('at %s: %s') % (inst.args[1], inst.args[0])
247 else:
247 else:
248 return inst.args[0]
248 return inst.args[0]
249
249
250 # helpers
250 # helpers
251
251
252 def getstring(x, err):
252 def getstring(x, err):
253 if x and (x[0] == 'string' or x[0] == 'symbol'):
253 if x and (x[0] == 'string' or x[0] == 'symbol'):
254 return x[1]
254 return x[1]
255 raise error.ParseError(err)
255 raise error.ParseError(err)
256
256
257 def getlist(x):
257 def getlist(x):
258 if not x:
258 if not x:
259 return []
259 return []
260 if x[0] == 'list':
260 if x[0] == 'list':
261 return getlist(x[1]) + [x[2]]
261 return getlist(x[1]) + [x[2]]
262 return [x]
262 return [x]
263
263
264 def getargs(x, min, max, err):
264 def getargs(x, min, max, err):
265 l = getlist(x)
265 l = getlist(x)
266 if len(l) < min or (max >= 0 and len(l) > max):
266 if len(l) < min or (max >= 0 and len(l) > max):
267 raise error.ParseError(err)
267 raise error.ParseError(err)
268 return l
268 return l
269
269
270 def isvalidsymbol(tree):
270 def isvalidsymbol(tree):
271 """Examine whether specified ``tree`` is valid ``symbol`` or not
271 """Examine whether specified ``tree`` is valid ``symbol`` or not
272 """
272 """
273 return tree[0] == 'symbol' and len(tree) > 1
273 return tree[0] == 'symbol' and len(tree) > 1
274
274
275 def getsymbol(tree):
275 def getsymbol(tree):
276 """Get symbol name from valid ``symbol`` in ``tree``
276 """Get symbol name from valid ``symbol`` in ``tree``
277
277
278 This assumes that ``tree`` is already examined by ``isvalidsymbol``.
278 This assumes that ``tree`` is already examined by ``isvalidsymbol``.
279 """
279 """
280 return tree[1]
280 return tree[1]
281
281
282 def isvalidfunc(tree):
282 def isvalidfunc(tree):
283 """Examine whether specified ``tree`` is valid ``func`` or not
283 """Examine whether specified ``tree`` is valid ``func`` or not
284 """
284 """
285 return tree[0] == 'func' and len(tree) > 1 and isvalidsymbol(tree[1])
285 return tree[0] == 'func' and len(tree) > 1 and isvalidsymbol(tree[1])
286
286
287 def getfuncname(tree):
287 def getfuncname(tree):
288 """Get function name from valid ``func`` in ``tree``
288 """Get function name from valid ``func`` in ``tree``
289
289
290 This assumes that ``tree`` is already examined by ``isvalidfunc``.
290 This assumes that ``tree`` is already examined by ``isvalidfunc``.
291 """
291 """
292 return getsymbol(tree[1])
292 return getsymbol(tree[1])
293
293
294 def getfuncargs(tree):
294 def getfuncargs(tree):
295 """Get list of function arguments from valid ``func`` in ``tree``
295 """Get list of function arguments from valid ``func`` in ``tree``
296
296
297 This assumes that ``tree`` is already examined by ``isvalidfunc``.
297 This assumes that ``tree`` is already examined by ``isvalidfunc``.
298 """
298 """
299 if len(tree) > 2:
299 if len(tree) > 2:
300 return getlist(tree[2])
300 return getlist(tree[2])
301 else:
301 else:
302 return []
302 return []
303
303
304 def getset(repo, subset, x):
304 def getset(repo, subset, x):
305 if not x:
305 if not x:
306 raise error.ParseError(_("missing argument"))
306 raise error.ParseError(_("missing argument"))
307 s = methods[x[0]](repo, subset, *x[1:])
307 s = methods[x[0]](repo, subset, *x[1:])
308 if util.safehasattr(s, 'isascending'):
308 if util.safehasattr(s, 'isascending'):
309 return s
309 return s
310 return baseset(s)
310 return baseset(s)
311
311
312 def _getrevsource(repo, r):
312 def _getrevsource(repo, r):
313 extra = repo[r].extra()
313 extra = repo[r].extra()
314 for label in ('source', 'transplant_source', 'rebase_source'):
314 for label in ('source', 'transplant_source', 'rebase_source'):
315 if label in extra:
315 if label in extra:
316 try:
316 try:
317 return repo[extra[label]].rev()
317 return repo[extra[label]].rev()
318 except error.RepoLookupError:
318 except error.RepoLookupError:
319 pass
319 pass
320 return None
320 return None
321
321
322 # operator methods
322 # operator methods
323
323
324 def stringset(repo, subset, x):
324 def stringset(repo, subset, x):
325 x = repo[x].rev()
325 x = repo[x].rev()
326 if x == -1 and len(subset) == len(repo):
326 if x == -1 and len(subset) == len(repo):
327 return baseset([-1])
327 return baseset([-1])
328 if x in subset:
328 if x in subset:
329 return baseset([x])
329 return baseset([x])
330 return baseset()
330 return baseset()
331
331
332 def symbolset(repo, subset, x):
332 def symbolset(repo, subset, x):
333 if x in symbols:
333 if x in symbols:
334 raise error.ParseError(_("can't use %s here") % x)
334 raise error.ParseError(_("can't use %s here") % x)
335 return stringset(repo, subset, x)
335 return stringset(repo, subset, x)
336
336
337 def rangeset(repo, subset, x, y):
337 def rangeset(repo, subset, x, y):
338 m = getset(repo, fullreposet(repo), x)
338 m = getset(repo, fullreposet(repo), x)
339 n = getset(repo, fullreposet(repo), y)
339 n = getset(repo, fullreposet(repo), y)
340
340
341 if not m or not n:
341 if not m or not n:
342 return baseset()
342 return baseset()
343 m, n = m.first(), n.last()
343 m, n = m.first(), n.last()
344
344
345 if m < n:
345 if m < n:
346 r = spanset(repo, m, n + 1)
346 r = spanset(repo, m, n + 1)
347 else:
347 else:
348 r = spanset(repo, m, n - 1)
348 r = spanset(repo, m, n - 1)
349 return r & subset
349 return r & subset
350
350
351 def dagrange(repo, subset, x, y):
351 def dagrange(repo, subset, x, y):
352 r = fullreposet(repo)
352 r = fullreposet(repo)
353 xs = _revsbetween(repo, getset(repo, r, x), getset(repo, r, y))
353 xs = _revsbetween(repo, getset(repo, r, x), getset(repo, r, y))
354 return xs & subset
354 return xs & subset
355
355
356 def andset(repo, subset, x, y):
356 def andset(repo, subset, x, y):
357 return getset(repo, getset(repo, subset, x), y)
357 return getset(repo, getset(repo, subset, x), y)
358
358
359 def orset(repo, subset, x, y):
359 def orset(repo, subset, x, y):
360 xl = getset(repo, subset, x)
360 xl = getset(repo, subset, x)
361 yl = getset(repo, subset - xl, y)
361 yl = getset(repo, subset - xl, y)
362 return xl + yl
362 return xl + yl
363
363
364 def notset(repo, subset, x):
364 def notset(repo, subset, x):
365 return subset - getset(repo, subset, x)
365 return subset - getset(repo, subset, x)
366
366
367 def listset(repo, subset, a, b):
367 def listset(repo, subset, a, b):
368 raise error.ParseError(_("can't use a list in this context"))
368 raise error.ParseError(_("can't use a list in this context"))
369
369
370 def func(repo, subset, a, b):
370 def func(repo, subset, a, b):
371 if a[0] == 'symbol' and a[1] in symbols:
371 if a[0] == 'symbol' and a[1] in symbols:
372 return symbols[a[1]](repo, subset, b)
372 return symbols[a[1]](repo, subset, b)
373 raise error.ParseError(_("not a function: %s") % a[1])
373 raise error.ParseError(_("not a function: %s") % a[1])
374
374
375 # functions
375 # functions
376
376
377 def adds(repo, subset, x):
377 def adds(repo, subset, x):
378 """``adds(pattern)``
378 """``adds(pattern)``
379 Changesets that add a file matching pattern.
379 Changesets that add a file matching pattern.
380
380
381 The pattern without explicit kind like ``glob:`` is expected to be
381 The pattern without explicit kind like ``glob:`` is expected to be
382 relative to the current directory and match against a file or a
382 relative to the current directory and match against a file or a
383 directory.
383 directory.
384 """
384 """
385 # i18n: "adds" is a keyword
385 # i18n: "adds" is a keyword
386 pat = getstring(x, _("adds requires a pattern"))
386 pat = getstring(x, _("adds requires a pattern"))
387 return checkstatus(repo, subset, pat, 1)
387 return checkstatus(repo, subset, pat, 1)
388
388
389 def ancestor(repo, subset, x):
389 def ancestor(repo, subset, x):
390 """``ancestor(*changeset)``
390 """``ancestor(*changeset)``
391 A greatest common ancestor of the changesets.
391 A greatest common ancestor of the changesets.
392
392
393 Accepts 0 or more changesets.
393 Accepts 0 or more changesets.
394 Will return empty list when passed no args.
394 Will return empty list when passed no args.
395 Greatest common ancestor of a single changeset is that changeset.
395 Greatest common ancestor of a single changeset is that changeset.
396 """
396 """
397 # i18n: "ancestor" is a keyword
397 # i18n: "ancestor" is a keyword
398 l = getlist(x)
398 l = getlist(x)
399 rl = fullreposet(repo)
399 rl = fullreposet(repo)
400 anc = None
400 anc = None
401
401
402 # (getset(repo, rl, i) for i in l) generates a list of lists
402 # (getset(repo, rl, i) for i in l) generates a list of lists
403 for revs in (getset(repo, rl, i) for i in l):
403 for revs in (getset(repo, rl, i) for i in l):
404 for r in revs:
404 for r in revs:
405 if anc is None:
405 if anc is None:
406 anc = repo[r]
406 anc = repo[r]
407 else:
407 else:
408 anc = anc.ancestor(repo[r])
408 anc = anc.ancestor(repo[r])
409
409
410 if anc is not None and anc.rev() in subset:
410 if anc is not None and anc.rev() in subset:
411 return baseset([anc.rev()])
411 return baseset([anc.rev()])
412 return baseset()
412 return baseset()
413
413
414 def _ancestors(repo, subset, x, followfirst=False):
414 def _ancestors(repo, subset, x, followfirst=False):
415 heads = getset(repo, fullreposet(repo), x)
415 heads = getset(repo, fullreposet(repo), x)
416 if not heads:
416 if not heads:
417 return baseset()
417 return baseset()
418 s = _revancestors(repo, heads, followfirst)
418 s = _revancestors(repo, heads, followfirst)
419 return subset & s
419 return subset & s
420
420
421 def ancestors(repo, subset, x):
421 def ancestors(repo, subset, x):
422 """``ancestors(set)``
422 """``ancestors(set)``
423 Changesets that are ancestors of a changeset in set.
423 Changesets that are ancestors of a changeset in set.
424 """
424 """
425 return _ancestors(repo, subset, x)
425 return _ancestors(repo, subset, x)
426
426
427 def _firstancestors(repo, subset, x):
427 def _firstancestors(repo, subset, x):
428 # ``_firstancestors(set)``
428 # ``_firstancestors(set)``
429 # Like ``ancestors(set)`` but follows only the first parents.
429 # Like ``ancestors(set)`` but follows only the first parents.
430 return _ancestors(repo, subset, x, followfirst=True)
430 return _ancestors(repo, subset, x, followfirst=True)
431
431
432 def ancestorspec(repo, subset, x, n):
432 def ancestorspec(repo, subset, x, n):
433 """``set~n``
433 """``set~n``
434 Changesets that are the Nth ancestor (first parents only) of a changeset
434 Changesets that are the Nth ancestor (first parents only) of a changeset
435 in set.
435 in set.
436 """
436 """
437 try:
437 try:
438 n = int(n[1])
438 n = int(n[1])
439 except (TypeError, ValueError):
439 except (TypeError, ValueError):
440 raise error.ParseError(_("~ expects a number"))
440 raise error.ParseError(_("~ expects a number"))
441 ps = set()
441 ps = set()
442 cl = repo.changelog
442 cl = repo.changelog
443 for r in getset(repo, fullreposet(repo), x):
443 for r in getset(repo, fullreposet(repo), x):
444 for i in range(n):
444 for i in range(n):
445 r = cl.parentrevs(r)[0]
445 r = cl.parentrevs(r)[0]
446 ps.add(r)
446 ps.add(r)
447 return subset & ps
447 return subset & ps
448
448
449 def author(repo, subset, x):
449 def author(repo, subset, x):
450 """``author(string)``
450 """``author(string)``
451 Alias for ``user(string)``.
451 Alias for ``user(string)``.
452 """
452 """
453 # i18n: "author" is a keyword
453 # i18n: "author" is a keyword
454 n = encoding.lower(getstring(x, _("author requires a string")))
454 n = encoding.lower(getstring(x, _("author requires a string")))
455 kind, pattern, matcher = _substringmatcher(n)
455 kind, pattern, matcher = _substringmatcher(n)
456 return subset.filter(lambda x: matcher(encoding.lower(repo[x].user())))
456 return subset.filter(lambda x: matcher(encoding.lower(repo[x].user())))
457
457
458 def bisect(repo, subset, x):
458 def bisect(repo, subset, x):
459 """``bisect(string)``
459 """``bisect(string)``
460 Changesets marked in the specified bisect status:
460 Changesets marked in the specified bisect status:
461
461
462 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
462 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
463 - ``goods``, ``bads`` : csets topologically good/bad
463 - ``goods``, ``bads`` : csets topologically good/bad
464 - ``range`` : csets taking part in the bisection
464 - ``range`` : csets taking part in the bisection
465 - ``pruned`` : csets that are goods, bads or skipped
465 - ``pruned`` : csets that are goods, bads or skipped
466 - ``untested`` : csets whose fate is yet unknown
466 - ``untested`` : csets whose fate is yet unknown
467 - ``ignored`` : csets ignored due to DAG topology
467 - ``ignored`` : csets ignored due to DAG topology
468 - ``current`` : the cset currently being bisected
468 - ``current`` : the cset currently being bisected
469 """
469 """
470 # i18n: "bisect" is a keyword
470 # i18n: "bisect" is a keyword
471 status = getstring(x, _("bisect requires a string")).lower()
471 status = getstring(x, _("bisect requires a string")).lower()
472 state = set(hbisect.get(repo, status))
472 state = set(hbisect.get(repo, status))
473 return subset & state
473 return subset & state
474
474
475 # Backward-compatibility
475 # Backward-compatibility
476 # - no help entry so that we do not advertise it any more
476 # - no help entry so that we do not advertise it any more
477 def bisected(repo, subset, x):
477 def bisected(repo, subset, x):
478 return bisect(repo, subset, x)
478 return bisect(repo, subset, x)
479
479
480 def bookmark(repo, subset, x):
480 def bookmark(repo, subset, x):
481 """``bookmark([name])``
481 """``bookmark([name])``
482 The named bookmark or all bookmarks.
482 The named bookmark or all bookmarks.
483
483
484 If `name` starts with `re:`, the remainder of the name is treated as
484 If `name` starts with `re:`, the remainder of the name is treated as
485 a regular expression. To match a bookmark that actually starts with `re:`,
485 a regular expression. To match a bookmark that actually starts with `re:`,
486 use the prefix `literal:`.
486 use the prefix `literal:`.
487 """
487 """
488 # i18n: "bookmark" is a keyword
488 # i18n: "bookmark" is a keyword
489 args = getargs(x, 0, 1, _('bookmark takes one or no arguments'))
489 args = getargs(x, 0, 1, _('bookmark takes one or no arguments'))
490 if args:
490 if args:
491 bm = getstring(args[0],
491 bm = getstring(args[0],
492 # i18n: "bookmark" is a keyword
492 # i18n: "bookmark" is a keyword
493 _('the argument to bookmark must be a string'))
493 _('the argument to bookmark must be a string'))
494 kind, pattern, matcher = _stringmatcher(bm)
494 kind, pattern, matcher = _stringmatcher(bm)
495 bms = set()
495 bms = set()
496 if kind == 'literal':
496 if kind == 'literal':
497 bmrev = repo._bookmarks.get(pattern, None)
497 bmrev = repo._bookmarks.get(pattern, None)
498 if not bmrev:
498 if not bmrev:
499 raise error.RepoLookupError(_("bookmark '%s' does not exist")
499 raise error.RepoLookupError(_("bookmark '%s' does not exist")
500 % bm)
500 % bm)
501 bms.add(repo[bmrev].rev())
501 bms.add(repo[bmrev].rev())
502 else:
502 else:
503 matchrevs = set()
503 matchrevs = set()
504 for name, bmrev in repo._bookmarks.iteritems():
504 for name, bmrev in repo._bookmarks.iteritems():
505 if matcher(name):
505 if matcher(name):
506 matchrevs.add(bmrev)
506 matchrevs.add(bmrev)
507 if not matchrevs:
507 if not matchrevs:
508 raise error.RepoLookupError(_("no bookmarks exist"
508 raise error.RepoLookupError(_("no bookmarks exist"
509 " that match '%s'") % pattern)
509 " that match '%s'") % pattern)
510 for bmrev in matchrevs:
510 for bmrev in matchrevs:
511 bms.add(repo[bmrev].rev())
511 bms.add(repo[bmrev].rev())
512 else:
512 else:
513 bms = set([repo[r].rev()
513 bms = set([repo[r].rev()
514 for r in repo._bookmarks.values()])
514 for r in repo._bookmarks.values()])
515 bms -= set([node.nullrev])
515 bms -= set([node.nullrev])
516 return subset & bms
516 return subset & bms
517
517
518 def branch(repo, subset, x):
518 def branch(repo, subset, x):
519 """``branch(string or set)``
519 """``branch(string or set)``
520 All changesets belonging to the given branch or the branches of the given
520 All changesets belonging to the given branch or the branches of the given
521 changesets.
521 changesets.
522
522
523 If `string` starts with `re:`, the remainder of the name is treated as
523 If `string` starts with `re:`, the remainder of the name is treated as
524 a regular expression. To match a branch that actually starts with `re:`,
524 a regular expression. To match a branch that actually starts with `re:`,
525 use the prefix `literal:`.
525 use the prefix `literal:`.
526 """
526 """
527 import branchmap
527 import branchmap
528 urepo = repo.unfiltered()
528 urepo = repo.unfiltered()
529 ucl = urepo.changelog
529 ucl = urepo.changelog
530 getbi = branchmap.revbranchcache(urepo, readonly=True).branchinfo
530 getbi = branchmap.revbranchcache(urepo, readonly=True).branchinfo
531
531
532 try:
532 try:
533 b = getstring(x, '')
533 b = getstring(x, '')
534 except error.ParseError:
534 except error.ParseError:
535 # not a string, but another revspec, e.g. tip()
535 # not a string, but another revspec, e.g. tip()
536 pass
536 pass
537 else:
537 else:
538 kind, pattern, matcher = _stringmatcher(b)
538 kind, pattern, matcher = _stringmatcher(b)
539 if kind == 'literal':
539 if kind == 'literal':
540 # note: falls through to the revspec case if no branch with
540 # note: falls through to the revspec case if no branch with
541 # this name exists
541 # this name exists
542 if pattern in repo.branchmap():
542 if pattern in repo.branchmap():
543 return subset.filter(lambda r: matcher(getbi(ucl, r)[0]))
543 return subset.filter(lambda r: matcher(getbi(ucl, r)[0]))
544 else:
544 else:
545 return subset.filter(lambda r: matcher(getbi(ucl, r)[0]))
545 return subset.filter(lambda r: matcher(getbi(ucl, r)[0]))
546
546
547 s = getset(repo, fullreposet(repo), x)
547 s = getset(repo, fullreposet(repo), x)
548 b = set()
548 b = set()
549 for r in s:
549 for r in s:
550 b.add(getbi(ucl, r)[0])
550 b.add(getbi(ucl, r)[0])
551 c = s.__contains__
551 c = s.__contains__
552 return subset.filter(lambda r: c(r) or getbi(ucl, r)[0] in b)
552 return subset.filter(lambda r: c(r) or getbi(ucl, r)[0] in b)
553
553
554 def bumped(repo, subset, x):
554 def bumped(repo, subset, x):
555 """``bumped()``
555 """``bumped()``
556 Mutable changesets marked as successors of public changesets.
556 Mutable changesets marked as successors of public changesets.
557
557
558 Only non-public and non-obsolete changesets can be `bumped`.
558 Only non-public and non-obsolete changesets can be `bumped`.
559 """
559 """
560 # i18n: "bumped" is a keyword
560 # i18n: "bumped" is a keyword
561 getargs(x, 0, 0, _("bumped takes no arguments"))
561 getargs(x, 0, 0, _("bumped takes no arguments"))
562 bumped = obsmod.getrevs(repo, 'bumped')
562 bumped = obsmod.getrevs(repo, 'bumped')
563 return subset & bumped
563 return subset & bumped
564
564
565 def bundle(repo, subset, x):
565 def bundle(repo, subset, x):
566 """``bundle()``
566 """``bundle()``
567 Changesets in the bundle.
567 Changesets in the bundle.
568
568
569 Bundle must be specified by the -R option."""
569 Bundle must be specified by the -R option."""
570
570
571 try:
571 try:
572 bundlerevs = repo.changelog.bundlerevs
572 bundlerevs = repo.changelog.bundlerevs
573 except AttributeError:
573 except AttributeError:
574 raise util.Abort(_("no bundle provided - specify with -R"))
574 raise util.Abort(_("no bundle provided - specify with -R"))
575 return subset & bundlerevs
575 return subset & bundlerevs
576
576
577 def checkstatus(repo, subset, pat, field):
577 def checkstatus(repo, subset, pat, field):
578 hasset = matchmod.patkind(pat) == 'set'
578 hasset = matchmod.patkind(pat) == 'set'
579
579
580 mcache = [None]
580 mcache = [None]
581 def matches(x):
581 def matches(x):
582 c = repo[x]
582 c = repo[x]
583 if not mcache[0] or hasset:
583 if not mcache[0] or hasset:
584 mcache[0] = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
584 mcache[0] = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
585 m = mcache[0]
585 m = mcache[0]
586 fname = None
586 fname = None
587 if not m.anypats() and len(m.files()) == 1:
587 if not m.anypats() and len(m.files()) == 1:
588 fname = m.files()[0]
588 fname = m.files()[0]
589 if fname is not None:
589 if fname is not None:
590 if fname not in c.files():
590 if fname not in c.files():
591 return False
591 return False
592 else:
592 else:
593 for f in c.files():
593 for f in c.files():
594 if m(f):
594 if m(f):
595 break
595 break
596 else:
596 else:
597 return False
597 return False
598 files = repo.status(c.p1().node(), c.node())[field]
598 files = repo.status(c.p1().node(), c.node())[field]
599 if fname is not None:
599 if fname is not None:
600 if fname in files:
600 if fname in files:
601 return True
601 return True
602 else:
602 else:
603 for f in files:
603 for f in files:
604 if m(f):
604 if m(f):
605 return True
605 return True
606
606
607 return subset.filter(matches)
607 return subset.filter(matches)
608
608
609 def _children(repo, narrow, parentset):
609 def _children(repo, narrow, parentset):
610 cs = set()
610 cs = set()
611 if not parentset:
611 if not parentset:
612 return baseset(cs)
612 return baseset(cs)
613 pr = repo.changelog.parentrevs
613 pr = repo.changelog.parentrevs
614 minrev = min(parentset)
614 minrev = min(parentset)
615 for r in narrow:
615 for r in narrow:
616 if r <= minrev:
616 if r <= minrev:
617 continue
617 continue
618 for p in pr(r):
618 for p in pr(r):
619 if p in parentset:
619 if p in parentset:
620 cs.add(r)
620 cs.add(r)
621 return baseset(cs)
621 return baseset(cs)
622
622
623 def children(repo, subset, x):
623 def children(repo, subset, x):
624 """``children(set)``
624 """``children(set)``
625 Child changesets of changesets in set.
625 Child changesets of changesets in set.
626 """
626 """
627 s = getset(repo, fullreposet(repo), x)
627 s = getset(repo, fullreposet(repo), x)
628 cs = _children(repo, subset, s)
628 cs = _children(repo, subset, s)
629 return subset & cs
629 return subset & cs
630
630
631 def closed(repo, subset, x):
631 def closed(repo, subset, x):
632 """``closed()``
632 """``closed()``
633 Changeset is closed.
633 Changeset is closed.
634 """
634 """
635 # i18n: "closed" is a keyword
635 # i18n: "closed" is a keyword
636 getargs(x, 0, 0, _("closed takes no arguments"))
636 getargs(x, 0, 0, _("closed takes no arguments"))
637 return subset.filter(lambda r: repo[r].closesbranch())
637 return subset.filter(lambda r: repo[r].closesbranch())
638
638
639 def contains(repo, subset, x):
639 def contains(repo, subset, x):
640 """``contains(pattern)``
640 """``contains(pattern)``
641 The revision's manifest contains a file matching pattern (but might not
641 The revision's manifest contains a file matching pattern (but might not
642 modify it). See :hg:`help patterns` for information about file patterns.
642 modify it). See :hg:`help patterns` for information about file patterns.
643
643
644 The pattern without explicit kind like ``glob:`` is expected to be
644 The pattern without explicit kind like ``glob:`` is expected to be
645 relative to the current directory and match against a file exactly
645 relative to the current directory and match against a file exactly
646 for efficiency.
646 for efficiency.
647 """
647 """
648 # i18n: "contains" is a keyword
648 # i18n: "contains" is a keyword
649 pat = getstring(x, _("contains requires a pattern"))
649 pat = getstring(x, _("contains requires a pattern"))
650
650
651 def matches(x):
651 def matches(x):
652 if not matchmod.patkind(pat):
652 if not matchmod.patkind(pat):
653 pats = pathutil.canonpath(repo.root, repo.getcwd(), pat)
653 pats = pathutil.canonpath(repo.root, repo.getcwd(), pat)
654 if pats in repo[x]:
654 if pats in repo[x]:
655 return True
655 return True
656 else:
656 else:
657 c = repo[x]
657 c = repo[x]
658 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
658 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
659 for f in c.manifest():
659 for f in c.manifest():
660 if m(f):
660 if m(f):
661 return True
661 return True
662 return False
662 return False
663
663
664 return subset.filter(matches)
664 return subset.filter(matches)
665
665
666 def converted(repo, subset, x):
666 def converted(repo, subset, x):
667 """``converted([id])``
667 """``converted([id])``
668 Changesets converted from the given identifier in the old repository if
668 Changesets converted from the given identifier in the old repository if
669 present, or all converted changesets if no identifier is specified.
669 present, or all converted changesets if no identifier is specified.
670 """
670 """
671
671
672 # There is exactly no chance of resolving the revision, so do a simple
672 # There is exactly no chance of resolving the revision, so do a simple
673 # string compare and hope for the best
673 # string compare and hope for the best
674
674
675 rev = None
675 rev = None
676 # i18n: "converted" is a keyword
676 # i18n: "converted" is a keyword
677 l = getargs(x, 0, 1, _('converted takes one or no arguments'))
677 l = getargs(x, 0, 1, _('converted takes one or no arguments'))
678 if l:
678 if l:
679 # i18n: "converted" is a keyword
679 # i18n: "converted" is a keyword
680 rev = getstring(l[0], _('converted requires a revision'))
680 rev = getstring(l[0], _('converted requires a revision'))
681
681
682 def _matchvalue(r):
682 def _matchvalue(r):
683 source = repo[r].extra().get('convert_revision', None)
683 source = repo[r].extra().get('convert_revision', None)
684 return source is not None and (rev is None or source.startswith(rev))
684 return source is not None and (rev is None or source.startswith(rev))
685
685
686 return subset.filter(lambda r: _matchvalue(r))
686 return subset.filter(lambda r: _matchvalue(r))
687
687
688 def date(repo, subset, x):
688 def date(repo, subset, x):
689 """``date(interval)``
689 """``date(interval)``
690 Changesets within the interval, see :hg:`help dates`.
690 Changesets within the interval, see :hg:`help dates`.
691 """
691 """
692 # i18n: "date" is a keyword
692 # i18n: "date" is a keyword
693 ds = getstring(x, _("date requires a string"))
693 ds = getstring(x, _("date requires a string"))
694 dm = util.matchdate(ds)
694 dm = util.matchdate(ds)
695 return subset.filter(lambda x: dm(repo[x].date()[0]))
695 return subset.filter(lambda x: dm(repo[x].date()[0]))
696
696
697 def desc(repo, subset, x):
697 def desc(repo, subset, x):
698 """``desc(string)``
698 """``desc(string)``
699 Search commit message for string. The match is case-insensitive.
699 Search commit message for string. The match is case-insensitive.
700 """
700 """
701 # i18n: "desc" is a keyword
701 # i18n: "desc" is a keyword
702 ds = encoding.lower(getstring(x, _("desc requires a string")))
702 ds = encoding.lower(getstring(x, _("desc requires a string")))
703
703
704 def matches(x):
704 def matches(x):
705 c = repo[x]
705 c = repo[x]
706 return ds in encoding.lower(c.description())
706 return ds in encoding.lower(c.description())
707
707
708 return subset.filter(matches)
708 return subset.filter(matches)
709
709
710 def _descendants(repo, subset, x, followfirst=False):
710 def _descendants(repo, subset, x, followfirst=False):
711 roots = getset(repo, fullreposet(repo), x)
711 roots = getset(repo, fullreposet(repo), x)
712 if not roots:
712 if not roots:
713 return baseset()
713 return baseset()
714 s = _revdescendants(repo, roots, followfirst)
714 s = _revdescendants(repo, roots, followfirst)
715
715
716 # Both sets need to be ascending in order to lazily return the union
716 # Both sets need to be ascending in order to lazily return the union
717 # in the correct order.
717 # in the correct order.
718 base = subset & roots
718 base = subset & roots
719 desc = subset & s
719 desc = subset & s
720 result = base + desc
720 result = base + desc
721 if subset.isascending():
721 if subset.isascending():
722 result.sort()
722 result.sort()
723 elif subset.isdescending():
723 elif subset.isdescending():
724 result.sort(reverse=True)
724 result.sort(reverse=True)
725 else:
725 else:
726 result = subset & result
726 result = subset & result
727 return result
727 return result
728
728
729 def descendants(repo, subset, x):
729 def descendants(repo, subset, x):
730 """``descendants(set)``
730 """``descendants(set)``
731 Changesets which are descendants of changesets in set.
731 Changesets which are descendants of changesets in set.
732 """
732 """
733 return _descendants(repo, subset, x)
733 return _descendants(repo, subset, x)
734
734
735 def _firstdescendants(repo, subset, x):
735 def _firstdescendants(repo, subset, x):
736 # ``_firstdescendants(set)``
736 # ``_firstdescendants(set)``
737 # Like ``descendants(set)`` but follows only the first parents.
737 # Like ``descendants(set)`` but follows only the first parents.
738 return _descendants(repo, subset, x, followfirst=True)
738 return _descendants(repo, subset, x, followfirst=True)
739
739
740 def destination(repo, subset, x):
740 def destination(repo, subset, x):
741 """``destination([set])``
741 """``destination([set])``
742 Changesets that were created by a graft, transplant or rebase operation,
742 Changesets that were created by a graft, transplant or rebase operation,
743 with the given revisions specified as the source. Omitting the optional set
743 with the given revisions specified as the source. Omitting the optional set
744 is the same as passing all().
744 is the same as passing all().
745 """
745 """
746 if x is not None:
746 if x is not None:
747 sources = getset(repo, fullreposet(repo), x)
747 sources = getset(repo, fullreposet(repo), x)
748 else:
748 else:
749 sources = fullreposet(repo)
749 sources = fullreposet(repo)
750
750
751 dests = set()
751 dests = set()
752
752
753 # subset contains all of the possible destinations that can be returned, so
753 # subset contains all of the possible destinations that can be returned, so
754 # iterate over them and see if their source(s) were provided in the arg set.
754 # iterate over them and see if their source(s) were provided in the arg set.
755 # Even if the immediate src of r is not in the arg set, src's source (or
755 # Even if the immediate src of r is not in the arg set, src's source (or
756 # further back) may be. Scanning back further than the immediate src allows
756 # further back) may be. Scanning back further than the immediate src allows
757 # transitive transplants and rebases to yield the same results as transitive
757 # transitive transplants and rebases to yield the same results as transitive
758 # grafts.
758 # grafts.
759 for r in subset:
759 for r in subset:
760 src = _getrevsource(repo, r)
760 src = _getrevsource(repo, r)
761 lineage = None
761 lineage = None
762
762
763 while src is not None:
763 while src is not None:
764 if lineage is None:
764 if lineage is None:
765 lineage = list()
765 lineage = list()
766
766
767 lineage.append(r)
767 lineage.append(r)
768
768
769 # The visited lineage is a match if the current source is in the arg
769 # The visited lineage is a match if the current source is in the arg
770 # set. Since every candidate dest is visited by way of iterating
770 # set. Since every candidate dest is visited by way of iterating
771 # subset, any dests further back in the lineage will be tested by a
771 # subset, any dests further back in the lineage will be tested by a
772 # different iteration over subset. Likewise, if the src was already
772 # different iteration over subset. Likewise, if the src was already
773 # selected, the current lineage can be selected without going back
773 # selected, the current lineage can be selected without going back
774 # further.
774 # further.
775 if src in sources or src in dests:
775 if src in sources or src in dests:
776 dests.update(lineage)
776 dests.update(lineage)
777 break
777 break
778
778
779 r = src
779 r = src
780 src = _getrevsource(repo, r)
780 src = _getrevsource(repo, r)
781
781
782 return subset.filter(dests.__contains__)
782 return subset.filter(dests.__contains__)
783
783
784 def divergent(repo, subset, x):
784 def divergent(repo, subset, x):
785 """``divergent()``
785 """``divergent()``
786 Final successors of changesets with an alternative set of final successors.
786 Final successors of changesets with an alternative set of final successors.
787 """
787 """
788 # i18n: "divergent" is a keyword
788 # i18n: "divergent" is a keyword
789 getargs(x, 0, 0, _("divergent takes no arguments"))
789 getargs(x, 0, 0, _("divergent takes no arguments"))
790 divergent = obsmod.getrevs(repo, 'divergent')
790 divergent = obsmod.getrevs(repo, 'divergent')
791 return subset & divergent
791 return subset & divergent
792
792
793 def draft(repo, subset, x):
793 def draft(repo, subset, x):
794 """``draft()``
794 """``draft()``
795 Changeset in draft phase."""
795 Changeset in draft phase."""
796 # i18n: "draft" is a keyword
796 # i18n: "draft" is a keyword
797 getargs(x, 0, 0, _("draft takes no arguments"))
797 getargs(x, 0, 0, _("draft takes no arguments"))
798 phase = repo._phasecache.phase
798 phase = repo._phasecache.phase
799 target = phases.draft
799 target = phases.draft
800 condition = lambda r: phase(repo, r) == target
800 condition = lambda r: phase(repo, r) == target
801 return subset.filter(condition, cache=False)
801 return subset.filter(condition, cache=False)
802
802
803 def extinct(repo, subset, x):
803 def extinct(repo, subset, x):
804 """``extinct()``
804 """``extinct()``
805 Obsolete changesets with obsolete descendants only.
805 Obsolete changesets with obsolete descendants only.
806 """
806 """
807 # i18n: "extinct" is a keyword
807 # i18n: "extinct" is a keyword
808 getargs(x, 0, 0, _("extinct takes no arguments"))
808 getargs(x, 0, 0, _("extinct takes no arguments"))
809 extincts = obsmod.getrevs(repo, 'extinct')
809 extincts = obsmod.getrevs(repo, 'extinct')
810 return subset & extincts
810 return subset & extincts
811
811
812 def extra(repo, subset, x):
812 def extra(repo, subset, x):
813 """``extra(label, [value])``
813 """``extra(label, [value])``
814 Changesets with the given label in the extra metadata, with the given
814 Changesets with the given label in the extra metadata, with the given
815 optional value.
815 optional value.
816
816
817 If `value` starts with `re:`, the remainder of the value is treated as
817 If `value` starts with `re:`, the remainder of the value is treated as
818 a regular expression. To match a value that actually starts with `re:`,
818 a regular expression. To match a value that actually starts with `re:`,
819 use the prefix `literal:`.
819 use the prefix `literal:`.
820 """
820 """
821
821
822 # i18n: "extra" is a keyword
822 # i18n: "extra" is a keyword
823 l = getargs(x, 1, 2, _('extra takes at least 1 and at most 2 arguments'))
823 l = getargs(x, 1, 2, _('extra takes at least 1 and at most 2 arguments'))
824 # i18n: "extra" is a keyword
824 # i18n: "extra" is a keyword
825 label = getstring(l[0], _('first argument to extra must be a string'))
825 label = getstring(l[0], _('first argument to extra must be a string'))
826 value = None
826 value = None
827
827
828 if len(l) > 1:
828 if len(l) > 1:
829 # i18n: "extra" is a keyword
829 # i18n: "extra" is a keyword
830 value = getstring(l[1], _('second argument to extra must be a string'))
830 value = getstring(l[1], _('second argument to extra must be a string'))
831 kind, value, matcher = _stringmatcher(value)
831 kind, value, matcher = _stringmatcher(value)
832
832
833 def _matchvalue(r):
833 def _matchvalue(r):
834 extra = repo[r].extra()
834 extra = repo[r].extra()
835 return label in extra and (value is None or matcher(extra[label]))
835 return label in extra and (value is None or matcher(extra[label]))
836
836
837 return subset.filter(lambda r: _matchvalue(r))
837 return subset.filter(lambda r: _matchvalue(r))
838
838
839 def filelog(repo, subset, x):
839 def filelog(repo, subset, x):
840 """``filelog(pattern)``
840 """``filelog(pattern)``
841 Changesets connected to the specified filelog.
841 Changesets connected to the specified filelog.
842
842
843 For performance reasons, visits only revisions mentioned in the file-level
843 For performance reasons, visits only revisions mentioned in the file-level
844 filelog, rather than filtering through all changesets (much faster, but
844 filelog, rather than filtering through all changesets (much faster, but
845 doesn't include deletes or duplicate changes). For a slower, more accurate
845 doesn't include deletes or duplicate changes). For a slower, more accurate
846 result, use ``file()``.
846 result, use ``file()``.
847
847
848 The pattern without explicit kind like ``glob:`` is expected to be
848 The pattern without explicit kind like ``glob:`` is expected to be
849 relative to the current directory and match against a file exactly
849 relative to the current directory and match against a file exactly
850 for efficiency.
850 for efficiency.
851
851
852 If some linkrev points to revisions filtered by the current repoview, we'll
852 If some linkrev points to revisions filtered by the current repoview, we'll
853 work around it to return a non-filtered value.
853 work around it to return a non-filtered value.
854 """
854 """
855
855
856 # i18n: "filelog" is a keyword
856 # i18n: "filelog" is a keyword
857 pat = getstring(x, _("filelog requires a pattern"))
857 pat = getstring(x, _("filelog requires a pattern"))
858 s = set()
858 s = set()
859 cl = repo.changelog
859 cl = repo.changelog
860
860
861 if not matchmod.patkind(pat):
861 if not matchmod.patkind(pat):
862 f = pathutil.canonpath(repo.root, repo.getcwd(), pat)
862 f = pathutil.canonpath(repo.root, repo.getcwd(), pat)
863 files = [f]
863 files = [f]
864 else:
864 else:
865 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[None])
865 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[None])
866 files = (f for f in repo[None] if m(f))
866 files = (f for f in repo[None] if m(f))
867
867
868 for f in files:
868 for f in files:
869 backrevref = {} # final value for: filerev -> changerev
869 backrevref = {} # final value for: filerev -> changerev
870 lowestchild = {} # lowest known filerev child of a filerev
870 lowestchild = {} # lowest known filerev child of a filerev
871 delayed = [] # filerev with filtered linkrev, for post-processing
871 delayed = [] # filerev with filtered linkrev, for post-processing
872 lowesthead = None # cache for manifest content of all head revisions
872 lowesthead = None # cache for manifest content of all head revisions
873 fl = repo.file(f)
873 fl = repo.file(f)
874 for fr in list(fl):
874 for fr in list(fl):
875 rev = fl.linkrev(fr)
875 rev = fl.linkrev(fr)
876 if rev not in cl:
876 if rev not in cl:
877 # changerev pointed in linkrev is filtered
877 # changerev pointed in linkrev is filtered
878 # record it for post processing.
878 # record it for post processing.
879 delayed.append((fr, rev))
879 delayed.append((fr, rev))
880 continue
880 continue
881 for p in fl.parentrevs(fr):
881 for p in fl.parentrevs(fr):
882 if 0 <= p and p not in lowestchild:
882 if 0 <= p and p not in lowestchild:
883 lowestchild[p] = fr
883 lowestchild[p] = fr
884 backrevref[fr] = rev
884 backrevref[fr] = rev
885 s.add(rev)
885 s.add(rev)
886
886
887 # Post-processing of all filerevs we skipped because they were
887 # Post-processing of all filerevs we skipped because they were
888 # filtered. If such filerevs have known and unfiltered children, this
888 # filtered. If such filerevs have known and unfiltered children, this
889 # means they have an unfiltered appearance out there. We'll use linkrev
889 # means they have an unfiltered appearance out there. We'll use linkrev
890 # adjustment to find one of these appearances. The lowest known child
890 # adjustment to find one of these appearances. The lowest known child
891 # will be used as a starting point because it is the best upper-bound we
891 # will be used as a starting point because it is the best upper-bound we
892 # have.
892 # have.
893 #
893 #
894 # This approach will fail when an unfiltered but linkrev-shadowed
894 # This approach will fail when an unfiltered but linkrev-shadowed
895 # appearance exists in a head changeset without unfiltered filerev
895 # appearance exists in a head changeset without unfiltered filerev
896 # children anywhere.
896 # children anywhere.
897 while delayed:
897 while delayed:
898 # must be a descending iteration. To slowly fill lowest child
898 # must be a descending iteration. To slowly fill lowest child
899 # information that is of potential use by the next item.
899 # information that is of potential use by the next item.
900 fr, rev = delayed.pop()
900 fr, rev = delayed.pop()
901 lkr = rev
901 lkr = rev
902
902
903 child = lowestchild.get(fr)
903 child = lowestchild.get(fr)
904
904
905 if child is None:
905 if child is None:
906 # search for existence of this file revision in a head revision.
906 # search for existence of this file revision in a head revision.
907 # There are three possibilities:
907 # There are three possibilities:
908 # - the revision exists in a head and we can find an
908 # - the revision exists in a head and we can find an
909 # introduction from there,
909 # introduction from there,
910 # - the revision does not exist in a head because it has been
910 # - the revision does not exist in a head because it has been
911 # changed since its introduction: we would have found a child
911 # changed since its introduction: we would have found a child
912 # and be in the other 'else' clause,
912 # and be in the other 'else' clause,
913 # - all versions of the revision are hidden.
913 # - all versions of the revision are hidden.
914 if lowesthead is None:
914 if lowesthead is None:
915 lowesthead = {}
915 lowesthead = {}
916 for h in repo.heads():
916 for h in repo.heads():
917 fnode = repo[h].manifest().get(f)
917 fnode = repo[h].manifest().get(f)
918 if fnode is not None:
918 if fnode is not None:
919 lowesthead[fl.rev(fnode)] = h
919 lowesthead[fl.rev(fnode)] = h
920 headrev = lowesthead.get(fr)
920 headrev = lowesthead.get(fr)
921 if headrev is None:
921 if headrev is None:
922 # content is nowhere unfiltered
922 # content is nowhere unfiltered
923 continue
923 continue
924 rev = repo[headrev][f].introrev()
924 rev = repo[headrev][f].introrev()
925 else:
925 else:
926 # the lowest known child is a good upper bound
926 # the lowest known child is a good upper bound
927 childcrev = backrevref[child]
927 childcrev = backrevref[child]
928 # XXX this does not guarantee returning the lowest
928 # XXX this does not guarantee returning the lowest
929 # introduction of this revision, but this gives a
929 # introduction of this revision, but this gives a
930 # result which is a good start and will fit in most
930 # result which is a good start and will fit in most
931 # cases. We probably need to fix the multiple
931 # cases. We probably need to fix the multiple
932 # introductions case properly (report each
932 # introductions case properly (report each
933 # introduction, even for identical file revisions)
933 # introduction, even for identical file revisions)
934 # once and for all at some point anyway.
934 # once and for all at some point anyway.
935 for p in repo[childcrev][f].parents():
935 for p in repo[childcrev][f].parents():
936 if p.filerev() == fr:
936 if p.filerev() == fr:
937 rev = p.rev()
937 rev = p.rev()
938 break
938 break
939 if rev == lkr: # no shadowed entry found
939 if rev == lkr: # no shadowed entry found
940 # XXX This should never happen unless some manifest points
940 # XXX This should never happen unless some manifest points
941 # to biggish file revisions (like a revision that uses a
941 # to biggish file revisions (like a revision that uses a
942 # parent that never appears in the manifest ancestors)
942 # parent that never appears in the manifest ancestors)
943 continue
943 continue
944
944
945 # Fill the data for the next iteration.
945 # Fill the data for the next iteration.
946 for p in fl.parentrevs(fr):
946 for p in fl.parentrevs(fr):
947 if 0 <= p and p not in lowestchild:
947 if 0 <= p and p not in lowestchild:
948 lowestchild[p] = fr
948 lowestchild[p] = fr
949 backrevref[fr] = rev
949 backrevref[fr] = rev
950 s.add(rev)
950 s.add(rev)
951
951
952 return subset & s
952 return subset & s
953
953
954 def first(repo, subset, x):
954 def first(repo, subset, x):
955 """``first(set, [n])``
955 """``first(set, [n])``
956 An alias for limit().
956 An alias for limit().
957 """
957 """
958 return limit(repo, subset, x)
958 return limit(repo, subset, x)
959
959
960 def _follow(repo, subset, x, name, followfirst=False):
960 def _follow(repo, subset, x, name, followfirst=False):
961 l = getargs(x, 0, 1, _("%s takes no arguments or a filename") % name)
961 l = getargs(x, 0, 1, _("%s takes no arguments or a filename") % name)
962 c = repo['.']
962 c = repo['.']
963 if l:
963 if l:
964 x = getstring(l[0], _("%s expected a filename") % name)
964 x = getstring(l[0], _("%s expected a filename") % name)
965 if x in c:
965 if x in c:
966 cx = c[x]
966 cx = c[x]
967 s = set(ctx.rev() for ctx in cx.ancestors(followfirst=followfirst))
967 s = set(ctx.rev() for ctx in cx.ancestors(followfirst=followfirst))
968 # include the revision responsible for the most recent version
968 # include the revision responsible for the most recent version
969 s.add(cx.introrev())
969 s.add(cx.introrev())
970 else:
970 else:
971 return baseset()
971 return baseset()
972 else:
972 else:
973 s = _revancestors(repo, baseset([c.rev()]), followfirst)
973 s = _revancestors(repo, baseset([c.rev()]), followfirst)
974
974
975 return subset & s
975 return subset & s
976
976
977 def follow(repo, subset, x):
977 def follow(repo, subset, x):
978 """``follow([file])``
978 """``follow([file])``
979 An alias for ``::.`` (ancestors of the working copy's first parent).
979 An alias for ``::.`` (ancestors of the working copy's first parent).
980 If a filename is specified, the history of the given file is followed,
980 If a filename is specified, the history of the given file is followed,
981 including copies.
981 including copies.
982 """
982 """
983 return _follow(repo, subset, x, 'follow')
983 return _follow(repo, subset, x, 'follow')
984
984
985 def _followfirst(repo, subset, x):
985 def _followfirst(repo, subset, x):
986 # ``followfirst([file])``
986 # ``followfirst([file])``
987 # Like ``follow([file])`` but follows only the first parent of
987 # Like ``follow([file])`` but follows only the first parent of
988 # every revision or file revision.
988 # every revision or file revision.
989 return _follow(repo, subset, x, '_followfirst', followfirst=True)
989 return _follow(repo, subset, x, '_followfirst', followfirst=True)
990
990
991 def getall(repo, subset, x):
991 def getall(repo, subset, x):
992 """``all()``
992 """``all()``
993 All changesets, the same as ``0:tip``.
993 All changesets, the same as ``0:tip``.
994 """
994 """
995 # i18n: "all" is a keyword
995 # i18n: "all" is a keyword
996 getargs(x, 0, 0, _("all takes no arguments"))
996 getargs(x, 0, 0, _("all takes no arguments"))
997 return subset
997 return subset & spanset(repo) # drop "null" if any
998
998
999 def grep(repo, subset, x):
999 def grep(repo, subset, x):
1000 """``grep(regex)``
1000 """``grep(regex)``
1001 Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
1001 Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
1002 to ensure special escape characters are handled correctly. Unlike
1002 to ensure special escape characters are handled correctly. Unlike
1003 ``keyword(string)``, the match is case-sensitive.
1003 ``keyword(string)``, the match is case-sensitive.
1004 """
1004 """
1005 try:
1005 try:
1006 # i18n: "grep" is a keyword
1006 # i18n: "grep" is a keyword
1007 gr = re.compile(getstring(x, _("grep requires a string")))
1007 gr = re.compile(getstring(x, _("grep requires a string")))
1008 except re.error, e:
1008 except re.error, e:
1009 raise error.ParseError(_('invalid match pattern: %s') % e)
1009 raise error.ParseError(_('invalid match pattern: %s') % e)
1010
1010
1011 def matches(x):
1011 def matches(x):
1012 c = repo[x]
1012 c = repo[x]
1013 for e in c.files() + [c.user(), c.description()]:
1013 for e in c.files() + [c.user(), c.description()]:
1014 if gr.search(e):
1014 if gr.search(e):
1015 return True
1015 return True
1016 return False
1016 return False
1017
1017
1018 return subset.filter(matches)
1018 return subset.filter(matches)
1019
1019
1020 def _matchfiles(repo, subset, x):
1020 def _matchfiles(repo, subset, x):
1021 # _matchfiles takes a revset list of prefixed arguments:
1021 # _matchfiles takes a revset list of prefixed arguments:
1022 #
1022 #
1023 # [p:foo, i:bar, x:baz]
1023 # [p:foo, i:bar, x:baz]
1024 #
1024 #
1025 # builds a match object from them and filters subset. Allowed
1025 # builds a match object from them and filters subset. Allowed
1026 # prefixes are 'p:' for regular patterns, 'i:' for include
1026 # prefixes are 'p:' for regular patterns, 'i:' for include
1027 # patterns and 'x:' for exclude patterns. Use 'r:' prefix to pass
1027 # patterns and 'x:' for exclude patterns. Use 'r:' prefix to pass
1028 # a revision identifier, or the empty string to reference the
1028 # a revision identifier, or the empty string to reference the
1029 # working directory, from which the match object is
1029 # working directory, from which the match object is
1030 # initialized. Use 'd:' to set the default matching mode, default
1030 # initialized. Use 'd:' to set the default matching mode, default
1031 # to 'glob'. At most one 'r:' and 'd:' argument can be passed.
1031 # to 'glob'. At most one 'r:' and 'd:' argument can be passed.
1032
1032
1033 # i18n: "_matchfiles" is a keyword
1033 # i18n: "_matchfiles" is a keyword
1034 l = getargs(x, 1, -1, _("_matchfiles requires at least one argument"))
1034 l = getargs(x, 1, -1, _("_matchfiles requires at least one argument"))
1035 pats, inc, exc = [], [], []
1035 pats, inc, exc = [], [], []
1036 rev, default = None, None
1036 rev, default = None, None
1037 for arg in l:
1037 for arg in l:
1038 # i18n: "_matchfiles" is a keyword
1038 # i18n: "_matchfiles" is a keyword
1039 s = getstring(arg, _("_matchfiles requires string arguments"))
1039 s = getstring(arg, _("_matchfiles requires string arguments"))
1040 prefix, value = s[:2], s[2:]
1040 prefix, value = s[:2], s[2:]
1041 if prefix == 'p:':
1041 if prefix == 'p:':
1042 pats.append(value)
1042 pats.append(value)
1043 elif prefix == 'i:':
1043 elif prefix == 'i:':
1044 inc.append(value)
1044 inc.append(value)
1045 elif prefix == 'x:':
1045 elif prefix == 'x:':
1046 exc.append(value)
1046 exc.append(value)
1047 elif prefix == 'r:':
1047 elif prefix == 'r:':
1048 if rev is not None:
1048 if rev is not None:
1049 # i18n: "_matchfiles" is a keyword
1049 # i18n: "_matchfiles" is a keyword
1050 raise error.ParseError(_('_matchfiles expected at most one '
1050 raise error.ParseError(_('_matchfiles expected at most one '
1051 'revision'))
1051 'revision'))
1052 if value != '': # empty means working directory; leave rev as None
1052 if value != '': # empty means working directory; leave rev as None
1053 rev = value
1053 rev = value
1054 elif prefix == 'd:':
1054 elif prefix == 'd:':
1055 if default is not None:
1055 if default is not None:
1056 # i18n: "_matchfiles" is a keyword
1056 # i18n: "_matchfiles" is a keyword
1057 raise error.ParseError(_('_matchfiles expected at most one '
1057 raise error.ParseError(_('_matchfiles expected at most one '
1058 'default mode'))
1058 'default mode'))
1059 default = value
1059 default = value
1060 else:
1060 else:
1061 # i18n: "_matchfiles" is a keyword
1061 # i18n: "_matchfiles" is a keyword
1062 raise error.ParseError(_('invalid _matchfiles prefix: %s') % prefix)
1062 raise error.ParseError(_('invalid _matchfiles prefix: %s') % prefix)
1063 if not default:
1063 if not default:
1064 default = 'glob'
1064 default = 'glob'
1065
1065
1066 m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc,
1066 m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc,
1067 exclude=exc, ctx=repo[rev], default=default)
1067 exclude=exc, ctx=repo[rev], default=default)
1068
1068
1069 def matches(x):
1069 def matches(x):
1070 for f in repo[x].files():
1070 for f in repo[x].files():
1071 if m(f):
1071 if m(f):
1072 return True
1072 return True
1073 return False
1073 return False
1074
1074
1075 return subset.filter(matches)
1075 return subset.filter(matches)
1076
1076
1077 def hasfile(repo, subset, x):
1077 def hasfile(repo, subset, x):
1078 """``file(pattern)``
1078 """``file(pattern)``
1079 Changesets affecting files matched by pattern.
1079 Changesets affecting files matched by pattern.
1080
1080
1081 For a faster but less accurate result, consider using ``filelog()``
1081 For a faster but less accurate result, consider using ``filelog()``
1082 instead.
1082 instead.
1083
1083
1084 This predicate uses ``glob:`` as the default kind of pattern.
1084 This predicate uses ``glob:`` as the default kind of pattern.
1085 """
1085 """
1086 # i18n: "file" is a keyword
1086 # i18n: "file" is a keyword
1087 pat = getstring(x, _("file requires a pattern"))
1087 pat = getstring(x, _("file requires a pattern"))
1088 return _matchfiles(repo, subset, ('string', 'p:' + pat))
1088 return _matchfiles(repo, subset, ('string', 'p:' + pat))
1089
1089
1090 def head(repo, subset, x):
1090 def head(repo, subset, x):
1091 """``head()``
1091 """``head()``
1092 Changeset is a named branch head.
1092 Changeset is a named branch head.
1093 """
1093 """
1094 # i18n: "head" is a keyword
1094 # i18n: "head" is a keyword
1095 getargs(x, 0, 0, _("head takes no arguments"))
1095 getargs(x, 0, 0, _("head takes no arguments"))
1096 hs = set()
1096 hs = set()
1097 for b, ls in repo.branchmap().iteritems():
1097 for b, ls in repo.branchmap().iteritems():
1098 hs.update(repo[h].rev() for h in ls)
1098 hs.update(repo[h].rev() for h in ls)
1099 return baseset(hs).filter(subset.__contains__)
1099 return baseset(hs).filter(subset.__contains__)
1100
1100
1101 def heads(repo, subset, x):
1101 def heads(repo, subset, x):
1102 """``heads(set)``
1102 """``heads(set)``
1103 Members of set with no children in set.
1103 Members of set with no children in set.
1104 """
1104 """
1105 s = getset(repo, subset, x)
1105 s = getset(repo, subset, x)
1106 ps = parents(repo, subset, x)
1106 ps = parents(repo, subset, x)
1107 return s - ps
1107 return s - ps
1108
1108
1109 def hidden(repo, subset, x):
1109 def hidden(repo, subset, x):
1110 """``hidden()``
1110 """``hidden()``
1111 Hidden changesets.
1111 Hidden changesets.
1112 """
1112 """
1113 # i18n: "hidden" is a keyword
1113 # i18n: "hidden" is a keyword
1114 getargs(x, 0, 0, _("hidden takes no arguments"))
1114 getargs(x, 0, 0, _("hidden takes no arguments"))
1115 hiddenrevs = repoview.filterrevs(repo, 'visible')
1115 hiddenrevs = repoview.filterrevs(repo, 'visible')
1116 return subset & hiddenrevs
1116 return subset & hiddenrevs
1117
1117
1118 def keyword(repo, subset, x):
1118 def keyword(repo, subset, x):
1119 """``keyword(string)``
1119 """``keyword(string)``
1120 Search commit message, user name, and names of changed files for
1120 Search commit message, user name, and names of changed files for
1121 string. The match is case-insensitive.
1121 string. The match is case-insensitive.
1122 """
1122 """
1123 # i18n: "keyword" is a keyword
1123 # i18n: "keyword" is a keyword
1124 kw = encoding.lower(getstring(x, _("keyword requires a string")))
1124 kw = encoding.lower(getstring(x, _("keyword requires a string")))
1125
1125
1126 def matches(r):
1126 def matches(r):
1127 c = repo[r]
1127 c = repo[r]
1128 return util.any(kw in encoding.lower(t) for t in c.files() + [c.user(),
1128 return util.any(kw in encoding.lower(t) for t in c.files() + [c.user(),
1129 c.description()])
1129 c.description()])
1130
1130
1131 return subset.filter(matches)
1131 return subset.filter(matches)
1132
1132
1133 def limit(repo, subset, x):
1133 def limit(repo, subset, x):
1134 """``limit(set, [n])``
1134 """``limit(set, [n])``
1135 First n members of set, defaulting to 1.
1135 First n members of set, defaulting to 1.
1136 """
1136 """
1137 # i18n: "limit" is a keyword
1137 # i18n: "limit" is a keyword
1138 l = getargs(x, 1, 2, _("limit requires one or two arguments"))
1138 l = getargs(x, 1, 2, _("limit requires one or two arguments"))
1139 try:
1139 try:
1140 lim = 1
1140 lim = 1
1141 if len(l) == 2:
1141 if len(l) == 2:
1142 # i18n: "limit" is a keyword
1142 # i18n: "limit" is a keyword
1143 lim = int(getstring(l[1], _("limit requires a number")))
1143 lim = int(getstring(l[1], _("limit requires a number")))
1144 except (TypeError, ValueError):
1144 except (TypeError, ValueError):
1145 # i18n: "limit" is a keyword
1145 # i18n: "limit" is a keyword
1146 raise error.ParseError(_("limit expects a number"))
1146 raise error.ParseError(_("limit expects a number"))
1147 ss = subset
1147 ss = subset
1148 os = getset(repo, fullreposet(repo), l[0])
1148 os = getset(repo, fullreposet(repo), l[0])
1149 result = []
1149 result = []
1150 it = iter(os)
1150 it = iter(os)
1151 for x in xrange(lim):
1151 for x in xrange(lim):
1152 try:
1152 try:
1153 y = it.next()
1153 y = it.next()
1154 if y in ss:
1154 if y in ss:
1155 result.append(y)
1155 result.append(y)
1156 except (StopIteration):
1156 except (StopIteration):
1157 break
1157 break
1158 return baseset(result)
1158 return baseset(result)
1159
1159
1160 def last(repo, subset, x):
1160 def last(repo, subset, x):
1161 """``last(set, [n])``
1161 """``last(set, [n])``
1162 Last n members of set, defaulting to 1.
1162 Last n members of set, defaulting to 1.
1163 """
1163 """
1164 # i18n: "last" is a keyword
1164 # i18n: "last" is a keyword
1165 l = getargs(x, 1, 2, _("last requires one or two arguments"))
1165 l = getargs(x, 1, 2, _("last requires one or two arguments"))
1166 try:
1166 try:
1167 lim = 1
1167 lim = 1
1168 if len(l) == 2:
1168 if len(l) == 2:
1169 # i18n: "last" is a keyword
1169 # i18n: "last" is a keyword
1170 lim = int(getstring(l[1], _("last requires a number")))
1170 lim = int(getstring(l[1], _("last requires a number")))
1171 except (TypeError, ValueError):
1171 except (TypeError, ValueError):
1172 # i18n: "last" is a keyword
1172 # i18n: "last" is a keyword
1173 raise error.ParseError(_("last expects a number"))
1173 raise error.ParseError(_("last expects a number"))
1174 ss = subset
1174 ss = subset
1175 os = getset(repo, fullreposet(repo), l[0])
1175 os = getset(repo, fullreposet(repo), l[0])
1176 os.reverse()
1176 os.reverse()
1177 result = []
1177 result = []
1178 it = iter(os)
1178 it = iter(os)
1179 for x in xrange(lim):
1179 for x in xrange(lim):
1180 try:
1180 try:
1181 y = it.next()
1181 y = it.next()
1182 if y in ss:
1182 if y in ss:
1183 result.append(y)
1183 result.append(y)
1184 except (StopIteration):
1184 except (StopIteration):
1185 break
1185 break
1186 return baseset(result)
1186 return baseset(result)
1187
1187
1188 def maxrev(repo, subset, x):
1188 def maxrev(repo, subset, x):
1189 """``max(set)``
1189 """``max(set)``
1190 Changeset with highest revision number in set.
1190 Changeset with highest revision number in set.
1191 """
1191 """
1192 os = getset(repo, fullreposet(repo), x)
1192 os = getset(repo, fullreposet(repo), x)
1193 if os:
1193 if os:
1194 m = os.max()
1194 m = os.max()
1195 if m in subset:
1195 if m in subset:
1196 return baseset([m])
1196 return baseset([m])
1197 return baseset()
1197 return baseset()
1198
1198
1199 def merge(repo, subset, x):
1199 def merge(repo, subset, x):
1200 """``merge()``
1200 """``merge()``
1201 Changeset is a merge changeset.
1201 Changeset is a merge changeset.
1202 """
1202 """
1203 # i18n: "merge" is a keyword
1203 # i18n: "merge" is a keyword
1204 getargs(x, 0, 0, _("merge takes no arguments"))
1204 getargs(x, 0, 0, _("merge takes no arguments"))
1205 cl = repo.changelog
1205 cl = repo.changelog
1206 return subset.filter(lambda r: cl.parentrevs(r)[1] != -1)
1206 return subset.filter(lambda r: cl.parentrevs(r)[1] != -1)
1207
1207
1208 def branchpoint(repo, subset, x):
1208 def branchpoint(repo, subset, x):
1209 """``branchpoint()``
1209 """``branchpoint()``
1210 Changesets with more than one child.
1210 Changesets with more than one child.
1211 """
1211 """
1212 # i18n: "branchpoint" is a keyword
1212 # i18n: "branchpoint" is a keyword
1213 getargs(x, 0, 0, _("branchpoint takes no arguments"))
1213 getargs(x, 0, 0, _("branchpoint takes no arguments"))
1214 cl = repo.changelog
1214 cl = repo.changelog
1215 if not subset:
1215 if not subset:
1216 return baseset()
1216 return baseset()
1217 baserev = min(subset)
1217 baserev = min(subset)
1218 parentscount = [0]*(len(repo) - baserev)
1218 parentscount = [0]*(len(repo) - baserev)
1219 for r in cl.revs(start=baserev + 1):
1219 for r in cl.revs(start=baserev + 1):
1220 for p in cl.parentrevs(r):
1220 for p in cl.parentrevs(r):
1221 if p >= baserev:
1221 if p >= baserev:
1222 parentscount[p - baserev] += 1
1222 parentscount[p - baserev] += 1
1223 return subset.filter(lambda r: parentscount[r - baserev] > 1)
1223 return subset.filter(lambda r: parentscount[r - baserev] > 1)
1224
1224
1225 def minrev(repo, subset, x):
1225 def minrev(repo, subset, x):
1226 """``min(set)``
1226 """``min(set)``
1227 Changeset with lowest revision number in set.
1227 Changeset with lowest revision number in set.
1228 """
1228 """
1229 os = getset(repo, fullreposet(repo), x)
1229 os = getset(repo, fullreposet(repo), x)
1230 if os:
1230 if os:
1231 m = os.min()
1231 m = os.min()
1232 if m in subset:
1232 if m in subset:
1233 return baseset([m])
1233 return baseset([m])
1234 return baseset()
1234 return baseset()
1235
1235
1236 def modifies(repo, subset, x):
1236 def modifies(repo, subset, x):
1237 """``modifies(pattern)``
1237 """``modifies(pattern)``
1238 Changesets modifying files matched by pattern.
1238 Changesets modifying files matched by pattern.
1239
1239
1240 The pattern without explicit kind like ``glob:`` is expected to be
1240 The pattern without explicit kind like ``glob:`` is expected to be
1241 relative to the current directory and match against a file or a
1241 relative to the current directory and match against a file or a
1242 directory.
1242 directory.
1243 """
1243 """
1244 # i18n: "modifies" is a keyword
1244 # i18n: "modifies" is a keyword
1245 pat = getstring(x, _("modifies requires a pattern"))
1245 pat = getstring(x, _("modifies requires a pattern"))
1246 return checkstatus(repo, subset, pat, 0)
1246 return checkstatus(repo, subset, pat, 0)
1247
1247
1248 def named(repo, subset, x):
1248 def named(repo, subset, x):
1249 """``named(namespace)``
1249 """``named(namespace)``
1250 The changesets in a given namespace.
1250 The changesets in a given namespace.
1251
1251
1252 If `namespace` starts with `re:`, the remainder of the string is treated as
1252 If `namespace` starts with `re:`, the remainder of the string is treated as
1253 a regular expression. To match a namespace that actually starts with `re:`,
1253 a regular expression. To match a namespace that actually starts with `re:`,
1254 use the prefix `literal:`.
1254 use the prefix `literal:`.
1255 """
1255 """
1256 # i18n: "named" is a keyword
1256 # i18n: "named" is a keyword
1257 args = getargs(x, 1, 1, _('named requires a namespace argument'))
1257 args = getargs(x, 1, 1, _('named requires a namespace argument'))
1258
1258
1259 ns = getstring(args[0],
1259 ns = getstring(args[0],
1260 # i18n: "named" is a keyword
1260 # i18n: "named" is a keyword
1261 _('the argument to named must be a string'))
1261 _('the argument to named must be a string'))
1262 kind, pattern, matcher = _stringmatcher(ns)
1262 kind, pattern, matcher = _stringmatcher(ns)
1263 namespaces = set()
1263 namespaces = set()
1264 if kind == 'literal':
1264 if kind == 'literal':
1265 if pattern not in repo.names:
1265 if pattern not in repo.names:
1266 raise error.RepoLookupError(_("namespace '%s' does not exist")
1266 raise error.RepoLookupError(_("namespace '%s' does not exist")
1267 % ns)
1267 % ns)
1268 namespaces.add(repo.names[pattern])
1268 namespaces.add(repo.names[pattern])
1269 else:
1269 else:
1270 for name, ns in repo.names.iteritems():
1270 for name, ns in repo.names.iteritems():
1271 if matcher(name):
1271 if matcher(name):
1272 namespaces.add(ns)
1272 namespaces.add(ns)
1273 if not namespaces:
1273 if not namespaces:
1274 raise error.RepoLookupError(_("no namespace exists"
1274 raise error.RepoLookupError(_("no namespace exists"
1275 " that match '%s'") % pattern)
1275 " that match '%s'") % pattern)
1276
1276
1277 names = set()
1277 names = set()
1278 for ns in namespaces:
1278 for ns in namespaces:
1279 for name in ns.listnames(repo):
1279 for name in ns.listnames(repo):
1280 if name not in ns.deprecated:
1280 if name not in ns.deprecated:
1281 names.update(repo[n].rev() for n in ns.nodes(repo, name))
1281 names.update(repo[n].rev() for n in ns.nodes(repo, name))
1282
1282
1283 names -= set([node.nullrev])
1283 names -= set([node.nullrev])
1284 return subset & names
1284 return subset & names
1285
1285
1286 def node_(repo, subset, x):
1286 def node_(repo, subset, x):
1287 """``id(string)``
1287 """``id(string)``
1288 Revision non-ambiguously specified by the given hex string prefix.
1288 Revision non-ambiguously specified by the given hex string prefix.
1289 """
1289 """
1290 # i18n: "id" is a keyword
1290 # i18n: "id" is a keyword
1291 l = getargs(x, 1, 1, _("id requires one argument"))
1291 l = getargs(x, 1, 1, _("id requires one argument"))
1292 # i18n: "id" is a keyword
1292 # i18n: "id" is a keyword
1293 n = getstring(l[0], _("id requires a string"))
1293 n = getstring(l[0], _("id requires a string"))
1294 if len(n) == 40:
1294 if len(n) == 40:
1295 rn = repo[n].rev()
1295 rn = repo[n].rev()
1296 else:
1296 else:
1297 rn = None
1297 rn = None
1298 pm = repo.changelog._partialmatch(n)
1298 pm = repo.changelog._partialmatch(n)
1299 if pm is not None:
1299 if pm is not None:
1300 rn = repo.changelog.rev(pm)
1300 rn = repo.changelog.rev(pm)
1301
1301
1302 if rn is None:
1302 if rn is None:
1303 return baseset()
1303 return baseset()
1304 result = baseset([rn])
1304 result = baseset([rn])
1305 return result & subset
1305 return result & subset
1306
1306
1307 def obsolete(repo, subset, x):
1307 def obsolete(repo, subset, x):
1308 """``obsolete()``
1308 """``obsolete()``
1309 Mutable changeset with a newer version."""
1309 Mutable changeset with a newer version."""
1310 # i18n: "obsolete" is a keyword
1310 # i18n: "obsolete" is a keyword
1311 getargs(x, 0, 0, _("obsolete takes no arguments"))
1311 getargs(x, 0, 0, _("obsolete takes no arguments"))
1312 obsoletes = obsmod.getrevs(repo, 'obsolete')
1312 obsoletes = obsmod.getrevs(repo, 'obsolete')
1313 return subset & obsoletes
1313 return subset & obsoletes
1314
1314
1315 def only(repo, subset, x):
1315 def only(repo, subset, x):
1316 """``only(set, [set])``
1316 """``only(set, [set])``
1317 Changesets that are ancestors of the first set that are not ancestors
1317 Changesets that are ancestors of the first set that are not ancestors
1318 of any other head in the repo. If a second set is specified, the result
1318 of any other head in the repo. If a second set is specified, the result
1319 is ancestors of the first set that are not ancestors of the second set
1319 is ancestors of the first set that are not ancestors of the second set
1320 (i.e. ::<set1> - ::<set2>).
1320 (i.e. ::<set1> - ::<set2>).
1321 """
1321 """
1322 cl = repo.changelog
1322 cl = repo.changelog
1323 # i18n: "only" is a keyword
1323 # i18n: "only" is a keyword
1324 args = getargs(x, 1, 2, _('only takes one or two arguments'))
1324 args = getargs(x, 1, 2, _('only takes one or two arguments'))
1325 include = getset(repo, fullreposet(repo), args[0])
1325 include = getset(repo, fullreposet(repo), args[0])
1326 if len(args) == 1:
1326 if len(args) == 1:
1327 if not include:
1327 if not include:
1328 return baseset()
1328 return baseset()
1329
1329
1330 descendants = set(_revdescendants(repo, include, False))
1330 descendants = set(_revdescendants(repo, include, False))
1331 exclude = [rev for rev in cl.headrevs()
1331 exclude = [rev for rev in cl.headrevs()
1332 if not rev in descendants and not rev in include]
1332 if not rev in descendants and not rev in include]
1333 else:
1333 else:
1334 exclude = getset(repo, fullreposet(repo), args[1])
1334 exclude = getset(repo, fullreposet(repo), args[1])
1335
1335
1336 results = set(cl.findmissingrevs(common=exclude, heads=include))
1336 results = set(cl.findmissingrevs(common=exclude, heads=include))
1337 return subset & results
1337 return subset & results
1338
1338
1339 def origin(repo, subset, x):
1339 def origin(repo, subset, x):
1340 """``origin([set])``
1340 """``origin([set])``
1341 Changesets that were specified as a source for the grafts, transplants or
1341 Changesets that were specified as a source for the grafts, transplants or
1342 rebases that created the given revisions. Omitting the optional set is the
1342 rebases that created the given revisions. Omitting the optional set is the
1343 same as passing all(). If a changeset created by these operations is itself
1343 same as passing all(). If a changeset created by these operations is itself
1344 specified as a source for one of these operations, only the source changeset
1344 specified as a source for one of these operations, only the source changeset
1345 for the first operation is selected.
1345 for the first operation is selected.
1346 """
1346 """
1347 if x is not None:
1347 if x is not None:
1348 dests = getset(repo, fullreposet(repo), x)
1348 dests = getset(repo, fullreposet(repo), x)
1349 else:
1349 else:
1350 dests = fullreposet(repo)
1350 dests = fullreposet(repo)
1351
1351
1352 def _firstsrc(rev):
1352 def _firstsrc(rev):
1353 src = _getrevsource(repo, rev)
1353 src = _getrevsource(repo, rev)
1354 if src is None:
1354 if src is None:
1355 return None
1355 return None
1356
1356
1357 while True:
1357 while True:
1358 prev = _getrevsource(repo, src)
1358 prev = _getrevsource(repo, src)
1359
1359
1360 if prev is None:
1360 if prev is None:
1361 return src
1361 return src
1362 src = prev
1362 src = prev
1363
1363
1364 o = set([_firstsrc(r) for r in dests])
1364 o = set([_firstsrc(r) for r in dests])
1365 o -= set([None])
1365 o -= set([None])
1366 return subset & o
1366 return subset & o
1367
1367
1368 def outgoing(repo, subset, x):
1368 def outgoing(repo, subset, x):
1369 """``outgoing([path])``
1369 """``outgoing([path])``
1370 Changesets not found in the specified destination repository, or the
1370 Changesets not found in the specified destination repository, or the
1371 default push location.
1371 default push location.
1372 """
1372 """
1373 import hg # avoid start-up nasties
1373 import hg # avoid start-up nasties
1374 # i18n: "outgoing" is a keyword
1374 # i18n: "outgoing" is a keyword
1375 l = getargs(x, 0, 1, _("outgoing takes one or no arguments"))
1375 l = getargs(x, 0, 1, _("outgoing takes one or no arguments"))
1376 # i18n: "outgoing" is a keyword
1376 # i18n: "outgoing" is a keyword
1377 dest = l and getstring(l[0], _("outgoing requires a repository path")) or ''
1377 dest = l and getstring(l[0], _("outgoing requires a repository path")) or ''
1378 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
1378 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
1379 dest, branches = hg.parseurl(dest)
1379 dest, branches = hg.parseurl(dest)
1380 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1380 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1381 if revs:
1381 if revs:
1382 revs = [repo.lookup(rev) for rev in revs]
1382 revs = [repo.lookup(rev) for rev in revs]
1383 other = hg.peer(repo, {}, dest)
1383 other = hg.peer(repo, {}, dest)
1384 repo.ui.pushbuffer()
1384 repo.ui.pushbuffer()
1385 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs)
1385 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs)
1386 repo.ui.popbuffer()
1386 repo.ui.popbuffer()
1387 cl = repo.changelog
1387 cl = repo.changelog
1388 o = set([cl.rev(r) for r in outgoing.missing])
1388 o = set([cl.rev(r) for r in outgoing.missing])
1389 return subset & o
1389 return subset & o
1390
1390
1391 def p1(repo, subset, x):
1391 def p1(repo, subset, x):
1392 """``p1([set])``
1392 """``p1([set])``
1393 First parent of changesets in set, or the working directory.
1393 First parent of changesets in set, or the working directory.
1394 """
1394 """
1395 if x is None:
1395 if x is None:
1396 p = repo[x].p1().rev()
1396 p = repo[x].p1().rev()
1397 if p >= 0:
1397 if p >= 0:
1398 return subset & baseset([p])
1398 return subset & baseset([p])
1399 return baseset()
1399 return baseset()
1400
1400
1401 ps = set()
1401 ps = set()
1402 cl = repo.changelog
1402 cl = repo.changelog
1403 for r in getset(repo, fullreposet(repo), x):
1403 for r in getset(repo, fullreposet(repo), x):
1404 ps.add(cl.parentrevs(r)[0])
1404 ps.add(cl.parentrevs(r)[0])
1405 ps -= set([node.nullrev])
1405 ps -= set([node.nullrev])
1406 return subset & ps
1406 return subset & ps
1407
1407
1408 def p2(repo, subset, x):
1408 def p2(repo, subset, x):
1409 """``p2([set])``
1409 """``p2([set])``
1410 Second parent of changesets in set, or the working directory.
1410 Second parent of changesets in set, or the working directory.
1411 """
1411 """
1412 if x is None:
1412 if x is None:
1413 ps = repo[x].parents()
1413 ps = repo[x].parents()
1414 try:
1414 try:
1415 p = ps[1].rev()
1415 p = ps[1].rev()
1416 if p >= 0:
1416 if p >= 0:
1417 return subset & baseset([p])
1417 return subset & baseset([p])
1418 return baseset()
1418 return baseset()
1419 except IndexError:
1419 except IndexError:
1420 return baseset()
1420 return baseset()
1421
1421
1422 ps = set()
1422 ps = set()
1423 cl = repo.changelog
1423 cl = repo.changelog
1424 for r in getset(repo, fullreposet(repo), x):
1424 for r in getset(repo, fullreposet(repo), x):
1425 ps.add(cl.parentrevs(r)[1])
1425 ps.add(cl.parentrevs(r)[1])
1426 ps -= set([node.nullrev])
1426 ps -= set([node.nullrev])
1427 return subset & ps
1427 return subset & ps
1428
1428
1429 def parents(repo, subset, x):
1429 def parents(repo, subset, x):
1430 """``parents([set])``
1430 """``parents([set])``
1431 The set of all parents for all changesets in set, or the working directory.
1431 The set of all parents for all changesets in set, or the working directory.
1432 """
1432 """
1433 if x is None:
1433 if x is None:
1434 ps = set(p.rev() for p in repo[x].parents())
1434 ps = set(p.rev() for p in repo[x].parents())
1435 else:
1435 else:
1436 ps = set()
1436 ps = set()
1437 cl = repo.changelog
1437 cl = repo.changelog
1438 for r in getset(repo, fullreposet(repo), x):
1438 for r in getset(repo, fullreposet(repo), x):
1439 ps.update(cl.parentrevs(r))
1439 ps.update(cl.parentrevs(r))
1440 ps -= set([node.nullrev])
1440 ps -= set([node.nullrev])
1441 return subset & ps
1441 return subset & ps
1442
1442
1443 def parentspec(repo, subset, x, n):
1443 def parentspec(repo, subset, x, n):
1444 """``set^0``
1444 """``set^0``
1445 The set.
1445 The set.
1446 ``set^1`` (or ``set^``), ``set^2``
1446 ``set^1`` (or ``set^``), ``set^2``
1447 First or second parent, respectively, of all changesets in set.
1447 First or second parent, respectively, of all changesets in set.
1448 """
1448 """
1449 try:
1449 try:
1450 n = int(n[1])
1450 n = int(n[1])
1451 if n not in (0, 1, 2):
1451 if n not in (0, 1, 2):
1452 raise ValueError
1452 raise ValueError
1453 except (TypeError, ValueError):
1453 except (TypeError, ValueError):
1454 raise error.ParseError(_("^ expects a number 0, 1, or 2"))
1454 raise error.ParseError(_("^ expects a number 0, 1, or 2"))
1455 ps = set()
1455 ps = set()
1456 cl = repo.changelog
1456 cl = repo.changelog
1457 for r in getset(repo, fullreposet(repo), x):
1457 for r in getset(repo, fullreposet(repo), x):
1458 if n == 0:
1458 if n == 0:
1459 ps.add(r)
1459 ps.add(r)
1460 elif n == 1:
1460 elif n == 1:
1461 ps.add(cl.parentrevs(r)[0])
1461 ps.add(cl.parentrevs(r)[0])
1462 elif n == 2:
1462 elif n == 2:
1463 parents = cl.parentrevs(r)
1463 parents = cl.parentrevs(r)
1464 if len(parents) > 1:
1464 if len(parents) > 1:
1465 ps.add(parents[1])
1465 ps.add(parents[1])
1466 return subset & ps
1466 return subset & ps
1467
1467
1468 def present(repo, subset, x):
1468 def present(repo, subset, x):
1469 """``present(set)``
1469 """``present(set)``
1470 An empty set, if any revision in set isn't found; otherwise,
1470 An empty set, if any revision in set isn't found; otherwise,
1471 all revisions in set.
1471 all revisions in set.
1472
1472
1473 If any of specified revisions is not present in the local repository,
1473 If any of specified revisions is not present in the local repository,
1474 the query is normally aborted. But this predicate allows the query
1474 the query is normally aborted. But this predicate allows the query
1475 to continue even in such cases.
1475 to continue even in such cases.
1476 """
1476 """
1477 try:
1477 try:
1478 return getset(repo, subset, x)
1478 return getset(repo, subset, x)
1479 except error.RepoLookupError:
1479 except error.RepoLookupError:
1480 return baseset()
1480 return baseset()
1481
1481
1482 def public(repo, subset, x):
1482 def public(repo, subset, x):
1483 """``public()``
1483 """``public()``
1484 Changeset in public phase."""
1484 Changeset in public phase."""
1485 # i18n: "public" is a keyword
1485 # i18n: "public" is a keyword
1486 getargs(x, 0, 0, _("public takes no arguments"))
1486 getargs(x, 0, 0, _("public takes no arguments"))
1487 phase = repo._phasecache.phase
1487 phase = repo._phasecache.phase
1488 target = phases.public
1488 target = phases.public
1489 condition = lambda r: phase(repo, r) == target
1489 condition = lambda r: phase(repo, r) == target
1490 return subset.filter(condition, cache=False)
1490 return subset.filter(condition, cache=False)
1491
1491
1492 def remote(repo, subset, x):
1492 def remote(repo, subset, x):
1493 """``remote([id [,path]])``
1493 """``remote([id [,path]])``
1494 Local revision that corresponds to the given identifier in a
1494 Local revision that corresponds to the given identifier in a
1495 remote repository, if present. Here, the '.' identifier is a
1495 remote repository, if present. Here, the '.' identifier is a
1496 synonym for the current local branch.
1496 synonym for the current local branch.
1497 """
1497 """
1498
1498
1499 import hg # avoid start-up nasties
1499 import hg # avoid start-up nasties
1500 # i18n: "remote" is a keyword
1500 # i18n: "remote" is a keyword
1501 l = getargs(x, 0, 2, _("remote takes one, two or no arguments"))
1501 l = getargs(x, 0, 2, _("remote takes one, two or no arguments"))
1502
1502
1503 q = '.'
1503 q = '.'
1504 if len(l) > 0:
1504 if len(l) > 0:
1505 # i18n: "remote" is a keyword
1505 # i18n: "remote" is a keyword
1506 q = getstring(l[0], _("remote requires a string id"))
1506 q = getstring(l[0], _("remote requires a string id"))
1507 if q == '.':
1507 if q == '.':
1508 q = repo['.'].branch()
1508 q = repo['.'].branch()
1509
1509
1510 dest = ''
1510 dest = ''
1511 if len(l) > 1:
1511 if len(l) > 1:
1512 # i18n: "remote" is a keyword
1512 # i18n: "remote" is a keyword
1513 dest = getstring(l[1], _("remote requires a repository path"))
1513 dest = getstring(l[1], _("remote requires a repository path"))
1514 dest = repo.ui.expandpath(dest or 'default')
1514 dest = repo.ui.expandpath(dest or 'default')
1515 dest, branches = hg.parseurl(dest)
1515 dest, branches = hg.parseurl(dest)
1516 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1516 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1517 if revs:
1517 if revs:
1518 revs = [repo.lookup(rev) for rev in revs]
1518 revs = [repo.lookup(rev) for rev in revs]
1519 other = hg.peer(repo, {}, dest)
1519 other = hg.peer(repo, {}, dest)
1520 n = other.lookup(q)
1520 n = other.lookup(q)
1521 if n in repo:
1521 if n in repo:
1522 r = repo[n].rev()
1522 r = repo[n].rev()
1523 if r in subset:
1523 if r in subset:
1524 return baseset([r])
1524 return baseset([r])
1525 return baseset()
1525 return baseset()
1526
1526
1527 def removes(repo, subset, x):
1527 def removes(repo, subset, x):
1528 """``removes(pattern)``
1528 """``removes(pattern)``
1529 Changesets which remove files matching pattern.
1529 Changesets which remove files matching pattern.
1530
1530
1531 The pattern without explicit kind like ``glob:`` is expected to be
1531 The pattern without explicit kind like ``glob:`` is expected to be
1532 relative to the current directory and match against a file or a
1532 relative to the current directory and match against a file or a
1533 directory.
1533 directory.
1534 """
1534 """
1535 # i18n: "removes" is a keyword
1535 # i18n: "removes" is a keyword
1536 pat = getstring(x, _("removes requires a pattern"))
1536 pat = getstring(x, _("removes requires a pattern"))
1537 return checkstatus(repo, subset, pat, 2)
1537 return checkstatus(repo, subset, pat, 2)
1538
1538
1539 def rev(repo, subset, x):
1539 def rev(repo, subset, x):
1540 """``rev(number)``
1540 """``rev(number)``
1541 Revision with the given numeric identifier.
1541 Revision with the given numeric identifier.
1542 """
1542 """
1543 # i18n: "rev" is a keyword
1543 # i18n: "rev" is a keyword
1544 l = getargs(x, 1, 1, _("rev requires one argument"))
1544 l = getargs(x, 1, 1, _("rev requires one argument"))
1545 try:
1545 try:
1546 # i18n: "rev" is a keyword
1546 # i18n: "rev" is a keyword
1547 l = int(getstring(l[0], _("rev requires a number")))
1547 l = int(getstring(l[0], _("rev requires a number")))
1548 except (TypeError, ValueError):
1548 except (TypeError, ValueError):
1549 # i18n: "rev" is a keyword
1549 # i18n: "rev" is a keyword
1550 raise error.ParseError(_("rev expects a number"))
1550 raise error.ParseError(_("rev expects a number"))
1551 if l not in repo.changelog and l != node.nullrev:
1551 if l not in repo.changelog and l != node.nullrev:
1552 return baseset()
1552 return baseset()
1553 return subset & baseset([l])
1553 return subset & baseset([l])
1554
1554
1555 def matching(repo, subset, x):
1555 def matching(repo, subset, x):
1556 """``matching(revision [, field])``
1556 """``matching(revision [, field])``
1557 Changesets in which a given set of fields match the set of fields in the
1557 Changesets in which a given set of fields match the set of fields in the
1558 selected revision or set.
1558 selected revision or set.
1559
1559
1560 To match more than one field pass the list of fields to match separated
1560 To match more than one field pass the list of fields to match separated
1561 by spaces (e.g. ``author description``).
1561 by spaces (e.g. ``author description``).
1562
1562
1563 Valid fields are most regular revision fields and some special fields.
1563 Valid fields are most regular revision fields and some special fields.
1564
1564
1565 Regular revision fields are ``description``, ``author``, ``branch``,
1565 Regular revision fields are ``description``, ``author``, ``branch``,
1566 ``date``, ``files``, ``phase``, ``parents``, ``substate``, ``user``
1566 ``date``, ``files``, ``phase``, ``parents``, ``substate``, ``user``
1567 and ``diff``.
1567 and ``diff``.
1568 Note that ``author`` and ``user`` are synonyms. ``diff`` refers to the
1568 Note that ``author`` and ``user`` are synonyms. ``diff`` refers to the
1569 contents of the revision. Two revisions matching their ``diff`` will
1569 contents of the revision. Two revisions matching their ``diff`` will
1570 also match their ``files``.
1570 also match their ``files``.
1571
1571
1572 Special fields are ``summary`` and ``metadata``:
1572 Special fields are ``summary`` and ``metadata``:
1573 ``summary`` matches the first line of the description.
1573 ``summary`` matches the first line of the description.
1574 ``metadata`` is equivalent to matching ``description user date``
1574 ``metadata`` is equivalent to matching ``description user date``
1575 (i.e. it matches the main metadata fields).
1575 (i.e. it matches the main metadata fields).
1576
1576
1577 ``metadata`` is the default field which is used when no fields are
1577 ``metadata`` is the default field which is used when no fields are
1578 specified. You can match more than one field at a time.
1578 specified. You can match more than one field at a time.
1579 """
1579 """
1580 # i18n: "matching" is a keyword
1580 # i18n: "matching" is a keyword
1581 l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
1581 l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
1582
1582
1583 revs = getset(repo, fullreposet(repo), l[0])
1583 revs = getset(repo, fullreposet(repo), l[0])
1584
1584
1585 fieldlist = ['metadata']
1585 fieldlist = ['metadata']
1586 if len(l) > 1:
1586 if len(l) > 1:
1587 fieldlist = getstring(l[1],
1587 fieldlist = getstring(l[1],
1588 # i18n: "matching" is a keyword
1588 # i18n: "matching" is a keyword
1589 _("matching requires a string "
1589 _("matching requires a string "
1590 "as its second argument")).split()
1590 "as its second argument")).split()
1591
1591
1592 # Make sure that there are no repeated fields,
1592 # Make sure that there are no repeated fields,
1593 # expand the 'special' 'metadata' field type
1593 # expand the 'special' 'metadata' field type
1594 # and check the 'files' whenever we check the 'diff'
1594 # and check the 'files' whenever we check the 'diff'
1595 fields = []
1595 fields = []
1596 for field in fieldlist:
1596 for field in fieldlist:
1597 if field == 'metadata':
1597 if field == 'metadata':
1598 fields += ['user', 'description', 'date']
1598 fields += ['user', 'description', 'date']
1599 elif field == 'diff':
1599 elif field == 'diff':
1600 # a revision matching the diff must also match the files
1600 # a revision matching the diff must also match the files
1601 # since matching the diff is very costly, make sure to
1601 # since matching the diff is very costly, make sure to
1602 # also match the files first
1602 # also match the files first
1603 fields += ['files', 'diff']
1603 fields += ['files', 'diff']
1604 else:
1604 else:
1605 if field == 'author':
1605 if field == 'author':
1606 field = 'user'
1606 field = 'user'
1607 fields.append(field)
1607 fields.append(field)
1608 fields = set(fields)
1608 fields = set(fields)
1609 if 'summary' in fields and 'description' in fields:
1609 if 'summary' in fields and 'description' in fields:
1610 # If a revision matches its description it also matches its summary
1610 # If a revision matches its description it also matches its summary
1611 fields.discard('summary')
1611 fields.discard('summary')
1612
1612
1613 # We may want to match more than one field
1613 # We may want to match more than one field
1614 # Not all fields take the same amount of time to be matched
1614 # Not all fields take the same amount of time to be matched
1615 # Sort the selected fields in order of increasing matching cost
1615 # Sort the selected fields in order of increasing matching cost
1616 fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary',
1616 fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary',
1617 'files', 'description', 'substate', 'diff']
1617 'files', 'description', 'substate', 'diff']
1618 def fieldkeyfunc(f):
1618 def fieldkeyfunc(f):
1619 try:
1619 try:
1620 return fieldorder.index(f)
1620 return fieldorder.index(f)
1621 except ValueError:
1621 except ValueError:
1622 # assume an unknown field is very costly
1622 # assume an unknown field is very costly
1623 return len(fieldorder)
1623 return len(fieldorder)
1624 fields = list(fields)
1624 fields = list(fields)
1625 fields.sort(key=fieldkeyfunc)
1625 fields.sort(key=fieldkeyfunc)
1626
1626
1627 # Each field will be matched with its own "getfield" function
1627 # Each field will be matched with its own "getfield" function
1628 # which will be added to the getfieldfuncs array of functions
1628 # which will be added to the getfieldfuncs array of functions
1629 getfieldfuncs = []
1629 getfieldfuncs = []
1630 _funcs = {
1630 _funcs = {
1631 'user': lambda r: repo[r].user(),
1631 'user': lambda r: repo[r].user(),
1632 'branch': lambda r: repo[r].branch(),
1632 'branch': lambda r: repo[r].branch(),
1633 'date': lambda r: repo[r].date(),
1633 'date': lambda r: repo[r].date(),
1634 'description': lambda r: repo[r].description(),
1634 'description': lambda r: repo[r].description(),
1635 'files': lambda r: repo[r].files(),
1635 'files': lambda r: repo[r].files(),
1636 'parents': lambda r: repo[r].parents(),
1636 'parents': lambda r: repo[r].parents(),
1637 'phase': lambda r: repo[r].phase(),
1637 'phase': lambda r: repo[r].phase(),
1638 'substate': lambda r: repo[r].substate,
1638 'substate': lambda r: repo[r].substate,
1639 'summary': lambda r: repo[r].description().splitlines()[0],
1639 'summary': lambda r: repo[r].description().splitlines()[0],
1640 'diff': lambda r: list(repo[r].diff(git=True),)
1640 'diff': lambda r: list(repo[r].diff(git=True),)
1641 }
1641 }
1642 for info in fields:
1642 for info in fields:
1643 getfield = _funcs.get(info, None)
1643 getfield = _funcs.get(info, None)
1644 if getfield is None:
1644 if getfield is None:
1645 raise error.ParseError(
1645 raise error.ParseError(
1646 # i18n: "matching" is a keyword
1646 # i18n: "matching" is a keyword
1647 _("unexpected field name passed to matching: %s") % info)
1647 _("unexpected field name passed to matching: %s") % info)
1648 getfieldfuncs.append(getfield)
1648 getfieldfuncs.append(getfield)
1649 # convert the getfield array of functions into a "getinfo" function
1649 # convert the getfield array of functions into a "getinfo" function
1650 # which returns an array of field values (or a single value if there
1650 # which returns an array of field values (or a single value if there
1651 # is only one field to match)
1651 # is only one field to match)
1652 getinfo = lambda r: [f(r) for f in getfieldfuncs]
1652 getinfo = lambda r: [f(r) for f in getfieldfuncs]
1653
1653
1654 def matches(x):
1654 def matches(x):
1655 for rev in revs:
1655 for rev in revs:
1656 target = getinfo(rev)
1656 target = getinfo(rev)
1657 match = True
1657 match = True
1658 for n, f in enumerate(getfieldfuncs):
1658 for n, f in enumerate(getfieldfuncs):
1659 if target[n] != f(x):
1659 if target[n] != f(x):
1660 match = False
1660 match = False
1661 if match:
1661 if match:
1662 return True
1662 return True
1663 return False
1663 return False
1664
1664
1665 return subset.filter(matches)
1665 return subset.filter(matches)
1666
1666
1667 def reverse(repo, subset, x):
1667 def reverse(repo, subset, x):
1668 """``reverse(set)``
1668 """``reverse(set)``
1669 Reverse order of set.
1669 Reverse order of set.
1670 """
1670 """
1671 l = getset(repo, subset, x)
1671 l = getset(repo, subset, x)
1672 l.reverse()
1672 l.reverse()
1673 return l
1673 return l
1674
1674
1675 def roots(repo, subset, x):
1675 def roots(repo, subset, x):
1676 """``roots(set)``
1676 """``roots(set)``
1677 Changesets in set with no parent changeset in set.
1677 Changesets in set with no parent changeset in set.
1678 """
1678 """
1679 s = getset(repo, fullreposet(repo), x)
1679 s = getset(repo, fullreposet(repo), x)
1680 subset = baseset([r for r in s if r in subset])
1680 subset = baseset([r for r in s if r in subset])
1681 cs = _children(repo, subset, s)
1681 cs = _children(repo, subset, s)
1682 return subset - cs
1682 return subset - cs
1683
1683
1684 def secret(repo, subset, x):
1684 def secret(repo, subset, x):
1685 """``secret()``
1685 """``secret()``
1686 Changeset in secret phase."""
1686 Changeset in secret phase."""
1687 # i18n: "secret" is a keyword
1687 # i18n: "secret" is a keyword
1688 getargs(x, 0, 0, _("secret takes no arguments"))
1688 getargs(x, 0, 0, _("secret takes no arguments"))
1689 phase = repo._phasecache.phase
1689 phase = repo._phasecache.phase
1690 target = phases.secret
1690 target = phases.secret
1691 condition = lambda r: phase(repo, r) == target
1691 condition = lambda r: phase(repo, r) == target
1692 return subset.filter(condition, cache=False)
1692 return subset.filter(condition, cache=False)
1693
1693
1694 def sort(repo, subset, x):
1694 def sort(repo, subset, x):
1695 """``sort(set[, [-]key...])``
1695 """``sort(set[, [-]key...])``
1696 Sort set by keys. The default sort order is ascending, specify a key
1696 Sort set by keys. The default sort order is ascending, specify a key
1697 as ``-key`` to sort in descending order.
1697 as ``-key`` to sort in descending order.
1698
1698
1699 The keys can be:
1699 The keys can be:
1700
1700
1701 - ``rev`` for the revision number,
1701 - ``rev`` for the revision number,
1702 - ``branch`` for the branch name,
1702 - ``branch`` for the branch name,
1703 - ``desc`` for the commit message (description),
1703 - ``desc`` for the commit message (description),
1704 - ``user`` for user name (``author`` can be used as an alias),
1704 - ``user`` for user name (``author`` can be used as an alias),
1705 - ``date`` for the commit date
1705 - ``date`` for the commit date
1706 """
1706 """
1707 # i18n: "sort" is a keyword
1707 # i18n: "sort" is a keyword
1708 l = getargs(x, 1, 2, _("sort requires one or two arguments"))
1708 l = getargs(x, 1, 2, _("sort requires one or two arguments"))
1709 keys = "rev"
1709 keys = "rev"
1710 if len(l) == 2:
1710 if len(l) == 2:
1711 # i18n: "sort" is a keyword
1711 # i18n: "sort" is a keyword
1712 keys = getstring(l[1], _("sort spec must be a string"))
1712 keys = getstring(l[1], _("sort spec must be a string"))
1713
1713
1714 s = l[0]
1714 s = l[0]
1715 keys = keys.split()
1715 keys = keys.split()
1716 l = []
1716 l = []
1717 def invert(s):
1717 def invert(s):
1718 return "".join(chr(255 - ord(c)) for c in s)
1718 return "".join(chr(255 - ord(c)) for c in s)
1719 revs = getset(repo, subset, s)
1719 revs = getset(repo, subset, s)
1720 if keys == ["rev"]:
1720 if keys == ["rev"]:
1721 revs.sort()
1721 revs.sort()
1722 return revs
1722 return revs
1723 elif keys == ["-rev"]:
1723 elif keys == ["-rev"]:
1724 revs.sort(reverse=True)
1724 revs.sort(reverse=True)
1725 return revs
1725 return revs
1726 for r in revs:
1726 for r in revs:
1727 c = repo[r]
1727 c = repo[r]
1728 e = []
1728 e = []
1729 for k in keys:
1729 for k in keys:
1730 if k == 'rev':
1730 if k == 'rev':
1731 e.append(r)
1731 e.append(r)
1732 elif k == '-rev':
1732 elif k == '-rev':
1733 e.append(-r)
1733 e.append(-r)
1734 elif k == 'branch':
1734 elif k == 'branch':
1735 e.append(c.branch())
1735 e.append(c.branch())
1736 elif k == '-branch':
1736 elif k == '-branch':
1737 e.append(invert(c.branch()))
1737 e.append(invert(c.branch()))
1738 elif k == 'desc':
1738 elif k == 'desc':
1739 e.append(c.description())
1739 e.append(c.description())
1740 elif k == '-desc':
1740 elif k == '-desc':
1741 e.append(invert(c.description()))
1741 e.append(invert(c.description()))
1742 elif k in 'user author':
1742 elif k in 'user author':
1743 e.append(c.user())
1743 e.append(c.user())
1744 elif k in '-user -author':
1744 elif k in '-user -author':
1745 e.append(invert(c.user()))
1745 e.append(invert(c.user()))
1746 elif k == 'date':
1746 elif k == 'date':
1747 e.append(c.date()[0])
1747 e.append(c.date()[0])
1748 elif k == '-date':
1748 elif k == '-date':
1749 e.append(-c.date()[0])
1749 e.append(-c.date()[0])
1750 else:
1750 else:
1751 raise error.ParseError(_("unknown sort key %r") % k)
1751 raise error.ParseError(_("unknown sort key %r") % k)
1752 e.append(r)
1752 e.append(r)
1753 l.append(e)
1753 l.append(e)
1754 l.sort()
1754 l.sort()
1755 return baseset([e[-1] for e in l])
1755 return baseset([e[-1] for e in l])
1756
1756
1757 def _stringmatcher(pattern):
1757 def _stringmatcher(pattern):
1758 """
1758 """
1759 accepts a string, possibly starting with 're:' or 'literal:' prefix.
1759 accepts a string, possibly starting with 're:' or 'literal:' prefix.
1760 returns the matcher name, pattern, and matcher function.
1760 returns the matcher name, pattern, and matcher function.
1761 missing or unknown prefixes are treated as literal matches.
1761 missing or unknown prefixes are treated as literal matches.
1762
1762
1763 helper for tests:
1763 helper for tests:
1764 >>> def test(pattern, *tests):
1764 >>> def test(pattern, *tests):
1765 ... kind, pattern, matcher = _stringmatcher(pattern)
1765 ... kind, pattern, matcher = _stringmatcher(pattern)
1766 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
1766 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
1767
1767
1768 exact matching (no prefix):
1768 exact matching (no prefix):
1769 >>> test('abcdefg', 'abc', 'def', 'abcdefg')
1769 >>> test('abcdefg', 'abc', 'def', 'abcdefg')
1770 ('literal', 'abcdefg', [False, False, True])
1770 ('literal', 'abcdefg', [False, False, True])
1771
1771
1772 regex matching ('re:' prefix)
1772 regex matching ('re:' prefix)
1773 >>> test('re:a.+b', 'nomatch', 'fooadef', 'fooadefbar')
1773 >>> test('re:a.+b', 'nomatch', 'fooadef', 'fooadefbar')
1774 ('re', 'a.+b', [False, False, True])
1774 ('re', 'a.+b', [False, False, True])
1775
1775
1776 force exact matches ('literal:' prefix)
1776 force exact matches ('literal:' prefix)
1777 >>> test('literal:re:foobar', 'foobar', 're:foobar')
1777 >>> test('literal:re:foobar', 'foobar', 're:foobar')
1778 ('literal', 're:foobar', [False, True])
1778 ('literal', 're:foobar', [False, True])
1779
1779
1780 unknown prefixes are ignored and treated as literals
1780 unknown prefixes are ignored and treated as literals
1781 >>> test('foo:bar', 'foo', 'bar', 'foo:bar')
1781 >>> test('foo:bar', 'foo', 'bar', 'foo:bar')
1782 ('literal', 'foo:bar', [False, False, True])
1782 ('literal', 'foo:bar', [False, False, True])
1783 """
1783 """
1784 if pattern.startswith('re:'):
1784 if pattern.startswith('re:'):
1785 pattern = pattern[3:]
1785 pattern = pattern[3:]
1786 try:
1786 try:
1787 regex = re.compile(pattern)
1787 regex = re.compile(pattern)
1788 except re.error, e:
1788 except re.error, e:
1789 raise error.ParseError(_('invalid regular expression: %s')
1789 raise error.ParseError(_('invalid regular expression: %s')
1790 % e)
1790 % e)
1791 return 're', pattern, regex.search
1791 return 're', pattern, regex.search
1792 elif pattern.startswith('literal:'):
1792 elif pattern.startswith('literal:'):
1793 pattern = pattern[8:]
1793 pattern = pattern[8:]
1794 return 'literal', pattern, pattern.__eq__
1794 return 'literal', pattern, pattern.__eq__
1795
1795
1796 def _substringmatcher(pattern):
1796 def _substringmatcher(pattern):
1797 kind, pattern, matcher = _stringmatcher(pattern)
1797 kind, pattern, matcher = _stringmatcher(pattern)
1798 if kind == 'literal':
1798 if kind == 'literal':
1799 matcher = lambda s: pattern in s
1799 matcher = lambda s: pattern in s
1800 return kind, pattern, matcher
1800 return kind, pattern, matcher
1801
1801
1802 def tag(repo, subset, x):
1802 def tag(repo, subset, x):
1803 """``tag([name])``
1803 """``tag([name])``
1804 The specified tag by name, or all tagged revisions if no name is given.
1804 The specified tag by name, or all tagged revisions if no name is given.
1805
1805
1806 If `name` starts with `re:`, the remainder of the name is treated as
1806 If `name` starts with `re:`, the remainder of the name is treated as
1807 a regular expression. To match a tag that actually starts with `re:`,
1807 a regular expression. To match a tag that actually starts with `re:`,
1808 use the prefix `literal:`.
1808 use the prefix `literal:`.
1809 """
1809 """
1810 # i18n: "tag" is a keyword
1810 # i18n: "tag" is a keyword
1811 args = getargs(x, 0, 1, _("tag takes one or no arguments"))
1811 args = getargs(x, 0, 1, _("tag takes one or no arguments"))
1812 cl = repo.changelog
1812 cl = repo.changelog
1813 if args:
1813 if args:
1814 pattern = getstring(args[0],
1814 pattern = getstring(args[0],
1815 # i18n: "tag" is a keyword
1815 # i18n: "tag" is a keyword
1816 _('the argument to tag must be a string'))
1816 _('the argument to tag must be a string'))
1817 kind, pattern, matcher = _stringmatcher(pattern)
1817 kind, pattern, matcher = _stringmatcher(pattern)
1818 if kind == 'literal':
1818 if kind == 'literal':
1819 # avoid resolving all tags
1819 # avoid resolving all tags
1820 tn = repo._tagscache.tags.get(pattern, None)
1820 tn = repo._tagscache.tags.get(pattern, None)
1821 if tn is None:
1821 if tn is None:
1822 raise error.RepoLookupError(_("tag '%s' does not exist")
1822 raise error.RepoLookupError(_("tag '%s' does not exist")
1823 % pattern)
1823 % pattern)
1824 s = set([repo[tn].rev()])
1824 s = set([repo[tn].rev()])
1825 else:
1825 else:
1826 s = set([cl.rev(n) for t, n in repo.tagslist() if matcher(t)])
1826 s = set([cl.rev(n) for t, n in repo.tagslist() if matcher(t)])
1827 else:
1827 else:
1828 s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
1828 s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
1829 return subset & s
1829 return subset & s
1830
1830
1831 def tagged(repo, subset, x):
1831 def tagged(repo, subset, x):
1832 return tag(repo, subset, x)
1832 return tag(repo, subset, x)
1833
1833
1834 def unstable(repo, subset, x):
1834 def unstable(repo, subset, x):
1835 """``unstable()``
1835 """``unstable()``
1836 Non-obsolete changesets with obsolete ancestors.
1836 Non-obsolete changesets with obsolete ancestors.
1837 """
1837 """
1838 # i18n: "unstable" is a keyword
1838 # i18n: "unstable" is a keyword
1839 getargs(x, 0, 0, _("unstable takes no arguments"))
1839 getargs(x, 0, 0, _("unstable takes no arguments"))
1840 unstables = obsmod.getrevs(repo, 'unstable')
1840 unstables = obsmod.getrevs(repo, 'unstable')
1841 return subset & unstables
1841 return subset & unstables
1842
1842
1843
1843
1844 def user(repo, subset, x):
1844 def user(repo, subset, x):
1845 """``user(string)``
1845 """``user(string)``
1846 User name contains string. The match is case-insensitive.
1846 User name contains string. The match is case-insensitive.
1847
1847
1848 If `string` starts with `re:`, the remainder of the string is treated as
1848 If `string` starts with `re:`, the remainder of the string is treated as
1849 a regular expression. To match a user that actually contains `re:`, use
1849 a regular expression. To match a user that actually contains `re:`, use
1850 the prefix `literal:`.
1850 the prefix `literal:`.
1851 """
1851 """
1852 return author(repo, subset, x)
1852 return author(repo, subset, x)
1853
1853
1854 # for internal use
1854 # for internal use
1855 def _list(repo, subset, x):
1855 def _list(repo, subset, x):
1856 s = getstring(x, "internal error")
1856 s = getstring(x, "internal error")
1857 if not s:
1857 if not s:
1858 return baseset()
1858 return baseset()
1859 ls = [repo[r].rev() for r in s.split('\0')]
1859 ls = [repo[r].rev() for r in s.split('\0')]
1860 s = subset
1860 s = subset
1861 return baseset([r for r in ls if r in s])
1861 return baseset([r for r in ls if r in s])
1862
1862
1863 # for internal use
1863 # for internal use
1864 def _intlist(repo, subset, x):
1864 def _intlist(repo, subset, x):
1865 s = getstring(x, "internal error")
1865 s = getstring(x, "internal error")
1866 if not s:
1866 if not s:
1867 return baseset()
1867 return baseset()
1868 ls = [int(r) for r in s.split('\0')]
1868 ls = [int(r) for r in s.split('\0')]
1869 s = subset
1869 s = subset
1870 return baseset([r for r in ls if r in s])
1870 return baseset([r for r in ls if r in s])
1871
1871
1872 # for internal use
1872 # for internal use
1873 def _hexlist(repo, subset, x):
1873 def _hexlist(repo, subset, x):
1874 s = getstring(x, "internal error")
1874 s = getstring(x, "internal error")
1875 if not s:
1875 if not s:
1876 return baseset()
1876 return baseset()
1877 cl = repo.changelog
1877 cl = repo.changelog
1878 ls = [cl.rev(node.bin(r)) for r in s.split('\0')]
1878 ls = [cl.rev(node.bin(r)) for r in s.split('\0')]
1879 s = subset
1879 s = subset
1880 return baseset([r for r in ls if r in s])
1880 return baseset([r for r in ls if r in s])
1881
1881
1882 symbols = {
1882 symbols = {
1883 "adds": adds,
1883 "adds": adds,
1884 "all": getall,
1884 "all": getall,
1885 "ancestor": ancestor,
1885 "ancestor": ancestor,
1886 "ancestors": ancestors,
1886 "ancestors": ancestors,
1887 "_firstancestors": _firstancestors,
1887 "_firstancestors": _firstancestors,
1888 "author": author,
1888 "author": author,
1889 "bisect": bisect,
1889 "bisect": bisect,
1890 "bisected": bisected,
1890 "bisected": bisected,
1891 "bookmark": bookmark,
1891 "bookmark": bookmark,
1892 "branch": branch,
1892 "branch": branch,
1893 "branchpoint": branchpoint,
1893 "branchpoint": branchpoint,
1894 "bumped": bumped,
1894 "bumped": bumped,
1895 "bundle": bundle,
1895 "bundle": bundle,
1896 "children": children,
1896 "children": children,
1897 "closed": closed,
1897 "closed": closed,
1898 "contains": contains,
1898 "contains": contains,
1899 "converted": converted,
1899 "converted": converted,
1900 "date": date,
1900 "date": date,
1901 "desc": desc,
1901 "desc": desc,
1902 "descendants": descendants,
1902 "descendants": descendants,
1903 "_firstdescendants": _firstdescendants,
1903 "_firstdescendants": _firstdescendants,
1904 "destination": destination,
1904 "destination": destination,
1905 "divergent": divergent,
1905 "divergent": divergent,
1906 "draft": draft,
1906 "draft": draft,
1907 "extinct": extinct,
1907 "extinct": extinct,
1908 "extra": extra,
1908 "extra": extra,
1909 "file": hasfile,
1909 "file": hasfile,
1910 "filelog": filelog,
1910 "filelog": filelog,
1911 "first": first,
1911 "first": first,
1912 "follow": follow,
1912 "follow": follow,
1913 "_followfirst": _followfirst,
1913 "_followfirst": _followfirst,
1914 "grep": grep,
1914 "grep": grep,
1915 "head": head,
1915 "head": head,
1916 "heads": heads,
1916 "heads": heads,
1917 "hidden": hidden,
1917 "hidden": hidden,
1918 "id": node_,
1918 "id": node_,
1919 "keyword": keyword,
1919 "keyword": keyword,
1920 "last": last,
1920 "last": last,
1921 "limit": limit,
1921 "limit": limit,
1922 "_matchfiles": _matchfiles,
1922 "_matchfiles": _matchfiles,
1923 "max": maxrev,
1923 "max": maxrev,
1924 "merge": merge,
1924 "merge": merge,
1925 "min": minrev,
1925 "min": minrev,
1926 "modifies": modifies,
1926 "modifies": modifies,
1927 "named": named,
1927 "named": named,
1928 "obsolete": obsolete,
1928 "obsolete": obsolete,
1929 "only": only,
1929 "only": only,
1930 "origin": origin,
1930 "origin": origin,
1931 "outgoing": outgoing,
1931 "outgoing": outgoing,
1932 "p1": p1,
1932 "p1": p1,
1933 "p2": p2,
1933 "p2": p2,
1934 "parents": parents,
1934 "parents": parents,
1935 "present": present,
1935 "present": present,
1936 "public": public,
1936 "public": public,
1937 "remote": remote,
1937 "remote": remote,
1938 "removes": removes,
1938 "removes": removes,
1939 "rev": rev,
1939 "rev": rev,
1940 "reverse": reverse,
1940 "reverse": reverse,
1941 "roots": roots,
1941 "roots": roots,
1942 "sort": sort,
1942 "sort": sort,
1943 "secret": secret,
1943 "secret": secret,
1944 "matching": matching,
1944 "matching": matching,
1945 "tag": tag,
1945 "tag": tag,
1946 "tagged": tagged,
1946 "tagged": tagged,
1947 "user": user,
1947 "user": user,
1948 "unstable": unstable,
1948 "unstable": unstable,
1949 "_list": _list,
1949 "_list": _list,
1950 "_intlist": _intlist,
1950 "_intlist": _intlist,
1951 "_hexlist": _hexlist,
1951 "_hexlist": _hexlist,
1952 }
1952 }
1953
1953
1954 # symbols which can't be used for a DoS attack for any given input
1954 # symbols which can't be used for a DoS attack for any given input
1955 # (e.g. those which accept regexes as plain strings shouldn't be included)
1955 # (e.g. those which accept regexes as plain strings shouldn't be included)
1956 # functions that just return a lot of changesets (like all) don't count here
1956 # functions that just return a lot of changesets (like all) don't count here
1957 safesymbols = set([
1957 safesymbols = set([
1958 "adds",
1958 "adds",
1959 "all",
1959 "all",
1960 "ancestor",
1960 "ancestor",
1961 "ancestors",
1961 "ancestors",
1962 "_firstancestors",
1962 "_firstancestors",
1963 "author",
1963 "author",
1964 "bisect",
1964 "bisect",
1965 "bisected",
1965 "bisected",
1966 "bookmark",
1966 "bookmark",
1967 "branch",
1967 "branch",
1968 "branchpoint",
1968 "branchpoint",
1969 "bumped",
1969 "bumped",
1970 "bundle",
1970 "bundle",
1971 "children",
1971 "children",
1972 "closed",
1972 "closed",
1973 "converted",
1973 "converted",
1974 "date",
1974 "date",
1975 "desc",
1975 "desc",
1976 "descendants",
1976 "descendants",
1977 "_firstdescendants",
1977 "_firstdescendants",
1978 "destination",
1978 "destination",
1979 "divergent",
1979 "divergent",
1980 "draft",
1980 "draft",
1981 "extinct",
1981 "extinct",
1982 "extra",
1982 "extra",
1983 "file",
1983 "file",
1984 "filelog",
1984 "filelog",
1985 "first",
1985 "first",
1986 "follow",
1986 "follow",
1987 "_followfirst",
1987 "_followfirst",
1988 "head",
1988 "head",
1989 "heads",
1989 "heads",
1990 "hidden",
1990 "hidden",
1991 "id",
1991 "id",
1992 "keyword",
1992 "keyword",
1993 "last",
1993 "last",
1994 "limit",
1994 "limit",
1995 "_matchfiles",
1995 "_matchfiles",
1996 "max",
1996 "max",
1997 "merge",
1997 "merge",
1998 "min",
1998 "min",
1999 "modifies",
1999 "modifies",
2000 "obsolete",
2000 "obsolete",
2001 "only",
2001 "only",
2002 "origin",
2002 "origin",
2003 "outgoing",
2003 "outgoing",
2004 "p1",
2004 "p1",
2005 "p2",
2005 "p2",
2006 "parents",
2006 "parents",
2007 "present",
2007 "present",
2008 "public",
2008 "public",
2009 "remote",
2009 "remote",
2010 "removes",
2010 "removes",
2011 "rev",
2011 "rev",
2012 "reverse",
2012 "reverse",
2013 "roots",
2013 "roots",
2014 "sort",
2014 "sort",
2015 "secret",
2015 "secret",
2016 "matching",
2016 "matching",
2017 "tag",
2017 "tag",
2018 "tagged",
2018 "tagged",
2019 "user",
2019 "user",
2020 "unstable",
2020 "unstable",
2021 "_list",
2021 "_list",
2022 "_intlist",
2022 "_intlist",
2023 "_hexlist",
2023 "_hexlist",
2024 ])
2024 ])
2025
2025
2026 methods = {
2026 methods = {
2027 "range": rangeset,
2027 "range": rangeset,
2028 "dagrange": dagrange,
2028 "dagrange": dagrange,
2029 "string": stringset,
2029 "string": stringset,
2030 "symbol": symbolset,
2030 "symbol": symbolset,
2031 "and": andset,
2031 "and": andset,
2032 "or": orset,
2032 "or": orset,
2033 "not": notset,
2033 "not": notset,
2034 "list": listset,
2034 "list": listset,
2035 "func": func,
2035 "func": func,
2036 "ancestor": ancestorspec,
2036 "ancestor": ancestorspec,
2037 "parent": parentspec,
2037 "parent": parentspec,
2038 "parentpost": p1,
2038 "parentpost": p1,
2039 "only": only,
2039 "only": only,
2040 "onlypost": only,
2040 "onlypost": only,
2041 }
2041 }
2042
2042
2043 def optimize(x, small):
2043 def optimize(x, small):
2044 if x is None:
2044 if x is None:
2045 return 0, x
2045 return 0, x
2046
2046
2047 smallbonus = 1
2047 smallbonus = 1
2048 if small:
2048 if small:
2049 smallbonus = .5
2049 smallbonus = .5
2050
2050
2051 op = x[0]
2051 op = x[0]
2052 if op == 'minus':
2052 if op == 'minus':
2053 return optimize(('and', x[1], ('not', x[2])), small)
2053 return optimize(('and', x[1], ('not', x[2])), small)
2054 elif op == 'only':
2054 elif op == 'only':
2055 return optimize(('func', ('symbol', 'only'),
2055 return optimize(('func', ('symbol', 'only'),
2056 ('list', x[1], x[2])), small)
2056 ('list', x[1], x[2])), small)
2057 elif op == 'dagrangepre':
2057 elif op == 'dagrangepre':
2058 return optimize(('func', ('symbol', 'ancestors'), x[1]), small)
2058 return optimize(('func', ('symbol', 'ancestors'), x[1]), small)
2059 elif op == 'dagrangepost':
2059 elif op == 'dagrangepost':
2060 return optimize(('func', ('symbol', 'descendants'), x[1]), small)
2060 return optimize(('func', ('symbol', 'descendants'), x[1]), small)
2061 elif op == 'rangepre':
2061 elif op == 'rangepre':
2062 return optimize(('range', ('string', '0'), x[1]), small)
2062 return optimize(('range', ('string', '0'), x[1]), small)
2063 elif op == 'rangepost':
2063 elif op == 'rangepost':
2064 return optimize(('range', x[1], ('string', 'tip')), small)
2064 return optimize(('range', x[1], ('string', 'tip')), small)
2065 elif op == 'negate':
2065 elif op == 'negate':
2066 return optimize(('string',
2066 return optimize(('string',
2067 '-' + getstring(x[1], _("can't negate that"))), small)
2067 '-' + getstring(x[1], _("can't negate that"))), small)
2068 elif op in 'string symbol negate':
2068 elif op in 'string symbol negate':
2069 return smallbonus, x # single revisions are small
2069 return smallbonus, x # single revisions are small
2070 elif op == 'and':
2070 elif op == 'and':
2071 wa, ta = optimize(x[1], True)
2071 wa, ta = optimize(x[1], True)
2072 wb, tb = optimize(x[2], True)
2072 wb, tb = optimize(x[2], True)
2073
2073
2074 # (::x and not ::y)/(not ::y and ::x) have a fast path
2074 # (::x and not ::y)/(not ::y and ::x) have a fast path
2075 def isonly(revs, bases):
2075 def isonly(revs, bases):
2076 return (
2076 return (
2077 revs[0] == 'func'
2077 revs[0] == 'func'
2078 and getstring(revs[1], _('not a symbol')) == 'ancestors'
2078 and getstring(revs[1], _('not a symbol')) == 'ancestors'
2079 and bases[0] == 'not'
2079 and bases[0] == 'not'
2080 and bases[1][0] == 'func'
2080 and bases[1][0] == 'func'
2081 and getstring(bases[1][1], _('not a symbol')) == 'ancestors')
2081 and getstring(bases[1][1], _('not a symbol')) == 'ancestors')
2082
2082
2083 w = min(wa, wb)
2083 w = min(wa, wb)
2084 if isonly(ta, tb):
2084 if isonly(ta, tb):
2085 return w, ('func', ('symbol', 'only'), ('list', ta[2], tb[1][2]))
2085 return w, ('func', ('symbol', 'only'), ('list', ta[2], tb[1][2]))
2086 if isonly(tb, ta):
2086 if isonly(tb, ta):
2087 return w, ('func', ('symbol', 'only'), ('list', tb[2], ta[1][2]))
2087 return w, ('func', ('symbol', 'only'), ('list', tb[2], ta[1][2]))
2088
2088
2089 if wa > wb:
2089 if wa > wb:
2090 return w, (op, tb, ta)
2090 return w, (op, tb, ta)
2091 return w, (op, ta, tb)
2091 return w, (op, ta, tb)
2092 elif op == 'or':
2092 elif op == 'or':
2093 wa, ta = optimize(x[1], False)
2093 wa, ta = optimize(x[1], False)
2094 wb, tb = optimize(x[2], False)
2094 wb, tb = optimize(x[2], False)
2095 if wb < wa:
2095 if wb < wa:
2096 wb, wa = wa, wb
2096 wb, wa = wa, wb
2097 return max(wa, wb), (op, ta, tb)
2097 return max(wa, wb), (op, ta, tb)
2098 elif op == 'not':
2098 elif op == 'not':
2099 o = optimize(x[1], not small)
2099 o = optimize(x[1], not small)
2100 return o[0], (op, o[1])
2100 return o[0], (op, o[1])
2101 elif op == 'parentpost':
2101 elif op == 'parentpost':
2102 o = optimize(x[1], small)
2102 o = optimize(x[1], small)
2103 return o[0], (op, o[1])
2103 return o[0], (op, o[1])
2104 elif op == 'group':
2104 elif op == 'group':
2105 return optimize(x[1], small)
2105 return optimize(x[1], small)
2106 elif op in 'dagrange range list parent ancestorspec':
2106 elif op in 'dagrange range list parent ancestorspec':
2107 if op == 'parent':
2107 if op == 'parent':
2108 # x^:y means (x^) : y, not x ^ (:y)
2108 # x^:y means (x^) : y, not x ^ (:y)
2109 post = ('parentpost', x[1])
2109 post = ('parentpost', x[1])
2110 if x[2][0] == 'dagrangepre':
2110 if x[2][0] == 'dagrangepre':
2111 return optimize(('dagrange', post, x[2][1]), small)
2111 return optimize(('dagrange', post, x[2][1]), small)
2112 elif x[2][0] == 'rangepre':
2112 elif x[2][0] == 'rangepre':
2113 return optimize(('range', post, x[2][1]), small)
2113 return optimize(('range', post, x[2][1]), small)
2114
2114
2115 wa, ta = optimize(x[1], small)
2115 wa, ta = optimize(x[1], small)
2116 wb, tb = optimize(x[2], small)
2116 wb, tb = optimize(x[2], small)
2117 return wa + wb, (op, ta, tb)
2117 return wa + wb, (op, ta, tb)
2118 elif op == 'func':
2118 elif op == 'func':
2119 f = getstring(x[1], _("not a symbol"))
2119 f = getstring(x[1], _("not a symbol"))
2120 wa, ta = optimize(x[2], small)
2120 wa, ta = optimize(x[2], small)
2121 if f in ("author branch closed date desc file grep keyword "
2121 if f in ("author branch closed date desc file grep keyword "
2122 "outgoing user"):
2122 "outgoing user"):
2123 w = 10 # slow
2123 w = 10 # slow
2124 elif f in "modifies adds removes":
2124 elif f in "modifies adds removes":
2125 w = 30 # slower
2125 w = 30 # slower
2126 elif f == "contains":
2126 elif f == "contains":
2127 w = 100 # very slow
2127 w = 100 # very slow
2128 elif f == "ancestor":
2128 elif f == "ancestor":
2129 w = 1 * smallbonus
2129 w = 1 * smallbonus
2130 elif f in "reverse limit first _intlist":
2130 elif f in "reverse limit first _intlist":
2131 w = 0
2131 w = 0
2132 elif f in "sort":
2132 elif f in "sort":
2133 w = 10 # assume most sorts look at changelog
2133 w = 10 # assume most sorts look at changelog
2134 else:
2134 else:
2135 w = 1
2135 w = 1
2136 return w + wa, (op, x[1], ta)
2136 return w + wa, (op, x[1], ta)
2137 return 1, x
2137 return 1, x
2138
2138
2139 _aliasarg = ('func', ('symbol', '_aliasarg'))
2139 _aliasarg = ('func', ('symbol', '_aliasarg'))
2140 def _getaliasarg(tree):
2140 def _getaliasarg(tree):
2141 """If tree matches ('func', ('symbol', '_aliasarg'), ('string', X))
2141 """If tree matches ('func', ('symbol', '_aliasarg'), ('string', X))
2142 return X, None otherwise.
2142 return X, None otherwise.
2143 """
2143 """
2144 if (len(tree) == 3 and tree[:2] == _aliasarg
2144 if (len(tree) == 3 and tree[:2] == _aliasarg
2145 and tree[2][0] == 'string'):
2145 and tree[2][0] == 'string'):
2146 return tree[2][1]
2146 return tree[2][1]
2147 return None
2147 return None
2148
2148
2149 def _checkaliasarg(tree, known=None):
2149 def _checkaliasarg(tree, known=None):
2150 """Check tree contains no _aliasarg construct or only ones which
2150 """Check tree contains no _aliasarg construct or only ones which
2151 value is in known. Used to avoid alias placeholders injection.
2151 value is in known. Used to avoid alias placeholders injection.
2152 """
2152 """
2153 if isinstance(tree, tuple):
2153 if isinstance(tree, tuple):
2154 arg = _getaliasarg(tree)
2154 arg = _getaliasarg(tree)
2155 if arg is not None and (not known or arg not in known):
2155 if arg is not None and (not known or arg not in known):
2156 raise error.ParseError(_("not a function: %s") % '_aliasarg')
2156 raise error.ParseError(_("not a function: %s") % '_aliasarg')
2157 for t in tree:
2157 for t in tree:
2158 _checkaliasarg(t, known)
2158 _checkaliasarg(t, known)
2159
2159
2160 # the set of valid characters for the initial letter of symbols in
2160 # the set of valid characters for the initial letter of symbols in
2161 # alias declarations and definitions
2161 # alias declarations and definitions
2162 _aliassyminitletters = set(c for c in [chr(i) for i in xrange(256)]
2162 _aliassyminitletters = set(c for c in [chr(i) for i in xrange(256)]
2163 if c.isalnum() or c in '._@$' or ord(c) > 127)
2163 if c.isalnum() or c in '._@$' or ord(c) > 127)
2164
2164
2165 def _tokenizealias(program, lookup=None):
2165 def _tokenizealias(program, lookup=None):
2166 """Parse alias declaration/definition into a stream of tokens
2166 """Parse alias declaration/definition into a stream of tokens
2167
2167
2168 This allows symbol names to use also ``$`` as an initial letter
2168 This allows symbol names to use also ``$`` as an initial letter
2169 (for backward compatibility), and callers of this function should
2169 (for backward compatibility), and callers of this function should
2170 examine whether ``$`` is used also for unexpected symbols or not.
2170 examine whether ``$`` is used also for unexpected symbols or not.
2171 """
2171 """
2172 return tokenize(program, lookup=lookup,
2172 return tokenize(program, lookup=lookup,
2173 syminitletters=_aliassyminitletters)
2173 syminitletters=_aliassyminitletters)
2174
2174
2175 def _parsealiasdecl(decl):
2175 def _parsealiasdecl(decl):
2176 """Parse alias declaration ``decl``
2176 """Parse alias declaration ``decl``
2177
2177
2178 This returns ``(name, tree, args, errorstr)`` tuple:
2178 This returns ``(name, tree, args, errorstr)`` tuple:
2179
2179
2180 - ``name``: of declared alias (may be ``decl`` itself at error)
2180 - ``name``: of declared alias (may be ``decl`` itself at error)
2181 - ``tree``: parse result (or ``None`` at error)
2181 - ``tree``: parse result (or ``None`` at error)
2182 - ``args``: list of alias argument names (or None for symbol declaration)
2182 - ``args``: list of alias argument names (or None for symbol declaration)
2183 - ``errorstr``: detail about detected error (or None)
2183 - ``errorstr``: detail about detected error (or None)
2184
2184
2185 >>> _parsealiasdecl('foo')
2185 >>> _parsealiasdecl('foo')
2186 ('foo', ('symbol', 'foo'), None, None)
2186 ('foo', ('symbol', 'foo'), None, None)
2187 >>> _parsealiasdecl('$foo')
2187 >>> _parsealiasdecl('$foo')
2188 ('$foo', None, None, "'$' not for alias arguments")
2188 ('$foo', None, None, "'$' not for alias arguments")
2189 >>> _parsealiasdecl('foo::bar')
2189 >>> _parsealiasdecl('foo::bar')
2190 ('foo::bar', None, None, 'invalid format')
2190 ('foo::bar', None, None, 'invalid format')
2191 >>> _parsealiasdecl('foo bar')
2191 >>> _parsealiasdecl('foo bar')
2192 ('foo bar', None, None, 'at 4: invalid token')
2192 ('foo bar', None, None, 'at 4: invalid token')
2193 >>> _parsealiasdecl('foo()')
2193 >>> _parsealiasdecl('foo()')
2194 ('foo', ('func', ('symbol', 'foo')), [], None)
2194 ('foo', ('func', ('symbol', 'foo')), [], None)
2195 >>> _parsealiasdecl('$foo()')
2195 >>> _parsealiasdecl('$foo()')
2196 ('$foo()', None, None, "'$' not for alias arguments")
2196 ('$foo()', None, None, "'$' not for alias arguments")
2197 >>> _parsealiasdecl('foo($1, $2)')
2197 >>> _parsealiasdecl('foo($1, $2)')
2198 ('foo', ('func', ('symbol', 'foo')), ['$1', '$2'], None)
2198 ('foo', ('func', ('symbol', 'foo')), ['$1', '$2'], None)
2199 >>> _parsealiasdecl('foo(bar_bar, baz.baz)')
2199 >>> _parsealiasdecl('foo(bar_bar, baz.baz)')
2200 ('foo', ('func', ('symbol', 'foo')), ['bar_bar', 'baz.baz'], None)
2200 ('foo', ('func', ('symbol', 'foo')), ['bar_bar', 'baz.baz'], None)
2201 >>> _parsealiasdecl('foo($1, $2, nested($1, $2))')
2201 >>> _parsealiasdecl('foo($1, $2, nested($1, $2))')
2202 ('foo($1, $2, nested($1, $2))', None, None, 'invalid argument list')
2202 ('foo($1, $2, nested($1, $2))', None, None, 'invalid argument list')
2203 >>> _parsealiasdecl('foo(bar($1, $2))')
2203 >>> _parsealiasdecl('foo(bar($1, $2))')
2204 ('foo(bar($1, $2))', None, None, 'invalid argument list')
2204 ('foo(bar($1, $2))', None, None, 'invalid argument list')
2205 >>> _parsealiasdecl('foo("string")')
2205 >>> _parsealiasdecl('foo("string")')
2206 ('foo("string")', None, None, 'invalid argument list')
2206 ('foo("string")', None, None, 'invalid argument list')
2207 >>> _parsealiasdecl('foo($1, $2')
2207 >>> _parsealiasdecl('foo($1, $2')
2208 ('foo($1, $2', None, None, 'at 10: unexpected token: end')
2208 ('foo($1, $2', None, None, 'at 10: unexpected token: end')
2209 >>> _parsealiasdecl('foo("string')
2209 >>> _parsealiasdecl('foo("string')
2210 ('foo("string', None, None, 'at 5: unterminated string')
2210 ('foo("string', None, None, 'at 5: unterminated string')
2211 >>> _parsealiasdecl('foo($1, $2, $1)')
2211 >>> _parsealiasdecl('foo($1, $2, $1)')
2212 ('foo', None, None, 'argument names collide with each other')
2212 ('foo', None, None, 'argument names collide with each other')
2213 """
2213 """
2214 p = parser.parser(_tokenizealias, elements)
2214 p = parser.parser(_tokenizealias, elements)
2215 try:
2215 try:
2216 tree, pos = p.parse(decl)
2216 tree, pos = p.parse(decl)
2217 if (pos != len(decl)):
2217 if (pos != len(decl)):
2218 raise error.ParseError(_('invalid token'), pos)
2218 raise error.ParseError(_('invalid token'), pos)
2219
2219
2220 if isvalidsymbol(tree):
2220 if isvalidsymbol(tree):
2221 # "name = ...." style
2221 # "name = ...." style
2222 name = getsymbol(tree)
2222 name = getsymbol(tree)
2223 if name.startswith('$'):
2223 if name.startswith('$'):
2224 return (decl, None, None, _("'$' not for alias arguments"))
2224 return (decl, None, None, _("'$' not for alias arguments"))
2225 return (name, ('symbol', name), None, None)
2225 return (name, ('symbol', name), None, None)
2226
2226
2227 if isvalidfunc(tree):
2227 if isvalidfunc(tree):
2228 # "name(arg, ....) = ...." style
2228 # "name(arg, ....) = ...." style
2229 name = getfuncname(tree)
2229 name = getfuncname(tree)
2230 if name.startswith('$'):
2230 if name.startswith('$'):
2231 return (decl, None, None, _("'$' not for alias arguments"))
2231 return (decl, None, None, _("'$' not for alias arguments"))
2232 args = []
2232 args = []
2233 for arg in getfuncargs(tree):
2233 for arg in getfuncargs(tree):
2234 if not isvalidsymbol(arg):
2234 if not isvalidsymbol(arg):
2235 return (decl, None, None, _("invalid argument list"))
2235 return (decl, None, None, _("invalid argument list"))
2236 args.append(getsymbol(arg))
2236 args.append(getsymbol(arg))
2237 if len(args) != len(set(args)):
2237 if len(args) != len(set(args)):
2238 return (name, None, None,
2238 return (name, None, None,
2239 _("argument names collide with each other"))
2239 _("argument names collide with each other"))
2240 return (name, ('func', ('symbol', name)), args, None)
2240 return (name, ('func', ('symbol', name)), args, None)
2241
2241
2242 return (decl, None, None, _("invalid format"))
2242 return (decl, None, None, _("invalid format"))
2243 except error.ParseError, inst:
2243 except error.ParseError, inst:
2244 return (decl, None, None, parseerrordetail(inst))
2244 return (decl, None, None, parseerrordetail(inst))
2245
2245
2246 def _parsealiasdefn(defn, args):
2246 def _parsealiasdefn(defn, args):
2247 """Parse alias definition ``defn``
2247 """Parse alias definition ``defn``
2248
2248
2249 This function also replaces alias argument references in the
2249 This function also replaces alias argument references in the
2250 specified definition by ``_aliasarg(ARGNAME)``.
2250 specified definition by ``_aliasarg(ARGNAME)``.
2251
2251
2252 ``args`` is a list of alias argument names, or None if the alias
2252 ``args`` is a list of alias argument names, or None if the alias
2253 is declared as a symbol.
2253 is declared as a symbol.
2254
2254
2255 This returns "tree" as parsing result.
2255 This returns "tree" as parsing result.
2256
2256
2257 >>> args = ['$1', '$2', 'foo']
2257 >>> args = ['$1', '$2', 'foo']
2258 >>> print prettyformat(_parsealiasdefn('$1 or foo', args))
2258 >>> print prettyformat(_parsealiasdefn('$1 or foo', args))
2259 (or
2259 (or
2260 (func
2260 (func
2261 ('symbol', '_aliasarg')
2261 ('symbol', '_aliasarg')
2262 ('string', '$1'))
2262 ('string', '$1'))
2263 (func
2263 (func
2264 ('symbol', '_aliasarg')
2264 ('symbol', '_aliasarg')
2265 ('string', 'foo')))
2265 ('string', 'foo')))
2266 >>> try:
2266 >>> try:
2267 ... _parsealiasdefn('$1 or $bar', args)
2267 ... _parsealiasdefn('$1 or $bar', args)
2268 ... except error.ParseError, inst:
2268 ... except error.ParseError, inst:
2269 ... print parseerrordetail(inst)
2269 ... print parseerrordetail(inst)
2270 at 6: '$' not for alias arguments
2270 at 6: '$' not for alias arguments
2271 >>> args = ['$1', '$10', 'foo']
2271 >>> args = ['$1', '$10', 'foo']
2272 >>> print prettyformat(_parsealiasdefn('$10 or foobar', args))
2272 >>> print prettyformat(_parsealiasdefn('$10 or foobar', args))
2273 (or
2273 (or
2274 (func
2274 (func
2275 ('symbol', '_aliasarg')
2275 ('symbol', '_aliasarg')
2276 ('string', '$10'))
2276 ('string', '$10'))
2277 ('symbol', 'foobar'))
2277 ('symbol', 'foobar'))
2278 >>> print prettyformat(_parsealiasdefn('"$1" or "foo"', args))
2278 >>> print prettyformat(_parsealiasdefn('"$1" or "foo"', args))
2279 (or
2279 (or
2280 ('string', '$1')
2280 ('string', '$1')
2281 ('string', 'foo'))
2281 ('string', 'foo'))
2282 """
2282 """
2283 def tokenizedefn(program, lookup=None):
2283 def tokenizedefn(program, lookup=None):
2284 if args:
2284 if args:
2285 argset = set(args)
2285 argset = set(args)
2286 else:
2286 else:
2287 argset = set()
2287 argset = set()
2288
2288
2289 for t, value, pos in _tokenizealias(program, lookup=lookup):
2289 for t, value, pos in _tokenizealias(program, lookup=lookup):
2290 if t == 'symbol':
2290 if t == 'symbol':
2291 if value in argset:
2291 if value in argset:
2292 # emulate tokenization of "_aliasarg('ARGNAME')":
2292 # emulate tokenization of "_aliasarg('ARGNAME')":
2293 # "_aliasarg()" is an unknown symbol only used separate
2293 # "_aliasarg()" is an unknown symbol only used separate
2294 # alias argument placeholders from regular strings.
2294 # alias argument placeholders from regular strings.
2295 yield ('symbol', '_aliasarg', pos)
2295 yield ('symbol', '_aliasarg', pos)
2296 yield ('(', None, pos)
2296 yield ('(', None, pos)
2297 yield ('string', value, pos)
2297 yield ('string', value, pos)
2298 yield (')', None, pos)
2298 yield (')', None, pos)
2299 continue
2299 continue
2300 elif value.startswith('$'):
2300 elif value.startswith('$'):
2301 raise error.ParseError(_("'$' not for alias arguments"),
2301 raise error.ParseError(_("'$' not for alias arguments"),
2302 pos)
2302 pos)
2303 yield (t, value, pos)
2303 yield (t, value, pos)
2304
2304
2305 p = parser.parser(tokenizedefn, elements)
2305 p = parser.parser(tokenizedefn, elements)
2306 tree, pos = p.parse(defn)
2306 tree, pos = p.parse(defn)
2307 if pos != len(defn):
2307 if pos != len(defn):
2308 raise error.ParseError(_('invalid token'), pos)
2308 raise error.ParseError(_('invalid token'), pos)
2309 return tree
2309 return tree
2310
2310
2311 class revsetalias(object):
2311 class revsetalias(object):
2312 # whether own `error` information is already shown or not.
2312 # whether own `error` information is already shown or not.
2313 # this avoids showing same warning multiple times at each `findaliases`.
2313 # this avoids showing same warning multiple times at each `findaliases`.
2314 warned = False
2314 warned = False
2315
2315
2316 def __init__(self, name, value):
2316 def __init__(self, name, value):
2317 '''Aliases like:
2317 '''Aliases like:
2318
2318
2319 h = heads(default)
2319 h = heads(default)
2320 b($1) = ancestors($1) - ancestors(default)
2320 b($1) = ancestors($1) - ancestors(default)
2321 '''
2321 '''
2322 self.name, self.tree, self.args, self.error = _parsealiasdecl(name)
2322 self.name, self.tree, self.args, self.error = _parsealiasdecl(name)
2323 if self.error:
2323 if self.error:
2324 self.error = _('failed to parse the declaration of revset alias'
2324 self.error = _('failed to parse the declaration of revset alias'
2325 ' "%s": %s') % (self.name, self.error)
2325 ' "%s": %s') % (self.name, self.error)
2326 return
2326 return
2327
2327
2328 try:
2328 try:
2329 self.replacement = _parsealiasdefn(value, self.args)
2329 self.replacement = _parsealiasdefn(value, self.args)
2330 # Check for placeholder injection
2330 # Check for placeholder injection
2331 _checkaliasarg(self.replacement, self.args)
2331 _checkaliasarg(self.replacement, self.args)
2332 except error.ParseError, inst:
2332 except error.ParseError, inst:
2333 self.error = _('failed to parse the definition of revset alias'
2333 self.error = _('failed to parse the definition of revset alias'
2334 ' "%s": %s') % (self.name, parseerrordetail(inst))
2334 ' "%s": %s') % (self.name, parseerrordetail(inst))
2335
2335
2336 def _getalias(aliases, tree):
2336 def _getalias(aliases, tree):
2337 """If tree looks like an unexpanded alias, return it. Return None
2337 """If tree looks like an unexpanded alias, return it. Return None
2338 otherwise.
2338 otherwise.
2339 """
2339 """
2340 if isinstance(tree, tuple) and tree:
2340 if isinstance(tree, tuple) and tree:
2341 if tree[0] == 'symbol' and len(tree) == 2:
2341 if tree[0] == 'symbol' and len(tree) == 2:
2342 name = tree[1]
2342 name = tree[1]
2343 alias = aliases.get(name)
2343 alias = aliases.get(name)
2344 if alias and alias.args is None and alias.tree == tree:
2344 if alias and alias.args is None and alias.tree == tree:
2345 return alias
2345 return alias
2346 if tree[0] == 'func' and len(tree) > 1:
2346 if tree[0] == 'func' and len(tree) > 1:
2347 if tree[1][0] == 'symbol' and len(tree[1]) == 2:
2347 if tree[1][0] == 'symbol' and len(tree[1]) == 2:
2348 name = tree[1][1]
2348 name = tree[1][1]
2349 alias = aliases.get(name)
2349 alias = aliases.get(name)
2350 if alias and alias.args is not None and alias.tree == tree[:2]:
2350 if alias and alias.args is not None and alias.tree == tree[:2]:
2351 return alias
2351 return alias
2352 return None
2352 return None
2353
2353
2354 def _expandargs(tree, args):
2354 def _expandargs(tree, args):
2355 """Replace _aliasarg instances with the substitution value of the
2355 """Replace _aliasarg instances with the substitution value of the
2356 same name in args, recursively.
2356 same name in args, recursively.
2357 """
2357 """
2358 if not tree or not isinstance(tree, tuple):
2358 if not tree or not isinstance(tree, tuple):
2359 return tree
2359 return tree
2360 arg = _getaliasarg(tree)
2360 arg = _getaliasarg(tree)
2361 if arg is not None:
2361 if arg is not None:
2362 return args[arg]
2362 return args[arg]
2363 return tuple(_expandargs(t, args) for t in tree)
2363 return tuple(_expandargs(t, args) for t in tree)
2364
2364
2365 def _expandaliases(aliases, tree, expanding, cache):
2365 def _expandaliases(aliases, tree, expanding, cache):
2366 """Expand aliases in tree, recursively.
2366 """Expand aliases in tree, recursively.
2367
2367
2368 'aliases' is a dictionary mapping user defined aliases to
2368 'aliases' is a dictionary mapping user defined aliases to
2369 revsetalias objects.
2369 revsetalias objects.
2370 """
2370 """
2371 if not isinstance(tree, tuple):
2371 if not isinstance(tree, tuple):
2372 # Do not expand raw strings
2372 # Do not expand raw strings
2373 return tree
2373 return tree
2374 alias = _getalias(aliases, tree)
2374 alias = _getalias(aliases, tree)
2375 if alias is not None:
2375 if alias is not None:
2376 if alias.error:
2376 if alias.error:
2377 raise util.Abort(alias.error)
2377 raise util.Abort(alias.error)
2378 if alias in expanding:
2378 if alias in expanding:
2379 raise error.ParseError(_('infinite expansion of revset alias "%s" '
2379 raise error.ParseError(_('infinite expansion of revset alias "%s" '
2380 'detected') % alias.name)
2380 'detected') % alias.name)
2381 expanding.append(alias)
2381 expanding.append(alias)
2382 if alias.name not in cache:
2382 if alias.name not in cache:
2383 cache[alias.name] = _expandaliases(aliases, alias.replacement,
2383 cache[alias.name] = _expandaliases(aliases, alias.replacement,
2384 expanding, cache)
2384 expanding, cache)
2385 result = cache[alias.name]
2385 result = cache[alias.name]
2386 expanding.pop()
2386 expanding.pop()
2387 if alias.args is not None:
2387 if alias.args is not None:
2388 l = getlist(tree[2])
2388 l = getlist(tree[2])
2389 if len(l) != len(alias.args):
2389 if len(l) != len(alias.args):
2390 raise error.ParseError(
2390 raise error.ParseError(
2391 _('invalid number of arguments: %s') % len(l))
2391 _('invalid number of arguments: %s') % len(l))
2392 l = [_expandaliases(aliases, a, [], cache) for a in l]
2392 l = [_expandaliases(aliases, a, [], cache) for a in l]
2393 result = _expandargs(result, dict(zip(alias.args, l)))
2393 result = _expandargs(result, dict(zip(alias.args, l)))
2394 else:
2394 else:
2395 result = tuple(_expandaliases(aliases, t, expanding, cache)
2395 result = tuple(_expandaliases(aliases, t, expanding, cache)
2396 for t in tree)
2396 for t in tree)
2397 return result
2397 return result
2398
2398
2399 def findaliases(ui, tree, showwarning=None):
2399 def findaliases(ui, tree, showwarning=None):
2400 _checkaliasarg(tree)
2400 _checkaliasarg(tree)
2401 aliases = {}
2401 aliases = {}
2402 for k, v in ui.configitems('revsetalias'):
2402 for k, v in ui.configitems('revsetalias'):
2403 alias = revsetalias(k, v)
2403 alias = revsetalias(k, v)
2404 aliases[alias.name] = alias
2404 aliases[alias.name] = alias
2405 tree = _expandaliases(aliases, tree, [], {})
2405 tree = _expandaliases(aliases, tree, [], {})
2406 if showwarning:
2406 if showwarning:
2407 # warn about problematic (but not referred) aliases
2407 # warn about problematic (but not referred) aliases
2408 for name, alias in sorted(aliases.iteritems()):
2408 for name, alias in sorted(aliases.iteritems()):
2409 if alias.error and not alias.warned:
2409 if alias.error and not alias.warned:
2410 showwarning(_('warning: %s\n') % (alias.error))
2410 showwarning(_('warning: %s\n') % (alias.error))
2411 alias.warned = True
2411 alias.warned = True
2412 return tree
2412 return tree
2413
2413
2414 def foldconcat(tree):
2414 def foldconcat(tree):
2415 """Fold elements to be concatenated by `##`
2415 """Fold elements to be concatenated by `##`
2416 """
2416 """
2417 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
2417 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
2418 return tree
2418 return tree
2419 if tree[0] == '_concat':
2419 if tree[0] == '_concat':
2420 pending = [tree]
2420 pending = [tree]
2421 l = []
2421 l = []
2422 while pending:
2422 while pending:
2423 e = pending.pop()
2423 e = pending.pop()
2424 if e[0] == '_concat':
2424 if e[0] == '_concat':
2425 pending.extend(reversed(e[1:]))
2425 pending.extend(reversed(e[1:]))
2426 elif e[0] in ('string', 'symbol'):
2426 elif e[0] in ('string', 'symbol'):
2427 l.append(e[1])
2427 l.append(e[1])
2428 else:
2428 else:
2429 msg = _("\"##\" can't concatenate \"%s\" element") % (e[0])
2429 msg = _("\"##\" can't concatenate \"%s\" element") % (e[0])
2430 raise error.ParseError(msg)
2430 raise error.ParseError(msg)
2431 return ('string', ''.join(l))
2431 return ('string', ''.join(l))
2432 else:
2432 else:
2433 return tuple(foldconcat(t) for t in tree)
2433 return tuple(foldconcat(t) for t in tree)
2434
2434
2435 def parse(spec, lookup=None):
2435 def parse(spec, lookup=None):
2436 p = parser.parser(tokenize, elements)
2436 p = parser.parser(tokenize, elements)
2437 return p.parse(spec, lookup=lookup)
2437 return p.parse(spec, lookup=lookup)
2438
2438
2439 def match(ui, spec, repo=None):
2439 def match(ui, spec, repo=None):
2440 if not spec:
2440 if not spec:
2441 raise error.ParseError(_("empty query"))
2441 raise error.ParseError(_("empty query"))
2442 lookup = None
2442 lookup = None
2443 if repo:
2443 if repo:
2444 lookup = repo.__contains__
2444 lookup = repo.__contains__
2445 tree, pos = parse(spec, lookup)
2445 tree, pos = parse(spec, lookup)
2446 if (pos != len(spec)):
2446 if (pos != len(spec)):
2447 raise error.ParseError(_("invalid token"), pos)
2447 raise error.ParseError(_("invalid token"), pos)
2448 if ui:
2448 if ui:
2449 tree = findaliases(ui, tree, showwarning=ui.warn)
2449 tree = findaliases(ui, tree, showwarning=ui.warn)
2450 tree = foldconcat(tree)
2450 tree = foldconcat(tree)
2451 weight, tree = optimize(tree, True)
2451 weight, tree = optimize(tree, True)
2452 def mfunc(repo, subset=None):
2452 def mfunc(repo, subset=None):
2453 if subset is None:
2453 if subset is None:
2454 subset = fullreposet(repo)
2454 subset = fullreposet(repo)
2455 if util.safehasattr(subset, 'isascending'):
2455 if util.safehasattr(subset, 'isascending'):
2456 result = getset(repo, subset, tree)
2456 result = getset(repo, subset, tree)
2457 else:
2457 else:
2458 result = getset(repo, baseset(subset), tree)
2458 result = getset(repo, baseset(subset), tree)
2459 return result
2459 return result
2460 return mfunc
2460 return mfunc
2461
2461
2462 def formatspec(expr, *args):
2462 def formatspec(expr, *args):
2463 '''
2463 '''
2464 This is a convenience function for using revsets internally, and
2464 This is a convenience function for using revsets internally, and
2465 escapes arguments appropriately. Aliases are intentionally ignored
2465 escapes arguments appropriately. Aliases are intentionally ignored
2466 so that intended expression behavior isn't accidentally subverted.
2466 so that intended expression behavior isn't accidentally subverted.
2467
2467
2468 Supported arguments:
2468 Supported arguments:
2469
2469
2470 %r = revset expression, parenthesized
2470 %r = revset expression, parenthesized
2471 %d = int(arg), no quoting
2471 %d = int(arg), no quoting
2472 %s = string(arg), escaped and single-quoted
2472 %s = string(arg), escaped and single-quoted
2473 %b = arg.branch(), escaped and single-quoted
2473 %b = arg.branch(), escaped and single-quoted
2474 %n = hex(arg), single-quoted
2474 %n = hex(arg), single-quoted
2475 %% = a literal '%'
2475 %% = a literal '%'
2476
2476
2477 Prefixing the type with 'l' specifies a parenthesized list of that type.
2477 Prefixing the type with 'l' specifies a parenthesized list of that type.
2478
2478
2479 >>> formatspec('%r:: and %lr', '10 or 11', ("this()", "that()"))
2479 >>> formatspec('%r:: and %lr', '10 or 11', ("this()", "that()"))
2480 '(10 or 11):: and ((this()) or (that()))'
2480 '(10 or 11):: and ((this()) or (that()))'
2481 >>> formatspec('%d:: and not %d::', 10, 20)
2481 >>> formatspec('%d:: and not %d::', 10, 20)
2482 '10:: and not 20::'
2482 '10:: and not 20::'
2483 >>> formatspec('%ld or %ld', [], [1])
2483 >>> formatspec('%ld or %ld', [], [1])
2484 "_list('') or 1"
2484 "_list('') or 1"
2485 >>> formatspec('keyword(%s)', 'foo\\xe9')
2485 >>> formatspec('keyword(%s)', 'foo\\xe9')
2486 "keyword('foo\\\\xe9')"
2486 "keyword('foo\\\\xe9')"
2487 >>> b = lambda: 'default'
2487 >>> b = lambda: 'default'
2488 >>> b.branch = b
2488 >>> b.branch = b
2489 >>> formatspec('branch(%b)', b)
2489 >>> formatspec('branch(%b)', b)
2490 "branch('default')"
2490 "branch('default')"
2491 >>> formatspec('root(%ls)', ['a', 'b', 'c', 'd'])
2491 >>> formatspec('root(%ls)', ['a', 'b', 'c', 'd'])
2492 "root(_list('a\\x00b\\x00c\\x00d'))"
2492 "root(_list('a\\x00b\\x00c\\x00d'))"
2493 '''
2493 '''
2494
2494
2495 def quote(s):
2495 def quote(s):
2496 return repr(str(s))
2496 return repr(str(s))
2497
2497
2498 def argtype(c, arg):
2498 def argtype(c, arg):
2499 if c == 'd':
2499 if c == 'd':
2500 return str(int(arg))
2500 return str(int(arg))
2501 elif c == 's':
2501 elif c == 's':
2502 return quote(arg)
2502 return quote(arg)
2503 elif c == 'r':
2503 elif c == 'r':
2504 parse(arg) # make sure syntax errors are confined
2504 parse(arg) # make sure syntax errors are confined
2505 return '(%s)' % arg
2505 return '(%s)' % arg
2506 elif c == 'n':
2506 elif c == 'n':
2507 return quote(node.hex(arg))
2507 return quote(node.hex(arg))
2508 elif c == 'b':
2508 elif c == 'b':
2509 return quote(arg.branch())
2509 return quote(arg.branch())
2510
2510
2511 def listexp(s, t):
2511 def listexp(s, t):
2512 l = len(s)
2512 l = len(s)
2513 if l == 0:
2513 if l == 0:
2514 return "_list('')"
2514 return "_list('')"
2515 elif l == 1:
2515 elif l == 1:
2516 return argtype(t, s[0])
2516 return argtype(t, s[0])
2517 elif t == 'd':
2517 elif t == 'd':
2518 return "_intlist('%s')" % "\0".join(str(int(a)) for a in s)
2518 return "_intlist('%s')" % "\0".join(str(int(a)) for a in s)
2519 elif t == 's':
2519 elif t == 's':
2520 return "_list('%s')" % "\0".join(s)
2520 return "_list('%s')" % "\0".join(s)
2521 elif t == 'n':
2521 elif t == 'n':
2522 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s)
2522 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s)
2523 elif t == 'b':
2523 elif t == 'b':
2524 return "_list('%s')" % "\0".join(a.branch() for a in s)
2524 return "_list('%s')" % "\0".join(a.branch() for a in s)
2525
2525
2526 m = l // 2
2526 m = l // 2
2527 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t))
2527 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t))
2528
2528
2529 ret = ''
2529 ret = ''
2530 pos = 0
2530 pos = 0
2531 arg = 0
2531 arg = 0
2532 while pos < len(expr):
2532 while pos < len(expr):
2533 c = expr[pos]
2533 c = expr[pos]
2534 if c == '%':
2534 if c == '%':
2535 pos += 1
2535 pos += 1
2536 d = expr[pos]
2536 d = expr[pos]
2537 if d == '%':
2537 if d == '%':
2538 ret += d
2538 ret += d
2539 elif d in 'dsnbr':
2539 elif d in 'dsnbr':
2540 ret += argtype(d, args[arg])
2540 ret += argtype(d, args[arg])
2541 arg += 1
2541 arg += 1
2542 elif d == 'l':
2542 elif d == 'l':
2543 # a list of some type
2543 # a list of some type
2544 pos += 1
2544 pos += 1
2545 d = expr[pos]
2545 d = expr[pos]
2546 ret += listexp(list(args[arg]), d)
2546 ret += listexp(list(args[arg]), d)
2547 arg += 1
2547 arg += 1
2548 else:
2548 else:
2549 raise util.Abort('unexpected revspec format character %s' % d)
2549 raise util.Abort('unexpected revspec format character %s' % d)
2550 else:
2550 else:
2551 ret += c
2551 ret += c
2552 pos += 1
2552 pos += 1
2553
2553
2554 return ret
2554 return ret
2555
2555
2556 def prettyformat(tree):
2556 def prettyformat(tree):
2557 def _prettyformat(tree, level, lines):
2557 def _prettyformat(tree, level, lines):
2558 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
2558 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
2559 lines.append((level, str(tree)))
2559 lines.append((level, str(tree)))
2560 else:
2560 else:
2561 lines.append((level, '(%s' % tree[0]))
2561 lines.append((level, '(%s' % tree[0]))
2562 for s in tree[1:]:
2562 for s in tree[1:]:
2563 _prettyformat(s, level + 1, lines)
2563 _prettyformat(s, level + 1, lines)
2564 lines[-1:] = [(lines[-1][0], lines[-1][1] + ')')]
2564 lines[-1:] = [(lines[-1][0], lines[-1][1] + ')')]
2565
2565
2566 lines = []
2566 lines = []
2567 _prettyformat(tree, 0, lines)
2567 _prettyformat(tree, 0, lines)
2568 output = '\n'.join((' '*l + s) for l, s in lines)
2568 output = '\n'.join((' '*l + s) for l, s in lines)
2569 return output
2569 return output
2570
2570
2571 def depth(tree):
2571 def depth(tree):
2572 if isinstance(tree, tuple):
2572 if isinstance(tree, tuple):
2573 return max(map(depth, tree)) + 1
2573 return max(map(depth, tree)) + 1
2574 else:
2574 else:
2575 return 0
2575 return 0
2576
2576
2577 def funcsused(tree):
2577 def funcsused(tree):
2578 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
2578 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
2579 return set()
2579 return set()
2580 else:
2580 else:
2581 funcs = set()
2581 funcs = set()
2582 for s in tree[1:]:
2582 for s in tree[1:]:
2583 funcs |= funcsused(s)
2583 funcs |= funcsused(s)
2584 if tree[0] == 'func':
2584 if tree[0] == 'func':
2585 funcs.add(tree[1][1])
2585 funcs.add(tree[1][1])
2586 return funcs
2586 return funcs
2587
2587
2588 class abstractsmartset(object):
2588 class abstractsmartset(object):
2589
2589
2590 def __nonzero__(self):
2590 def __nonzero__(self):
2591 """True if the smartset is not empty"""
2591 """True if the smartset is not empty"""
2592 raise NotImplementedError()
2592 raise NotImplementedError()
2593
2593
2594 def __contains__(self, rev):
2594 def __contains__(self, rev):
2595 """provide fast membership testing"""
2595 """provide fast membership testing"""
2596 raise NotImplementedError()
2596 raise NotImplementedError()
2597
2597
2598 def __iter__(self):
2598 def __iter__(self):
2599 """iterate the set in the order it is supposed to be iterated"""
2599 """iterate the set in the order it is supposed to be iterated"""
2600 raise NotImplementedError()
2600 raise NotImplementedError()
2601
2601
2602 # Attributes containing a function to perform a fast iteration in a given
2602 # Attributes containing a function to perform a fast iteration in a given
2603 # direction. A smartset can have none, one, or both defined.
2603 # direction. A smartset can have none, one, or both defined.
2604 #
2604 #
2605 # Default value is None instead of a function returning None to avoid
2605 # Default value is None instead of a function returning None to avoid
2606 # initializing an iterator just for testing if a fast method exists.
2606 # initializing an iterator just for testing if a fast method exists.
2607 fastasc = None
2607 fastasc = None
2608 fastdesc = None
2608 fastdesc = None
2609
2609
2610 def isascending(self):
2610 def isascending(self):
2611 """True if the set will iterate in ascending order"""
2611 """True if the set will iterate in ascending order"""
2612 raise NotImplementedError()
2612 raise NotImplementedError()
2613
2613
2614 def isdescending(self):
2614 def isdescending(self):
2615 """True if the set will iterate in descending order"""
2615 """True if the set will iterate in descending order"""
2616 raise NotImplementedError()
2616 raise NotImplementedError()
2617
2617
2618 def min(self):
2618 def min(self):
2619 """return the minimum element in the set"""
2619 """return the minimum element in the set"""
2620 if self.fastasc is not None:
2620 if self.fastasc is not None:
2621 for r in self.fastasc():
2621 for r in self.fastasc():
2622 return r
2622 return r
2623 raise ValueError('arg is an empty sequence')
2623 raise ValueError('arg is an empty sequence')
2624 return min(self)
2624 return min(self)
2625
2625
2626 def max(self):
2626 def max(self):
2627 """return the maximum element in the set"""
2627 """return the maximum element in the set"""
2628 if self.fastdesc is not None:
2628 if self.fastdesc is not None:
2629 for r in self.fastdesc():
2629 for r in self.fastdesc():
2630 return r
2630 return r
2631 raise ValueError('arg is an empty sequence')
2631 raise ValueError('arg is an empty sequence')
2632 return max(self)
2632 return max(self)
2633
2633
2634 def first(self):
2634 def first(self):
2635 """return the first element in the set (user iteration perspective)
2635 """return the first element in the set (user iteration perspective)
2636
2636
2637 Return None if the set is empty"""
2637 Return None if the set is empty"""
2638 raise NotImplementedError()
2638 raise NotImplementedError()
2639
2639
2640 def last(self):
2640 def last(self):
2641 """return the last element in the set (user iteration perspective)
2641 """return the last element in the set (user iteration perspective)
2642
2642
2643 Return None if the set is empty"""
2643 Return None if the set is empty"""
2644 raise NotImplementedError()
2644 raise NotImplementedError()
2645
2645
2646 def __len__(self):
2646 def __len__(self):
2647 """return the length of the smartsets
2647 """return the length of the smartsets
2648
2648
2649 This can be expensive on smartset that could be lazy otherwise."""
2649 This can be expensive on smartset that could be lazy otherwise."""
2650 raise NotImplementedError()
2650 raise NotImplementedError()
2651
2651
2652 def reverse(self):
2652 def reverse(self):
2653 """reverse the expected iteration order"""
2653 """reverse the expected iteration order"""
2654 raise NotImplementedError()
2654 raise NotImplementedError()
2655
2655
2656 def sort(self, reverse=True):
2656 def sort(self, reverse=True):
2657 """get the set to iterate in an ascending or descending order"""
2657 """get the set to iterate in an ascending or descending order"""
2658 raise NotImplementedError()
2658 raise NotImplementedError()
2659
2659
2660 def __and__(self, other):
2660 def __and__(self, other):
2661 """Returns a new object with the intersection of the two collections.
2661 """Returns a new object with the intersection of the two collections.
2662
2662
2663 This is part of the mandatory API for smartset."""
2663 This is part of the mandatory API for smartset."""
2664 return self.filter(other.__contains__, cache=False)
2664 return self.filter(other.__contains__, cache=False)
2665
2665
2666 def __add__(self, other):
2666 def __add__(self, other):
2667 """Returns a new object with the union of the two collections.
2667 """Returns a new object with the union of the two collections.
2668
2668
2669 This is part of the mandatory API for smartset."""
2669 This is part of the mandatory API for smartset."""
2670 return addset(self, other)
2670 return addset(self, other)
2671
2671
2672 def __sub__(self, other):
2672 def __sub__(self, other):
2673 """Returns a new object with the substraction of the two collections.
2673 """Returns a new object with the substraction of the two collections.
2674
2674
2675 This is part of the mandatory API for smartset."""
2675 This is part of the mandatory API for smartset."""
2676 c = other.__contains__
2676 c = other.__contains__
2677 return self.filter(lambda r: not c(r), cache=False)
2677 return self.filter(lambda r: not c(r), cache=False)
2678
2678
2679 def filter(self, condition, cache=True):
2679 def filter(self, condition, cache=True):
2680 """Returns this smartset filtered by condition as a new smartset.
2680 """Returns this smartset filtered by condition as a new smartset.
2681
2681
2682 `condition` is a callable which takes a revision number and returns a
2682 `condition` is a callable which takes a revision number and returns a
2683 boolean.
2683 boolean.
2684
2684
2685 This is part of the mandatory API for smartset."""
2685 This is part of the mandatory API for smartset."""
2686 # builtin cannot be cached. but do not needs to
2686 # builtin cannot be cached. but do not needs to
2687 if cache and util.safehasattr(condition, 'func_code'):
2687 if cache and util.safehasattr(condition, 'func_code'):
2688 condition = util.cachefunc(condition)
2688 condition = util.cachefunc(condition)
2689 return filteredset(self, condition)
2689 return filteredset(self, condition)
2690
2690
2691 class baseset(abstractsmartset):
2691 class baseset(abstractsmartset):
2692 """Basic data structure that represents a revset and contains the basic
2692 """Basic data structure that represents a revset and contains the basic
2693 operation that it should be able to perform.
2693 operation that it should be able to perform.
2694
2694
2695 Every method in this class should be implemented by any smartset class.
2695 Every method in this class should be implemented by any smartset class.
2696 """
2696 """
2697 def __init__(self, data=()):
2697 def __init__(self, data=()):
2698 if not isinstance(data, list):
2698 if not isinstance(data, list):
2699 data = list(data)
2699 data = list(data)
2700 self._list = data
2700 self._list = data
2701 self._ascending = None
2701 self._ascending = None
2702
2702
2703 @util.propertycache
2703 @util.propertycache
2704 def _set(self):
2704 def _set(self):
2705 return set(self._list)
2705 return set(self._list)
2706
2706
2707 @util.propertycache
2707 @util.propertycache
2708 def _asclist(self):
2708 def _asclist(self):
2709 asclist = self._list[:]
2709 asclist = self._list[:]
2710 asclist.sort()
2710 asclist.sort()
2711 return asclist
2711 return asclist
2712
2712
2713 def __iter__(self):
2713 def __iter__(self):
2714 if self._ascending is None:
2714 if self._ascending is None:
2715 return iter(self._list)
2715 return iter(self._list)
2716 elif self._ascending:
2716 elif self._ascending:
2717 return iter(self._asclist)
2717 return iter(self._asclist)
2718 else:
2718 else:
2719 return reversed(self._asclist)
2719 return reversed(self._asclist)
2720
2720
2721 def fastasc(self):
2721 def fastasc(self):
2722 return iter(self._asclist)
2722 return iter(self._asclist)
2723
2723
2724 def fastdesc(self):
2724 def fastdesc(self):
2725 return reversed(self._asclist)
2725 return reversed(self._asclist)
2726
2726
2727 @util.propertycache
2727 @util.propertycache
2728 def __contains__(self):
2728 def __contains__(self):
2729 return self._set.__contains__
2729 return self._set.__contains__
2730
2730
2731 def __nonzero__(self):
2731 def __nonzero__(self):
2732 return bool(self._list)
2732 return bool(self._list)
2733
2733
2734 def sort(self, reverse=False):
2734 def sort(self, reverse=False):
2735 self._ascending = not bool(reverse)
2735 self._ascending = not bool(reverse)
2736
2736
2737 def reverse(self):
2737 def reverse(self):
2738 if self._ascending is None:
2738 if self._ascending is None:
2739 self._list.reverse()
2739 self._list.reverse()
2740 else:
2740 else:
2741 self._ascending = not self._ascending
2741 self._ascending = not self._ascending
2742
2742
2743 def __len__(self):
2743 def __len__(self):
2744 return len(self._list)
2744 return len(self._list)
2745
2745
2746 def isascending(self):
2746 def isascending(self):
2747 """Returns True if the collection is ascending order, False if not.
2747 """Returns True if the collection is ascending order, False if not.
2748
2748
2749 This is part of the mandatory API for smartset."""
2749 This is part of the mandatory API for smartset."""
2750 if len(self) <= 1:
2750 if len(self) <= 1:
2751 return True
2751 return True
2752 return self._ascending is not None and self._ascending
2752 return self._ascending is not None and self._ascending
2753
2753
2754 def isdescending(self):
2754 def isdescending(self):
2755 """Returns True if the collection is descending order, False if not.
2755 """Returns True if the collection is descending order, False if not.
2756
2756
2757 This is part of the mandatory API for smartset."""
2757 This is part of the mandatory API for smartset."""
2758 if len(self) <= 1:
2758 if len(self) <= 1:
2759 return True
2759 return True
2760 return self._ascending is not None and not self._ascending
2760 return self._ascending is not None and not self._ascending
2761
2761
2762 def first(self):
2762 def first(self):
2763 if self:
2763 if self:
2764 if self._ascending is None:
2764 if self._ascending is None:
2765 return self._list[0]
2765 return self._list[0]
2766 elif self._ascending:
2766 elif self._ascending:
2767 return self._asclist[0]
2767 return self._asclist[0]
2768 else:
2768 else:
2769 return self._asclist[-1]
2769 return self._asclist[-1]
2770 return None
2770 return None
2771
2771
2772 def last(self):
2772 def last(self):
2773 if self:
2773 if self:
2774 if self._ascending is None:
2774 if self._ascending is None:
2775 return self._list[-1]
2775 return self._list[-1]
2776 elif self._ascending:
2776 elif self._ascending:
2777 return self._asclist[-1]
2777 return self._asclist[-1]
2778 else:
2778 else:
2779 return self._asclist[0]
2779 return self._asclist[0]
2780 return None
2780 return None
2781
2781
2782 class filteredset(abstractsmartset):
2782 class filteredset(abstractsmartset):
2783 """Duck type for baseset class which iterates lazily over the revisions in
2783 """Duck type for baseset class which iterates lazily over the revisions in
2784 the subset and contains a function which tests for membership in the
2784 the subset and contains a function which tests for membership in the
2785 revset
2785 revset
2786 """
2786 """
2787 def __init__(self, subset, condition=lambda x: True):
2787 def __init__(self, subset, condition=lambda x: True):
2788 """
2788 """
2789 condition: a function that decide whether a revision in the subset
2789 condition: a function that decide whether a revision in the subset
2790 belongs to the revset or not.
2790 belongs to the revset or not.
2791 """
2791 """
2792 self._subset = subset
2792 self._subset = subset
2793 self._condition = condition
2793 self._condition = condition
2794 self._cache = {}
2794 self._cache = {}
2795
2795
2796 def __contains__(self, x):
2796 def __contains__(self, x):
2797 c = self._cache
2797 c = self._cache
2798 if x not in c:
2798 if x not in c:
2799 v = c[x] = x in self._subset and self._condition(x)
2799 v = c[x] = x in self._subset and self._condition(x)
2800 return v
2800 return v
2801 return c[x]
2801 return c[x]
2802
2802
2803 def __iter__(self):
2803 def __iter__(self):
2804 return self._iterfilter(self._subset)
2804 return self._iterfilter(self._subset)
2805
2805
2806 def _iterfilter(self, it):
2806 def _iterfilter(self, it):
2807 cond = self._condition
2807 cond = self._condition
2808 for x in it:
2808 for x in it:
2809 if cond(x):
2809 if cond(x):
2810 yield x
2810 yield x
2811
2811
2812 @property
2812 @property
2813 def fastasc(self):
2813 def fastasc(self):
2814 it = self._subset.fastasc
2814 it = self._subset.fastasc
2815 if it is None:
2815 if it is None:
2816 return None
2816 return None
2817 return lambda: self._iterfilter(it())
2817 return lambda: self._iterfilter(it())
2818
2818
2819 @property
2819 @property
2820 def fastdesc(self):
2820 def fastdesc(self):
2821 it = self._subset.fastdesc
2821 it = self._subset.fastdesc
2822 if it is None:
2822 if it is None:
2823 return None
2823 return None
2824 return lambda: self._iterfilter(it())
2824 return lambda: self._iterfilter(it())
2825
2825
2826 def __nonzero__(self):
2826 def __nonzero__(self):
2827 for r in self:
2827 for r in self:
2828 return True
2828 return True
2829 return False
2829 return False
2830
2830
2831 def __len__(self):
2831 def __len__(self):
2832 # Basic implementation to be changed in future patches.
2832 # Basic implementation to be changed in future patches.
2833 l = baseset([r for r in self])
2833 l = baseset([r for r in self])
2834 return len(l)
2834 return len(l)
2835
2835
2836 def sort(self, reverse=False):
2836 def sort(self, reverse=False):
2837 self._subset.sort(reverse=reverse)
2837 self._subset.sort(reverse=reverse)
2838
2838
2839 def reverse(self):
2839 def reverse(self):
2840 self._subset.reverse()
2840 self._subset.reverse()
2841
2841
2842 def isascending(self):
2842 def isascending(self):
2843 return self._subset.isascending()
2843 return self._subset.isascending()
2844
2844
2845 def isdescending(self):
2845 def isdescending(self):
2846 return self._subset.isdescending()
2846 return self._subset.isdescending()
2847
2847
2848 def first(self):
2848 def first(self):
2849 for x in self:
2849 for x in self:
2850 return x
2850 return x
2851 return None
2851 return None
2852
2852
2853 def last(self):
2853 def last(self):
2854 it = None
2854 it = None
2855 if self._subset.isascending:
2855 if self._subset.isascending:
2856 it = self.fastdesc
2856 it = self.fastdesc
2857 elif self._subset.isdescending:
2857 elif self._subset.isdescending:
2858 it = self.fastdesc
2858 it = self.fastdesc
2859 if it is None:
2859 if it is None:
2860 # slowly consume everything. This needs improvement
2860 # slowly consume everything. This needs improvement
2861 it = lambda: reversed(list(self))
2861 it = lambda: reversed(list(self))
2862 for x in it():
2862 for x in it():
2863 return x
2863 return x
2864 return None
2864 return None
2865
2865
2866 class addset(abstractsmartset):
2866 class addset(abstractsmartset):
2867 """Represent the addition of two sets
2867 """Represent the addition of two sets
2868
2868
2869 Wrapper structure for lazily adding two structures without losing much
2869 Wrapper structure for lazily adding two structures without losing much
2870 performance on the __contains__ method
2870 performance on the __contains__ method
2871
2871
2872 If the ascending attribute is set, that means the two structures are
2872 If the ascending attribute is set, that means the two structures are
2873 ordered in either an ascending or descending way. Therefore, we can add
2873 ordered in either an ascending or descending way. Therefore, we can add
2874 them maintaining the order by iterating over both at the same time
2874 them maintaining the order by iterating over both at the same time
2875 """
2875 """
2876 def __init__(self, revs1, revs2, ascending=None):
2876 def __init__(self, revs1, revs2, ascending=None):
2877 self._r1 = revs1
2877 self._r1 = revs1
2878 self._r2 = revs2
2878 self._r2 = revs2
2879 self._iter = None
2879 self._iter = None
2880 self._ascending = ascending
2880 self._ascending = ascending
2881 self._genlist = None
2881 self._genlist = None
2882 self._asclist = None
2882 self._asclist = None
2883
2883
2884 def __len__(self):
2884 def __len__(self):
2885 return len(self._list)
2885 return len(self._list)
2886
2886
2887 def __nonzero__(self):
2887 def __nonzero__(self):
2888 return bool(self._r1) or bool(self._r2)
2888 return bool(self._r1) or bool(self._r2)
2889
2889
2890 @util.propertycache
2890 @util.propertycache
2891 def _list(self):
2891 def _list(self):
2892 if not self._genlist:
2892 if not self._genlist:
2893 self._genlist = baseset(self._iterator())
2893 self._genlist = baseset(self._iterator())
2894 return self._genlist
2894 return self._genlist
2895
2895
2896 def _iterator(self):
2896 def _iterator(self):
2897 """Iterate over both collections without repeating elements
2897 """Iterate over both collections without repeating elements
2898
2898
2899 If the ascending attribute is not set, iterate over the first one and
2899 If the ascending attribute is not set, iterate over the first one and
2900 then over the second one checking for membership on the first one so we
2900 then over the second one checking for membership on the first one so we
2901 dont yield any duplicates.
2901 dont yield any duplicates.
2902
2902
2903 If the ascending attribute is set, iterate over both collections at the
2903 If the ascending attribute is set, iterate over both collections at the
2904 same time, yielding only one value at a time in the given order.
2904 same time, yielding only one value at a time in the given order.
2905 """
2905 """
2906 if self._ascending is None:
2906 if self._ascending is None:
2907 def gen():
2907 def gen():
2908 for r in self._r1:
2908 for r in self._r1:
2909 yield r
2909 yield r
2910 inr1 = self._r1.__contains__
2910 inr1 = self._r1.__contains__
2911 for r in self._r2:
2911 for r in self._r2:
2912 if not inr1(r):
2912 if not inr1(r):
2913 yield r
2913 yield r
2914 gen = gen()
2914 gen = gen()
2915 else:
2915 else:
2916 iter1 = iter(self._r1)
2916 iter1 = iter(self._r1)
2917 iter2 = iter(self._r2)
2917 iter2 = iter(self._r2)
2918 gen = self._iterordered(self._ascending, iter1, iter2)
2918 gen = self._iterordered(self._ascending, iter1, iter2)
2919 return gen
2919 return gen
2920
2920
2921 def __iter__(self):
2921 def __iter__(self):
2922 if self._ascending is None:
2922 if self._ascending is None:
2923 if self._genlist:
2923 if self._genlist:
2924 return iter(self._genlist)
2924 return iter(self._genlist)
2925 return iter(self._iterator())
2925 return iter(self._iterator())
2926 self._trysetasclist()
2926 self._trysetasclist()
2927 if self._ascending:
2927 if self._ascending:
2928 it = self.fastasc
2928 it = self.fastasc
2929 else:
2929 else:
2930 it = self.fastdesc
2930 it = self.fastdesc
2931 if it is None:
2931 if it is None:
2932 # consume the gen and try again
2932 # consume the gen and try again
2933 self._list
2933 self._list
2934 return iter(self)
2934 return iter(self)
2935 return it()
2935 return it()
2936
2936
2937 def _trysetasclist(self):
2937 def _trysetasclist(self):
2938 """populate the _asclist attribute if possible and necessary"""
2938 """populate the _asclist attribute if possible and necessary"""
2939 if self._genlist is not None and self._asclist is None:
2939 if self._genlist is not None and self._asclist is None:
2940 self._asclist = sorted(self._genlist)
2940 self._asclist = sorted(self._genlist)
2941
2941
2942 @property
2942 @property
2943 def fastasc(self):
2943 def fastasc(self):
2944 self._trysetasclist()
2944 self._trysetasclist()
2945 if self._asclist is not None:
2945 if self._asclist is not None:
2946 return self._asclist.__iter__
2946 return self._asclist.__iter__
2947 iter1 = self._r1.fastasc
2947 iter1 = self._r1.fastasc
2948 iter2 = self._r2.fastasc
2948 iter2 = self._r2.fastasc
2949 if None in (iter1, iter2):
2949 if None in (iter1, iter2):
2950 return None
2950 return None
2951 return lambda: self._iterordered(True, iter1(), iter2())
2951 return lambda: self._iterordered(True, iter1(), iter2())
2952
2952
2953 @property
2953 @property
2954 def fastdesc(self):
2954 def fastdesc(self):
2955 self._trysetasclist()
2955 self._trysetasclist()
2956 if self._asclist is not None:
2956 if self._asclist is not None:
2957 return self._asclist.__reversed__
2957 return self._asclist.__reversed__
2958 iter1 = self._r1.fastdesc
2958 iter1 = self._r1.fastdesc
2959 iter2 = self._r2.fastdesc
2959 iter2 = self._r2.fastdesc
2960 if None in (iter1, iter2):
2960 if None in (iter1, iter2):
2961 return None
2961 return None
2962 return lambda: self._iterordered(False, iter1(), iter2())
2962 return lambda: self._iterordered(False, iter1(), iter2())
2963
2963
2964 def _iterordered(self, ascending, iter1, iter2):
2964 def _iterordered(self, ascending, iter1, iter2):
2965 """produce an ordered iteration from two iterators with the same order
2965 """produce an ordered iteration from two iterators with the same order
2966
2966
2967 The ascending is used to indicated the iteration direction.
2967 The ascending is used to indicated the iteration direction.
2968 """
2968 """
2969 choice = max
2969 choice = max
2970 if ascending:
2970 if ascending:
2971 choice = min
2971 choice = min
2972
2972
2973 val1 = None
2973 val1 = None
2974 val2 = None
2974 val2 = None
2975
2975
2976 choice = max
2976 choice = max
2977 if ascending:
2977 if ascending:
2978 choice = min
2978 choice = min
2979 try:
2979 try:
2980 # Consume both iterators in an ordered way until one is
2980 # Consume both iterators in an ordered way until one is
2981 # empty
2981 # empty
2982 while True:
2982 while True:
2983 if val1 is None:
2983 if val1 is None:
2984 val1 = iter1.next()
2984 val1 = iter1.next()
2985 if val2 is None:
2985 if val2 is None:
2986 val2 = iter2.next()
2986 val2 = iter2.next()
2987 next = choice(val1, val2)
2987 next = choice(val1, val2)
2988 yield next
2988 yield next
2989 if val1 == next:
2989 if val1 == next:
2990 val1 = None
2990 val1 = None
2991 if val2 == next:
2991 if val2 == next:
2992 val2 = None
2992 val2 = None
2993 except StopIteration:
2993 except StopIteration:
2994 # Flush any remaining values and consume the other one
2994 # Flush any remaining values and consume the other one
2995 it = iter2
2995 it = iter2
2996 if val1 is not None:
2996 if val1 is not None:
2997 yield val1
2997 yield val1
2998 it = iter1
2998 it = iter1
2999 elif val2 is not None:
2999 elif val2 is not None:
3000 # might have been equality and both are empty
3000 # might have been equality and both are empty
3001 yield val2
3001 yield val2
3002 for val in it:
3002 for val in it:
3003 yield val
3003 yield val
3004
3004
3005 def __contains__(self, x):
3005 def __contains__(self, x):
3006 return x in self._r1 or x in self._r2
3006 return x in self._r1 or x in self._r2
3007
3007
3008 def sort(self, reverse=False):
3008 def sort(self, reverse=False):
3009 """Sort the added set
3009 """Sort the added set
3010
3010
3011 For this we use the cached list with all the generated values and if we
3011 For this we use the cached list with all the generated values and if we
3012 know they are ascending or descending we can sort them in a smart way.
3012 know they are ascending or descending we can sort them in a smart way.
3013 """
3013 """
3014 self._ascending = not reverse
3014 self._ascending = not reverse
3015
3015
3016 def isascending(self):
3016 def isascending(self):
3017 return self._ascending is not None and self._ascending
3017 return self._ascending is not None and self._ascending
3018
3018
3019 def isdescending(self):
3019 def isdescending(self):
3020 return self._ascending is not None and not self._ascending
3020 return self._ascending is not None and not self._ascending
3021
3021
3022 def reverse(self):
3022 def reverse(self):
3023 if self._ascending is None:
3023 if self._ascending is None:
3024 self._list.reverse()
3024 self._list.reverse()
3025 else:
3025 else:
3026 self._ascending = not self._ascending
3026 self._ascending = not self._ascending
3027
3027
3028 def first(self):
3028 def first(self):
3029 for x in self:
3029 for x in self:
3030 return x
3030 return x
3031 return None
3031 return None
3032
3032
3033 def last(self):
3033 def last(self):
3034 self.reverse()
3034 self.reverse()
3035 val = self.first()
3035 val = self.first()
3036 self.reverse()
3036 self.reverse()
3037 return val
3037 return val
3038
3038
3039 class generatorset(abstractsmartset):
3039 class generatorset(abstractsmartset):
3040 """Wrap a generator for lazy iteration
3040 """Wrap a generator for lazy iteration
3041
3041
3042 Wrapper structure for generators that provides lazy membership and can
3042 Wrapper structure for generators that provides lazy membership and can
3043 be iterated more than once.
3043 be iterated more than once.
3044 When asked for membership it generates values until either it finds the
3044 When asked for membership it generates values until either it finds the
3045 requested one or has gone through all the elements in the generator
3045 requested one or has gone through all the elements in the generator
3046 """
3046 """
3047 def __init__(self, gen, iterasc=None):
3047 def __init__(self, gen, iterasc=None):
3048 """
3048 """
3049 gen: a generator producing the values for the generatorset.
3049 gen: a generator producing the values for the generatorset.
3050 """
3050 """
3051 self._gen = gen
3051 self._gen = gen
3052 self._asclist = None
3052 self._asclist = None
3053 self._cache = {}
3053 self._cache = {}
3054 self._genlist = []
3054 self._genlist = []
3055 self._finished = False
3055 self._finished = False
3056 self._ascending = True
3056 self._ascending = True
3057 if iterasc is not None:
3057 if iterasc is not None:
3058 if iterasc:
3058 if iterasc:
3059 self.fastasc = self._iterator
3059 self.fastasc = self._iterator
3060 self.__contains__ = self._asccontains
3060 self.__contains__ = self._asccontains
3061 else:
3061 else:
3062 self.fastdesc = self._iterator
3062 self.fastdesc = self._iterator
3063 self.__contains__ = self._desccontains
3063 self.__contains__ = self._desccontains
3064
3064
3065 def __nonzero__(self):
3065 def __nonzero__(self):
3066 for r in self:
3066 for r in self:
3067 return True
3067 return True
3068 return False
3068 return False
3069
3069
3070 def __contains__(self, x):
3070 def __contains__(self, x):
3071 if x in self._cache:
3071 if x in self._cache:
3072 return self._cache[x]
3072 return self._cache[x]
3073
3073
3074 # Use new values only, as existing values would be cached.
3074 # Use new values only, as existing values would be cached.
3075 for l in self._consumegen():
3075 for l in self._consumegen():
3076 if l == x:
3076 if l == x:
3077 return True
3077 return True
3078
3078
3079 self._cache[x] = False
3079 self._cache[x] = False
3080 return False
3080 return False
3081
3081
3082 def _asccontains(self, x):
3082 def _asccontains(self, x):
3083 """version of contains optimised for ascending generator"""
3083 """version of contains optimised for ascending generator"""
3084 if x in self._cache:
3084 if x in self._cache:
3085 return self._cache[x]
3085 return self._cache[x]
3086
3086
3087 # Use new values only, as existing values would be cached.
3087 # Use new values only, as existing values would be cached.
3088 for l in self._consumegen():
3088 for l in self._consumegen():
3089 if l == x:
3089 if l == x:
3090 return True
3090 return True
3091 if l > x:
3091 if l > x:
3092 break
3092 break
3093
3093
3094 self._cache[x] = False
3094 self._cache[x] = False
3095 return False
3095 return False
3096
3096
3097 def _desccontains(self, x):
3097 def _desccontains(self, x):
3098 """version of contains optimised for descending generator"""
3098 """version of contains optimised for descending generator"""
3099 if x in self._cache:
3099 if x in self._cache:
3100 return self._cache[x]
3100 return self._cache[x]
3101
3101
3102 # Use new values only, as existing values would be cached.
3102 # Use new values only, as existing values would be cached.
3103 for l in self._consumegen():
3103 for l in self._consumegen():
3104 if l == x:
3104 if l == x:
3105 return True
3105 return True
3106 if l < x:
3106 if l < x:
3107 break
3107 break
3108
3108
3109 self._cache[x] = False
3109 self._cache[x] = False
3110 return False
3110 return False
3111
3111
3112 def __iter__(self):
3112 def __iter__(self):
3113 if self._ascending:
3113 if self._ascending:
3114 it = self.fastasc
3114 it = self.fastasc
3115 else:
3115 else:
3116 it = self.fastdesc
3116 it = self.fastdesc
3117 if it is not None:
3117 if it is not None:
3118 return it()
3118 return it()
3119 # we need to consume the iterator
3119 # we need to consume the iterator
3120 for x in self._consumegen():
3120 for x in self._consumegen():
3121 pass
3121 pass
3122 # recall the same code
3122 # recall the same code
3123 return iter(self)
3123 return iter(self)
3124
3124
3125 def _iterator(self):
3125 def _iterator(self):
3126 if self._finished:
3126 if self._finished:
3127 return iter(self._genlist)
3127 return iter(self._genlist)
3128
3128
3129 # We have to use this complex iteration strategy to allow multiple
3129 # We have to use this complex iteration strategy to allow multiple
3130 # iterations at the same time. We need to be able to catch revision
3130 # iterations at the same time. We need to be able to catch revision
3131 # removed from _consumegen and added to genlist in another instance.
3131 # removed from _consumegen and added to genlist in another instance.
3132 #
3132 #
3133 # Getting rid of it would provide an about 15% speed up on this
3133 # Getting rid of it would provide an about 15% speed up on this
3134 # iteration.
3134 # iteration.
3135 genlist = self._genlist
3135 genlist = self._genlist
3136 nextrev = self._consumegen().next
3136 nextrev = self._consumegen().next
3137 _len = len # cache global lookup
3137 _len = len # cache global lookup
3138 def gen():
3138 def gen():
3139 i = 0
3139 i = 0
3140 while True:
3140 while True:
3141 if i < _len(genlist):
3141 if i < _len(genlist):
3142 yield genlist[i]
3142 yield genlist[i]
3143 else:
3143 else:
3144 yield nextrev()
3144 yield nextrev()
3145 i += 1
3145 i += 1
3146 return gen()
3146 return gen()
3147
3147
3148 def _consumegen(self):
3148 def _consumegen(self):
3149 cache = self._cache
3149 cache = self._cache
3150 genlist = self._genlist.append
3150 genlist = self._genlist.append
3151 for item in self._gen:
3151 for item in self._gen:
3152 cache[item] = True
3152 cache[item] = True
3153 genlist(item)
3153 genlist(item)
3154 yield item
3154 yield item
3155 if not self._finished:
3155 if not self._finished:
3156 self._finished = True
3156 self._finished = True
3157 asc = self._genlist[:]
3157 asc = self._genlist[:]
3158 asc.sort()
3158 asc.sort()
3159 self._asclist = asc
3159 self._asclist = asc
3160 self.fastasc = asc.__iter__
3160 self.fastasc = asc.__iter__
3161 self.fastdesc = asc.__reversed__
3161 self.fastdesc = asc.__reversed__
3162
3162
3163 def __len__(self):
3163 def __len__(self):
3164 for x in self._consumegen():
3164 for x in self._consumegen():
3165 pass
3165 pass
3166 return len(self._genlist)
3166 return len(self._genlist)
3167
3167
3168 def sort(self, reverse=False):
3168 def sort(self, reverse=False):
3169 self._ascending = not reverse
3169 self._ascending = not reverse
3170
3170
3171 def reverse(self):
3171 def reverse(self):
3172 self._ascending = not self._ascending
3172 self._ascending = not self._ascending
3173
3173
3174 def isascending(self):
3174 def isascending(self):
3175 return self._ascending
3175 return self._ascending
3176
3176
3177 def isdescending(self):
3177 def isdescending(self):
3178 return not self._ascending
3178 return not self._ascending
3179
3179
3180 def first(self):
3180 def first(self):
3181 if self._ascending:
3181 if self._ascending:
3182 it = self.fastasc
3182 it = self.fastasc
3183 else:
3183 else:
3184 it = self.fastdesc
3184 it = self.fastdesc
3185 if it is None:
3185 if it is None:
3186 # we need to consume all and try again
3186 # we need to consume all and try again
3187 for x in self._consumegen():
3187 for x in self._consumegen():
3188 pass
3188 pass
3189 return self.first()
3189 return self.first()
3190 if self:
3190 if self:
3191 return it().next()
3191 return it().next()
3192 return None
3192 return None
3193
3193
3194 def last(self):
3194 def last(self):
3195 if self._ascending:
3195 if self._ascending:
3196 it = self.fastdesc
3196 it = self.fastdesc
3197 else:
3197 else:
3198 it = self.fastasc
3198 it = self.fastasc
3199 if it is None:
3199 if it is None:
3200 # we need to consume all and try again
3200 # we need to consume all and try again
3201 for x in self._consumegen():
3201 for x in self._consumegen():
3202 pass
3202 pass
3203 return self.first()
3203 return self.first()
3204 if self:
3204 if self:
3205 return it().next()
3205 return it().next()
3206 return None
3206 return None
3207
3207
3208 class spanset(abstractsmartset):
3208 class spanset(abstractsmartset):
3209 """Duck type for baseset class which represents a range of revisions and
3209 """Duck type for baseset class which represents a range of revisions and
3210 can work lazily and without having all the range in memory
3210 can work lazily and without having all the range in memory
3211
3211
3212 Note that spanset(x, y) behave almost like xrange(x, y) except for two
3212 Note that spanset(x, y) behave almost like xrange(x, y) except for two
3213 notable points:
3213 notable points:
3214 - when x < y it will be automatically descending,
3214 - when x < y it will be automatically descending,
3215 - revision filtered with this repoview will be skipped.
3215 - revision filtered with this repoview will be skipped.
3216
3216
3217 """
3217 """
3218 def __init__(self, repo, start=0, end=None):
3218 def __init__(self, repo, start=0, end=None):
3219 """
3219 """
3220 start: first revision included the set
3220 start: first revision included the set
3221 (default to 0)
3221 (default to 0)
3222 end: first revision excluded (last+1)
3222 end: first revision excluded (last+1)
3223 (default to len(repo)
3223 (default to len(repo)
3224
3224
3225 Spanset will be descending if `end` < `start`.
3225 Spanset will be descending if `end` < `start`.
3226 """
3226 """
3227 if end is None:
3227 if end is None:
3228 end = len(repo)
3228 end = len(repo)
3229 self._ascending = start <= end
3229 self._ascending = start <= end
3230 if not self._ascending:
3230 if not self._ascending:
3231 start, end = end + 1, start +1
3231 start, end = end + 1, start +1
3232 self._start = start
3232 self._start = start
3233 self._end = end
3233 self._end = end
3234 self._hiddenrevs = repo.changelog.filteredrevs
3234 self._hiddenrevs = repo.changelog.filteredrevs
3235
3235
3236 def sort(self, reverse=False):
3236 def sort(self, reverse=False):
3237 self._ascending = not reverse
3237 self._ascending = not reverse
3238
3238
3239 def reverse(self):
3239 def reverse(self):
3240 self._ascending = not self._ascending
3240 self._ascending = not self._ascending
3241
3241
3242 def _iterfilter(self, iterrange):
3242 def _iterfilter(self, iterrange):
3243 s = self._hiddenrevs
3243 s = self._hiddenrevs
3244 for r in iterrange:
3244 for r in iterrange:
3245 if r not in s:
3245 if r not in s:
3246 yield r
3246 yield r
3247
3247
3248 def __iter__(self):
3248 def __iter__(self):
3249 if self._ascending:
3249 if self._ascending:
3250 return self.fastasc()
3250 return self.fastasc()
3251 else:
3251 else:
3252 return self.fastdesc()
3252 return self.fastdesc()
3253
3253
3254 def fastasc(self):
3254 def fastasc(self):
3255 iterrange = xrange(self._start, self._end)
3255 iterrange = xrange(self._start, self._end)
3256 if self._hiddenrevs:
3256 if self._hiddenrevs:
3257 return self._iterfilter(iterrange)
3257 return self._iterfilter(iterrange)
3258 return iter(iterrange)
3258 return iter(iterrange)
3259
3259
3260 def fastdesc(self):
3260 def fastdesc(self):
3261 iterrange = xrange(self._end - 1, self._start - 1, -1)
3261 iterrange = xrange(self._end - 1, self._start - 1, -1)
3262 if self._hiddenrevs:
3262 if self._hiddenrevs:
3263 return self._iterfilter(iterrange)
3263 return self._iterfilter(iterrange)
3264 return iter(iterrange)
3264 return iter(iterrange)
3265
3265
3266 def __contains__(self, rev):
3266 def __contains__(self, rev):
3267 hidden = self._hiddenrevs
3267 hidden = self._hiddenrevs
3268 return ((self._start <= rev < self._end)
3268 return ((self._start <= rev < self._end)
3269 and not (hidden and rev in hidden))
3269 and not (hidden and rev in hidden))
3270
3270
3271 def __nonzero__(self):
3271 def __nonzero__(self):
3272 for r in self:
3272 for r in self:
3273 return True
3273 return True
3274 return False
3274 return False
3275
3275
3276 def __len__(self):
3276 def __len__(self):
3277 if not self._hiddenrevs:
3277 if not self._hiddenrevs:
3278 return abs(self._end - self._start)
3278 return abs(self._end - self._start)
3279 else:
3279 else:
3280 count = 0
3280 count = 0
3281 start = self._start
3281 start = self._start
3282 end = self._end
3282 end = self._end
3283 for rev in self._hiddenrevs:
3283 for rev in self._hiddenrevs:
3284 if (end < rev <= start) or (start <= rev < end):
3284 if (end < rev <= start) or (start <= rev < end):
3285 count += 1
3285 count += 1
3286 return abs(self._end - self._start) - count
3286 return abs(self._end - self._start) - count
3287
3287
3288 def isascending(self):
3288 def isascending(self):
3289 return self._ascending
3289 return self._ascending
3290
3290
3291 def isdescending(self):
3291 def isdescending(self):
3292 return not self._ascending
3292 return not self._ascending
3293
3293
3294 def first(self):
3294 def first(self):
3295 if self._ascending:
3295 if self._ascending:
3296 it = self.fastasc
3296 it = self.fastasc
3297 else:
3297 else:
3298 it = self.fastdesc
3298 it = self.fastdesc
3299 for x in it():
3299 for x in it():
3300 return x
3300 return x
3301 return None
3301 return None
3302
3302
3303 def last(self):
3303 def last(self):
3304 if self._ascending:
3304 if self._ascending:
3305 it = self.fastdesc
3305 it = self.fastdesc
3306 else:
3306 else:
3307 it = self.fastasc
3307 it = self.fastasc
3308 for x in it():
3308 for x in it():
3309 return x
3309 return x
3310 return None
3310 return None
3311
3311
3312 class fullreposet(spanset):
3312 class fullreposet(spanset):
3313 """a set containing all revisions in the repo
3313 """a set containing all revisions in the repo
3314
3314
3315 This class exists to host special optimization.
3315 This class exists to host special optimization.
3316 """
3316 """
3317
3317
3318 def __init__(self, repo):
3318 def __init__(self, repo):
3319 super(fullreposet, self).__init__(repo)
3319 super(fullreposet, self).__init__(repo)
3320
3320
3321 def __and__(self, other):
3321 def __and__(self, other):
3322 """As self contains the whole repo, all of the other set should also be
3322 """As self contains the whole repo, all of the other set should also be
3323 in self. Therefore `self & other = other`.
3323 in self. Therefore `self & other = other`.
3324
3324
3325 This boldly assumes the other contains valid revs only.
3325 This boldly assumes the other contains valid revs only.
3326 """
3326 """
3327 # other not a smartset, make is so
3327 # other not a smartset, make is so
3328 if not util.safehasattr(other, 'isascending'):
3328 if not util.safehasattr(other, 'isascending'):
3329 # filter out hidden revision
3329 # filter out hidden revision
3330 # (this boldly assumes all smartset are pure)
3330 # (this boldly assumes all smartset are pure)
3331 #
3331 #
3332 # `other` was used with "&", let's assume this is a set like
3332 # `other` was used with "&", let's assume this is a set like
3333 # object.
3333 # object.
3334 other = baseset(other - self._hiddenrevs)
3334 other = baseset(other - self._hiddenrevs)
3335
3335
3336 other.sort(reverse=self.isdescending())
3336 other.sort(reverse=self.isdescending())
3337 return other
3337 return other
3338
3338
3339 # tell hggettext to extract docstrings from these functions:
3339 # tell hggettext to extract docstrings from these functions:
3340 i18nfunctions = symbols.values()
3340 i18nfunctions = symbols.values()
@@ -1,2368 +1,2378 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)[0]
92 > tree = revset.parse(expr)[0]
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 > diff -u log.nodes glog.nodes | grep '^[-+@ ]' || :
1432 > diff -u log.nodes glog.nodes | grep '^[-+@ ]' || :
1433 > }
1433 > }
1434
1434
1435 glog always reorders nodes which explains the difference with log
1435 glog always reorders nodes which explains the difference with log
1436
1436
1437 $ testlog -r 27 -r 25 -r 21 -r 34 -r 32 -r 31
1437 $ testlog -r 27 -r 25 -r 21 -r 34 -r 32 -r 31
1438 ['27', '25', '21', '34', '32', '31']
1438 ['27', '25', '21', '34', '32', '31']
1439 []
1439 []
1440 --- log.nodes * (glob)
1440 --- log.nodes * (glob)
1441 +++ glog.nodes * (glob)
1441 +++ glog.nodes * (glob)
1442 @@ -1,6 +1,6 @@
1442 @@ -1,6 +1,6 @@
1443 -nodetag 27
1443 -nodetag 27
1444 -nodetag 25
1444 -nodetag 25
1445 -nodetag 21
1445 -nodetag 21
1446 nodetag 34
1446 nodetag 34
1447 nodetag 32
1447 nodetag 32
1448 nodetag 31
1448 nodetag 31
1449 +nodetag 27
1449 +nodetag 27
1450 +nodetag 25
1450 +nodetag 25
1451 +nodetag 21
1451 +nodetag 21
1452 $ testlog -u test -u not-a-user
1452 $ testlog -u test -u not-a-user
1453 []
1453 []
1454 (group
1454 (group
1455 (group
1455 (group
1456 (or
1456 (or
1457 (func
1457 (func
1458 ('symbol', 'user')
1458 ('symbol', 'user')
1459 ('string', 'test'))
1459 ('string', 'test'))
1460 (func
1460 (func
1461 ('symbol', 'user')
1461 ('symbol', 'user')
1462 ('string', 'not-a-user')))))
1462 ('string', 'not-a-user')))))
1463 $ testlog -b not-a-branch
1463 $ testlog -b not-a-branch
1464 abort: unknown revision 'not-a-branch'!
1464 abort: unknown revision 'not-a-branch'!
1465 abort: unknown revision '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 $ testlog -b 35 -b 36 --only-branch branch
1467 $ testlog -b 35 -b 36 --only-branch branch
1468 []
1468 []
1469 (group
1469 (group
1470 (group
1470 (group
1471 (or
1471 (or
1472 (or
1472 (or
1473 (func
1473 (func
1474 ('symbol', 'branch')
1474 ('symbol', 'branch')
1475 ('string', 'default'))
1475 ('string', 'default'))
1476 (func
1476 (func
1477 ('symbol', 'branch')
1477 ('symbol', 'branch')
1478 ('string', 'branch')))
1478 ('string', 'branch')))
1479 (func
1479 (func
1480 ('symbol', 'branch')
1480 ('symbol', 'branch')
1481 ('string', 'branch')))))
1481 ('string', 'branch')))))
1482 $ testlog -k expand -k merge
1482 $ testlog -k expand -k merge
1483 []
1483 []
1484 (group
1484 (group
1485 (group
1485 (group
1486 (or
1486 (or
1487 (func
1487 (func
1488 ('symbol', 'keyword')
1488 ('symbol', 'keyword')
1489 ('string', 'expand'))
1489 ('string', 'expand'))
1490 (func
1490 (func
1491 ('symbol', 'keyword')
1491 ('symbol', 'keyword')
1492 ('string', 'merge')))))
1492 ('string', 'merge')))))
1493 $ testlog --only-merges
1493 $ testlog --only-merges
1494 []
1494 []
1495 (group
1495 (group
1496 (func
1496 (func
1497 ('symbol', 'merge')
1497 ('symbol', 'merge')
1498 None))
1498 None))
1499 $ testlog --no-merges
1499 $ testlog --no-merges
1500 []
1500 []
1501 (group
1501 (group
1502 (not
1502 (not
1503 (func
1503 (func
1504 ('symbol', 'merge')
1504 ('symbol', 'merge')
1505 None)))
1505 None)))
1506 $ testlog --date '2 0 to 4 0'
1506 $ testlog --date '2 0 to 4 0'
1507 []
1507 []
1508 (group
1508 (group
1509 (func
1509 (func
1510 ('symbol', 'date')
1510 ('symbol', 'date')
1511 ('string', '2 0 to 4 0')))
1511 ('string', '2 0 to 4 0')))
1512 $ hg log -G -d 'brace ) in a date'
1512 $ hg log -G -d 'brace ) in a date'
1513 abort: invalid date: 'brace ) in a date'
1513 abort: invalid date: 'brace ) in a date'
1514 [255]
1514 [255]
1515 $ testlog --prune 31 --prune 32
1515 $ testlog --prune 31 --prune 32
1516 []
1516 []
1517 (group
1517 (group
1518 (group
1518 (group
1519 (and
1519 (and
1520 (not
1520 (not
1521 (group
1521 (group
1522 (or
1522 (or
1523 ('string', '31')
1523 ('string', '31')
1524 (func
1524 (func
1525 ('symbol', 'ancestors')
1525 ('symbol', 'ancestors')
1526 ('string', '31')))))
1526 ('string', '31')))))
1527 (not
1527 (not
1528 (group
1528 (group
1529 (or
1529 (or
1530 ('string', '32')
1530 ('string', '32')
1531 (func
1531 (func
1532 ('symbol', 'ancestors')
1532 ('symbol', 'ancestors')
1533 ('string', '32'))))))))
1533 ('string', '32'))))))))
1534
1534
1535 Dedicated repo for --follow and paths filtering. The g is crafted to
1535 Dedicated repo for --follow and paths filtering. The g is crafted to
1536 have 2 filelog topological heads in a linear changeset graph.
1536 have 2 filelog topological heads in a linear changeset graph.
1537
1537
1538 $ cd ..
1538 $ cd ..
1539 $ hg init follow
1539 $ hg init follow
1540 $ cd follow
1540 $ cd follow
1541 $ testlog --follow
1541 $ testlog --follow
1542 []
1542 []
1543 []
1543 []
1544 $ testlog -rnull
1544 $ testlog -rnull
1545 ['null']
1545 ['null']
1546 []
1546 []
1547 $ echo a > a
1547 $ echo a > a
1548 $ echo aa > aa
1548 $ echo aa > aa
1549 $ echo f > f
1549 $ echo f > f
1550 $ hg ci -Am "add a" a aa f
1550 $ hg ci -Am "add a" a aa f
1551 $ hg cp a b
1551 $ hg cp a b
1552 $ hg cp f g
1552 $ hg cp f g
1553 $ hg ci -m "copy a b"
1553 $ hg ci -m "copy a b"
1554 $ mkdir dir
1554 $ mkdir dir
1555 $ hg mv b dir
1555 $ hg mv b dir
1556 $ echo g >> g
1556 $ echo g >> g
1557 $ echo f >> f
1557 $ echo f >> f
1558 $ hg ci -m "mv b dir/b"
1558 $ hg ci -m "mv b dir/b"
1559 $ hg mv a b
1559 $ hg mv a b
1560 $ hg cp -f f g
1560 $ hg cp -f f g
1561 $ echo a > d
1561 $ echo a > d
1562 $ hg add d
1562 $ hg add d
1563 $ hg ci -m "mv a b; add d"
1563 $ hg ci -m "mv a b; add d"
1564 $ hg mv dir/b e
1564 $ hg mv dir/b e
1565 $ hg ci -m "mv dir/b e"
1565 $ hg ci -m "mv dir/b e"
1566 $ hg log -G --template '({rev}) {desc|firstline}\n'
1566 $ hg log -G --template '({rev}) {desc|firstline}\n'
1567 @ (4) mv dir/b e
1567 @ (4) mv dir/b e
1568 |
1568 |
1569 o (3) mv a b; add d
1569 o (3) mv a b; add d
1570 |
1570 |
1571 o (2) mv b dir/b
1571 o (2) mv b dir/b
1572 |
1572 |
1573 o (1) copy a b
1573 o (1) copy a b
1574 |
1574 |
1575 o (0) add a
1575 o (0) add a
1576
1576
1577
1577
1578 $ testlog a
1578 $ testlog a
1579 []
1579 []
1580 (group
1580 (group
1581 (group
1581 (group
1582 (func
1582 (func
1583 ('symbol', 'filelog')
1583 ('symbol', 'filelog')
1584 ('string', 'a'))))
1584 ('string', 'a'))))
1585 $ testlog a b
1585 $ testlog a b
1586 []
1586 []
1587 (group
1587 (group
1588 (group
1588 (group
1589 (or
1589 (or
1590 (func
1590 (func
1591 ('symbol', 'filelog')
1591 ('symbol', 'filelog')
1592 ('string', 'a'))
1592 ('string', 'a'))
1593 (func
1593 (func
1594 ('symbol', 'filelog')
1594 ('symbol', 'filelog')
1595 ('string', 'b')))))
1595 ('string', 'b')))))
1596
1596
1597 Test falling back to slow path for non-existing files
1597 Test falling back to slow path for non-existing files
1598
1598
1599 $ testlog a c
1599 $ testlog a c
1600 []
1600 []
1601 (group
1601 (group
1602 (func
1602 (func
1603 ('symbol', '_matchfiles')
1603 ('symbol', '_matchfiles')
1604 (list
1604 (list
1605 (list
1605 (list
1606 (list
1606 (list
1607 ('string', 'r:')
1607 ('string', 'r:')
1608 ('string', 'd:relpath'))
1608 ('string', 'd:relpath'))
1609 ('string', 'p:a'))
1609 ('string', 'p:a'))
1610 ('string', 'p:c'))))
1610 ('string', 'p:c'))))
1611
1611
1612 Test multiple --include/--exclude/paths
1612 Test multiple --include/--exclude/paths
1613
1613
1614 $ testlog --include a --include e --exclude b --exclude e a e
1614 $ testlog --include a --include e --exclude b --exclude e a e
1615 []
1615 []
1616 (group
1616 (group
1617 (func
1617 (func
1618 ('symbol', '_matchfiles')
1618 ('symbol', '_matchfiles')
1619 (list
1619 (list
1620 (list
1620 (list
1621 (list
1621 (list
1622 (list
1622 (list
1623 (list
1623 (list
1624 (list
1624 (list
1625 (list
1625 (list
1626 ('string', 'r:')
1626 ('string', 'r:')
1627 ('string', 'd:relpath'))
1627 ('string', 'd:relpath'))
1628 ('string', 'p:a'))
1628 ('string', 'p:a'))
1629 ('string', 'p:e'))
1629 ('string', 'p:e'))
1630 ('string', 'i:a'))
1630 ('string', 'i:a'))
1631 ('string', 'i:e'))
1631 ('string', 'i:e'))
1632 ('string', 'x:b'))
1632 ('string', 'x:b'))
1633 ('string', 'x:e'))))
1633 ('string', 'x:e'))))
1634
1634
1635 Test glob expansion of pats
1635 Test glob expansion of pats
1636
1636
1637 $ expandglobs=`$PYTHON -c "import mercurial.util; \
1637 $ expandglobs=`$PYTHON -c "import mercurial.util; \
1638 > print mercurial.util.expandglobs and 'true' or 'false'"`
1638 > print mercurial.util.expandglobs and 'true' or 'false'"`
1639 $ if [ $expandglobs = "true" ]; then
1639 $ if [ $expandglobs = "true" ]; then
1640 > testlog 'a*';
1640 > testlog 'a*';
1641 > else
1641 > else
1642 > testlog a*;
1642 > testlog a*;
1643 > fi;
1643 > fi;
1644 []
1644 []
1645 (group
1645 (group
1646 (group
1646 (group
1647 (func
1647 (func
1648 ('symbol', 'filelog')
1648 ('symbol', 'filelog')
1649 ('string', 'aa'))))
1649 ('string', 'aa'))))
1650
1650
1651 Test --follow on a non-existent directory
1651 Test --follow on a non-existent directory
1652
1652
1653 $ testlog -f dir
1653 $ testlog -f dir
1654 abort: cannot follow file not in parent revision: "dir"
1654 abort: cannot follow file not in parent revision: "dir"
1655 abort: cannot follow file not in parent revision: "dir"
1655 abort: cannot follow file not in parent revision: "dir"
1656 abort: cannot follow file not in parent revision: "dir"
1656 abort: cannot follow file not in parent revision: "dir"
1657
1657
1658 Test --follow on a directory
1658 Test --follow on a directory
1659
1659
1660 $ hg up -q '.^'
1660 $ hg up -q '.^'
1661 $ testlog -f dir
1661 $ testlog -f dir
1662 []
1662 []
1663 (group
1663 (group
1664 (and
1664 (and
1665 (func
1665 (func
1666 ('symbol', 'ancestors')
1666 ('symbol', 'ancestors')
1667 ('symbol', '.'))
1667 ('symbol', '.'))
1668 (func
1668 (func
1669 ('symbol', '_matchfiles')
1669 ('symbol', '_matchfiles')
1670 (list
1670 (list
1671 (list
1671 (list
1672 ('string', 'r:')
1672 ('string', 'r:')
1673 ('string', 'd:relpath'))
1673 ('string', 'd:relpath'))
1674 ('string', 'p:dir')))))
1674 ('string', 'p:dir')))))
1675 $ hg up -q tip
1675 $ hg up -q tip
1676
1676
1677 Test --follow on file not in parent revision
1677 Test --follow on file not in parent revision
1678
1678
1679 $ testlog -f a
1679 $ testlog -f a
1680 abort: cannot follow file not in parent revision: "a"
1680 abort: cannot follow file not in parent revision: "a"
1681 abort: cannot follow file not in parent revision: "a"
1681 abort: cannot follow file not in parent revision: "a"
1682 abort: cannot follow file not in parent revision: "a"
1682 abort: cannot follow file not in parent revision: "a"
1683
1683
1684 Test --follow and patterns
1684 Test --follow and patterns
1685
1685
1686 $ testlog -f 'glob:*'
1686 $ testlog -f 'glob:*'
1687 []
1687 []
1688 (group
1688 (group
1689 (and
1689 (and
1690 (func
1690 (func
1691 ('symbol', 'ancestors')
1691 ('symbol', 'ancestors')
1692 ('symbol', '.'))
1692 ('symbol', '.'))
1693 (func
1693 (func
1694 ('symbol', '_matchfiles')
1694 ('symbol', '_matchfiles')
1695 (list
1695 (list
1696 (list
1696 (list
1697 ('string', 'r:')
1697 ('string', 'r:')
1698 ('string', 'd:relpath'))
1698 ('string', 'd:relpath'))
1699 ('string', 'p:glob:*')))))
1699 ('string', 'p:glob:*')))))
1700
1700
1701 Test --follow on a single rename
1701 Test --follow on a single rename
1702
1702
1703 $ hg up -q 2
1703 $ hg up -q 2
1704 $ testlog -f a
1704 $ testlog -f a
1705 []
1705 []
1706 (group
1706 (group
1707 (group
1707 (group
1708 (func
1708 (func
1709 ('symbol', 'follow')
1709 ('symbol', 'follow')
1710 ('string', 'a'))))
1710 ('string', 'a'))))
1711
1711
1712 Test --follow and multiple renames
1712 Test --follow and multiple renames
1713
1713
1714 $ hg up -q tip
1714 $ hg up -q tip
1715 $ testlog -f e
1715 $ testlog -f e
1716 []
1716 []
1717 (group
1717 (group
1718 (group
1718 (group
1719 (func
1719 (func
1720 ('symbol', 'follow')
1720 ('symbol', 'follow')
1721 ('string', 'e'))))
1721 ('string', 'e'))))
1722
1722
1723 Test --follow and multiple filelog heads
1723 Test --follow and multiple filelog heads
1724
1724
1725 $ hg up -q 2
1725 $ hg up -q 2
1726 $ testlog -f g
1726 $ testlog -f g
1727 []
1727 []
1728 (group
1728 (group
1729 (group
1729 (group
1730 (func
1730 (func
1731 ('symbol', 'follow')
1731 ('symbol', 'follow')
1732 ('string', 'g'))))
1732 ('string', 'g'))))
1733 $ cat log.nodes
1733 $ cat log.nodes
1734 nodetag 2
1734 nodetag 2
1735 nodetag 1
1735 nodetag 1
1736 nodetag 0
1736 nodetag 0
1737 $ hg up -q tip
1737 $ hg up -q tip
1738 $ testlog -f g
1738 $ testlog -f g
1739 []
1739 []
1740 (group
1740 (group
1741 (group
1741 (group
1742 (func
1742 (func
1743 ('symbol', 'follow')
1743 ('symbol', 'follow')
1744 ('string', 'g'))))
1744 ('string', 'g'))))
1745 $ cat log.nodes
1745 $ cat log.nodes
1746 nodetag 3
1746 nodetag 3
1747 nodetag 2
1747 nodetag 2
1748 nodetag 0
1748 nodetag 0
1749
1749
1750 Test --follow and multiple files
1750 Test --follow and multiple files
1751
1751
1752 $ testlog -f g e
1752 $ testlog -f g e
1753 []
1753 []
1754 (group
1754 (group
1755 (group
1755 (group
1756 (or
1756 (or
1757 (func
1757 (func
1758 ('symbol', 'follow')
1758 ('symbol', 'follow')
1759 ('string', 'g'))
1759 ('string', 'g'))
1760 (func
1760 (func
1761 ('symbol', 'follow')
1761 ('symbol', 'follow')
1762 ('string', 'e')))))
1762 ('string', 'e')))))
1763 $ cat log.nodes
1763 $ cat log.nodes
1764 nodetag 4
1764 nodetag 4
1765 nodetag 3
1765 nodetag 3
1766 nodetag 2
1766 nodetag 2
1767 nodetag 1
1767 nodetag 1
1768 nodetag 0
1768 nodetag 0
1769
1769
1770 Test --follow null parent
1770 Test --follow null parent
1771
1771
1772 $ hg up -q null
1772 $ hg up -q null
1773 $ testlog -f
1773 $ testlog -f
1774 []
1774 []
1775 []
1775 []
1776
1776
1777 Test --follow-first
1777 Test --follow-first
1778
1778
1779 $ hg up -q 3
1779 $ hg up -q 3
1780 $ echo ee > e
1780 $ echo ee > e
1781 $ hg ci -Am "add another e" e
1781 $ hg ci -Am "add another e" e
1782 created new head
1782 created new head
1783 $ hg merge --tool internal:other 4
1783 $ hg merge --tool internal:other 4
1784 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
1784 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
1785 (branch merge, don't forget to commit)
1785 (branch merge, don't forget to commit)
1786 $ echo merge > e
1786 $ echo merge > e
1787 $ hg ci -m "merge 5 and 4"
1787 $ hg ci -m "merge 5 and 4"
1788 $ testlog --follow-first
1788 $ testlog --follow-first
1789 []
1789 []
1790 (group
1790 (group
1791 (func
1791 (func
1792 ('symbol', '_firstancestors')
1792 ('symbol', '_firstancestors')
1793 (func
1793 (func
1794 ('symbol', 'rev')
1794 ('symbol', 'rev')
1795 ('symbol', '6'))))
1795 ('symbol', '6'))))
1796
1796
1797 Cannot compare with log --follow-first FILE as it never worked
1797 Cannot compare with log --follow-first FILE as it never worked
1798
1798
1799 $ hg log -G --print-revset --follow-first e
1799 $ hg log -G --print-revset --follow-first e
1800 []
1800 []
1801 (group
1801 (group
1802 (group
1802 (group
1803 (func
1803 (func
1804 ('symbol', '_followfirst')
1804 ('symbol', '_followfirst')
1805 ('string', 'e'))))
1805 ('string', 'e'))))
1806 $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n'
1806 $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n'
1807 @ 6 merge 5 and 4
1807 @ 6 merge 5 and 4
1808 |\
1808 |\
1809 o | 5 add another e
1809 o | 5 add another e
1810 | |
1810 | |
1811
1811
1812 Test --copies
1812 Test --copies
1813
1813
1814 $ hg log -G --copies --template "{rev} {desc|firstline} \
1814 $ hg log -G --copies --template "{rev} {desc|firstline} \
1815 > copies: {file_copies_switch}\n"
1815 > copies: {file_copies_switch}\n"
1816 @ 6 merge 5 and 4 copies:
1816 @ 6 merge 5 and 4 copies:
1817 |\
1817 |\
1818 | o 5 add another e copies:
1818 | o 5 add another e copies:
1819 | |
1819 | |
1820 o | 4 mv dir/b e copies: e (dir/b)
1820 o | 4 mv dir/b e copies: e (dir/b)
1821 |/
1821 |/
1822 o 3 mv a b; add d copies: b (a)g (f)
1822 o 3 mv a b; add d copies: b (a)g (f)
1823 |
1823 |
1824 o 2 mv b dir/b copies: dir/b (b)
1824 o 2 mv b dir/b copies: dir/b (b)
1825 |
1825 |
1826 o 1 copy a b copies: b (a)g (f)
1826 o 1 copy a b copies: b (a)g (f)
1827 |
1827 |
1828 o 0 add a copies:
1828 o 0 add a copies:
1829
1829
1830 Test "set:..." and parent revision
1830 Test "set:..." and parent revision
1831
1831
1832 $ hg up -q 4
1832 $ hg up -q 4
1833 $ testlog "set:copied()"
1833 $ testlog "set:copied()"
1834 []
1834 []
1835 (group
1835 (group
1836 (func
1836 (func
1837 ('symbol', '_matchfiles')
1837 ('symbol', '_matchfiles')
1838 (list
1838 (list
1839 (list
1839 (list
1840 ('string', 'r:')
1840 ('string', 'r:')
1841 ('string', 'd:relpath'))
1841 ('string', 'd:relpath'))
1842 ('string', 'p:set:copied()'))))
1842 ('string', 'p:set:copied()'))))
1843 $ testlog --include "set:copied()"
1843 $ testlog --include "set:copied()"
1844 []
1844 []
1845 (group
1845 (group
1846 (func
1846 (func
1847 ('symbol', '_matchfiles')
1847 ('symbol', '_matchfiles')
1848 (list
1848 (list
1849 (list
1849 (list
1850 ('string', 'r:')
1850 ('string', 'r:')
1851 ('string', 'd:relpath'))
1851 ('string', 'd:relpath'))
1852 ('string', 'i:set:copied()'))))
1852 ('string', 'i:set:copied()'))))
1853 $ testlog -r "sort(file('set:copied()'), -rev)"
1853 $ testlog -r "sort(file('set:copied()'), -rev)"
1854 ["sort(file('set:copied()'), -rev)"]
1854 ["sort(file('set:copied()'), -rev)"]
1855 []
1855 []
1856
1856
1857 Test --removed
1857 Test --removed
1858
1858
1859 $ testlog --removed
1859 $ testlog --removed
1860 []
1860 []
1861 []
1861 []
1862 $ testlog --removed a
1862 $ testlog --removed a
1863 []
1863 []
1864 (group
1864 (group
1865 (func
1865 (func
1866 ('symbol', '_matchfiles')
1866 ('symbol', '_matchfiles')
1867 (list
1867 (list
1868 (list
1868 (list
1869 ('string', 'r:')
1869 ('string', 'r:')
1870 ('string', 'd:relpath'))
1870 ('string', 'd:relpath'))
1871 ('string', 'p:a'))))
1871 ('string', 'p:a'))))
1872 $ testlog --removed --follow a
1872 $ testlog --removed --follow a
1873 []
1873 []
1874 (group
1874 (group
1875 (and
1875 (and
1876 (func
1876 (func
1877 ('symbol', 'ancestors')
1877 ('symbol', 'ancestors')
1878 ('symbol', '.'))
1878 ('symbol', '.'))
1879 (func
1879 (func
1880 ('symbol', '_matchfiles')
1880 ('symbol', '_matchfiles')
1881 (list
1881 (list
1882 (list
1882 (list
1883 ('string', 'r:')
1883 ('string', 'r:')
1884 ('string', 'd:relpath'))
1884 ('string', 'd:relpath'))
1885 ('string', 'p:a')))))
1885 ('string', 'p:a')))))
1886
1886
1887 Test --patch and --stat with --follow and --follow-first
1887 Test --patch and --stat with --follow and --follow-first
1888
1888
1889 $ hg up -q 3
1889 $ hg up -q 3
1890 $ hg log -G --git --patch b
1890 $ hg log -G --git --patch b
1891 o changeset: 1:216d4c92cf98
1891 o changeset: 1:216d4c92cf98
1892 | user: test
1892 | user: test
1893 | date: Thu Jan 01 00:00:00 1970 +0000
1893 | date: Thu Jan 01 00:00:00 1970 +0000
1894 | summary: copy a b
1894 | summary: copy a b
1895 |
1895 |
1896 | diff --git a/a b/b
1896 | diff --git a/a b/b
1897 | copy from a
1897 | copy from a
1898 | copy to b
1898 | copy to b
1899 |
1899 |
1900
1900
1901 $ hg log -G --git --stat b
1901 $ hg log -G --git --stat b
1902 o changeset: 1:216d4c92cf98
1902 o changeset: 1:216d4c92cf98
1903 | user: test
1903 | user: test
1904 | date: Thu Jan 01 00:00:00 1970 +0000
1904 | date: Thu Jan 01 00:00:00 1970 +0000
1905 | summary: copy a b
1905 | summary: copy a b
1906 |
1906 |
1907 | b | 0
1907 | b | 0
1908 | 1 files changed, 0 insertions(+), 0 deletions(-)
1908 | 1 files changed, 0 insertions(+), 0 deletions(-)
1909 |
1909 |
1910
1910
1911 $ hg log -G --git --patch --follow b
1911 $ hg log -G --git --patch --follow b
1912 o changeset: 1:216d4c92cf98
1912 o changeset: 1:216d4c92cf98
1913 | user: test
1913 | user: test
1914 | date: Thu Jan 01 00:00:00 1970 +0000
1914 | date: Thu Jan 01 00:00:00 1970 +0000
1915 | summary: copy a b
1915 | summary: copy a b
1916 |
1916 |
1917 | diff --git a/a b/b
1917 | diff --git a/a b/b
1918 | copy from a
1918 | copy from a
1919 | copy to b
1919 | copy to b
1920 |
1920 |
1921 o changeset: 0:f8035bb17114
1921 o changeset: 0:f8035bb17114
1922 user: test
1922 user: test
1923 date: Thu Jan 01 00:00:00 1970 +0000
1923 date: Thu Jan 01 00:00:00 1970 +0000
1924 summary: add a
1924 summary: add a
1925
1925
1926 diff --git a/a b/a
1926 diff --git a/a b/a
1927 new file mode 100644
1927 new file mode 100644
1928 --- /dev/null
1928 --- /dev/null
1929 +++ b/a
1929 +++ b/a
1930 @@ -0,0 +1,1 @@
1930 @@ -0,0 +1,1 @@
1931 +a
1931 +a
1932
1932
1933
1933
1934 $ hg log -G --git --stat --follow b
1934 $ hg log -G --git --stat --follow b
1935 o changeset: 1:216d4c92cf98
1935 o changeset: 1:216d4c92cf98
1936 | user: test
1936 | user: test
1937 | date: Thu Jan 01 00:00:00 1970 +0000
1937 | date: Thu Jan 01 00:00:00 1970 +0000
1938 | summary: copy a b
1938 | summary: copy a b
1939 |
1939 |
1940 | b | 0
1940 | b | 0
1941 | 1 files changed, 0 insertions(+), 0 deletions(-)
1941 | 1 files changed, 0 insertions(+), 0 deletions(-)
1942 |
1942 |
1943 o changeset: 0:f8035bb17114
1943 o changeset: 0:f8035bb17114
1944 user: test
1944 user: test
1945 date: Thu Jan 01 00:00:00 1970 +0000
1945 date: Thu Jan 01 00:00:00 1970 +0000
1946 summary: add a
1946 summary: add a
1947
1947
1948 a | 1 +
1948 a | 1 +
1949 1 files changed, 1 insertions(+), 0 deletions(-)
1949 1 files changed, 1 insertions(+), 0 deletions(-)
1950
1950
1951
1951
1952 $ hg up -q 6
1952 $ hg up -q 6
1953 $ hg log -G --git --patch --follow-first e
1953 $ hg log -G --git --patch --follow-first e
1954 @ changeset: 6:fc281d8ff18d
1954 @ changeset: 6:fc281d8ff18d
1955 |\ tag: tip
1955 |\ tag: tip
1956 | | parent: 5:99b31f1c2782
1956 | | parent: 5:99b31f1c2782
1957 | | parent: 4:17d952250a9d
1957 | | parent: 4:17d952250a9d
1958 | | user: test
1958 | | user: test
1959 | | date: Thu Jan 01 00:00:00 1970 +0000
1959 | | date: Thu Jan 01 00:00:00 1970 +0000
1960 | | summary: merge 5 and 4
1960 | | summary: merge 5 and 4
1961 | |
1961 | |
1962 | | diff --git a/e b/e
1962 | | diff --git a/e b/e
1963 | | --- a/e
1963 | | --- a/e
1964 | | +++ b/e
1964 | | +++ b/e
1965 | | @@ -1,1 +1,1 @@
1965 | | @@ -1,1 +1,1 @@
1966 | | -ee
1966 | | -ee
1967 | | +merge
1967 | | +merge
1968 | |
1968 | |
1969 o | changeset: 5:99b31f1c2782
1969 o | changeset: 5:99b31f1c2782
1970 | | parent: 3:5918b8d165d1
1970 | | parent: 3:5918b8d165d1
1971 | | user: test
1971 | | user: test
1972 | | date: Thu Jan 01 00:00:00 1970 +0000
1972 | | date: Thu Jan 01 00:00:00 1970 +0000
1973 | | summary: add another e
1973 | | summary: add another e
1974 | |
1974 | |
1975 | | diff --git a/e b/e
1975 | | diff --git a/e b/e
1976 | | new file mode 100644
1976 | | new file mode 100644
1977 | | --- /dev/null
1977 | | --- /dev/null
1978 | | +++ b/e
1978 | | +++ b/e
1979 | | @@ -0,0 +1,1 @@
1979 | | @@ -0,0 +1,1 @@
1980 | | +ee
1980 | | +ee
1981 | |
1981 | |
1982
1982
1983 Test old-style --rev
1983 Test old-style --rev
1984
1984
1985 $ hg tag 'foo-bar'
1985 $ hg tag 'foo-bar'
1986 $ testlog -r 'foo-bar'
1986 $ testlog -r 'foo-bar'
1987 ['foo-bar']
1987 ['foo-bar']
1988 []
1988 []
1989
1989
1990 Test --follow and forward --rev
1990 Test --follow and forward --rev
1991
1991
1992 $ hg up -q 6
1992 $ hg up -q 6
1993 $ echo g > g
1993 $ echo g > g
1994 $ hg ci -Am 'add g' g
1994 $ hg ci -Am 'add g' g
1995 created new head
1995 created new head
1996 $ hg up -q 2
1996 $ hg up -q 2
1997 $ hg log -G --template "{rev} {desc|firstline}\n"
1997 $ hg log -G --template "{rev} {desc|firstline}\n"
1998 o 8 add g
1998 o 8 add g
1999 |
1999 |
2000 | o 7 Added tag foo-bar for changeset fc281d8ff18d
2000 | o 7 Added tag foo-bar for changeset fc281d8ff18d
2001 |/
2001 |/
2002 o 6 merge 5 and 4
2002 o 6 merge 5 and 4
2003 |\
2003 |\
2004 | o 5 add another e
2004 | o 5 add another e
2005 | |
2005 | |
2006 o | 4 mv dir/b e
2006 o | 4 mv dir/b e
2007 |/
2007 |/
2008 o 3 mv a b; add d
2008 o 3 mv a b; add d
2009 |
2009 |
2010 @ 2 mv b dir/b
2010 @ 2 mv b dir/b
2011 |
2011 |
2012 o 1 copy a b
2012 o 1 copy a b
2013 |
2013 |
2014 o 0 add a
2014 o 0 add a
2015
2015
2016 $ hg export 'all()'
2016 $ hg export 'all()'
2017 # HG changeset patch
2017 # HG changeset patch
2018 # User test
2018 # User test
2019 # Date 0 0
2019 # Date 0 0
2020 # Thu Jan 01 00:00:00 1970 +0000
2020 # Thu Jan 01 00:00:00 1970 +0000
2021 # Node ID f8035bb17114da16215af3436ec5222428ace8ee
2021 # Node ID f8035bb17114da16215af3436ec5222428ace8ee
2022 # Parent 0000000000000000000000000000000000000000
2022 # Parent 0000000000000000000000000000000000000000
2023 add a
2023 add a
2024
2024
2025 diff -r 000000000000 -r f8035bb17114 a
2025 diff -r 000000000000 -r f8035bb17114 a
2026 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2026 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2027 +++ b/a Thu Jan 01 00:00:00 1970 +0000
2027 +++ b/a Thu Jan 01 00:00:00 1970 +0000
2028 @@ -0,0 +1,1 @@
2028 @@ -0,0 +1,1 @@
2029 +a
2029 +a
2030 diff -r 000000000000 -r f8035bb17114 aa
2030 diff -r 000000000000 -r f8035bb17114 aa
2031 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2031 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2032 +++ b/aa Thu Jan 01 00:00:00 1970 +0000
2032 +++ b/aa Thu Jan 01 00:00:00 1970 +0000
2033 @@ -0,0 +1,1 @@
2033 @@ -0,0 +1,1 @@
2034 +aa
2034 +aa
2035 diff -r 000000000000 -r f8035bb17114 f
2035 diff -r 000000000000 -r f8035bb17114 f
2036 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2036 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2037 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2037 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2038 @@ -0,0 +1,1 @@
2038 @@ -0,0 +1,1 @@
2039 +f
2039 +f
2040 # HG changeset patch
2040 # HG changeset patch
2041 # User test
2041 # User test
2042 # Date 0 0
2042 # Date 0 0
2043 # Thu Jan 01 00:00:00 1970 +0000
2043 # Thu Jan 01 00:00:00 1970 +0000
2044 # Node ID 216d4c92cf98ff2b4641d508b76b529f3d424c92
2044 # Node ID 216d4c92cf98ff2b4641d508b76b529f3d424c92
2045 # Parent f8035bb17114da16215af3436ec5222428ace8ee
2045 # Parent f8035bb17114da16215af3436ec5222428ace8ee
2046 copy a b
2046 copy a b
2047
2047
2048 diff -r f8035bb17114 -r 216d4c92cf98 b
2048 diff -r f8035bb17114 -r 216d4c92cf98 b
2049 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2049 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2050 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2050 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2051 @@ -0,0 +1,1 @@
2051 @@ -0,0 +1,1 @@
2052 +a
2052 +a
2053 diff -r f8035bb17114 -r 216d4c92cf98 g
2053 diff -r f8035bb17114 -r 216d4c92cf98 g
2054 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2054 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2055 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2055 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2056 @@ -0,0 +1,1 @@
2056 @@ -0,0 +1,1 @@
2057 +f
2057 +f
2058 # HG changeset patch
2058 # HG changeset patch
2059 # User test
2059 # User test
2060 # Date 0 0
2060 # Date 0 0
2061 # Thu Jan 01 00:00:00 1970 +0000
2061 # Thu Jan 01 00:00:00 1970 +0000
2062 # Node ID bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2062 # Node ID bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2063 # Parent 216d4c92cf98ff2b4641d508b76b529f3d424c92
2063 # Parent 216d4c92cf98ff2b4641d508b76b529f3d424c92
2064 mv b dir/b
2064 mv b dir/b
2065
2065
2066 diff -r 216d4c92cf98 -r bb573313a9e8 b
2066 diff -r 216d4c92cf98 -r bb573313a9e8 b
2067 --- a/b Thu Jan 01 00:00:00 1970 +0000
2067 --- a/b Thu Jan 01 00:00:00 1970 +0000
2068 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2068 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2069 @@ -1,1 +0,0 @@
2069 @@ -1,1 +0,0 @@
2070 -a
2070 -a
2071 diff -r 216d4c92cf98 -r bb573313a9e8 dir/b
2071 diff -r 216d4c92cf98 -r bb573313a9e8 dir/b
2072 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2072 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2073 +++ b/dir/b Thu Jan 01 00:00:00 1970 +0000
2073 +++ b/dir/b Thu Jan 01 00:00:00 1970 +0000
2074 @@ -0,0 +1,1 @@
2074 @@ -0,0 +1,1 @@
2075 +a
2075 +a
2076 diff -r 216d4c92cf98 -r bb573313a9e8 f
2076 diff -r 216d4c92cf98 -r bb573313a9e8 f
2077 --- a/f Thu Jan 01 00:00:00 1970 +0000
2077 --- a/f Thu Jan 01 00:00:00 1970 +0000
2078 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2078 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2079 @@ -1,1 +1,2 @@
2079 @@ -1,1 +1,2 @@
2080 f
2080 f
2081 +f
2081 +f
2082 diff -r 216d4c92cf98 -r bb573313a9e8 g
2082 diff -r 216d4c92cf98 -r bb573313a9e8 g
2083 --- a/g Thu Jan 01 00:00:00 1970 +0000
2083 --- a/g Thu Jan 01 00:00:00 1970 +0000
2084 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2084 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2085 @@ -1,1 +1,2 @@
2085 @@ -1,1 +1,2 @@
2086 f
2086 f
2087 +g
2087 +g
2088 # HG changeset patch
2088 # HG changeset patch
2089 # User test
2089 # User test
2090 # Date 0 0
2090 # Date 0 0
2091 # Thu Jan 01 00:00:00 1970 +0000
2091 # Thu Jan 01 00:00:00 1970 +0000
2092 # Node ID 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2092 # Node ID 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2093 # Parent bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2093 # Parent bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2094 mv a b; add d
2094 mv a b; add d
2095
2095
2096 diff -r bb573313a9e8 -r 5918b8d165d1 a
2096 diff -r bb573313a9e8 -r 5918b8d165d1 a
2097 --- a/a Thu Jan 01 00:00:00 1970 +0000
2097 --- a/a Thu Jan 01 00:00:00 1970 +0000
2098 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2098 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2099 @@ -1,1 +0,0 @@
2099 @@ -1,1 +0,0 @@
2100 -a
2100 -a
2101 diff -r bb573313a9e8 -r 5918b8d165d1 b
2101 diff -r bb573313a9e8 -r 5918b8d165d1 b
2102 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2102 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2103 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2103 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2104 @@ -0,0 +1,1 @@
2104 @@ -0,0 +1,1 @@
2105 +a
2105 +a
2106 diff -r bb573313a9e8 -r 5918b8d165d1 d
2106 diff -r bb573313a9e8 -r 5918b8d165d1 d
2107 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2107 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2108 +++ b/d Thu Jan 01 00:00:00 1970 +0000
2108 +++ b/d Thu Jan 01 00:00:00 1970 +0000
2109 @@ -0,0 +1,1 @@
2109 @@ -0,0 +1,1 @@
2110 +a
2110 +a
2111 diff -r bb573313a9e8 -r 5918b8d165d1 g
2111 diff -r bb573313a9e8 -r 5918b8d165d1 g
2112 --- a/g Thu Jan 01 00:00:00 1970 +0000
2112 --- a/g Thu Jan 01 00:00:00 1970 +0000
2113 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2113 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2114 @@ -1,2 +1,2 @@
2114 @@ -1,2 +1,2 @@
2115 f
2115 f
2116 -g
2116 -g
2117 +f
2117 +f
2118 # HG changeset patch
2118 # HG changeset patch
2119 # User test
2119 # User test
2120 # Date 0 0
2120 # Date 0 0
2121 # Thu Jan 01 00:00:00 1970 +0000
2121 # Thu Jan 01 00:00:00 1970 +0000
2122 # Node ID 17d952250a9d03cc3dc77b199ab60e959b9b0260
2122 # Node ID 17d952250a9d03cc3dc77b199ab60e959b9b0260
2123 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2123 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2124 mv dir/b e
2124 mv dir/b e
2125
2125
2126 diff -r 5918b8d165d1 -r 17d952250a9d dir/b
2126 diff -r 5918b8d165d1 -r 17d952250a9d dir/b
2127 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2127 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2128 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2128 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2129 @@ -1,1 +0,0 @@
2129 @@ -1,1 +0,0 @@
2130 -a
2130 -a
2131 diff -r 5918b8d165d1 -r 17d952250a9d e
2131 diff -r 5918b8d165d1 -r 17d952250a9d e
2132 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2132 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2133 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2133 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2134 @@ -0,0 +1,1 @@
2134 @@ -0,0 +1,1 @@
2135 +a
2135 +a
2136 # HG changeset patch
2136 # HG changeset patch
2137 # User test
2137 # User test
2138 # Date 0 0
2138 # Date 0 0
2139 # Thu Jan 01 00:00:00 1970 +0000
2139 # Thu Jan 01 00:00:00 1970 +0000
2140 # Node ID 99b31f1c2782e2deb1723cef08930f70fc84b37b
2140 # Node ID 99b31f1c2782e2deb1723cef08930f70fc84b37b
2141 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2141 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2142 add another e
2142 add another e
2143
2143
2144 diff -r 5918b8d165d1 -r 99b31f1c2782 e
2144 diff -r 5918b8d165d1 -r 99b31f1c2782 e
2145 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2145 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2146 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2146 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2147 @@ -0,0 +1,1 @@
2147 @@ -0,0 +1,1 @@
2148 +ee
2148 +ee
2149 # HG changeset patch
2149 # HG changeset patch
2150 # User test
2150 # User test
2151 # Date 0 0
2151 # Date 0 0
2152 # Thu Jan 01 00:00:00 1970 +0000
2152 # Thu Jan 01 00:00:00 1970 +0000
2153 # Node ID fc281d8ff18d999ad6497b3d27390bcd695dcc73
2153 # Node ID fc281d8ff18d999ad6497b3d27390bcd695dcc73
2154 # Parent 99b31f1c2782e2deb1723cef08930f70fc84b37b
2154 # Parent 99b31f1c2782e2deb1723cef08930f70fc84b37b
2155 # Parent 17d952250a9d03cc3dc77b199ab60e959b9b0260
2155 # Parent 17d952250a9d03cc3dc77b199ab60e959b9b0260
2156 merge 5 and 4
2156 merge 5 and 4
2157
2157
2158 diff -r 99b31f1c2782 -r fc281d8ff18d dir/b
2158 diff -r 99b31f1c2782 -r fc281d8ff18d dir/b
2159 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2159 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2160 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2160 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2161 @@ -1,1 +0,0 @@
2161 @@ -1,1 +0,0 @@
2162 -a
2162 -a
2163 diff -r 99b31f1c2782 -r fc281d8ff18d e
2163 diff -r 99b31f1c2782 -r fc281d8ff18d e
2164 --- a/e Thu Jan 01 00:00:00 1970 +0000
2164 --- a/e Thu Jan 01 00:00:00 1970 +0000
2165 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2165 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2166 @@ -1,1 +1,1 @@
2166 @@ -1,1 +1,1 @@
2167 -ee
2167 -ee
2168 +merge
2168 +merge
2169 # HG changeset patch
2169 # HG changeset patch
2170 # User test
2170 # User test
2171 # Date 0 0
2171 # Date 0 0
2172 # Thu Jan 01 00:00:00 1970 +0000
2172 # Thu Jan 01 00:00:00 1970 +0000
2173 # Node ID 02dbb8e276b8ab7abfd07cab50c901647e75c2dd
2173 # Node ID 02dbb8e276b8ab7abfd07cab50c901647e75c2dd
2174 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2174 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2175 Added tag foo-bar for changeset fc281d8ff18d
2175 Added tag foo-bar for changeset fc281d8ff18d
2176
2176
2177 diff -r fc281d8ff18d -r 02dbb8e276b8 .hgtags
2177 diff -r fc281d8ff18d -r 02dbb8e276b8 .hgtags
2178 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2178 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2179 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2179 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2180 @@ -0,0 +1,1 @@
2180 @@ -0,0 +1,1 @@
2181 +fc281d8ff18d999ad6497b3d27390bcd695dcc73 foo-bar
2181 +fc281d8ff18d999ad6497b3d27390bcd695dcc73 foo-bar
2182 # HG changeset patch
2182 # HG changeset patch
2183 # User test
2183 # User test
2184 # Date 0 0
2184 # Date 0 0
2185 # Thu Jan 01 00:00:00 1970 +0000
2185 # Thu Jan 01 00:00:00 1970 +0000
2186 # Node ID 24c2e826ddebf80f9dcd60b856bdb8e6715c5449
2186 # Node ID 24c2e826ddebf80f9dcd60b856bdb8e6715c5449
2187 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2187 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2188 add g
2188 add g
2189
2189
2190 diff -r fc281d8ff18d -r 24c2e826ddeb g
2190 diff -r fc281d8ff18d -r 24c2e826ddeb g
2191 --- a/g Thu Jan 01 00:00:00 1970 +0000
2191 --- a/g Thu Jan 01 00:00:00 1970 +0000
2192 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2192 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2193 @@ -1,2 +1,1 @@
2193 @@ -1,2 +1,1 @@
2194 -f
2194 -f
2195 -f
2195 -f
2196 +g
2196 +g
2197 $ testlog --follow -r6 -r8 -r5 -r7 -r4
2197 $ testlog --follow -r6 -r8 -r5 -r7 -r4
2198 ['6', '8', '5', '7', '4']
2198 ['6', '8', '5', '7', '4']
2199 (group
2199 (group
2200 (func
2200 (func
2201 ('symbol', 'descendants')
2201 ('symbol', 'descendants')
2202 (func
2202 (func
2203 ('symbol', 'rev')
2203 ('symbol', 'rev')
2204 ('symbol', '6'))))
2204 ('symbol', '6'))))
2205
2205
2206 Test --follow-first and forward --rev
2206 Test --follow-first and forward --rev
2207
2207
2208 $ testlog --follow-first -r6 -r8 -r5 -r7 -r4
2208 $ testlog --follow-first -r6 -r8 -r5 -r7 -r4
2209 ['6', '8', '5', '7', '4']
2209 ['6', '8', '5', '7', '4']
2210 (group
2210 (group
2211 (func
2211 (func
2212 ('symbol', '_firstdescendants')
2212 ('symbol', '_firstdescendants')
2213 (func
2213 (func
2214 ('symbol', 'rev')
2214 ('symbol', 'rev')
2215 ('symbol', '6'))))
2215 ('symbol', '6'))))
2216 --- log.nodes * (glob)
2216 --- log.nodes * (glob)
2217 +++ glog.nodes * (glob)
2217 +++ glog.nodes * (glob)
2218 @@ -1,3 +1,3 @@
2218 @@ -1,3 +1,3 @@
2219 -nodetag 6
2219 -nodetag 6
2220 nodetag 8
2220 nodetag 8
2221 nodetag 7
2221 nodetag 7
2222 +nodetag 6
2222 +nodetag 6
2223
2223
2224 Test --follow and backward --rev
2224 Test --follow and backward --rev
2225
2225
2226 $ testlog --follow -r6 -r5 -r7 -r8 -r4
2226 $ testlog --follow -r6 -r5 -r7 -r8 -r4
2227 ['6', '5', '7', '8', '4']
2227 ['6', '5', '7', '8', '4']
2228 (group
2228 (group
2229 (func
2229 (func
2230 ('symbol', 'ancestors')
2230 ('symbol', 'ancestors')
2231 (func
2231 (func
2232 ('symbol', 'rev')
2232 ('symbol', 'rev')
2233 ('symbol', '6'))))
2233 ('symbol', '6'))))
2234
2234
2235 Test --follow-first and backward --rev
2235 Test --follow-first and backward --rev
2236
2236
2237 $ testlog --follow-first -r6 -r5 -r7 -r8 -r4
2237 $ testlog --follow-first -r6 -r5 -r7 -r8 -r4
2238 ['6', '5', '7', '8', '4']
2238 ['6', '5', '7', '8', '4']
2239 (group
2239 (group
2240 (func
2240 (func
2241 ('symbol', '_firstancestors')
2241 ('symbol', '_firstancestors')
2242 (func
2242 (func
2243 ('symbol', 'rev')
2243 ('symbol', 'rev')
2244 ('symbol', '6'))))
2244 ('symbol', '6'))))
2245
2245
2246 Test --follow with --rev of graphlog extension
2246 Test --follow with --rev of graphlog extension
2247
2247
2248 $ hg --config extensions.graphlog= glog -qfr1
2248 $ hg --config extensions.graphlog= glog -qfr1
2249 o 1:216d4c92cf98
2249 o 1:216d4c92cf98
2250 |
2250 |
2251 o 0:f8035bb17114
2251 o 0:f8035bb17114
2252
2252
2253
2253
2254 Test subdir
2254 Test subdir
2255
2255
2256 $ hg up -q 3
2256 $ hg up -q 3
2257 $ cd dir
2257 $ cd dir
2258 $ testlog .
2258 $ testlog .
2259 []
2259 []
2260 (group
2260 (group
2261 (func
2261 (func
2262 ('symbol', '_matchfiles')
2262 ('symbol', '_matchfiles')
2263 (list
2263 (list
2264 (list
2264 (list
2265 ('string', 'r:')
2265 ('string', 'r:')
2266 ('string', 'd:relpath'))
2266 ('string', 'd:relpath'))
2267 ('string', 'p:.'))))
2267 ('string', 'p:.'))))
2268 $ testlog ../b
2268 $ testlog ../b
2269 []
2269 []
2270 (group
2270 (group
2271 (group
2271 (group
2272 (func
2272 (func
2273 ('symbol', 'filelog')
2273 ('symbol', 'filelog')
2274 ('string', '../b'))))
2274 ('string', '../b'))))
2275 $ testlog -f ../b
2275 $ testlog -f ../b
2276 []
2276 []
2277 (group
2277 (group
2278 (group
2278 (group
2279 (func
2279 (func
2280 ('symbol', 'follow')
2280 ('symbol', 'follow')
2281 ('string', 'b'))))
2281 ('string', 'b'))))
2282 $ cd ..
2282 $ cd ..
2283
2283
2284 Test --hidden
2284 Test --hidden
2285 (enable obsolete)
2285 (enable obsolete)
2286
2286
2287 $ cat >> $HGRCPATH << EOF
2287 $ cat >> $HGRCPATH << EOF
2288 > [experimental]
2288 > [experimental]
2289 > evolution=createmarkers
2289 > evolution=createmarkers
2290 > EOF
2290 > EOF
2291
2291
2292 $ hg debugobsolete `hg id --debug -i -r 8`
2292 $ hg debugobsolete `hg id --debug -i -r 8`
2293 $ testlog
2293 $ testlog
2294 []
2294 []
2295 []
2295 []
2296 $ testlog --hidden
2296 $ testlog --hidden
2297 []
2297 []
2298 []
2298 []
2299 $ hg log -G --template '{rev} {desc}\n'
2299 $ hg log -G --template '{rev} {desc}\n'
2300 o 7 Added tag foo-bar for changeset fc281d8ff18d
2300 o 7 Added tag foo-bar for changeset fc281d8ff18d
2301 |
2301 |
2302 o 6 merge 5 and 4
2302 o 6 merge 5 and 4
2303 |\
2303 |\
2304 | o 5 add another e
2304 | o 5 add another e
2305 | |
2305 | |
2306 o | 4 mv dir/b e
2306 o | 4 mv dir/b e
2307 |/
2307 |/
2308 @ 3 mv a b; add d
2308 @ 3 mv a b; add d
2309 |
2309 |
2310 o 2 mv b dir/b
2310 o 2 mv b dir/b
2311 |
2311 |
2312 o 1 copy a b
2312 o 1 copy a b
2313 |
2313 |
2314 o 0 add a
2314 o 0 add a
2315
2315
2316
2316
2317 A template without trailing newline should do something sane
2317 A template without trailing newline should do something sane
2318
2318
2319 $ hg log -G -r ::2 --template '{rev} {desc}'
2319 $ hg log -G -r ::2 --template '{rev} {desc}'
2320 o 2 mv b dir/b
2320 o 2 mv b dir/b
2321 |
2321 |
2322 o 1 copy a b
2322 o 1 copy a b
2323 |
2323 |
2324 o 0 add a
2324 o 0 add a
2325
2325
2326
2326
2327 Extra newlines must be preserved
2327 Extra newlines must be preserved
2328
2328
2329 $ hg log -G -r ::2 --template '\n{rev} {desc}\n\n'
2329 $ hg log -G -r ::2 --template '\n{rev} {desc}\n\n'
2330 o
2330 o
2331 | 2 mv b dir/b
2331 | 2 mv b dir/b
2332 |
2332 |
2333 o
2333 o
2334 | 1 copy a b
2334 | 1 copy a b
2335 |
2335 |
2336 o
2336 o
2337 0 add a
2337 0 add a
2338
2338
2339
2339
2340 The almost-empty template should do something sane too ...
2340 The almost-empty template should do something sane too ...
2341
2341
2342 $ hg log -G -r ::2 --template '\n'
2342 $ hg log -G -r ::2 --template '\n'
2343 o
2343 o
2344 |
2344 |
2345 o
2345 o
2346 |
2346 |
2347 o
2347 o
2348
2348
2349
2349
2350 issue3772
2350 issue3772
2351
2351
2352 $ hg log -G -r :null
2352 $ hg log -G -r :null
2353 o changeset: 0:f8035bb17114
2353 o changeset: 0:f8035bb17114
2354 | user: test
2354 | user: test
2355 | date: Thu Jan 01 00:00:00 1970 +0000
2355 | date: Thu Jan 01 00:00:00 1970 +0000
2356 | summary: add a
2356 | summary: add a
2357 |
2357 |
2358 o changeset: -1:000000000000
2358 o changeset: -1:000000000000
2359 user:
2359 user:
2360 date: Thu Jan 01 00:00:00 1970 +0000
2360 date: Thu Jan 01 00:00:00 1970 +0000
2361
2361
2362 $ hg log -G -r null:null
2362 $ hg log -G -r null:null
2363 o changeset: -1:000000000000
2363 o changeset: -1:000000000000
2364 user:
2364 user:
2365 date: Thu Jan 01 00:00:00 1970 +0000
2365 date: Thu Jan 01 00:00:00 1970 +0000
2366
2366
2367
2367
2368 should not draw line down to null due to the magic of fullreposet
2369
2370 $ hg log -G -r 'all()' | tail -6
2371 |
2372 o changeset: 0:f8035bb17114
2373 user: test
2374 date: Thu Jan 01 00:00:00 1970 +0000
2375 summary: add a
2376
2377
2368 $ cd ..
2378 $ cd ..
@@ -1,1360 +1,1363 b''
1 $ HGENCODING=utf-8
1 $ HGENCODING=utf-8
2 $ export HGENCODING
2 $ export HGENCODING
3
3
4 $ try() {
4 $ try() {
5 > hg debugrevspec --debug "$@"
5 > hg debugrevspec --debug "$@"
6 > }
6 > }
7
7
8 $ log() {
8 $ log() {
9 > hg log --template '{rev}\n' -r "$1"
9 > hg log --template '{rev}\n' -r "$1"
10 > }
10 > }
11
11
12 $ hg init repo
12 $ hg init repo
13 $ cd repo
13 $ cd repo
14
14
15 $ echo a > a
15 $ echo a > a
16 $ hg branch a
16 $ hg branch a
17 marked working directory as branch a
17 marked working directory as branch a
18 (branches are permanent and global, did you want a bookmark?)
18 (branches are permanent and global, did you want a bookmark?)
19 $ hg ci -Aqm0
19 $ hg ci -Aqm0
20
20
21 $ echo b > b
21 $ echo b > b
22 $ hg branch b
22 $ hg branch b
23 marked working directory as branch b
23 marked working directory as branch b
24 (branches are permanent and global, did you want a bookmark?)
24 (branches are permanent and global, did you want a bookmark?)
25 $ hg ci -Aqm1
25 $ hg ci -Aqm1
26
26
27 $ rm a
27 $ rm a
28 $ hg branch a-b-c-
28 $ hg branch a-b-c-
29 marked working directory as branch a-b-c-
29 marked working directory as branch a-b-c-
30 (branches are permanent and global, did you want a bookmark?)
30 (branches are permanent and global, did you want a bookmark?)
31 $ hg ci -Aqm2 -u Bob
31 $ hg ci -Aqm2 -u Bob
32
32
33 $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
33 $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
34 2
34 2
35 $ hg log -r "extra('branch')" --template '{rev}\n'
35 $ hg log -r "extra('branch')" --template '{rev}\n'
36 0
36 0
37 1
37 1
38 2
38 2
39 $ hg log -r "extra('branch', 're:a')" --template '{rev} {branch}\n'
39 $ hg log -r "extra('branch', 're:a')" --template '{rev} {branch}\n'
40 0 a
40 0 a
41 2 a-b-c-
41 2 a-b-c-
42
42
43 $ hg co 1
43 $ hg co 1
44 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
44 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 $ hg branch +a+b+c+
45 $ hg branch +a+b+c+
46 marked working directory as branch +a+b+c+
46 marked working directory as branch +a+b+c+
47 (branches are permanent and global, did you want a bookmark?)
47 (branches are permanent and global, did you want a bookmark?)
48 $ hg ci -Aqm3
48 $ hg ci -Aqm3
49
49
50 $ hg co 2 # interleave
50 $ hg co 2 # interleave
51 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
51 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
52 $ echo bb > b
52 $ echo bb > b
53 $ hg branch -- -a-b-c-
53 $ hg branch -- -a-b-c-
54 marked working directory as branch -a-b-c-
54 marked working directory as branch -a-b-c-
55 (branches are permanent and global, did you want a bookmark?)
55 (branches are permanent and global, did you want a bookmark?)
56 $ hg ci -Aqm4 -d "May 12 2005"
56 $ hg ci -Aqm4 -d "May 12 2005"
57
57
58 $ hg co 3
58 $ hg co 3
59 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
60 $ hg branch !a/b/c/
60 $ hg branch !a/b/c/
61 marked working directory as branch !a/b/c/
61 marked working directory as branch !a/b/c/
62 (branches are permanent and global, did you want a bookmark?)
62 (branches are permanent and global, did you want a bookmark?)
63 $ hg ci -Aqm"5 bug"
63 $ hg ci -Aqm"5 bug"
64
64
65 $ hg merge 4
65 $ hg merge 4
66 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
66 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
67 (branch merge, don't forget to commit)
67 (branch merge, don't forget to commit)
68 $ hg branch _a_b_c_
68 $ hg branch _a_b_c_
69 marked working directory as branch _a_b_c_
69 marked working directory as branch _a_b_c_
70 (branches are permanent and global, did you want a bookmark?)
70 (branches are permanent and global, did you want a bookmark?)
71 $ hg ci -Aqm"6 issue619"
71 $ hg ci -Aqm"6 issue619"
72
72
73 $ hg branch .a.b.c.
73 $ hg branch .a.b.c.
74 marked working directory as branch .a.b.c.
74 marked working directory as branch .a.b.c.
75 (branches are permanent and global, did you want a bookmark?)
75 (branches are permanent and global, did you want a bookmark?)
76 $ hg ci -Aqm7
76 $ hg ci -Aqm7
77
77
78 $ hg branch all
78 $ hg branch all
79 marked working directory as branch all
79 marked working directory as branch all
80 (branches are permanent and global, did you want a bookmark?)
80 (branches are permanent and global, did you want a bookmark?)
81
81
82 $ hg co 4
82 $ hg co 4
83 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
84 $ hg branch Γ©
84 $ hg branch Γ©
85 marked working directory as branch \xc3\xa9 (esc)
85 marked working directory as branch \xc3\xa9 (esc)
86 (branches are permanent and global, did you want a bookmark?)
86 (branches are permanent and global, did you want a bookmark?)
87 $ hg ci -Aqm9
87 $ hg ci -Aqm9
88
88
89 $ hg tag -r6 1.0
89 $ hg tag -r6 1.0
90
90
91 $ hg clone --quiet -U -r 7 . ../remote1
91 $ hg clone --quiet -U -r 7 . ../remote1
92 $ hg clone --quiet -U -r 8 . ../remote2
92 $ hg clone --quiet -U -r 8 . ../remote2
93 $ echo "[paths]" >> .hg/hgrc
93 $ echo "[paths]" >> .hg/hgrc
94 $ echo "default = ../remote1" >> .hg/hgrc
94 $ echo "default = ../remote1" >> .hg/hgrc
95
95
96 names that should work without quoting
96 names that should work without quoting
97
97
98 $ try a
98 $ try a
99 ('symbol', 'a')
99 ('symbol', 'a')
100 0
100 0
101 $ try b-a
101 $ try b-a
102 (minus
102 (minus
103 ('symbol', 'b')
103 ('symbol', 'b')
104 ('symbol', 'a'))
104 ('symbol', 'a'))
105 1
105 1
106 $ try _a_b_c_
106 $ try _a_b_c_
107 ('symbol', '_a_b_c_')
107 ('symbol', '_a_b_c_')
108 6
108 6
109 $ try _a_b_c_-a
109 $ try _a_b_c_-a
110 (minus
110 (minus
111 ('symbol', '_a_b_c_')
111 ('symbol', '_a_b_c_')
112 ('symbol', 'a'))
112 ('symbol', 'a'))
113 6
113 6
114 $ try .a.b.c.
114 $ try .a.b.c.
115 ('symbol', '.a.b.c.')
115 ('symbol', '.a.b.c.')
116 7
116 7
117 $ try .a.b.c.-a
117 $ try .a.b.c.-a
118 (minus
118 (minus
119 ('symbol', '.a.b.c.')
119 ('symbol', '.a.b.c.')
120 ('symbol', 'a'))
120 ('symbol', 'a'))
121 7
121 7
122 $ try -- '-a-b-c-' # complains
122 $ try -- '-a-b-c-' # complains
123 hg: parse error at 7: not a prefix: end
123 hg: parse error at 7: not a prefix: end
124 [255]
124 [255]
125 $ log -a-b-c- # succeeds with fallback
125 $ log -a-b-c- # succeeds with fallback
126 4
126 4
127
127
128 $ try -- -a-b-c--a # complains
128 $ try -- -a-b-c--a # complains
129 (minus
129 (minus
130 (minus
130 (minus
131 (minus
131 (minus
132 (negate
132 (negate
133 ('symbol', 'a'))
133 ('symbol', 'a'))
134 ('symbol', 'b'))
134 ('symbol', 'b'))
135 ('symbol', 'c'))
135 ('symbol', 'c'))
136 (negate
136 (negate
137 ('symbol', 'a')))
137 ('symbol', 'a')))
138 abort: unknown revision '-a'!
138 abort: unknown revision '-a'!
139 [255]
139 [255]
140 $ try Γ©
140 $ try Γ©
141 ('symbol', '\xc3\xa9')
141 ('symbol', '\xc3\xa9')
142 9
142 9
143
143
144 no quoting needed
144 no quoting needed
145
145
146 $ log ::a-b-c-
146 $ log ::a-b-c-
147 0
147 0
148 1
148 1
149 2
149 2
150
150
151 quoting needed
151 quoting needed
152
152
153 $ try '"-a-b-c-"-a'
153 $ try '"-a-b-c-"-a'
154 (minus
154 (minus
155 ('string', '-a-b-c-')
155 ('string', '-a-b-c-')
156 ('symbol', 'a'))
156 ('symbol', 'a'))
157 4
157 4
158
158
159 $ log '1 or 2'
159 $ log '1 or 2'
160 1
160 1
161 2
161 2
162 $ log '1|2'
162 $ log '1|2'
163 1
163 1
164 2
164 2
165 $ log '1 and 2'
165 $ log '1 and 2'
166 $ log '1&2'
166 $ log '1&2'
167 $ try '1&2|3' # precedence - and is higher
167 $ try '1&2|3' # precedence - and is higher
168 (or
168 (or
169 (and
169 (and
170 ('symbol', '1')
170 ('symbol', '1')
171 ('symbol', '2'))
171 ('symbol', '2'))
172 ('symbol', '3'))
172 ('symbol', '3'))
173 3
173 3
174 $ try '1|2&3'
174 $ try '1|2&3'
175 (or
175 (or
176 ('symbol', '1')
176 ('symbol', '1')
177 (and
177 (and
178 ('symbol', '2')
178 ('symbol', '2')
179 ('symbol', '3')))
179 ('symbol', '3')))
180 1
180 1
181 $ try '1&2&3' # associativity
181 $ try '1&2&3' # associativity
182 (and
182 (and
183 (and
183 (and
184 ('symbol', '1')
184 ('symbol', '1')
185 ('symbol', '2'))
185 ('symbol', '2'))
186 ('symbol', '3'))
186 ('symbol', '3'))
187 $ try '1|(2|3)'
187 $ try '1|(2|3)'
188 (or
188 (or
189 ('symbol', '1')
189 ('symbol', '1')
190 (group
190 (group
191 (or
191 (or
192 ('symbol', '2')
192 ('symbol', '2')
193 ('symbol', '3'))))
193 ('symbol', '3'))))
194 1
194 1
195 2
195 2
196 3
196 3
197 $ log '1.0' # tag
197 $ log '1.0' # tag
198 6
198 6
199 $ log 'a' # branch
199 $ log 'a' # branch
200 0
200 0
201 $ log '2785f51ee'
201 $ log '2785f51ee'
202 0
202 0
203 $ log 'date(2005)'
203 $ log 'date(2005)'
204 4
204 4
205 $ log 'date(this is a test)'
205 $ log 'date(this is a test)'
206 hg: parse error at 10: unexpected token: symbol
206 hg: parse error at 10: unexpected token: symbol
207 [255]
207 [255]
208 $ log 'date()'
208 $ log 'date()'
209 hg: parse error: date requires a string
209 hg: parse error: date requires a string
210 [255]
210 [255]
211 $ log 'date'
211 $ log 'date'
212 hg: parse error: can't use date here
212 hg: parse error: can't use date here
213 [255]
213 [255]
214 $ log 'date('
214 $ log 'date('
215 hg: parse error at 5: not a prefix: end
215 hg: parse error at 5: not a prefix: end
216 [255]
216 [255]
217 $ log 'date(tip)'
217 $ log 'date(tip)'
218 abort: invalid date: 'tip'
218 abort: invalid date: 'tip'
219 [255]
219 [255]
220 $ log '"date"'
220 $ log '"date"'
221 abort: unknown revision 'date'!
221 abort: unknown revision 'date'!
222 [255]
222 [255]
223 $ log 'date(2005) and 1::'
223 $ log 'date(2005) and 1::'
224 4
224 4
225
225
226 ancestor can accept 0 or more arguments
226 ancestor can accept 0 or more arguments
227
227
228 $ log 'ancestor()'
228 $ log 'ancestor()'
229 $ log 'ancestor(1)'
229 $ log 'ancestor(1)'
230 1
230 1
231 $ log 'ancestor(4,5)'
231 $ log 'ancestor(4,5)'
232 1
232 1
233 $ log 'ancestor(4,5) and 4'
233 $ log 'ancestor(4,5) and 4'
234 $ log 'ancestor(0,0,1,3)'
234 $ log 'ancestor(0,0,1,3)'
235 0
235 0
236 $ log 'ancestor(3,1,5,3,5,1)'
236 $ log 'ancestor(3,1,5,3,5,1)'
237 1
237 1
238 $ log 'ancestor(0,1,3,5)'
238 $ log 'ancestor(0,1,3,5)'
239 0
239 0
240 $ log 'ancestor(1,2,3,4,5)'
240 $ log 'ancestor(1,2,3,4,5)'
241 1
241 1
242 $ log 'ancestors(5)'
242 $ log 'ancestors(5)'
243 0
243 0
244 1
244 1
245 3
245 3
246 5
246 5
247 $ log 'ancestor(ancestors(5))'
247 $ log 'ancestor(ancestors(5))'
248 0
248 0
249 $ log 'author(bob)'
249 $ log 'author(bob)'
250 2
250 2
251 $ log 'author("re:bob|test")'
251 $ log 'author("re:bob|test")'
252 0
252 0
253 1
253 1
254 2
254 2
255 3
255 3
256 4
256 4
257 5
257 5
258 6
258 6
259 7
259 7
260 8
260 8
261 9
261 9
262 $ log 'branch(Γ©)'
262 $ log 'branch(Γ©)'
263 8
263 8
264 9
264 9
265 $ log 'branch(a)'
265 $ log 'branch(a)'
266 0
266 0
267 $ hg log -r 'branch("re:a")' --template '{rev} {branch}\n'
267 $ hg log -r 'branch("re:a")' --template '{rev} {branch}\n'
268 0 a
268 0 a
269 2 a-b-c-
269 2 a-b-c-
270 3 +a+b+c+
270 3 +a+b+c+
271 4 -a-b-c-
271 4 -a-b-c-
272 5 !a/b/c/
272 5 !a/b/c/
273 6 _a_b_c_
273 6 _a_b_c_
274 7 .a.b.c.
274 7 .a.b.c.
275 $ log 'children(ancestor(4,5))'
275 $ log 'children(ancestor(4,5))'
276 2
276 2
277 3
277 3
278 $ log 'closed()'
278 $ log 'closed()'
279 $ log 'contains(a)'
279 $ log 'contains(a)'
280 0
280 0
281 1
281 1
282 3
282 3
283 5
283 5
284 $ log 'contains("../repo/a")'
284 $ log 'contains("../repo/a")'
285 0
285 0
286 1
286 1
287 3
287 3
288 5
288 5
289 $ log 'desc(B)'
289 $ log 'desc(B)'
290 5
290 5
291 $ log 'descendants(2 or 3)'
291 $ log 'descendants(2 or 3)'
292 2
292 2
293 3
293 3
294 4
294 4
295 5
295 5
296 6
296 6
297 7
297 7
298 8
298 8
299 9
299 9
300 $ log 'file("b*")'
300 $ log 'file("b*")'
301 1
301 1
302 4
302 4
303 $ log 'filelog("b")'
303 $ log 'filelog("b")'
304 1
304 1
305 4
305 4
306 $ log 'filelog("../repo/b")'
306 $ log 'filelog("../repo/b")'
307 1
307 1
308 4
308 4
309 $ log 'follow()'
309 $ log 'follow()'
310 0
310 0
311 1
311 1
312 2
312 2
313 4
313 4
314 8
314 8
315 9
315 9
316 $ log 'grep("issue\d+")'
316 $ log 'grep("issue\d+")'
317 6
317 6
318 $ try 'grep("(")' # invalid regular expression
318 $ try 'grep("(")' # invalid regular expression
319 (func
319 (func
320 ('symbol', 'grep')
320 ('symbol', 'grep')
321 ('string', '('))
321 ('string', '('))
322 hg: parse error: invalid match pattern: unbalanced parenthesis
322 hg: parse error: invalid match pattern: unbalanced parenthesis
323 [255]
323 [255]
324 $ try 'grep("\bissue\d+")'
324 $ try 'grep("\bissue\d+")'
325 (func
325 (func
326 ('symbol', 'grep')
326 ('symbol', 'grep')
327 ('string', '\x08issue\\d+'))
327 ('string', '\x08issue\\d+'))
328 $ try 'grep(r"\bissue\d+")'
328 $ try 'grep(r"\bissue\d+")'
329 (func
329 (func
330 ('symbol', 'grep')
330 ('symbol', 'grep')
331 ('string', '\\bissue\\d+'))
331 ('string', '\\bissue\\d+'))
332 6
332 6
333 $ try 'grep(r"\")'
333 $ try 'grep(r"\")'
334 hg: parse error at 7: unterminated string
334 hg: parse error at 7: unterminated string
335 [255]
335 [255]
336 $ log 'head()'
336 $ log 'head()'
337 0
337 0
338 1
338 1
339 2
339 2
340 3
340 3
341 4
341 4
342 5
342 5
343 6
343 6
344 7
344 7
345 9
345 9
346 $ log 'heads(6::)'
346 $ log 'heads(6::)'
347 7
347 7
348 $ log 'keyword(issue)'
348 $ log 'keyword(issue)'
349 6
349 6
350 $ log 'keyword("test a")'
350 $ log 'keyword("test a")'
351 $ log 'limit(head(), 1)'
351 $ log 'limit(head(), 1)'
352 0
352 0
353 $ log 'matching(6)'
353 $ log 'matching(6)'
354 6
354 6
355 $ log 'matching(6:7, "phase parents user date branch summary files description substate")'
355 $ log 'matching(6:7, "phase parents user date branch summary files description substate")'
356 6
356 6
357 7
357 7
358
358
359 Testing min and max
359 Testing min and max
360
360
361 max: simple
361 max: simple
362
362
363 $ log 'max(contains(a))'
363 $ log 'max(contains(a))'
364 5
364 5
365
365
366 max: simple on unordered set)
366 max: simple on unordered set)
367
367
368 $ log 'max((4+0+2+5+7) and contains(a))'
368 $ log 'max((4+0+2+5+7) and contains(a))'
369 5
369 5
370
370
371 max: no result
371 max: no result
372
372
373 $ log 'max(contains(stringthatdoesnotappearanywhere))'
373 $ log 'max(contains(stringthatdoesnotappearanywhere))'
374
374
375 max: no result on unordered set
375 max: no result on unordered set
376
376
377 $ log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
377 $ log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
378
378
379 min: simple
379 min: simple
380
380
381 $ log 'min(contains(a))'
381 $ log 'min(contains(a))'
382 0
382 0
383
383
384 min: simple on unordered set
384 min: simple on unordered set
385
385
386 $ log 'min((4+0+2+5+7) and contains(a))'
386 $ log 'min((4+0+2+5+7) and contains(a))'
387 0
387 0
388
388
389 min: empty
389 min: empty
390
390
391 $ log 'min(contains(stringthatdoesnotappearanywhere))'
391 $ log 'min(contains(stringthatdoesnotappearanywhere))'
392
392
393 min: empty on unordered set
393 min: empty on unordered set
394
394
395 $ log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
395 $ log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
396
396
397
397
398 $ log 'merge()'
398 $ log 'merge()'
399 6
399 6
400 $ log 'branchpoint()'
400 $ log 'branchpoint()'
401 1
401 1
402 4
402 4
403 $ log 'modifies(b)'
403 $ log 'modifies(b)'
404 4
404 4
405 $ log 'modifies("path:b")'
405 $ log 'modifies("path:b")'
406 4
406 4
407 $ log 'modifies("*")'
407 $ log 'modifies("*")'
408 4
408 4
409 6
409 6
410 $ log 'modifies("set:modified()")'
410 $ log 'modifies("set:modified()")'
411 4
411 4
412 $ log 'id(5)'
412 $ log 'id(5)'
413 2
413 2
414 $ log 'only(9)'
414 $ log 'only(9)'
415 8
415 8
416 9
416 9
417 $ log 'only(8)'
417 $ log 'only(8)'
418 8
418 8
419 $ log 'only(9, 5)'
419 $ log 'only(9, 5)'
420 2
420 2
421 4
421 4
422 8
422 8
423 9
423 9
424 $ log 'only(7 + 9, 5 + 2)'
424 $ log 'only(7 + 9, 5 + 2)'
425 4
425 4
426 6
426 6
427 7
427 7
428 8
428 8
429 9
429 9
430
430
431 Test empty set input
431 Test empty set input
432 $ log 'only(p2())'
432 $ log 'only(p2())'
433 $ log 'only(p1(), p2())'
433 $ log 'only(p1(), p2())'
434 0
434 0
435 1
435 1
436 2
436 2
437 4
437 4
438 8
438 8
439 9
439 9
440
440
441 Test '%' operator
441 Test '%' operator
442
442
443 $ log '9%'
443 $ log '9%'
444 8
444 8
445 9
445 9
446 $ log '9%5'
446 $ log '9%5'
447 2
447 2
448 4
448 4
449 8
449 8
450 9
450 9
451 $ log '(7 + 9)%(5 + 2)'
451 $ log '(7 + 9)%(5 + 2)'
452 4
452 4
453 6
453 6
454 7
454 7
455 8
455 8
456 9
456 9
457
457
458 Test the order of operations
458 Test the order of operations
459
459
460 $ log '7 + 9%5 + 2'
460 $ log '7 + 9%5 + 2'
461 7
461 7
462 2
462 2
463 4
463 4
464 8
464 8
465 9
465 9
466
466
467 Test explicit numeric revision
467 Test explicit numeric revision
468 $ log 'rev(-2)'
468 $ log 'rev(-2)'
469 $ log 'rev(-1)'
469 $ log 'rev(-1)'
470 -1
470 -1
471 $ log 'rev(0)'
471 $ log 'rev(0)'
472 0
472 0
473 $ log 'rev(9)'
473 $ log 'rev(9)'
474 9
474 9
475 $ log 'rev(10)'
475 $ log 'rev(10)'
476 $ log 'rev(tip)'
476 $ log 'rev(tip)'
477 hg: parse error: rev expects a number
477 hg: parse error: rev expects a number
478 [255]
478 [255]
479
479
480 Test null revision
480 Test null revision
481 $ log 'ancestors(null)'
481 $ log 'ancestors(null)'
482 -1
482 -1
483 $ log 'tip:null and all()' | tail -2
484 1
485 0
483
486
484 $ log 'outgoing()'
487 $ log 'outgoing()'
485 8
488 8
486 9
489 9
487 $ log 'outgoing("../remote1")'
490 $ log 'outgoing("../remote1")'
488 8
491 8
489 9
492 9
490 $ log 'outgoing("../remote2")'
493 $ log 'outgoing("../remote2")'
491 3
494 3
492 5
495 5
493 6
496 6
494 7
497 7
495 9
498 9
496 $ log 'p1(merge())'
499 $ log 'p1(merge())'
497 5
500 5
498 $ log 'p2(merge())'
501 $ log 'p2(merge())'
499 4
502 4
500 $ log 'parents(merge())'
503 $ log 'parents(merge())'
501 4
504 4
502 5
505 5
503 $ log 'p1(branchpoint())'
506 $ log 'p1(branchpoint())'
504 0
507 0
505 2
508 2
506 $ log 'p2(branchpoint())'
509 $ log 'p2(branchpoint())'
507 $ log 'parents(branchpoint())'
510 $ log 'parents(branchpoint())'
508 0
511 0
509 2
512 2
510 $ log 'removes(a)'
513 $ log 'removes(a)'
511 2
514 2
512 6
515 6
513 $ log 'roots(all())'
516 $ log 'roots(all())'
514 0
517 0
515 $ log 'reverse(2 or 3 or 4 or 5)'
518 $ log 'reverse(2 or 3 or 4 or 5)'
516 5
519 5
517 4
520 4
518 3
521 3
519 2
522 2
520 $ log 'reverse(all())'
523 $ log 'reverse(all())'
521 9
524 9
522 8
525 8
523 7
526 7
524 6
527 6
525 5
528 5
526 4
529 4
527 3
530 3
528 2
531 2
529 1
532 1
530 0
533 0
531 $ log 'reverse(all()) & filelog(b)'
534 $ log 'reverse(all()) & filelog(b)'
532 4
535 4
533 1
536 1
534 $ log 'rev(5)'
537 $ log 'rev(5)'
535 5
538 5
536 $ log 'sort(limit(reverse(all()), 3))'
539 $ log 'sort(limit(reverse(all()), 3))'
537 7
540 7
538 8
541 8
539 9
542 9
540 $ log 'sort(2 or 3 or 4 or 5, date)'
543 $ log 'sort(2 or 3 or 4 or 5, date)'
541 2
544 2
542 3
545 3
543 5
546 5
544 4
547 4
545 $ log 'tagged()'
548 $ log 'tagged()'
546 6
549 6
547 $ log 'tag()'
550 $ log 'tag()'
548 6
551 6
549 $ log 'tag(1.0)'
552 $ log 'tag(1.0)'
550 6
553 6
551 $ log 'tag(tip)'
554 $ log 'tag(tip)'
552 9
555 9
553
556
554 test sort revset
557 test sort revset
555 --------------------------------------------
558 --------------------------------------------
556
559
557 test when adding two unordered revsets
560 test when adding two unordered revsets
558
561
559 $ log 'sort(keyword(issue) or modifies(b))'
562 $ log 'sort(keyword(issue) or modifies(b))'
560 4
563 4
561 6
564 6
562
565
563 test when sorting a reversed collection in the same way it is
566 test when sorting a reversed collection in the same way it is
564
567
565 $ log 'sort(reverse(all()), -rev)'
568 $ log 'sort(reverse(all()), -rev)'
566 9
569 9
567 8
570 8
568 7
571 7
569 6
572 6
570 5
573 5
571 4
574 4
572 3
575 3
573 2
576 2
574 1
577 1
575 0
578 0
576
579
577 test when sorting a reversed collection
580 test when sorting a reversed collection
578
581
579 $ log 'sort(reverse(all()), rev)'
582 $ log 'sort(reverse(all()), rev)'
580 0
583 0
581 1
584 1
582 2
585 2
583 3
586 3
584 4
587 4
585 5
588 5
586 6
589 6
587 7
590 7
588 8
591 8
589 9
592 9
590
593
591
594
592 test sorting two sorted collections in different orders
595 test sorting two sorted collections in different orders
593
596
594 $ log 'sort(outgoing() or reverse(removes(a)), rev)'
597 $ log 'sort(outgoing() or reverse(removes(a)), rev)'
595 2
598 2
596 6
599 6
597 8
600 8
598 9
601 9
599
602
600 test sorting two sorted collections in different orders backwards
603 test sorting two sorted collections in different orders backwards
601
604
602 $ log 'sort(outgoing() or reverse(removes(a)), -rev)'
605 $ log 'sort(outgoing() or reverse(removes(a)), -rev)'
603 9
606 9
604 8
607 8
605 6
608 6
606 2
609 2
607
610
608 test subtracting something from an addset
611 test subtracting something from an addset
609
612
610 $ log '(outgoing() or removes(a)) - removes(a)'
613 $ log '(outgoing() or removes(a)) - removes(a)'
611 8
614 8
612 9
615 9
613
616
614 test intersecting something with an addset
617 test intersecting something with an addset
615
618
616 $ log 'parents(outgoing() or removes(a))'
619 $ log 'parents(outgoing() or removes(a))'
617 1
620 1
618 4
621 4
619 5
622 5
620 8
623 8
621
624
622 test that `or` operation combines elements in the right order:
625 test that `or` operation combines elements in the right order:
623
626
624 $ log '3:4 or 2:5'
627 $ log '3:4 or 2:5'
625 3
628 3
626 4
629 4
627 2
630 2
628 5
631 5
629 $ log '3:4 or 5:2'
632 $ log '3:4 or 5:2'
630 3
633 3
631 4
634 4
632 5
635 5
633 2
636 2
634 $ log 'sort(3:4 or 2:5)'
637 $ log 'sort(3:4 or 2:5)'
635 2
638 2
636 3
639 3
637 4
640 4
638 5
641 5
639 $ log 'sort(3:4 or 5:2)'
642 $ log 'sort(3:4 or 5:2)'
640 2
643 2
641 3
644 3
642 4
645 4
643 5
646 5
644
647
645 check that conversion to only works
648 check that conversion to only works
646 $ try --optimize '::3 - ::1'
649 $ try --optimize '::3 - ::1'
647 (minus
650 (minus
648 (dagrangepre
651 (dagrangepre
649 ('symbol', '3'))
652 ('symbol', '3'))
650 (dagrangepre
653 (dagrangepre
651 ('symbol', '1')))
654 ('symbol', '1')))
652 * optimized:
655 * optimized:
653 (func
656 (func
654 ('symbol', 'only')
657 ('symbol', 'only')
655 (list
658 (list
656 ('symbol', '3')
659 ('symbol', '3')
657 ('symbol', '1')))
660 ('symbol', '1')))
658 3
661 3
659 $ try --optimize 'ancestors(1) - ancestors(3)'
662 $ try --optimize 'ancestors(1) - ancestors(3)'
660 (minus
663 (minus
661 (func
664 (func
662 ('symbol', 'ancestors')
665 ('symbol', 'ancestors')
663 ('symbol', '1'))
666 ('symbol', '1'))
664 (func
667 (func
665 ('symbol', 'ancestors')
668 ('symbol', 'ancestors')
666 ('symbol', '3')))
669 ('symbol', '3')))
667 * optimized:
670 * optimized:
668 (func
671 (func
669 ('symbol', 'only')
672 ('symbol', 'only')
670 (list
673 (list
671 ('symbol', '1')
674 ('symbol', '1')
672 ('symbol', '3')))
675 ('symbol', '3')))
673 $ try --optimize 'not ::2 and ::6'
676 $ try --optimize 'not ::2 and ::6'
674 (and
677 (and
675 (not
678 (not
676 (dagrangepre
679 (dagrangepre
677 ('symbol', '2')))
680 ('symbol', '2')))
678 (dagrangepre
681 (dagrangepre
679 ('symbol', '6')))
682 ('symbol', '6')))
680 * optimized:
683 * optimized:
681 (func
684 (func
682 ('symbol', 'only')
685 ('symbol', 'only')
683 (list
686 (list
684 ('symbol', '6')
687 ('symbol', '6')
685 ('symbol', '2')))
688 ('symbol', '2')))
686 3
689 3
687 4
690 4
688 5
691 5
689 6
692 6
690 $ try --optimize 'ancestors(6) and not ancestors(4)'
693 $ try --optimize 'ancestors(6) and not ancestors(4)'
691 (and
694 (and
692 (func
695 (func
693 ('symbol', 'ancestors')
696 ('symbol', 'ancestors')
694 ('symbol', '6'))
697 ('symbol', '6'))
695 (not
698 (not
696 (func
699 (func
697 ('symbol', 'ancestors')
700 ('symbol', 'ancestors')
698 ('symbol', '4'))))
701 ('symbol', '4'))))
699 * optimized:
702 * optimized:
700 (func
703 (func
701 ('symbol', 'only')
704 ('symbol', 'only')
702 (list
705 (list
703 ('symbol', '6')
706 ('symbol', '6')
704 ('symbol', '4')))
707 ('symbol', '4')))
705 3
708 3
706 5
709 5
707 6
710 6
708
711
709 we can use patterns when searching for tags
712 we can use patterns when searching for tags
710
713
711 $ log 'tag("1..*")'
714 $ log 'tag("1..*")'
712 abort: tag '1..*' does not exist!
715 abort: tag '1..*' does not exist!
713 [255]
716 [255]
714 $ log 'tag("re:1..*")'
717 $ log 'tag("re:1..*")'
715 6
718 6
716 $ log 'tag("re:[0-9].[0-9]")'
719 $ log 'tag("re:[0-9].[0-9]")'
717 6
720 6
718 $ log 'tag("literal:1.0")'
721 $ log 'tag("literal:1.0")'
719 6
722 6
720 $ log 'tag("re:0..*")'
723 $ log 'tag("re:0..*")'
721
724
722 $ log 'tag(unknown)'
725 $ log 'tag(unknown)'
723 abort: tag 'unknown' does not exist!
726 abort: tag 'unknown' does not exist!
724 [255]
727 [255]
725 $ log 'tag("re:unknown")'
728 $ log 'tag("re:unknown")'
726 $ log 'present(tag("unknown"))'
729 $ log 'present(tag("unknown"))'
727 $ log 'present(tag("re:unknown"))'
730 $ log 'present(tag("re:unknown"))'
728 $ log 'branch(unknown)'
731 $ log 'branch(unknown)'
729 abort: unknown revision 'unknown'!
732 abort: unknown revision 'unknown'!
730 [255]
733 [255]
731 $ log 'branch("re:unknown")'
734 $ log 'branch("re:unknown")'
732 $ log 'present(branch("unknown"))'
735 $ log 'present(branch("unknown"))'
733 $ log 'present(branch("re:unknown"))'
736 $ log 'present(branch("re:unknown"))'
734 $ log 'user(bob)'
737 $ log 'user(bob)'
735 2
738 2
736
739
737 $ log '4::8'
740 $ log '4::8'
738 4
741 4
739 8
742 8
740 $ log '4:8'
743 $ log '4:8'
741 4
744 4
742 5
745 5
743 6
746 6
744 7
747 7
745 8
748 8
746
749
747 $ log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
750 $ log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
748 4
751 4
749 2
752 2
750 5
753 5
751
754
752 $ log 'not 0 and 0:2'
755 $ log 'not 0 and 0:2'
753 1
756 1
754 2
757 2
755 $ log 'not 1 and 0:2'
758 $ log 'not 1 and 0:2'
756 0
759 0
757 2
760 2
758 $ log 'not 2 and 0:2'
761 $ log 'not 2 and 0:2'
759 0
762 0
760 1
763 1
761 $ log '(1 and 2)::'
764 $ log '(1 and 2)::'
762 $ log '(1 and 2):'
765 $ log '(1 and 2):'
763 $ log '(1 and 2):3'
766 $ log '(1 and 2):3'
764 $ log 'sort(head(), -rev)'
767 $ log 'sort(head(), -rev)'
765 9
768 9
766 7
769 7
767 6
770 6
768 5
771 5
769 4
772 4
770 3
773 3
771 2
774 2
772 1
775 1
773 0
776 0
774 $ log '4::8 - 8'
777 $ log '4::8 - 8'
775 4
778 4
776 $ log 'matching(1 or 2 or 3) and (2 or 3 or 1)'
779 $ log 'matching(1 or 2 or 3) and (2 or 3 or 1)'
777 2
780 2
778 3
781 3
779 1
782 1
780
783
781 $ log 'named("unknown")'
784 $ log 'named("unknown")'
782 abort: namespace 'unknown' does not exist!
785 abort: namespace 'unknown' does not exist!
783 [255]
786 [255]
784 $ log 'named("re:unknown")'
787 $ log 'named("re:unknown")'
785 abort: no namespace exists that match 'unknown'!
788 abort: no namespace exists that match 'unknown'!
786 [255]
789 [255]
787 $ log 'present(named("unknown"))'
790 $ log 'present(named("unknown"))'
788 $ log 'present(named("re:unknown"))'
791 $ log 'present(named("re:unknown"))'
789
792
790 $ log 'tag()'
793 $ log 'tag()'
791 6
794 6
792 $ log 'named("tags")'
795 $ log 'named("tags")'
793 6
796 6
794
797
795 issue2437
798 issue2437
796
799
797 $ log '3 and p1(5)'
800 $ log '3 and p1(5)'
798 3
801 3
799 $ log '4 and p2(6)'
802 $ log '4 and p2(6)'
800 4
803 4
801 $ log '1 and parents(:2)'
804 $ log '1 and parents(:2)'
802 1
805 1
803 $ log '2 and children(1:)'
806 $ log '2 and children(1:)'
804 2
807 2
805 $ log 'roots(all()) or roots(all())'
808 $ log 'roots(all()) or roots(all())'
806 0
809 0
807 $ hg debugrevspec 'roots(all()) or roots(all())'
810 $ hg debugrevspec 'roots(all()) or roots(all())'
808 0
811 0
809 $ log 'heads(branch(Γ©)) or heads(branch(Γ©))'
812 $ log 'heads(branch(Γ©)) or heads(branch(Γ©))'
810 9
813 9
811 $ log 'ancestors(8) and (heads(branch("-a-b-c-")) or heads(branch(Γ©)))'
814 $ log 'ancestors(8) and (heads(branch("-a-b-c-")) or heads(branch(Γ©)))'
812 4
815 4
813
816
814 issue2654: report a parse error if the revset was not completely parsed
817 issue2654: report a parse error if the revset was not completely parsed
815
818
816 $ log '1 OR 2'
819 $ log '1 OR 2'
817 hg: parse error at 2: invalid token
820 hg: parse error at 2: invalid token
818 [255]
821 [255]
819
822
820 or operator should preserve ordering:
823 or operator should preserve ordering:
821 $ log 'reverse(2::4) or tip'
824 $ log 'reverse(2::4) or tip'
822 4
825 4
823 2
826 2
824 9
827 9
825
828
826 parentrevspec
829 parentrevspec
827
830
828 $ log 'merge()^0'
831 $ log 'merge()^0'
829 6
832 6
830 $ log 'merge()^'
833 $ log 'merge()^'
831 5
834 5
832 $ log 'merge()^1'
835 $ log 'merge()^1'
833 5
836 5
834 $ log 'merge()^2'
837 $ log 'merge()^2'
835 4
838 4
836 $ log 'merge()^^'
839 $ log 'merge()^^'
837 3
840 3
838 $ log 'merge()^1^'
841 $ log 'merge()^1^'
839 3
842 3
840 $ log 'merge()^^^'
843 $ log 'merge()^^^'
841 1
844 1
842
845
843 $ log 'merge()~0'
846 $ log 'merge()~0'
844 6
847 6
845 $ log 'merge()~1'
848 $ log 'merge()~1'
846 5
849 5
847 $ log 'merge()~2'
850 $ log 'merge()~2'
848 3
851 3
849 $ log 'merge()~2^1'
852 $ log 'merge()~2^1'
850 1
853 1
851 $ log 'merge()~3'
854 $ log 'merge()~3'
852 1
855 1
853
856
854 $ log '(-3:tip)^'
857 $ log '(-3:tip)^'
855 4
858 4
856 6
859 6
857 8
860 8
858
861
859 $ log 'tip^foo'
862 $ log 'tip^foo'
860 hg: parse error: ^ expects a number 0, 1, or 2
863 hg: parse error: ^ expects a number 0, 1, or 2
861 [255]
864 [255]
862
865
863 multiple revspecs
866 multiple revspecs
864
867
865 $ hg log -r 'tip~1:tip' -r 'tip~2:tip~1' --template '{rev}\n'
868 $ hg log -r 'tip~1:tip' -r 'tip~2:tip~1' --template '{rev}\n'
866 8
869 8
867 9
870 9
868 4
871 4
869 5
872 5
870 6
873 6
871 7
874 7
872
875
873 test usage in revpair (with "+")
876 test usage in revpair (with "+")
874
877
875 (real pair)
878 (real pair)
876
879
877 $ hg diff -r 'tip^^' -r 'tip'
880 $ hg diff -r 'tip^^' -r 'tip'
878 diff -r 2326846efdab -r 24286f4ae135 .hgtags
881 diff -r 2326846efdab -r 24286f4ae135 .hgtags
879 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
882 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
880 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
883 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
881 @@ -0,0 +1,1 @@
884 @@ -0,0 +1,1 @@
882 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
885 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
883 $ hg diff -r 'tip^^::tip'
886 $ hg diff -r 'tip^^::tip'
884 diff -r 2326846efdab -r 24286f4ae135 .hgtags
887 diff -r 2326846efdab -r 24286f4ae135 .hgtags
885 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
888 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
886 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
889 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
887 @@ -0,0 +1,1 @@
890 @@ -0,0 +1,1 @@
888 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
891 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
889
892
890 (single rev)
893 (single rev)
891
894
892 $ hg diff -r 'tip^' -r 'tip^'
895 $ hg diff -r 'tip^' -r 'tip^'
893 $ hg diff -r 'tip^::tip^ or tip^'
896 $ hg diff -r 'tip^::tip^ or tip^'
894
897
895 (single rev that does not looks like a range)
898 (single rev that does not looks like a range)
896
899
897 $ hg diff -r 'tip^ or tip^'
900 $ hg diff -r 'tip^ or tip^'
898 diff -r d5d0dcbdc4d9 .hgtags
901 diff -r d5d0dcbdc4d9 .hgtags
899 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
902 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
900 +++ b/.hgtags * (glob)
903 +++ b/.hgtags * (glob)
901 @@ -0,0 +1,1 @@
904 @@ -0,0 +1,1 @@
902 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
905 +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0
903
906
904 (no rev)
907 (no rev)
905
908
906 $ hg diff -r 'author("babar") or author("celeste")'
909 $ hg diff -r 'author("babar") or author("celeste")'
907 abort: empty revision range
910 abort: empty revision range
908 [255]
911 [255]
909
912
910 aliases:
913 aliases:
911
914
912 $ echo '[revsetalias]' >> .hg/hgrc
915 $ echo '[revsetalias]' >> .hg/hgrc
913 $ echo 'm = merge()' >> .hg/hgrc
916 $ echo 'm = merge()' >> .hg/hgrc
914 $ echo 'sincem = descendants(m)' >> .hg/hgrc
917 $ echo 'sincem = descendants(m)' >> .hg/hgrc
915 $ echo 'd($1) = reverse(sort($1, date))' >> .hg/hgrc
918 $ echo 'd($1) = reverse(sort($1, date))' >> .hg/hgrc
916 $ echo 'rs(ARG1, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
919 $ echo 'rs(ARG1, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
917 $ echo 'rs4(ARG1, ARGA, ARGB, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
920 $ echo 'rs4(ARG1, ARGA, ARGB, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
918
921
919 $ try m
922 $ try m
920 ('symbol', 'm')
923 ('symbol', 'm')
921 (func
924 (func
922 ('symbol', 'merge')
925 ('symbol', 'merge')
923 None)
926 None)
924 6
927 6
925
928
926 test alias recursion
929 test alias recursion
927
930
928 $ try sincem
931 $ try sincem
929 ('symbol', 'sincem')
932 ('symbol', 'sincem')
930 (func
933 (func
931 ('symbol', 'descendants')
934 ('symbol', 'descendants')
932 (func
935 (func
933 ('symbol', 'merge')
936 ('symbol', 'merge')
934 None))
937 None))
935 6
938 6
936 7
939 7
937
940
938 test infinite recursion
941 test infinite recursion
939
942
940 $ echo 'recurse1 = recurse2' >> .hg/hgrc
943 $ echo 'recurse1 = recurse2' >> .hg/hgrc
941 $ echo 'recurse2 = recurse1' >> .hg/hgrc
944 $ echo 'recurse2 = recurse1' >> .hg/hgrc
942 $ try recurse1
945 $ try recurse1
943 ('symbol', 'recurse1')
946 ('symbol', 'recurse1')
944 hg: parse error: infinite expansion of revset alias "recurse1" detected
947 hg: parse error: infinite expansion of revset alias "recurse1" detected
945 [255]
948 [255]
946
949
947 $ echo 'level1($1, $2) = $1 or $2' >> .hg/hgrc
950 $ echo 'level1($1, $2) = $1 or $2' >> .hg/hgrc
948 $ echo 'level2($1, $2) = level1($2, $1)' >> .hg/hgrc
951 $ echo 'level2($1, $2) = level1($2, $1)' >> .hg/hgrc
949 $ try "level2(level1(1, 2), 3)"
952 $ try "level2(level1(1, 2), 3)"
950 (func
953 (func
951 ('symbol', 'level2')
954 ('symbol', 'level2')
952 (list
955 (list
953 (func
956 (func
954 ('symbol', 'level1')
957 ('symbol', 'level1')
955 (list
958 (list
956 ('symbol', '1')
959 ('symbol', '1')
957 ('symbol', '2')))
960 ('symbol', '2')))
958 ('symbol', '3')))
961 ('symbol', '3')))
959 (or
962 (or
960 ('symbol', '3')
963 ('symbol', '3')
961 (or
964 (or
962 ('symbol', '1')
965 ('symbol', '1')
963 ('symbol', '2')))
966 ('symbol', '2')))
964 3
967 3
965 1
968 1
966 2
969 2
967
970
968 test nesting and variable passing
971 test nesting and variable passing
969
972
970 $ echo 'nested($1) = nested2($1)' >> .hg/hgrc
973 $ echo 'nested($1) = nested2($1)' >> .hg/hgrc
971 $ echo 'nested2($1) = nested3($1)' >> .hg/hgrc
974 $ echo 'nested2($1) = nested3($1)' >> .hg/hgrc
972 $ echo 'nested3($1) = max($1)' >> .hg/hgrc
975 $ echo 'nested3($1) = max($1)' >> .hg/hgrc
973 $ try 'nested(2:5)'
976 $ try 'nested(2:5)'
974 (func
977 (func
975 ('symbol', 'nested')
978 ('symbol', 'nested')
976 (range
979 (range
977 ('symbol', '2')
980 ('symbol', '2')
978 ('symbol', '5')))
981 ('symbol', '5')))
979 (func
982 (func
980 ('symbol', 'max')
983 ('symbol', 'max')
981 (range
984 (range
982 ('symbol', '2')
985 ('symbol', '2')
983 ('symbol', '5')))
986 ('symbol', '5')))
984 5
987 5
985
988
986 test variable isolation, variable placeholders are rewritten as string
989 test variable isolation, variable placeholders are rewritten as string
987 then parsed and matched again as string. Check they do not leak too
990 then parsed and matched again as string. Check they do not leak too
988 far away.
991 far away.
989
992
990 $ echo 'injectparamasstring = max("$1")' >> .hg/hgrc
993 $ echo 'injectparamasstring = max("$1")' >> .hg/hgrc
991 $ echo 'callinjection($1) = descendants(injectparamasstring)' >> .hg/hgrc
994 $ echo 'callinjection($1) = descendants(injectparamasstring)' >> .hg/hgrc
992 $ try 'callinjection(2:5)'
995 $ try 'callinjection(2:5)'
993 (func
996 (func
994 ('symbol', 'callinjection')
997 ('symbol', 'callinjection')
995 (range
998 (range
996 ('symbol', '2')
999 ('symbol', '2')
997 ('symbol', '5')))
1000 ('symbol', '5')))
998 (func
1001 (func
999 ('symbol', 'descendants')
1002 ('symbol', 'descendants')
1000 (func
1003 (func
1001 ('symbol', 'max')
1004 ('symbol', 'max')
1002 ('string', '$1')))
1005 ('string', '$1')))
1003 abort: unknown revision '$1'!
1006 abort: unknown revision '$1'!
1004 [255]
1007 [255]
1005
1008
1006 $ echo 'injectparamasstring2 = max(_aliasarg("$1"))' >> .hg/hgrc
1009 $ echo 'injectparamasstring2 = max(_aliasarg("$1"))' >> .hg/hgrc
1007 $ echo 'callinjection2($1) = descendants(injectparamasstring2)' >> .hg/hgrc
1010 $ echo 'callinjection2($1) = descendants(injectparamasstring2)' >> .hg/hgrc
1008 $ try 'callinjection2(2:5)'
1011 $ try 'callinjection2(2:5)'
1009 (func
1012 (func
1010 ('symbol', 'callinjection2')
1013 ('symbol', 'callinjection2')
1011 (range
1014 (range
1012 ('symbol', '2')
1015 ('symbol', '2')
1013 ('symbol', '5')))
1016 ('symbol', '5')))
1014 abort: failed to parse the definition of revset alias "injectparamasstring2": not a function: _aliasarg
1017 abort: failed to parse the definition of revset alias "injectparamasstring2": not a function: _aliasarg
1015 [255]
1018 [255]
1016 $ hg debugrevspec --debug --config revsetalias.anotherbadone='branch(' "tip"
1019 $ hg debugrevspec --debug --config revsetalias.anotherbadone='branch(' "tip"
1017 ('symbol', 'tip')
1020 ('symbol', 'tip')
1018 warning: failed to parse the definition of revset alias "anotherbadone": at 7: not a prefix: end
1021 warning: failed to parse the definition of revset alias "anotherbadone": at 7: not a prefix: end
1019 warning: failed to parse the definition of revset alias "injectparamasstring2": not a function: _aliasarg
1022 warning: failed to parse the definition of revset alias "injectparamasstring2": not a function: _aliasarg
1020 9
1023 9
1021 >>> data = file('.hg/hgrc', 'rb').read()
1024 >>> data = file('.hg/hgrc', 'rb').read()
1022 >>> file('.hg/hgrc', 'wb').write(data.replace('_aliasarg', ''))
1025 >>> file('.hg/hgrc', 'wb').write(data.replace('_aliasarg', ''))
1023
1026
1024 $ try 'tip'
1027 $ try 'tip'
1025 ('symbol', 'tip')
1028 ('symbol', 'tip')
1026 9
1029 9
1027
1030
1028 $ hg debugrevspec --debug --config revsetalias.'bad name'='tip' "tip"
1031 $ hg debugrevspec --debug --config revsetalias.'bad name'='tip' "tip"
1029 ('symbol', 'tip')
1032 ('symbol', 'tip')
1030 warning: failed to parse the declaration of revset alias "bad name": at 4: invalid token
1033 warning: failed to parse the declaration of revset alias "bad name": at 4: invalid token
1031 9
1034 9
1032 $ echo 'strictreplacing($1, $10) = $10 or desc("$1")' >> .hg/hgrc
1035 $ echo 'strictreplacing($1, $10) = $10 or desc("$1")' >> .hg/hgrc
1033 $ try 'strictreplacing("foo", tip)'
1036 $ try 'strictreplacing("foo", tip)'
1034 (func
1037 (func
1035 ('symbol', 'strictreplacing')
1038 ('symbol', 'strictreplacing')
1036 (list
1039 (list
1037 ('string', 'foo')
1040 ('string', 'foo')
1038 ('symbol', 'tip')))
1041 ('symbol', 'tip')))
1039 (or
1042 (or
1040 ('symbol', 'tip')
1043 ('symbol', 'tip')
1041 (func
1044 (func
1042 ('symbol', 'desc')
1045 ('symbol', 'desc')
1043 ('string', '$1')))
1046 ('string', '$1')))
1044 9
1047 9
1045
1048
1046 $ try 'd(2:5)'
1049 $ try 'd(2:5)'
1047 (func
1050 (func
1048 ('symbol', 'd')
1051 ('symbol', 'd')
1049 (range
1052 (range
1050 ('symbol', '2')
1053 ('symbol', '2')
1051 ('symbol', '5')))
1054 ('symbol', '5')))
1052 (func
1055 (func
1053 ('symbol', 'reverse')
1056 ('symbol', 'reverse')
1054 (func
1057 (func
1055 ('symbol', 'sort')
1058 ('symbol', 'sort')
1056 (list
1059 (list
1057 (range
1060 (range
1058 ('symbol', '2')
1061 ('symbol', '2')
1059 ('symbol', '5'))
1062 ('symbol', '5'))
1060 ('symbol', 'date'))))
1063 ('symbol', 'date'))))
1061 4
1064 4
1062 5
1065 5
1063 3
1066 3
1064 2
1067 2
1065 $ try 'rs(2 or 3, date)'
1068 $ try 'rs(2 or 3, date)'
1066 (func
1069 (func
1067 ('symbol', 'rs')
1070 ('symbol', 'rs')
1068 (list
1071 (list
1069 (or
1072 (or
1070 ('symbol', '2')
1073 ('symbol', '2')
1071 ('symbol', '3'))
1074 ('symbol', '3'))
1072 ('symbol', 'date')))
1075 ('symbol', 'date')))
1073 (func
1076 (func
1074 ('symbol', 'reverse')
1077 ('symbol', 'reverse')
1075 (func
1078 (func
1076 ('symbol', 'sort')
1079 ('symbol', 'sort')
1077 (list
1080 (list
1078 (or
1081 (or
1079 ('symbol', '2')
1082 ('symbol', '2')
1080 ('symbol', '3'))
1083 ('symbol', '3'))
1081 ('symbol', 'date'))))
1084 ('symbol', 'date'))))
1082 3
1085 3
1083 2
1086 2
1084 $ try 'rs()'
1087 $ try 'rs()'
1085 (func
1088 (func
1086 ('symbol', 'rs')
1089 ('symbol', 'rs')
1087 None)
1090 None)
1088 hg: parse error: invalid number of arguments: 0
1091 hg: parse error: invalid number of arguments: 0
1089 [255]
1092 [255]
1090 $ try 'rs(2)'
1093 $ try 'rs(2)'
1091 (func
1094 (func
1092 ('symbol', 'rs')
1095 ('symbol', 'rs')
1093 ('symbol', '2'))
1096 ('symbol', '2'))
1094 hg: parse error: invalid number of arguments: 1
1097 hg: parse error: invalid number of arguments: 1
1095 [255]
1098 [255]
1096 $ try 'rs(2, data, 7)'
1099 $ try 'rs(2, data, 7)'
1097 (func
1100 (func
1098 ('symbol', 'rs')
1101 ('symbol', 'rs')
1099 (list
1102 (list
1100 (list
1103 (list
1101 ('symbol', '2')
1104 ('symbol', '2')
1102 ('symbol', 'data'))
1105 ('symbol', 'data'))
1103 ('symbol', '7')))
1106 ('symbol', '7')))
1104 hg: parse error: invalid number of arguments: 3
1107 hg: parse error: invalid number of arguments: 3
1105 [255]
1108 [255]
1106 $ try 'rs4(2 or 3, x, x, date)'
1109 $ try 'rs4(2 or 3, x, x, date)'
1107 (func
1110 (func
1108 ('symbol', 'rs4')
1111 ('symbol', 'rs4')
1109 (list
1112 (list
1110 (list
1113 (list
1111 (list
1114 (list
1112 (or
1115 (or
1113 ('symbol', '2')
1116 ('symbol', '2')
1114 ('symbol', '3'))
1117 ('symbol', '3'))
1115 ('symbol', 'x'))
1118 ('symbol', 'x'))
1116 ('symbol', 'x'))
1119 ('symbol', 'x'))
1117 ('symbol', 'date')))
1120 ('symbol', 'date')))
1118 (func
1121 (func
1119 ('symbol', 'reverse')
1122 ('symbol', 'reverse')
1120 (func
1123 (func
1121 ('symbol', 'sort')
1124 ('symbol', 'sort')
1122 (list
1125 (list
1123 (or
1126 (or
1124 ('symbol', '2')
1127 ('symbol', '2')
1125 ('symbol', '3'))
1128 ('symbol', '3'))
1126 ('symbol', 'date'))))
1129 ('symbol', 'date'))))
1127 3
1130 3
1128 2
1131 2
1129
1132
1130 issue4553: check that revset aliases override existing hash prefix
1133 issue4553: check that revset aliases override existing hash prefix
1131
1134
1132 $ hg log -qr e
1135 $ hg log -qr e
1133 6:e0cc66ef77e8
1136 6:e0cc66ef77e8
1134
1137
1135 $ hg log -qr e --config revsetalias.e="all()"
1138 $ hg log -qr e --config revsetalias.e="all()"
1136 0:2785f51eece5
1139 0:2785f51eece5
1137 1:d75937da8da0
1140 1:d75937da8da0
1138 2:5ed5505e9f1c
1141 2:5ed5505e9f1c
1139 3:8528aa5637f2
1142 3:8528aa5637f2
1140 4:2326846efdab
1143 4:2326846efdab
1141 5:904fa392b941
1144 5:904fa392b941
1142 6:e0cc66ef77e8
1145 6:e0cc66ef77e8
1143 7:013af1973af4
1146 7:013af1973af4
1144 8:d5d0dcbdc4d9
1147 8:d5d0dcbdc4d9
1145 9:24286f4ae135
1148 9:24286f4ae135
1146
1149
1147 $ hg log -qr e: --config revsetalias.e="0"
1150 $ hg log -qr e: --config revsetalias.e="0"
1148 0:2785f51eece5
1151 0:2785f51eece5
1149 1:d75937da8da0
1152 1:d75937da8da0
1150 2:5ed5505e9f1c
1153 2:5ed5505e9f1c
1151 3:8528aa5637f2
1154 3:8528aa5637f2
1152 4:2326846efdab
1155 4:2326846efdab
1153 5:904fa392b941
1156 5:904fa392b941
1154 6:e0cc66ef77e8
1157 6:e0cc66ef77e8
1155 7:013af1973af4
1158 7:013af1973af4
1156 8:d5d0dcbdc4d9
1159 8:d5d0dcbdc4d9
1157 9:24286f4ae135
1160 9:24286f4ae135
1158
1161
1159 $ hg log -qr :e --config revsetalias.e="9"
1162 $ hg log -qr :e --config revsetalias.e="9"
1160 0:2785f51eece5
1163 0:2785f51eece5
1161 1:d75937da8da0
1164 1:d75937da8da0
1162 2:5ed5505e9f1c
1165 2:5ed5505e9f1c
1163 3:8528aa5637f2
1166 3:8528aa5637f2
1164 4:2326846efdab
1167 4:2326846efdab
1165 5:904fa392b941
1168 5:904fa392b941
1166 6:e0cc66ef77e8
1169 6:e0cc66ef77e8
1167 7:013af1973af4
1170 7:013af1973af4
1168 8:d5d0dcbdc4d9
1171 8:d5d0dcbdc4d9
1169 9:24286f4ae135
1172 9:24286f4ae135
1170
1173
1171 $ hg log -qr e:
1174 $ hg log -qr e:
1172 6:e0cc66ef77e8
1175 6:e0cc66ef77e8
1173 7:013af1973af4
1176 7:013af1973af4
1174 8:d5d0dcbdc4d9
1177 8:d5d0dcbdc4d9
1175 9:24286f4ae135
1178 9:24286f4ae135
1176
1179
1177 $ hg log -qr :e
1180 $ hg log -qr :e
1178 0:2785f51eece5
1181 0:2785f51eece5
1179 1:d75937da8da0
1182 1:d75937da8da0
1180 2:5ed5505e9f1c
1183 2:5ed5505e9f1c
1181 3:8528aa5637f2
1184 3:8528aa5637f2
1182 4:2326846efdab
1185 4:2326846efdab
1183 5:904fa392b941
1186 5:904fa392b941
1184 6:e0cc66ef77e8
1187 6:e0cc66ef77e8
1185
1188
1186 issue2549 - correct optimizations
1189 issue2549 - correct optimizations
1187
1190
1188 $ log 'limit(1 or 2 or 3, 2) and not 2'
1191 $ log 'limit(1 or 2 or 3, 2) and not 2'
1189 1
1192 1
1190 $ log 'max(1 or 2) and not 2'
1193 $ log 'max(1 or 2) and not 2'
1191 $ log 'min(1 or 2) and not 1'
1194 $ log 'min(1 or 2) and not 1'
1192 $ log 'last(1 or 2, 1) and not 2'
1195 $ log 'last(1 or 2, 1) and not 2'
1193
1196
1194 issue4289 - ordering of built-ins
1197 issue4289 - ordering of built-ins
1195 $ hg log -M -q -r 3:2
1198 $ hg log -M -q -r 3:2
1196 3:8528aa5637f2
1199 3:8528aa5637f2
1197 2:5ed5505e9f1c
1200 2:5ed5505e9f1c
1198
1201
1199 test revsets started with 40-chars hash (issue3669)
1202 test revsets started with 40-chars hash (issue3669)
1200
1203
1201 $ ISSUE3669_TIP=`hg tip --template '{node}'`
1204 $ ISSUE3669_TIP=`hg tip --template '{node}'`
1202 $ hg log -r "${ISSUE3669_TIP}" --template '{rev}\n'
1205 $ hg log -r "${ISSUE3669_TIP}" --template '{rev}\n'
1203 9
1206 9
1204 $ hg log -r "${ISSUE3669_TIP}^" --template '{rev}\n'
1207 $ hg log -r "${ISSUE3669_TIP}^" --template '{rev}\n'
1205 8
1208 8
1206
1209
1207 test or-ed indirect predicates (issue3775)
1210 test or-ed indirect predicates (issue3775)
1208
1211
1209 $ log '6 or 6^1' | sort
1212 $ log '6 or 6^1' | sort
1210 5
1213 5
1211 6
1214 6
1212 $ log '6^1 or 6' | sort
1215 $ log '6^1 or 6' | sort
1213 5
1216 5
1214 6
1217 6
1215 $ log '4 or 4~1' | sort
1218 $ log '4 or 4~1' | sort
1216 2
1219 2
1217 4
1220 4
1218 $ log '4~1 or 4' | sort
1221 $ log '4~1 or 4' | sort
1219 2
1222 2
1220 4
1223 4
1221 $ log '(0 or 2):(4 or 6) or 0 or 6' | sort
1224 $ log '(0 or 2):(4 or 6) or 0 or 6' | sort
1222 0
1225 0
1223 1
1226 1
1224 2
1227 2
1225 3
1228 3
1226 4
1229 4
1227 5
1230 5
1228 6
1231 6
1229 $ log '0 or 6 or (0 or 2):(4 or 6)' | sort
1232 $ log '0 or 6 or (0 or 2):(4 or 6)' | sort
1230 0
1233 0
1231 1
1234 1
1232 2
1235 2
1233 3
1236 3
1234 4
1237 4
1235 5
1238 5
1236 6
1239 6
1237
1240
1238 tests for 'remote()' predicate:
1241 tests for 'remote()' predicate:
1239 #. (csets in remote) (id) (remote)
1242 #. (csets in remote) (id) (remote)
1240 1. less than local current branch "default"
1243 1. less than local current branch "default"
1241 2. same with local specified "default"
1244 2. same with local specified "default"
1242 3. more than local specified specified
1245 3. more than local specified specified
1243
1246
1244 $ hg clone --quiet -U . ../remote3
1247 $ hg clone --quiet -U . ../remote3
1245 $ cd ../remote3
1248 $ cd ../remote3
1246 $ hg update -q 7
1249 $ hg update -q 7
1247 $ echo r > r
1250 $ echo r > r
1248 $ hg ci -Aqm 10
1251 $ hg ci -Aqm 10
1249 $ log 'remote()'
1252 $ log 'remote()'
1250 7
1253 7
1251 $ log 'remote("a-b-c-")'
1254 $ log 'remote("a-b-c-")'
1252 2
1255 2
1253 $ cd ../repo
1256 $ cd ../repo
1254 $ log 'remote(".a.b.c.", "../remote3")'
1257 $ log 'remote(".a.b.c.", "../remote3")'
1255
1258
1256 tests for concatenation of strings/symbols by "##"
1259 tests for concatenation of strings/symbols by "##"
1257
1260
1258 $ try "278 ## '5f5' ## 1ee ## 'ce5'"
1261 $ try "278 ## '5f5' ## 1ee ## 'ce5'"
1259 (_concat
1262 (_concat
1260 (_concat
1263 (_concat
1261 (_concat
1264 (_concat
1262 ('symbol', '278')
1265 ('symbol', '278')
1263 ('string', '5f5'))
1266 ('string', '5f5'))
1264 ('symbol', '1ee'))
1267 ('symbol', '1ee'))
1265 ('string', 'ce5'))
1268 ('string', 'ce5'))
1266 ('string', '2785f51eece5')
1269 ('string', '2785f51eece5')
1267 0
1270 0
1268
1271
1269 $ echo 'cat4($1, $2, $3, $4) = $1 ## $2 ## $3 ## $4' >> .hg/hgrc
1272 $ echo 'cat4($1, $2, $3, $4) = $1 ## $2 ## $3 ## $4' >> .hg/hgrc
1270 $ try "cat4(278, '5f5', 1ee, 'ce5')"
1273 $ try "cat4(278, '5f5', 1ee, 'ce5')"
1271 (func
1274 (func
1272 ('symbol', 'cat4')
1275 ('symbol', 'cat4')
1273 (list
1276 (list
1274 (list
1277 (list
1275 (list
1278 (list
1276 ('symbol', '278')
1279 ('symbol', '278')
1277 ('string', '5f5'))
1280 ('string', '5f5'))
1278 ('symbol', '1ee'))
1281 ('symbol', '1ee'))
1279 ('string', 'ce5')))
1282 ('string', 'ce5')))
1280 (_concat
1283 (_concat
1281 (_concat
1284 (_concat
1282 (_concat
1285 (_concat
1283 ('symbol', '278')
1286 ('symbol', '278')
1284 ('string', '5f5'))
1287 ('string', '5f5'))
1285 ('symbol', '1ee'))
1288 ('symbol', '1ee'))
1286 ('string', 'ce5'))
1289 ('string', 'ce5'))
1287 ('string', '2785f51eece5')
1290 ('string', '2785f51eece5')
1288 0
1291 0
1289
1292
1290 (check concatenation in alias nesting)
1293 (check concatenation in alias nesting)
1291
1294
1292 $ echo 'cat2($1, $2) = $1 ## $2' >> .hg/hgrc
1295 $ echo 'cat2($1, $2) = $1 ## $2' >> .hg/hgrc
1293 $ echo 'cat2x2($1, $2, $3, $4) = cat2($1 ## $2, $3 ## $4)' >> .hg/hgrc
1296 $ echo 'cat2x2($1, $2, $3, $4) = cat2($1 ## $2, $3 ## $4)' >> .hg/hgrc
1294 $ log "cat2x2(278, '5f5', 1ee, 'ce5')"
1297 $ log "cat2x2(278, '5f5', 1ee, 'ce5')"
1295 0
1298 0
1296
1299
1297 (check operator priority)
1300 (check operator priority)
1298
1301
1299 $ echo 'cat2n2($1, $2, $3, $4) = $1 ## $2 or $3 ## $4~2' >> .hg/hgrc
1302 $ echo 'cat2n2($1, $2, $3, $4) = $1 ## $2 or $3 ## $4~2' >> .hg/hgrc
1300 $ log "cat2n2(2785f5, 1eece5, 24286f, 4ae135)"
1303 $ log "cat2n2(2785f5, 1eece5, 24286f, 4ae135)"
1301 0
1304 0
1302 4
1305 4
1303
1306
1304 $ cd ..
1307 $ cd ..
1305
1308
1306 test author/desc/keyword in problematic encoding
1309 test author/desc/keyword in problematic encoding
1307 # unicode: cp932:
1310 # unicode: cp932:
1308 # u30A2 0x83 0x41(= 'A')
1311 # u30A2 0x83 0x41(= 'A')
1309 # u30C2 0x83 0x61(= 'a')
1312 # u30C2 0x83 0x61(= 'a')
1310
1313
1311 $ hg init problematicencoding
1314 $ hg init problematicencoding
1312 $ cd problematicencoding
1315 $ cd problematicencoding
1313
1316
1314 $ python > setup.sh <<EOF
1317 $ python > setup.sh <<EOF
1315 > print u'''
1318 > print u'''
1316 > echo a > text
1319 > echo a > text
1317 > hg add text
1320 > hg add text
1318 > hg --encoding utf-8 commit -u '\u30A2' -m none
1321 > hg --encoding utf-8 commit -u '\u30A2' -m none
1319 > echo b > text
1322 > echo b > text
1320 > hg --encoding utf-8 commit -u '\u30C2' -m none
1323 > hg --encoding utf-8 commit -u '\u30C2' -m none
1321 > echo c > text
1324 > echo c > text
1322 > hg --encoding utf-8 commit -u none -m '\u30A2'
1325 > hg --encoding utf-8 commit -u none -m '\u30A2'
1323 > echo d > text
1326 > echo d > text
1324 > hg --encoding utf-8 commit -u none -m '\u30C2'
1327 > hg --encoding utf-8 commit -u none -m '\u30C2'
1325 > '''.encode('utf-8')
1328 > '''.encode('utf-8')
1326 > EOF
1329 > EOF
1327 $ sh < setup.sh
1330 $ sh < setup.sh
1328
1331
1329 test in problematic encoding
1332 test in problematic encoding
1330 $ python > test.sh <<EOF
1333 $ python > test.sh <<EOF
1331 > print u'''
1334 > print u'''
1332 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30A2)'
1335 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30A2)'
1333 > echo ====
1336 > echo ====
1334 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30C2)'
1337 > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30C2)'
1335 > echo ====
1338 > echo ====
1336 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30A2)'
1339 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30A2)'
1337 > echo ====
1340 > echo ====
1338 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30C2)'
1341 > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30C2)'
1339 > echo ====
1342 > echo ====
1340 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30A2)'
1343 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30A2)'
1341 > echo ====
1344 > echo ====
1342 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30C2)'
1345 > hg --encoding cp932 log --template '{rev}\\n' -r 'keyword(\u30C2)'
1343 > '''.encode('cp932')
1346 > '''.encode('cp932')
1344 > EOF
1347 > EOF
1345 $ sh < test.sh
1348 $ sh < test.sh
1346 0
1349 0
1347 ====
1350 ====
1348 1
1351 1
1349 ====
1352 ====
1350 2
1353 2
1351 ====
1354 ====
1352 3
1355 3
1353 ====
1356 ====
1354 0
1357 0
1355 2
1358 2
1356 ====
1359 ====
1357 1
1360 1
1358 3
1361 3
1359
1362
1360 $ cd ..
1363 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now