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