##// END OF EJS Templates
templatefilters: add dirname() filter...
Yuya Nishihara -
r36260:9ee10b32 default
parent child Browse files
Show More
@@ -1,449 +1,456 b''
1 1 # templatefilters.py - common template expansion filters
2 2 #
3 3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import os
11 11 import re
12 12 import time
13 13
14 14 from . import (
15 15 encoding,
16 16 error,
17 17 hbisect,
18 18 node,
19 19 pycompat,
20 20 registrar,
21 21 templatekw,
22 22 url,
23 23 util,
24 24 )
25 25
26 26 urlerr = util.urlerr
27 27 urlreq = util.urlreq
28 28
29 29 if pycompat.ispy3:
30 30 long = int
31 31
32 32 # filters are callables like:
33 33 # fn(obj)
34 34 # with:
35 35 # obj - object to be filtered (text, date, list and so on)
36 36 filters = {}
37 37
38 38 templatefilter = registrar.templatefilter(filters)
39 39
40 40 @templatefilter('addbreaks')
41 41 def addbreaks(text):
42 42 """Any text. Add an XHTML "<br />" tag before the end of
43 43 every line except the last.
44 44 """
45 45 return text.replace('\n', '<br/>\n')
46 46
47 47 agescales = [("year", 3600 * 24 * 365, 'Y'),
48 48 ("month", 3600 * 24 * 30, 'M'),
49 49 ("week", 3600 * 24 * 7, 'W'),
50 50 ("day", 3600 * 24, 'd'),
51 51 ("hour", 3600, 'h'),
52 52 ("minute", 60, 'm'),
53 53 ("second", 1, 's')]
54 54
55 55 @templatefilter('age')
56 56 def age(date, abbrev=False):
57 57 """Date. Returns a human-readable date/time difference between the
58 58 given date/time and the current date/time.
59 59 """
60 60
61 61 def plural(t, c):
62 62 if c == 1:
63 63 return t
64 64 return t + "s"
65 65 def fmt(t, c, a):
66 66 if abbrev:
67 67 return "%d%s" % (c, a)
68 68 return "%d %s" % (c, plural(t, c))
69 69
70 70 now = time.time()
71 71 then = date[0]
72 72 future = False
73 73 if then > now:
74 74 future = True
75 75 delta = max(1, int(then - now))
76 76 if delta > agescales[0][1] * 30:
77 77 return 'in the distant future'
78 78 else:
79 79 delta = max(1, int(now - then))
80 80 if delta > agescales[0][1] * 2:
81 81 return util.shortdate(date)
82 82
83 83 for t, s, a in agescales:
84 84 n = delta // s
85 85 if n >= 2 or s == 1:
86 86 if future:
87 87 return '%s from now' % fmt(t, n, a)
88 88 return '%s ago' % fmt(t, n, a)
89 89
90 90 @templatefilter('basename')
91 91 def basename(path):
92 92 """Any text. Treats the text as a path, and returns the last
93 93 component of the path after splitting by the path separator.
94 94 For example, "foo/bar/baz" becomes "baz" and "foo/bar//" becomes "".
95 95 """
96 96 return os.path.basename(path)
97 97
98 98 @templatefilter('count')
99 99 def count(i):
100 100 """List or text. Returns the length as an integer."""
101 101 return len(i)
102 102
103 @templatefilter('dirname')
104 def dirname(path):
105 """Any text. Treats the text as a path, and strips the last
106 component of the path after splitting by the path separator.
107 """
108 return os.path.dirname(path)
109
103 110 @templatefilter('domain')
104 111 def domain(author):
105 112 """Any text. Finds the first string that looks like an email
106 113 address, and extracts just the domain component. Example: ``User
107 114 <user@example.com>`` becomes ``example.com``.
108 115 """
109 116 f = author.find('@')
110 117 if f == -1:
111 118 return ''
112 119 author = author[f + 1:]
113 120 f = author.find('>')
114 121 if f >= 0:
115 122 author = author[:f]
116 123 return author
117 124
118 125 @templatefilter('email')
119 126 def email(text):
120 127 """Any text. Extracts the first string that looks like an email
121 128 address. Example: ``User <user@example.com>`` becomes
122 129 ``user@example.com``.
123 130 """
124 131 return util.email(text)
125 132
126 133 @templatefilter('escape')
127 134 def escape(text):
128 135 """Any text. Replaces the special XML/XHTML characters "&", "<"
129 136 and ">" with XML entities, and filters out NUL characters.
130 137 """
131 138 return url.escape(text.replace('\0', ''), True)
132 139
133 140 para_re = None
134 141 space_re = None
135 142
136 143 def fill(text, width, initindent='', hangindent=''):
137 144 '''fill many paragraphs with optional indentation.'''
138 145 global para_re, space_re
139 146 if para_re is None:
140 147 para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
141 148 space_re = re.compile(r' +')
142 149
143 150 def findparas():
144 151 start = 0
145 152 while True:
146 153 m = para_re.search(text, start)
147 154 if not m:
148 155 uctext = unicode(text[start:], encoding.encoding)
149 156 w = len(uctext)
150 157 while 0 < w and uctext[w - 1].isspace():
151 158 w -= 1
152 159 yield (uctext[:w].encode(encoding.encoding),
153 160 uctext[w:].encode(encoding.encoding))
154 161 break
155 162 yield text[start:m.start(0)], m.group(1)
156 163 start = m.end(1)
157 164
158 165 return "".join([util.wrap(space_re.sub(' ', util.wrap(para, width)),
159 166 width, initindent, hangindent) + rest
160 167 for para, rest in findparas()])
161 168
162 169 @templatefilter('fill68')
163 170 def fill68(text):
164 171 """Any text. Wraps the text to fit in 68 columns."""
165 172 return fill(text, 68)
166 173
167 174 @templatefilter('fill76')
168 175 def fill76(text):
169 176 """Any text. Wraps the text to fit in 76 columns."""
170 177 return fill(text, 76)
171 178
172 179 @templatefilter('firstline')
173 180 def firstline(text):
174 181 """Any text. Returns the first line of text."""
175 182 try:
176 183 return text.splitlines(True)[0].rstrip('\r\n')
177 184 except IndexError:
178 185 return ''
179 186
180 187 @templatefilter('hex')
181 188 def hexfilter(text):
182 189 """Any text. Convert a binary Mercurial node identifier into
183 190 its long hexadecimal representation.
184 191 """
185 192 return node.hex(text)
186 193
187 194 @templatefilter('hgdate')
188 195 def hgdate(text):
189 196 """Date. Returns the date as a pair of numbers: "1157407993
190 197 25200" (Unix timestamp, timezone offset).
191 198 """
192 199 return "%d %d" % text
193 200
194 201 @templatefilter('isodate')
195 202 def isodate(text):
196 203 """Date. Returns the date in ISO 8601 format: "2009-08-18 13:00
197 204 +0200".
198 205 """
199 206 return util.datestr(text, '%Y-%m-%d %H:%M %1%2')
200 207
201 208 @templatefilter('isodatesec')
202 209 def isodatesec(text):
203 210 """Date. Returns the date in ISO 8601 format, including
204 211 seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date
205 212 filter.
206 213 """
207 214 return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2')
208 215
209 216 def indent(text, prefix):
210 217 '''indent each non-empty line of text after first with prefix.'''
211 218 lines = text.splitlines()
212 219 num_lines = len(lines)
213 220 endswithnewline = text[-1:] == '\n'
214 221 def indenter():
215 222 for i in xrange(num_lines):
216 223 l = lines[i]
217 224 if i and l.strip():
218 225 yield prefix
219 226 yield l
220 227 if i < num_lines - 1 or endswithnewline:
221 228 yield '\n'
222 229 return "".join(indenter())
223 230
224 231 @templatefilter('json')
225 232 def json(obj, paranoid=True):
226 233 if obj is None:
227 234 return 'null'
228 235 elif obj is False:
229 236 return 'false'
230 237 elif obj is True:
231 238 return 'true'
232 239 elif isinstance(obj, (int, long, float)):
233 240 return pycompat.bytestr(obj)
234 241 elif isinstance(obj, bytes):
235 242 return '"%s"' % encoding.jsonescape(obj, paranoid=paranoid)
236 243 elif isinstance(obj, str):
237 244 # This branch is unreachable on Python 2, because bytes == str
238 245 # and we'll return in the next-earlier block in the elif
239 246 # ladder. On Python 3, this helps us catch bugs before they
240 247 # hurt someone.
241 248 raise error.ProgrammingError(
242 249 'Mercurial only does output with bytes on Python 3: %r' % obj)
243 250 elif util.safehasattr(obj, 'keys'):
244 251 out = ['"%s": %s' % (encoding.jsonescape(k, paranoid=paranoid),
245 252 json(v, paranoid))
246 253 for k, v in sorted(obj.iteritems())]
247 254 return '{' + ', '.join(out) + '}'
248 255 elif util.safehasattr(obj, '__iter__'):
249 256 out = [json(i, paranoid) for i in obj]
250 257 return '[' + ', '.join(out) + ']'
251 258 else:
252 259 raise TypeError('cannot encode type %s' % obj.__class__.__name__)
253 260
254 261 @templatefilter('lower')
255 262 def lower(text):
256 263 """Any text. Converts the text to lowercase."""
257 264 return encoding.lower(text)
258 265
259 266 @templatefilter('nonempty')
260 267 def nonempty(str):
261 268 """Any text. Returns '(none)' if the string is empty."""
262 269 return str or "(none)"
263 270
264 271 @templatefilter('obfuscate')
265 272 def obfuscate(text):
266 273 """Any text. Returns the input text rendered as a sequence of
267 274 XML entities.
268 275 """
269 276 text = unicode(text, encoding.encoding, 'replace')
270 277 return ''.join(['&#%d;' % ord(c) for c in text])
271 278
272 279 @templatefilter('permissions')
273 280 def permissions(flags):
274 281 if "l" in flags:
275 282 return "lrwxrwxrwx"
276 283 if "x" in flags:
277 284 return "-rwxr-xr-x"
278 285 return "-rw-r--r--"
279 286
280 287 @templatefilter('person')
281 288 def person(author):
282 289 """Any text. Returns the name before an email address,
283 290 interpreting it as per RFC 5322.
284 291
285 292 >>> person(b'foo@bar')
286 293 'foo'
287 294 >>> person(b'Foo Bar <foo@bar>')
288 295 'Foo Bar'
289 296 >>> person(b'"Foo Bar" <foo@bar>')
290 297 'Foo Bar'
291 298 >>> person(b'"Foo \"buz\" Bar" <foo@bar>')
292 299 'Foo "buz" Bar'
293 300 >>> # The following are invalid, but do exist in real-life
294 301 ...
295 302 >>> person(b'Foo "buz" Bar <foo@bar>')
296 303 'Foo "buz" Bar'
297 304 >>> person(b'"Foo Bar <foo@bar>')
298 305 'Foo Bar'
299 306 """
300 307 if '@' not in author:
301 308 return author
302 309 f = author.find('<')
303 310 if f != -1:
304 311 return author[:f].strip(' "').replace('\\"', '"')
305 312 f = author.find('@')
306 313 return author[:f].replace('.', ' ')
307 314
308 315 @templatefilter('revescape')
309 316 def revescape(text):
310 317 """Any text. Escapes all "special" characters, except @.
311 318 Forward slashes are escaped twice to prevent web servers from prematurely
312 319 unescaping them. For example, "@foo bar/baz" becomes "@foo%20bar%252Fbaz".
313 320 """
314 321 return urlreq.quote(text, safe='/@').replace('/', '%252F')
315 322
316 323 @templatefilter('rfc3339date')
317 324 def rfc3339date(text):
318 325 """Date. Returns a date using the Internet date format
319 326 specified in RFC 3339: "2009-08-18T13:00:13+02:00".
320 327 """
321 328 return util.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2")
322 329
323 330 @templatefilter('rfc822date')
324 331 def rfc822date(text):
325 332 """Date. Returns a date using the same format used in email
326 333 headers: "Tue, 18 Aug 2009 13:00:13 +0200".
327 334 """
328 335 return util.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
329 336
330 337 @templatefilter('short')
331 338 def short(text):
332 339 """Changeset hash. Returns the short form of a changeset hash,
333 340 i.e. a 12 hexadecimal digit string.
334 341 """
335 342 return text[:12]
336 343
337 344 @templatefilter('shortbisect')
338 345 def shortbisect(text):
339 346 """Any text. Treats `text` as a bisection status, and
340 347 returns a single-character representing the status (G: good, B: bad,
341 348 S: skipped, U: untested, I: ignored). Returns single space if `text`
342 349 is not a valid bisection status.
343 350 """
344 351 return hbisect.shortlabel(text) or ' '
345 352
346 353 @templatefilter('shortdate')
347 354 def shortdate(text):
348 355 """Date. Returns a date like "2006-09-18"."""
349 356 return util.shortdate(text)
350 357
351 358 @templatefilter('slashpath')
352 359 def slashpath(path):
353 360 """Any text. Replaces the native path separator with slash."""
354 361 return util.pconvert(path)
355 362
356 363 @templatefilter('splitlines')
357 364 def splitlines(text):
358 365 """Any text. Split text into a list of lines."""
359 366 return templatekw.hybridlist(text.splitlines(), name='line')
360 367
361 368 @templatefilter('stringescape')
362 369 def stringescape(text):
363 370 return util.escapestr(text)
364 371
365 372 @templatefilter('stringify')
366 373 def stringify(thing):
367 374 """Any type. Turns the value into text by converting values into
368 375 text and concatenating them.
369 376 """
370 377 thing = templatekw.unwraphybrid(thing)
371 378 if util.safehasattr(thing, '__iter__') and not isinstance(thing, bytes):
372 379 return "".join([stringify(t) for t in thing if t is not None])
373 380 if thing is None:
374 381 return ""
375 382 return pycompat.bytestr(thing)
376 383
377 384 @templatefilter('stripdir')
378 385 def stripdir(text):
379 386 """Treat the text as path and strip a directory level, if
380 387 possible. For example, "foo" and "foo/bar" becomes "foo".
381 388 """
382 389 dir = os.path.dirname(text)
383 390 if dir == "":
384 391 return os.path.basename(text)
385 392 else:
386 393 return dir
387 394
388 395 @templatefilter('tabindent')
389 396 def tabindent(text):
390 397 """Any text. Returns the text, with every non-empty line
391 398 except the first starting with a tab character.
392 399 """
393 400 return indent(text, '\t')
394 401
395 402 @templatefilter('upper')
396 403 def upper(text):
397 404 """Any text. Converts the text to uppercase."""
398 405 return encoding.upper(text)
399 406
400 407 @templatefilter('urlescape')
401 408 def urlescape(text):
402 409 """Any text. Escapes all "special" characters. For example,
403 410 "foo bar" becomes "foo%20bar".
404 411 """
405 412 return urlreq.quote(text)
406 413
407 414 @templatefilter('user')
408 415 def userfilter(text):
409 416 """Any text. Returns a short representation of a user name or email
410 417 address."""
411 418 return util.shortuser(text)
412 419
413 420 @templatefilter('emailuser')
414 421 def emailuser(text):
415 422 """Any text. Returns the user portion of an email address."""
416 423 return util.emailuser(text)
417 424
418 425 @templatefilter('utf8')
419 426 def utf8(text):
420 427 """Any text. Converts from the local character encoding to UTF-8."""
421 428 return encoding.fromlocal(text)
422 429
423 430 @templatefilter('xmlescape')
424 431 def xmlescape(text):
425 432 text = (text
426 433 .replace('&', '&amp;')
427 434 .replace('<', '&lt;')
428 435 .replace('>', '&gt;')
429 436 .replace('"', '&quot;')
430 437 .replace("'", '&#39;')) # &apos; invalid in HTML
431 438 return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
432 439
433 440 def websub(text, websubtable):
434 441 """:websub: Any text. Only applies to hgweb. Applies the regular
435 442 expression replacements defined in the websub section.
436 443 """
437 444 if websubtable:
438 445 for regexp, format in websubtable:
439 446 text = regexp.sub(format, text)
440 447 return text
441 448
442 449 def loadfilter(ui, extname, registrarobj):
443 450 """Load template filter from specified registrarobj
444 451 """
445 452 for name, func in registrarobj._table.iteritems():
446 453 filters[name] = func
447 454
448 455 # tell hggettext to extract docstrings from these functions:
449 456 i18nfunctions = filters.values()
@@ -1,4783 +1,4787 b''
1 1 $ hg init a
2 2 $ cd a
3 3 $ echo a > a
4 4 $ hg add a
5 5 $ echo line 1 > b
6 6 $ echo line 2 >> b
7 7 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
8 8
9 9 $ hg add b
10 10 $ echo other 1 > c
11 11 $ echo other 2 >> c
12 12 $ echo >> c
13 13 $ echo other 3 >> c
14 14 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
15 15
16 16 $ hg add c
17 17 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
18 18 $ echo c >> c
19 19 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
20 20
21 21 $ echo foo > .hg/branch
22 22 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
23 23
24 24 $ hg co -q 3
25 25 $ echo other 4 >> d
26 26 $ hg add d
27 27 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
28 28
29 29 $ hg merge -q foo
30 30 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
31 31
32 32 Test arithmetic operators have the right precedence:
33 33
34 34 $ hg log -l 1 -T '{date(date, "%Y") + 5 * 10} {date(date, "%Y") - 2 * 3}\n'
35 35 2020 1964
36 36 $ hg log -l 1 -T '{date(date, "%Y") * 5 + 10} {date(date, "%Y") * 3 - 2}\n'
37 37 9860 5908
38 38
39 39 Test division:
40 40
41 41 $ hg debugtemplate -r0 -v '{5 / 2} {mod(5, 2)}\n'
42 42 (template
43 43 (/
44 44 (integer '5')
45 45 (integer '2'))
46 46 (string ' ')
47 47 (func
48 48 (symbol 'mod')
49 49 (list
50 50 (integer '5')
51 51 (integer '2')))
52 52 (string '\n'))
53 53 2 1
54 54 $ hg debugtemplate -r0 -v '{5 / -2} {mod(5, -2)}\n'
55 55 (template
56 56 (/
57 57 (integer '5')
58 58 (negate
59 59 (integer '2')))
60 60 (string ' ')
61 61 (func
62 62 (symbol 'mod')
63 63 (list
64 64 (integer '5')
65 65 (negate
66 66 (integer '2'))))
67 67 (string '\n'))
68 68 -3 -1
69 69 $ hg debugtemplate -r0 -v '{-5 / 2} {mod(-5, 2)}\n'
70 70 (template
71 71 (/
72 72 (negate
73 73 (integer '5'))
74 74 (integer '2'))
75 75 (string ' ')
76 76 (func
77 77 (symbol 'mod')
78 78 (list
79 79 (negate
80 80 (integer '5'))
81 81 (integer '2')))
82 82 (string '\n'))
83 83 -3 1
84 84 $ hg debugtemplate -r0 -v '{-5 / -2} {mod(-5, -2)}\n'
85 85 (template
86 86 (/
87 87 (negate
88 88 (integer '5'))
89 89 (negate
90 90 (integer '2')))
91 91 (string ' ')
92 92 (func
93 93 (symbol 'mod')
94 94 (list
95 95 (negate
96 96 (integer '5'))
97 97 (negate
98 98 (integer '2'))))
99 99 (string '\n'))
100 100 2 -1
101 101
102 102 Filters bind closer than arithmetic:
103 103
104 104 $ hg debugtemplate -r0 -v '{revset(".")|count - 1}\n'
105 105 (template
106 106 (-
107 107 (|
108 108 (func
109 109 (symbol 'revset')
110 110 (string '.'))
111 111 (symbol 'count'))
112 112 (integer '1'))
113 113 (string '\n'))
114 114 0
115 115
116 116 But negate binds closer still:
117 117
118 118 $ hg debugtemplate -r0 -v '{1-3|stringify}\n'
119 119 (template
120 120 (-
121 121 (integer '1')
122 122 (|
123 123 (integer '3')
124 124 (symbol 'stringify')))
125 125 (string '\n'))
126 126 hg: parse error: arithmetic only defined on integers
127 127 [255]
128 128 $ hg debugtemplate -r0 -v '{-3|stringify}\n'
129 129 (template
130 130 (|
131 131 (negate
132 132 (integer '3'))
133 133 (symbol 'stringify'))
134 134 (string '\n'))
135 135 -3
136 136
137 137 Filters bind as close as map operator:
138 138
139 139 $ hg debugtemplate -r0 -v '{desc|splitlines % "{line}\n"}'
140 140 (template
141 141 (%
142 142 (|
143 143 (symbol 'desc')
144 144 (symbol 'splitlines'))
145 145 (template
146 146 (symbol 'line')
147 147 (string '\n'))))
148 148 line 1
149 149 line 2
150 150
151 151 Keyword arguments:
152 152
153 153 $ hg debugtemplate -r0 -v '{foo=bar|baz}'
154 154 (template
155 155 (keyvalue
156 156 (symbol 'foo')
157 157 (|
158 158 (symbol 'bar')
159 159 (symbol 'baz'))))
160 160 hg: parse error: can't use a key-value pair in this context
161 161 [255]
162 162
163 163 $ hg debugtemplate '{pad("foo", width=10, left=true)}\n'
164 164 foo
165 165
166 166 Call function which takes named arguments by filter syntax:
167 167
168 168 $ hg debugtemplate '{" "|separate}'
169 169 $ hg debugtemplate '{("not", "an", "argument", "list")|separate}'
170 170 hg: parse error: unknown method 'list'
171 171 [255]
172 172
173 173 Second branch starting at nullrev:
174 174
175 175 $ hg update null
176 176 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
177 177 $ echo second > second
178 178 $ hg add second
179 179 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
180 180 created new head
181 181
182 182 $ echo third > third
183 183 $ hg add third
184 184 $ hg mv second fourth
185 185 $ hg commit -m third -d "2020-01-01 10:01"
186 186
187 187 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
188 188 fourth (second)
189 189 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
190 190 second -> fourth
191 191 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
192 192 8 t
193 193 7 f
194 194
195 195 Working-directory revision has special identifiers, though they are still
196 196 experimental:
197 197
198 198 $ hg log -r 'wdir()' -T '{rev}:{node}\n'
199 199 2147483647:ffffffffffffffffffffffffffffffffffffffff
200 200
201 201 Some keywords are invalid for working-directory revision, but they should
202 202 never cause crash:
203 203
204 204 $ hg log -r 'wdir()' -T '{manifest}\n'
205 205
206 206
207 207 Internal resources shouldn't be exposed (issue5699):
208 208
209 209 $ hg log -r. -T '{cache}{ctx}{repo}{revcache}{templ}{ui}'
210 210
211 211 Never crash on internal resource not available:
212 212
213 213 $ hg --cwd .. debugtemplate '{"c0bebeef"|shortest}\n'
214 214 abort: template resource not available: ctx
215 215 [255]
216 216
217 217 Quoting for ui.logtemplate
218 218
219 219 $ hg tip --config "ui.logtemplate={rev}\n"
220 220 8
221 221 $ hg tip --config "ui.logtemplate='{rev}\n'"
222 222 8
223 223 $ hg tip --config 'ui.logtemplate="{rev}\n"'
224 224 8
225 225 $ hg tip --config 'ui.logtemplate=n{rev}\n'
226 226 n8
227 227
228 228 Make sure user/global hgrc does not affect tests
229 229
230 230 $ echo '[ui]' > .hg/hgrc
231 231 $ echo 'logtemplate =' >> .hg/hgrc
232 232 $ echo 'style =' >> .hg/hgrc
233 233
234 234 Add some simple styles to settings
235 235
236 236 $ cat <<'EOF' >> .hg/hgrc
237 237 > [templates]
238 238 > simple = "{rev}\n"
239 239 > simple2 = {rev}\n
240 240 > rev = "should not precede {rev} keyword\n"
241 241 > EOF
242 242
243 243 $ hg log -l1 -Tsimple
244 244 8
245 245 $ hg log -l1 -Tsimple2
246 246 8
247 247 $ hg log -l1 -Trev
248 248 should not precede 8 keyword
249 249 $ hg log -l1 -T '{simple}'
250 250 8
251 251
252 252 Map file shouldn't see user templates:
253 253
254 254 $ cat <<EOF > tmpl
255 255 > changeset = 'nothing expanded:{simple}\n'
256 256 > EOF
257 257 $ hg log -l1 --style ./tmpl
258 258 nothing expanded:
259 259
260 260 Test templates and style maps in files:
261 261
262 262 $ echo "{rev}" > tmpl
263 263 $ hg log -l1 -T./tmpl
264 264 8
265 265 $ hg log -l1 -Tblah/blah
266 266 blah/blah (no-eol)
267 267
268 268 $ printf 'changeset = "{rev}\\n"\n' > map-simple
269 269 $ hg log -l1 -T./map-simple
270 270 8
271 271
272 272 a map file may have [templates] and [templatealias] sections:
273 273
274 274 $ cat <<'EOF' > map-simple
275 275 > [templates]
276 276 > changeset = "{a}\n"
277 277 > [templatealias]
278 278 > a = rev
279 279 > EOF
280 280 $ hg log -l1 -T./map-simple
281 281 8
282 282
283 283 so it can be included in hgrc
284 284
285 285 $ cat <<'EOF' > myhgrc
286 286 > %include map-simple
287 287 > [templates]
288 288 > foo = "{changeset}"
289 289 > EOF
290 290 $ HGRCPATH=./myhgrc hg log -l1 -Tfoo
291 291 8
292 292 $ HGRCPATH=./myhgrc hg log -l1 -T'{a}\n'
293 293 8
294 294
295 295 Test template map inheritance
296 296
297 297 $ echo "__base__ = map-cmdline.default" > map-simple
298 298 $ printf 'cset = "changeset: ***{rev}***\\n"\n' >> map-simple
299 299 $ hg log -l1 -T./map-simple
300 300 changeset: ***8***
301 301 tag: tip
302 302 user: test
303 303 date: Wed Jan 01 10:01:00 2020 +0000
304 304 summary: third
305 305
306 306
307 307 Test docheader, docfooter and separator in template map
308 308
309 309 $ cat <<'EOF' > map-myjson
310 310 > docheader = '\{\n'
311 311 > docfooter = '\n}\n'
312 312 > separator = ',\n'
313 313 > changeset = ' {dict(rev, node|short)|json}'
314 314 > EOF
315 315 $ hg log -l2 -T./map-myjson
316 316 {
317 317 {"node": "95c24699272e", "rev": 8},
318 318 {"node": "29114dbae42b", "rev": 7}
319 319 }
320 320
321 321 Test docheader, docfooter and separator in [templates] section
322 322
323 323 $ cat <<'EOF' >> .hg/hgrc
324 324 > [templates]
325 325 > myjson = ' {dict(rev, node|short)|json}'
326 326 > myjson:docheader = '\{\n'
327 327 > myjson:docfooter = '\n}\n'
328 328 > myjson:separator = ',\n'
329 329 > :docheader = 'should not be selected as a docheader for literal templates\n'
330 330 > EOF
331 331 $ hg log -l2 -Tmyjson
332 332 {
333 333 {"node": "95c24699272e", "rev": 8},
334 334 {"node": "29114dbae42b", "rev": 7}
335 335 }
336 336 $ hg log -l1 -T'{rev}\n'
337 337 8
338 338
339 339 Template should precede style option
340 340
341 341 $ hg log -l1 --style default -T '{rev}\n'
342 342 8
343 343
344 344 Add a commit with empty description, to ensure that the templates
345 345 below will omit the description line.
346 346
347 347 $ echo c >> c
348 348 $ hg add c
349 349 $ hg commit -qm ' '
350 350
351 351 Default style is like normal output. Phases style should be the same
352 352 as default style, except for extra phase lines.
353 353
354 354 $ hg log > log.out
355 355 $ hg log --style default > style.out
356 356 $ cmp log.out style.out || diff -u log.out style.out
357 357 $ hg log -T phases > phases.out
358 358 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
359 359 +phase: draft
360 360 +phase: draft
361 361 +phase: draft
362 362 +phase: draft
363 363 +phase: draft
364 364 +phase: draft
365 365 +phase: draft
366 366 +phase: draft
367 367 +phase: draft
368 368 +phase: draft
369 369
370 370 $ hg log -v > log.out
371 371 $ hg log -v --style default > style.out
372 372 $ cmp log.out style.out || diff -u log.out style.out
373 373 $ hg log -v -T phases > phases.out
374 374 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
375 375 +phase: draft
376 376 +phase: draft
377 377 +phase: draft
378 378 +phase: draft
379 379 +phase: draft
380 380 +phase: draft
381 381 +phase: draft
382 382 +phase: draft
383 383 +phase: draft
384 384 +phase: draft
385 385
386 386 $ hg log -q > log.out
387 387 $ hg log -q --style default > style.out
388 388 $ cmp log.out style.out || diff -u log.out style.out
389 389 $ hg log -q -T phases > phases.out
390 390 $ cmp log.out phases.out || diff -u log.out phases.out
391 391
392 392 $ hg log --debug > log.out
393 393 $ hg log --debug --style default > style.out
394 394 $ cmp log.out style.out || diff -u log.out style.out
395 395 $ hg log --debug -T phases > phases.out
396 396 $ cmp log.out phases.out || diff -u log.out phases.out
397 397
398 398 Default style of working-directory revision should also be the same (but
399 399 date may change while running tests):
400 400
401 401 $ hg log -r 'wdir()' | sed 's|^date:.*|date:|' > log.out
402 402 $ hg log -r 'wdir()' --style default | sed 's|^date:.*|date:|' > style.out
403 403 $ cmp log.out style.out || diff -u log.out style.out
404 404
405 405 $ hg log -r 'wdir()' -v | sed 's|^date:.*|date:|' > log.out
406 406 $ hg log -r 'wdir()' -v --style default | sed 's|^date:.*|date:|' > style.out
407 407 $ cmp log.out style.out || diff -u log.out style.out
408 408
409 409 $ hg log -r 'wdir()' -q > log.out
410 410 $ hg log -r 'wdir()' -q --style default > style.out
411 411 $ cmp log.out style.out || diff -u log.out style.out
412 412
413 413 $ hg log -r 'wdir()' --debug | sed 's|^date:.*|date:|' > log.out
414 414 $ hg log -r 'wdir()' --debug --style default \
415 415 > | sed 's|^date:.*|date:|' > style.out
416 416 $ cmp log.out style.out || diff -u log.out style.out
417 417
418 418 Default style should also preserve color information (issue2866):
419 419
420 420 $ cp $HGRCPATH $HGRCPATH-bak
421 421 $ cat <<EOF >> $HGRCPATH
422 422 > [extensions]
423 423 > color=
424 424 > EOF
425 425
426 426 $ hg --color=debug log > log.out
427 427 $ hg --color=debug log --style default > style.out
428 428 $ cmp log.out style.out || diff -u log.out style.out
429 429 $ hg --color=debug log -T phases > phases.out
430 430 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
431 431 +[log.phase|phase: draft]
432 432 +[log.phase|phase: draft]
433 433 +[log.phase|phase: draft]
434 434 +[log.phase|phase: draft]
435 435 +[log.phase|phase: draft]
436 436 +[log.phase|phase: draft]
437 437 +[log.phase|phase: draft]
438 438 +[log.phase|phase: draft]
439 439 +[log.phase|phase: draft]
440 440 +[log.phase|phase: draft]
441 441
442 442 $ hg --color=debug -v log > log.out
443 443 $ hg --color=debug -v log --style default > style.out
444 444 $ cmp log.out style.out || diff -u log.out style.out
445 445 $ hg --color=debug -v log -T phases > phases.out
446 446 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
447 447 +[log.phase|phase: draft]
448 448 +[log.phase|phase: draft]
449 449 +[log.phase|phase: draft]
450 450 +[log.phase|phase: draft]
451 451 +[log.phase|phase: draft]
452 452 +[log.phase|phase: draft]
453 453 +[log.phase|phase: draft]
454 454 +[log.phase|phase: draft]
455 455 +[log.phase|phase: draft]
456 456 +[log.phase|phase: draft]
457 457
458 458 $ hg --color=debug -q log > log.out
459 459 $ hg --color=debug -q log --style default > style.out
460 460 $ cmp log.out style.out || diff -u log.out style.out
461 461 $ hg --color=debug -q log -T phases > phases.out
462 462 $ cmp log.out phases.out || diff -u log.out phases.out
463 463
464 464 $ hg --color=debug --debug log > log.out
465 465 $ hg --color=debug --debug log --style default > style.out
466 466 $ cmp log.out style.out || diff -u log.out style.out
467 467 $ hg --color=debug --debug log -T phases > phases.out
468 468 $ cmp log.out phases.out || diff -u log.out phases.out
469 469
470 470 $ mv $HGRCPATH-bak $HGRCPATH
471 471
472 472 Remove commit with empty commit message, so as to not pollute further
473 473 tests.
474 474
475 475 $ hg --config extensions.strip= strip -q .
476 476
477 477 Revision with no copies (used to print a traceback):
478 478
479 479 $ hg tip -v --template '\n'
480 480
481 481
482 482 Compact style works:
483 483
484 484 $ hg log -Tcompact
485 485 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
486 486 third
487 487
488 488 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
489 489 second
490 490
491 491 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
492 492 merge
493 493
494 494 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
495 495 new head
496 496
497 497 4 bbe44766e73d 1970-01-17 04:53 +0000 person
498 498 new branch
499 499
500 500 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
501 501 no user, no domain
502 502
503 503 2 97054abb4ab8 1970-01-14 21:20 +0000 other
504 504 no person
505 505
506 506 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
507 507 other 1
508 508
509 509 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
510 510 line 1
511 511
512 512
513 513 $ hg log -v --style compact
514 514 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
515 515 third
516 516
517 517 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
518 518 second
519 519
520 520 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
521 521 merge
522 522
523 523 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
524 524 new head
525 525
526 526 4 bbe44766e73d 1970-01-17 04:53 +0000 person
527 527 new branch
528 528
529 529 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
530 530 no user, no domain
531 531
532 532 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
533 533 no person
534 534
535 535 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
536 536 other 1
537 537 other 2
538 538
539 539 other 3
540 540
541 541 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
542 542 line 1
543 543 line 2
544 544
545 545
546 546 $ hg log --debug --style compact
547 547 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
548 548 third
549 549
550 550 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
551 551 second
552 552
553 553 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
554 554 merge
555 555
556 556 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
557 557 new head
558 558
559 559 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
560 560 new branch
561 561
562 562 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
563 563 no user, no domain
564 564
565 565 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
566 566 no person
567 567
568 568 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
569 569 other 1
570 570 other 2
571 571
572 572 other 3
573 573
574 574 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
575 575 line 1
576 576 line 2
577 577
578 578
579 579 Test xml styles:
580 580
581 581 $ hg log --style xml -r 'not all()'
582 582 <?xml version="1.0"?>
583 583 <log>
584 584 </log>
585 585
586 586 $ hg log --style xml
587 587 <?xml version="1.0"?>
588 588 <log>
589 589 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
590 590 <tag>tip</tag>
591 591 <author email="test">test</author>
592 592 <date>2020-01-01T10:01:00+00:00</date>
593 593 <msg xml:space="preserve">third</msg>
594 594 </logentry>
595 595 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
596 596 <parent revision="-1" node="0000000000000000000000000000000000000000" />
597 597 <author email="user@hostname">User Name</author>
598 598 <date>1970-01-12T13:46:40+00:00</date>
599 599 <msg xml:space="preserve">second</msg>
600 600 </logentry>
601 601 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
602 602 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
603 603 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
604 604 <author email="person">person</author>
605 605 <date>1970-01-18T08:40:01+00:00</date>
606 606 <msg xml:space="preserve">merge</msg>
607 607 </logentry>
608 608 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
609 609 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
610 610 <author email="person">person</author>
611 611 <date>1970-01-18T08:40:00+00:00</date>
612 612 <msg xml:space="preserve">new head</msg>
613 613 </logentry>
614 614 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
615 615 <branch>foo</branch>
616 616 <author email="person">person</author>
617 617 <date>1970-01-17T04:53:20+00:00</date>
618 618 <msg xml:space="preserve">new branch</msg>
619 619 </logentry>
620 620 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
621 621 <author email="person">person</author>
622 622 <date>1970-01-16T01:06:40+00:00</date>
623 623 <msg xml:space="preserve">no user, no domain</msg>
624 624 </logentry>
625 625 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
626 626 <author email="other@place">other</author>
627 627 <date>1970-01-14T21:20:00+00:00</date>
628 628 <msg xml:space="preserve">no person</msg>
629 629 </logentry>
630 630 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
631 631 <author email="other@place">A. N. Other</author>
632 632 <date>1970-01-13T17:33:20+00:00</date>
633 633 <msg xml:space="preserve">other 1
634 634 other 2
635 635
636 636 other 3</msg>
637 637 </logentry>
638 638 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
639 639 <author email="user@hostname">User Name</author>
640 640 <date>1970-01-12T13:46:40+00:00</date>
641 641 <msg xml:space="preserve">line 1
642 642 line 2</msg>
643 643 </logentry>
644 644 </log>
645 645
646 646 $ hg log -v --style xml
647 647 <?xml version="1.0"?>
648 648 <log>
649 649 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
650 650 <tag>tip</tag>
651 651 <author email="test">test</author>
652 652 <date>2020-01-01T10:01:00+00:00</date>
653 653 <msg xml:space="preserve">third</msg>
654 654 <paths>
655 655 <path action="A">fourth</path>
656 656 <path action="A">third</path>
657 657 <path action="R">second</path>
658 658 </paths>
659 659 <copies>
660 660 <copy source="second">fourth</copy>
661 661 </copies>
662 662 </logentry>
663 663 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
664 664 <parent revision="-1" node="0000000000000000000000000000000000000000" />
665 665 <author email="user@hostname">User Name</author>
666 666 <date>1970-01-12T13:46:40+00:00</date>
667 667 <msg xml:space="preserve">second</msg>
668 668 <paths>
669 669 <path action="A">second</path>
670 670 </paths>
671 671 </logentry>
672 672 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
673 673 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
674 674 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
675 675 <author email="person">person</author>
676 676 <date>1970-01-18T08:40:01+00:00</date>
677 677 <msg xml:space="preserve">merge</msg>
678 678 <paths>
679 679 </paths>
680 680 </logentry>
681 681 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
682 682 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
683 683 <author email="person">person</author>
684 684 <date>1970-01-18T08:40:00+00:00</date>
685 685 <msg xml:space="preserve">new head</msg>
686 686 <paths>
687 687 <path action="A">d</path>
688 688 </paths>
689 689 </logentry>
690 690 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
691 691 <branch>foo</branch>
692 692 <author email="person">person</author>
693 693 <date>1970-01-17T04:53:20+00:00</date>
694 694 <msg xml:space="preserve">new branch</msg>
695 695 <paths>
696 696 </paths>
697 697 </logentry>
698 698 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
699 699 <author email="person">person</author>
700 700 <date>1970-01-16T01:06:40+00:00</date>
701 701 <msg xml:space="preserve">no user, no domain</msg>
702 702 <paths>
703 703 <path action="M">c</path>
704 704 </paths>
705 705 </logentry>
706 706 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
707 707 <author email="other@place">other</author>
708 708 <date>1970-01-14T21:20:00+00:00</date>
709 709 <msg xml:space="preserve">no person</msg>
710 710 <paths>
711 711 <path action="A">c</path>
712 712 </paths>
713 713 </logentry>
714 714 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
715 715 <author email="other@place">A. N. Other</author>
716 716 <date>1970-01-13T17:33:20+00:00</date>
717 717 <msg xml:space="preserve">other 1
718 718 other 2
719 719
720 720 other 3</msg>
721 721 <paths>
722 722 <path action="A">b</path>
723 723 </paths>
724 724 </logentry>
725 725 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
726 726 <author email="user@hostname">User Name</author>
727 727 <date>1970-01-12T13:46:40+00:00</date>
728 728 <msg xml:space="preserve">line 1
729 729 line 2</msg>
730 730 <paths>
731 731 <path action="A">a</path>
732 732 </paths>
733 733 </logentry>
734 734 </log>
735 735
736 736 $ hg log --debug --style xml
737 737 <?xml version="1.0"?>
738 738 <log>
739 739 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
740 740 <tag>tip</tag>
741 741 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
742 742 <parent revision="-1" node="0000000000000000000000000000000000000000" />
743 743 <author email="test">test</author>
744 744 <date>2020-01-01T10:01:00+00:00</date>
745 745 <msg xml:space="preserve">third</msg>
746 746 <paths>
747 747 <path action="A">fourth</path>
748 748 <path action="A">third</path>
749 749 <path action="R">second</path>
750 750 </paths>
751 751 <copies>
752 752 <copy source="second">fourth</copy>
753 753 </copies>
754 754 <extra key="branch">default</extra>
755 755 </logentry>
756 756 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
757 757 <parent revision="-1" node="0000000000000000000000000000000000000000" />
758 758 <parent revision="-1" node="0000000000000000000000000000000000000000" />
759 759 <author email="user@hostname">User Name</author>
760 760 <date>1970-01-12T13:46:40+00:00</date>
761 761 <msg xml:space="preserve">second</msg>
762 762 <paths>
763 763 <path action="A">second</path>
764 764 </paths>
765 765 <extra key="branch">default</extra>
766 766 </logentry>
767 767 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
768 768 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
769 769 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
770 770 <author email="person">person</author>
771 771 <date>1970-01-18T08:40:01+00:00</date>
772 772 <msg xml:space="preserve">merge</msg>
773 773 <paths>
774 774 </paths>
775 775 <extra key="branch">default</extra>
776 776 </logentry>
777 777 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
778 778 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
779 779 <parent revision="-1" node="0000000000000000000000000000000000000000" />
780 780 <author email="person">person</author>
781 781 <date>1970-01-18T08:40:00+00:00</date>
782 782 <msg xml:space="preserve">new head</msg>
783 783 <paths>
784 784 <path action="A">d</path>
785 785 </paths>
786 786 <extra key="branch">default</extra>
787 787 </logentry>
788 788 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
789 789 <branch>foo</branch>
790 790 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
791 791 <parent revision="-1" node="0000000000000000000000000000000000000000" />
792 792 <author email="person">person</author>
793 793 <date>1970-01-17T04:53:20+00:00</date>
794 794 <msg xml:space="preserve">new branch</msg>
795 795 <paths>
796 796 </paths>
797 797 <extra key="branch">foo</extra>
798 798 </logentry>
799 799 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
800 800 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
801 801 <parent revision="-1" node="0000000000000000000000000000000000000000" />
802 802 <author email="person">person</author>
803 803 <date>1970-01-16T01:06:40+00:00</date>
804 804 <msg xml:space="preserve">no user, no domain</msg>
805 805 <paths>
806 806 <path action="M">c</path>
807 807 </paths>
808 808 <extra key="branch">default</extra>
809 809 </logentry>
810 810 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
811 811 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
812 812 <parent revision="-1" node="0000000000000000000000000000000000000000" />
813 813 <author email="other@place">other</author>
814 814 <date>1970-01-14T21:20:00+00:00</date>
815 815 <msg xml:space="preserve">no person</msg>
816 816 <paths>
817 817 <path action="A">c</path>
818 818 </paths>
819 819 <extra key="branch">default</extra>
820 820 </logentry>
821 821 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
822 822 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
823 823 <parent revision="-1" node="0000000000000000000000000000000000000000" />
824 824 <author email="other@place">A. N. Other</author>
825 825 <date>1970-01-13T17:33:20+00:00</date>
826 826 <msg xml:space="preserve">other 1
827 827 other 2
828 828
829 829 other 3</msg>
830 830 <paths>
831 831 <path action="A">b</path>
832 832 </paths>
833 833 <extra key="branch">default</extra>
834 834 </logentry>
835 835 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
836 836 <parent revision="-1" node="0000000000000000000000000000000000000000" />
837 837 <parent revision="-1" node="0000000000000000000000000000000000000000" />
838 838 <author email="user@hostname">User Name</author>
839 839 <date>1970-01-12T13:46:40+00:00</date>
840 840 <msg xml:space="preserve">line 1
841 841 line 2</msg>
842 842 <paths>
843 843 <path action="A">a</path>
844 844 </paths>
845 845 <extra key="branch">default</extra>
846 846 </logentry>
847 847 </log>
848 848
849 849
850 850 Test JSON style:
851 851
852 852 $ hg log -k nosuch -Tjson
853 853 []
854 854
855 855 $ hg log -qr . -Tjson
856 856 [
857 857 {
858 858 "rev": 8,
859 859 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
860 860 }
861 861 ]
862 862
863 863 $ hg log -vpr . -Tjson --stat
864 864 [
865 865 {
866 866 "rev": 8,
867 867 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
868 868 "branch": "default",
869 869 "phase": "draft",
870 870 "user": "test",
871 871 "date": [1577872860, 0],
872 872 "desc": "third",
873 873 "bookmarks": [],
874 874 "tags": ["tip"],
875 875 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
876 876 "files": ["fourth", "second", "third"],
877 877 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
878 878 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"
879 879 }
880 880 ]
881 881
882 882 honor --git but not format-breaking diffopts
883 883 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
884 884 [
885 885 {
886 886 "rev": 8,
887 887 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
888 888 "branch": "default",
889 889 "phase": "draft",
890 890 "user": "test",
891 891 "date": [1577872860, 0],
892 892 "desc": "third",
893 893 "bookmarks": [],
894 894 "tags": ["tip"],
895 895 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
896 896 "files": ["fourth", "second", "third"],
897 897 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n"
898 898 }
899 899 ]
900 900
901 901 $ hg log -T json
902 902 [
903 903 {
904 904 "rev": 8,
905 905 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
906 906 "branch": "default",
907 907 "phase": "draft",
908 908 "user": "test",
909 909 "date": [1577872860, 0],
910 910 "desc": "third",
911 911 "bookmarks": [],
912 912 "tags": ["tip"],
913 913 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
914 914 },
915 915 {
916 916 "rev": 7,
917 917 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
918 918 "branch": "default",
919 919 "phase": "draft",
920 920 "user": "User Name <user@hostname>",
921 921 "date": [1000000, 0],
922 922 "desc": "second",
923 923 "bookmarks": [],
924 924 "tags": [],
925 925 "parents": ["0000000000000000000000000000000000000000"]
926 926 },
927 927 {
928 928 "rev": 6,
929 929 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
930 930 "branch": "default",
931 931 "phase": "draft",
932 932 "user": "person",
933 933 "date": [1500001, 0],
934 934 "desc": "merge",
935 935 "bookmarks": [],
936 936 "tags": [],
937 937 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
938 938 },
939 939 {
940 940 "rev": 5,
941 941 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
942 942 "branch": "default",
943 943 "phase": "draft",
944 944 "user": "person",
945 945 "date": [1500000, 0],
946 946 "desc": "new head",
947 947 "bookmarks": [],
948 948 "tags": [],
949 949 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
950 950 },
951 951 {
952 952 "rev": 4,
953 953 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
954 954 "branch": "foo",
955 955 "phase": "draft",
956 956 "user": "person",
957 957 "date": [1400000, 0],
958 958 "desc": "new branch",
959 959 "bookmarks": [],
960 960 "tags": [],
961 961 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
962 962 },
963 963 {
964 964 "rev": 3,
965 965 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
966 966 "branch": "default",
967 967 "phase": "draft",
968 968 "user": "person",
969 969 "date": [1300000, 0],
970 970 "desc": "no user, no domain",
971 971 "bookmarks": [],
972 972 "tags": [],
973 973 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
974 974 },
975 975 {
976 976 "rev": 2,
977 977 "node": "97054abb4ab824450e9164180baf491ae0078465",
978 978 "branch": "default",
979 979 "phase": "draft",
980 980 "user": "other@place",
981 981 "date": [1200000, 0],
982 982 "desc": "no person",
983 983 "bookmarks": [],
984 984 "tags": [],
985 985 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
986 986 },
987 987 {
988 988 "rev": 1,
989 989 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
990 990 "branch": "default",
991 991 "phase": "draft",
992 992 "user": "A. N. Other <other@place>",
993 993 "date": [1100000, 0],
994 994 "desc": "other 1\nother 2\n\nother 3",
995 995 "bookmarks": [],
996 996 "tags": [],
997 997 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
998 998 },
999 999 {
1000 1000 "rev": 0,
1001 1001 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1002 1002 "branch": "default",
1003 1003 "phase": "draft",
1004 1004 "user": "User Name <user@hostname>",
1005 1005 "date": [1000000, 0],
1006 1006 "desc": "line 1\nline 2",
1007 1007 "bookmarks": [],
1008 1008 "tags": [],
1009 1009 "parents": ["0000000000000000000000000000000000000000"]
1010 1010 }
1011 1011 ]
1012 1012
1013 1013 $ hg heads -v -Tjson
1014 1014 [
1015 1015 {
1016 1016 "rev": 8,
1017 1017 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
1018 1018 "branch": "default",
1019 1019 "phase": "draft",
1020 1020 "user": "test",
1021 1021 "date": [1577872860, 0],
1022 1022 "desc": "third",
1023 1023 "bookmarks": [],
1024 1024 "tags": ["tip"],
1025 1025 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
1026 1026 "files": ["fourth", "second", "third"]
1027 1027 },
1028 1028 {
1029 1029 "rev": 6,
1030 1030 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1031 1031 "branch": "default",
1032 1032 "phase": "draft",
1033 1033 "user": "person",
1034 1034 "date": [1500001, 0],
1035 1035 "desc": "merge",
1036 1036 "bookmarks": [],
1037 1037 "tags": [],
1038 1038 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1039 1039 "files": []
1040 1040 },
1041 1041 {
1042 1042 "rev": 4,
1043 1043 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1044 1044 "branch": "foo",
1045 1045 "phase": "draft",
1046 1046 "user": "person",
1047 1047 "date": [1400000, 0],
1048 1048 "desc": "new branch",
1049 1049 "bookmarks": [],
1050 1050 "tags": [],
1051 1051 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1052 1052 "files": []
1053 1053 }
1054 1054 ]
1055 1055
1056 1056 $ hg log --debug -Tjson
1057 1057 [
1058 1058 {
1059 1059 "rev": 8,
1060 1060 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
1061 1061 "branch": "default",
1062 1062 "phase": "draft",
1063 1063 "user": "test",
1064 1064 "date": [1577872860, 0],
1065 1065 "desc": "third",
1066 1066 "bookmarks": [],
1067 1067 "tags": ["tip"],
1068 1068 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
1069 1069 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
1070 1070 "extra": {"branch": "default"},
1071 1071 "modified": [],
1072 1072 "added": ["fourth", "third"],
1073 1073 "removed": ["second"]
1074 1074 },
1075 1075 {
1076 1076 "rev": 7,
1077 1077 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
1078 1078 "branch": "default",
1079 1079 "phase": "draft",
1080 1080 "user": "User Name <user@hostname>",
1081 1081 "date": [1000000, 0],
1082 1082 "desc": "second",
1083 1083 "bookmarks": [],
1084 1084 "tags": [],
1085 1085 "parents": ["0000000000000000000000000000000000000000"],
1086 1086 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
1087 1087 "extra": {"branch": "default"},
1088 1088 "modified": [],
1089 1089 "added": ["second"],
1090 1090 "removed": []
1091 1091 },
1092 1092 {
1093 1093 "rev": 6,
1094 1094 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1095 1095 "branch": "default",
1096 1096 "phase": "draft",
1097 1097 "user": "person",
1098 1098 "date": [1500001, 0],
1099 1099 "desc": "merge",
1100 1100 "bookmarks": [],
1101 1101 "tags": [],
1102 1102 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1103 1103 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1104 1104 "extra": {"branch": "default"},
1105 1105 "modified": [],
1106 1106 "added": [],
1107 1107 "removed": []
1108 1108 },
1109 1109 {
1110 1110 "rev": 5,
1111 1111 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
1112 1112 "branch": "default",
1113 1113 "phase": "draft",
1114 1114 "user": "person",
1115 1115 "date": [1500000, 0],
1116 1116 "desc": "new head",
1117 1117 "bookmarks": [],
1118 1118 "tags": [],
1119 1119 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1120 1120 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1121 1121 "extra": {"branch": "default"},
1122 1122 "modified": [],
1123 1123 "added": ["d"],
1124 1124 "removed": []
1125 1125 },
1126 1126 {
1127 1127 "rev": 4,
1128 1128 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1129 1129 "branch": "foo",
1130 1130 "phase": "draft",
1131 1131 "user": "person",
1132 1132 "date": [1400000, 0],
1133 1133 "desc": "new branch",
1134 1134 "bookmarks": [],
1135 1135 "tags": [],
1136 1136 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1137 1137 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1138 1138 "extra": {"branch": "foo"},
1139 1139 "modified": [],
1140 1140 "added": [],
1141 1141 "removed": []
1142 1142 },
1143 1143 {
1144 1144 "rev": 3,
1145 1145 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
1146 1146 "branch": "default",
1147 1147 "phase": "draft",
1148 1148 "user": "person",
1149 1149 "date": [1300000, 0],
1150 1150 "desc": "no user, no domain",
1151 1151 "bookmarks": [],
1152 1152 "tags": [],
1153 1153 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
1154 1154 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1155 1155 "extra": {"branch": "default"},
1156 1156 "modified": ["c"],
1157 1157 "added": [],
1158 1158 "removed": []
1159 1159 },
1160 1160 {
1161 1161 "rev": 2,
1162 1162 "node": "97054abb4ab824450e9164180baf491ae0078465",
1163 1163 "branch": "default",
1164 1164 "phase": "draft",
1165 1165 "user": "other@place",
1166 1166 "date": [1200000, 0],
1167 1167 "desc": "no person",
1168 1168 "bookmarks": [],
1169 1169 "tags": [],
1170 1170 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
1171 1171 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
1172 1172 "extra": {"branch": "default"},
1173 1173 "modified": [],
1174 1174 "added": ["c"],
1175 1175 "removed": []
1176 1176 },
1177 1177 {
1178 1178 "rev": 1,
1179 1179 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
1180 1180 "branch": "default",
1181 1181 "phase": "draft",
1182 1182 "user": "A. N. Other <other@place>",
1183 1183 "date": [1100000, 0],
1184 1184 "desc": "other 1\nother 2\n\nother 3",
1185 1185 "bookmarks": [],
1186 1186 "tags": [],
1187 1187 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
1188 1188 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
1189 1189 "extra": {"branch": "default"},
1190 1190 "modified": [],
1191 1191 "added": ["b"],
1192 1192 "removed": []
1193 1193 },
1194 1194 {
1195 1195 "rev": 0,
1196 1196 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1197 1197 "branch": "default",
1198 1198 "phase": "draft",
1199 1199 "user": "User Name <user@hostname>",
1200 1200 "date": [1000000, 0],
1201 1201 "desc": "line 1\nline 2",
1202 1202 "bookmarks": [],
1203 1203 "tags": [],
1204 1204 "parents": ["0000000000000000000000000000000000000000"],
1205 1205 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
1206 1206 "extra": {"branch": "default"},
1207 1207 "modified": [],
1208 1208 "added": ["a"],
1209 1209 "removed": []
1210 1210 }
1211 1211 ]
1212 1212
1213 1213 Error if style not readable:
1214 1214
1215 1215 #if unix-permissions no-root
1216 1216 $ touch q
1217 1217 $ chmod 0 q
1218 1218 $ hg log --style ./q
1219 1219 abort: Permission denied: ./q
1220 1220 [255]
1221 1221 #endif
1222 1222
1223 1223 Error if no style:
1224 1224
1225 1225 $ hg log --style notexist
1226 1226 abort: style 'notexist' not found
1227 1227 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1228 1228 [255]
1229 1229
1230 1230 $ hg log -T list
1231 1231 available styles: bisect, changelog, compact, default, phases, show, status, xml
1232 1232 abort: specify a template
1233 1233 [255]
1234 1234
1235 1235 Error if style missing key:
1236 1236
1237 1237 $ echo 'q = q' > t
1238 1238 $ hg log --style ./t
1239 1239 abort: "changeset" not in template map
1240 1240 [255]
1241 1241
1242 1242 Error if style missing value:
1243 1243
1244 1244 $ echo 'changeset =' > t
1245 1245 $ hg log --style t
1246 1246 hg: parse error at t:1: missing value
1247 1247 [255]
1248 1248
1249 1249 Error if include fails:
1250 1250
1251 1251 $ echo 'changeset = q' >> t
1252 1252 #if unix-permissions no-root
1253 1253 $ hg log --style ./t
1254 1254 abort: template file ./q: Permission denied
1255 1255 [255]
1256 1256 $ rm -f q
1257 1257 #endif
1258 1258
1259 1259 Include works:
1260 1260
1261 1261 $ echo '{rev}' > q
1262 1262 $ hg log --style ./t
1263 1263 8
1264 1264 7
1265 1265 6
1266 1266 5
1267 1267 4
1268 1268 3
1269 1269 2
1270 1270 1
1271 1271 0
1272 1272
1273 1273 Check that recursive reference does not fall into RuntimeError (issue4758):
1274 1274
1275 1275 common mistake:
1276 1276
1277 1277 $ cat << EOF > issue4758
1278 1278 > changeset = '{changeset}\n'
1279 1279 > EOF
1280 1280 $ hg log --style ./issue4758
1281 1281 abort: recursive reference 'changeset' in template
1282 1282 [255]
1283 1283
1284 1284 circular reference:
1285 1285
1286 1286 $ cat << EOF > issue4758
1287 1287 > changeset = '{foo}'
1288 1288 > foo = '{changeset}'
1289 1289 > EOF
1290 1290 $ hg log --style ./issue4758
1291 1291 abort: recursive reference 'foo' in template
1292 1292 [255]
1293 1293
1294 1294 buildmap() -> gettemplate(), where no thunk was made:
1295 1295
1296 1296 $ cat << EOF > issue4758
1297 1297 > changeset = '{files % changeset}\n'
1298 1298 > EOF
1299 1299 $ hg log --style ./issue4758
1300 1300 abort: recursive reference 'changeset' in template
1301 1301 [255]
1302 1302
1303 1303 not a recursion if a keyword of the same name exists:
1304 1304
1305 1305 $ cat << EOF > issue4758
1306 1306 > changeset = '{tags % rev}'
1307 1307 > rev = '{rev} {tag}\n'
1308 1308 > EOF
1309 1309 $ hg log --style ./issue4758 -r tip
1310 1310 8 tip
1311 1311
1312 1312 Check that {phase} works correctly on parents:
1313 1313
1314 1314 $ cat << EOF > parentphase
1315 1315 > changeset_debug = '{rev} ({phase}):{parents}\n'
1316 1316 > parent = ' {rev} ({phase})'
1317 1317 > EOF
1318 1318 $ hg phase -r 5 --public
1319 1319 $ hg phase -r 7 --secret --force
1320 1320 $ hg log --debug -G --style ./parentphase
1321 1321 @ 8 (secret): 7 (secret) -1 (public)
1322 1322 |
1323 1323 o 7 (secret): -1 (public) -1 (public)
1324 1324
1325 1325 o 6 (draft): 5 (public) 4 (draft)
1326 1326 |\
1327 1327 | o 5 (public): 3 (public) -1 (public)
1328 1328 | |
1329 1329 o | 4 (draft): 3 (public) -1 (public)
1330 1330 |/
1331 1331 o 3 (public): 2 (public) -1 (public)
1332 1332 |
1333 1333 o 2 (public): 1 (public) -1 (public)
1334 1334 |
1335 1335 o 1 (public): 0 (public) -1 (public)
1336 1336 |
1337 1337 o 0 (public): -1 (public) -1 (public)
1338 1338
1339 1339
1340 1340 Missing non-standard names give no error (backward compatibility):
1341 1341
1342 1342 $ echo "changeset = '{c}'" > t
1343 1343 $ hg log --style ./t
1344 1344
1345 1345 Defining non-standard name works:
1346 1346
1347 1347 $ cat <<EOF > t
1348 1348 > changeset = '{c}'
1349 1349 > c = q
1350 1350 > EOF
1351 1351 $ hg log --style ./t
1352 1352 8
1353 1353 7
1354 1354 6
1355 1355 5
1356 1356 4
1357 1357 3
1358 1358 2
1359 1359 1
1360 1360 0
1361 1361
1362 1362 ui.style works:
1363 1363
1364 1364 $ echo '[ui]' > .hg/hgrc
1365 1365 $ echo 'style = t' >> .hg/hgrc
1366 1366 $ hg log
1367 1367 8
1368 1368 7
1369 1369 6
1370 1370 5
1371 1371 4
1372 1372 3
1373 1373 2
1374 1374 1
1375 1375 0
1376 1376
1377 1377
1378 1378 Issue338:
1379 1379
1380 1380 $ hg log --style=changelog > changelog
1381 1381
1382 1382 $ cat changelog
1383 1383 2020-01-01 test <test>
1384 1384
1385 1385 * fourth, second, third:
1386 1386 third
1387 1387 [95c24699272e] [tip]
1388 1388
1389 1389 1970-01-12 User Name <user@hostname>
1390 1390
1391 1391 * second:
1392 1392 second
1393 1393 [29114dbae42b]
1394 1394
1395 1395 1970-01-18 person <person>
1396 1396
1397 1397 * merge
1398 1398 [d41e714fe50d]
1399 1399
1400 1400 * d:
1401 1401 new head
1402 1402 [13207e5a10d9]
1403 1403
1404 1404 1970-01-17 person <person>
1405 1405
1406 1406 * new branch
1407 1407 [bbe44766e73d] <foo>
1408 1408
1409 1409 1970-01-16 person <person>
1410 1410
1411 1411 * c:
1412 1412 no user, no domain
1413 1413 [10e46f2dcbf4]
1414 1414
1415 1415 1970-01-14 other <other@place>
1416 1416
1417 1417 * c:
1418 1418 no person
1419 1419 [97054abb4ab8]
1420 1420
1421 1421 1970-01-13 A. N. Other <other@place>
1422 1422
1423 1423 * b:
1424 1424 other 1 other 2
1425 1425
1426 1426 other 3
1427 1427 [b608e9d1a3f0]
1428 1428
1429 1429 1970-01-12 User Name <user@hostname>
1430 1430
1431 1431 * a:
1432 1432 line 1 line 2
1433 1433 [1e4e1b8f71e0]
1434 1434
1435 1435
1436 1436 Issue2130: xml output for 'hg heads' is malformed
1437 1437
1438 1438 $ hg heads --style changelog
1439 1439 2020-01-01 test <test>
1440 1440
1441 1441 * fourth, second, third:
1442 1442 third
1443 1443 [95c24699272e] [tip]
1444 1444
1445 1445 1970-01-18 person <person>
1446 1446
1447 1447 * merge
1448 1448 [d41e714fe50d]
1449 1449
1450 1450 1970-01-17 person <person>
1451 1451
1452 1452 * new branch
1453 1453 [bbe44766e73d] <foo>
1454 1454
1455 1455
1456 1456 Keys work:
1457 1457
1458 1458 $ for key in author branch branches date desc file_adds file_dels file_mods \
1459 1459 > file_copies file_copies_switch files \
1460 1460 > manifest node parents rev tags diffstat extras \
1461 1461 > p1rev p2rev p1node p2node; do
1462 1462 > for mode in '' --verbose --debug; do
1463 1463 > hg log $mode --template "$key$mode: {$key}\n"
1464 1464 > done
1465 1465 > done
1466 1466 author: test
1467 1467 author: User Name <user@hostname>
1468 1468 author: person
1469 1469 author: person
1470 1470 author: person
1471 1471 author: person
1472 1472 author: other@place
1473 1473 author: A. N. Other <other@place>
1474 1474 author: User Name <user@hostname>
1475 1475 author--verbose: test
1476 1476 author--verbose: User Name <user@hostname>
1477 1477 author--verbose: person
1478 1478 author--verbose: person
1479 1479 author--verbose: person
1480 1480 author--verbose: person
1481 1481 author--verbose: other@place
1482 1482 author--verbose: A. N. Other <other@place>
1483 1483 author--verbose: User Name <user@hostname>
1484 1484 author--debug: test
1485 1485 author--debug: User Name <user@hostname>
1486 1486 author--debug: person
1487 1487 author--debug: person
1488 1488 author--debug: person
1489 1489 author--debug: person
1490 1490 author--debug: other@place
1491 1491 author--debug: A. N. Other <other@place>
1492 1492 author--debug: User Name <user@hostname>
1493 1493 branch: default
1494 1494 branch: default
1495 1495 branch: default
1496 1496 branch: default
1497 1497 branch: foo
1498 1498 branch: default
1499 1499 branch: default
1500 1500 branch: default
1501 1501 branch: default
1502 1502 branch--verbose: default
1503 1503 branch--verbose: default
1504 1504 branch--verbose: default
1505 1505 branch--verbose: default
1506 1506 branch--verbose: foo
1507 1507 branch--verbose: default
1508 1508 branch--verbose: default
1509 1509 branch--verbose: default
1510 1510 branch--verbose: default
1511 1511 branch--debug: default
1512 1512 branch--debug: default
1513 1513 branch--debug: default
1514 1514 branch--debug: default
1515 1515 branch--debug: foo
1516 1516 branch--debug: default
1517 1517 branch--debug: default
1518 1518 branch--debug: default
1519 1519 branch--debug: default
1520 1520 branches:
1521 1521 branches:
1522 1522 branches:
1523 1523 branches:
1524 1524 branches: foo
1525 1525 branches:
1526 1526 branches:
1527 1527 branches:
1528 1528 branches:
1529 1529 branches--verbose:
1530 1530 branches--verbose:
1531 1531 branches--verbose:
1532 1532 branches--verbose:
1533 1533 branches--verbose: foo
1534 1534 branches--verbose:
1535 1535 branches--verbose:
1536 1536 branches--verbose:
1537 1537 branches--verbose:
1538 1538 branches--debug:
1539 1539 branches--debug:
1540 1540 branches--debug:
1541 1541 branches--debug:
1542 1542 branches--debug: foo
1543 1543 branches--debug:
1544 1544 branches--debug:
1545 1545 branches--debug:
1546 1546 branches--debug:
1547 1547 date: 1577872860.00
1548 1548 date: 1000000.00
1549 1549 date: 1500001.00
1550 1550 date: 1500000.00
1551 1551 date: 1400000.00
1552 1552 date: 1300000.00
1553 1553 date: 1200000.00
1554 1554 date: 1100000.00
1555 1555 date: 1000000.00
1556 1556 date--verbose: 1577872860.00
1557 1557 date--verbose: 1000000.00
1558 1558 date--verbose: 1500001.00
1559 1559 date--verbose: 1500000.00
1560 1560 date--verbose: 1400000.00
1561 1561 date--verbose: 1300000.00
1562 1562 date--verbose: 1200000.00
1563 1563 date--verbose: 1100000.00
1564 1564 date--verbose: 1000000.00
1565 1565 date--debug: 1577872860.00
1566 1566 date--debug: 1000000.00
1567 1567 date--debug: 1500001.00
1568 1568 date--debug: 1500000.00
1569 1569 date--debug: 1400000.00
1570 1570 date--debug: 1300000.00
1571 1571 date--debug: 1200000.00
1572 1572 date--debug: 1100000.00
1573 1573 date--debug: 1000000.00
1574 1574 desc: third
1575 1575 desc: second
1576 1576 desc: merge
1577 1577 desc: new head
1578 1578 desc: new branch
1579 1579 desc: no user, no domain
1580 1580 desc: no person
1581 1581 desc: other 1
1582 1582 other 2
1583 1583
1584 1584 other 3
1585 1585 desc: line 1
1586 1586 line 2
1587 1587 desc--verbose: third
1588 1588 desc--verbose: second
1589 1589 desc--verbose: merge
1590 1590 desc--verbose: new head
1591 1591 desc--verbose: new branch
1592 1592 desc--verbose: no user, no domain
1593 1593 desc--verbose: no person
1594 1594 desc--verbose: other 1
1595 1595 other 2
1596 1596
1597 1597 other 3
1598 1598 desc--verbose: line 1
1599 1599 line 2
1600 1600 desc--debug: third
1601 1601 desc--debug: second
1602 1602 desc--debug: merge
1603 1603 desc--debug: new head
1604 1604 desc--debug: new branch
1605 1605 desc--debug: no user, no domain
1606 1606 desc--debug: no person
1607 1607 desc--debug: other 1
1608 1608 other 2
1609 1609
1610 1610 other 3
1611 1611 desc--debug: line 1
1612 1612 line 2
1613 1613 file_adds: fourth third
1614 1614 file_adds: second
1615 1615 file_adds:
1616 1616 file_adds: d
1617 1617 file_adds:
1618 1618 file_adds:
1619 1619 file_adds: c
1620 1620 file_adds: b
1621 1621 file_adds: a
1622 1622 file_adds--verbose: fourth third
1623 1623 file_adds--verbose: second
1624 1624 file_adds--verbose:
1625 1625 file_adds--verbose: d
1626 1626 file_adds--verbose:
1627 1627 file_adds--verbose:
1628 1628 file_adds--verbose: c
1629 1629 file_adds--verbose: b
1630 1630 file_adds--verbose: a
1631 1631 file_adds--debug: fourth third
1632 1632 file_adds--debug: second
1633 1633 file_adds--debug:
1634 1634 file_adds--debug: d
1635 1635 file_adds--debug:
1636 1636 file_adds--debug:
1637 1637 file_adds--debug: c
1638 1638 file_adds--debug: b
1639 1639 file_adds--debug: a
1640 1640 file_dels: second
1641 1641 file_dels:
1642 1642 file_dels:
1643 1643 file_dels:
1644 1644 file_dels:
1645 1645 file_dels:
1646 1646 file_dels:
1647 1647 file_dels:
1648 1648 file_dels:
1649 1649 file_dels--verbose: second
1650 1650 file_dels--verbose:
1651 1651 file_dels--verbose:
1652 1652 file_dels--verbose:
1653 1653 file_dels--verbose:
1654 1654 file_dels--verbose:
1655 1655 file_dels--verbose:
1656 1656 file_dels--verbose:
1657 1657 file_dels--verbose:
1658 1658 file_dels--debug: second
1659 1659 file_dels--debug:
1660 1660 file_dels--debug:
1661 1661 file_dels--debug:
1662 1662 file_dels--debug:
1663 1663 file_dels--debug:
1664 1664 file_dels--debug:
1665 1665 file_dels--debug:
1666 1666 file_dels--debug:
1667 1667 file_mods:
1668 1668 file_mods:
1669 1669 file_mods:
1670 1670 file_mods:
1671 1671 file_mods:
1672 1672 file_mods: c
1673 1673 file_mods:
1674 1674 file_mods:
1675 1675 file_mods:
1676 1676 file_mods--verbose:
1677 1677 file_mods--verbose:
1678 1678 file_mods--verbose:
1679 1679 file_mods--verbose:
1680 1680 file_mods--verbose:
1681 1681 file_mods--verbose: c
1682 1682 file_mods--verbose:
1683 1683 file_mods--verbose:
1684 1684 file_mods--verbose:
1685 1685 file_mods--debug:
1686 1686 file_mods--debug:
1687 1687 file_mods--debug:
1688 1688 file_mods--debug:
1689 1689 file_mods--debug:
1690 1690 file_mods--debug: c
1691 1691 file_mods--debug:
1692 1692 file_mods--debug:
1693 1693 file_mods--debug:
1694 1694 file_copies: fourth (second)
1695 1695 file_copies:
1696 1696 file_copies:
1697 1697 file_copies:
1698 1698 file_copies:
1699 1699 file_copies:
1700 1700 file_copies:
1701 1701 file_copies:
1702 1702 file_copies:
1703 1703 file_copies--verbose: fourth (second)
1704 1704 file_copies--verbose:
1705 1705 file_copies--verbose:
1706 1706 file_copies--verbose:
1707 1707 file_copies--verbose:
1708 1708 file_copies--verbose:
1709 1709 file_copies--verbose:
1710 1710 file_copies--verbose:
1711 1711 file_copies--verbose:
1712 1712 file_copies--debug: fourth (second)
1713 1713 file_copies--debug:
1714 1714 file_copies--debug:
1715 1715 file_copies--debug:
1716 1716 file_copies--debug:
1717 1717 file_copies--debug:
1718 1718 file_copies--debug:
1719 1719 file_copies--debug:
1720 1720 file_copies--debug:
1721 1721 file_copies_switch:
1722 1722 file_copies_switch:
1723 1723 file_copies_switch:
1724 1724 file_copies_switch:
1725 1725 file_copies_switch:
1726 1726 file_copies_switch:
1727 1727 file_copies_switch:
1728 1728 file_copies_switch:
1729 1729 file_copies_switch:
1730 1730 file_copies_switch--verbose:
1731 1731 file_copies_switch--verbose:
1732 1732 file_copies_switch--verbose:
1733 1733 file_copies_switch--verbose:
1734 1734 file_copies_switch--verbose:
1735 1735 file_copies_switch--verbose:
1736 1736 file_copies_switch--verbose:
1737 1737 file_copies_switch--verbose:
1738 1738 file_copies_switch--verbose:
1739 1739 file_copies_switch--debug:
1740 1740 file_copies_switch--debug:
1741 1741 file_copies_switch--debug:
1742 1742 file_copies_switch--debug:
1743 1743 file_copies_switch--debug:
1744 1744 file_copies_switch--debug:
1745 1745 file_copies_switch--debug:
1746 1746 file_copies_switch--debug:
1747 1747 file_copies_switch--debug:
1748 1748 files: fourth second third
1749 1749 files: second
1750 1750 files:
1751 1751 files: d
1752 1752 files:
1753 1753 files: c
1754 1754 files: c
1755 1755 files: b
1756 1756 files: a
1757 1757 files--verbose: fourth second third
1758 1758 files--verbose: second
1759 1759 files--verbose:
1760 1760 files--verbose: d
1761 1761 files--verbose:
1762 1762 files--verbose: c
1763 1763 files--verbose: c
1764 1764 files--verbose: b
1765 1765 files--verbose: a
1766 1766 files--debug: fourth second third
1767 1767 files--debug: second
1768 1768 files--debug:
1769 1769 files--debug: d
1770 1770 files--debug:
1771 1771 files--debug: c
1772 1772 files--debug: c
1773 1773 files--debug: b
1774 1774 files--debug: a
1775 1775 manifest: 6:94961b75a2da
1776 1776 manifest: 5:f2dbc354b94e
1777 1777 manifest: 4:4dc3def4f9b4
1778 1778 manifest: 4:4dc3def4f9b4
1779 1779 manifest: 3:cb5a1327723b
1780 1780 manifest: 3:cb5a1327723b
1781 1781 manifest: 2:6e0e82995c35
1782 1782 manifest: 1:4e8d705b1e53
1783 1783 manifest: 0:a0c8bcbbb45c
1784 1784 manifest--verbose: 6:94961b75a2da
1785 1785 manifest--verbose: 5:f2dbc354b94e
1786 1786 manifest--verbose: 4:4dc3def4f9b4
1787 1787 manifest--verbose: 4:4dc3def4f9b4
1788 1788 manifest--verbose: 3:cb5a1327723b
1789 1789 manifest--verbose: 3:cb5a1327723b
1790 1790 manifest--verbose: 2:6e0e82995c35
1791 1791 manifest--verbose: 1:4e8d705b1e53
1792 1792 manifest--verbose: 0:a0c8bcbbb45c
1793 1793 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1794 1794 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1795 1795 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1796 1796 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1797 1797 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1798 1798 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1799 1799 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1800 1800 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1801 1801 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1802 1802 node: 95c24699272ef57d062b8bccc32c878bf841784a
1803 1803 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1804 1804 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1805 1805 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1806 1806 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1807 1807 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1808 1808 node: 97054abb4ab824450e9164180baf491ae0078465
1809 1809 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1810 1810 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1811 1811 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1812 1812 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1813 1813 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1814 1814 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1815 1815 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1816 1816 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1817 1817 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1818 1818 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1819 1819 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1820 1820 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1821 1821 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1822 1822 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1823 1823 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1824 1824 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1825 1825 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1826 1826 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1827 1827 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1828 1828 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1829 1829 parents:
1830 1830 parents: -1:000000000000
1831 1831 parents: 5:13207e5a10d9 4:bbe44766e73d
1832 1832 parents: 3:10e46f2dcbf4
1833 1833 parents:
1834 1834 parents:
1835 1835 parents:
1836 1836 parents:
1837 1837 parents:
1838 1838 parents--verbose:
1839 1839 parents--verbose: -1:000000000000
1840 1840 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1841 1841 parents--verbose: 3:10e46f2dcbf4
1842 1842 parents--verbose:
1843 1843 parents--verbose:
1844 1844 parents--verbose:
1845 1845 parents--verbose:
1846 1846 parents--verbose:
1847 1847 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1848 1848 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1849 1849 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1850 1850 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1851 1851 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1852 1852 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1853 1853 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1854 1854 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1855 1855 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1856 1856 rev: 8
1857 1857 rev: 7
1858 1858 rev: 6
1859 1859 rev: 5
1860 1860 rev: 4
1861 1861 rev: 3
1862 1862 rev: 2
1863 1863 rev: 1
1864 1864 rev: 0
1865 1865 rev--verbose: 8
1866 1866 rev--verbose: 7
1867 1867 rev--verbose: 6
1868 1868 rev--verbose: 5
1869 1869 rev--verbose: 4
1870 1870 rev--verbose: 3
1871 1871 rev--verbose: 2
1872 1872 rev--verbose: 1
1873 1873 rev--verbose: 0
1874 1874 rev--debug: 8
1875 1875 rev--debug: 7
1876 1876 rev--debug: 6
1877 1877 rev--debug: 5
1878 1878 rev--debug: 4
1879 1879 rev--debug: 3
1880 1880 rev--debug: 2
1881 1881 rev--debug: 1
1882 1882 rev--debug: 0
1883 1883 tags: tip
1884 1884 tags:
1885 1885 tags:
1886 1886 tags:
1887 1887 tags:
1888 1888 tags:
1889 1889 tags:
1890 1890 tags:
1891 1891 tags:
1892 1892 tags--verbose: tip
1893 1893 tags--verbose:
1894 1894 tags--verbose:
1895 1895 tags--verbose:
1896 1896 tags--verbose:
1897 1897 tags--verbose:
1898 1898 tags--verbose:
1899 1899 tags--verbose:
1900 1900 tags--verbose:
1901 1901 tags--debug: tip
1902 1902 tags--debug:
1903 1903 tags--debug:
1904 1904 tags--debug:
1905 1905 tags--debug:
1906 1906 tags--debug:
1907 1907 tags--debug:
1908 1908 tags--debug:
1909 1909 tags--debug:
1910 1910 diffstat: 3: +2/-1
1911 1911 diffstat: 1: +1/-0
1912 1912 diffstat: 0: +0/-0
1913 1913 diffstat: 1: +1/-0
1914 1914 diffstat: 0: +0/-0
1915 1915 diffstat: 1: +1/-0
1916 1916 diffstat: 1: +4/-0
1917 1917 diffstat: 1: +2/-0
1918 1918 diffstat: 1: +1/-0
1919 1919 diffstat--verbose: 3: +2/-1
1920 1920 diffstat--verbose: 1: +1/-0
1921 1921 diffstat--verbose: 0: +0/-0
1922 1922 diffstat--verbose: 1: +1/-0
1923 1923 diffstat--verbose: 0: +0/-0
1924 1924 diffstat--verbose: 1: +1/-0
1925 1925 diffstat--verbose: 1: +4/-0
1926 1926 diffstat--verbose: 1: +2/-0
1927 1927 diffstat--verbose: 1: +1/-0
1928 1928 diffstat--debug: 3: +2/-1
1929 1929 diffstat--debug: 1: +1/-0
1930 1930 diffstat--debug: 0: +0/-0
1931 1931 diffstat--debug: 1: +1/-0
1932 1932 diffstat--debug: 0: +0/-0
1933 1933 diffstat--debug: 1: +1/-0
1934 1934 diffstat--debug: 1: +4/-0
1935 1935 diffstat--debug: 1: +2/-0
1936 1936 diffstat--debug: 1: +1/-0
1937 1937 extras: branch=default
1938 1938 extras: branch=default
1939 1939 extras: branch=default
1940 1940 extras: branch=default
1941 1941 extras: branch=foo
1942 1942 extras: branch=default
1943 1943 extras: branch=default
1944 1944 extras: branch=default
1945 1945 extras: branch=default
1946 1946 extras--verbose: branch=default
1947 1947 extras--verbose: branch=default
1948 1948 extras--verbose: branch=default
1949 1949 extras--verbose: branch=default
1950 1950 extras--verbose: branch=foo
1951 1951 extras--verbose: branch=default
1952 1952 extras--verbose: branch=default
1953 1953 extras--verbose: branch=default
1954 1954 extras--verbose: branch=default
1955 1955 extras--debug: branch=default
1956 1956 extras--debug: branch=default
1957 1957 extras--debug: branch=default
1958 1958 extras--debug: branch=default
1959 1959 extras--debug: branch=foo
1960 1960 extras--debug: branch=default
1961 1961 extras--debug: branch=default
1962 1962 extras--debug: branch=default
1963 1963 extras--debug: branch=default
1964 1964 p1rev: 7
1965 1965 p1rev: -1
1966 1966 p1rev: 5
1967 1967 p1rev: 3
1968 1968 p1rev: 3
1969 1969 p1rev: 2
1970 1970 p1rev: 1
1971 1971 p1rev: 0
1972 1972 p1rev: -1
1973 1973 p1rev--verbose: 7
1974 1974 p1rev--verbose: -1
1975 1975 p1rev--verbose: 5
1976 1976 p1rev--verbose: 3
1977 1977 p1rev--verbose: 3
1978 1978 p1rev--verbose: 2
1979 1979 p1rev--verbose: 1
1980 1980 p1rev--verbose: 0
1981 1981 p1rev--verbose: -1
1982 1982 p1rev--debug: 7
1983 1983 p1rev--debug: -1
1984 1984 p1rev--debug: 5
1985 1985 p1rev--debug: 3
1986 1986 p1rev--debug: 3
1987 1987 p1rev--debug: 2
1988 1988 p1rev--debug: 1
1989 1989 p1rev--debug: 0
1990 1990 p1rev--debug: -1
1991 1991 p2rev: -1
1992 1992 p2rev: -1
1993 1993 p2rev: 4
1994 1994 p2rev: -1
1995 1995 p2rev: -1
1996 1996 p2rev: -1
1997 1997 p2rev: -1
1998 1998 p2rev: -1
1999 1999 p2rev: -1
2000 2000 p2rev--verbose: -1
2001 2001 p2rev--verbose: -1
2002 2002 p2rev--verbose: 4
2003 2003 p2rev--verbose: -1
2004 2004 p2rev--verbose: -1
2005 2005 p2rev--verbose: -1
2006 2006 p2rev--verbose: -1
2007 2007 p2rev--verbose: -1
2008 2008 p2rev--verbose: -1
2009 2009 p2rev--debug: -1
2010 2010 p2rev--debug: -1
2011 2011 p2rev--debug: 4
2012 2012 p2rev--debug: -1
2013 2013 p2rev--debug: -1
2014 2014 p2rev--debug: -1
2015 2015 p2rev--debug: -1
2016 2016 p2rev--debug: -1
2017 2017 p2rev--debug: -1
2018 2018 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2019 2019 p1node: 0000000000000000000000000000000000000000
2020 2020 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
2021 2021 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2022 2022 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2023 2023 p1node: 97054abb4ab824450e9164180baf491ae0078465
2024 2024 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2025 2025 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
2026 2026 p1node: 0000000000000000000000000000000000000000
2027 2027 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2028 2028 p1node--verbose: 0000000000000000000000000000000000000000
2029 2029 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
2030 2030 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2031 2031 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2032 2032 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
2033 2033 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2034 2034 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
2035 2035 p1node--verbose: 0000000000000000000000000000000000000000
2036 2036 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2037 2037 p1node--debug: 0000000000000000000000000000000000000000
2038 2038 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
2039 2039 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2040 2040 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2041 2041 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
2042 2042 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2043 2043 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
2044 2044 p1node--debug: 0000000000000000000000000000000000000000
2045 2045 p2node: 0000000000000000000000000000000000000000
2046 2046 p2node: 0000000000000000000000000000000000000000
2047 2047 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2048 2048 p2node: 0000000000000000000000000000000000000000
2049 2049 p2node: 0000000000000000000000000000000000000000
2050 2050 p2node: 0000000000000000000000000000000000000000
2051 2051 p2node: 0000000000000000000000000000000000000000
2052 2052 p2node: 0000000000000000000000000000000000000000
2053 2053 p2node: 0000000000000000000000000000000000000000
2054 2054 p2node--verbose: 0000000000000000000000000000000000000000
2055 2055 p2node--verbose: 0000000000000000000000000000000000000000
2056 2056 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2057 2057 p2node--verbose: 0000000000000000000000000000000000000000
2058 2058 p2node--verbose: 0000000000000000000000000000000000000000
2059 2059 p2node--verbose: 0000000000000000000000000000000000000000
2060 2060 p2node--verbose: 0000000000000000000000000000000000000000
2061 2061 p2node--verbose: 0000000000000000000000000000000000000000
2062 2062 p2node--verbose: 0000000000000000000000000000000000000000
2063 2063 p2node--debug: 0000000000000000000000000000000000000000
2064 2064 p2node--debug: 0000000000000000000000000000000000000000
2065 2065 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2066 2066 p2node--debug: 0000000000000000000000000000000000000000
2067 2067 p2node--debug: 0000000000000000000000000000000000000000
2068 2068 p2node--debug: 0000000000000000000000000000000000000000
2069 2069 p2node--debug: 0000000000000000000000000000000000000000
2070 2070 p2node--debug: 0000000000000000000000000000000000000000
2071 2071 p2node--debug: 0000000000000000000000000000000000000000
2072 2072
2073 2073 Filters work:
2074 2074
2075 2075 $ hg log --template '{author|domain}\n'
2076 2076
2077 2077 hostname
2078 2078
2079 2079
2080 2080
2081 2081
2082 2082 place
2083 2083 place
2084 2084 hostname
2085 2085
2086 2086 $ hg log --template '{author|person}\n'
2087 2087 test
2088 2088 User Name
2089 2089 person
2090 2090 person
2091 2091 person
2092 2092 person
2093 2093 other
2094 2094 A. N. Other
2095 2095 User Name
2096 2096
2097 2097 $ hg log --template '{author|user}\n'
2098 2098 test
2099 2099 user
2100 2100 person
2101 2101 person
2102 2102 person
2103 2103 person
2104 2104 other
2105 2105 other
2106 2106 user
2107 2107
2108 2108 $ hg log --template '{date|date}\n'
2109 2109 Wed Jan 01 10:01:00 2020 +0000
2110 2110 Mon Jan 12 13:46:40 1970 +0000
2111 2111 Sun Jan 18 08:40:01 1970 +0000
2112 2112 Sun Jan 18 08:40:00 1970 +0000
2113 2113 Sat Jan 17 04:53:20 1970 +0000
2114 2114 Fri Jan 16 01:06:40 1970 +0000
2115 2115 Wed Jan 14 21:20:00 1970 +0000
2116 2116 Tue Jan 13 17:33:20 1970 +0000
2117 2117 Mon Jan 12 13:46:40 1970 +0000
2118 2118
2119 2119 $ hg log --template '{date|isodate}\n'
2120 2120 2020-01-01 10:01 +0000
2121 2121 1970-01-12 13:46 +0000
2122 2122 1970-01-18 08:40 +0000
2123 2123 1970-01-18 08:40 +0000
2124 2124 1970-01-17 04:53 +0000
2125 2125 1970-01-16 01:06 +0000
2126 2126 1970-01-14 21:20 +0000
2127 2127 1970-01-13 17:33 +0000
2128 2128 1970-01-12 13:46 +0000
2129 2129
2130 2130 $ hg log --template '{date|isodatesec}\n'
2131 2131 2020-01-01 10:01:00 +0000
2132 2132 1970-01-12 13:46:40 +0000
2133 2133 1970-01-18 08:40:01 +0000
2134 2134 1970-01-18 08:40:00 +0000
2135 2135 1970-01-17 04:53:20 +0000
2136 2136 1970-01-16 01:06:40 +0000
2137 2137 1970-01-14 21:20:00 +0000
2138 2138 1970-01-13 17:33:20 +0000
2139 2139 1970-01-12 13:46:40 +0000
2140 2140
2141 2141 $ hg log --template '{date|rfc822date}\n'
2142 2142 Wed, 01 Jan 2020 10:01:00 +0000
2143 2143 Mon, 12 Jan 1970 13:46:40 +0000
2144 2144 Sun, 18 Jan 1970 08:40:01 +0000
2145 2145 Sun, 18 Jan 1970 08:40:00 +0000
2146 2146 Sat, 17 Jan 1970 04:53:20 +0000
2147 2147 Fri, 16 Jan 1970 01:06:40 +0000
2148 2148 Wed, 14 Jan 1970 21:20:00 +0000
2149 2149 Tue, 13 Jan 1970 17:33:20 +0000
2150 2150 Mon, 12 Jan 1970 13:46:40 +0000
2151 2151
2152 2152 $ hg log --template '{desc|firstline}\n'
2153 2153 third
2154 2154 second
2155 2155 merge
2156 2156 new head
2157 2157 new branch
2158 2158 no user, no domain
2159 2159 no person
2160 2160 other 1
2161 2161 line 1
2162 2162
2163 2163 $ hg log --template '{node|short}\n'
2164 2164 95c24699272e
2165 2165 29114dbae42b
2166 2166 d41e714fe50d
2167 2167 13207e5a10d9
2168 2168 bbe44766e73d
2169 2169 10e46f2dcbf4
2170 2170 97054abb4ab8
2171 2171 b608e9d1a3f0
2172 2172 1e4e1b8f71e0
2173 2173
2174 2174 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
2175 2175 <changeset author="test"/>
2176 2176 <changeset author="User Name &lt;user@hostname&gt;"/>
2177 2177 <changeset author="person"/>
2178 2178 <changeset author="person"/>
2179 2179 <changeset author="person"/>
2180 2180 <changeset author="person"/>
2181 2181 <changeset author="other@place"/>
2182 2182 <changeset author="A. N. Other &lt;other@place&gt;"/>
2183 2183 <changeset author="User Name &lt;user@hostname&gt;"/>
2184 2184
2185 2185 $ hg log --template '{rev}: {children}\n'
2186 2186 8:
2187 2187 7: 8:95c24699272e
2188 2188 6:
2189 2189 5: 6:d41e714fe50d
2190 2190 4: 6:d41e714fe50d
2191 2191 3: 4:bbe44766e73d 5:13207e5a10d9
2192 2192 2: 3:10e46f2dcbf4
2193 2193 1: 2:97054abb4ab8
2194 2194 0: 1:b608e9d1a3f0
2195 2195
2196 2196 Formatnode filter works:
2197 2197
2198 2198 $ hg -q log -r 0 --template '{node|formatnode}\n'
2199 2199 1e4e1b8f71e0
2200 2200
2201 2201 $ hg log -r 0 --template '{node|formatnode}\n'
2202 2202 1e4e1b8f71e0
2203 2203
2204 2204 $ hg -v log -r 0 --template '{node|formatnode}\n'
2205 2205 1e4e1b8f71e0
2206 2206
2207 2207 $ hg --debug log -r 0 --template '{node|formatnode}\n'
2208 2208 1e4e1b8f71e05681d422154f5421e385fec3454f
2209 2209
2210 2210 Age filter:
2211 2211
2212 2212 $ hg init unstable-hash
2213 2213 $ cd unstable-hash
2214 2214 $ hg log --template '{date|age}\n' > /dev/null || exit 1
2215 2215
2216 2216 >>> from __future__ import absolute_import
2217 2217 >>> import datetime
2218 2218 >>> fp = open('a', 'w')
2219 2219 >>> n = datetime.datetime.now() + datetime.timedelta(366 * 7)
2220 2220 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
2221 2221 >>> fp.close()
2222 2222 $ hg add a
2223 2223 $ hg commit -m future -d "`cat a`"
2224 2224
2225 2225 $ hg log -l1 --template '{date|age}\n'
2226 2226 7 years from now
2227 2227
2228 2228 $ cd ..
2229 2229 $ rm -rf unstable-hash
2230 2230
2231 2231 Filename filters:
2232 2232
2233 2233 $ hg debugtemplate '{"foo/bar"|basename}|{"foo/"|basename}|{"foo"|basename}|\n'
2234 2234 bar||foo|
2235 $ hg debugtemplate '{"foo/bar"|dirname}|{"foo/"|dirname}|{"foo"|dirname}|\n'
2236 foo|foo||
2237 $ hg debugtemplate '{"foo/bar"|stripdir}|{"foo/"|stripdir}|{"foo"|stripdir}|\n'
2238 foo|foo|foo|
2235 2239
2236 2240 Add a dummy commit to make up for the instability of the above:
2237 2241
2238 2242 $ echo a > a
2239 2243 $ hg add a
2240 2244 $ hg ci -m future
2241 2245
2242 2246 Count filter:
2243 2247
2244 2248 $ hg log -l1 --template '{node|count} {node|short|count}\n'
2245 2249 40 12
2246 2250
2247 2251 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
2248 2252 0 1 4
2249 2253
2250 2254 $ hg log -G --template '{rev}: children: {children|count}, \
2251 2255 > tags: {tags|count}, file_adds: {file_adds|count}, \
2252 2256 > ancestors: {revset("ancestors(%s)", rev)|count}'
2253 2257 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
2254 2258 |
2255 2259 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
2256 2260 |
2257 2261 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
2258 2262
2259 2263 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
2260 2264 |\
2261 2265 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
2262 2266 | |
2263 2267 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
2264 2268 |/
2265 2269 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
2266 2270 |
2267 2271 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
2268 2272 |
2269 2273 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
2270 2274 |
2271 2275 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
2272 2276
2273 2277
2274 2278 Upper/lower filters:
2275 2279
2276 2280 $ hg log -r0 --template '{branch|upper}\n'
2277 2281 DEFAULT
2278 2282 $ hg log -r0 --template '{author|lower}\n'
2279 2283 user name <user@hostname>
2280 2284 $ hg log -r0 --template '{date|upper}\n'
2281 2285 abort: template filter 'upper' is not compatible with keyword 'date'
2282 2286 [255]
2283 2287
2284 2288 Add a commit that does all possible modifications at once
2285 2289
2286 2290 $ echo modify >> third
2287 2291 $ touch b
2288 2292 $ hg add b
2289 2293 $ hg mv fourth fifth
2290 2294 $ hg rm a
2291 2295 $ hg ci -m "Modify, add, remove, rename"
2292 2296
2293 2297 Check the status template
2294 2298
2295 2299 $ cat <<EOF >> $HGRCPATH
2296 2300 > [extensions]
2297 2301 > color=
2298 2302 > EOF
2299 2303
2300 2304 $ hg log -T status -r 10
2301 2305 changeset: 10:0f9759ec227a
2302 2306 tag: tip
2303 2307 user: test
2304 2308 date: Thu Jan 01 00:00:00 1970 +0000
2305 2309 summary: Modify, add, remove, rename
2306 2310 files:
2307 2311 M third
2308 2312 A b
2309 2313 A fifth
2310 2314 R a
2311 2315 R fourth
2312 2316
2313 2317 $ hg log -T status -C -r 10
2314 2318 changeset: 10:0f9759ec227a
2315 2319 tag: tip
2316 2320 user: test
2317 2321 date: Thu Jan 01 00:00:00 1970 +0000
2318 2322 summary: Modify, add, remove, rename
2319 2323 files:
2320 2324 M third
2321 2325 A b
2322 2326 A fifth
2323 2327 fourth
2324 2328 R a
2325 2329 R fourth
2326 2330
2327 2331 $ hg log -T status -C -r 10 -v
2328 2332 changeset: 10:0f9759ec227a
2329 2333 tag: tip
2330 2334 user: test
2331 2335 date: Thu Jan 01 00:00:00 1970 +0000
2332 2336 description:
2333 2337 Modify, add, remove, rename
2334 2338
2335 2339 files:
2336 2340 M third
2337 2341 A b
2338 2342 A fifth
2339 2343 fourth
2340 2344 R a
2341 2345 R fourth
2342 2346
2343 2347 $ hg log -T status -C -r 10 --debug
2344 2348 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
2345 2349 tag: tip
2346 2350 phase: secret
2347 2351 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
2348 2352 parent: -1:0000000000000000000000000000000000000000
2349 2353 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
2350 2354 user: test
2351 2355 date: Thu Jan 01 00:00:00 1970 +0000
2352 2356 extra: branch=default
2353 2357 description:
2354 2358 Modify, add, remove, rename
2355 2359
2356 2360 files:
2357 2361 M third
2358 2362 A b
2359 2363 A fifth
2360 2364 fourth
2361 2365 R a
2362 2366 R fourth
2363 2367
2364 2368 $ hg log -T status -C -r 10 --quiet
2365 2369 10:0f9759ec227a
2366 2370 $ hg --color=debug log -T status -r 10
2367 2371 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2368 2372 [log.tag|tag: tip]
2369 2373 [log.user|user: test]
2370 2374 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2371 2375 [log.summary|summary: Modify, add, remove, rename]
2372 2376 [ui.note log.files|files:]
2373 2377 [status.modified|M third]
2374 2378 [status.added|A b]
2375 2379 [status.added|A fifth]
2376 2380 [status.removed|R a]
2377 2381 [status.removed|R fourth]
2378 2382
2379 2383 $ hg --color=debug log -T status -C -r 10
2380 2384 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2381 2385 [log.tag|tag: tip]
2382 2386 [log.user|user: test]
2383 2387 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2384 2388 [log.summary|summary: Modify, add, remove, rename]
2385 2389 [ui.note log.files|files:]
2386 2390 [status.modified|M third]
2387 2391 [status.added|A b]
2388 2392 [status.added|A fifth]
2389 2393 [status.copied| fourth]
2390 2394 [status.removed|R a]
2391 2395 [status.removed|R fourth]
2392 2396
2393 2397 $ hg --color=debug log -T status -C -r 10 -v
2394 2398 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2395 2399 [log.tag|tag: tip]
2396 2400 [log.user|user: test]
2397 2401 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2398 2402 [ui.note log.description|description:]
2399 2403 [ui.note log.description|Modify, add, remove, rename]
2400 2404
2401 2405 [ui.note log.files|files:]
2402 2406 [status.modified|M third]
2403 2407 [status.added|A b]
2404 2408 [status.added|A fifth]
2405 2409 [status.copied| fourth]
2406 2410 [status.removed|R a]
2407 2411 [status.removed|R fourth]
2408 2412
2409 2413 $ hg --color=debug log -T status -C -r 10 --debug
2410 2414 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
2411 2415 [log.tag|tag: tip]
2412 2416 [log.phase|phase: secret]
2413 2417 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
2414 2418 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2415 2419 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
2416 2420 [log.user|user: test]
2417 2421 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2418 2422 [ui.debug log.extra|extra: branch=default]
2419 2423 [ui.note log.description|description:]
2420 2424 [ui.note log.description|Modify, add, remove, rename]
2421 2425
2422 2426 [ui.note log.files|files:]
2423 2427 [status.modified|M third]
2424 2428 [status.added|A b]
2425 2429 [status.added|A fifth]
2426 2430 [status.copied| fourth]
2427 2431 [status.removed|R a]
2428 2432 [status.removed|R fourth]
2429 2433
2430 2434 $ hg --color=debug log -T status -C -r 10 --quiet
2431 2435 [log.node|10:0f9759ec227a]
2432 2436
2433 2437 Check the bisect template
2434 2438
2435 2439 $ hg bisect -g 1
2436 2440 $ hg bisect -b 3 --noupdate
2437 2441 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
2438 2442 $ hg log -T bisect -r 0:4
2439 2443 changeset: 0:1e4e1b8f71e0
2440 2444 bisect: good (implicit)
2441 2445 user: User Name <user@hostname>
2442 2446 date: Mon Jan 12 13:46:40 1970 +0000
2443 2447 summary: line 1
2444 2448
2445 2449 changeset: 1:b608e9d1a3f0
2446 2450 bisect: good
2447 2451 user: A. N. Other <other@place>
2448 2452 date: Tue Jan 13 17:33:20 1970 +0000
2449 2453 summary: other 1
2450 2454
2451 2455 changeset: 2:97054abb4ab8
2452 2456 bisect: untested
2453 2457 user: other@place
2454 2458 date: Wed Jan 14 21:20:00 1970 +0000
2455 2459 summary: no person
2456 2460
2457 2461 changeset: 3:10e46f2dcbf4
2458 2462 bisect: bad
2459 2463 user: person
2460 2464 date: Fri Jan 16 01:06:40 1970 +0000
2461 2465 summary: no user, no domain
2462 2466
2463 2467 changeset: 4:bbe44766e73d
2464 2468 bisect: bad (implicit)
2465 2469 branch: foo
2466 2470 user: person
2467 2471 date: Sat Jan 17 04:53:20 1970 +0000
2468 2472 summary: new branch
2469 2473
2470 2474 $ hg log --debug -T bisect -r 0:4
2471 2475 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2472 2476 bisect: good (implicit)
2473 2477 phase: public
2474 2478 parent: -1:0000000000000000000000000000000000000000
2475 2479 parent: -1:0000000000000000000000000000000000000000
2476 2480 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
2477 2481 user: User Name <user@hostname>
2478 2482 date: Mon Jan 12 13:46:40 1970 +0000
2479 2483 files+: a
2480 2484 extra: branch=default
2481 2485 description:
2482 2486 line 1
2483 2487 line 2
2484 2488
2485 2489
2486 2490 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2487 2491 bisect: good
2488 2492 phase: public
2489 2493 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2490 2494 parent: -1:0000000000000000000000000000000000000000
2491 2495 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
2492 2496 user: A. N. Other <other@place>
2493 2497 date: Tue Jan 13 17:33:20 1970 +0000
2494 2498 files+: b
2495 2499 extra: branch=default
2496 2500 description:
2497 2501 other 1
2498 2502 other 2
2499 2503
2500 2504 other 3
2501 2505
2502 2506
2503 2507 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
2504 2508 bisect: untested
2505 2509 phase: public
2506 2510 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2507 2511 parent: -1:0000000000000000000000000000000000000000
2508 2512 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
2509 2513 user: other@place
2510 2514 date: Wed Jan 14 21:20:00 1970 +0000
2511 2515 files+: c
2512 2516 extra: branch=default
2513 2517 description:
2514 2518 no person
2515 2519
2516 2520
2517 2521 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2518 2522 bisect: bad
2519 2523 phase: public
2520 2524 parent: 2:97054abb4ab824450e9164180baf491ae0078465
2521 2525 parent: -1:0000000000000000000000000000000000000000
2522 2526 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2523 2527 user: person
2524 2528 date: Fri Jan 16 01:06:40 1970 +0000
2525 2529 files: c
2526 2530 extra: branch=default
2527 2531 description:
2528 2532 no user, no domain
2529 2533
2530 2534
2531 2535 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
2532 2536 bisect: bad (implicit)
2533 2537 branch: foo
2534 2538 phase: draft
2535 2539 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2536 2540 parent: -1:0000000000000000000000000000000000000000
2537 2541 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2538 2542 user: person
2539 2543 date: Sat Jan 17 04:53:20 1970 +0000
2540 2544 extra: branch=foo
2541 2545 description:
2542 2546 new branch
2543 2547
2544 2548
2545 2549 $ hg log -v -T bisect -r 0:4
2546 2550 changeset: 0:1e4e1b8f71e0
2547 2551 bisect: good (implicit)
2548 2552 user: User Name <user@hostname>
2549 2553 date: Mon Jan 12 13:46:40 1970 +0000
2550 2554 files: a
2551 2555 description:
2552 2556 line 1
2553 2557 line 2
2554 2558
2555 2559
2556 2560 changeset: 1:b608e9d1a3f0
2557 2561 bisect: good
2558 2562 user: A. N. Other <other@place>
2559 2563 date: Tue Jan 13 17:33:20 1970 +0000
2560 2564 files: b
2561 2565 description:
2562 2566 other 1
2563 2567 other 2
2564 2568
2565 2569 other 3
2566 2570
2567 2571
2568 2572 changeset: 2:97054abb4ab8
2569 2573 bisect: untested
2570 2574 user: other@place
2571 2575 date: Wed Jan 14 21:20:00 1970 +0000
2572 2576 files: c
2573 2577 description:
2574 2578 no person
2575 2579
2576 2580
2577 2581 changeset: 3:10e46f2dcbf4
2578 2582 bisect: bad
2579 2583 user: person
2580 2584 date: Fri Jan 16 01:06:40 1970 +0000
2581 2585 files: c
2582 2586 description:
2583 2587 no user, no domain
2584 2588
2585 2589
2586 2590 changeset: 4:bbe44766e73d
2587 2591 bisect: bad (implicit)
2588 2592 branch: foo
2589 2593 user: person
2590 2594 date: Sat Jan 17 04:53:20 1970 +0000
2591 2595 description:
2592 2596 new branch
2593 2597
2594 2598
2595 2599 $ hg --color=debug log -T bisect -r 0:4
2596 2600 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2597 2601 [log.bisect bisect.good|bisect: good (implicit)]
2598 2602 [log.user|user: User Name <user@hostname>]
2599 2603 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2600 2604 [log.summary|summary: line 1]
2601 2605
2602 2606 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2603 2607 [log.bisect bisect.good|bisect: good]
2604 2608 [log.user|user: A. N. Other <other@place>]
2605 2609 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2606 2610 [log.summary|summary: other 1]
2607 2611
2608 2612 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2609 2613 [log.bisect bisect.untested|bisect: untested]
2610 2614 [log.user|user: other@place]
2611 2615 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2612 2616 [log.summary|summary: no person]
2613 2617
2614 2618 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2615 2619 [log.bisect bisect.bad|bisect: bad]
2616 2620 [log.user|user: person]
2617 2621 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2618 2622 [log.summary|summary: no user, no domain]
2619 2623
2620 2624 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2621 2625 [log.bisect bisect.bad|bisect: bad (implicit)]
2622 2626 [log.branch|branch: foo]
2623 2627 [log.user|user: person]
2624 2628 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2625 2629 [log.summary|summary: new branch]
2626 2630
2627 2631 $ hg --color=debug log --debug -T bisect -r 0:4
2628 2632 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2629 2633 [log.bisect bisect.good|bisect: good (implicit)]
2630 2634 [log.phase|phase: public]
2631 2635 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2632 2636 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2633 2637 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
2634 2638 [log.user|user: User Name <user@hostname>]
2635 2639 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2636 2640 [ui.debug log.files|files+: a]
2637 2641 [ui.debug log.extra|extra: branch=default]
2638 2642 [ui.note log.description|description:]
2639 2643 [ui.note log.description|line 1
2640 2644 line 2]
2641 2645
2642 2646
2643 2647 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2644 2648 [log.bisect bisect.good|bisect: good]
2645 2649 [log.phase|phase: public]
2646 2650 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2647 2651 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2648 2652 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
2649 2653 [log.user|user: A. N. Other <other@place>]
2650 2654 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2651 2655 [ui.debug log.files|files+: b]
2652 2656 [ui.debug log.extra|extra: branch=default]
2653 2657 [ui.note log.description|description:]
2654 2658 [ui.note log.description|other 1
2655 2659 other 2
2656 2660
2657 2661 other 3]
2658 2662
2659 2663
2660 2664 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
2661 2665 [log.bisect bisect.untested|bisect: untested]
2662 2666 [log.phase|phase: public]
2663 2667 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2664 2668 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2665 2669 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
2666 2670 [log.user|user: other@place]
2667 2671 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2668 2672 [ui.debug log.files|files+: c]
2669 2673 [ui.debug log.extra|extra: branch=default]
2670 2674 [ui.note log.description|description:]
2671 2675 [ui.note log.description|no person]
2672 2676
2673 2677
2674 2678 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2675 2679 [log.bisect bisect.bad|bisect: bad]
2676 2680 [log.phase|phase: public]
2677 2681 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
2678 2682 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2679 2683 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2680 2684 [log.user|user: person]
2681 2685 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2682 2686 [ui.debug log.files|files: c]
2683 2687 [ui.debug log.extra|extra: branch=default]
2684 2688 [ui.note log.description|description:]
2685 2689 [ui.note log.description|no user, no domain]
2686 2690
2687 2691
2688 2692 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
2689 2693 [log.bisect bisect.bad|bisect: bad (implicit)]
2690 2694 [log.branch|branch: foo]
2691 2695 [log.phase|phase: draft]
2692 2696 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2693 2697 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2694 2698 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2695 2699 [log.user|user: person]
2696 2700 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2697 2701 [ui.debug log.extra|extra: branch=foo]
2698 2702 [ui.note log.description|description:]
2699 2703 [ui.note log.description|new branch]
2700 2704
2701 2705
2702 2706 $ hg --color=debug log -v -T bisect -r 0:4
2703 2707 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2704 2708 [log.bisect bisect.good|bisect: good (implicit)]
2705 2709 [log.user|user: User Name <user@hostname>]
2706 2710 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2707 2711 [ui.note log.files|files: a]
2708 2712 [ui.note log.description|description:]
2709 2713 [ui.note log.description|line 1
2710 2714 line 2]
2711 2715
2712 2716
2713 2717 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2714 2718 [log.bisect bisect.good|bisect: good]
2715 2719 [log.user|user: A. N. Other <other@place>]
2716 2720 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2717 2721 [ui.note log.files|files: b]
2718 2722 [ui.note log.description|description:]
2719 2723 [ui.note log.description|other 1
2720 2724 other 2
2721 2725
2722 2726 other 3]
2723 2727
2724 2728
2725 2729 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2726 2730 [log.bisect bisect.untested|bisect: untested]
2727 2731 [log.user|user: other@place]
2728 2732 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2729 2733 [ui.note log.files|files: c]
2730 2734 [ui.note log.description|description:]
2731 2735 [ui.note log.description|no person]
2732 2736
2733 2737
2734 2738 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2735 2739 [log.bisect bisect.bad|bisect: bad]
2736 2740 [log.user|user: person]
2737 2741 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2738 2742 [ui.note log.files|files: c]
2739 2743 [ui.note log.description|description:]
2740 2744 [ui.note log.description|no user, no domain]
2741 2745
2742 2746
2743 2747 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2744 2748 [log.bisect bisect.bad|bisect: bad (implicit)]
2745 2749 [log.branch|branch: foo]
2746 2750 [log.user|user: person]
2747 2751 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2748 2752 [ui.note log.description|description:]
2749 2753 [ui.note log.description|new branch]
2750 2754
2751 2755
2752 2756 $ hg bisect --reset
2753 2757
2754 2758 Error on syntax:
2755 2759
2756 2760 $ echo 'x = "f' >> t
2757 2761 $ hg log
2758 2762 hg: parse error at t:3: unmatched quotes
2759 2763 [255]
2760 2764
2761 2765 $ hg log -T '{date'
2762 2766 hg: parse error at 1: unterminated template expansion
2763 2767 [255]
2764 2768 $ hg log -T '{date(}'
2765 2769 hg: parse error at 7: not a prefix: end
2766 2770 [255]
2767 2771 $ hg log -T '{date)}'
2768 2772 hg: parse error at 5: invalid token
2769 2773 [255]
2770 2774 $ hg log -T '{date date}'
2771 2775 hg: parse error at 6: invalid token
2772 2776 [255]
2773 2777
2774 2778 $ hg log -T '{}'
2775 2779 hg: parse error at 2: not a prefix: end
2776 2780 [255]
2777 2781 $ hg debugtemplate -v '{()}'
2778 2782 (template
2779 2783 (group
2780 2784 None))
2781 2785 hg: parse error: missing argument
2782 2786 [255]
2783 2787
2784 2788 Behind the scenes, this will throw TypeError
2785 2789
2786 2790 $ hg log -l 3 --template '{date|obfuscate}\n'
2787 2791 abort: template filter 'obfuscate' is not compatible with keyword 'date'
2788 2792 [255]
2789 2793
2790 2794 Behind the scenes, this will throw a ValueError
2791 2795
2792 2796 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
2793 2797 abort: template filter 'shortdate' is not compatible with keyword 'desc'
2794 2798 [255]
2795 2799
2796 2800 Behind the scenes, this will throw AttributeError
2797 2801
2798 2802 $ hg log -l 3 --template 'line: {date|escape}\n'
2799 2803 abort: template filter 'escape' is not compatible with keyword 'date'
2800 2804 [255]
2801 2805
2802 2806 $ hg log -l 3 --template 'line: {extras|localdate}\n'
2803 2807 hg: parse error: localdate expects a date information
2804 2808 [255]
2805 2809
2806 2810 Behind the scenes, this will throw ValueError
2807 2811
2808 2812 $ hg tip --template '{author|email|date}\n'
2809 2813 hg: parse error: date expects a date information
2810 2814 [255]
2811 2815
2812 2816 $ hg tip -T '{author|email|shortdate}\n'
2813 2817 abort: template filter 'shortdate' is not compatible with keyword 'author'
2814 2818 [255]
2815 2819
2816 2820 $ hg tip -T '{get(extras, "branch")|shortdate}\n'
2817 2821 abort: incompatible use of template filter 'shortdate'
2818 2822 [255]
2819 2823
2820 2824 Error in nested template:
2821 2825
2822 2826 $ hg log -T '{"date'
2823 2827 hg: parse error at 2: unterminated string
2824 2828 [255]
2825 2829
2826 2830 $ hg log -T '{"foo{date|?}"}'
2827 2831 hg: parse error at 11: syntax error
2828 2832 [255]
2829 2833
2830 2834 Thrown an error if a template function doesn't exist
2831 2835
2832 2836 $ hg tip --template '{foo()}\n'
2833 2837 hg: parse error: unknown function 'foo'
2834 2838 [255]
2835 2839
2836 2840 Pass generator object created by template function to filter
2837 2841
2838 2842 $ hg log -l 1 --template '{if(author, author)|user}\n'
2839 2843 test
2840 2844
2841 2845 Test index keyword:
2842 2846
2843 2847 $ hg log -l 2 -T '{index + 10}{files % " {index}:{file}"}\n'
2844 2848 10 0:a 1:b 2:fifth 3:fourth 4:third
2845 2849 11 0:a
2846 2850
2847 2851 $ hg branches -T '{index} {branch}\n'
2848 2852 0 default
2849 2853 1 foo
2850 2854
2851 2855 Test diff function:
2852 2856
2853 2857 $ hg diff -c 8
2854 2858 diff -r 29114dbae42b -r 95c24699272e fourth
2855 2859 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2856 2860 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2857 2861 @@ -0,0 +1,1 @@
2858 2862 +second
2859 2863 diff -r 29114dbae42b -r 95c24699272e second
2860 2864 --- a/second Mon Jan 12 13:46:40 1970 +0000
2861 2865 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2862 2866 @@ -1,1 +0,0 @@
2863 2867 -second
2864 2868 diff -r 29114dbae42b -r 95c24699272e third
2865 2869 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2866 2870 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2867 2871 @@ -0,0 +1,1 @@
2868 2872 +third
2869 2873
2870 2874 $ hg log -r 8 -T "{diff()}"
2871 2875 diff -r 29114dbae42b -r 95c24699272e fourth
2872 2876 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2873 2877 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2874 2878 @@ -0,0 +1,1 @@
2875 2879 +second
2876 2880 diff -r 29114dbae42b -r 95c24699272e second
2877 2881 --- a/second Mon Jan 12 13:46:40 1970 +0000
2878 2882 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2879 2883 @@ -1,1 +0,0 @@
2880 2884 -second
2881 2885 diff -r 29114dbae42b -r 95c24699272e third
2882 2886 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2883 2887 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2884 2888 @@ -0,0 +1,1 @@
2885 2889 +third
2886 2890
2887 2891 $ hg log -r 8 -T "{diff('glob:f*')}"
2888 2892 diff -r 29114dbae42b -r 95c24699272e fourth
2889 2893 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2890 2894 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2891 2895 @@ -0,0 +1,1 @@
2892 2896 +second
2893 2897
2894 2898 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2895 2899 diff -r 29114dbae42b -r 95c24699272e second
2896 2900 --- a/second Mon Jan 12 13:46:40 1970 +0000
2897 2901 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2898 2902 @@ -1,1 +0,0 @@
2899 2903 -second
2900 2904 diff -r 29114dbae42b -r 95c24699272e third
2901 2905 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2902 2906 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2903 2907 @@ -0,0 +1,1 @@
2904 2908 +third
2905 2909
2906 2910 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
2907 2911 diff -r 29114dbae42b -r 95c24699272e fourth
2908 2912 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2909 2913 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2910 2914 @@ -0,0 +1,1 @@
2911 2915 +second
2912 2916
2913 2917 ui verbosity:
2914 2918
2915 2919 $ hg log -l1 -T '{verbosity}\n'
2916 2920
2917 2921 $ hg log -l1 -T '{verbosity}\n' --debug
2918 2922 debug
2919 2923 $ hg log -l1 -T '{verbosity}\n' --quiet
2920 2924 quiet
2921 2925 $ hg log -l1 -T '{verbosity}\n' --verbose
2922 2926 verbose
2923 2927
2924 2928 $ cd ..
2925 2929
2926 2930
2927 2931 latesttag:
2928 2932
2929 2933 $ hg init latesttag
2930 2934 $ cd latesttag
2931 2935
2932 2936 $ echo a > file
2933 2937 $ hg ci -Am a -d '0 0'
2934 2938 adding file
2935 2939
2936 2940 $ echo b >> file
2937 2941 $ hg ci -m b -d '1 0'
2938 2942
2939 2943 $ echo c >> head1
2940 2944 $ hg ci -Am h1c -d '2 0'
2941 2945 adding head1
2942 2946
2943 2947 $ hg update -q 1
2944 2948 $ echo d >> head2
2945 2949 $ hg ci -Am h2d -d '3 0'
2946 2950 adding head2
2947 2951 created new head
2948 2952
2949 2953 $ echo e >> head2
2950 2954 $ hg ci -m h2e -d '4 0'
2951 2955
2952 2956 $ hg merge -q
2953 2957 $ hg ci -m merge -d '5 -3600'
2954 2958
2955 2959 No tag set:
2956 2960
2957 2961 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2958 2962 @ 5: null+5
2959 2963 |\
2960 2964 | o 4: null+4
2961 2965 | |
2962 2966 | o 3: null+3
2963 2967 | |
2964 2968 o | 2: null+3
2965 2969 |/
2966 2970 o 1: null+2
2967 2971 |
2968 2972 o 0: null+1
2969 2973
2970 2974
2971 2975 One common tag: longest path wins for {latesttagdistance}:
2972 2976
2973 2977 $ hg tag -r 1 -m t1 -d '6 0' t1
2974 2978 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2975 2979 @ 6: t1+4
2976 2980 |
2977 2981 o 5: t1+3
2978 2982 |\
2979 2983 | o 4: t1+2
2980 2984 | |
2981 2985 | o 3: t1+1
2982 2986 | |
2983 2987 o | 2: t1+1
2984 2988 |/
2985 2989 o 1: t1+0
2986 2990 |
2987 2991 o 0: null+1
2988 2992
2989 2993
2990 2994 One ancestor tag: closest wins:
2991 2995
2992 2996 $ hg tag -r 2 -m t2 -d '7 0' t2
2993 2997 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2994 2998 @ 7: t2+3
2995 2999 |
2996 3000 o 6: t2+2
2997 3001 |
2998 3002 o 5: t2+1
2999 3003 |\
3000 3004 | o 4: t1+2
3001 3005 | |
3002 3006 | o 3: t1+1
3003 3007 | |
3004 3008 o | 2: t2+0
3005 3009 |/
3006 3010 o 1: t1+0
3007 3011 |
3008 3012 o 0: null+1
3009 3013
3010 3014
3011 3015 Two branch tags: more recent wins if same number of changes:
3012 3016
3013 3017 $ hg tag -r 3 -m t3 -d '8 0' t3
3014 3018 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
3015 3019 @ 8: t3+5
3016 3020 |
3017 3021 o 7: t3+4
3018 3022 |
3019 3023 o 6: t3+3
3020 3024 |
3021 3025 o 5: t3+2
3022 3026 |\
3023 3027 | o 4: t3+1
3024 3028 | |
3025 3029 | o 3: t3+0
3026 3030 | |
3027 3031 o | 2: t2+0
3028 3032 |/
3029 3033 o 1: t1+0
3030 3034 |
3031 3035 o 0: null+1
3032 3036
3033 3037
3034 3038 Two branch tags: fewest changes wins:
3035 3039
3036 3040 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
3037 3041 $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
3038 3042 @ 9: t4+5,6
3039 3043 |
3040 3044 o 8: t4+4,5
3041 3045 |
3042 3046 o 7: t4+3,4
3043 3047 |
3044 3048 o 6: t4+2,3
3045 3049 |
3046 3050 o 5: t4+1,2
3047 3051 |\
3048 3052 | o 4: t4+0,0
3049 3053 | |
3050 3054 | o 3: t3+0,0
3051 3055 | |
3052 3056 o | 2: t2+0,0
3053 3057 |/
3054 3058 o 1: t1+0,0
3055 3059 |
3056 3060 o 0: null+1,1
3057 3061
3058 3062
3059 3063 Merged tag overrides:
3060 3064
3061 3065 $ hg tag -r 5 -m t5 -d '9 0' t5
3062 3066 $ hg tag -r 3 -m at3 -d '10 0' at3
3063 3067 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
3064 3068 @ 11: t5+6
3065 3069 |
3066 3070 o 10: t5+5
3067 3071 |
3068 3072 o 9: t5+4
3069 3073 |
3070 3074 o 8: t5+3
3071 3075 |
3072 3076 o 7: t5+2
3073 3077 |
3074 3078 o 6: t5+1
3075 3079 |
3076 3080 o 5: t5+0
3077 3081 |\
3078 3082 | o 4: t4+0
3079 3083 | |
3080 3084 | o 3: at3:t3+0
3081 3085 | |
3082 3086 o | 2: t2+0
3083 3087 |/
3084 3088 o 1: t1+0
3085 3089 |
3086 3090 o 0: null+1
3087 3091
3088 3092
3089 3093 $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
3090 3094 @ 11: t5+6,6
3091 3095 |
3092 3096 o 10: t5+5,5
3093 3097 |
3094 3098 o 9: t5+4,4
3095 3099 |
3096 3100 o 8: t5+3,3
3097 3101 |
3098 3102 o 7: t5+2,2
3099 3103 |
3100 3104 o 6: t5+1,1
3101 3105 |
3102 3106 o 5: t5+0,0
3103 3107 |\
3104 3108 | o 4: t4+0,0
3105 3109 | |
3106 3110 | o 3: at3+0,0 t3+0,0
3107 3111 | |
3108 3112 o | 2: t2+0,0
3109 3113 |/
3110 3114 o 1: t1+0,0
3111 3115 |
3112 3116 o 0: null+1,1
3113 3117
3114 3118
3115 3119 $ hg log -G --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
3116 3120 @ 11: t3, C: 9, D: 8
3117 3121 |
3118 3122 o 10: t3, C: 8, D: 7
3119 3123 |
3120 3124 o 9: t3, C: 7, D: 6
3121 3125 |
3122 3126 o 8: t3, C: 6, D: 5
3123 3127 |
3124 3128 o 7: t3, C: 5, D: 4
3125 3129 |
3126 3130 o 6: t3, C: 4, D: 3
3127 3131 |
3128 3132 o 5: t3, C: 3, D: 2
3129 3133 |\
3130 3134 | o 4: t3, C: 1, D: 1
3131 3135 | |
3132 3136 | o 3: t3, C: 0, D: 0
3133 3137 | |
3134 3138 o | 2: t1, C: 1, D: 1
3135 3139 |/
3136 3140 o 1: t1, C: 0, D: 0
3137 3141 |
3138 3142 o 0: null, C: 1, D: 1
3139 3143
3140 3144
3141 3145 $ cd ..
3142 3146
3143 3147
3144 3148 Style path expansion: issue1948 - ui.style option doesn't work on OSX
3145 3149 if it is a relative path
3146 3150
3147 3151 $ mkdir -p home/styles
3148 3152
3149 3153 $ cat > home/styles/teststyle <<EOF
3150 3154 > changeset = 'test {rev}:{node|short}\n'
3151 3155 > EOF
3152 3156
3153 3157 $ HOME=`pwd`/home; export HOME
3154 3158
3155 3159 $ cat > latesttag/.hg/hgrc <<EOF
3156 3160 > [ui]
3157 3161 > style = ~/styles/teststyle
3158 3162 > EOF
3159 3163
3160 3164 $ hg -R latesttag tip
3161 3165 test 11:97e5943b523a
3162 3166
3163 3167 Test recursive showlist template (issue1989):
3164 3168
3165 3169 $ cat > style1989 <<EOF
3166 3170 > changeset = '{file_mods}{manifest}{extras}'
3167 3171 > file_mod = 'M|{author|person}\n'
3168 3172 > manifest = '{rev},{author}\n'
3169 3173 > extra = '{key}: {author}\n'
3170 3174 > EOF
3171 3175
3172 3176 $ hg -R latesttag log -r tip --style=style1989
3173 3177 M|test
3174 3178 11,test
3175 3179 branch: test
3176 3180
3177 3181 Test new-style inline templating:
3178 3182
3179 3183 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
3180 3184 modified files: .hgtags
3181 3185
3182 3186
3183 3187 $ hg log -R latesttag -r tip -T '{rev % "a"}\n'
3184 3188 hg: parse error: keyword 'rev' is not iterable
3185 3189 [255]
3186 3190 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "a"}\n'
3187 3191 hg: parse error: None is not iterable
3188 3192 [255]
3189 3193
3190 3194 Test new-style inline templating of non-list/dict type:
3191 3195
3192 3196 $ hg log -R latesttag -r tip -T '{manifest}\n'
3193 3197 11:2bc6e9006ce2
3194 3198 $ hg log -R latesttag -r tip -T 'string length: {manifest|count}\n'
3195 3199 string length: 15
3196 3200 $ hg log -R latesttag -r tip -T '{manifest % "{rev}:{node}"}\n'
3197 3201 11:2bc6e9006ce29882383a22d39fd1f4e66dd3e2fc
3198 3202
3199 3203 $ hg log -R latesttag -r tip -T '{get(extras, "branch") % "{key}: {value}\n"}'
3200 3204 branch: default
3201 3205 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "{key}\n"}'
3202 3206 hg: parse error: None is not iterable
3203 3207 [255]
3204 3208 $ hg log -R latesttag -r tip -T '{min(extras) % "{key}: {value}\n"}'
3205 3209 branch: default
3206 3210 $ hg log -R latesttag -l1 -T '{min(revset("0:9")) % "{rev}:{node|short}\n"}'
3207 3211 0:ce3cec86e6c2
3208 3212 $ hg log -R latesttag -l1 -T '{max(revset("0:9")) % "{rev}:{node|short}\n"}'
3209 3213 9:fbc7cd862e9c
3210 3214
3211 3215 Test manifest/get() can be join()-ed as before, though it's silly:
3212 3216
3213 3217 $ hg log -R latesttag -r tip -T '{join(manifest, "")}\n'
3214 3218 11:2bc6e9006ce2
3215 3219 $ hg log -R latesttag -r tip -T '{join(get(extras, "branch"), "")}\n'
3216 3220 default
3217 3221
3218 3222 Test min/max of integers
3219 3223
3220 3224 $ hg log -R latesttag -l1 -T '{min(revset("9:10"))}\n'
3221 3225 9
3222 3226 $ hg log -R latesttag -l1 -T '{max(revset("9:10"))}\n'
3223 3227 10
3224 3228
3225 3229 Test dot operator precedence:
3226 3230
3227 3231 $ hg debugtemplate -R latesttag -r0 -v '{manifest.node|short}\n'
3228 3232 (template
3229 3233 (|
3230 3234 (.
3231 3235 (symbol 'manifest')
3232 3236 (symbol 'node'))
3233 3237 (symbol 'short'))
3234 3238 (string '\n'))
3235 3239 89f4071fec70
3236 3240
3237 3241 (the following examples are invalid, but seem natural in parsing POV)
3238 3242
3239 3243 $ hg debugtemplate -R latesttag -r0 -v '{foo|bar.baz}\n' 2> /dev/null
3240 3244 (template
3241 3245 (|
3242 3246 (symbol 'foo')
3243 3247 (.
3244 3248 (symbol 'bar')
3245 3249 (symbol 'baz')))
3246 3250 (string '\n'))
3247 3251 [255]
3248 3252 $ hg debugtemplate -R latesttag -r0 -v '{foo.bar()}\n' 2> /dev/null
3249 3253 (template
3250 3254 (.
3251 3255 (symbol 'foo')
3252 3256 (func
3253 3257 (symbol 'bar')
3254 3258 None))
3255 3259 (string '\n'))
3256 3260 [255]
3257 3261
3258 3262 Test evaluation of dot operator:
3259 3263
3260 3264 $ hg log -R latesttag -l1 -T '{min(revset("0:9")).node}\n'
3261 3265 ce3cec86e6c26bd9bdfc590a6b92abc9680f1796
3262 3266 $ hg log -R latesttag -r0 -T '{extras.branch}\n'
3263 3267 default
3264 3268
3265 3269 $ hg log -R latesttag -l1 -T '{author.invalid}\n'
3266 3270 hg: parse error: keyword 'author' has no member
3267 3271 [255]
3268 3272 $ hg log -R latesttag -l1 -T '{min("abc").invalid}\n'
3269 3273 hg: parse error: 'a' has no member
3270 3274 [255]
3271 3275
3272 3276 Test the sub function of templating for expansion:
3273 3277
3274 3278 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
3275 3279 xx
3276 3280
3277 3281 $ hg log -R latesttag -r 10 -T '{sub("[", "x", rev)}\n'
3278 3282 hg: parse error: sub got an invalid pattern: [
3279 3283 [255]
3280 3284 $ hg log -R latesttag -r 10 -T '{sub("[0-9]", r"\1", rev)}\n'
3281 3285 hg: parse error: sub got an invalid replacement: \1
3282 3286 [255]
3283 3287
3284 3288 Test the strip function with chars specified:
3285 3289
3286 3290 $ hg log -R latesttag --template '{desc}\n'
3287 3291 at3
3288 3292 t5
3289 3293 t4
3290 3294 t3
3291 3295 t2
3292 3296 t1
3293 3297 merge
3294 3298 h2e
3295 3299 h2d
3296 3300 h1c
3297 3301 b
3298 3302 a
3299 3303
3300 3304 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
3301 3305 at3
3302 3306 5
3303 3307 4
3304 3308 3
3305 3309 2
3306 3310 1
3307 3311 merg
3308 3312 h2
3309 3313 h2d
3310 3314 h1c
3311 3315 b
3312 3316 a
3313 3317
3314 3318 Test date format:
3315 3319
3316 3320 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
3317 3321 date: 70 01 01 10 +0000
3318 3322 date: 70 01 01 09 +0000
3319 3323 date: 70 01 01 04 +0000
3320 3324 date: 70 01 01 08 +0000
3321 3325 date: 70 01 01 07 +0000
3322 3326 date: 70 01 01 06 +0000
3323 3327 date: 70 01 01 05 +0100
3324 3328 date: 70 01 01 04 +0000
3325 3329 date: 70 01 01 03 +0000
3326 3330 date: 70 01 01 02 +0000
3327 3331 date: 70 01 01 01 +0000
3328 3332 date: 70 01 01 00 +0000
3329 3333
3330 3334 Test invalid date:
3331 3335
3332 3336 $ hg log -R latesttag -T '{date(rev)}\n'
3333 3337 hg: parse error: date expects a date information
3334 3338 [255]
3335 3339
3336 3340 Test integer literal:
3337 3341
3338 3342 $ hg debugtemplate -v '{(0)}\n'
3339 3343 (template
3340 3344 (group
3341 3345 (integer '0'))
3342 3346 (string '\n'))
3343 3347 0
3344 3348 $ hg debugtemplate -v '{(123)}\n'
3345 3349 (template
3346 3350 (group
3347 3351 (integer '123'))
3348 3352 (string '\n'))
3349 3353 123
3350 3354 $ hg debugtemplate -v '{(-4)}\n'
3351 3355 (template
3352 3356 (group
3353 3357 (negate
3354 3358 (integer '4')))
3355 3359 (string '\n'))
3356 3360 -4
3357 3361 $ hg debugtemplate '{(-)}\n'
3358 3362 hg: parse error at 3: not a prefix: )
3359 3363 [255]
3360 3364 $ hg debugtemplate '{(-a)}\n'
3361 3365 hg: parse error: negation needs an integer argument
3362 3366 [255]
3363 3367
3364 3368 top-level integer literal is interpreted as symbol (i.e. variable name):
3365 3369
3366 3370 $ hg debugtemplate -D 1=one -v '{1}\n'
3367 3371 (template
3368 3372 (integer '1')
3369 3373 (string '\n'))
3370 3374 one
3371 3375 $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
3372 3376 (template
3373 3377 (func
3374 3378 (symbol 'if')
3375 3379 (list
3376 3380 (string 't')
3377 3381 (template
3378 3382 (integer '1'))))
3379 3383 (string '\n'))
3380 3384 one
3381 3385 $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
3382 3386 (template
3383 3387 (|
3384 3388 (integer '1')
3385 3389 (symbol 'stringify'))
3386 3390 (string '\n'))
3387 3391 one
3388 3392
3389 3393 unless explicit symbol is expected:
3390 3394
3391 3395 $ hg log -Ra -r0 -T '{desc|1}\n'
3392 3396 hg: parse error: expected a symbol, got 'integer'
3393 3397 [255]
3394 3398 $ hg log -Ra -r0 -T '{1()}\n'
3395 3399 hg: parse error: expected a symbol, got 'integer'
3396 3400 [255]
3397 3401
3398 3402 Test string literal:
3399 3403
3400 3404 $ hg debugtemplate -Ra -r0 -v '{"string with no template fragment"}\n'
3401 3405 (template
3402 3406 (string 'string with no template fragment')
3403 3407 (string '\n'))
3404 3408 string with no template fragment
3405 3409 $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
3406 3410 (template
3407 3411 (template
3408 3412 (string 'template: ')
3409 3413 (symbol 'rev'))
3410 3414 (string '\n'))
3411 3415 template: 0
3412 3416 $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
3413 3417 (template
3414 3418 (string 'rawstring: {rev}')
3415 3419 (string '\n'))
3416 3420 rawstring: {rev}
3417 3421 $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
3418 3422 (template
3419 3423 (%
3420 3424 (symbol 'files')
3421 3425 (string 'rawstring: {file}'))
3422 3426 (string '\n'))
3423 3427 rawstring: {file}
3424 3428
3425 3429 Test string escaping:
3426 3430
3427 3431 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3428 3432 >
3429 3433 <>\n<[>
3430 3434 <>\n<]>
3431 3435 <>\n<
3432 3436
3433 3437 $ hg log -R latesttag -r 0 \
3434 3438 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3435 3439 >
3436 3440 <>\n<[>
3437 3441 <>\n<]>
3438 3442 <>\n<
3439 3443
3440 3444 $ hg log -R latesttag -r 0 -T esc \
3441 3445 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3442 3446 >
3443 3447 <>\n<[>
3444 3448 <>\n<]>
3445 3449 <>\n<
3446 3450
3447 3451 $ cat <<'EOF' > esctmpl
3448 3452 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3449 3453 > EOF
3450 3454 $ hg log -R latesttag -r 0 --style ./esctmpl
3451 3455 >
3452 3456 <>\n<[>
3453 3457 <>\n<]>
3454 3458 <>\n<
3455 3459
3456 3460 Test string escaping of quotes:
3457 3461
3458 3462 $ hg log -Ra -r0 -T '{"\""}\n'
3459 3463 "
3460 3464 $ hg log -Ra -r0 -T '{"\\\""}\n'
3461 3465 \"
3462 3466 $ hg log -Ra -r0 -T '{r"\""}\n'
3463 3467 \"
3464 3468 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3465 3469 \\\"
3466 3470
3467 3471
3468 3472 $ hg log -Ra -r0 -T '{"\""}\n'
3469 3473 "
3470 3474 $ hg log -Ra -r0 -T '{"\\\""}\n'
3471 3475 \"
3472 3476 $ hg log -Ra -r0 -T '{r"\""}\n'
3473 3477 \"
3474 3478 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3475 3479 \\\"
3476 3480
3477 3481 Test exception in quoted template. single backslash before quotation mark is
3478 3482 stripped before parsing:
3479 3483
3480 3484 $ cat <<'EOF' > escquotetmpl
3481 3485 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
3482 3486 > EOF
3483 3487 $ cd latesttag
3484 3488 $ hg log -r 2 --style ../escquotetmpl
3485 3489 " \" \" \\" head1
3486 3490
3487 3491 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
3488 3492 valid
3489 3493 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
3490 3494 valid
3491 3495
3492 3496 Test compatibility with 2.9.2-3.4 of escaped quoted strings in nested
3493 3497 _evalifliteral() templates (issue4733):
3494 3498
3495 3499 $ hg log -r 2 -T '{if(rev, "\"{rev}")}\n'
3496 3500 "2
3497 3501 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\"{rev}\")}")}\n'
3498 3502 "2
3499 3503 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\"{rev}\\\")}\")}")}\n'
3500 3504 "2
3501 3505
3502 3506 $ hg log -r 2 -T '{if(rev, "\\\"")}\n'
3503 3507 \"
3504 3508 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\\\\\"\")}")}\n'
3505 3509 \"
3506 3510 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3507 3511 \"
3508 3512
3509 3513 $ hg log -r 2 -T '{if(rev, r"\\\"")}\n'
3510 3514 \\\"
3511 3515 $ hg log -r 2 -T '{if(rev, "{if(rev, r\"\\\\\\\"\")}")}\n'
3512 3516 \\\"
3513 3517 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, r\\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3514 3518 \\\"
3515 3519
3516 3520 escaped single quotes and errors:
3517 3521
3518 3522 $ hg log -r 2 -T "{if(rev, '{if(rev, \'foo\')}')}"'\n'
3519 3523 foo
3520 3524 $ hg log -r 2 -T "{if(rev, '{if(rev, r\'foo\')}')}"'\n'
3521 3525 foo
3522 3526 $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n'
3523 3527 hg: parse error at 21: unterminated string
3524 3528 [255]
3525 3529 $ hg log -r 2 -T '{if(rev, \"\\"")}\n'
3526 3530 hg: parse error: trailing \ in string
3527 3531 [255]
3528 3532 $ hg log -r 2 -T '{if(rev, r\"\\"")}\n'
3529 3533 hg: parse error: trailing \ in string
3530 3534 [255]
3531 3535
3532 3536 $ cd ..
3533 3537
3534 3538 Test leading backslashes:
3535 3539
3536 3540 $ cd latesttag
3537 3541 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
3538 3542 {rev} {file}
3539 3543 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
3540 3544 \2 \head1
3541 3545 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
3542 3546 \{rev} \{file}
3543 3547 $ cd ..
3544 3548
3545 3549 Test leading backslashes in "if" expression (issue4714):
3546 3550
3547 3551 $ cd latesttag
3548 3552 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
3549 3553 {rev} \{rev}
3550 3554 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
3551 3555 \2 \\{rev}
3552 3556 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
3553 3557 \{rev} \\\{rev}
3554 3558 $ cd ..
3555 3559
3556 3560 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
3557 3561
3558 3562 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
3559 3563 \x6e
3560 3564 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
3561 3565 \x5c\x786e
3562 3566 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
3563 3567 \x6e
3564 3568 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
3565 3569 \x5c\x786e
3566 3570
3567 3571 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
3568 3572 \x6e
3569 3573 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
3570 3574 \x5c\x786e
3571 3575 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
3572 3576 \x6e
3573 3577 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
3574 3578 \x5c\x786e
3575 3579
3576 3580 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
3577 3581 fourth
3578 3582 second
3579 3583 third
3580 3584 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
3581 3585 fourth\nsecond\nthird
3582 3586
3583 3587 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
3584 3588 <p>
3585 3589 1st
3586 3590 </p>
3587 3591 <p>
3588 3592 2nd
3589 3593 </p>
3590 3594 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
3591 3595 <p>
3592 3596 1st\n\n2nd
3593 3597 </p>
3594 3598 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
3595 3599 1st
3596 3600
3597 3601 2nd
3598 3602
3599 3603 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
3600 3604 o perso
3601 3605 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
3602 3606 no person
3603 3607 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
3604 3608 o perso
3605 3609 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
3606 3610 no perso
3607 3611
3608 3612 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
3609 3613 -o perso-
3610 3614 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
3611 3615 no person
3612 3616 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
3613 3617 \x2do perso\x2d
3614 3618 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
3615 3619 -o perso-
3616 3620 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
3617 3621 \x2do perso\x6e
3618 3622
3619 3623 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
3620 3624 fourth
3621 3625 second
3622 3626 third
3623 3627
3624 3628 Test string escaping in nested expression:
3625 3629
3626 3630 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
3627 3631 fourth\x6esecond\x6ethird
3628 3632 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
3629 3633 fourth\x6esecond\x6ethird
3630 3634
3631 3635 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
3632 3636 fourth\x6esecond\x6ethird
3633 3637 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
3634 3638 fourth\x5c\x786esecond\x5c\x786ethird
3635 3639
3636 3640 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
3637 3641 3:\x6eo user, \x6eo domai\x6e
3638 3642 4:\x5c\x786eew bra\x5c\x786ech
3639 3643
3640 3644 Test quotes in nested expression are evaluated just like a $(command)
3641 3645 substitution in POSIX shells:
3642 3646
3643 3647 $ hg log -R a -r 8 -T '{"{"{rev}:{node|short}"}"}\n'
3644 3648 8:95c24699272e
3645 3649 $ hg log -R a -r 8 -T '{"{"\{{rev}} \"{node|short}\""}"}\n'
3646 3650 {8} "95c24699272e"
3647 3651
3648 3652 Test recursive evaluation:
3649 3653
3650 3654 $ hg init r
3651 3655 $ cd r
3652 3656 $ echo a > a
3653 3657 $ hg ci -Am '{rev}'
3654 3658 adding a
3655 3659 $ hg log -r 0 --template '{if(rev, desc)}\n'
3656 3660 {rev}
3657 3661 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
3658 3662 test 0
3659 3663
3660 3664 $ hg branch -q 'text.{rev}'
3661 3665 $ echo aa >> aa
3662 3666 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
3663 3667
3664 3668 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
3665 3669 {node|short}desc to
3666 3670 text.{rev}be wrapped
3667 3671 text.{rev}desc to be
3668 3672 text.{rev}wrapped (no-eol)
3669 3673 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
3670 3674 bcc7ff960b8e:desc to
3671 3675 text.1:be wrapped
3672 3676 text.1:desc to be
3673 3677 text.1:wrapped (no-eol)
3674 3678 $ hg log -l1 -T '{fill(desc, date, "", "")}\n'
3675 3679 hg: parse error: fill expects an integer width
3676 3680 [255]
3677 3681
3678 3682 $ COLUMNS=25 hg log -l1 --template '{fill(desc, termwidth, "{node|short}:", "termwidth.{rev}:")}'
3679 3683 bcc7ff960b8e:desc to be
3680 3684 termwidth.1:wrapped desc
3681 3685 termwidth.1:to be wrapped (no-eol)
3682 3686
3683 3687 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
3684 3688 {node|short} (no-eol)
3685 3689 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
3686 3690 bcc-ff---b-e (no-eol)
3687 3691
3688 3692 $ cat >> .hg/hgrc <<EOF
3689 3693 > [extensions]
3690 3694 > color=
3691 3695 > [color]
3692 3696 > mode=ansi
3693 3697 > text.{rev} = red
3694 3698 > text.1 = green
3695 3699 > EOF
3696 3700 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
3697 3701 \x1b[0;31mtext\x1b[0m (esc)
3698 3702 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
3699 3703 \x1b[0;32mtext\x1b[0m (esc)
3700 3704
3701 3705 color effect can be specified without quoting:
3702 3706
3703 3707 $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
3704 3708 \x1b[0;31mtext\x1b[0m (esc)
3705 3709
3706 3710 color effects can be nested (issue5413)
3707 3711
3708 3712 $ hg debugtemplate --color=always \
3709 3713 > '{label(red, "red{label(magenta, "ma{label(cyan, "cyan")}{label(yellow, "yellow")}genta")}")}\n'
3710 3714 \x1b[0;31mred\x1b[0;35mma\x1b[0;36mcyan\x1b[0m\x1b[0;31m\x1b[0;35m\x1b[0;33myellow\x1b[0m\x1b[0;31m\x1b[0;35mgenta\x1b[0m (esc)
3711 3715
3712 3716 pad() should interact well with color codes (issue5416)
3713 3717
3714 3718 $ hg debugtemplate --color=always \
3715 3719 > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n'
3716 3720 \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc)
3717 3721
3718 3722 label should be no-op if color is disabled:
3719 3723
3720 3724 $ hg log --color=never -l 1 --template '{label(red, "text\n")}'
3721 3725 text
3722 3726 $ hg log --config extensions.color=! -l 1 --template '{label(red, "text\n")}'
3723 3727 text
3724 3728
3725 3729 Test branches inside if statement:
3726 3730
3727 3731 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
3728 3732 no
3729 3733
3730 3734 Test dict constructor:
3731 3735
3732 3736 $ hg log -r 0 -T '{dict(y=node|short, x=rev)}\n'
3733 3737 y=f7769ec2ab97 x=0
3734 3738 $ hg log -r 0 -T '{dict(x=rev, y=node|short) % "{key}={value}\n"}'
3735 3739 x=0
3736 3740 y=f7769ec2ab97
3737 3741 $ hg log -r 0 -T '{dict(x=rev, y=node|short)|json}\n'
3738 3742 {"x": 0, "y": "f7769ec2ab97"}
3739 3743 $ hg log -r 0 -T '{dict()|json}\n'
3740 3744 {}
3741 3745
3742 3746 $ hg log -r 0 -T '{dict(rev, node=node|short)}\n'
3743 3747 rev=0 node=f7769ec2ab97
3744 3748 $ hg log -r 0 -T '{dict(rev, node|short)}\n'
3745 3749 rev=0 node=f7769ec2ab97
3746 3750
3747 3751 $ hg log -r 0 -T '{dict(rev, rev=rev)}\n'
3748 3752 hg: parse error: duplicated dict key 'rev' inferred
3749 3753 [255]
3750 3754 $ hg log -r 0 -T '{dict(node, node|short)}\n'
3751 3755 hg: parse error: duplicated dict key 'node' inferred
3752 3756 [255]
3753 3757 $ hg log -r 0 -T '{dict(1 + 2)}'
3754 3758 hg: parse error: dict key cannot be inferred
3755 3759 [255]
3756 3760
3757 3761 $ hg log -r 0 -T '{dict(x=rev, x=node)}'
3758 3762 hg: parse error: dict got multiple values for keyword argument 'x'
3759 3763 [255]
3760 3764
3761 3765 Test get function:
3762 3766
3763 3767 $ hg log -r 0 --template '{get(extras, "branch")}\n'
3764 3768 default
3765 3769 $ hg log -r 0 --template '{get(extras, "br{"anch"}")}\n'
3766 3770 default
3767 3771 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3768 3772 hg: parse error: get() expects a dict as first argument
3769 3773 [255]
3770 3774
3771 3775 Test json filter applied to hybrid object:
3772 3776
3773 3777 $ hg log -r0 -T '{files|json}\n'
3774 3778 ["a"]
3775 3779 $ hg log -r0 -T '{extras|json}\n'
3776 3780 {"branch": "default"}
3777 3781
3778 3782 Test localdate(date, tz) function:
3779 3783
3780 3784 $ TZ=JST-09 hg log -r0 -T '{date|localdate|isodate}\n'
3781 3785 1970-01-01 09:00 +0900
3782 3786 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "UTC")|isodate}\n'
3783 3787 1970-01-01 00:00 +0000
3784 3788 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n'
3785 3789 hg: parse error: localdate expects a timezone
3786 3790 [255]
3787 3791 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n'
3788 3792 1970-01-01 02:00 +0200
3789 3793 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n'
3790 3794 1970-01-01 00:00 +0000
3791 3795 $ TZ=JST-09 hg log -r0 -T '{localdate(date, 0)|isodate}\n'
3792 3796 1970-01-01 00:00 +0000
3793 3797 $ hg log -r0 -T '{localdate(date, "invalid")|isodate}\n'
3794 3798 hg: parse error: localdate expects a timezone
3795 3799 [255]
3796 3800 $ hg log -r0 -T '{localdate(date, date)|isodate}\n'
3797 3801 hg: parse error: localdate expects a timezone
3798 3802 [255]
3799 3803
3800 3804 Test shortest(node) function:
3801 3805
3802 3806 $ echo b > b
3803 3807 $ hg ci -qAm b
3804 3808 $ hg log --template '{shortest(node)}\n'
3805 3809 e777
3806 3810 bcc7
3807 3811 f776
3808 3812 $ hg log --template '{shortest(node, 10)}\n'
3809 3813 e777603221
3810 3814 bcc7ff960b
3811 3815 f7769ec2ab
3812 3816 $ hg log --template '{node|shortest}\n' -l1
3813 3817 e777
3814 3818
3815 3819 $ hg log -r 0 -T '{shortest(node, "1{"0"}")}\n'
3816 3820 f7769ec2ab
3817 3821 $ hg log -r 0 -T '{shortest(node, "not an int")}\n'
3818 3822 hg: parse error: shortest() expects an integer minlength
3819 3823 [255]
3820 3824
3821 3825 $ hg log -r 'wdir()' -T '{node|shortest}\n'
3822 3826 ffff
3823 3827
3824 3828 $ cd ..
3825 3829
3826 3830 Test shortest(node) with the repo having short hash collision:
3827 3831
3828 3832 $ hg init hashcollision
3829 3833 $ cd hashcollision
3830 3834 $ cat <<EOF >> .hg/hgrc
3831 3835 > [experimental]
3832 3836 > evolution.createmarkers=True
3833 3837 > EOF
3834 3838 $ echo 0 > a
3835 3839 $ hg ci -qAm 0
3836 3840 $ for i in 17 129 248 242 480 580 617 1057 2857 4025; do
3837 3841 > hg up -q 0
3838 3842 > echo $i > a
3839 3843 > hg ci -qm $i
3840 3844 > done
3841 3845 $ hg up -q null
3842 3846 $ hg log -r0: -T '{rev}:{node}\n'
3843 3847 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
3844 3848 1:11424df6dc1dd4ea255eae2b58eaca7831973bbc
3845 3849 2:11407b3f1b9c3e76a79c1ec5373924df096f0499
3846 3850 3:11dd92fe0f39dfdaacdaa5f3997edc533875cfc4
3847 3851 4:10776689e627b465361ad5c296a20a487e153ca4
3848 3852 5:a00be79088084cb3aff086ab799f8790e01a976b
3849 3853 6:a0b0acd79b4498d0052993d35a6a748dd51d13e6
3850 3854 7:a0457b3450b8e1b778f1163b31a435802987fe5d
3851 3855 8:c56256a09cd28e5764f32e8e2810d0f01e2e357a
3852 3856 9:c5623987d205cd6d9d8389bfc40fff9dbb670b48
3853 3857 10:c562ddd9c94164376c20b86b0b4991636a3bf84f
3854 3858 $ hg debugobsolete a00be79088084cb3aff086ab799f8790e01a976b
3855 3859 obsoleted 1 changesets
3856 3860 $ hg debugobsolete c5623987d205cd6d9d8389bfc40fff9dbb670b48
3857 3861 obsoleted 1 changesets
3858 3862 $ hg debugobsolete c562ddd9c94164376c20b86b0b4991636a3bf84f
3859 3863 obsoleted 1 changesets
3860 3864
3861 3865 nodes starting with '11' (we don't have the revision number '11' though)
3862 3866
3863 3867 $ hg log -r 1:3 -T '{rev}:{shortest(node, 0)}\n'
3864 3868 1:1142
3865 3869 2:1140
3866 3870 3:11d
3867 3871
3868 3872 '5:a00' is hidden, but still we have two nodes starting with 'a0'
3869 3873
3870 3874 $ hg log -r 6:7 -T '{rev}:{shortest(node, 0)}\n'
3871 3875 6:a0b
3872 3876 7:a04
3873 3877
3874 3878 node '10' conflicts with the revision number '10' even if it is hidden
3875 3879 (we could exclude hidden revision numbers, but currently we don't)
3876 3880
3877 3881 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n'
3878 3882 4:107
3879 3883 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
3880 3884 4:107
3881 3885
3882 3886 node 'c562' should be unique if the other 'c562' nodes are hidden
3883 3887 (but we don't try the slow path to filter out hidden nodes for now)
3884 3888
3885 3889 $ hg log -r 8 -T '{rev}:{node|shortest}\n'
3886 3890 8:c5625
3887 3891 $ hg log -r 8:10 -T '{rev}:{node|shortest}\n' --hidden
3888 3892 8:c5625
3889 3893 9:c5623
3890 3894 10:c562d
3891 3895
3892 3896 $ cd ..
3893 3897
3894 3898 Test pad function
3895 3899
3896 3900 $ cd r
3897 3901
3898 3902 $ hg log --template '{pad(rev, 20)} {author|user}\n'
3899 3903 2 test
3900 3904 1 {node|short}
3901 3905 0 test
3902 3906
3903 3907 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
3904 3908 2 test
3905 3909 1 {node|short}
3906 3910 0 test
3907 3911
3908 3912 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
3909 3913 2------------------- test
3910 3914 1------------------- {node|short}
3911 3915 0------------------- test
3912 3916
3913 3917 Test template string in pad function
3914 3918
3915 3919 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
3916 3920 {0} test
3917 3921
3918 3922 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
3919 3923 \{rev} test
3920 3924
3921 3925 Test width argument passed to pad function
3922 3926
3923 3927 $ hg log -r 0 -T '{pad(rev, "1{"0"}")} {author|user}\n'
3924 3928 0 test
3925 3929 $ hg log -r 0 -T '{pad(rev, "not an int")}\n'
3926 3930 hg: parse error: pad() expects an integer width
3927 3931 [255]
3928 3932
3929 3933 Test invalid fillchar passed to pad function
3930 3934
3931 3935 $ hg log -r 0 -T '{pad(rev, 10, "")}\n'
3932 3936 hg: parse error: pad() expects a single fill character
3933 3937 [255]
3934 3938 $ hg log -r 0 -T '{pad(rev, 10, "--")}\n'
3935 3939 hg: parse error: pad() expects a single fill character
3936 3940 [255]
3937 3941
3938 3942 Test boolean argument passed to pad function
3939 3943
3940 3944 no crash
3941 3945
3942 3946 $ hg log -r 0 -T '{pad(rev, 10, "-", "f{"oo"}")}\n'
3943 3947 ---------0
3944 3948
3945 3949 string/literal
3946 3950
3947 3951 $ hg log -r 0 -T '{pad(rev, 10, "-", "false")}\n'
3948 3952 ---------0
3949 3953 $ hg log -r 0 -T '{pad(rev, 10, "-", false)}\n'
3950 3954 0---------
3951 3955 $ hg log -r 0 -T '{pad(rev, 10, "-", "")}\n'
3952 3956 0---------
3953 3957
3954 3958 unknown keyword is evaluated to ''
3955 3959
3956 3960 $ hg log -r 0 -T '{pad(rev, 10, "-", unknownkeyword)}\n'
3957 3961 0---------
3958 3962
3959 3963 Test separate function
3960 3964
3961 3965 $ hg log -r 0 -T '{separate("-", "", "a", "b", "", "", "c", "")}\n'
3962 3966 a-b-c
3963 3967 $ hg log -r 0 -T '{separate(" ", "{rev}:{node|short}", author|user, branch)}\n'
3964 3968 0:f7769ec2ab97 test default
3965 3969 $ hg log -r 0 --color=always -T '{separate(" ", "a", label(red, "b"), "c", label(red, ""), "d")}\n'
3966 3970 a \x1b[0;31mb\x1b[0m c d (esc)
3967 3971
3968 3972 Test boolean expression/literal passed to if function
3969 3973
3970 3974 $ hg log -r 0 -T '{if(rev, "rev 0 is True")}\n'
3971 3975 rev 0 is True
3972 3976 $ hg log -r 0 -T '{if(0, "literal 0 is True as well")}\n'
3973 3977 literal 0 is True as well
3974 3978 $ hg log -r 0 -T '{if("", "", "empty string is False")}\n'
3975 3979 empty string is False
3976 3980 $ hg log -r 0 -T '{if(revset(r"0 - 0"), "", "empty list is False")}\n'
3977 3981 empty list is False
3978 3982 $ hg log -r 0 -T '{if(true, "true is True")}\n'
3979 3983 true is True
3980 3984 $ hg log -r 0 -T '{if(false, "", "false is False")}\n'
3981 3985 false is False
3982 3986 $ hg log -r 0 -T '{if("false", "non-empty string is True")}\n'
3983 3987 non-empty string is True
3984 3988
3985 3989 Test ifcontains function
3986 3990
3987 3991 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
3988 3992 2 is in the string
3989 3993 1 is not
3990 3994 0 is in the string
3991 3995
3992 3996 $ hg log -T '{rev} {ifcontains(rev, "2 two{" 0"}", "is in the string", "is not")}\n'
3993 3997 2 is in the string
3994 3998 1 is not
3995 3999 0 is in the string
3996 4000
3997 4001 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
3998 4002 2 did not add a
3999 4003 1 did not add a
4000 4004 0 added a
4001 4005
4002 4006 $ hg log --debug -T '{rev}{ifcontains(1, parents, " is parent of 1")}\n'
4003 4007 2 is parent of 1
4004 4008 1
4005 4009 0
4006 4010
4007 4011 Test revset function
4008 4012
4009 4013 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
4010 4014 2 current rev
4011 4015 1 not current rev
4012 4016 0 not current rev
4013 4017
4014 4018 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
4015 4019 2 match rev
4016 4020 1 match rev
4017 4021 0 not match rev
4018 4022
4019 4023 $ hg log -T '{ifcontains(desc, revset(":"), "", "type not match")}\n' -l1
4020 4024 type not match
4021 4025
4022 4026 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
4023 4027 2 Parents: 1
4024 4028 1 Parents: 0
4025 4029 0 Parents:
4026 4030
4027 4031 $ cat >> .hg/hgrc <<EOF
4028 4032 > [revsetalias]
4029 4033 > myparents(\$1) = parents(\$1)
4030 4034 > EOF
4031 4035 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
4032 4036 2 Parents: 1
4033 4037 1 Parents: 0
4034 4038 0 Parents:
4035 4039
4036 4040 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
4037 4041 Rev: 2
4038 4042 Ancestor: 0
4039 4043 Ancestor: 1
4040 4044 Ancestor: 2
4041 4045
4042 4046 Rev: 1
4043 4047 Ancestor: 0
4044 4048 Ancestor: 1
4045 4049
4046 4050 Rev: 0
4047 4051 Ancestor: 0
4048 4052
4049 4053 $ hg log --template '{revset("TIP"|lower)}\n' -l1
4050 4054 2
4051 4055
4052 4056 $ hg log -T '{revset("%s", "t{"ip"}")}\n' -l1
4053 4057 2
4054 4058
4055 4059 a list template is evaluated for each item of revset/parents
4056 4060
4057 4061 $ hg log -T '{rev} p: {revset("p1(%s)", rev) % "{rev}:{node|short}"}\n'
4058 4062 2 p: 1:bcc7ff960b8e
4059 4063 1 p: 0:f7769ec2ab97
4060 4064 0 p:
4061 4065
4062 4066 $ hg log --debug -T '{rev} p:{parents % " {rev}:{node|short}"}\n'
4063 4067 2 p: 1:bcc7ff960b8e -1:000000000000
4064 4068 1 p: 0:f7769ec2ab97 -1:000000000000
4065 4069 0 p: -1:000000000000 -1:000000000000
4066 4070
4067 4071 therefore, 'revcache' should be recreated for each rev
4068 4072
4069 4073 $ hg log -T '{rev} {file_adds}\np {revset("p1(%s)", rev) % "{file_adds}"}\n'
4070 4074 2 aa b
4071 4075 p
4072 4076 1
4073 4077 p a
4074 4078 0 a
4075 4079 p
4076 4080
4077 4081 $ hg log --debug -T '{rev} {file_adds}\np {parents % "{file_adds}"}\n'
4078 4082 2 aa b
4079 4083 p
4080 4084 1
4081 4085 p a
4082 4086 0 a
4083 4087 p
4084 4088
4085 4089 a revset item must be evaluated as an integer revision, not an offset from tip
4086 4090
4087 4091 $ hg log -l 1 -T '{revset("null") % "{rev}:{node|short}"}\n'
4088 4092 -1:000000000000
4089 4093 $ hg log -l 1 -T '{revset("%s", "null") % "{rev}:{node|short}"}\n'
4090 4094 -1:000000000000
4091 4095
4092 4096 join() should pick '{rev}' from revset items:
4093 4097
4094 4098 $ hg log -R ../a -T '{join(revset("parents(%d)", rev), ", ")}\n' -r6
4095 4099 4, 5
4096 4100
4097 4101 on the other hand, parents are formatted as '{rev}:{node|formatnode}' by
4098 4102 default. join() should agree with the default formatting:
4099 4103
4100 4104 $ hg log -R ../a -T '{join(parents, ", ")}\n' -r6
4101 4105 5:13207e5a10d9, 4:bbe44766e73d
4102 4106
4103 4107 $ hg log -R ../a -T '{join(parents, ",\n")}\n' -r6 --debug
4104 4108 5:13207e5a10d9fd28ec424934298e176197f2c67f,
4105 4109 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
4106 4110
4107 4111 Invalid arguments passed to revset()
4108 4112
4109 4113 $ hg log -T '{revset("%whatever", 0)}\n'
4110 4114 hg: parse error: unexpected revspec format character w
4111 4115 [255]
4112 4116 $ hg log -T '{revset("%lwhatever", files)}\n'
4113 4117 hg: parse error: unexpected revspec format character w
4114 4118 [255]
4115 4119 $ hg log -T '{revset("%s %s", 0)}\n'
4116 4120 hg: parse error: missing argument for revspec
4117 4121 [255]
4118 4122 $ hg log -T '{revset("", 0)}\n'
4119 4123 hg: parse error: too many revspec arguments specified
4120 4124 [255]
4121 4125 $ hg log -T '{revset("%s", 0, 1)}\n'
4122 4126 hg: parse error: too many revspec arguments specified
4123 4127 [255]
4124 4128 $ hg log -T '{revset("%", 0)}\n'
4125 4129 hg: parse error: incomplete revspec format character
4126 4130 [255]
4127 4131 $ hg log -T '{revset("%l", 0)}\n'
4128 4132 hg: parse error: incomplete revspec format character
4129 4133 [255]
4130 4134 $ hg log -T '{revset("%d", 'foo')}\n'
4131 4135 hg: parse error: invalid argument for revspec
4132 4136 [255]
4133 4137 $ hg log -T '{revset("%ld", files)}\n'
4134 4138 hg: parse error: invalid argument for revspec
4135 4139 [255]
4136 4140 $ hg log -T '{revset("%ls", 0)}\n'
4137 4141 hg: parse error: invalid argument for revspec
4138 4142 [255]
4139 4143 $ hg log -T '{revset("%b", 'foo')}\n'
4140 4144 hg: parse error: invalid argument for revspec
4141 4145 [255]
4142 4146 $ hg log -T '{revset("%lb", files)}\n'
4143 4147 hg: parse error: invalid argument for revspec
4144 4148 [255]
4145 4149 $ hg log -T '{revset("%r", 0)}\n'
4146 4150 hg: parse error: invalid argument for revspec
4147 4151 [255]
4148 4152
4149 4153 Test files function
4150 4154
4151 4155 $ hg log -T "{rev}\n{join(files('*'), '\n')}\n"
4152 4156 2
4153 4157 a
4154 4158 aa
4155 4159 b
4156 4160 1
4157 4161 a
4158 4162 0
4159 4163 a
4160 4164
4161 4165 $ hg log -T "{rev}\n{join(files('aa'), '\n')}\n"
4162 4166 2
4163 4167 aa
4164 4168 1
4165 4169
4166 4170 0
4167 4171
4168 4172
4169 4173 Test relpath function
4170 4174
4171 4175 $ hg log -r0 -T '{files % "{file|relpath}\n"}'
4172 4176 a
4173 4177 $ cd ..
4174 4178 $ hg log -R r -r0 -T '{files % "{file|relpath}\n"}'
4175 4179 r/a
4176 4180 $ cd r
4177 4181
4178 4182 Test active bookmark templating
4179 4183
4180 4184 $ hg book foo
4181 4185 $ hg book bar
4182 4186 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
4183 4187 2 bar* foo
4184 4188 1
4185 4189 0
4186 4190 $ hg log --template "{rev} {activebookmark}\n"
4187 4191 2 bar
4188 4192 1
4189 4193 0
4190 4194 $ hg bookmarks --inactive bar
4191 4195 $ hg log --template "{rev} {activebookmark}\n"
4192 4196 2
4193 4197 1
4194 4198 0
4195 4199 $ hg book -r1 baz
4196 4200 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
4197 4201 2 bar foo
4198 4202 1 baz
4199 4203 0
4200 4204 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
4201 4205 2 t
4202 4206 1 f
4203 4207 0 f
4204 4208
4205 4209 Test namespaces dict
4206 4210
4207 4211 $ hg --config extensions.revnamesext=$TESTDIR/revnamesext.py log -T '{rev}\n{namespaces % " {namespace} color={colorname} builtin={builtin}\n {join(names, ",")}\n"}\n'
4208 4212 2
4209 4213 bookmarks color=bookmark builtin=True
4210 4214 bar,foo
4211 4215 tags color=tag builtin=True
4212 4216 tip
4213 4217 branches color=branch builtin=True
4214 4218 text.{rev}
4215 4219 revnames color=revname builtin=False
4216 4220 r2
4217 4221
4218 4222 1
4219 4223 bookmarks color=bookmark builtin=True
4220 4224 baz
4221 4225 tags color=tag builtin=True
4222 4226
4223 4227 branches color=branch builtin=True
4224 4228 text.{rev}
4225 4229 revnames color=revname builtin=False
4226 4230 r1
4227 4231
4228 4232 0
4229 4233 bookmarks color=bookmark builtin=True
4230 4234
4231 4235 tags color=tag builtin=True
4232 4236
4233 4237 branches color=branch builtin=True
4234 4238 default
4235 4239 revnames color=revname builtin=False
4236 4240 r0
4237 4241
4238 4242 $ hg log -r2 -T '{namespaces % "{namespace}: {names}\n"}'
4239 4243 bookmarks: bar foo
4240 4244 tags: tip
4241 4245 branches: text.{rev}
4242 4246 $ hg log -r2 -T '{namespaces % "{namespace}:\n{names % " {name}\n"}"}'
4243 4247 bookmarks:
4244 4248 bar
4245 4249 foo
4246 4250 tags:
4247 4251 tip
4248 4252 branches:
4249 4253 text.{rev}
4250 4254 $ hg log -r2 -T '{get(namespaces, "bookmarks") % "{name}\n"}'
4251 4255 bar
4252 4256 foo
4253 4257 $ hg log -r2 -T '{namespaces.bookmarks % "{bookmark}\n"}'
4254 4258 bar
4255 4259 foo
4256 4260
4257 4261 Test stringify on sub expressions
4258 4262
4259 4263 $ cd ..
4260 4264 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
4261 4265 fourth, second, third
4262 4266 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
4263 4267 abc
4264 4268
4265 4269 Test splitlines
4266 4270
4267 4271 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
4268 4272 @ foo Modify, add, remove, rename
4269 4273 |
4270 4274 o foo future
4271 4275 |
4272 4276 o foo third
4273 4277 |
4274 4278 o foo second
4275 4279
4276 4280 o foo merge
4277 4281 |\
4278 4282 | o foo new head
4279 4283 | |
4280 4284 o | foo new branch
4281 4285 |/
4282 4286 o foo no user, no domain
4283 4287 |
4284 4288 o foo no person
4285 4289 |
4286 4290 o foo other 1
4287 4291 | foo other 2
4288 4292 | foo
4289 4293 | foo other 3
4290 4294 o foo line 1
4291 4295 foo line 2
4292 4296
4293 4297 $ hg log -R a -r0 -T '{desc|splitlines}\n'
4294 4298 line 1 line 2
4295 4299 $ hg log -R a -r0 -T '{join(desc|splitlines, "|")}\n'
4296 4300 line 1|line 2
4297 4301
4298 4302 Test startswith
4299 4303 $ hg log -Gv -R a --template "{startswith(desc)}"
4300 4304 hg: parse error: startswith expects two arguments
4301 4305 [255]
4302 4306
4303 4307 $ hg log -Gv -R a --template "{startswith('line', desc)}"
4304 4308 @
4305 4309 |
4306 4310 o
4307 4311 |
4308 4312 o
4309 4313 |
4310 4314 o
4311 4315
4312 4316 o
4313 4317 |\
4314 4318 | o
4315 4319 | |
4316 4320 o |
4317 4321 |/
4318 4322 o
4319 4323 |
4320 4324 o
4321 4325 |
4322 4326 o
4323 4327 |
4324 4328 o line 1
4325 4329 line 2
4326 4330
4327 4331 Test bad template with better error message
4328 4332
4329 4333 $ hg log -Gv -R a --template '{desc|user()}'
4330 4334 hg: parse error: expected a symbol, got 'func'
4331 4335 [255]
4332 4336
4333 4337 Test word function (including index out of bounds graceful failure)
4334 4338
4335 4339 $ hg log -Gv -R a --template "{word('1', desc)}"
4336 4340 @ add,
4337 4341 |
4338 4342 o
4339 4343 |
4340 4344 o
4341 4345 |
4342 4346 o
4343 4347
4344 4348 o
4345 4349 |\
4346 4350 | o head
4347 4351 | |
4348 4352 o | branch
4349 4353 |/
4350 4354 o user,
4351 4355 |
4352 4356 o person
4353 4357 |
4354 4358 o 1
4355 4359 |
4356 4360 o 1
4357 4361
4358 4362
4359 4363 Test word third parameter used as splitter
4360 4364
4361 4365 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
4362 4366 @ M
4363 4367 |
4364 4368 o future
4365 4369 |
4366 4370 o third
4367 4371 |
4368 4372 o sec
4369 4373
4370 4374 o merge
4371 4375 |\
4372 4376 | o new head
4373 4377 | |
4374 4378 o | new branch
4375 4379 |/
4376 4380 o n
4377 4381 |
4378 4382 o n
4379 4383 |
4380 4384 o
4381 4385 |
4382 4386 o line 1
4383 4387 line 2
4384 4388
4385 4389 Test word error messages for not enough and too many arguments
4386 4390
4387 4391 $ hg log -Gv -R a --template "{word('0')}"
4388 4392 hg: parse error: word expects two or three arguments, got 1
4389 4393 [255]
4390 4394
4391 4395 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
4392 4396 hg: parse error: word expects two or three arguments, got 7
4393 4397 [255]
4394 4398
4395 4399 Test word for integer literal
4396 4400
4397 4401 $ hg log -R a --template "{word(2, desc)}\n" -r0
4398 4402 line
4399 4403
4400 4404 Test word for invalid numbers
4401 4405
4402 4406 $ hg log -Gv -R a --template "{word('a', desc)}"
4403 4407 hg: parse error: word expects an integer index
4404 4408 [255]
4405 4409
4406 4410 Test word for out of range
4407 4411
4408 4412 $ hg log -R a --template "{word(10000, desc)}"
4409 4413 $ hg log -R a --template "{word(-10000, desc)}"
4410 4414
4411 4415 Test indent and not adding to empty lines
4412 4416
4413 4417 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
4414 4418 -----
4415 4419 > line 1
4416 4420 >> line 2
4417 4421 -----
4418 4422 > other 1
4419 4423 >> other 2
4420 4424
4421 4425 >> other 3
4422 4426
4423 4427 Test with non-strings like dates
4424 4428
4425 4429 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
4426 4430 1200000.00
4427 4431 1300000.00
4428 4432
4429 4433 Test broken string escapes:
4430 4434
4431 4435 $ hg log -T "bogus\\" -R a
4432 4436 hg: parse error: trailing \ in string
4433 4437 [255]
4434 4438 $ hg log -T "\\xy" -R a
4435 4439 hg: parse error: invalid \x escape
4436 4440 [255]
4437 4441
4438 4442 json filter should escape HTML tags so that the output can be embedded in hgweb:
4439 4443
4440 4444 $ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1
4441 4445 "\u003cfoo@example.org\u003e"
4442 4446
4443 4447 Templater supports aliases of symbol and func() styles:
4444 4448
4445 4449 $ hg clone -q a aliases
4446 4450 $ cd aliases
4447 4451 $ cat <<EOF >> .hg/hgrc
4448 4452 > [templatealias]
4449 4453 > r = rev
4450 4454 > rn = "{r}:{node|short}"
4451 4455 > status(c, files) = files % "{c} {file}\n"
4452 4456 > utcdate(d) = localdate(d, "UTC")
4453 4457 > EOF
4454 4458
4455 4459 $ hg debugtemplate -vr0 '{rn} {utcdate(date)|isodate}\n'
4456 4460 (template
4457 4461 (symbol 'rn')
4458 4462 (string ' ')
4459 4463 (|
4460 4464 (func
4461 4465 (symbol 'utcdate')
4462 4466 (symbol 'date'))
4463 4467 (symbol 'isodate'))
4464 4468 (string '\n'))
4465 4469 * expanded:
4466 4470 (template
4467 4471 (template
4468 4472 (symbol 'rev')
4469 4473 (string ':')
4470 4474 (|
4471 4475 (symbol 'node')
4472 4476 (symbol 'short')))
4473 4477 (string ' ')
4474 4478 (|
4475 4479 (func
4476 4480 (symbol 'localdate')
4477 4481 (list
4478 4482 (symbol 'date')
4479 4483 (string 'UTC')))
4480 4484 (symbol 'isodate'))
4481 4485 (string '\n'))
4482 4486 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4483 4487
4484 4488 $ hg debugtemplate -vr0 '{status("A", file_adds)}'
4485 4489 (template
4486 4490 (func
4487 4491 (symbol 'status')
4488 4492 (list
4489 4493 (string 'A')
4490 4494 (symbol 'file_adds'))))
4491 4495 * expanded:
4492 4496 (template
4493 4497 (%
4494 4498 (symbol 'file_adds')
4495 4499 (template
4496 4500 (string 'A')
4497 4501 (string ' ')
4498 4502 (symbol 'file')
4499 4503 (string '\n'))))
4500 4504 A a
4501 4505
4502 4506 A unary function alias can be called as a filter:
4503 4507
4504 4508 $ hg debugtemplate -vr0 '{date|utcdate|isodate}\n'
4505 4509 (template
4506 4510 (|
4507 4511 (|
4508 4512 (symbol 'date')
4509 4513 (symbol 'utcdate'))
4510 4514 (symbol 'isodate'))
4511 4515 (string '\n'))
4512 4516 * expanded:
4513 4517 (template
4514 4518 (|
4515 4519 (func
4516 4520 (symbol 'localdate')
4517 4521 (list
4518 4522 (symbol 'date')
4519 4523 (string 'UTC')))
4520 4524 (symbol 'isodate'))
4521 4525 (string '\n'))
4522 4526 1970-01-12 13:46 +0000
4523 4527
4524 4528 Aliases should be applied only to command arguments and templates in hgrc.
4525 4529 Otherwise, our stock styles and web templates could be corrupted:
4526 4530
4527 4531 $ hg log -r0 -T '{rn} {utcdate(date)|isodate}\n'
4528 4532 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4529 4533
4530 4534 $ hg log -r0 --config ui.logtemplate='"{rn} {utcdate(date)|isodate}\n"'
4531 4535 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4532 4536
4533 4537 $ cat <<EOF > tmpl
4534 4538 > changeset = 'nothing expanded:{rn}\n'
4535 4539 > EOF
4536 4540 $ hg log -r0 --style ./tmpl
4537 4541 nothing expanded:
4538 4542
4539 4543 Aliases in formatter:
4540 4544
4541 4545 $ hg branches -T '{pad(branch, 7)} {rn}\n'
4542 4546 default 6:d41e714fe50d
4543 4547 foo 4:bbe44766e73d
4544 4548
4545 4549 Aliases should honor HGPLAIN:
4546 4550
4547 4551 $ HGPLAIN= hg log -r0 -T 'nothing expanded:{rn}\n'
4548 4552 nothing expanded:
4549 4553 $ HGPLAINEXCEPT=templatealias hg log -r0 -T '{rn}\n'
4550 4554 0:1e4e1b8f71e0
4551 4555
4552 4556 Unparsable alias:
4553 4557
4554 4558 $ hg debugtemplate --config templatealias.bad='x(' -v '{bad}'
4555 4559 (template
4556 4560 (symbol 'bad'))
4557 4561 abort: bad definition of template alias "bad": at 2: not a prefix: end
4558 4562 [255]
4559 4563 $ hg log --config templatealias.bad='x(' -T '{bad}'
4560 4564 abort: bad definition of template alias "bad": at 2: not a prefix: end
4561 4565 [255]
4562 4566
4563 4567 $ cd ..
4564 4568
4565 4569 Set up repository for non-ascii encoding tests:
4566 4570
4567 4571 $ hg init nonascii
4568 4572 $ cd nonascii
4569 4573 $ $PYTHON <<EOF
4570 4574 > open('latin1', 'w').write('\xe9')
4571 4575 > open('utf-8', 'w').write('\xc3\xa9')
4572 4576 > EOF
4573 4577 $ HGENCODING=utf-8 hg branch -q `cat utf-8`
4574 4578 $ HGENCODING=utf-8 hg ci -qAm "non-ascii branch: `cat utf-8`" utf-8
4575 4579
4576 4580 json filter should try round-trip conversion to utf-8:
4577 4581
4578 4582 $ HGENCODING=ascii hg log -T "{branch|json}\n" -r0
4579 4583 "\u00e9"
4580 4584 $ HGENCODING=ascii hg log -T "{desc|json}\n" -r0
4581 4585 "non-ascii branch: \u00e9"
4582 4586
4583 4587 json filter takes input as utf-8b:
4584 4588
4585 4589 $ HGENCODING=ascii hg log -T "{'`cat utf-8`'|json}\n" -l1
4586 4590 "\u00e9"
4587 4591 $ HGENCODING=ascii hg log -T "{'`cat latin1`'|json}\n" -l1
4588 4592 "\udce9"
4589 4593
4590 4594 utf8 filter:
4591 4595
4592 4596 $ HGENCODING=ascii hg log -T "round-trip: {branch|utf8|hex}\n" -r0
4593 4597 round-trip: c3a9
4594 4598 $ HGENCODING=latin1 hg log -T "decoded: {'`cat latin1`'|utf8|hex}\n" -l1
4595 4599 decoded: c3a9
4596 4600 $ HGENCODING=ascii hg log -T "replaced: {'`cat latin1`'|utf8|hex}\n" -l1
4597 4601 abort: decoding near * (glob)
4598 4602 [255]
4599 4603 $ hg log -T "invalid type: {rev|utf8}\n" -r0
4600 4604 abort: template filter 'utf8' is not compatible with keyword 'rev'
4601 4605 [255]
4602 4606
4603 4607 pad width:
4604 4608
4605 4609 $ HGENCODING=utf-8 hg debugtemplate "{pad('`cat utf-8`', 2, '-')}\n"
4606 4610 \xc3\xa9- (esc)
4607 4611
4608 4612 $ cd ..
4609 4613
4610 4614 Test that template function in extension is registered as expected
4611 4615
4612 4616 $ cd a
4613 4617
4614 4618 $ cat <<EOF > $TESTTMP/customfunc.py
4615 4619 > from mercurial import registrar
4616 4620 >
4617 4621 > templatefunc = registrar.templatefunc()
4618 4622 >
4619 4623 > @templatefunc('custom()')
4620 4624 > def custom(context, mapping, args):
4621 4625 > return 'custom'
4622 4626 > EOF
4623 4627 $ cat <<EOF > .hg/hgrc
4624 4628 > [extensions]
4625 4629 > customfunc = $TESTTMP/customfunc.py
4626 4630 > EOF
4627 4631
4628 4632 $ hg log -r . -T "{custom()}\n" --config customfunc.enabled=true
4629 4633 custom
4630 4634
4631 4635 $ cd ..
4632 4636
4633 4637 Test 'graphwidth' in 'hg log' on various topologies. The key here is that the
4634 4638 printed graphwidths 3, 5, 7, etc. should all line up in their respective
4635 4639 columns. We don't care about other aspects of the graph rendering here.
4636 4640
4637 4641 $ hg init graphwidth
4638 4642 $ cd graphwidth
4639 4643
4640 4644 $ wrappabletext="a a a a a a a a a a a a"
4641 4645
4642 4646 $ printf "first\n" > file
4643 4647 $ hg add file
4644 4648 $ hg commit -m "$wrappabletext"
4645 4649
4646 4650 $ printf "first\nsecond\n" > file
4647 4651 $ hg commit -m "$wrappabletext"
4648 4652
4649 4653 $ hg checkout 0
4650 4654 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4651 4655 $ printf "third\nfirst\n" > file
4652 4656 $ hg commit -m "$wrappabletext"
4653 4657 created new head
4654 4658
4655 4659 $ hg merge
4656 4660 merging file
4657 4661 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
4658 4662 (branch merge, don't forget to commit)
4659 4663
4660 4664 $ hg log --graph -T "{graphwidth}"
4661 4665 @ 3
4662 4666 |
4663 4667 | @ 5
4664 4668 |/
4665 4669 o 3
4666 4670
4667 4671 $ hg commit -m "$wrappabletext"
4668 4672
4669 4673 $ hg log --graph -T "{graphwidth}"
4670 4674 @ 5
4671 4675 |\
4672 4676 | o 5
4673 4677 | |
4674 4678 o | 5
4675 4679 |/
4676 4680 o 3
4677 4681
4678 4682
4679 4683 $ hg checkout 0
4680 4684 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4681 4685 $ printf "third\nfirst\nsecond\n" > file
4682 4686 $ hg commit -m "$wrappabletext"
4683 4687 created new head
4684 4688
4685 4689 $ hg log --graph -T "{graphwidth}"
4686 4690 @ 3
4687 4691 |
4688 4692 | o 7
4689 4693 | |\
4690 4694 +---o 7
4691 4695 | |
4692 4696 | o 5
4693 4697 |/
4694 4698 o 3
4695 4699
4696 4700
4697 4701 $ hg log --graph -T "{graphwidth}" -r 3
4698 4702 o 5
4699 4703 |\
4700 4704 ~ ~
4701 4705
4702 4706 $ hg log --graph -T "{graphwidth}" -r 1
4703 4707 o 3
4704 4708 |
4705 4709 ~
4706 4710
4707 4711 $ hg merge
4708 4712 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4709 4713 (branch merge, don't forget to commit)
4710 4714 $ hg commit -m "$wrappabletext"
4711 4715
4712 4716 $ printf "seventh\n" >> file
4713 4717 $ hg commit -m "$wrappabletext"
4714 4718
4715 4719 $ hg log --graph -T "{graphwidth}"
4716 4720 @ 3
4717 4721 |
4718 4722 o 5
4719 4723 |\
4720 4724 | o 5
4721 4725 | |
4722 4726 o | 7
4723 4727 |\ \
4724 4728 | o | 7
4725 4729 | |/
4726 4730 o / 5
4727 4731 |/
4728 4732 o 3
4729 4733
4730 4734
4731 4735 The point of graphwidth is to allow wrapping that accounts for the space taken
4732 4736 by the graph.
4733 4737
4734 4738 $ COLUMNS=10 hg log --graph -T "{fill(desc, termwidth - graphwidth)}"
4735 4739 @ a a a a
4736 4740 | a a a a
4737 4741 | a a a a
4738 4742 o a a a
4739 4743 |\ a a a
4740 4744 | | a a a
4741 4745 | | a a a
4742 4746 | o a a a
4743 4747 | | a a a
4744 4748 | | a a a
4745 4749 | | a a a
4746 4750 o | a a
4747 4751 |\ \ a a
4748 4752 | | | a a
4749 4753 | | | a a
4750 4754 | | | a a
4751 4755 | | | a a
4752 4756 | o | a a
4753 4757 | |/ a a
4754 4758 | | a a
4755 4759 | | a a
4756 4760 | | a a
4757 4761 | | a a
4758 4762 o | a a a
4759 4763 |/ a a a
4760 4764 | a a a
4761 4765 | a a a
4762 4766 o a a a a
4763 4767 a a a a
4764 4768 a a a a
4765 4769
4766 4770 Something tricky happens when there are elided nodes; the next drawn row of
4767 4771 edges can be more than one column wider, but the graph width only increases by
4768 4772 one column. The remaining columns are added in between the nodes.
4769 4773
4770 4774 $ hg log --graph -T "{graphwidth}" -r "0|2|4|5"
4771 4775 o 5
4772 4776 |\
4773 4777 | \
4774 4778 | :\
4775 4779 o : : 7
4776 4780 :/ /
4777 4781 : o 5
4778 4782 :/
4779 4783 o 3
4780 4784
4781 4785
4782 4786 $ cd ..
4783 4787
General Comments 0
You need to be logged in to leave comments. Login now