##// END OF EJS Templates
templater: handle a missing value correctly...
Ross Lagerwall -
r17334:39c01f8e stable
parent child Browse files
Show More
@@ -1,392 +1,394 b''
1 1 # templater.py - template expansion for output
2 2 #
3 3 # Copyright 2005, 2006 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 i18n import _
9 9 import sys, os
10 10 import util, config, templatefilters, parser, error
11 11
12 12 # template parsing
13 13
14 14 elements = {
15 15 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
16 16 ",": (2, None, ("list", 2)),
17 17 "|": (5, None, ("|", 5)),
18 18 "%": (6, None, ("%", 6)),
19 19 ")": (0, None, None),
20 20 "symbol": (0, ("symbol",), None),
21 21 "string": (0, ("string",), None),
22 22 "end": (0, None, None),
23 23 }
24 24
25 25 def tokenizer(data):
26 26 program, start, end = data
27 27 pos = start
28 28 while pos < end:
29 29 c = program[pos]
30 30 if c.isspace(): # skip inter-token whitespace
31 31 pass
32 32 elif c in "(,)%|": # handle simple operators
33 33 yield (c, None, pos)
34 34 elif (c in '"\'' or c == 'r' and
35 35 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
36 36 if c == 'r':
37 37 pos += 1
38 38 c = program[pos]
39 39 decode = lambda x: x
40 40 else:
41 41 decode = lambda x: x.decode('string-escape')
42 42 pos += 1
43 43 s = pos
44 44 while pos < end: # find closing quote
45 45 d = program[pos]
46 46 if d == '\\': # skip over escaped characters
47 47 pos += 2
48 48 continue
49 49 if d == c:
50 50 yield ('string', decode(program[s:pos]), s)
51 51 break
52 52 pos += 1
53 53 else:
54 54 raise error.ParseError(_("unterminated string"), s)
55 55 elif c.isalnum() or c in '_':
56 56 s = pos
57 57 pos += 1
58 58 while pos < end: # find end of symbol
59 59 d = program[pos]
60 60 if not (d.isalnum() or d == "_"):
61 61 break
62 62 pos += 1
63 63 sym = program[s:pos]
64 64 yield ('symbol', sym, s)
65 65 pos -= 1
66 66 elif c == '}':
67 67 pos += 1
68 68 break
69 69 else:
70 70 raise error.ParseError(_("syntax error"), pos)
71 71 pos += 1
72 72 yield ('end', None, pos)
73 73
74 74 def compiletemplate(tmpl, context):
75 75 parsed = []
76 76 pos, stop = 0, len(tmpl)
77 77 p = parser.parser(tokenizer, elements)
78 78
79 79 while pos < stop:
80 80 n = tmpl.find('{', pos)
81 81 if n < 0:
82 82 parsed.append(("string", tmpl[pos:]))
83 83 break
84 84 if n > 0 and tmpl[n - 1] == '\\':
85 85 # escaped
86 86 parsed.append(("string", tmpl[pos:n - 1] + "{"))
87 87 pos = n + 1
88 88 continue
89 89 if n > pos:
90 90 parsed.append(("string", tmpl[pos:n]))
91 91
92 92 pd = [tmpl, n + 1, stop]
93 93 parseres, pos = p.parse(pd)
94 94 parsed.append(parseres)
95 95
96 96 return [compileexp(e, context) for e in parsed]
97 97
98 98 def compileexp(exp, context):
99 99 t = exp[0]
100 100 if t in methods:
101 101 return methods[t](exp, context)
102 102 raise error.ParseError(_("unknown method '%s'") % t)
103 103
104 104 # template evaluation
105 105
106 106 def getsymbol(exp):
107 107 if exp[0] == 'symbol':
108 108 return exp[1]
109 109 raise error.ParseError(_("expected a symbol"))
110 110
111 111 def getlist(x):
112 112 if not x:
113 113 return []
114 114 if x[0] == 'list':
115 115 return getlist(x[1]) + [x[2]]
116 116 return [x]
117 117
118 118 def getfilter(exp, context):
119 119 f = getsymbol(exp)
120 120 if f not in context._filters:
121 121 raise error.ParseError(_("unknown function '%s'") % f)
122 122 return context._filters[f]
123 123
124 124 def gettemplate(exp, context):
125 125 if exp[0] == 'string':
126 126 return compiletemplate(exp[1], context)
127 127 if exp[0] == 'symbol':
128 128 return context._load(exp[1])
129 129 raise error.ParseError(_("expected template specifier"))
130 130
131 131 def runstring(context, mapping, data):
132 132 return data
133 133
134 134 def runsymbol(context, mapping, key):
135 135 v = mapping.get(key)
136 136 if v is None:
137 137 v = context._defaults.get(key, '')
138 138 if util.safehasattr(v, '__call__'):
139 139 return v(**mapping)
140 140 return v
141 141
142 142 def buildfilter(exp, context):
143 143 func, data = compileexp(exp[1], context)
144 144 filt = getfilter(exp[2], context)
145 145 return (runfilter, (func, data, filt))
146 146
147 147 def runfilter(context, mapping, data):
148 148 func, data, filt = data
149 149 return filt(func(context, mapping, data))
150 150
151 151 def buildmap(exp, context):
152 152 func, data = compileexp(exp[1], context)
153 153 ctmpl = gettemplate(exp[2], context)
154 154 return (runmap, (func, data, ctmpl))
155 155
156 156 def runmap(context, mapping, data):
157 157 func, data, ctmpl = data
158 158 d = func(context, mapping, data)
159 159 lm = mapping.copy()
160 160
161 161 for i in d:
162 162 if isinstance(i, dict):
163 163 lm.update(i)
164 164 for f, d in ctmpl:
165 165 yield f(context, lm, d)
166 166 else:
167 167 # v is not an iterable of dicts, this happen when 'key'
168 168 # has been fully expanded already and format is useless.
169 169 # If so, return the expanded value.
170 170 yield i
171 171
172 172 def buildfunc(exp, context):
173 173 n = getsymbol(exp[1])
174 174 args = [compileexp(x, context) for x in getlist(exp[2])]
175 175 if n in funcs:
176 176 f = funcs[n]
177 177 return (f, args)
178 178 if n in context._filters:
179 179 if len(args) != 1:
180 180 raise error.ParseError(_("filter %s expects one argument") % n)
181 181 f = context._filters[n]
182 182 return (runfilter, (args[0][0], args[0][1], f))
183 183
184 184 methods = {
185 185 "string": lambda e, c: (runstring, e[1]),
186 186 "symbol": lambda e, c: (runsymbol, e[1]),
187 187 "group": lambda e, c: compileexp(e[1], c),
188 188 # ".": buildmember,
189 189 "|": buildfilter,
190 190 "%": buildmap,
191 191 "func": buildfunc,
192 192 }
193 193
194 194 funcs = {
195 195 }
196 196
197 197 # template engine
198 198
199 199 path = ['templates', '../templates']
200 200 stringify = templatefilters.stringify
201 201
202 202 def _flatten(thing):
203 203 '''yield a single stream from a possibly nested set of iterators'''
204 204 if isinstance(thing, str):
205 205 yield thing
206 206 elif not util.safehasattr(thing, '__iter__'):
207 207 if thing is not None:
208 208 yield str(thing)
209 209 else:
210 210 for i in thing:
211 211 if isinstance(i, str):
212 212 yield i
213 213 elif not util.safehasattr(i, '__iter__'):
214 214 if i is not None:
215 215 yield str(i)
216 216 elif i is not None:
217 217 for j in _flatten(i):
218 218 yield j
219 219
220 220 def parsestring(s, quoted=True):
221 221 '''parse a string using simple c-like syntax.
222 222 string must be in quotes if quoted is True.'''
223 223 if quoted:
224 224 if len(s) < 2 or s[0] != s[-1]:
225 225 raise SyntaxError(_('unmatched quotes'))
226 226 return s[1:-1].decode('string_escape')
227 227
228 228 return s.decode('string_escape')
229 229
230 230 class engine(object):
231 231 '''template expansion engine.
232 232
233 233 template expansion works like this. a map file contains key=value
234 234 pairs. if value is quoted, it is treated as string. otherwise, it
235 235 is treated as name of template file.
236 236
237 237 templater is asked to expand a key in map. it looks up key, and
238 238 looks for strings like this: {foo}. it expands {foo} by looking up
239 239 foo in map, and substituting it. expansion is recursive: it stops
240 240 when there is no more {foo} to replace.
241 241
242 242 expansion also allows formatting and filtering.
243 243
244 244 format uses key to expand each item in list. syntax is
245 245 {key%format}.
246 246
247 247 filter uses function to transform value. syntax is
248 248 {key|filter1|filter2|...}.'''
249 249
250 250 def __init__(self, loader, filters={}, defaults={}):
251 251 self._loader = loader
252 252 self._filters = filters
253 253 self._defaults = defaults
254 254 self._cache = {}
255 255
256 256 def _load(self, t):
257 257 '''load, parse, and cache a template'''
258 258 if t not in self._cache:
259 259 self._cache[t] = compiletemplate(self._loader(t), self)
260 260 return self._cache[t]
261 261
262 262 def process(self, t, mapping):
263 263 '''Perform expansion. t is name of map element to expand.
264 264 mapping contains added elements for use during expansion. Is a
265 265 generator.'''
266 266 return _flatten(func(self, mapping, data) for func, data in
267 267 self._load(t))
268 268
269 269 engines = {'default': engine}
270 270
271 271 class templater(object):
272 272
273 273 def __init__(self, mapfile, filters={}, defaults={}, cache={},
274 274 minchunk=1024, maxchunk=65536):
275 275 '''set up template engine.
276 276 mapfile is name of file to read map definitions from.
277 277 filters is dict of functions. each transforms a value into another.
278 278 defaults is dict of default map definitions.'''
279 279 self.mapfile = mapfile or 'template'
280 280 self.cache = cache.copy()
281 281 self.map = {}
282 282 self.base = (mapfile and os.path.dirname(mapfile)) or ''
283 283 self.filters = templatefilters.filters.copy()
284 284 self.filters.update(filters)
285 285 self.defaults = defaults
286 286 self.minchunk, self.maxchunk = minchunk, maxchunk
287 287 self.ecache = {}
288 288
289 289 if not mapfile:
290 290 return
291 291 if not os.path.exists(mapfile):
292 292 raise util.Abort(_('style not found: %s') % mapfile)
293 293
294 294 conf = config.config()
295 295 conf.read(mapfile)
296 296
297 297 for key, val in conf[''].items():
298 if not val:
299 raise SyntaxError(_('%s: missing value') % conf.source('', key))
298 300 if val[0] in "'\"":
299 301 try:
300 302 self.cache[key] = parsestring(val)
301 303 except SyntaxError, inst:
302 304 raise SyntaxError('%s: %s' %
303 305 (conf.source('', key), inst.args[0]))
304 306 else:
305 307 val = 'default', val
306 308 if ':' in val[1]:
307 309 val = val[1].split(':', 1)
308 310 self.map[key] = val[0], os.path.join(self.base, val[1])
309 311
310 312 def __contains__(self, key):
311 313 return key in self.cache or key in self.map
312 314
313 315 def load(self, t):
314 316 '''Get the template for the given template name. Use a local cache.'''
315 317 if t not in self.cache:
316 318 try:
317 319 self.cache[t] = util.readfile(self.map[t][1])
318 320 except KeyError, inst:
319 321 raise util.Abort(_('"%s" not in template map') % inst.args[0])
320 322 except IOError, inst:
321 323 raise IOError(inst.args[0], _('template file %s: %s') %
322 324 (self.map[t][1], inst.args[1]))
323 325 return self.cache[t]
324 326
325 327 def __call__(self, t, **mapping):
326 328 ttype = t in self.map and self.map[t][0] or 'default'
327 329 if ttype not in self.ecache:
328 330 self.ecache[ttype] = engines[ttype](self.load,
329 331 self.filters, self.defaults)
330 332 proc = self.ecache[ttype]
331 333
332 334 stream = proc.process(t, mapping)
333 335 if self.minchunk:
334 336 stream = util.increasingchunks(stream, min=self.minchunk,
335 337 max=self.maxchunk)
336 338 return stream
337 339
338 340 def templatepath(name=None):
339 341 '''return location of template file or directory (if no name).
340 342 returns None if not found.'''
341 343 normpaths = []
342 344
343 345 # executable version (py2exe) doesn't support __file__
344 346 if util.mainfrozen():
345 347 module = sys.executable
346 348 else:
347 349 module = __file__
348 350 for f in path:
349 351 if f.startswith('/'):
350 352 p = f
351 353 else:
352 354 fl = f.split('/')
353 355 p = os.path.join(os.path.dirname(module), *fl)
354 356 if name:
355 357 p = os.path.join(p, name)
356 358 if name and os.path.exists(p):
357 359 return os.path.normpath(p)
358 360 elif os.path.isdir(p):
359 361 normpaths.append(os.path.normpath(p))
360 362
361 363 return normpaths
362 364
363 365 def stylemap(styles, paths=None):
364 366 """Return path to mapfile for a given style.
365 367
366 368 Searches mapfile in the following locations:
367 369 1. templatepath/style/map
368 370 2. templatepath/map-style
369 371 3. templatepath/map
370 372 """
371 373
372 374 if paths is None:
373 375 paths = templatepath()
374 376 elif isinstance(paths, str):
375 377 paths = [paths]
376 378
377 379 if isinstance(styles, str):
378 380 styles = [styles]
379 381
380 382 for style in styles:
381 383 if not style:
382 384 continue
383 385 locations = [os.path.join(style, 'map'), 'map-' + style]
384 386 locations.append('map')
385 387
386 388 for path in paths:
387 389 for location in locations:
388 390 mapfile = os.path.join(path, location)
389 391 if os.path.isfile(mapfile):
390 392 return style, mapfile
391 393
392 394 raise RuntimeError("No hgweb templates found in %r" % paths)
@@ -1,1383 +1,1390 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 Second branch starting at nullrev:
33 33
34 34 $ hg update null
35 35 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
36 36 $ echo second > second
37 37 $ hg add second
38 38 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
39 39 created new head
40 40
41 41 $ echo third > third
42 42 $ hg add third
43 43 $ hg mv second fourth
44 44 $ hg commit -m third -d "2020-01-01 10:01"
45 45
46 46 Quoting for ui.logtemplate
47 47
48 48 $ hg tip --config "ui.logtemplate={rev}\n"
49 49 8
50 50 $ hg tip --config "ui.logtemplate='{rev}\n'"
51 51 8
52 52 $ hg tip --config 'ui.logtemplate="{rev}\n"'
53 53 8
54 54
55 55 Make sure user/global hgrc does not affect tests
56 56
57 57 $ echo '[ui]' > .hg/hgrc
58 58 $ echo 'logtemplate =' >> .hg/hgrc
59 59 $ echo 'style =' >> .hg/hgrc
60 60
61 61 Default style is like normal output:
62 62
63 63 $ hg log > log.out
64 64 $ hg log --style default > style.out
65 65 $ cmp log.out style.out || diff -u log.out style.out
66 66
67 67 $ hg log -v > log.out
68 68 $ hg log -v --style default > style.out
69 69 $ cmp log.out style.out || diff -u log.out style.out
70 70
71 71 $ hg log --debug > log.out
72 72 $ hg log --debug --style default > style.out
73 73 $ cmp log.out style.out || diff -u log.out style.out
74 74
75 75 Revision with no copies (used to print a traceback):
76 76
77 77 $ hg tip -v --template '\n'
78 78
79 79
80 80 Compact style works:
81 81
82 82 $ hg log --style compact
83 83 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
84 84 third
85 85
86 86 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
87 87 second
88 88
89 89 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
90 90 merge
91 91
92 92 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
93 93 new head
94 94
95 95 4 bbe44766e73d 1970-01-17 04:53 +0000 person
96 96 new branch
97 97
98 98 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
99 99 no user, no domain
100 100
101 101 2 97054abb4ab8 1970-01-14 21:20 +0000 other
102 102 no person
103 103
104 104 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
105 105 other 1
106 106
107 107 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
108 108 line 1
109 109
110 110
111 111 $ hg log -v --style compact
112 112 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
113 113 third
114 114
115 115 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
116 116 second
117 117
118 118 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
119 119 merge
120 120
121 121 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
122 122 new head
123 123
124 124 4 bbe44766e73d 1970-01-17 04:53 +0000 person
125 125 new branch
126 126
127 127 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
128 128 no user, no domain
129 129
130 130 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
131 131 no person
132 132
133 133 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
134 134 other 1
135 135 other 2
136 136
137 137 other 3
138 138
139 139 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
140 140 line 1
141 141 line 2
142 142
143 143
144 144 $ hg log --debug --style compact
145 145 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
146 146 third
147 147
148 148 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
149 149 second
150 150
151 151 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
152 152 merge
153 153
154 154 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
155 155 new head
156 156
157 157 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
158 158 new branch
159 159
160 160 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
161 161 no user, no domain
162 162
163 163 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
164 164 no person
165 165
166 166 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
167 167 other 1
168 168 other 2
169 169
170 170 other 3
171 171
172 172 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
173 173 line 1
174 174 line 2
175 175
176 176
177 177 Test xml styles:
178 178
179 179 $ hg log --style xml
180 180 <?xml version="1.0"?>
181 181 <log>
182 182 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
183 183 <tag>tip</tag>
184 184 <author email="test">test</author>
185 185 <date>2020-01-01T10:01:00+00:00</date>
186 186 <msg xml:space="preserve">third</msg>
187 187 </logentry>
188 188 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
189 189 <parent revision="-1" node="0000000000000000000000000000000000000000" />
190 190 <author email="user@hostname">User Name</author>
191 191 <date>1970-01-12T13:46:40+00:00</date>
192 192 <msg xml:space="preserve">second</msg>
193 193 </logentry>
194 194 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
195 195 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
196 196 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
197 197 <author email="person">person</author>
198 198 <date>1970-01-18T08:40:01+00:00</date>
199 199 <msg xml:space="preserve">merge</msg>
200 200 </logentry>
201 201 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
202 202 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
203 203 <author email="person">person</author>
204 204 <date>1970-01-18T08:40:00+00:00</date>
205 205 <msg xml:space="preserve">new head</msg>
206 206 </logentry>
207 207 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
208 208 <branch>foo</branch>
209 209 <author email="person">person</author>
210 210 <date>1970-01-17T04:53:20+00:00</date>
211 211 <msg xml:space="preserve">new branch</msg>
212 212 </logentry>
213 213 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
214 214 <author email="person">person</author>
215 215 <date>1970-01-16T01:06:40+00:00</date>
216 216 <msg xml:space="preserve">no user, no domain</msg>
217 217 </logentry>
218 218 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
219 219 <author email="other@place">other</author>
220 220 <date>1970-01-14T21:20:00+00:00</date>
221 221 <msg xml:space="preserve">no person</msg>
222 222 </logentry>
223 223 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
224 224 <author email="other@place">A. N. Other</author>
225 225 <date>1970-01-13T17:33:20+00:00</date>
226 226 <msg xml:space="preserve">other 1
227 227 other 2
228 228
229 229 other 3</msg>
230 230 </logentry>
231 231 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
232 232 <author email="user@hostname">User Name</author>
233 233 <date>1970-01-12T13:46:40+00:00</date>
234 234 <msg xml:space="preserve">line 1
235 235 line 2</msg>
236 236 </logentry>
237 237 </log>
238 238
239 239 $ hg log -v --style xml
240 240 <?xml version="1.0"?>
241 241 <log>
242 242 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
243 243 <tag>tip</tag>
244 244 <author email="test">test</author>
245 245 <date>2020-01-01T10:01:00+00:00</date>
246 246 <msg xml:space="preserve">third</msg>
247 247 <paths>
248 248 <path action="A">fourth</path>
249 249 <path action="A">third</path>
250 250 <path action="R">second</path>
251 251 </paths>
252 252 <copies>
253 253 <copy source="second">fourth</copy>
254 254 </copies>
255 255 </logentry>
256 256 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
257 257 <parent revision="-1" node="0000000000000000000000000000000000000000" />
258 258 <author email="user@hostname">User Name</author>
259 259 <date>1970-01-12T13:46:40+00:00</date>
260 260 <msg xml:space="preserve">second</msg>
261 261 <paths>
262 262 <path action="A">second</path>
263 263 </paths>
264 264 </logentry>
265 265 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
266 266 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
267 267 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
268 268 <author email="person">person</author>
269 269 <date>1970-01-18T08:40:01+00:00</date>
270 270 <msg xml:space="preserve">merge</msg>
271 271 <paths>
272 272 </paths>
273 273 </logentry>
274 274 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
275 275 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
276 276 <author email="person">person</author>
277 277 <date>1970-01-18T08:40:00+00:00</date>
278 278 <msg xml:space="preserve">new head</msg>
279 279 <paths>
280 280 <path action="A">d</path>
281 281 </paths>
282 282 </logentry>
283 283 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
284 284 <branch>foo</branch>
285 285 <author email="person">person</author>
286 286 <date>1970-01-17T04:53:20+00:00</date>
287 287 <msg xml:space="preserve">new branch</msg>
288 288 <paths>
289 289 </paths>
290 290 </logentry>
291 291 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
292 292 <author email="person">person</author>
293 293 <date>1970-01-16T01:06:40+00:00</date>
294 294 <msg xml:space="preserve">no user, no domain</msg>
295 295 <paths>
296 296 <path action="M">c</path>
297 297 </paths>
298 298 </logentry>
299 299 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
300 300 <author email="other@place">other</author>
301 301 <date>1970-01-14T21:20:00+00:00</date>
302 302 <msg xml:space="preserve">no person</msg>
303 303 <paths>
304 304 <path action="A">c</path>
305 305 </paths>
306 306 </logentry>
307 307 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
308 308 <author email="other@place">A. N. Other</author>
309 309 <date>1970-01-13T17:33:20+00:00</date>
310 310 <msg xml:space="preserve">other 1
311 311 other 2
312 312
313 313 other 3</msg>
314 314 <paths>
315 315 <path action="A">b</path>
316 316 </paths>
317 317 </logentry>
318 318 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
319 319 <author email="user@hostname">User Name</author>
320 320 <date>1970-01-12T13:46:40+00:00</date>
321 321 <msg xml:space="preserve">line 1
322 322 line 2</msg>
323 323 <paths>
324 324 <path action="A">a</path>
325 325 </paths>
326 326 </logentry>
327 327 </log>
328 328
329 329 $ hg log --debug --style xml
330 330 <?xml version="1.0"?>
331 331 <log>
332 332 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
333 333 <tag>tip</tag>
334 334 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
335 335 <parent revision="-1" node="0000000000000000000000000000000000000000" />
336 336 <author email="test">test</author>
337 337 <date>2020-01-01T10:01:00+00:00</date>
338 338 <msg xml:space="preserve">third</msg>
339 339 <paths>
340 340 <path action="A">fourth</path>
341 341 <path action="A">third</path>
342 342 <path action="R">second</path>
343 343 </paths>
344 344 <copies>
345 345 <copy source="second">fourth</copy>
346 346 </copies>
347 347 <extra key="branch">default</extra>
348 348 </logentry>
349 349 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
350 350 <parent revision="-1" node="0000000000000000000000000000000000000000" />
351 351 <parent revision="-1" node="0000000000000000000000000000000000000000" />
352 352 <author email="user@hostname">User Name</author>
353 353 <date>1970-01-12T13:46:40+00:00</date>
354 354 <msg xml:space="preserve">second</msg>
355 355 <paths>
356 356 <path action="A">second</path>
357 357 </paths>
358 358 <extra key="branch">default</extra>
359 359 </logentry>
360 360 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
361 361 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
362 362 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
363 363 <author email="person">person</author>
364 364 <date>1970-01-18T08:40:01+00:00</date>
365 365 <msg xml:space="preserve">merge</msg>
366 366 <paths>
367 367 </paths>
368 368 <extra key="branch">default</extra>
369 369 </logentry>
370 370 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
371 371 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
372 372 <parent revision="-1" node="0000000000000000000000000000000000000000" />
373 373 <author email="person">person</author>
374 374 <date>1970-01-18T08:40:00+00:00</date>
375 375 <msg xml:space="preserve">new head</msg>
376 376 <paths>
377 377 <path action="A">d</path>
378 378 </paths>
379 379 <extra key="branch">default</extra>
380 380 </logentry>
381 381 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
382 382 <branch>foo</branch>
383 383 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
384 384 <parent revision="-1" node="0000000000000000000000000000000000000000" />
385 385 <author email="person">person</author>
386 386 <date>1970-01-17T04:53:20+00:00</date>
387 387 <msg xml:space="preserve">new branch</msg>
388 388 <paths>
389 389 </paths>
390 390 <extra key="branch">foo</extra>
391 391 </logentry>
392 392 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
393 393 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
394 394 <parent revision="-1" node="0000000000000000000000000000000000000000" />
395 395 <author email="person">person</author>
396 396 <date>1970-01-16T01:06:40+00:00</date>
397 397 <msg xml:space="preserve">no user, no domain</msg>
398 398 <paths>
399 399 <path action="M">c</path>
400 400 </paths>
401 401 <extra key="branch">default</extra>
402 402 </logentry>
403 403 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
404 404 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
405 405 <parent revision="-1" node="0000000000000000000000000000000000000000" />
406 406 <author email="other@place">other</author>
407 407 <date>1970-01-14T21:20:00+00:00</date>
408 408 <msg xml:space="preserve">no person</msg>
409 409 <paths>
410 410 <path action="A">c</path>
411 411 </paths>
412 412 <extra key="branch">default</extra>
413 413 </logentry>
414 414 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
415 415 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
416 416 <parent revision="-1" node="0000000000000000000000000000000000000000" />
417 417 <author email="other@place">A. N. Other</author>
418 418 <date>1970-01-13T17:33:20+00:00</date>
419 419 <msg xml:space="preserve">other 1
420 420 other 2
421 421
422 422 other 3</msg>
423 423 <paths>
424 424 <path action="A">b</path>
425 425 </paths>
426 426 <extra key="branch">default</extra>
427 427 </logentry>
428 428 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
429 429 <parent revision="-1" node="0000000000000000000000000000000000000000" />
430 430 <parent revision="-1" node="0000000000000000000000000000000000000000" />
431 431 <author email="user@hostname">User Name</author>
432 432 <date>1970-01-12T13:46:40+00:00</date>
433 433 <msg xml:space="preserve">line 1
434 434 line 2</msg>
435 435 <paths>
436 436 <path action="A">a</path>
437 437 </paths>
438 438 <extra key="branch">default</extra>
439 439 </logentry>
440 440 </log>
441 441
442 442
443 443 Error if style not readable:
444 444
445 445 #if unix-permissions
446 446 $ touch q
447 447 $ chmod 0 q
448 448 $ hg log --style ./q
449 449 abort: Permission denied: ./q
450 450 [255]
451 451 #endif
452 452
453 453 Error if no style:
454 454
455 455 $ hg log --style notexist
456 456 abort: style not found: notexist
457 457 [255]
458 458
459 459 Error if style missing key:
460 460
461 461 $ echo 'q = q' > t
462 462 $ hg log --style ./t
463 463 abort: "changeset" not in template map
464 464 [255]
465 465
466 Error if style missing value:
467
468 $ echo 'changeset =' > t
469 $ hg log --style t
470 abort: t:1: missing value
471 [255]
472
466 473 Error if include fails:
467 474
468 475 $ echo 'changeset = q' >> t
469 476 #if unix-permissions
470 477 $ hg log --style ./t
471 478 abort: template file ./q: Permission denied
472 479 [255]
473 480 $ rm q
474 481 #endif
475 482
476 483 Include works:
477 484
478 485 $ echo '{rev}' > q
479 486 $ hg log --style ./t
480 487 8
481 488 7
482 489 6
483 490 5
484 491 4
485 492 3
486 493 2
487 494 1
488 495 0
489 496
490 497 ui.style works:
491 498
492 499 $ echo '[ui]' > .hg/hgrc
493 500 $ echo 'style = t' >> .hg/hgrc
494 501 $ hg log
495 502 8
496 503 7
497 504 6
498 505 5
499 506 4
500 507 3
501 508 2
502 509 1
503 510 0
504 511
505 512
506 513 Issue338:
507 514
508 515 $ hg log --style=changelog > changelog
509 516
510 517 $ cat changelog
511 518 2020-01-01 test <test>
512 519
513 520 * fourth, second, third:
514 521 third
515 522 [95c24699272e] [tip]
516 523
517 524 1970-01-12 User Name <user@hostname>
518 525
519 526 * second:
520 527 second
521 528 [29114dbae42b]
522 529
523 530 1970-01-18 person <person>
524 531
525 532 * merge
526 533 [d41e714fe50d]
527 534
528 535 * d:
529 536 new head
530 537 [13207e5a10d9]
531 538
532 539 1970-01-17 person <person>
533 540
534 541 * new branch
535 542 [bbe44766e73d] <foo>
536 543
537 544 1970-01-16 person <person>
538 545
539 546 * c:
540 547 no user, no domain
541 548 [10e46f2dcbf4]
542 549
543 550 1970-01-14 other <other@place>
544 551
545 552 * c:
546 553 no person
547 554 [97054abb4ab8]
548 555
549 556 1970-01-13 A. N. Other <other@place>
550 557
551 558 * b:
552 559 other 1 other 2
553 560
554 561 other 3
555 562 [b608e9d1a3f0]
556 563
557 564 1970-01-12 User Name <user@hostname>
558 565
559 566 * a:
560 567 line 1 line 2
561 568 [1e4e1b8f71e0]
562 569
563 570
564 571 Issue2130: xml output for 'hg heads' is malformed
565 572
566 573 $ hg heads --style changelog
567 574 2020-01-01 test <test>
568 575
569 576 * fourth, second, third:
570 577 third
571 578 [95c24699272e] [tip]
572 579
573 580 1970-01-18 person <person>
574 581
575 582 * merge
576 583 [d41e714fe50d]
577 584
578 585 1970-01-17 person <person>
579 586
580 587 * new branch
581 588 [bbe44766e73d] <foo>
582 589
583 590
584 591 Keys work:
585 592
586 593 $ for key in author branch branches date desc file_adds file_dels file_mods \
587 594 > file_copies file_copies_switch files \
588 595 > manifest node parents rev tags diffstat extras; do
589 596 > for mode in '' --verbose --debug; do
590 597 > hg log $mode --template "$key$mode: {$key}\n"
591 598 > done
592 599 > done
593 600 author: test
594 601 author: User Name <user@hostname>
595 602 author: person
596 603 author: person
597 604 author: person
598 605 author: person
599 606 author: other@place
600 607 author: A. N. Other <other@place>
601 608 author: User Name <user@hostname>
602 609 author--verbose: test
603 610 author--verbose: User Name <user@hostname>
604 611 author--verbose: person
605 612 author--verbose: person
606 613 author--verbose: person
607 614 author--verbose: person
608 615 author--verbose: other@place
609 616 author--verbose: A. N. Other <other@place>
610 617 author--verbose: User Name <user@hostname>
611 618 author--debug: test
612 619 author--debug: User Name <user@hostname>
613 620 author--debug: person
614 621 author--debug: person
615 622 author--debug: person
616 623 author--debug: person
617 624 author--debug: other@place
618 625 author--debug: A. N. Other <other@place>
619 626 author--debug: User Name <user@hostname>
620 627 branch: default
621 628 branch: default
622 629 branch: default
623 630 branch: default
624 631 branch: foo
625 632 branch: default
626 633 branch: default
627 634 branch: default
628 635 branch: default
629 636 branch--verbose: default
630 637 branch--verbose: default
631 638 branch--verbose: default
632 639 branch--verbose: default
633 640 branch--verbose: foo
634 641 branch--verbose: default
635 642 branch--verbose: default
636 643 branch--verbose: default
637 644 branch--verbose: default
638 645 branch--debug: default
639 646 branch--debug: default
640 647 branch--debug: default
641 648 branch--debug: default
642 649 branch--debug: foo
643 650 branch--debug: default
644 651 branch--debug: default
645 652 branch--debug: default
646 653 branch--debug: default
647 654 branches:
648 655 branches:
649 656 branches:
650 657 branches:
651 658 branches: foo
652 659 branches:
653 660 branches:
654 661 branches:
655 662 branches:
656 663 branches--verbose:
657 664 branches--verbose:
658 665 branches--verbose:
659 666 branches--verbose:
660 667 branches--verbose: foo
661 668 branches--verbose:
662 669 branches--verbose:
663 670 branches--verbose:
664 671 branches--verbose:
665 672 branches--debug:
666 673 branches--debug:
667 674 branches--debug:
668 675 branches--debug:
669 676 branches--debug: foo
670 677 branches--debug:
671 678 branches--debug:
672 679 branches--debug:
673 680 branches--debug:
674 681 date: 1577872860.00
675 682 date: 1000000.00
676 683 date: 1500001.00
677 684 date: 1500000.00
678 685 date: 1400000.00
679 686 date: 1300000.00
680 687 date: 1200000.00
681 688 date: 1100000.00
682 689 date: 1000000.00
683 690 date--verbose: 1577872860.00
684 691 date--verbose: 1000000.00
685 692 date--verbose: 1500001.00
686 693 date--verbose: 1500000.00
687 694 date--verbose: 1400000.00
688 695 date--verbose: 1300000.00
689 696 date--verbose: 1200000.00
690 697 date--verbose: 1100000.00
691 698 date--verbose: 1000000.00
692 699 date--debug: 1577872860.00
693 700 date--debug: 1000000.00
694 701 date--debug: 1500001.00
695 702 date--debug: 1500000.00
696 703 date--debug: 1400000.00
697 704 date--debug: 1300000.00
698 705 date--debug: 1200000.00
699 706 date--debug: 1100000.00
700 707 date--debug: 1000000.00
701 708 desc: third
702 709 desc: second
703 710 desc: merge
704 711 desc: new head
705 712 desc: new branch
706 713 desc: no user, no domain
707 714 desc: no person
708 715 desc: other 1
709 716 other 2
710 717
711 718 other 3
712 719 desc: line 1
713 720 line 2
714 721 desc--verbose: third
715 722 desc--verbose: second
716 723 desc--verbose: merge
717 724 desc--verbose: new head
718 725 desc--verbose: new branch
719 726 desc--verbose: no user, no domain
720 727 desc--verbose: no person
721 728 desc--verbose: other 1
722 729 other 2
723 730
724 731 other 3
725 732 desc--verbose: line 1
726 733 line 2
727 734 desc--debug: third
728 735 desc--debug: second
729 736 desc--debug: merge
730 737 desc--debug: new head
731 738 desc--debug: new branch
732 739 desc--debug: no user, no domain
733 740 desc--debug: no person
734 741 desc--debug: other 1
735 742 other 2
736 743
737 744 other 3
738 745 desc--debug: line 1
739 746 line 2
740 747 file_adds: fourth third
741 748 file_adds: second
742 749 file_adds:
743 750 file_adds: d
744 751 file_adds:
745 752 file_adds:
746 753 file_adds: c
747 754 file_adds: b
748 755 file_adds: a
749 756 file_adds--verbose: fourth third
750 757 file_adds--verbose: second
751 758 file_adds--verbose:
752 759 file_adds--verbose: d
753 760 file_adds--verbose:
754 761 file_adds--verbose:
755 762 file_adds--verbose: c
756 763 file_adds--verbose: b
757 764 file_adds--verbose: a
758 765 file_adds--debug: fourth third
759 766 file_adds--debug: second
760 767 file_adds--debug:
761 768 file_adds--debug: d
762 769 file_adds--debug:
763 770 file_adds--debug:
764 771 file_adds--debug: c
765 772 file_adds--debug: b
766 773 file_adds--debug: a
767 774 file_dels: second
768 775 file_dels:
769 776 file_dels:
770 777 file_dels:
771 778 file_dels:
772 779 file_dels:
773 780 file_dels:
774 781 file_dels:
775 782 file_dels:
776 783 file_dels--verbose: second
777 784 file_dels--verbose:
778 785 file_dels--verbose:
779 786 file_dels--verbose:
780 787 file_dels--verbose:
781 788 file_dels--verbose:
782 789 file_dels--verbose:
783 790 file_dels--verbose:
784 791 file_dels--verbose:
785 792 file_dels--debug: second
786 793 file_dels--debug:
787 794 file_dels--debug:
788 795 file_dels--debug:
789 796 file_dels--debug:
790 797 file_dels--debug:
791 798 file_dels--debug:
792 799 file_dels--debug:
793 800 file_dels--debug:
794 801 file_mods:
795 802 file_mods:
796 803 file_mods:
797 804 file_mods:
798 805 file_mods:
799 806 file_mods: c
800 807 file_mods:
801 808 file_mods:
802 809 file_mods:
803 810 file_mods--verbose:
804 811 file_mods--verbose:
805 812 file_mods--verbose:
806 813 file_mods--verbose:
807 814 file_mods--verbose:
808 815 file_mods--verbose: c
809 816 file_mods--verbose:
810 817 file_mods--verbose:
811 818 file_mods--verbose:
812 819 file_mods--debug:
813 820 file_mods--debug:
814 821 file_mods--debug:
815 822 file_mods--debug:
816 823 file_mods--debug:
817 824 file_mods--debug: c
818 825 file_mods--debug:
819 826 file_mods--debug:
820 827 file_mods--debug:
821 828 file_copies: fourth (second)
822 829 file_copies:
823 830 file_copies:
824 831 file_copies:
825 832 file_copies:
826 833 file_copies:
827 834 file_copies:
828 835 file_copies:
829 836 file_copies:
830 837 file_copies--verbose: fourth (second)
831 838 file_copies--verbose:
832 839 file_copies--verbose:
833 840 file_copies--verbose:
834 841 file_copies--verbose:
835 842 file_copies--verbose:
836 843 file_copies--verbose:
837 844 file_copies--verbose:
838 845 file_copies--verbose:
839 846 file_copies--debug: fourth (second)
840 847 file_copies--debug:
841 848 file_copies--debug:
842 849 file_copies--debug:
843 850 file_copies--debug:
844 851 file_copies--debug:
845 852 file_copies--debug:
846 853 file_copies--debug:
847 854 file_copies--debug:
848 855 file_copies_switch:
849 856 file_copies_switch:
850 857 file_copies_switch:
851 858 file_copies_switch:
852 859 file_copies_switch:
853 860 file_copies_switch:
854 861 file_copies_switch:
855 862 file_copies_switch:
856 863 file_copies_switch:
857 864 file_copies_switch--verbose:
858 865 file_copies_switch--verbose:
859 866 file_copies_switch--verbose:
860 867 file_copies_switch--verbose:
861 868 file_copies_switch--verbose:
862 869 file_copies_switch--verbose:
863 870 file_copies_switch--verbose:
864 871 file_copies_switch--verbose:
865 872 file_copies_switch--verbose:
866 873 file_copies_switch--debug:
867 874 file_copies_switch--debug:
868 875 file_copies_switch--debug:
869 876 file_copies_switch--debug:
870 877 file_copies_switch--debug:
871 878 file_copies_switch--debug:
872 879 file_copies_switch--debug:
873 880 file_copies_switch--debug:
874 881 file_copies_switch--debug:
875 882 files: fourth second third
876 883 files: second
877 884 files:
878 885 files: d
879 886 files:
880 887 files: c
881 888 files: c
882 889 files: b
883 890 files: a
884 891 files--verbose: fourth second third
885 892 files--verbose: second
886 893 files--verbose:
887 894 files--verbose: d
888 895 files--verbose:
889 896 files--verbose: c
890 897 files--verbose: c
891 898 files--verbose: b
892 899 files--verbose: a
893 900 files--debug: fourth second third
894 901 files--debug: second
895 902 files--debug:
896 903 files--debug: d
897 904 files--debug:
898 905 files--debug: c
899 906 files--debug: c
900 907 files--debug: b
901 908 files--debug: a
902 909 manifest: 6:94961b75a2da
903 910 manifest: 5:f2dbc354b94e
904 911 manifest: 4:4dc3def4f9b4
905 912 manifest: 4:4dc3def4f9b4
906 913 manifest: 3:cb5a1327723b
907 914 manifest: 3:cb5a1327723b
908 915 manifest: 2:6e0e82995c35
909 916 manifest: 1:4e8d705b1e53
910 917 manifest: 0:a0c8bcbbb45c
911 918 manifest--verbose: 6:94961b75a2da
912 919 manifest--verbose: 5:f2dbc354b94e
913 920 manifest--verbose: 4:4dc3def4f9b4
914 921 manifest--verbose: 4:4dc3def4f9b4
915 922 manifest--verbose: 3:cb5a1327723b
916 923 manifest--verbose: 3:cb5a1327723b
917 924 manifest--verbose: 2:6e0e82995c35
918 925 manifest--verbose: 1:4e8d705b1e53
919 926 manifest--verbose: 0:a0c8bcbbb45c
920 927 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
921 928 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
922 929 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
923 930 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
924 931 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
925 932 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
926 933 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
927 934 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
928 935 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
929 936 node: 95c24699272ef57d062b8bccc32c878bf841784a
930 937 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
931 938 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
932 939 node: 13207e5a10d9fd28ec424934298e176197f2c67f
933 940 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
934 941 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
935 942 node: 97054abb4ab824450e9164180baf491ae0078465
936 943 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
937 944 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
938 945 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
939 946 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
940 947 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
941 948 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
942 949 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
943 950 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
944 951 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
945 952 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
946 953 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
947 954 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
948 955 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
949 956 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
950 957 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
951 958 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
952 959 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
953 960 node--debug: 97054abb4ab824450e9164180baf491ae0078465
954 961 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
955 962 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
956 963 parents:
957 964 parents: -1:000000000000
958 965 parents: 5:13207e5a10d9 4:bbe44766e73d
959 966 parents: 3:10e46f2dcbf4
960 967 parents:
961 968 parents:
962 969 parents:
963 970 parents:
964 971 parents:
965 972 parents--verbose:
966 973 parents--verbose: -1:000000000000
967 974 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
968 975 parents--verbose: 3:10e46f2dcbf4
969 976 parents--verbose:
970 977 parents--verbose:
971 978 parents--verbose:
972 979 parents--verbose:
973 980 parents--verbose:
974 981 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
975 982 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
976 983 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
977 984 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
978 985 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
979 986 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
980 987 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
981 988 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
982 989 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
983 990 rev: 8
984 991 rev: 7
985 992 rev: 6
986 993 rev: 5
987 994 rev: 4
988 995 rev: 3
989 996 rev: 2
990 997 rev: 1
991 998 rev: 0
992 999 rev--verbose: 8
993 1000 rev--verbose: 7
994 1001 rev--verbose: 6
995 1002 rev--verbose: 5
996 1003 rev--verbose: 4
997 1004 rev--verbose: 3
998 1005 rev--verbose: 2
999 1006 rev--verbose: 1
1000 1007 rev--verbose: 0
1001 1008 rev--debug: 8
1002 1009 rev--debug: 7
1003 1010 rev--debug: 6
1004 1011 rev--debug: 5
1005 1012 rev--debug: 4
1006 1013 rev--debug: 3
1007 1014 rev--debug: 2
1008 1015 rev--debug: 1
1009 1016 rev--debug: 0
1010 1017 tags: tip
1011 1018 tags:
1012 1019 tags:
1013 1020 tags:
1014 1021 tags:
1015 1022 tags:
1016 1023 tags:
1017 1024 tags:
1018 1025 tags:
1019 1026 tags--verbose: tip
1020 1027 tags--verbose:
1021 1028 tags--verbose:
1022 1029 tags--verbose:
1023 1030 tags--verbose:
1024 1031 tags--verbose:
1025 1032 tags--verbose:
1026 1033 tags--verbose:
1027 1034 tags--verbose:
1028 1035 tags--debug: tip
1029 1036 tags--debug:
1030 1037 tags--debug:
1031 1038 tags--debug:
1032 1039 tags--debug:
1033 1040 tags--debug:
1034 1041 tags--debug:
1035 1042 tags--debug:
1036 1043 tags--debug:
1037 1044 diffstat: 3: +2/-1
1038 1045 diffstat: 1: +1/-0
1039 1046 diffstat: 0: +0/-0
1040 1047 diffstat: 1: +1/-0
1041 1048 diffstat: 0: +0/-0
1042 1049 diffstat: 1: +1/-0
1043 1050 diffstat: 1: +4/-0
1044 1051 diffstat: 1: +2/-0
1045 1052 diffstat: 1: +1/-0
1046 1053 diffstat--verbose: 3: +2/-1
1047 1054 diffstat--verbose: 1: +1/-0
1048 1055 diffstat--verbose: 0: +0/-0
1049 1056 diffstat--verbose: 1: +1/-0
1050 1057 diffstat--verbose: 0: +0/-0
1051 1058 diffstat--verbose: 1: +1/-0
1052 1059 diffstat--verbose: 1: +4/-0
1053 1060 diffstat--verbose: 1: +2/-0
1054 1061 diffstat--verbose: 1: +1/-0
1055 1062 diffstat--debug: 3: +2/-1
1056 1063 diffstat--debug: 1: +1/-0
1057 1064 diffstat--debug: 0: +0/-0
1058 1065 diffstat--debug: 1: +1/-0
1059 1066 diffstat--debug: 0: +0/-0
1060 1067 diffstat--debug: 1: +1/-0
1061 1068 diffstat--debug: 1: +4/-0
1062 1069 diffstat--debug: 1: +2/-0
1063 1070 diffstat--debug: 1: +1/-0
1064 1071 extras: branch=default
1065 1072 extras: branch=default
1066 1073 extras: branch=default
1067 1074 extras: branch=default
1068 1075 extras: branch=foo
1069 1076 extras: branch=default
1070 1077 extras: branch=default
1071 1078 extras: branch=default
1072 1079 extras: branch=default
1073 1080 extras--verbose: branch=default
1074 1081 extras--verbose: branch=default
1075 1082 extras--verbose: branch=default
1076 1083 extras--verbose: branch=default
1077 1084 extras--verbose: branch=foo
1078 1085 extras--verbose: branch=default
1079 1086 extras--verbose: branch=default
1080 1087 extras--verbose: branch=default
1081 1088 extras--verbose: branch=default
1082 1089 extras--debug: branch=default
1083 1090 extras--debug: branch=default
1084 1091 extras--debug: branch=default
1085 1092 extras--debug: branch=default
1086 1093 extras--debug: branch=foo
1087 1094 extras--debug: branch=default
1088 1095 extras--debug: branch=default
1089 1096 extras--debug: branch=default
1090 1097 extras--debug: branch=default
1091 1098
1092 1099
1093 1100 Filters work:
1094 1101
1095 1102 $ hg log --template '{author|domain}\n'
1096 1103
1097 1104 hostname
1098 1105
1099 1106
1100 1107
1101 1108
1102 1109 place
1103 1110 place
1104 1111 hostname
1105 1112
1106 1113 $ hg log --template '{author|person}\n'
1107 1114 test
1108 1115 User Name
1109 1116 person
1110 1117 person
1111 1118 person
1112 1119 person
1113 1120 other
1114 1121 A. N. Other
1115 1122 User Name
1116 1123
1117 1124 $ hg log --template '{author|user}\n'
1118 1125 test
1119 1126 user
1120 1127 person
1121 1128 person
1122 1129 person
1123 1130 person
1124 1131 other
1125 1132 other
1126 1133 user
1127 1134
1128 1135 $ hg log --template '{date|date}\n'
1129 1136 Wed Jan 01 10:01:00 2020 +0000
1130 1137 Mon Jan 12 13:46:40 1970 +0000
1131 1138 Sun Jan 18 08:40:01 1970 +0000
1132 1139 Sun Jan 18 08:40:00 1970 +0000
1133 1140 Sat Jan 17 04:53:20 1970 +0000
1134 1141 Fri Jan 16 01:06:40 1970 +0000
1135 1142 Wed Jan 14 21:20:00 1970 +0000
1136 1143 Tue Jan 13 17:33:20 1970 +0000
1137 1144 Mon Jan 12 13:46:40 1970 +0000
1138 1145
1139 1146 $ hg log --template '{date|isodate}\n'
1140 1147 2020-01-01 10:01 +0000
1141 1148 1970-01-12 13:46 +0000
1142 1149 1970-01-18 08:40 +0000
1143 1150 1970-01-18 08:40 +0000
1144 1151 1970-01-17 04:53 +0000
1145 1152 1970-01-16 01:06 +0000
1146 1153 1970-01-14 21:20 +0000
1147 1154 1970-01-13 17:33 +0000
1148 1155 1970-01-12 13:46 +0000
1149 1156
1150 1157 $ hg log --template '{date|isodatesec}\n'
1151 1158 2020-01-01 10:01:00 +0000
1152 1159 1970-01-12 13:46:40 +0000
1153 1160 1970-01-18 08:40:01 +0000
1154 1161 1970-01-18 08:40:00 +0000
1155 1162 1970-01-17 04:53:20 +0000
1156 1163 1970-01-16 01:06:40 +0000
1157 1164 1970-01-14 21:20:00 +0000
1158 1165 1970-01-13 17:33:20 +0000
1159 1166 1970-01-12 13:46:40 +0000
1160 1167
1161 1168 $ hg log --template '{date|rfc822date}\n'
1162 1169 Wed, 01 Jan 2020 10:01:00 +0000
1163 1170 Mon, 12 Jan 1970 13:46:40 +0000
1164 1171 Sun, 18 Jan 1970 08:40:01 +0000
1165 1172 Sun, 18 Jan 1970 08:40:00 +0000
1166 1173 Sat, 17 Jan 1970 04:53:20 +0000
1167 1174 Fri, 16 Jan 1970 01:06:40 +0000
1168 1175 Wed, 14 Jan 1970 21:20:00 +0000
1169 1176 Tue, 13 Jan 1970 17:33:20 +0000
1170 1177 Mon, 12 Jan 1970 13:46:40 +0000
1171 1178
1172 1179 $ hg log --template '{desc|firstline}\n'
1173 1180 third
1174 1181 second
1175 1182 merge
1176 1183 new head
1177 1184 new branch
1178 1185 no user, no domain
1179 1186 no person
1180 1187 other 1
1181 1188 line 1
1182 1189
1183 1190 $ hg log --template '{node|short}\n'
1184 1191 95c24699272e
1185 1192 29114dbae42b
1186 1193 d41e714fe50d
1187 1194 13207e5a10d9
1188 1195 bbe44766e73d
1189 1196 10e46f2dcbf4
1190 1197 97054abb4ab8
1191 1198 b608e9d1a3f0
1192 1199 1e4e1b8f71e0
1193 1200
1194 1201 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1195 1202 <changeset author="test"/>
1196 1203 <changeset author="User Name &lt;user@hostname&gt;"/>
1197 1204 <changeset author="person"/>
1198 1205 <changeset author="person"/>
1199 1206 <changeset author="person"/>
1200 1207 <changeset author="person"/>
1201 1208 <changeset author="other@place"/>
1202 1209 <changeset author="A. N. Other &lt;other@place&gt;"/>
1203 1210 <changeset author="User Name &lt;user@hostname&gt;"/>
1204 1211
1205 1212 $ hg log --template '{rev}: {children}\n'
1206 1213 8:
1207 1214 7: 8:95c24699272e
1208 1215 6:
1209 1216 5: 6:d41e714fe50d
1210 1217 4: 6:d41e714fe50d
1211 1218 3: 4:bbe44766e73d 5:13207e5a10d9
1212 1219 2: 3:10e46f2dcbf4
1213 1220 1: 2:97054abb4ab8
1214 1221 0: 1:b608e9d1a3f0
1215 1222
1216 1223 Formatnode filter works:
1217 1224
1218 1225 $ hg -q log -r 0 --template '{node|formatnode}\n'
1219 1226 1e4e1b8f71e0
1220 1227
1221 1228 $ hg log -r 0 --template '{node|formatnode}\n'
1222 1229 1e4e1b8f71e0
1223 1230
1224 1231 $ hg -v log -r 0 --template '{node|formatnode}\n'
1225 1232 1e4e1b8f71e0
1226 1233
1227 1234 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1228 1235 1e4e1b8f71e05681d422154f5421e385fec3454f
1229 1236
1230 1237 Age filter:
1231 1238
1232 1239 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1233 1240
1234 1241 >>> from datetime import datetime
1235 1242 >>> fp = open('a', 'w')
1236 1243 >>> fp.write(str(datetime.now().year + 8) + '-01-01 00:00')
1237 1244 >>> fp.close()
1238 1245 $ hg add a
1239 1246 $ hg commit -m future -d "`cat a`"
1240 1247
1241 1248 $ hg log -l1 --template '{date|age}\n'
1242 1249 7 years from now
1243 1250
1244 1251 Error on syntax:
1245 1252
1246 1253 $ echo 'x = "f' >> t
1247 1254 $ hg log
1248 1255 abort: t:3: unmatched quotes
1249 1256 [255]
1250 1257
1251 1258 $ cd ..
1252 1259
1253 1260
1254 1261 latesttag:
1255 1262
1256 1263 $ hg init latesttag
1257 1264 $ cd latesttag
1258 1265
1259 1266 $ echo a > file
1260 1267 $ hg ci -Am a -d '0 0'
1261 1268 adding file
1262 1269
1263 1270 $ echo b >> file
1264 1271 $ hg ci -m b -d '1 0'
1265 1272
1266 1273 $ echo c >> head1
1267 1274 $ hg ci -Am h1c -d '2 0'
1268 1275 adding head1
1269 1276
1270 1277 $ hg update -q 1
1271 1278 $ echo d >> head2
1272 1279 $ hg ci -Am h2d -d '3 0'
1273 1280 adding head2
1274 1281 created new head
1275 1282
1276 1283 $ echo e >> head2
1277 1284 $ hg ci -m h2e -d '4 0'
1278 1285
1279 1286 $ hg merge -q
1280 1287 $ hg ci -m merge -d '5 0'
1281 1288
1282 1289 No tag set:
1283 1290
1284 1291 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1285 1292 5: null+5
1286 1293 4: null+4
1287 1294 3: null+3
1288 1295 2: null+3
1289 1296 1: null+2
1290 1297 0: null+1
1291 1298
1292 1299 One common tag: longuest path wins:
1293 1300
1294 1301 $ hg tag -r 1 -m t1 -d '6 0' t1
1295 1302 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1296 1303 6: t1+4
1297 1304 5: t1+3
1298 1305 4: t1+2
1299 1306 3: t1+1
1300 1307 2: t1+1
1301 1308 1: t1+0
1302 1309 0: null+1
1303 1310
1304 1311 One ancestor tag: more recent wins:
1305 1312
1306 1313 $ hg tag -r 2 -m t2 -d '7 0' t2
1307 1314 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1308 1315 7: t2+3
1309 1316 6: t2+2
1310 1317 5: t2+1
1311 1318 4: t1+2
1312 1319 3: t1+1
1313 1320 2: t2+0
1314 1321 1: t1+0
1315 1322 0: null+1
1316 1323
1317 1324 Two branch tags: more recent wins:
1318 1325
1319 1326 $ hg tag -r 3 -m t3 -d '8 0' t3
1320 1327 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1321 1328 8: t3+5
1322 1329 7: t3+4
1323 1330 6: t3+3
1324 1331 5: t3+2
1325 1332 4: t3+1
1326 1333 3: t3+0
1327 1334 2: t2+0
1328 1335 1: t1+0
1329 1336 0: null+1
1330 1337
1331 1338 Merged tag overrides:
1332 1339
1333 1340 $ hg tag -r 5 -m t5 -d '9 0' t5
1334 1341 $ hg tag -r 3 -m at3 -d '10 0' at3
1335 1342 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1336 1343 10: t5+5
1337 1344 9: t5+4
1338 1345 8: t5+3
1339 1346 7: t5+2
1340 1347 6: t5+1
1341 1348 5: t5+0
1342 1349 4: at3:t3+1
1343 1350 3: at3:t3+0
1344 1351 2: t2+0
1345 1352 1: t1+0
1346 1353 0: null+1
1347 1354
1348 1355 $ cd ..
1349 1356
1350 1357
1351 1358 Style path expansion: issue1948 - ui.style option doesn't work on OSX
1352 1359 if it is a relative path
1353 1360
1354 1361 $ mkdir -p home/styles
1355 1362
1356 1363 $ cat > home/styles/teststyle <<EOF
1357 1364 > changeset = 'test {rev}:{node|short}\n'
1358 1365 > EOF
1359 1366
1360 1367 $ HOME=`pwd`/home; export HOME
1361 1368
1362 1369 $ cat > latesttag/.hg/hgrc <<EOF
1363 1370 > [ui]
1364 1371 > style = ~/styles/teststyle
1365 1372 > EOF
1366 1373
1367 1374 $ hg -R latesttag tip
1368 1375 test 10:dee8f28249af
1369 1376
1370 1377 Test recursive showlist template (issue1989):
1371 1378
1372 1379 $ cat > style1989 <<EOF
1373 1380 > changeset = '{file_mods}{manifest}{extras}'
1374 1381 > file_mod = 'M|{author|person}\n'
1375 1382 > manifest = '{rev},{author}\n'
1376 1383 > extra = '{key}: {author}\n'
1377 1384 > EOF
1378 1385
1379 1386 $ hg -R latesttag log -r tip --style=style1989
1380 1387 M|test
1381 1388 10,test
1382 1389 branch: test
1383 1390
General Comments 0
You need to be logged in to leave comments. Login now