##// END OF EJS Templates
templatefilters: declare input type as date where appropriate...
Yuya Nishihara -
r37244:9bcf096a default
parent child Browse files
Show More
@@ -1,443 +1,443 b''
1 # registrar.py - utilities to register function for specific purpose
1 # registrar.py - utilities to register function for specific purpose
2 #
2 #
3 # Copyright FUJIWARA Katsunori <foozy@lares.dti.ne.jp> and others
3 # Copyright FUJIWARA Katsunori <foozy@lares.dti.ne.jp> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 from . import (
10 from . import (
11 configitems,
11 configitems,
12 error,
12 error,
13 pycompat,
13 pycompat,
14 util,
14 util,
15 )
15 )
16
16
17 # unlike the other registered items, config options are neither functions or
17 # unlike the other registered items, config options are neither functions or
18 # classes. Registering the option is just small function call.
18 # classes. Registering the option is just small function call.
19 #
19 #
20 # We still add the official API to the registrar module for consistency with
20 # We still add the official API to the registrar module for consistency with
21 # the other items extensions want might to register.
21 # the other items extensions want might to register.
22 configitem = configitems.getitemregister
22 configitem = configitems.getitemregister
23
23
24 class _funcregistrarbase(object):
24 class _funcregistrarbase(object):
25 """Base of decorator to register a function for specific purpose
25 """Base of decorator to register a function for specific purpose
26
26
27 This decorator stores decorated functions into own dict 'table'.
27 This decorator stores decorated functions into own dict 'table'.
28
28
29 The least derived class can be defined by overriding 'formatdoc',
29 The least derived class can be defined by overriding 'formatdoc',
30 for example::
30 for example::
31
31
32 class keyword(_funcregistrarbase):
32 class keyword(_funcregistrarbase):
33 _docformat = ":%s: %s"
33 _docformat = ":%s: %s"
34
34
35 This should be used as below:
35 This should be used as below:
36
36
37 keyword = registrar.keyword()
37 keyword = registrar.keyword()
38
38
39 @keyword('bar')
39 @keyword('bar')
40 def barfunc(*args, **kwargs):
40 def barfunc(*args, **kwargs):
41 '''Explanation of bar keyword ....
41 '''Explanation of bar keyword ....
42 '''
42 '''
43 pass
43 pass
44
44
45 In this case:
45 In this case:
46
46
47 - 'barfunc' is stored as 'bar' in '_table' of an instance 'keyword' above
47 - 'barfunc' is stored as 'bar' in '_table' of an instance 'keyword' above
48 - 'barfunc.__doc__' becomes ":bar: Explanation of bar keyword"
48 - 'barfunc.__doc__' becomes ":bar: Explanation of bar keyword"
49 """
49 """
50 def __init__(self, table=None):
50 def __init__(self, table=None):
51 if table is None:
51 if table is None:
52 self._table = {}
52 self._table = {}
53 else:
53 else:
54 self._table = table
54 self._table = table
55
55
56 def __call__(self, decl, *args, **kwargs):
56 def __call__(self, decl, *args, **kwargs):
57 return lambda func: self._doregister(func, decl, *args, **kwargs)
57 return lambda func: self._doregister(func, decl, *args, **kwargs)
58
58
59 def _doregister(self, func, decl, *args, **kwargs):
59 def _doregister(self, func, decl, *args, **kwargs):
60 name = self._getname(decl)
60 name = self._getname(decl)
61
61
62 if name in self._table:
62 if name in self._table:
63 msg = 'duplicate registration for name: "%s"' % name
63 msg = 'duplicate registration for name: "%s"' % name
64 raise error.ProgrammingError(msg)
64 raise error.ProgrammingError(msg)
65
65
66 if func.__doc__ and not util.safehasattr(func, '_origdoc'):
66 if func.__doc__ and not util.safehasattr(func, '_origdoc'):
67 doc = pycompat.sysbytes(func.__doc__).strip()
67 doc = pycompat.sysbytes(func.__doc__).strip()
68 func._origdoc = doc
68 func._origdoc = doc
69 func.__doc__ = pycompat.sysstr(self._formatdoc(decl, doc))
69 func.__doc__ = pycompat.sysstr(self._formatdoc(decl, doc))
70
70
71 self._table[name] = func
71 self._table[name] = func
72 self._extrasetup(name, func, *args, **kwargs)
72 self._extrasetup(name, func, *args, **kwargs)
73
73
74 return func
74 return func
75
75
76 def _parsefuncdecl(self, decl):
76 def _parsefuncdecl(self, decl):
77 """Parse function declaration and return the name of function in it
77 """Parse function declaration and return the name of function in it
78 """
78 """
79 i = decl.find('(')
79 i = decl.find('(')
80 if i >= 0:
80 if i >= 0:
81 return decl[:i]
81 return decl[:i]
82 else:
82 else:
83 return decl
83 return decl
84
84
85 def _getname(self, decl):
85 def _getname(self, decl):
86 """Return the name of the registered function from decl
86 """Return the name of the registered function from decl
87
87
88 Derived class should override this, if it allows more
88 Derived class should override this, if it allows more
89 descriptive 'decl' string than just a name.
89 descriptive 'decl' string than just a name.
90 """
90 """
91 return decl
91 return decl
92
92
93 _docformat = None
93 _docformat = None
94
94
95 def _formatdoc(self, decl, doc):
95 def _formatdoc(self, decl, doc):
96 """Return formatted document of the registered function for help
96 """Return formatted document of the registered function for help
97
97
98 'doc' is '__doc__.strip()' of the registered function.
98 'doc' is '__doc__.strip()' of the registered function.
99 """
99 """
100 return self._docformat % (decl, doc)
100 return self._docformat % (decl, doc)
101
101
102 def _extrasetup(self, name, func):
102 def _extrasetup(self, name, func):
103 """Execute exra setup for registered function, if needed
103 """Execute exra setup for registered function, if needed
104 """
104 """
105
105
106 class command(_funcregistrarbase):
106 class command(_funcregistrarbase):
107 """Decorator to register a command function to table
107 """Decorator to register a command function to table
108
108
109 This class receives a command table as its argument. The table should
109 This class receives a command table as its argument. The table should
110 be a dict.
110 be a dict.
111
111
112 The created object can be used as a decorator for adding commands to
112 The created object can be used as a decorator for adding commands to
113 that command table. This accepts multiple arguments to define a command.
113 that command table. This accepts multiple arguments to define a command.
114
114
115 The first argument is the command name (as bytes).
115 The first argument is the command name (as bytes).
116
116
117 The `options` keyword argument is an iterable of tuples defining command
117 The `options` keyword argument is an iterable of tuples defining command
118 arguments. See ``mercurial.fancyopts.fancyopts()`` for the format of each
118 arguments. See ``mercurial.fancyopts.fancyopts()`` for the format of each
119 tuple.
119 tuple.
120
120
121 The `synopsis` argument defines a short, one line summary of how to use the
121 The `synopsis` argument defines a short, one line summary of how to use the
122 command. This shows up in the help output.
122 command. This shows up in the help output.
123
123
124 There are three arguments that control what repository (if any) is found
124 There are three arguments that control what repository (if any) is found
125 and passed to the decorated function: `norepo`, `optionalrepo`, and
125 and passed to the decorated function: `norepo`, `optionalrepo`, and
126 `inferrepo`.
126 `inferrepo`.
127
127
128 The `norepo` argument defines whether the command does not require a
128 The `norepo` argument defines whether the command does not require a
129 local repository. Most commands operate against a repository, thus the
129 local repository. Most commands operate against a repository, thus the
130 default is False. When True, no repository will be passed.
130 default is False. When True, no repository will be passed.
131
131
132 The `optionalrepo` argument defines whether the command optionally requires
132 The `optionalrepo` argument defines whether the command optionally requires
133 a local repository. If no repository can be found, None will be passed
133 a local repository. If no repository can be found, None will be passed
134 to the decorated function.
134 to the decorated function.
135
135
136 The `inferrepo` argument defines whether to try to find a repository from
136 The `inferrepo` argument defines whether to try to find a repository from
137 the command line arguments. If True, arguments will be examined for
137 the command line arguments. If True, arguments will be examined for
138 potential repository locations. See ``findrepo()``. If a repository is
138 potential repository locations. See ``findrepo()``. If a repository is
139 found, it will be used and passed to the decorated function.
139 found, it will be used and passed to the decorated function.
140
140
141 There are three constants in the class which tells what type of the command
141 There are three constants in the class which tells what type of the command
142 that is. That information will be helpful at various places. It will be also
142 that is. That information will be helpful at various places. It will be also
143 be used to decide what level of access the command has on hidden commits.
143 be used to decide what level of access the command has on hidden commits.
144 The constants are:
144 The constants are:
145
145
146 `unrecoverablewrite` is for those write commands which can't be recovered
146 `unrecoverablewrite` is for those write commands which can't be recovered
147 like push.
147 like push.
148 `recoverablewrite` is for write commands which can be recovered like commit.
148 `recoverablewrite` is for write commands which can be recovered like commit.
149 `readonly` is for commands which are read only.
149 `readonly` is for commands which are read only.
150
150
151 The signature of the decorated function looks like this:
151 The signature of the decorated function looks like this:
152 def cmd(ui[, repo] [, <args>] [, <options>])
152 def cmd(ui[, repo] [, <args>] [, <options>])
153
153
154 `repo` is required if `norepo` is False.
154 `repo` is required if `norepo` is False.
155 `<args>` are positional args (or `*args`) arguments, of non-option
155 `<args>` are positional args (or `*args`) arguments, of non-option
156 arguments from the command line.
156 arguments from the command line.
157 `<options>` are keyword arguments (or `**options`) of option arguments
157 `<options>` are keyword arguments (or `**options`) of option arguments
158 from the command line.
158 from the command line.
159
159
160 See the WritingExtensions and MercurialApi documentation for more exhaustive
160 See the WritingExtensions and MercurialApi documentation for more exhaustive
161 descriptions and examples.
161 descriptions and examples.
162 """
162 """
163
163
164 unrecoverablewrite = "unrecoverable"
164 unrecoverablewrite = "unrecoverable"
165 recoverablewrite = "recoverable"
165 recoverablewrite = "recoverable"
166 readonly = "readonly"
166 readonly = "readonly"
167
167
168 possiblecmdtypes = {unrecoverablewrite, recoverablewrite, readonly}
168 possiblecmdtypes = {unrecoverablewrite, recoverablewrite, readonly}
169
169
170 def _doregister(self, func, name, options=(), synopsis=None,
170 def _doregister(self, func, name, options=(), synopsis=None,
171 norepo=False, optionalrepo=False, inferrepo=False,
171 norepo=False, optionalrepo=False, inferrepo=False,
172 cmdtype=unrecoverablewrite):
172 cmdtype=unrecoverablewrite):
173
173
174 if cmdtype not in self.possiblecmdtypes:
174 if cmdtype not in self.possiblecmdtypes:
175 raise error.ProgrammingError("unknown cmdtype value '%s' for "
175 raise error.ProgrammingError("unknown cmdtype value '%s' for "
176 "'%s' command" % (cmdtype, name))
176 "'%s' command" % (cmdtype, name))
177 func.norepo = norepo
177 func.norepo = norepo
178 func.optionalrepo = optionalrepo
178 func.optionalrepo = optionalrepo
179 func.inferrepo = inferrepo
179 func.inferrepo = inferrepo
180 func.cmdtype = cmdtype
180 func.cmdtype = cmdtype
181 if synopsis:
181 if synopsis:
182 self._table[name] = func, list(options), synopsis
182 self._table[name] = func, list(options), synopsis
183 else:
183 else:
184 self._table[name] = func, list(options)
184 self._table[name] = func, list(options)
185 return func
185 return func
186
186
187 class revsetpredicate(_funcregistrarbase):
187 class revsetpredicate(_funcregistrarbase):
188 """Decorator to register revset predicate
188 """Decorator to register revset predicate
189
189
190 Usage::
190 Usage::
191
191
192 revsetpredicate = registrar.revsetpredicate()
192 revsetpredicate = registrar.revsetpredicate()
193
193
194 @revsetpredicate('mypredicate(arg1, arg2[, arg3])')
194 @revsetpredicate('mypredicate(arg1, arg2[, arg3])')
195 def mypredicatefunc(repo, subset, x):
195 def mypredicatefunc(repo, subset, x):
196 '''Explanation of this revset predicate ....
196 '''Explanation of this revset predicate ....
197 '''
197 '''
198 pass
198 pass
199
199
200 The first string argument is used also in online help.
200 The first string argument is used also in online help.
201
201
202 Optional argument 'safe' indicates whether a predicate is safe for
202 Optional argument 'safe' indicates whether a predicate is safe for
203 DoS attack (False by default).
203 DoS attack (False by default).
204
204
205 Optional argument 'takeorder' indicates whether a predicate function
205 Optional argument 'takeorder' indicates whether a predicate function
206 takes ordering policy as the last argument.
206 takes ordering policy as the last argument.
207
207
208 Optional argument 'weight' indicates the estimated run-time cost, useful
208 Optional argument 'weight' indicates the estimated run-time cost, useful
209 for static optimization, default is 1. Higher weight means more expensive.
209 for static optimization, default is 1. Higher weight means more expensive.
210 Usually, revsets that are fast and return only one revision has a weight of
210 Usually, revsets that are fast and return only one revision has a weight of
211 0.5 (ex. a symbol); revsets with O(changelog) complexity and read only the
211 0.5 (ex. a symbol); revsets with O(changelog) complexity and read only the
212 changelog have weight 10 (ex. author); revsets reading manifest deltas have
212 changelog have weight 10 (ex. author); revsets reading manifest deltas have
213 weight 30 (ex. adds); revset reading manifest contents have weight 100
213 weight 30 (ex. adds); revset reading manifest contents have weight 100
214 (ex. contains). Note: those values are flexible. If the revset has a
214 (ex. contains). Note: those values are flexible. If the revset has a
215 same big-O time complexity as 'contains', but with a smaller constant, it
215 same big-O time complexity as 'contains', but with a smaller constant, it
216 might have a weight of 90.
216 might have a weight of 90.
217
217
218 'revsetpredicate' instance in example above can be used to
218 'revsetpredicate' instance in example above can be used to
219 decorate multiple functions.
219 decorate multiple functions.
220
220
221 Decorated functions are registered automatically at loading
221 Decorated functions are registered automatically at loading
222 extension, if an instance named as 'revsetpredicate' is used for
222 extension, if an instance named as 'revsetpredicate' is used for
223 decorating in extension.
223 decorating in extension.
224
224
225 Otherwise, explicit 'revset.loadpredicate()' is needed.
225 Otherwise, explicit 'revset.loadpredicate()' is needed.
226 """
226 """
227 _getname = _funcregistrarbase._parsefuncdecl
227 _getname = _funcregistrarbase._parsefuncdecl
228 _docformat = "``%s``\n %s"
228 _docformat = "``%s``\n %s"
229
229
230 def _extrasetup(self, name, func, safe=False, takeorder=False, weight=1):
230 def _extrasetup(self, name, func, safe=False, takeorder=False, weight=1):
231 func._safe = safe
231 func._safe = safe
232 func._takeorder = takeorder
232 func._takeorder = takeorder
233 func._weight = weight
233 func._weight = weight
234
234
235 class filesetpredicate(_funcregistrarbase):
235 class filesetpredicate(_funcregistrarbase):
236 """Decorator to register fileset predicate
236 """Decorator to register fileset predicate
237
237
238 Usage::
238 Usage::
239
239
240 filesetpredicate = registrar.filesetpredicate()
240 filesetpredicate = registrar.filesetpredicate()
241
241
242 @filesetpredicate('mypredicate()')
242 @filesetpredicate('mypredicate()')
243 def mypredicatefunc(mctx, x):
243 def mypredicatefunc(mctx, x):
244 '''Explanation of this fileset predicate ....
244 '''Explanation of this fileset predicate ....
245 '''
245 '''
246 pass
246 pass
247
247
248 The first string argument is used also in online help.
248 The first string argument is used also in online help.
249
249
250 Optional argument 'callstatus' indicates whether a predicate
250 Optional argument 'callstatus' indicates whether a predicate
251 implies 'matchctx.status()' at runtime or not (False, by
251 implies 'matchctx.status()' at runtime or not (False, by
252 default).
252 default).
253
253
254 Optional argument 'callexisting' indicates whether a predicate
254 Optional argument 'callexisting' indicates whether a predicate
255 implies 'matchctx.existing()' at runtime or not (False, by
255 implies 'matchctx.existing()' at runtime or not (False, by
256 default).
256 default).
257
257
258 'filesetpredicate' instance in example above can be used to
258 'filesetpredicate' instance in example above can be used to
259 decorate multiple functions.
259 decorate multiple functions.
260
260
261 Decorated functions are registered automatically at loading
261 Decorated functions are registered automatically at loading
262 extension, if an instance named as 'filesetpredicate' is used for
262 extension, if an instance named as 'filesetpredicate' is used for
263 decorating in extension.
263 decorating in extension.
264
264
265 Otherwise, explicit 'fileset.loadpredicate()' is needed.
265 Otherwise, explicit 'fileset.loadpredicate()' is needed.
266 """
266 """
267 _getname = _funcregistrarbase._parsefuncdecl
267 _getname = _funcregistrarbase._parsefuncdecl
268 _docformat = "``%s``\n %s"
268 _docformat = "``%s``\n %s"
269
269
270 def _extrasetup(self, name, func, callstatus=False, callexisting=False):
270 def _extrasetup(self, name, func, callstatus=False, callexisting=False):
271 func._callstatus = callstatus
271 func._callstatus = callstatus
272 func._callexisting = callexisting
272 func._callexisting = callexisting
273
273
274 class _templateregistrarbase(_funcregistrarbase):
274 class _templateregistrarbase(_funcregistrarbase):
275 """Base of decorator to register functions as template specific one
275 """Base of decorator to register functions as template specific one
276 """
276 """
277 _docformat = ":%s: %s"
277 _docformat = ":%s: %s"
278
278
279 class templatekeyword(_templateregistrarbase):
279 class templatekeyword(_templateregistrarbase):
280 """Decorator to register template keyword
280 """Decorator to register template keyword
281
281
282 Usage::
282 Usage::
283
283
284 templatekeyword = registrar.templatekeyword()
284 templatekeyword = registrar.templatekeyword()
285
285
286 # new API (since Mercurial 4.6)
286 # new API (since Mercurial 4.6)
287 @templatekeyword('mykeyword', requires={'repo', 'ctx'})
287 @templatekeyword('mykeyword', requires={'repo', 'ctx'})
288 def mykeywordfunc(context, mapping):
288 def mykeywordfunc(context, mapping):
289 '''Explanation of this template keyword ....
289 '''Explanation of this template keyword ....
290 '''
290 '''
291 pass
291 pass
292
292
293 # old API
293 # old API
294 @templatekeyword('mykeyword')
294 @templatekeyword('mykeyword')
295 def mykeywordfunc(repo, ctx, templ, cache, revcache, **args):
295 def mykeywordfunc(repo, ctx, templ, cache, revcache, **args):
296 '''Explanation of this template keyword ....
296 '''Explanation of this template keyword ....
297 '''
297 '''
298 pass
298 pass
299
299
300 The first string argument is used also in online help.
300 The first string argument is used also in online help.
301
301
302 Optional argument 'requires' should be a collection of resource names
302 Optional argument 'requires' should be a collection of resource names
303 which the template keyword depends on. This also serves as a flag to
303 which the template keyword depends on. This also serves as a flag to
304 switch to the new API. If 'requires' is unspecified, all template
304 switch to the new API. If 'requires' is unspecified, all template
305 keywords and resources are expanded to the function arguments.
305 keywords and resources are expanded to the function arguments.
306
306
307 'templatekeyword' instance in example above can be used to
307 'templatekeyword' instance in example above can be used to
308 decorate multiple functions.
308 decorate multiple functions.
309
309
310 Decorated functions are registered automatically at loading
310 Decorated functions are registered automatically at loading
311 extension, if an instance named as 'templatekeyword' is used for
311 extension, if an instance named as 'templatekeyword' is used for
312 decorating in extension.
312 decorating in extension.
313
313
314 Otherwise, explicit 'templatekw.loadkeyword()' is needed.
314 Otherwise, explicit 'templatekw.loadkeyword()' is needed.
315 """
315 """
316
316
317 def _extrasetup(self, name, func, requires=None):
317 def _extrasetup(self, name, func, requires=None):
318 func._requires = requires
318 func._requires = requires
319
319
320 class templatefilter(_templateregistrarbase):
320 class templatefilter(_templateregistrarbase):
321 """Decorator to register template filer
321 """Decorator to register template filer
322
322
323 Usage::
323 Usage::
324
324
325 templatefilter = registrar.templatefilter()
325 templatefilter = registrar.templatefilter()
326
326
327 @templatefilter('myfilter', intype=bytes)
327 @templatefilter('myfilter', intype=bytes)
328 def myfilterfunc(text):
328 def myfilterfunc(text):
329 '''Explanation of this template filter ....
329 '''Explanation of this template filter ....
330 '''
330 '''
331 pass
331 pass
332
332
333 The first string argument is used also in online help.
333 The first string argument is used also in online help.
334
334
335 Optional argument 'intype' defines the type of the input argument,
335 Optional argument 'intype' defines the type of the input argument,
336 which should be (bytes, int, or None for any.)
336 which should be (bytes, int, templateutil.date, or None for any.)
337
337
338 'templatefilter' instance in example above can be used to
338 'templatefilter' instance in example above can be used to
339 decorate multiple functions.
339 decorate multiple functions.
340
340
341 Decorated functions are registered automatically at loading
341 Decorated functions are registered automatically at loading
342 extension, if an instance named as 'templatefilter' is used for
342 extension, if an instance named as 'templatefilter' is used for
343 decorating in extension.
343 decorating in extension.
344
344
345 Otherwise, explicit 'templatefilters.loadkeyword()' is needed.
345 Otherwise, explicit 'templatefilters.loadkeyword()' is needed.
346 """
346 """
347
347
348 def _extrasetup(self, name, func, intype=None):
348 def _extrasetup(self, name, func, intype=None):
349 func._intype = intype
349 func._intype = intype
350
350
351 class templatefunc(_templateregistrarbase):
351 class templatefunc(_templateregistrarbase):
352 """Decorator to register template function
352 """Decorator to register template function
353
353
354 Usage::
354 Usage::
355
355
356 templatefunc = registrar.templatefunc()
356 templatefunc = registrar.templatefunc()
357
357
358 @templatefunc('myfunc(arg1, arg2[, arg3])', argspec='arg1 arg2 arg3')
358 @templatefunc('myfunc(arg1, arg2[, arg3])', argspec='arg1 arg2 arg3')
359 def myfuncfunc(context, mapping, args):
359 def myfuncfunc(context, mapping, args):
360 '''Explanation of this template function ....
360 '''Explanation of this template function ....
361 '''
361 '''
362 pass
362 pass
363
363
364 The first string argument is used also in online help.
364 The first string argument is used also in online help.
365
365
366 If optional 'argspec' is defined, the function will receive 'args' as
366 If optional 'argspec' is defined, the function will receive 'args' as
367 a dict of named arguments. Otherwise 'args' is a list of positional
367 a dict of named arguments. Otherwise 'args' is a list of positional
368 arguments.
368 arguments.
369
369
370 'templatefunc' instance in example above can be used to
370 'templatefunc' instance in example above can be used to
371 decorate multiple functions.
371 decorate multiple functions.
372
372
373 Decorated functions are registered automatically at loading
373 Decorated functions are registered automatically at loading
374 extension, if an instance named as 'templatefunc' is used for
374 extension, if an instance named as 'templatefunc' is used for
375 decorating in extension.
375 decorating in extension.
376
376
377 Otherwise, explicit 'templatefuncs.loadfunction()' is needed.
377 Otherwise, explicit 'templatefuncs.loadfunction()' is needed.
378 """
378 """
379 _getname = _funcregistrarbase._parsefuncdecl
379 _getname = _funcregistrarbase._parsefuncdecl
380
380
381 def _extrasetup(self, name, func, argspec=None):
381 def _extrasetup(self, name, func, argspec=None):
382 func._argspec = argspec
382 func._argspec = argspec
383
383
384 class internalmerge(_funcregistrarbase):
384 class internalmerge(_funcregistrarbase):
385 """Decorator to register in-process merge tool
385 """Decorator to register in-process merge tool
386
386
387 Usage::
387 Usage::
388
388
389 internalmerge = registrar.internalmerge()
389 internalmerge = registrar.internalmerge()
390
390
391 @internalmerge('mymerge', internalmerge.mergeonly,
391 @internalmerge('mymerge', internalmerge.mergeonly,
392 onfailure=None, precheck=None):
392 onfailure=None, precheck=None):
393 def mymergefunc(repo, mynode, orig, fcd, fco, fca,
393 def mymergefunc(repo, mynode, orig, fcd, fco, fca,
394 toolconf, files, labels=None):
394 toolconf, files, labels=None):
395 '''Explanation of this internal merge tool ....
395 '''Explanation of this internal merge tool ....
396 '''
396 '''
397 return 1, False # means "conflicted", "no deletion needed"
397 return 1, False # means "conflicted", "no deletion needed"
398
398
399 The first string argument is used to compose actual merge tool name,
399 The first string argument is used to compose actual merge tool name,
400 ":name" and "internal:name" (the latter is historical one).
400 ":name" and "internal:name" (the latter is historical one).
401
401
402 The second argument is one of merge types below:
402 The second argument is one of merge types below:
403
403
404 ========== ======== ======== =========
404 ========== ======== ======== =========
405 merge type precheck premerge fullmerge
405 merge type precheck premerge fullmerge
406 ========== ======== ======== =========
406 ========== ======== ======== =========
407 nomerge x x x
407 nomerge x x x
408 mergeonly o x o
408 mergeonly o x o
409 fullmerge o o o
409 fullmerge o o o
410 ========== ======== ======== =========
410 ========== ======== ======== =========
411
411
412 Optional argument 'onfailure' is the format of warning message
412 Optional argument 'onfailure' is the format of warning message
413 to be used at failure of merging (target filename is specified
413 to be used at failure of merging (target filename is specified
414 at formatting). Or, None or so, if warning message should be
414 at formatting). Or, None or so, if warning message should be
415 suppressed.
415 suppressed.
416
416
417 Optional argument 'precheck' is the function to be used
417 Optional argument 'precheck' is the function to be used
418 before actual invocation of internal merge tool itself.
418 before actual invocation of internal merge tool itself.
419 It takes as same arguments as internal merge tool does, other than
419 It takes as same arguments as internal merge tool does, other than
420 'files' and 'labels'. If it returns false value, merging is aborted
420 'files' and 'labels'. If it returns false value, merging is aborted
421 immediately (and file is marked as "unresolved").
421 immediately (and file is marked as "unresolved").
422
422
423 'internalmerge' instance in example above can be used to
423 'internalmerge' instance in example above can be used to
424 decorate multiple functions.
424 decorate multiple functions.
425
425
426 Decorated functions are registered automatically at loading
426 Decorated functions are registered automatically at loading
427 extension, if an instance named as 'internalmerge' is used for
427 extension, if an instance named as 'internalmerge' is used for
428 decorating in extension.
428 decorating in extension.
429
429
430 Otherwise, explicit 'filemerge.loadinternalmerge()' is needed.
430 Otherwise, explicit 'filemerge.loadinternalmerge()' is needed.
431 """
431 """
432 _docformat = "``:%s``\n %s"
432 _docformat = "``:%s``\n %s"
433
433
434 # merge type definitions:
434 # merge type definitions:
435 nomerge = None
435 nomerge = None
436 mergeonly = 'mergeonly' # just the full merge, no premerge
436 mergeonly = 'mergeonly' # just the full merge, no premerge
437 fullmerge = 'fullmerge' # both premerge and merge
437 fullmerge = 'fullmerge' # both premerge and merge
438
438
439 def _extrasetup(self, name, func, mergetype,
439 def _extrasetup(self, name, func, mergetype,
440 onfailure=None, precheck=None):
440 onfailure=None, precheck=None):
441 func.mergetype = mergetype
441 func.mergetype = mergetype
442 func.onfailure = onfailure
442 func.onfailure = onfailure
443 func.precheck = precheck
443 func.precheck = precheck
@@ -1,436 +1,436 b''
1 # templatefilters.py - common template expansion filters
1 # templatefilters.py - common template expansion filters
2 #
2 #
3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import os
10 import os
11 import re
11 import re
12 import time
12 import time
13
13
14 from . import (
14 from . import (
15 encoding,
15 encoding,
16 error,
16 error,
17 node,
17 node,
18 pycompat,
18 pycompat,
19 registrar,
19 registrar,
20 templateutil,
20 templateutil,
21 url,
21 url,
22 util,
22 util,
23 )
23 )
24 from .utils import (
24 from .utils import (
25 dateutil,
25 dateutil,
26 stringutil,
26 stringutil,
27 )
27 )
28
28
29 urlerr = util.urlerr
29 urlerr = util.urlerr
30 urlreq = util.urlreq
30 urlreq = util.urlreq
31
31
32 if pycompat.ispy3:
32 if pycompat.ispy3:
33 long = int
33 long = int
34
34
35 # filters are callables like:
35 # filters are callables like:
36 # fn(obj)
36 # fn(obj)
37 # with:
37 # with:
38 # obj - object to be filtered (text, date, list and so on)
38 # obj - object to be filtered (text, date, list and so on)
39 filters = {}
39 filters = {}
40
40
41 templatefilter = registrar.templatefilter(filters)
41 templatefilter = registrar.templatefilter(filters)
42
42
43 @templatefilter('addbreaks', intype=bytes)
43 @templatefilter('addbreaks', intype=bytes)
44 def addbreaks(text):
44 def addbreaks(text):
45 """Any text. Add an XHTML "<br />" tag before the end of
45 """Any text. Add an XHTML "<br />" tag before the end of
46 every line except the last.
46 every line except the last.
47 """
47 """
48 return text.replace('\n', '<br/>\n')
48 return text.replace('\n', '<br/>\n')
49
49
50 agescales = [("year", 3600 * 24 * 365, 'Y'),
50 agescales = [("year", 3600 * 24 * 365, 'Y'),
51 ("month", 3600 * 24 * 30, 'M'),
51 ("month", 3600 * 24 * 30, 'M'),
52 ("week", 3600 * 24 * 7, 'W'),
52 ("week", 3600 * 24 * 7, 'W'),
53 ("day", 3600 * 24, 'd'),
53 ("day", 3600 * 24, 'd'),
54 ("hour", 3600, 'h'),
54 ("hour", 3600, 'h'),
55 ("minute", 60, 'm'),
55 ("minute", 60, 'm'),
56 ("second", 1, 's')]
56 ("second", 1, 's')]
57
57
58 @templatefilter('age')
58 @templatefilter('age', intype=templateutil.date)
59 def age(date, abbrev=False):
59 def age(date, abbrev=False):
60 """Date. Returns a human-readable date/time difference between the
60 """Date. Returns a human-readable date/time difference between the
61 given date/time and the current date/time.
61 given date/time and the current date/time.
62 """
62 """
63
63
64 def plural(t, c):
64 def plural(t, c):
65 if c == 1:
65 if c == 1:
66 return t
66 return t
67 return t + "s"
67 return t + "s"
68 def fmt(t, c, a):
68 def fmt(t, c, a):
69 if abbrev:
69 if abbrev:
70 return "%d%s" % (c, a)
70 return "%d%s" % (c, a)
71 return "%d %s" % (c, plural(t, c))
71 return "%d %s" % (c, plural(t, c))
72
72
73 now = time.time()
73 now = time.time()
74 then = date[0]
74 then = date[0]
75 future = False
75 future = False
76 if then > now:
76 if then > now:
77 future = True
77 future = True
78 delta = max(1, int(then - now))
78 delta = max(1, int(then - now))
79 if delta > agescales[0][1] * 30:
79 if delta > agescales[0][1] * 30:
80 return 'in the distant future'
80 return 'in the distant future'
81 else:
81 else:
82 delta = max(1, int(now - then))
82 delta = max(1, int(now - then))
83 if delta > agescales[0][1] * 2:
83 if delta > agescales[0][1] * 2:
84 return dateutil.shortdate(date)
84 return dateutil.shortdate(date)
85
85
86 for t, s, a in agescales:
86 for t, s, a in agescales:
87 n = delta // s
87 n = delta // s
88 if n >= 2 or s == 1:
88 if n >= 2 or s == 1:
89 if future:
89 if future:
90 return '%s from now' % fmt(t, n, a)
90 return '%s from now' % fmt(t, n, a)
91 return '%s ago' % fmt(t, n, a)
91 return '%s ago' % fmt(t, n, a)
92
92
93 @templatefilter('basename', intype=bytes)
93 @templatefilter('basename', intype=bytes)
94 def basename(path):
94 def basename(path):
95 """Any text. Treats the text as a path, and returns the last
95 """Any text. Treats the text as a path, and returns the last
96 component of the path after splitting by the path separator.
96 component of the path after splitting by the path separator.
97 For example, "foo/bar/baz" becomes "baz" and "foo/bar//" becomes "".
97 For example, "foo/bar/baz" becomes "baz" and "foo/bar//" becomes "".
98 """
98 """
99 return os.path.basename(path)
99 return os.path.basename(path)
100
100
101 @templatefilter('count')
101 @templatefilter('count')
102 def count(i):
102 def count(i):
103 """List or text. Returns the length as an integer."""
103 """List or text. Returns the length as an integer."""
104 return len(i)
104 return len(i)
105
105
106 @templatefilter('dirname', intype=bytes)
106 @templatefilter('dirname', intype=bytes)
107 def dirname(path):
107 def dirname(path):
108 """Any text. Treats the text as a path, and strips the last
108 """Any text. Treats the text as a path, and strips the last
109 component of the path after splitting by the path separator.
109 component of the path after splitting by the path separator.
110 """
110 """
111 return os.path.dirname(path)
111 return os.path.dirname(path)
112
112
113 @templatefilter('domain', intype=bytes)
113 @templatefilter('domain', intype=bytes)
114 def domain(author):
114 def domain(author):
115 """Any text. Finds the first string that looks like an email
115 """Any text. Finds the first string that looks like an email
116 address, and extracts just the domain component. Example: ``User
116 address, and extracts just the domain component. Example: ``User
117 <user@example.com>`` becomes ``example.com``.
117 <user@example.com>`` becomes ``example.com``.
118 """
118 """
119 f = author.find('@')
119 f = author.find('@')
120 if f == -1:
120 if f == -1:
121 return ''
121 return ''
122 author = author[f + 1:]
122 author = author[f + 1:]
123 f = author.find('>')
123 f = author.find('>')
124 if f >= 0:
124 if f >= 0:
125 author = author[:f]
125 author = author[:f]
126 return author
126 return author
127
127
128 @templatefilter('email', intype=bytes)
128 @templatefilter('email', intype=bytes)
129 def email(text):
129 def email(text):
130 """Any text. Extracts the first string that looks like an email
130 """Any text. Extracts the first string that looks like an email
131 address. Example: ``User <user@example.com>`` becomes
131 address. Example: ``User <user@example.com>`` becomes
132 ``user@example.com``.
132 ``user@example.com``.
133 """
133 """
134 return stringutil.email(text)
134 return stringutil.email(text)
135
135
136 @templatefilter('escape', intype=bytes)
136 @templatefilter('escape', intype=bytes)
137 def escape(text):
137 def escape(text):
138 """Any text. Replaces the special XML/XHTML characters "&", "<"
138 """Any text. Replaces the special XML/XHTML characters "&", "<"
139 and ">" with XML entities, and filters out NUL characters.
139 and ">" with XML entities, and filters out NUL characters.
140 """
140 """
141 return url.escape(text.replace('\0', ''), True)
141 return url.escape(text.replace('\0', ''), True)
142
142
143 para_re = None
143 para_re = None
144 space_re = None
144 space_re = None
145
145
146 def fill(text, width, initindent='', hangindent=''):
146 def fill(text, width, initindent='', hangindent=''):
147 '''fill many paragraphs with optional indentation.'''
147 '''fill many paragraphs with optional indentation.'''
148 global para_re, space_re
148 global para_re, space_re
149 if para_re is None:
149 if para_re is None:
150 para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
150 para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
151 space_re = re.compile(br' +')
151 space_re = re.compile(br' +')
152
152
153 def findparas():
153 def findparas():
154 start = 0
154 start = 0
155 while True:
155 while True:
156 m = para_re.search(text, start)
156 m = para_re.search(text, start)
157 if not m:
157 if not m:
158 uctext = encoding.unifromlocal(text[start:])
158 uctext = encoding.unifromlocal(text[start:])
159 w = len(uctext)
159 w = len(uctext)
160 while 0 < w and uctext[w - 1].isspace():
160 while 0 < w and uctext[w - 1].isspace():
161 w -= 1
161 w -= 1
162 yield (encoding.unitolocal(uctext[:w]),
162 yield (encoding.unitolocal(uctext[:w]),
163 encoding.unitolocal(uctext[w:]))
163 encoding.unitolocal(uctext[w:]))
164 break
164 break
165 yield text[start:m.start(0)], m.group(1)
165 yield text[start:m.start(0)], m.group(1)
166 start = m.end(1)
166 start = m.end(1)
167
167
168 return "".join([stringutil.wrap(space_re.sub(' ',
168 return "".join([stringutil.wrap(space_re.sub(' ',
169 stringutil.wrap(para, width)),
169 stringutil.wrap(para, width)),
170 width, initindent, hangindent) + rest
170 width, initindent, hangindent) + rest
171 for para, rest in findparas()])
171 for para, rest in findparas()])
172
172
173 @templatefilter('fill68', intype=bytes)
173 @templatefilter('fill68', intype=bytes)
174 def fill68(text):
174 def fill68(text):
175 """Any text. Wraps the text to fit in 68 columns."""
175 """Any text. Wraps the text to fit in 68 columns."""
176 return fill(text, 68)
176 return fill(text, 68)
177
177
178 @templatefilter('fill76', intype=bytes)
178 @templatefilter('fill76', intype=bytes)
179 def fill76(text):
179 def fill76(text):
180 """Any text. Wraps the text to fit in 76 columns."""
180 """Any text. Wraps the text to fit in 76 columns."""
181 return fill(text, 76)
181 return fill(text, 76)
182
182
183 @templatefilter('firstline', intype=bytes)
183 @templatefilter('firstline', intype=bytes)
184 def firstline(text):
184 def firstline(text):
185 """Any text. Returns the first line of text."""
185 """Any text. Returns the first line of text."""
186 try:
186 try:
187 return text.splitlines(True)[0].rstrip('\r\n')
187 return text.splitlines(True)[0].rstrip('\r\n')
188 except IndexError:
188 except IndexError:
189 return ''
189 return ''
190
190
191 @templatefilter('hex', intype=bytes)
191 @templatefilter('hex', intype=bytes)
192 def hexfilter(text):
192 def hexfilter(text):
193 """Any text. Convert a binary Mercurial node identifier into
193 """Any text. Convert a binary Mercurial node identifier into
194 its long hexadecimal representation.
194 its long hexadecimal representation.
195 """
195 """
196 return node.hex(text)
196 return node.hex(text)
197
197
198 @templatefilter('hgdate')
198 @templatefilter('hgdate', intype=templateutil.date)
199 def hgdate(text):
199 def hgdate(text):
200 """Date. Returns the date as a pair of numbers: "1157407993
200 """Date. Returns the date as a pair of numbers: "1157407993
201 25200" (Unix timestamp, timezone offset).
201 25200" (Unix timestamp, timezone offset).
202 """
202 """
203 return "%d %d" % text
203 return "%d %d" % text
204
204
205 @templatefilter('isodate')
205 @templatefilter('isodate', intype=templateutil.date)
206 def isodate(text):
206 def isodate(text):
207 """Date. Returns the date in ISO 8601 format: "2009-08-18 13:00
207 """Date. Returns the date in ISO 8601 format: "2009-08-18 13:00
208 +0200".
208 +0200".
209 """
209 """
210 return dateutil.datestr(text, '%Y-%m-%d %H:%M %1%2')
210 return dateutil.datestr(text, '%Y-%m-%d %H:%M %1%2')
211
211
212 @templatefilter('isodatesec')
212 @templatefilter('isodatesec', intype=templateutil.date)
213 def isodatesec(text):
213 def isodatesec(text):
214 """Date. Returns the date in ISO 8601 format, including
214 """Date. Returns the date in ISO 8601 format, including
215 seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date
215 seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date
216 filter.
216 filter.
217 """
217 """
218 return dateutil.datestr(text, '%Y-%m-%d %H:%M:%S %1%2')
218 return dateutil.datestr(text, '%Y-%m-%d %H:%M:%S %1%2')
219
219
220 def indent(text, prefix):
220 def indent(text, prefix):
221 '''indent each non-empty line of text after first with prefix.'''
221 '''indent each non-empty line of text after first with prefix.'''
222 lines = text.splitlines()
222 lines = text.splitlines()
223 num_lines = len(lines)
223 num_lines = len(lines)
224 endswithnewline = text[-1:] == '\n'
224 endswithnewline = text[-1:] == '\n'
225 def indenter():
225 def indenter():
226 for i in xrange(num_lines):
226 for i in xrange(num_lines):
227 l = lines[i]
227 l = lines[i]
228 if i and l.strip():
228 if i and l.strip():
229 yield prefix
229 yield prefix
230 yield l
230 yield l
231 if i < num_lines - 1 or endswithnewline:
231 if i < num_lines - 1 or endswithnewline:
232 yield '\n'
232 yield '\n'
233 return "".join(indenter())
233 return "".join(indenter())
234
234
235 @templatefilter('json')
235 @templatefilter('json')
236 def json(obj, paranoid=True):
236 def json(obj, paranoid=True):
237 if obj is None:
237 if obj is None:
238 return 'null'
238 return 'null'
239 elif obj is False:
239 elif obj is False:
240 return 'false'
240 return 'false'
241 elif obj is True:
241 elif obj is True:
242 return 'true'
242 return 'true'
243 elif isinstance(obj, (int, long, float)):
243 elif isinstance(obj, (int, long, float)):
244 return pycompat.bytestr(obj)
244 return pycompat.bytestr(obj)
245 elif isinstance(obj, bytes):
245 elif isinstance(obj, bytes):
246 return '"%s"' % encoding.jsonescape(obj, paranoid=paranoid)
246 return '"%s"' % encoding.jsonescape(obj, paranoid=paranoid)
247 elif isinstance(obj, str):
247 elif isinstance(obj, str):
248 # This branch is unreachable on Python 2, because bytes == str
248 # This branch is unreachable on Python 2, because bytes == str
249 # and we'll return in the next-earlier block in the elif
249 # and we'll return in the next-earlier block in the elif
250 # ladder. On Python 3, this helps us catch bugs before they
250 # ladder. On Python 3, this helps us catch bugs before they
251 # hurt someone.
251 # hurt someone.
252 raise error.ProgrammingError(
252 raise error.ProgrammingError(
253 'Mercurial only does output with bytes on Python 3: %r' % obj)
253 'Mercurial only does output with bytes on Python 3: %r' % obj)
254 elif util.safehasattr(obj, 'keys'):
254 elif util.safehasattr(obj, 'keys'):
255 out = ['"%s": %s' % (encoding.jsonescape(k, paranoid=paranoid),
255 out = ['"%s": %s' % (encoding.jsonescape(k, paranoid=paranoid),
256 json(v, paranoid))
256 json(v, paranoid))
257 for k, v in sorted(obj.iteritems())]
257 for k, v in sorted(obj.iteritems())]
258 return '{' + ', '.join(out) + '}'
258 return '{' + ', '.join(out) + '}'
259 elif util.safehasattr(obj, '__iter__'):
259 elif util.safehasattr(obj, '__iter__'):
260 out = [json(i, paranoid) for i in obj]
260 out = [json(i, paranoid) for i in obj]
261 return '[' + ', '.join(out) + ']'
261 return '[' + ', '.join(out) + ']'
262 else:
262 else:
263 raise TypeError('cannot encode type %s' % obj.__class__.__name__)
263 raise TypeError('cannot encode type %s' % obj.__class__.__name__)
264
264
265 @templatefilter('lower', intype=bytes)
265 @templatefilter('lower', intype=bytes)
266 def lower(text):
266 def lower(text):
267 """Any text. Converts the text to lowercase."""
267 """Any text. Converts the text to lowercase."""
268 return encoding.lower(text)
268 return encoding.lower(text)
269
269
270 @templatefilter('nonempty', intype=bytes)
270 @templatefilter('nonempty', intype=bytes)
271 def nonempty(text):
271 def nonempty(text):
272 """Any text. Returns '(none)' if the string is empty."""
272 """Any text. Returns '(none)' if the string is empty."""
273 return text or "(none)"
273 return text or "(none)"
274
274
275 @templatefilter('obfuscate', intype=bytes)
275 @templatefilter('obfuscate', intype=bytes)
276 def obfuscate(text):
276 def obfuscate(text):
277 """Any text. Returns the input text rendered as a sequence of
277 """Any text. Returns the input text rendered as a sequence of
278 XML entities.
278 XML entities.
279 """
279 """
280 text = unicode(text, pycompat.sysstr(encoding.encoding), r'replace')
280 text = unicode(text, pycompat.sysstr(encoding.encoding), r'replace')
281 return ''.join(['&#%d;' % ord(c) for c in text])
281 return ''.join(['&#%d;' % ord(c) for c in text])
282
282
283 @templatefilter('permissions', intype=bytes)
283 @templatefilter('permissions', intype=bytes)
284 def permissions(flags):
284 def permissions(flags):
285 if "l" in flags:
285 if "l" in flags:
286 return "lrwxrwxrwx"
286 return "lrwxrwxrwx"
287 if "x" in flags:
287 if "x" in flags:
288 return "-rwxr-xr-x"
288 return "-rwxr-xr-x"
289 return "-rw-r--r--"
289 return "-rw-r--r--"
290
290
291 @templatefilter('person', intype=bytes)
291 @templatefilter('person', intype=bytes)
292 def person(author):
292 def person(author):
293 """Any text. Returns the name before an email address,
293 """Any text. Returns the name before an email address,
294 interpreting it as per RFC 5322.
294 interpreting it as per RFC 5322.
295 """
295 """
296 return stringutil.person(author)
296 return stringutil.person(author)
297
297
298 @templatefilter('revescape', intype=bytes)
298 @templatefilter('revescape', intype=bytes)
299 def revescape(text):
299 def revescape(text):
300 """Any text. Escapes all "special" characters, except @.
300 """Any text. Escapes all "special" characters, except @.
301 Forward slashes are escaped twice to prevent web servers from prematurely
301 Forward slashes are escaped twice to prevent web servers from prematurely
302 unescaping them. For example, "@foo bar/baz" becomes "@foo%20bar%252Fbaz".
302 unescaping them. For example, "@foo bar/baz" becomes "@foo%20bar%252Fbaz".
303 """
303 """
304 return urlreq.quote(text, safe='/@').replace('/', '%252F')
304 return urlreq.quote(text, safe='/@').replace('/', '%252F')
305
305
306 @templatefilter('rfc3339date')
306 @templatefilter('rfc3339date', intype=templateutil.date)
307 def rfc3339date(text):
307 def rfc3339date(text):
308 """Date. Returns a date using the Internet date format
308 """Date. Returns a date using the Internet date format
309 specified in RFC 3339: "2009-08-18T13:00:13+02:00".
309 specified in RFC 3339: "2009-08-18T13:00:13+02:00".
310 """
310 """
311 return dateutil.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2")
311 return dateutil.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2")
312
312
313 @templatefilter('rfc822date')
313 @templatefilter('rfc822date', intype=templateutil.date)
314 def rfc822date(text):
314 def rfc822date(text):
315 """Date. Returns a date using the same format used in email
315 """Date. Returns a date using the same format used in email
316 headers: "Tue, 18 Aug 2009 13:00:13 +0200".
316 headers: "Tue, 18 Aug 2009 13:00:13 +0200".
317 """
317 """
318 return dateutil.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
318 return dateutil.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
319
319
320 @templatefilter('short', intype=bytes)
320 @templatefilter('short', intype=bytes)
321 def short(text):
321 def short(text):
322 """Changeset hash. Returns the short form of a changeset hash,
322 """Changeset hash. Returns the short form of a changeset hash,
323 i.e. a 12 hexadecimal digit string.
323 i.e. a 12 hexadecimal digit string.
324 """
324 """
325 return text[:12]
325 return text[:12]
326
326
327 @templatefilter('shortbisect', intype=bytes)
327 @templatefilter('shortbisect', intype=bytes)
328 def shortbisect(label):
328 def shortbisect(label):
329 """Any text. Treats `label` as a bisection status, and
329 """Any text. Treats `label` as a bisection status, and
330 returns a single-character representing the status (G: good, B: bad,
330 returns a single-character representing the status (G: good, B: bad,
331 S: skipped, U: untested, I: ignored). Returns single space if `text`
331 S: skipped, U: untested, I: ignored). Returns single space if `text`
332 is not a valid bisection status.
332 is not a valid bisection status.
333 """
333 """
334 if label:
334 if label:
335 return label[0:1].upper()
335 return label[0:1].upper()
336 return ' '
336 return ' '
337
337
338 @templatefilter('shortdate')
338 @templatefilter('shortdate', intype=templateutil.date)
339 def shortdate(text):
339 def shortdate(text):
340 """Date. Returns a date like "2006-09-18"."""
340 """Date. Returns a date like "2006-09-18"."""
341 return dateutil.shortdate(text)
341 return dateutil.shortdate(text)
342
342
343 @templatefilter('slashpath', intype=bytes)
343 @templatefilter('slashpath', intype=bytes)
344 def slashpath(path):
344 def slashpath(path):
345 """Any text. Replaces the native path separator with slash."""
345 """Any text. Replaces the native path separator with slash."""
346 return util.pconvert(path)
346 return util.pconvert(path)
347
347
348 @templatefilter('splitlines', intype=bytes)
348 @templatefilter('splitlines', intype=bytes)
349 def splitlines(text):
349 def splitlines(text):
350 """Any text. Split text into a list of lines."""
350 """Any text. Split text into a list of lines."""
351 return templateutil.hybridlist(text.splitlines(), name='line')
351 return templateutil.hybridlist(text.splitlines(), name='line')
352
352
353 @templatefilter('stringescape', intype=bytes)
353 @templatefilter('stringescape', intype=bytes)
354 def stringescape(text):
354 def stringescape(text):
355 return stringutil.escapestr(text)
355 return stringutil.escapestr(text)
356
356
357 @templatefilter('stringify', intype=bytes)
357 @templatefilter('stringify', intype=bytes)
358 def stringify(thing):
358 def stringify(thing):
359 """Any type. Turns the value into text by converting values into
359 """Any type. Turns the value into text by converting values into
360 text and concatenating them.
360 text and concatenating them.
361 """
361 """
362 return thing # coerced by the intype
362 return thing # coerced by the intype
363
363
364 @templatefilter('stripdir', intype=bytes)
364 @templatefilter('stripdir', intype=bytes)
365 def stripdir(text):
365 def stripdir(text):
366 """Treat the text as path and strip a directory level, if
366 """Treat the text as path and strip a directory level, if
367 possible. For example, "foo" and "foo/bar" becomes "foo".
367 possible. For example, "foo" and "foo/bar" becomes "foo".
368 """
368 """
369 dir = os.path.dirname(text)
369 dir = os.path.dirname(text)
370 if dir == "":
370 if dir == "":
371 return os.path.basename(text)
371 return os.path.basename(text)
372 else:
372 else:
373 return dir
373 return dir
374
374
375 @templatefilter('tabindent', intype=bytes)
375 @templatefilter('tabindent', intype=bytes)
376 def tabindent(text):
376 def tabindent(text):
377 """Any text. Returns the text, with every non-empty line
377 """Any text. Returns the text, with every non-empty line
378 except the first starting with a tab character.
378 except the first starting with a tab character.
379 """
379 """
380 return indent(text, '\t')
380 return indent(text, '\t')
381
381
382 @templatefilter('upper', intype=bytes)
382 @templatefilter('upper', intype=bytes)
383 def upper(text):
383 def upper(text):
384 """Any text. Converts the text to uppercase."""
384 """Any text. Converts the text to uppercase."""
385 return encoding.upper(text)
385 return encoding.upper(text)
386
386
387 @templatefilter('urlescape', intype=bytes)
387 @templatefilter('urlescape', intype=bytes)
388 def urlescape(text):
388 def urlescape(text):
389 """Any text. Escapes all "special" characters. For example,
389 """Any text. Escapes all "special" characters. For example,
390 "foo bar" becomes "foo%20bar".
390 "foo bar" becomes "foo%20bar".
391 """
391 """
392 return urlreq.quote(text)
392 return urlreq.quote(text)
393
393
394 @templatefilter('user', intype=bytes)
394 @templatefilter('user', intype=bytes)
395 def userfilter(text):
395 def userfilter(text):
396 """Any text. Returns a short representation of a user name or email
396 """Any text. Returns a short representation of a user name or email
397 address."""
397 address."""
398 return stringutil.shortuser(text)
398 return stringutil.shortuser(text)
399
399
400 @templatefilter('emailuser', intype=bytes)
400 @templatefilter('emailuser', intype=bytes)
401 def emailuser(text):
401 def emailuser(text):
402 """Any text. Returns the user portion of an email address."""
402 """Any text. Returns the user portion of an email address."""
403 return stringutil.emailuser(text)
403 return stringutil.emailuser(text)
404
404
405 @templatefilter('utf8', intype=bytes)
405 @templatefilter('utf8', intype=bytes)
406 def utf8(text):
406 def utf8(text):
407 """Any text. Converts from the local character encoding to UTF-8."""
407 """Any text. Converts from the local character encoding to UTF-8."""
408 return encoding.fromlocal(text)
408 return encoding.fromlocal(text)
409
409
410 @templatefilter('xmlescape', intype=bytes)
410 @templatefilter('xmlescape', intype=bytes)
411 def xmlescape(text):
411 def xmlescape(text):
412 text = (text
412 text = (text
413 .replace('&', '&amp;')
413 .replace('&', '&amp;')
414 .replace('<', '&lt;')
414 .replace('<', '&lt;')
415 .replace('>', '&gt;')
415 .replace('>', '&gt;')
416 .replace('"', '&quot;')
416 .replace('"', '&quot;')
417 .replace("'", '&#39;')) # &apos; invalid in HTML
417 .replace("'", '&#39;')) # &apos; invalid in HTML
418 return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
418 return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
419
419
420 def websub(text, websubtable):
420 def websub(text, websubtable):
421 """:websub: Any text. Only applies to hgweb. Applies the regular
421 """:websub: Any text. Only applies to hgweb. Applies the regular
422 expression replacements defined in the websub section.
422 expression replacements defined in the websub section.
423 """
423 """
424 if websubtable:
424 if websubtable:
425 for regexp, format in websubtable:
425 for regexp, format in websubtable:
426 text = regexp.sub(format, text)
426 text = regexp.sub(format, text)
427 return text
427 return text
428
428
429 def loadfilter(ui, extname, registrarobj):
429 def loadfilter(ui, extname, registrarobj):
430 """Load template filter from specified registrarobj
430 """Load template filter from specified registrarobj
431 """
431 """
432 for name, func in registrarobj._table.iteritems():
432 for name, func in registrarobj._table.iteritems():
433 filters[name] = func
433 filters[name] = func
434
434
435 # tell hggettext to extract docstrings from these functions:
435 # tell hggettext to extract docstrings from these functions:
436 i18nfunctions = filters.values()
436 i18nfunctions = filters.values()
@@ -1,499 +1,505 b''
1 # templateutil.py - utility for template evaluation
1 # templateutil.py - utility for template evaluation
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import types
10 import types
11
11
12 from .i18n import _
12 from .i18n import _
13 from . import (
13 from . import (
14 error,
14 error,
15 pycompat,
15 pycompat,
16 util,
16 util,
17 )
17 )
18 from .utils import (
18 from .utils import (
19 dateutil,
19 dateutil,
20 stringutil,
20 stringutil,
21 )
21 )
22
22
23 class ResourceUnavailable(error.Abort):
23 class ResourceUnavailable(error.Abort):
24 pass
24 pass
25
25
26 class TemplateNotFound(error.Abort):
26 class TemplateNotFound(error.Abort):
27 pass
27 pass
28
28
29 # stub for representing a date type; may be a real date type that can
30 # provide a readable string value
31 class date(object):
32 pass
33
29 class hybrid(object):
34 class hybrid(object):
30 """Wrapper for list or dict to support legacy template
35 """Wrapper for list or dict to support legacy template
31
36
32 This class allows us to handle both:
37 This class allows us to handle both:
33 - "{files}" (legacy command-line-specific list hack) and
38 - "{files}" (legacy command-line-specific list hack) and
34 - "{files % '{file}\n'}" (hgweb-style with inlining and function support)
39 - "{files % '{file}\n'}" (hgweb-style with inlining and function support)
35 and to access raw values:
40 and to access raw values:
36 - "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
41 - "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
37 - "{get(extras, key)}"
42 - "{get(extras, key)}"
38 - "{files|json}"
43 - "{files|json}"
39 """
44 """
40
45
41 def __init__(self, gen, values, makemap, joinfmt, keytype=None):
46 def __init__(self, gen, values, makemap, joinfmt, keytype=None):
42 if gen is not None:
47 if gen is not None:
43 self.gen = gen # generator or function returning generator
48 self.gen = gen # generator or function returning generator
44 self._values = values
49 self._values = values
45 self._makemap = makemap
50 self._makemap = makemap
46 self.joinfmt = joinfmt
51 self.joinfmt = joinfmt
47 self.keytype = keytype # hint for 'x in y' where type(x) is unresolved
52 self.keytype = keytype # hint for 'x in y' where type(x) is unresolved
48 def gen(self):
53 def gen(self):
49 """Default generator to stringify this as {join(self, ' ')}"""
54 """Default generator to stringify this as {join(self, ' ')}"""
50 for i, x in enumerate(self._values):
55 for i, x in enumerate(self._values):
51 if i > 0:
56 if i > 0:
52 yield ' '
57 yield ' '
53 yield self.joinfmt(x)
58 yield self.joinfmt(x)
54 def itermaps(self):
59 def itermaps(self):
55 makemap = self._makemap
60 makemap = self._makemap
56 for x in self._values:
61 for x in self._values:
57 yield makemap(x)
62 yield makemap(x)
58 def __contains__(self, x):
63 def __contains__(self, x):
59 return x in self._values
64 return x in self._values
60 def __getitem__(self, key):
65 def __getitem__(self, key):
61 return self._values[key]
66 return self._values[key]
62 def __len__(self):
67 def __len__(self):
63 return len(self._values)
68 return len(self._values)
64 def __iter__(self):
69 def __iter__(self):
65 return iter(self._values)
70 return iter(self._values)
66 def __getattr__(self, name):
71 def __getattr__(self, name):
67 if name not in (r'get', r'items', r'iteritems', r'iterkeys',
72 if name not in (r'get', r'items', r'iteritems', r'iterkeys',
68 r'itervalues', r'keys', r'values'):
73 r'itervalues', r'keys', r'values'):
69 raise AttributeError(name)
74 raise AttributeError(name)
70 return getattr(self._values, name)
75 return getattr(self._values, name)
71
76
72 class mappable(object):
77 class mappable(object):
73 """Wrapper for non-list/dict object to support map operation
78 """Wrapper for non-list/dict object to support map operation
74
79
75 This class allows us to handle both:
80 This class allows us to handle both:
76 - "{manifest}"
81 - "{manifest}"
77 - "{manifest % '{rev}:{node}'}"
82 - "{manifest % '{rev}:{node}'}"
78 - "{manifest.rev}"
83 - "{manifest.rev}"
79
84
80 Unlike a hybrid, this does not simulate the behavior of the underling
85 Unlike a hybrid, this does not simulate the behavior of the underling
81 value. Use unwrapvalue(), unwrapastype(), or unwraphybrid() to obtain
86 value. Use unwrapvalue(), unwrapastype(), or unwraphybrid() to obtain
82 the inner object.
87 the inner object.
83 """
88 """
84
89
85 def __init__(self, gen, key, value, makemap):
90 def __init__(self, gen, key, value, makemap):
86 if gen is not None:
91 if gen is not None:
87 self.gen = gen # generator or function returning generator
92 self.gen = gen # generator or function returning generator
88 self._key = key
93 self._key = key
89 self._value = value # may be generator of strings
94 self._value = value # may be generator of strings
90 self._makemap = makemap
95 self._makemap = makemap
91
96
92 def gen(self):
97 def gen(self):
93 yield pycompat.bytestr(self._value)
98 yield pycompat.bytestr(self._value)
94
99
95 def tomap(self):
100 def tomap(self):
96 return self._makemap(self._key)
101 return self._makemap(self._key)
97
102
98 def itermaps(self):
103 def itermaps(self):
99 yield self.tomap()
104 yield self.tomap()
100
105
101 def hybriddict(data, key='key', value='value', fmt=None, gen=None):
106 def hybriddict(data, key='key', value='value', fmt=None, gen=None):
102 """Wrap data to support both dict-like and string-like operations"""
107 """Wrap data to support both dict-like and string-like operations"""
103 prefmt = pycompat.identity
108 prefmt = pycompat.identity
104 if fmt is None:
109 if fmt is None:
105 fmt = '%s=%s'
110 fmt = '%s=%s'
106 prefmt = pycompat.bytestr
111 prefmt = pycompat.bytestr
107 return hybrid(gen, data, lambda k: {key: k, value: data[k]},
112 return hybrid(gen, data, lambda k: {key: k, value: data[k]},
108 lambda k: fmt % (prefmt(k), prefmt(data[k])))
113 lambda k: fmt % (prefmt(k), prefmt(data[k])))
109
114
110 def hybridlist(data, name, fmt=None, gen=None):
115 def hybridlist(data, name, fmt=None, gen=None):
111 """Wrap data to support both list-like and string-like operations"""
116 """Wrap data to support both list-like and string-like operations"""
112 prefmt = pycompat.identity
117 prefmt = pycompat.identity
113 if fmt is None:
118 if fmt is None:
114 fmt = '%s'
119 fmt = '%s'
115 prefmt = pycompat.bytestr
120 prefmt = pycompat.bytestr
116 return hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % prefmt(x))
121 return hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % prefmt(x))
117
122
118 def unwraphybrid(thing):
123 def unwraphybrid(thing):
119 """Return an object which can be stringified possibly by using a legacy
124 """Return an object which can be stringified possibly by using a legacy
120 template"""
125 template"""
121 gen = getattr(thing, 'gen', None)
126 gen = getattr(thing, 'gen', None)
122 if gen is None:
127 if gen is None:
123 return thing
128 return thing
124 if callable(gen):
129 if callable(gen):
125 return gen()
130 return gen()
126 return gen
131 return gen
127
132
128 def unwrapvalue(thing):
133 def unwrapvalue(thing):
129 """Move the inner value object out of the wrapper"""
134 """Move the inner value object out of the wrapper"""
130 if not util.safehasattr(thing, '_value'):
135 if not util.safehasattr(thing, '_value'):
131 return thing
136 return thing
132 return thing._value
137 return thing._value
133
138
134 def wraphybridvalue(container, key, value):
139 def wraphybridvalue(container, key, value):
135 """Wrap an element of hybrid container to be mappable
140 """Wrap an element of hybrid container to be mappable
136
141
137 The key is passed to the makemap function of the given container, which
142 The key is passed to the makemap function of the given container, which
138 should be an item generated by iter(container).
143 should be an item generated by iter(container).
139 """
144 """
140 makemap = getattr(container, '_makemap', None)
145 makemap = getattr(container, '_makemap', None)
141 if makemap is None:
146 if makemap is None:
142 return value
147 return value
143 if util.safehasattr(value, '_makemap'):
148 if util.safehasattr(value, '_makemap'):
144 # a nested hybrid list/dict, which has its own way of map operation
149 # a nested hybrid list/dict, which has its own way of map operation
145 return value
150 return value
146 return mappable(None, key, value, makemap)
151 return mappable(None, key, value, makemap)
147
152
148 def compatdict(context, mapping, name, data, key='key', value='value',
153 def compatdict(context, mapping, name, data, key='key', value='value',
149 fmt=None, plural=None, separator=' '):
154 fmt=None, plural=None, separator=' '):
150 """Wrap data like hybriddict(), but also supports old-style list template
155 """Wrap data like hybriddict(), but also supports old-style list template
151
156
152 This exists for backward compatibility with the old-style template. Use
157 This exists for backward compatibility with the old-style template. Use
153 hybriddict() for new template keywords.
158 hybriddict() for new template keywords.
154 """
159 """
155 c = [{key: k, value: v} for k, v in data.iteritems()]
160 c = [{key: k, value: v} for k, v in data.iteritems()]
156 f = _showcompatlist(context, mapping, name, c, plural, separator)
161 f = _showcompatlist(context, mapping, name, c, plural, separator)
157 return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
162 return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
158
163
159 def compatlist(context, mapping, name, data, element=None, fmt=None,
164 def compatlist(context, mapping, name, data, element=None, fmt=None,
160 plural=None, separator=' '):
165 plural=None, separator=' '):
161 """Wrap data like hybridlist(), but also supports old-style list template
166 """Wrap data like hybridlist(), but also supports old-style list template
162
167
163 This exists for backward compatibility with the old-style template. Use
168 This exists for backward compatibility with the old-style template. Use
164 hybridlist() for new template keywords.
169 hybridlist() for new template keywords.
165 """
170 """
166 f = _showcompatlist(context, mapping, name, data, plural, separator)
171 f = _showcompatlist(context, mapping, name, data, plural, separator)
167 return hybridlist(data, name=element or name, fmt=fmt, gen=f)
172 return hybridlist(data, name=element or name, fmt=fmt, gen=f)
168
173
169 def _showcompatlist(context, mapping, name, values, plural=None, separator=' '):
174 def _showcompatlist(context, mapping, name, values, plural=None, separator=' '):
170 """Return a generator that renders old-style list template
175 """Return a generator that renders old-style list template
171
176
172 name is name of key in template map.
177 name is name of key in template map.
173 values is list of strings or dicts.
178 values is list of strings or dicts.
174 plural is plural of name, if not simply name + 's'.
179 plural is plural of name, if not simply name + 's'.
175 separator is used to join values as a string
180 separator is used to join values as a string
176
181
177 expansion works like this, given name 'foo'.
182 expansion works like this, given name 'foo'.
178
183
179 if values is empty, expand 'no_foos'.
184 if values is empty, expand 'no_foos'.
180
185
181 if 'foo' not in template map, return values as a string,
186 if 'foo' not in template map, return values as a string,
182 joined by 'separator'.
187 joined by 'separator'.
183
188
184 expand 'start_foos'.
189 expand 'start_foos'.
185
190
186 for each value, expand 'foo'. if 'last_foo' in template
191 for each value, expand 'foo'. if 'last_foo' in template
187 map, expand it instead of 'foo' for last key.
192 map, expand it instead of 'foo' for last key.
188
193
189 expand 'end_foos'.
194 expand 'end_foos'.
190 """
195 """
191 if not plural:
196 if not plural:
192 plural = name + 's'
197 plural = name + 's'
193 if not values:
198 if not values:
194 noname = 'no_' + plural
199 noname = 'no_' + plural
195 if context.preload(noname):
200 if context.preload(noname):
196 yield context.process(noname, mapping)
201 yield context.process(noname, mapping)
197 return
202 return
198 if not context.preload(name):
203 if not context.preload(name):
199 if isinstance(values[0], bytes):
204 if isinstance(values[0], bytes):
200 yield separator.join(values)
205 yield separator.join(values)
201 else:
206 else:
202 for v in values:
207 for v in values:
203 r = dict(v)
208 r = dict(v)
204 r.update(mapping)
209 r.update(mapping)
205 yield r
210 yield r
206 return
211 return
207 startname = 'start_' + plural
212 startname = 'start_' + plural
208 if context.preload(startname):
213 if context.preload(startname):
209 yield context.process(startname, mapping)
214 yield context.process(startname, mapping)
210 def one(v, tag=name):
215 def one(v, tag=name):
211 vmapping = {}
216 vmapping = {}
212 try:
217 try:
213 vmapping.update(v)
218 vmapping.update(v)
214 # Python 2 raises ValueError if the type of v is wrong. Python
219 # Python 2 raises ValueError if the type of v is wrong. Python
215 # 3 raises TypeError.
220 # 3 raises TypeError.
216 except (AttributeError, TypeError, ValueError):
221 except (AttributeError, TypeError, ValueError):
217 try:
222 try:
218 # Python 2 raises ValueError trying to destructure an e.g.
223 # Python 2 raises ValueError trying to destructure an e.g.
219 # bytes. Python 3 raises TypeError.
224 # bytes. Python 3 raises TypeError.
220 for a, b in v:
225 for a, b in v:
221 vmapping[a] = b
226 vmapping[a] = b
222 except (TypeError, ValueError):
227 except (TypeError, ValueError):
223 vmapping[name] = v
228 vmapping[name] = v
224 vmapping = context.overlaymap(mapping, vmapping)
229 vmapping = context.overlaymap(mapping, vmapping)
225 return context.process(tag, vmapping)
230 return context.process(tag, vmapping)
226 lastname = 'last_' + name
231 lastname = 'last_' + name
227 if context.preload(lastname):
232 if context.preload(lastname):
228 last = values.pop()
233 last = values.pop()
229 else:
234 else:
230 last = None
235 last = None
231 for v in values:
236 for v in values:
232 yield one(v)
237 yield one(v)
233 if last is not None:
238 if last is not None:
234 yield one(last, tag=lastname)
239 yield one(last, tag=lastname)
235 endname = 'end_' + plural
240 endname = 'end_' + plural
236 if context.preload(endname):
241 if context.preload(endname):
237 yield context.process(endname, mapping)
242 yield context.process(endname, mapping)
238
243
239 def flatten(thing):
244 def flatten(thing):
240 """Yield a single stream from a possibly nested set of iterators"""
245 """Yield a single stream from a possibly nested set of iterators"""
241 thing = unwraphybrid(thing)
246 thing = unwraphybrid(thing)
242 if isinstance(thing, bytes):
247 if isinstance(thing, bytes):
243 yield thing
248 yield thing
244 elif isinstance(thing, str):
249 elif isinstance(thing, str):
245 # We can only hit this on Python 3, and it's here to guard
250 # We can only hit this on Python 3, and it's here to guard
246 # against infinite recursion.
251 # against infinite recursion.
247 raise error.ProgrammingError('Mercurial IO including templates is done'
252 raise error.ProgrammingError('Mercurial IO including templates is done'
248 ' with bytes, not strings, got %r' % thing)
253 ' with bytes, not strings, got %r' % thing)
249 elif thing is None:
254 elif thing is None:
250 pass
255 pass
251 elif not util.safehasattr(thing, '__iter__'):
256 elif not util.safehasattr(thing, '__iter__'):
252 yield pycompat.bytestr(thing)
257 yield pycompat.bytestr(thing)
253 else:
258 else:
254 for i in thing:
259 for i in thing:
255 i = unwraphybrid(i)
260 i = unwraphybrid(i)
256 if isinstance(i, bytes):
261 if isinstance(i, bytes):
257 yield i
262 yield i
258 elif i is None:
263 elif i is None:
259 pass
264 pass
260 elif not util.safehasattr(i, '__iter__'):
265 elif not util.safehasattr(i, '__iter__'):
261 yield pycompat.bytestr(i)
266 yield pycompat.bytestr(i)
262 else:
267 else:
263 for j in flatten(i):
268 for j in flatten(i):
264 yield j
269 yield j
265
270
266 def stringify(thing):
271 def stringify(thing):
267 """Turn values into bytes by converting into text and concatenating them"""
272 """Turn values into bytes by converting into text and concatenating them"""
268 if isinstance(thing, bytes):
273 if isinstance(thing, bytes):
269 return thing # retain localstr to be round-tripped
274 return thing # retain localstr to be round-tripped
270 return b''.join(flatten(thing))
275 return b''.join(flatten(thing))
271
276
272 def findsymbolicname(arg):
277 def findsymbolicname(arg):
273 """Find symbolic name for the given compiled expression; returns None
278 """Find symbolic name for the given compiled expression; returns None
274 if nothing found reliably"""
279 if nothing found reliably"""
275 while True:
280 while True:
276 func, data = arg
281 func, data = arg
277 if func is runsymbol:
282 if func is runsymbol:
278 return data
283 return data
279 elif func is runfilter:
284 elif func is runfilter:
280 arg = data[0]
285 arg = data[0]
281 else:
286 else:
282 return None
287 return None
283
288
284 def evalrawexp(context, mapping, arg):
289 def evalrawexp(context, mapping, arg):
285 """Evaluate given argument as a bare template object which may require
290 """Evaluate given argument as a bare template object which may require
286 further processing (such as folding generator of strings)"""
291 further processing (such as folding generator of strings)"""
287 func, data = arg
292 func, data = arg
288 return func(context, mapping, data)
293 return func(context, mapping, data)
289
294
290 def evalfuncarg(context, mapping, arg):
295 def evalfuncarg(context, mapping, arg):
291 """Evaluate given argument as value type"""
296 """Evaluate given argument as value type"""
292 return _unwrapvalue(evalrawexp(context, mapping, arg))
297 return _unwrapvalue(evalrawexp(context, mapping, arg))
293
298
294 # TODO: unify this with unwrapvalue() once the bug of templatefunc.join()
299 # TODO: unify this with unwrapvalue() once the bug of templatefunc.join()
295 # is fixed. we can't do that right now because join() has to take a generator
300 # is fixed. we can't do that right now because join() has to take a generator
296 # of byte strings as it is, not a lazy byte string.
301 # of byte strings as it is, not a lazy byte string.
297 def _unwrapvalue(thing):
302 def _unwrapvalue(thing):
298 thing = unwrapvalue(thing)
303 thing = unwrapvalue(thing)
299 # evalrawexp() may return string, generator of strings or arbitrary object
304 # evalrawexp() may return string, generator of strings or arbitrary object
300 # such as date tuple, but filter does not want generator.
305 # such as date tuple, but filter does not want generator.
301 if isinstance(thing, types.GeneratorType):
306 if isinstance(thing, types.GeneratorType):
302 thing = stringify(thing)
307 thing = stringify(thing)
303 return thing
308 return thing
304
309
305 def evalboolean(context, mapping, arg):
310 def evalboolean(context, mapping, arg):
306 """Evaluate given argument as boolean, but also takes boolean literals"""
311 """Evaluate given argument as boolean, but also takes boolean literals"""
307 func, data = arg
312 func, data = arg
308 if func is runsymbol:
313 if func is runsymbol:
309 thing = func(context, mapping, data, default=None)
314 thing = func(context, mapping, data, default=None)
310 if thing is None:
315 if thing is None:
311 # not a template keyword, takes as a boolean literal
316 # not a template keyword, takes as a boolean literal
312 thing = stringutil.parsebool(data)
317 thing = stringutil.parsebool(data)
313 else:
318 else:
314 thing = func(context, mapping, data)
319 thing = func(context, mapping, data)
315 thing = unwrapvalue(thing)
320 thing = unwrapvalue(thing)
316 if isinstance(thing, bool):
321 if isinstance(thing, bool):
317 return thing
322 return thing
318 # other objects are evaluated as strings, which means 0 is True, but
323 # other objects are evaluated as strings, which means 0 is True, but
319 # empty dict/list should be False as they are expected to be ''
324 # empty dict/list should be False as they are expected to be ''
320 return bool(stringify(thing))
325 return bool(stringify(thing))
321
326
322 def evaldate(context, mapping, arg, err=None):
327 def evaldate(context, mapping, arg, err=None):
323 """Evaluate given argument as a date tuple or a date string; returns
328 """Evaluate given argument as a date tuple or a date string; returns
324 a (unixtime, offset) tuple"""
329 a (unixtime, offset) tuple"""
325 return unwrapdate(evalrawexp(context, mapping, arg), err)
330 return unwrapdate(evalrawexp(context, mapping, arg), err)
326
331
327 def unwrapdate(thing, err=None):
332 def unwrapdate(thing, err=None):
328 thing = _unwrapvalue(thing)
333 thing = _unwrapvalue(thing)
329 try:
334 try:
330 return dateutil.parsedate(thing)
335 return dateutil.parsedate(thing)
331 except AttributeError:
336 except AttributeError:
332 raise error.ParseError(err or _('not a date tuple nor a string'))
337 raise error.ParseError(err or _('not a date tuple nor a string'))
333 except error.ParseError:
338 except error.ParseError:
334 if not err:
339 if not err:
335 raise
340 raise
336 raise error.ParseError(err)
341 raise error.ParseError(err)
337
342
338 def evalinteger(context, mapping, arg, err=None):
343 def evalinteger(context, mapping, arg, err=None):
339 return unwrapinteger(evalrawexp(context, mapping, arg), err)
344 return unwrapinteger(evalrawexp(context, mapping, arg), err)
340
345
341 def unwrapinteger(thing, err=None):
346 def unwrapinteger(thing, err=None):
342 thing = _unwrapvalue(thing)
347 thing = _unwrapvalue(thing)
343 try:
348 try:
344 return int(thing)
349 return int(thing)
345 except (TypeError, ValueError):
350 except (TypeError, ValueError):
346 raise error.ParseError(err or _('not an integer'))
351 raise error.ParseError(err or _('not an integer'))
347
352
348 def evalstring(context, mapping, arg):
353 def evalstring(context, mapping, arg):
349 return stringify(evalrawexp(context, mapping, arg))
354 return stringify(evalrawexp(context, mapping, arg))
350
355
351 def evalstringliteral(context, mapping, arg):
356 def evalstringliteral(context, mapping, arg):
352 """Evaluate given argument as string template, but returns symbol name
357 """Evaluate given argument as string template, but returns symbol name
353 if it is unknown"""
358 if it is unknown"""
354 func, data = arg
359 func, data = arg
355 if func is runsymbol:
360 if func is runsymbol:
356 thing = func(context, mapping, data, default=data)
361 thing = func(context, mapping, data, default=data)
357 else:
362 else:
358 thing = func(context, mapping, data)
363 thing = func(context, mapping, data)
359 return stringify(thing)
364 return stringify(thing)
360
365
361 _unwrapfuncbytype = {
366 _unwrapfuncbytype = {
362 None: _unwrapvalue,
367 None: _unwrapvalue,
363 bytes: stringify,
368 bytes: stringify,
369 date: unwrapdate,
364 int: unwrapinteger,
370 int: unwrapinteger,
365 }
371 }
366
372
367 def unwrapastype(thing, typ):
373 def unwrapastype(thing, typ):
368 """Move the inner value object out of the wrapper and coerce its type"""
374 """Move the inner value object out of the wrapper and coerce its type"""
369 try:
375 try:
370 f = _unwrapfuncbytype[typ]
376 f = _unwrapfuncbytype[typ]
371 except KeyError:
377 except KeyError:
372 raise error.ProgrammingError('invalid type specified: %r' % typ)
378 raise error.ProgrammingError('invalid type specified: %r' % typ)
373 return f(thing)
379 return f(thing)
374
380
375 def runinteger(context, mapping, data):
381 def runinteger(context, mapping, data):
376 return int(data)
382 return int(data)
377
383
378 def runstring(context, mapping, data):
384 def runstring(context, mapping, data):
379 return data
385 return data
380
386
381 def _recursivesymbolblocker(key):
387 def _recursivesymbolblocker(key):
382 def showrecursion(**args):
388 def showrecursion(**args):
383 raise error.Abort(_("recursive reference '%s' in template") % key)
389 raise error.Abort(_("recursive reference '%s' in template") % key)
384 return showrecursion
390 return showrecursion
385
391
386 def runsymbol(context, mapping, key, default=''):
392 def runsymbol(context, mapping, key, default=''):
387 v = context.symbol(mapping, key)
393 v = context.symbol(mapping, key)
388 if v is None:
394 if v is None:
389 # put poison to cut recursion. we can't move this to parsing phase
395 # put poison to cut recursion. we can't move this to parsing phase
390 # because "x = {x}" is allowed if "x" is a keyword. (issue4758)
396 # because "x = {x}" is allowed if "x" is a keyword. (issue4758)
391 safemapping = mapping.copy()
397 safemapping = mapping.copy()
392 safemapping[key] = _recursivesymbolblocker(key)
398 safemapping[key] = _recursivesymbolblocker(key)
393 try:
399 try:
394 v = context.process(key, safemapping)
400 v = context.process(key, safemapping)
395 except TemplateNotFound:
401 except TemplateNotFound:
396 v = default
402 v = default
397 if callable(v) and getattr(v, '_requires', None) is None:
403 if callable(v) and getattr(v, '_requires', None) is None:
398 # old templatekw: expand all keywords and resources
404 # old templatekw: expand all keywords and resources
399 # (TODO: deprecate this after porting web template keywords to new API)
405 # (TODO: deprecate this after porting web template keywords to new API)
400 props = {k: context._resources.lookup(context, mapping, k)
406 props = {k: context._resources.lookup(context, mapping, k)
401 for k in context._resources.knownkeys()}
407 for k in context._resources.knownkeys()}
402 # pass context to _showcompatlist() through templatekw._showlist()
408 # pass context to _showcompatlist() through templatekw._showlist()
403 props['templ'] = context
409 props['templ'] = context
404 props.update(mapping)
410 props.update(mapping)
405 return v(**pycompat.strkwargs(props))
411 return v(**pycompat.strkwargs(props))
406 if callable(v):
412 if callable(v):
407 # new templatekw
413 # new templatekw
408 try:
414 try:
409 return v(context, mapping)
415 return v(context, mapping)
410 except ResourceUnavailable:
416 except ResourceUnavailable:
411 # unsupported keyword is mapped to empty just like unknown keyword
417 # unsupported keyword is mapped to empty just like unknown keyword
412 return None
418 return None
413 return v
419 return v
414
420
415 def runtemplate(context, mapping, template):
421 def runtemplate(context, mapping, template):
416 for arg in template:
422 for arg in template:
417 yield evalrawexp(context, mapping, arg)
423 yield evalrawexp(context, mapping, arg)
418
424
419 def runfilter(context, mapping, data):
425 def runfilter(context, mapping, data):
420 arg, filt = data
426 arg, filt = data
421 thing = evalrawexp(context, mapping, arg)
427 thing = evalrawexp(context, mapping, arg)
422 try:
428 try:
423 thing = unwrapastype(thing, getattr(filt, '_intype', None))
429 thing = unwrapastype(thing, getattr(filt, '_intype', None))
424 return filt(thing)
430 return filt(thing)
425 except (ValueError, AttributeError, TypeError):
431 except (ValueError, AttributeError, TypeError):
426 raise error.Abort(_formatfiltererror(arg, filt))
432 raise error.Abort(_formatfiltererror(arg, filt))
427 except error.ParseError as e:
433 except error.ParseError as e:
428 raise error.ParseError(bytes(e), hint=_formatfiltererror(arg, filt))
434 raise error.ParseError(bytes(e), hint=_formatfiltererror(arg, filt))
429
435
430 def _formatfiltererror(arg, filt):
436 def _formatfiltererror(arg, filt):
431 fn = pycompat.sysbytes(filt.__name__)
437 fn = pycompat.sysbytes(filt.__name__)
432 sym = findsymbolicname(arg)
438 sym = findsymbolicname(arg)
433 if not sym:
439 if not sym:
434 return _("incompatible use of template filter '%s'") % fn
440 return _("incompatible use of template filter '%s'") % fn
435 return (_("template filter '%s' is not compatible with keyword '%s'")
441 return (_("template filter '%s' is not compatible with keyword '%s'")
436 % (fn, sym))
442 % (fn, sym))
437
443
438 def runmap(context, mapping, data):
444 def runmap(context, mapping, data):
439 darg, targ = data
445 darg, targ = data
440 d = evalrawexp(context, mapping, darg)
446 d = evalrawexp(context, mapping, darg)
441 if util.safehasattr(d, 'itermaps'):
447 if util.safehasattr(d, 'itermaps'):
442 diter = d.itermaps()
448 diter = d.itermaps()
443 else:
449 else:
444 try:
450 try:
445 diter = iter(d)
451 diter = iter(d)
446 except TypeError:
452 except TypeError:
447 sym = findsymbolicname(darg)
453 sym = findsymbolicname(darg)
448 if sym:
454 if sym:
449 raise error.ParseError(_("keyword '%s' is not iterable") % sym)
455 raise error.ParseError(_("keyword '%s' is not iterable") % sym)
450 else:
456 else:
451 raise error.ParseError(_("%r is not iterable") % d)
457 raise error.ParseError(_("%r is not iterable") % d)
452
458
453 for i, v in enumerate(diter):
459 for i, v in enumerate(diter):
454 if isinstance(v, dict):
460 if isinstance(v, dict):
455 lm = context.overlaymap(mapping, v)
461 lm = context.overlaymap(mapping, v)
456 lm['index'] = i
462 lm['index'] = i
457 yield evalrawexp(context, lm, targ)
463 yield evalrawexp(context, lm, targ)
458 else:
464 else:
459 # v is not an iterable of dicts, this happen when 'key'
465 # v is not an iterable of dicts, this happen when 'key'
460 # has been fully expanded already and format is useless.
466 # has been fully expanded already and format is useless.
461 # If so, return the expanded value.
467 # If so, return the expanded value.
462 yield v
468 yield v
463
469
464 def runmember(context, mapping, data):
470 def runmember(context, mapping, data):
465 darg, memb = data
471 darg, memb = data
466 d = evalrawexp(context, mapping, darg)
472 d = evalrawexp(context, mapping, darg)
467 if util.safehasattr(d, 'tomap'):
473 if util.safehasattr(d, 'tomap'):
468 lm = context.overlaymap(mapping, d.tomap())
474 lm = context.overlaymap(mapping, d.tomap())
469 return runsymbol(context, lm, memb)
475 return runsymbol(context, lm, memb)
470 if util.safehasattr(d, 'get'):
476 if util.safehasattr(d, 'get'):
471 return getdictitem(d, memb)
477 return getdictitem(d, memb)
472
478
473 sym = findsymbolicname(darg)
479 sym = findsymbolicname(darg)
474 if sym:
480 if sym:
475 raise error.ParseError(_("keyword '%s' has no member") % sym)
481 raise error.ParseError(_("keyword '%s' has no member") % sym)
476 else:
482 else:
477 raise error.ParseError(_("%r has no member") % pycompat.bytestr(d))
483 raise error.ParseError(_("%r has no member") % pycompat.bytestr(d))
478
484
479 def runnegate(context, mapping, data):
485 def runnegate(context, mapping, data):
480 data = evalinteger(context, mapping, data,
486 data = evalinteger(context, mapping, data,
481 _('negation needs an integer argument'))
487 _('negation needs an integer argument'))
482 return -data
488 return -data
483
489
484 def runarithmetic(context, mapping, data):
490 def runarithmetic(context, mapping, data):
485 func, left, right = data
491 func, left, right = data
486 left = evalinteger(context, mapping, left,
492 left = evalinteger(context, mapping, left,
487 _('arithmetic only defined on integers'))
493 _('arithmetic only defined on integers'))
488 right = evalinteger(context, mapping, right,
494 right = evalinteger(context, mapping, right,
489 _('arithmetic only defined on integers'))
495 _('arithmetic only defined on integers'))
490 try:
496 try:
491 return func(left, right)
497 return func(left, right)
492 except ZeroDivisionError:
498 except ZeroDivisionError:
493 raise error.Abort(_('division by zero is not defined'))
499 raise error.Abort(_('division by zero is not defined'))
494
500
495 def getdictitem(dictarg, key):
501 def getdictitem(dictarg, key):
496 val = dictarg.get(key)
502 val = dictarg.get(key)
497 if val is None:
503 if val is None:
498 return
504 return
499 return wraphybridvalue(dictarg, key, val)
505 return wraphybridvalue(dictarg, key, val)
@@ -1,4843 +1,4846 b''
1 $ hg init a
1 $ hg init a
2 $ cd a
2 $ cd a
3 $ echo a > a
3 $ echo a > a
4 $ hg add a
4 $ hg add a
5 $ echo line 1 > b
5 $ echo line 1 > b
6 $ echo line 2 >> b
6 $ echo line 2 >> b
7 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
7 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
8
8
9 $ hg add b
9 $ hg add b
10 $ echo other 1 > c
10 $ echo other 1 > c
11 $ echo other 2 >> c
11 $ echo other 2 >> c
12 $ echo >> c
12 $ echo >> c
13 $ echo other 3 >> c
13 $ echo other 3 >> c
14 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
14 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
15
15
16 $ hg add c
16 $ hg add c
17 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
17 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
18 $ echo c >> c
18 $ echo c >> c
19 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
19 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
20
20
21 $ echo foo > .hg/branch
21 $ echo foo > .hg/branch
22 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
22 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
23
23
24 $ hg co -q 3
24 $ hg co -q 3
25 $ echo other 4 >> d
25 $ echo other 4 >> d
26 $ hg add d
26 $ hg add d
27 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
27 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
28
28
29 $ hg merge -q foo
29 $ hg merge -q foo
30 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
30 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
31
31
32 Test arithmetic operators have the right precedence:
32 Test arithmetic operators have the right precedence:
33
33
34 $ hg log -l 1 -T '{date(date, "%Y") + 5 * 10} {date(date, "%Y") - 2 * 3}\n'
34 $ hg log -l 1 -T '{date(date, "%Y") + 5 * 10} {date(date, "%Y") - 2 * 3}\n'
35 2020 1964
35 2020 1964
36 $ hg log -l 1 -T '{date(date, "%Y") * 5 + 10} {date(date, "%Y") * 3 - 2}\n'
36 $ hg log -l 1 -T '{date(date, "%Y") * 5 + 10} {date(date, "%Y") * 3 - 2}\n'
37 9860 5908
37 9860 5908
38
38
39 Test division:
39 Test division:
40
40
41 $ hg debugtemplate -r0 -v '{5 / 2} {mod(5, 2)}\n'
41 $ hg debugtemplate -r0 -v '{5 / 2} {mod(5, 2)}\n'
42 (template
42 (template
43 (/
43 (/
44 (integer '5')
44 (integer '5')
45 (integer '2'))
45 (integer '2'))
46 (string ' ')
46 (string ' ')
47 (func
47 (func
48 (symbol 'mod')
48 (symbol 'mod')
49 (list
49 (list
50 (integer '5')
50 (integer '5')
51 (integer '2')))
51 (integer '2')))
52 (string '\n'))
52 (string '\n'))
53 2 1
53 2 1
54 $ hg debugtemplate -r0 -v '{5 / -2} {mod(5, -2)}\n'
54 $ hg debugtemplate -r0 -v '{5 / -2} {mod(5, -2)}\n'
55 (template
55 (template
56 (/
56 (/
57 (integer '5')
57 (integer '5')
58 (negate
58 (negate
59 (integer '2')))
59 (integer '2')))
60 (string ' ')
60 (string ' ')
61 (func
61 (func
62 (symbol 'mod')
62 (symbol 'mod')
63 (list
63 (list
64 (integer '5')
64 (integer '5')
65 (negate
65 (negate
66 (integer '2'))))
66 (integer '2'))))
67 (string '\n'))
67 (string '\n'))
68 -3 -1
68 -3 -1
69 $ hg debugtemplate -r0 -v '{-5 / 2} {mod(-5, 2)}\n'
69 $ hg debugtemplate -r0 -v '{-5 / 2} {mod(-5, 2)}\n'
70 (template
70 (template
71 (/
71 (/
72 (negate
72 (negate
73 (integer '5'))
73 (integer '5'))
74 (integer '2'))
74 (integer '2'))
75 (string ' ')
75 (string ' ')
76 (func
76 (func
77 (symbol 'mod')
77 (symbol 'mod')
78 (list
78 (list
79 (negate
79 (negate
80 (integer '5'))
80 (integer '5'))
81 (integer '2')))
81 (integer '2')))
82 (string '\n'))
82 (string '\n'))
83 -3 1
83 -3 1
84 $ hg debugtemplate -r0 -v '{-5 / -2} {mod(-5, -2)}\n'
84 $ hg debugtemplate -r0 -v '{-5 / -2} {mod(-5, -2)}\n'
85 (template
85 (template
86 (/
86 (/
87 (negate
87 (negate
88 (integer '5'))
88 (integer '5'))
89 (negate
89 (negate
90 (integer '2')))
90 (integer '2')))
91 (string ' ')
91 (string ' ')
92 (func
92 (func
93 (symbol 'mod')
93 (symbol 'mod')
94 (list
94 (list
95 (negate
95 (negate
96 (integer '5'))
96 (integer '5'))
97 (negate
97 (negate
98 (integer '2'))))
98 (integer '2'))))
99 (string '\n'))
99 (string '\n'))
100 2 -1
100 2 -1
101
101
102 Filters bind closer than arithmetic:
102 Filters bind closer than arithmetic:
103
103
104 $ hg debugtemplate -r0 -v '{revset(".")|count - 1}\n'
104 $ hg debugtemplate -r0 -v '{revset(".")|count - 1}\n'
105 (template
105 (template
106 (-
106 (-
107 (|
107 (|
108 (func
108 (func
109 (symbol 'revset')
109 (symbol 'revset')
110 (string '.'))
110 (string '.'))
111 (symbol 'count'))
111 (symbol 'count'))
112 (integer '1'))
112 (integer '1'))
113 (string '\n'))
113 (string '\n'))
114 0
114 0
115
115
116 But negate binds closer still:
116 But negate binds closer still:
117
117
118 $ hg debugtemplate -r0 -v '{1-3|stringify}\n'
118 $ hg debugtemplate -r0 -v '{1-3|stringify}\n'
119 (template
119 (template
120 (-
120 (-
121 (integer '1')
121 (integer '1')
122 (|
122 (|
123 (integer '3')
123 (integer '3')
124 (symbol 'stringify')))
124 (symbol 'stringify')))
125 (string '\n'))
125 (string '\n'))
126 hg: parse error: arithmetic only defined on integers
126 hg: parse error: arithmetic only defined on integers
127 [255]
127 [255]
128 $ hg debugtemplate -r0 -v '{-3|stringify}\n'
128 $ hg debugtemplate -r0 -v '{-3|stringify}\n'
129 (template
129 (template
130 (|
130 (|
131 (negate
131 (negate
132 (integer '3'))
132 (integer '3'))
133 (symbol 'stringify'))
133 (symbol 'stringify'))
134 (string '\n'))
134 (string '\n'))
135 -3
135 -3
136
136
137 Filters bind as close as map operator:
137 Filters bind as close as map operator:
138
138
139 $ hg debugtemplate -r0 -v '{desc|splitlines % "{line}\n"}'
139 $ hg debugtemplate -r0 -v '{desc|splitlines % "{line}\n"}'
140 (template
140 (template
141 (%
141 (%
142 (|
142 (|
143 (symbol 'desc')
143 (symbol 'desc')
144 (symbol 'splitlines'))
144 (symbol 'splitlines'))
145 (template
145 (template
146 (symbol 'line')
146 (symbol 'line')
147 (string '\n'))))
147 (string '\n'))))
148 line 1
148 line 1
149 line 2
149 line 2
150
150
151 Keyword arguments:
151 Keyword arguments:
152
152
153 $ hg debugtemplate -r0 -v '{foo=bar|baz}'
153 $ hg debugtemplate -r0 -v '{foo=bar|baz}'
154 (template
154 (template
155 (keyvalue
155 (keyvalue
156 (symbol 'foo')
156 (symbol 'foo')
157 (|
157 (|
158 (symbol 'bar')
158 (symbol 'bar')
159 (symbol 'baz'))))
159 (symbol 'baz'))))
160 hg: parse error: can't use a key-value pair in this context
160 hg: parse error: can't use a key-value pair in this context
161 [255]
161 [255]
162
162
163 $ hg debugtemplate '{pad("foo", width=10, left=true)}\n'
163 $ hg debugtemplate '{pad("foo", width=10, left=true)}\n'
164 foo
164 foo
165
165
166 Call function which takes named arguments by filter syntax:
166 Call function which takes named arguments by filter syntax:
167
167
168 $ hg debugtemplate '{" "|separate}'
168 $ hg debugtemplate '{" "|separate}'
169 $ hg debugtemplate '{("not", "an", "argument", "list")|separate}'
169 $ hg debugtemplate '{("not", "an", "argument", "list")|separate}'
170 hg: parse error: unknown method 'list'
170 hg: parse error: unknown method 'list'
171 [255]
171 [255]
172
172
173 Second branch starting at nullrev:
173 Second branch starting at nullrev:
174
174
175 $ hg update null
175 $ hg update null
176 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
176 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
177 $ echo second > second
177 $ echo second > second
178 $ hg add second
178 $ hg add second
179 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
179 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
180 created new head
180 created new head
181
181
182 $ echo third > third
182 $ echo third > third
183 $ hg add third
183 $ hg add third
184 $ hg mv second fourth
184 $ hg mv second fourth
185 $ hg commit -m third -d "2020-01-01 10:01"
185 $ hg commit -m third -d "2020-01-01 10:01"
186
186
187 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
187 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
188 fourth (second)
188 fourth (second)
189 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
189 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
190 second -> fourth
190 second -> fourth
191 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
191 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
192 8 t
192 8 t
193 7 f
193 7 f
194
194
195 Working-directory revision has special identifiers, though they are still
195 Working-directory revision has special identifiers, though they are still
196 experimental:
196 experimental:
197
197
198 $ hg log -r 'wdir()' -T '{rev}:{node}\n'
198 $ hg log -r 'wdir()' -T '{rev}:{node}\n'
199 2147483647:ffffffffffffffffffffffffffffffffffffffff
199 2147483647:ffffffffffffffffffffffffffffffffffffffff
200
200
201 Some keywords are invalid for working-directory revision, but they should
201 Some keywords are invalid for working-directory revision, but they should
202 never cause crash:
202 never cause crash:
203
203
204 $ hg log -r 'wdir()' -T '{manifest}\n'
204 $ hg log -r 'wdir()' -T '{manifest}\n'
205
205
206
206
207 Internal resources shouldn't be exposed (issue5699):
207 Internal resources shouldn't be exposed (issue5699):
208
208
209 $ hg log -r. -T '{cache}{ctx}{repo}{revcache}{templ}{ui}'
209 $ hg log -r. -T '{cache}{ctx}{repo}{revcache}{templ}{ui}'
210
210
211 Never crash on internal resource not available:
211 Never crash on internal resource not available:
212
212
213 $ hg --cwd .. debugtemplate '{"c0bebeef"|shortest}\n'
213 $ hg --cwd .. debugtemplate '{"c0bebeef"|shortest}\n'
214 abort: template resource not available: ctx
214 abort: template resource not available: ctx
215 [255]
215 [255]
216
216
217 $ hg config -T '{author}'
217 $ hg config -T '{author}'
218
218
219 Quoting for ui.logtemplate
219 Quoting for ui.logtemplate
220
220
221 $ hg tip --config "ui.logtemplate={rev}\n"
221 $ hg tip --config "ui.logtemplate={rev}\n"
222 8
222 8
223 $ hg tip --config "ui.logtemplate='{rev}\n'"
223 $ hg tip --config "ui.logtemplate='{rev}\n'"
224 8
224 8
225 $ hg tip --config 'ui.logtemplate="{rev}\n"'
225 $ hg tip --config 'ui.logtemplate="{rev}\n"'
226 8
226 8
227 $ hg tip --config 'ui.logtemplate=n{rev}\n'
227 $ hg tip --config 'ui.logtemplate=n{rev}\n'
228 n8
228 n8
229
229
230 Make sure user/global hgrc does not affect tests
230 Make sure user/global hgrc does not affect tests
231
231
232 $ echo '[ui]' > .hg/hgrc
232 $ echo '[ui]' > .hg/hgrc
233 $ echo 'logtemplate =' >> .hg/hgrc
233 $ echo 'logtemplate =' >> .hg/hgrc
234 $ echo 'style =' >> .hg/hgrc
234 $ echo 'style =' >> .hg/hgrc
235
235
236 Add some simple styles to settings
236 Add some simple styles to settings
237
237
238 $ cat <<'EOF' >> .hg/hgrc
238 $ cat <<'EOF' >> .hg/hgrc
239 > [templates]
239 > [templates]
240 > simple = "{rev}\n"
240 > simple = "{rev}\n"
241 > simple2 = {rev}\n
241 > simple2 = {rev}\n
242 > rev = "should not precede {rev} keyword\n"
242 > rev = "should not precede {rev} keyword\n"
243 > EOF
243 > EOF
244
244
245 $ hg log -l1 -Tsimple
245 $ hg log -l1 -Tsimple
246 8
246 8
247 $ hg log -l1 -Tsimple2
247 $ hg log -l1 -Tsimple2
248 8
248 8
249 $ hg log -l1 -Trev
249 $ hg log -l1 -Trev
250 should not precede 8 keyword
250 should not precede 8 keyword
251 $ hg log -l1 -T '{simple}'
251 $ hg log -l1 -T '{simple}'
252 8
252 8
253
253
254 Map file shouldn't see user templates:
254 Map file shouldn't see user templates:
255
255
256 $ cat <<EOF > tmpl
256 $ cat <<EOF > tmpl
257 > changeset = 'nothing expanded:{simple}\n'
257 > changeset = 'nothing expanded:{simple}\n'
258 > EOF
258 > EOF
259 $ hg log -l1 --style ./tmpl
259 $ hg log -l1 --style ./tmpl
260 nothing expanded:
260 nothing expanded:
261
261
262 Test templates and style maps in files:
262 Test templates and style maps in files:
263
263
264 $ echo "{rev}" > tmpl
264 $ echo "{rev}" > tmpl
265 $ hg log -l1 -T./tmpl
265 $ hg log -l1 -T./tmpl
266 8
266 8
267 $ hg log -l1 -Tblah/blah
267 $ hg log -l1 -Tblah/blah
268 blah/blah (no-eol)
268 blah/blah (no-eol)
269
269
270 $ printf 'changeset = "{rev}\\n"\n' > map-simple
270 $ printf 'changeset = "{rev}\\n"\n' > map-simple
271 $ hg log -l1 -T./map-simple
271 $ hg log -l1 -T./map-simple
272 8
272 8
273
273
274 a map file may have [templates] and [templatealias] sections:
274 a map file may have [templates] and [templatealias] sections:
275
275
276 $ cat <<'EOF' > map-simple
276 $ cat <<'EOF' > map-simple
277 > [templates]
277 > [templates]
278 > changeset = "{a}\n"
278 > changeset = "{a}\n"
279 > [templatealias]
279 > [templatealias]
280 > a = rev
280 > a = rev
281 > EOF
281 > EOF
282 $ hg log -l1 -T./map-simple
282 $ hg log -l1 -T./map-simple
283 8
283 8
284
284
285 so it can be included in hgrc
285 so it can be included in hgrc
286
286
287 $ cat <<'EOF' > myhgrc
287 $ cat <<'EOF' > myhgrc
288 > %include map-simple
288 > %include map-simple
289 > [templates]
289 > [templates]
290 > foo = "{changeset}"
290 > foo = "{changeset}"
291 > EOF
291 > EOF
292 $ HGRCPATH=./myhgrc hg log -l1 -Tfoo
292 $ HGRCPATH=./myhgrc hg log -l1 -Tfoo
293 8
293 8
294 $ HGRCPATH=./myhgrc hg log -l1 -T'{a}\n'
294 $ HGRCPATH=./myhgrc hg log -l1 -T'{a}\n'
295 8
295 8
296
296
297 Test template map inheritance
297 Test template map inheritance
298
298
299 $ echo "__base__ = map-cmdline.default" > map-simple
299 $ echo "__base__ = map-cmdline.default" > map-simple
300 $ printf 'cset = "changeset: ***{rev}***\\n"\n' >> map-simple
300 $ printf 'cset = "changeset: ***{rev}***\\n"\n' >> map-simple
301 $ hg log -l1 -T./map-simple
301 $ hg log -l1 -T./map-simple
302 changeset: ***8***
302 changeset: ***8***
303 tag: tip
303 tag: tip
304 user: test
304 user: test
305 date: Wed Jan 01 10:01:00 2020 +0000
305 date: Wed Jan 01 10:01:00 2020 +0000
306 summary: third
306 summary: third
307
307
308
308
309 Test docheader, docfooter and separator in template map
309 Test docheader, docfooter and separator in template map
310
310
311 $ cat <<'EOF' > map-myjson
311 $ cat <<'EOF' > map-myjson
312 > docheader = '\{\n'
312 > docheader = '\{\n'
313 > docfooter = '\n}\n'
313 > docfooter = '\n}\n'
314 > separator = ',\n'
314 > separator = ',\n'
315 > changeset = ' {dict(rev, node|short)|json}'
315 > changeset = ' {dict(rev, node|short)|json}'
316 > EOF
316 > EOF
317 $ hg log -l2 -T./map-myjson
317 $ hg log -l2 -T./map-myjson
318 {
318 {
319 {"node": "95c24699272e", "rev": 8},
319 {"node": "95c24699272e", "rev": 8},
320 {"node": "29114dbae42b", "rev": 7}
320 {"node": "29114dbae42b", "rev": 7}
321 }
321 }
322
322
323 Test docheader, docfooter and separator in [templates] section
323 Test docheader, docfooter and separator in [templates] section
324
324
325 $ cat <<'EOF' >> .hg/hgrc
325 $ cat <<'EOF' >> .hg/hgrc
326 > [templates]
326 > [templates]
327 > myjson = ' {dict(rev, node|short)|json}'
327 > myjson = ' {dict(rev, node|short)|json}'
328 > myjson:docheader = '\{\n'
328 > myjson:docheader = '\{\n'
329 > myjson:docfooter = '\n}\n'
329 > myjson:docfooter = '\n}\n'
330 > myjson:separator = ',\n'
330 > myjson:separator = ',\n'
331 > :docheader = 'should not be selected as a docheader for literal templates\n'
331 > :docheader = 'should not be selected as a docheader for literal templates\n'
332 > EOF
332 > EOF
333 $ hg log -l2 -Tmyjson
333 $ hg log -l2 -Tmyjson
334 {
334 {
335 {"node": "95c24699272e", "rev": 8},
335 {"node": "95c24699272e", "rev": 8},
336 {"node": "29114dbae42b", "rev": 7}
336 {"node": "29114dbae42b", "rev": 7}
337 }
337 }
338 $ hg log -l1 -T'{rev}\n'
338 $ hg log -l1 -T'{rev}\n'
339 8
339 8
340
340
341 Template should precede style option
341 Template should precede style option
342
342
343 $ hg log -l1 --style default -T '{rev}\n'
343 $ hg log -l1 --style default -T '{rev}\n'
344 8
344 8
345
345
346 Add a commit with empty description, to ensure that the templates
346 Add a commit with empty description, to ensure that the templates
347 below will omit the description line.
347 below will omit the description line.
348
348
349 $ echo c >> c
349 $ echo c >> c
350 $ hg add c
350 $ hg add c
351 $ hg commit -qm ' '
351 $ hg commit -qm ' '
352
352
353 Default style is like normal output. Phases style should be the same
353 Default style is like normal output. Phases style should be the same
354 as default style, except for extra phase lines.
354 as default style, except for extra phase lines.
355
355
356 $ hg log > log.out
356 $ hg log > log.out
357 $ hg log --style default > style.out
357 $ hg log --style default > style.out
358 $ cmp log.out style.out || diff -u log.out style.out
358 $ cmp log.out style.out || diff -u log.out style.out
359 $ hg log -T phases > phases.out
359 $ hg log -T phases > phases.out
360 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
360 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
361 +phase: draft
361 +phase: draft
362 +phase: draft
362 +phase: draft
363 +phase: draft
363 +phase: draft
364 +phase: draft
364 +phase: draft
365 +phase: draft
365 +phase: draft
366 +phase: draft
366 +phase: draft
367 +phase: draft
367 +phase: draft
368 +phase: draft
368 +phase: draft
369 +phase: draft
369 +phase: draft
370 +phase: draft
370 +phase: draft
371
371
372 $ hg log -v > log.out
372 $ hg log -v > log.out
373 $ hg log -v --style default > style.out
373 $ hg log -v --style default > style.out
374 $ cmp log.out style.out || diff -u log.out style.out
374 $ cmp log.out style.out || diff -u log.out style.out
375 $ hg log -v -T phases > phases.out
375 $ hg log -v -T phases > phases.out
376 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
376 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
377 +phase: draft
377 +phase: draft
378 +phase: draft
378 +phase: draft
379 +phase: draft
379 +phase: draft
380 +phase: draft
380 +phase: draft
381 +phase: draft
381 +phase: draft
382 +phase: draft
382 +phase: draft
383 +phase: draft
383 +phase: draft
384 +phase: draft
384 +phase: draft
385 +phase: draft
385 +phase: draft
386 +phase: draft
386 +phase: draft
387
387
388 $ hg log -q > log.out
388 $ hg log -q > log.out
389 $ hg log -q --style default > style.out
389 $ hg log -q --style default > style.out
390 $ cmp log.out style.out || diff -u log.out style.out
390 $ cmp log.out style.out || diff -u log.out style.out
391 $ hg log -q -T phases > phases.out
391 $ hg log -q -T phases > phases.out
392 $ cmp log.out phases.out || diff -u log.out phases.out
392 $ cmp log.out phases.out || diff -u log.out phases.out
393
393
394 $ hg log --debug > log.out
394 $ hg log --debug > log.out
395 $ hg log --debug --style default > style.out
395 $ hg log --debug --style default > style.out
396 $ cmp log.out style.out || diff -u log.out style.out
396 $ cmp log.out style.out || diff -u log.out style.out
397 $ hg log --debug -T phases > phases.out
397 $ hg log --debug -T phases > phases.out
398 $ cmp log.out phases.out || diff -u log.out phases.out
398 $ cmp log.out phases.out || diff -u log.out phases.out
399
399
400 Default style of working-directory revision should also be the same (but
400 Default style of working-directory revision should also be the same (but
401 date may change while running tests):
401 date may change while running tests):
402
402
403 $ hg log -r 'wdir()' | sed 's|^date:.*|date:|' > log.out
403 $ hg log -r 'wdir()' | sed 's|^date:.*|date:|' > log.out
404 $ hg log -r 'wdir()' --style default | sed 's|^date:.*|date:|' > style.out
404 $ hg log -r 'wdir()' --style default | sed 's|^date:.*|date:|' > style.out
405 $ cmp log.out style.out || diff -u log.out style.out
405 $ cmp log.out style.out || diff -u log.out style.out
406
406
407 $ hg log -r 'wdir()' -v | sed 's|^date:.*|date:|' > log.out
407 $ hg log -r 'wdir()' -v | sed 's|^date:.*|date:|' > log.out
408 $ hg log -r 'wdir()' -v --style default | sed 's|^date:.*|date:|' > style.out
408 $ hg log -r 'wdir()' -v --style default | sed 's|^date:.*|date:|' > style.out
409 $ cmp log.out style.out || diff -u log.out style.out
409 $ cmp log.out style.out || diff -u log.out style.out
410
410
411 $ hg log -r 'wdir()' -q > log.out
411 $ hg log -r 'wdir()' -q > log.out
412 $ hg log -r 'wdir()' -q --style default > style.out
412 $ hg log -r 'wdir()' -q --style default > style.out
413 $ cmp log.out style.out || diff -u log.out style.out
413 $ cmp log.out style.out || diff -u log.out style.out
414
414
415 $ hg log -r 'wdir()' --debug | sed 's|^date:.*|date:|' > log.out
415 $ hg log -r 'wdir()' --debug | sed 's|^date:.*|date:|' > log.out
416 $ hg log -r 'wdir()' --debug --style default \
416 $ hg log -r 'wdir()' --debug --style default \
417 > | sed 's|^date:.*|date:|' > style.out
417 > | sed 's|^date:.*|date:|' > style.out
418 $ cmp log.out style.out || diff -u log.out style.out
418 $ cmp log.out style.out || diff -u log.out style.out
419
419
420 Default style should also preserve color information (issue2866):
420 Default style should also preserve color information (issue2866):
421
421
422 $ cp $HGRCPATH $HGRCPATH-bak
422 $ cp $HGRCPATH $HGRCPATH-bak
423 $ cat <<EOF >> $HGRCPATH
423 $ cat <<EOF >> $HGRCPATH
424 > [extensions]
424 > [extensions]
425 > color=
425 > color=
426 > EOF
426 > EOF
427
427
428 $ hg --color=debug log > log.out
428 $ hg --color=debug log > log.out
429 $ hg --color=debug log --style default > style.out
429 $ hg --color=debug log --style default > style.out
430 $ cmp log.out style.out || diff -u log.out style.out
430 $ cmp log.out style.out || diff -u log.out style.out
431 $ hg --color=debug log -T phases > phases.out
431 $ hg --color=debug log -T phases > phases.out
432 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
432 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
433 +[log.phase|phase: draft]
433 +[log.phase|phase: draft]
434 +[log.phase|phase: draft]
434 +[log.phase|phase: draft]
435 +[log.phase|phase: draft]
435 +[log.phase|phase: draft]
436 +[log.phase|phase: draft]
436 +[log.phase|phase: draft]
437 +[log.phase|phase: draft]
437 +[log.phase|phase: draft]
438 +[log.phase|phase: draft]
438 +[log.phase|phase: draft]
439 +[log.phase|phase: draft]
439 +[log.phase|phase: draft]
440 +[log.phase|phase: draft]
440 +[log.phase|phase: draft]
441 +[log.phase|phase: draft]
441 +[log.phase|phase: draft]
442 +[log.phase|phase: draft]
442 +[log.phase|phase: draft]
443
443
444 $ hg --color=debug -v log > log.out
444 $ hg --color=debug -v log > log.out
445 $ hg --color=debug -v log --style default > style.out
445 $ hg --color=debug -v log --style default > style.out
446 $ cmp log.out style.out || diff -u log.out style.out
446 $ cmp log.out style.out || diff -u log.out style.out
447 $ hg --color=debug -v log -T phases > phases.out
447 $ hg --color=debug -v log -T phases > phases.out
448 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
448 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
449 +[log.phase|phase: draft]
449 +[log.phase|phase: draft]
450 +[log.phase|phase: draft]
450 +[log.phase|phase: draft]
451 +[log.phase|phase: draft]
451 +[log.phase|phase: draft]
452 +[log.phase|phase: draft]
452 +[log.phase|phase: draft]
453 +[log.phase|phase: draft]
453 +[log.phase|phase: draft]
454 +[log.phase|phase: draft]
454 +[log.phase|phase: draft]
455 +[log.phase|phase: draft]
455 +[log.phase|phase: draft]
456 +[log.phase|phase: draft]
456 +[log.phase|phase: draft]
457 +[log.phase|phase: draft]
457 +[log.phase|phase: draft]
458 +[log.phase|phase: draft]
458 +[log.phase|phase: draft]
459
459
460 $ hg --color=debug -q log > log.out
460 $ hg --color=debug -q log > log.out
461 $ hg --color=debug -q log --style default > style.out
461 $ hg --color=debug -q log --style default > style.out
462 $ cmp log.out style.out || diff -u log.out style.out
462 $ cmp log.out style.out || diff -u log.out style.out
463 $ hg --color=debug -q log -T phases > phases.out
463 $ hg --color=debug -q log -T phases > phases.out
464 $ cmp log.out phases.out || diff -u log.out phases.out
464 $ cmp log.out phases.out || diff -u log.out phases.out
465
465
466 $ hg --color=debug --debug log > log.out
466 $ hg --color=debug --debug log > log.out
467 $ hg --color=debug --debug log --style default > style.out
467 $ hg --color=debug --debug log --style default > style.out
468 $ cmp log.out style.out || diff -u log.out style.out
468 $ cmp log.out style.out || diff -u log.out style.out
469 $ hg --color=debug --debug log -T phases > phases.out
469 $ hg --color=debug --debug log -T phases > phases.out
470 $ cmp log.out phases.out || diff -u log.out phases.out
470 $ cmp log.out phases.out || diff -u log.out phases.out
471
471
472 $ mv $HGRCPATH-bak $HGRCPATH
472 $ mv $HGRCPATH-bak $HGRCPATH
473
473
474 Remove commit with empty commit message, so as to not pollute further
474 Remove commit with empty commit message, so as to not pollute further
475 tests.
475 tests.
476
476
477 $ hg --config extensions.strip= strip -q .
477 $ hg --config extensions.strip= strip -q .
478
478
479 Revision with no copies (used to print a traceback):
479 Revision with no copies (used to print a traceback):
480
480
481 $ hg tip -v --template '\n'
481 $ hg tip -v --template '\n'
482
482
483
483
484 Compact style works:
484 Compact style works:
485
485
486 $ hg log -Tcompact
486 $ hg log -Tcompact
487 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
487 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
488 third
488 third
489
489
490 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
490 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
491 second
491 second
492
492
493 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
493 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
494 merge
494 merge
495
495
496 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
496 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
497 new head
497 new head
498
498
499 4 bbe44766e73d 1970-01-17 04:53 +0000 person
499 4 bbe44766e73d 1970-01-17 04:53 +0000 person
500 new branch
500 new branch
501
501
502 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
502 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
503 no user, no domain
503 no user, no domain
504
504
505 2 97054abb4ab8 1970-01-14 21:20 +0000 other
505 2 97054abb4ab8 1970-01-14 21:20 +0000 other
506 no person
506 no person
507
507
508 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
508 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
509 other 1
509 other 1
510
510
511 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
511 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
512 line 1
512 line 1
513
513
514
514
515 $ hg log -v --style compact
515 $ hg log -v --style compact
516 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
516 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
517 third
517 third
518
518
519 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
519 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
520 second
520 second
521
521
522 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
522 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
523 merge
523 merge
524
524
525 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
525 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
526 new head
526 new head
527
527
528 4 bbe44766e73d 1970-01-17 04:53 +0000 person
528 4 bbe44766e73d 1970-01-17 04:53 +0000 person
529 new branch
529 new branch
530
530
531 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
531 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
532 no user, no domain
532 no user, no domain
533
533
534 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
534 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
535 no person
535 no person
536
536
537 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
537 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
538 other 1
538 other 1
539 other 2
539 other 2
540
540
541 other 3
541 other 3
542
542
543 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
543 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
544 line 1
544 line 1
545 line 2
545 line 2
546
546
547
547
548 $ hg log --debug --style compact
548 $ hg log --debug --style compact
549 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
549 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
550 third
550 third
551
551
552 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
552 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
553 second
553 second
554
554
555 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
555 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
556 merge
556 merge
557
557
558 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
558 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
559 new head
559 new head
560
560
561 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
561 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
562 new branch
562 new branch
563
563
564 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
564 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
565 no user, no domain
565 no user, no domain
566
566
567 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
567 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
568 no person
568 no person
569
569
570 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
570 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
571 other 1
571 other 1
572 other 2
572 other 2
573
573
574 other 3
574 other 3
575
575
576 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
576 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
577 line 1
577 line 1
578 line 2
578 line 2
579
579
580
580
581 Test xml styles:
581 Test xml styles:
582
582
583 $ hg log --style xml -r 'not all()'
583 $ hg log --style xml -r 'not all()'
584 <?xml version="1.0"?>
584 <?xml version="1.0"?>
585 <log>
585 <log>
586 </log>
586 </log>
587
587
588 $ hg log --style xml
588 $ hg log --style xml
589 <?xml version="1.0"?>
589 <?xml version="1.0"?>
590 <log>
590 <log>
591 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
591 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
592 <tag>tip</tag>
592 <tag>tip</tag>
593 <author email="test">test</author>
593 <author email="test">test</author>
594 <date>2020-01-01T10:01:00+00:00</date>
594 <date>2020-01-01T10:01:00+00:00</date>
595 <msg xml:space="preserve">third</msg>
595 <msg xml:space="preserve">third</msg>
596 </logentry>
596 </logentry>
597 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
597 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
598 <parent revision="-1" node="0000000000000000000000000000000000000000" />
598 <parent revision="-1" node="0000000000000000000000000000000000000000" />
599 <author email="user@hostname">User Name</author>
599 <author email="user@hostname">User Name</author>
600 <date>1970-01-12T13:46:40+00:00</date>
600 <date>1970-01-12T13:46:40+00:00</date>
601 <msg xml:space="preserve">second</msg>
601 <msg xml:space="preserve">second</msg>
602 </logentry>
602 </logentry>
603 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
603 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
604 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
604 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
605 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
605 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
606 <author email="person">person</author>
606 <author email="person">person</author>
607 <date>1970-01-18T08:40:01+00:00</date>
607 <date>1970-01-18T08:40:01+00:00</date>
608 <msg xml:space="preserve">merge</msg>
608 <msg xml:space="preserve">merge</msg>
609 </logentry>
609 </logentry>
610 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
610 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
611 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
611 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
612 <author email="person">person</author>
612 <author email="person">person</author>
613 <date>1970-01-18T08:40:00+00:00</date>
613 <date>1970-01-18T08:40:00+00:00</date>
614 <msg xml:space="preserve">new head</msg>
614 <msg xml:space="preserve">new head</msg>
615 </logentry>
615 </logentry>
616 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
616 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
617 <branch>foo</branch>
617 <branch>foo</branch>
618 <author email="person">person</author>
618 <author email="person">person</author>
619 <date>1970-01-17T04:53:20+00:00</date>
619 <date>1970-01-17T04:53:20+00:00</date>
620 <msg xml:space="preserve">new branch</msg>
620 <msg xml:space="preserve">new branch</msg>
621 </logentry>
621 </logentry>
622 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
622 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
623 <author email="person">person</author>
623 <author email="person">person</author>
624 <date>1970-01-16T01:06:40+00:00</date>
624 <date>1970-01-16T01:06:40+00:00</date>
625 <msg xml:space="preserve">no user, no domain</msg>
625 <msg xml:space="preserve">no user, no domain</msg>
626 </logentry>
626 </logentry>
627 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
627 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
628 <author email="other@place">other</author>
628 <author email="other@place">other</author>
629 <date>1970-01-14T21:20:00+00:00</date>
629 <date>1970-01-14T21:20:00+00:00</date>
630 <msg xml:space="preserve">no person</msg>
630 <msg xml:space="preserve">no person</msg>
631 </logentry>
631 </logentry>
632 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
632 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
633 <author email="other@place">A. N. Other</author>
633 <author email="other@place">A. N. Other</author>
634 <date>1970-01-13T17:33:20+00:00</date>
634 <date>1970-01-13T17:33:20+00:00</date>
635 <msg xml:space="preserve">other 1
635 <msg xml:space="preserve">other 1
636 other 2
636 other 2
637
637
638 other 3</msg>
638 other 3</msg>
639 </logentry>
639 </logentry>
640 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
640 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
641 <author email="user@hostname">User Name</author>
641 <author email="user@hostname">User Name</author>
642 <date>1970-01-12T13:46:40+00:00</date>
642 <date>1970-01-12T13:46:40+00:00</date>
643 <msg xml:space="preserve">line 1
643 <msg xml:space="preserve">line 1
644 line 2</msg>
644 line 2</msg>
645 </logentry>
645 </logentry>
646 </log>
646 </log>
647
647
648 $ hg log -v --style xml
648 $ hg log -v --style xml
649 <?xml version="1.0"?>
649 <?xml version="1.0"?>
650 <log>
650 <log>
651 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
651 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
652 <tag>tip</tag>
652 <tag>tip</tag>
653 <author email="test">test</author>
653 <author email="test">test</author>
654 <date>2020-01-01T10:01:00+00:00</date>
654 <date>2020-01-01T10:01:00+00:00</date>
655 <msg xml:space="preserve">third</msg>
655 <msg xml:space="preserve">third</msg>
656 <paths>
656 <paths>
657 <path action="A">fourth</path>
657 <path action="A">fourth</path>
658 <path action="A">third</path>
658 <path action="A">third</path>
659 <path action="R">second</path>
659 <path action="R">second</path>
660 </paths>
660 </paths>
661 <copies>
661 <copies>
662 <copy source="second">fourth</copy>
662 <copy source="second">fourth</copy>
663 </copies>
663 </copies>
664 </logentry>
664 </logentry>
665 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
665 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
666 <parent revision="-1" node="0000000000000000000000000000000000000000" />
666 <parent revision="-1" node="0000000000000000000000000000000000000000" />
667 <author email="user@hostname">User Name</author>
667 <author email="user@hostname">User Name</author>
668 <date>1970-01-12T13:46:40+00:00</date>
668 <date>1970-01-12T13:46:40+00:00</date>
669 <msg xml:space="preserve">second</msg>
669 <msg xml:space="preserve">second</msg>
670 <paths>
670 <paths>
671 <path action="A">second</path>
671 <path action="A">second</path>
672 </paths>
672 </paths>
673 </logentry>
673 </logentry>
674 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
674 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
675 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
675 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
676 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
676 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
677 <author email="person">person</author>
677 <author email="person">person</author>
678 <date>1970-01-18T08:40:01+00:00</date>
678 <date>1970-01-18T08:40:01+00:00</date>
679 <msg xml:space="preserve">merge</msg>
679 <msg xml:space="preserve">merge</msg>
680 <paths>
680 <paths>
681 </paths>
681 </paths>
682 </logentry>
682 </logentry>
683 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
683 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
684 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
684 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
685 <author email="person">person</author>
685 <author email="person">person</author>
686 <date>1970-01-18T08:40:00+00:00</date>
686 <date>1970-01-18T08:40:00+00:00</date>
687 <msg xml:space="preserve">new head</msg>
687 <msg xml:space="preserve">new head</msg>
688 <paths>
688 <paths>
689 <path action="A">d</path>
689 <path action="A">d</path>
690 </paths>
690 </paths>
691 </logentry>
691 </logentry>
692 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
692 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
693 <branch>foo</branch>
693 <branch>foo</branch>
694 <author email="person">person</author>
694 <author email="person">person</author>
695 <date>1970-01-17T04:53:20+00:00</date>
695 <date>1970-01-17T04:53:20+00:00</date>
696 <msg xml:space="preserve">new branch</msg>
696 <msg xml:space="preserve">new branch</msg>
697 <paths>
697 <paths>
698 </paths>
698 </paths>
699 </logentry>
699 </logentry>
700 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
700 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
701 <author email="person">person</author>
701 <author email="person">person</author>
702 <date>1970-01-16T01:06:40+00:00</date>
702 <date>1970-01-16T01:06:40+00:00</date>
703 <msg xml:space="preserve">no user, no domain</msg>
703 <msg xml:space="preserve">no user, no domain</msg>
704 <paths>
704 <paths>
705 <path action="M">c</path>
705 <path action="M">c</path>
706 </paths>
706 </paths>
707 </logentry>
707 </logentry>
708 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
708 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
709 <author email="other@place">other</author>
709 <author email="other@place">other</author>
710 <date>1970-01-14T21:20:00+00:00</date>
710 <date>1970-01-14T21:20:00+00:00</date>
711 <msg xml:space="preserve">no person</msg>
711 <msg xml:space="preserve">no person</msg>
712 <paths>
712 <paths>
713 <path action="A">c</path>
713 <path action="A">c</path>
714 </paths>
714 </paths>
715 </logentry>
715 </logentry>
716 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
716 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
717 <author email="other@place">A. N. Other</author>
717 <author email="other@place">A. N. Other</author>
718 <date>1970-01-13T17:33:20+00:00</date>
718 <date>1970-01-13T17:33:20+00:00</date>
719 <msg xml:space="preserve">other 1
719 <msg xml:space="preserve">other 1
720 other 2
720 other 2
721
721
722 other 3</msg>
722 other 3</msg>
723 <paths>
723 <paths>
724 <path action="A">b</path>
724 <path action="A">b</path>
725 </paths>
725 </paths>
726 </logentry>
726 </logentry>
727 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
727 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
728 <author email="user@hostname">User Name</author>
728 <author email="user@hostname">User Name</author>
729 <date>1970-01-12T13:46:40+00:00</date>
729 <date>1970-01-12T13:46:40+00:00</date>
730 <msg xml:space="preserve">line 1
730 <msg xml:space="preserve">line 1
731 line 2</msg>
731 line 2</msg>
732 <paths>
732 <paths>
733 <path action="A">a</path>
733 <path action="A">a</path>
734 </paths>
734 </paths>
735 </logentry>
735 </logentry>
736 </log>
736 </log>
737
737
738 $ hg log --debug --style xml
738 $ hg log --debug --style xml
739 <?xml version="1.0"?>
739 <?xml version="1.0"?>
740 <log>
740 <log>
741 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
741 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
742 <tag>tip</tag>
742 <tag>tip</tag>
743 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
743 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
744 <parent revision="-1" node="0000000000000000000000000000000000000000" />
744 <parent revision="-1" node="0000000000000000000000000000000000000000" />
745 <author email="test">test</author>
745 <author email="test">test</author>
746 <date>2020-01-01T10:01:00+00:00</date>
746 <date>2020-01-01T10:01:00+00:00</date>
747 <msg xml:space="preserve">third</msg>
747 <msg xml:space="preserve">third</msg>
748 <paths>
748 <paths>
749 <path action="A">fourth</path>
749 <path action="A">fourth</path>
750 <path action="A">third</path>
750 <path action="A">third</path>
751 <path action="R">second</path>
751 <path action="R">second</path>
752 </paths>
752 </paths>
753 <copies>
753 <copies>
754 <copy source="second">fourth</copy>
754 <copy source="second">fourth</copy>
755 </copies>
755 </copies>
756 <extra key="branch">default</extra>
756 <extra key="branch">default</extra>
757 </logentry>
757 </logentry>
758 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
758 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
759 <parent revision="-1" node="0000000000000000000000000000000000000000" />
759 <parent revision="-1" node="0000000000000000000000000000000000000000" />
760 <parent revision="-1" node="0000000000000000000000000000000000000000" />
760 <parent revision="-1" node="0000000000000000000000000000000000000000" />
761 <author email="user@hostname">User Name</author>
761 <author email="user@hostname">User Name</author>
762 <date>1970-01-12T13:46:40+00:00</date>
762 <date>1970-01-12T13:46:40+00:00</date>
763 <msg xml:space="preserve">second</msg>
763 <msg xml:space="preserve">second</msg>
764 <paths>
764 <paths>
765 <path action="A">second</path>
765 <path action="A">second</path>
766 </paths>
766 </paths>
767 <extra key="branch">default</extra>
767 <extra key="branch">default</extra>
768 </logentry>
768 </logentry>
769 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
769 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
770 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
770 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
771 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
771 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
772 <author email="person">person</author>
772 <author email="person">person</author>
773 <date>1970-01-18T08:40:01+00:00</date>
773 <date>1970-01-18T08:40:01+00:00</date>
774 <msg xml:space="preserve">merge</msg>
774 <msg xml:space="preserve">merge</msg>
775 <paths>
775 <paths>
776 </paths>
776 </paths>
777 <extra key="branch">default</extra>
777 <extra key="branch">default</extra>
778 </logentry>
778 </logentry>
779 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
779 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
780 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
780 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
781 <parent revision="-1" node="0000000000000000000000000000000000000000" />
781 <parent revision="-1" node="0000000000000000000000000000000000000000" />
782 <author email="person">person</author>
782 <author email="person">person</author>
783 <date>1970-01-18T08:40:00+00:00</date>
783 <date>1970-01-18T08:40:00+00:00</date>
784 <msg xml:space="preserve">new head</msg>
784 <msg xml:space="preserve">new head</msg>
785 <paths>
785 <paths>
786 <path action="A">d</path>
786 <path action="A">d</path>
787 </paths>
787 </paths>
788 <extra key="branch">default</extra>
788 <extra key="branch">default</extra>
789 </logentry>
789 </logentry>
790 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
790 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
791 <branch>foo</branch>
791 <branch>foo</branch>
792 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
792 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
793 <parent revision="-1" node="0000000000000000000000000000000000000000" />
793 <parent revision="-1" node="0000000000000000000000000000000000000000" />
794 <author email="person">person</author>
794 <author email="person">person</author>
795 <date>1970-01-17T04:53:20+00:00</date>
795 <date>1970-01-17T04:53:20+00:00</date>
796 <msg xml:space="preserve">new branch</msg>
796 <msg xml:space="preserve">new branch</msg>
797 <paths>
797 <paths>
798 </paths>
798 </paths>
799 <extra key="branch">foo</extra>
799 <extra key="branch">foo</extra>
800 </logentry>
800 </logentry>
801 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
801 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
802 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
802 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
803 <parent revision="-1" node="0000000000000000000000000000000000000000" />
803 <parent revision="-1" node="0000000000000000000000000000000000000000" />
804 <author email="person">person</author>
804 <author email="person">person</author>
805 <date>1970-01-16T01:06:40+00:00</date>
805 <date>1970-01-16T01:06:40+00:00</date>
806 <msg xml:space="preserve">no user, no domain</msg>
806 <msg xml:space="preserve">no user, no domain</msg>
807 <paths>
807 <paths>
808 <path action="M">c</path>
808 <path action="M">c</path>
809 </paths>
809 </paths>
810 <extra key="branch">default</extra>
810 <extra key="branch">default</extra>
811 </logentry>
811 </logentry>
812 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
812 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
813 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
813 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
814 <parent revision="-1" node="0000000000000000000000000000000000000000" />
814 <parent revision="-1" node="0000000000000000000000000000000000000000" />
815 <author email="other@place">other</author>
815 <author email="other@place">other</author>
816 <date>1970-01-14T21:20:00+00:00</date>
816 <date>1970-01-14T21:20:00+00:00</date>
817 <msg xml:space="preserve">no person</msg>
817 <msg xml:space="preserve">no person</msg>
818 <paths>
818 <paths>
819 <path action="A">c</path>
819 <path action="A">c</path>
820 </paths>
820 </paths>
821 <extra key="branch">default</extra>
821 <extra key="branch">default</extra>
822 </logentry>
822 </logentry>
823 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
823 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
824 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
824 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
825 <parent revision="-1" node="0000000000000000000000000000000000000000" />
825 <parent revision="-1" node="0000000000000000000000000000000000000000" />
826 <author email="other@place">A. N. Other</author>
826 <author email="other@place">A. N. Other</author>
827 <date>1970-01-13T17:33:20+00:00</date>
827 <date>1970-01-13T17:33:20+00:00</date>
828 <msg xml:space="preserve">other 1
828 <msg xml:space="preserve">other 1
829 other 2
829 other 2
830
830
831 other 3</msg>
831 other 3</msg>
832 <paths>
832 <paths>
833 <path action="A">b</path>
833 <path action="A">b</path>
834 </paths>
834 </paths>
835 <extra key="branch">default</extra>
835 <extra key="branch">default</extra>
836 </logentry>
836 </logentry>
837 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
837 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
838 <parent revision="-1" node="0000000000000000000000000000000000000000" />
838 <parent revision="-1" node="0000000000000000000000000000000000000000" />
839 <parent revision="-1" node="0000000000000000000000000000000000000000" />
839 <parent revision="-1" node="0000000000000000000000000000000000000000" />
840 <author email="user@hostname">User Name</author>
840 <author email="user@hostname">User Name</author>
841 <date>1970-01-12T13:46:40+00:00</date>
841 <date>1970-01-12T13:46:40+00:00</date>
842 <msg xml:space="preserve">line 1
842 <msg xml:space="preserve">line 1
843 line 2</msg>
843 line 2</msg>
844 <paths>
844 <paths>
845 <path action="A">a</path>
845 <path action="A">a</path>
846 </paths>
846 </paths>
847 <extra key="branch">default</extra>
847 <extra key="branch">default</extra>
848 </logentry>
848 </logentry>
849 </log>
849 </log>
850
850
851
851
852 Test JSON style:
852 Test JSON style:
853
853
854 $ hg log -k nosuch -Tjson
854 $ hg log -k nosuch -Tjson
855 []
855 []
856
856
857 $ hg log -qr . -Tjson
857 $ hg log -qr . -Tjson
858 [
858 [
859 {
859 {
860 "rev": 8,
860 "rev": 8,
861 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
861 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
862 }
862 }
863 ]
863 ]
864
864
865 $ hg log -vpr . -Tjson --stat
865 $ hg log -vpr . -Tjson --stat
866 [
866 [
867 {
867 {
868 "rev": 8,
868 "rev": 8,
869 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
869 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
870 "branch": "default",
870 "branch": "default",
871 "phase": "draft",
871 "phase": "draft",
872 "user": "test",
872 "user": "test",
873 "date": [1577872860, 0],
873 "date": [1577872860, 0],
874 "desc": "third",
874 "desc": "third",
875 "bookmarks": [],
875 "bookmarks": [],
876 "tags": ["tip"],
876 "tags": ["tip"],
877 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
877 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
878 "files": ["fourth", "second", "third"],
878 "files": ["fourth", "second", "third"],
879 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
879 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
880 "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"
880 "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"
881 }
881 }
882 ]
882 ]
883
883
884 honor --git but not format-breaking diffopts
884 honor --git but not format-breaking diffopts
885 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
885 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
886 [
886 [
887 {
887 {
888 "rev": 8,
888 "rev": 8,
889 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
889 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
890 "branch": "default",
890 "branch": "default",
891 "phase": "draft",
891 "phase": "draft",
892 "user": "test",
892 "user": "test",
893 "date": [1577872860, 0],
893 "date": [1577872860, 0],
894 "desc": "third",
894 "desc": "third",
895 "bookmarks": [],
895 "bookmarks": [],
896 "tags": ["tip"],
896 "tags": ["tip"],
897 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
897 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
898 "files": ["fourth", "second", "third"],
898 "files": ["fourth", "second", "third"],
899 "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"
899 "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"
900 }
900 }
901 ]
901 ]
902
902
903 $ hg log -T json
903 $ hg log -T json
904 [
904 [
905 {
905 {
906 "rev": 8,
906 "rev": 8,
907 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
907 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
908 "branch": "default",
908 "branch": "default",
909 "phase": "draft",
909 "phase": "draft",
910 "user": "test",
910 "user": "test",
911 "date": [1577872860, 0],
911 "date": [1577872860, 0],
912 "desc": "third",
912 "desc": "third",
913 "bookmarks": [],
913 "bookmarks": [],
914 "tags": ["tip"],
914 "tags": ["tip"],
915 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
915 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
916 },
916 },
917 {
917 {
918 "rev": 7,
918 "rev": 7,
919 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
919 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
920 "branch": "default",
920 "branch": "default",
921 "phase": "draft",
921 "phase": "draft",
922 "user": "User Name <user@hostname>",
922 "user": "User Name <user@hostname>",
923 "date": [1000000, 0],
923 "date": [1000000, 0],
924 "desc": "second",
924 "desc": "second",
925 "bookmarks": [],
925 "bookmarks": [],
926 "tags": [],
926 "tags": [],
927 "parents": ["0000000000000000000000000000000000000000"]
927 "parents": ["0000000000000000000000000000000000000000"]
928 },
928 },
929 {
929 {
930 "rev": 6,
930 "rev": 6,
931 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
931 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
932 "branch": "default",
932 "branch": "default",
933 "phase": "draft",
933 "phase": "draft",
934 "user": "person",
934 "user": "person",
935 "date": [1500001, 0],
935 "date": [1500001, 0],
936 "desc": "merge",
936 "desc": "merge",
937 "bookmarks": [],
937 "bookmarks": [],
938 "tags": [],
938 "tags": [],
939 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
939 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
940 },
940 },
941 {
941 {
942 "rev": 5,
942 "rev": 5,
943 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
943 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
944 "branch": "default",
944 "branch": "default",
945 "phase": "draft",
945 "phase": "draft",
946 "user": "person",
946 "user": "person",
947 "date": [1500000, 0],
947 "date": [1500000, 0],
948 "desc": "new head",
948 "desc": "new head",
949 "bookmarks": [],
949 "bookmarks": [],
950 "tags": [],
950 "tags": [],
951 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
951 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
952 },
952 },
953 {
953 {
954 "rev": 4,
954 "rev": 4,
955 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
955 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
956 "branch": "foo",
956 "branch": "foo",
957 "phase": "draft",
957 "phase": "draft",
958 "user": "person",
958 "user": "person",
959 "date": [1400000, 0],
959 "date": [1400000, 0],
960 "desc": "new branch",
960 "desc": "new branch",
961 "bookmarks": [],
961 "bookmarks": [],
962 "tags": [],
962 "tags": [],
963 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
963 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
964 },
964 },
965 {
965 {
966 "rev": 3,
966 "rev": 3,
967 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
967 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
968 "branch": "default",
968 "branch": "default",
969 "phase": "draft",
969 "phase": "draft",
970 "user": "person",
970 "user": "person",
971 "date": [1300000, 0],
971 "date": [1300000, 0],
972 "desc": "no user, no domain",
972 "desc": "no user, no domain",
973 "bookmarks": [],
973 "bookmarks": [],
974 "tags": [],
974 "tags": [],
975 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
975 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
976 },
976 },
977 {
977 {
978 "rev": 2,
978 "rev": 2,
979 "node": "97054abb4ab824450e9164180baf491ae0078465",
979 "node": "97054abb4ab824450e9164180baf491ae0078465",
980 "branch": "default",
980 "branch": "default",
981 "phase": "draft",
981 "phase": "draft",
982 "user": "other@place",
982 "user": "other@place",
983 "date": [1200000, 0],
983 "date": [1200000, 0],
984 "desc": "no person",
984 "desc": "no person",
985 "bookmarks": [],
985 "bookmarks": [],
986 "tags": [],
986 "tags": [],
987 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
987 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
988 },
988 },
989 {
989 {
990 "rev": 1,
990 "rev": 1,
991 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
991 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
992 "branch": "default",
992 "branch": "default",
993 "phase": "draft",
993 "phase": "draft",
994 "user": "A. N. Other <other@place>",
994 "user": "A. N. Other <other@place>",
995 "date": [1100000, 0],
995 "date": [1100000, 0],
996 "desc": "other 1\nother 2\n\nother 3",
996 "desc": "other 1\nother 2\n\nother 3",
997 "bookmarks": [],
997 "bookmarks": [],
998 "tags": [],
998 "tags": [],
999 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
999 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
1000 },
1000 },
1001 {
1001 {
1002 "rev": 0,
1002 "rev": 0,
1003 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1003 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1004 "branch": "default",
1004 "branch": "default",
1005 "phase": "draft",
1005 "phase": "draft",
1006 "user": "User Name <user@hostname>",
1006 "user": "User Name <user@hostname>",
1007 "date": [1000000, 0],
1007 "date": [1000000, 0],
1008 "desc": "line 1\nline 2",
1008 "desc": "line 1\nline 2",
1009 "bookmarks": [],
1009 "bookmarks": [],
1010 "tags": [],
1010 "tags": [],
1011 "parents": ["0000000000000000000000000000000000000000"]
1011 "parents": ["0000000000000000000000000000000000000000"]
1012 }
1012 }
1013 ]
1013 ]
1014
1014
1015 $ hg heads -v -Tjson
1015 $ hg heads -v -Tjson
1016 [
1016 [
1017 {
1017 {
1018 "rev": 8,
1018 "rev": 8,
1019 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
1019 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
1020 "branch": "default",
1020 "branch": "default",
1021 "phase": "draft",
1021 "phase": "draft",
1022 "user": "test",
1022 "user": "test",
1023 "date": [1577872860, 0],
1023 "date": [1577872860, 0],
1024 "desc": "third",
1024 "desc": "third",
1025 "bookmarks": [],
1025 "bookmarks": [],
1026 "tags": ["tip"],
1026 "tags": ["tip"],
1027 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
1027 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
1028 "files": ["fourth", "second", "third"]
1028 "files": ["fourth", "second", "third"]
1029 },
1029 },
1030 {
1030 {
1031 "rev": 6,
1031 "rev": 6,
1032 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1032 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1033 "branch": "default",
1033 "branch": "default",
1034 "phase": "draft",
1034 "phase": "draft",
1035 "user": "person",
1035 "user": "person",
1036 "date": [1500001, 0],
1036 "date": [1500001, 0],
1037 "desc": "merge",
1037 "desc": "merge",
1038 "bookmarks": [],
1038 "bookmarks": [],
1039 "tags": [],
1039 "tags": [],
1040 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1040 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1041 "files": []
1041 "files": []
1042 },
1042 },
1043 {
1043 {
1044 "rev": 4,
1044 "rev": 4,
1045 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1045 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1046 "branch": "foo",
1046 "branch": "foo",
1047 "phase": "draft",
1047 "phase": "draft",
1048 "user": "person",
1048 "user": "person",
1049 "date": [1400000, 0],
1049 "date": [1400000, 0],
1050 "desc": "new branch",
1050 "desc": "new branch",
1051 "bookmarks": [],
1051 "bookmarks": [],
1052 "tags": [],
1052 "tags": [],
1053 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1053 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1054 "files": []
1054 "files": []
1055 }
1055 }
1056 ]
1056 ]
1057
1057
1058 $ hg log --debug -Tjson
1058 $ hg log --debug -Tjson
1059 [
1059 [
1060 {
1060 {
1061 "rev": 8,
1061 "rev": 8,
1062 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
1062 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
1063 "branch": "default",
1063 "branch": "default",
1064 "phase": "draft",
1064 "phase": "draft",
1065 "user": "test",
1065 "user": "test",
1066 "date": [1577872860, 0],
1066 "date": [1577872860, 0],
1067 "desc": "third",
1067 "desc": "third",
1068 "bookmarks": [],
1068 "bookmarks": [],
1069 "tags": ["tip"],
1069 "tags": ["tip"],
1070 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
1070 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
1071 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
1071 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
1072 "extra": {"branch": "default"},
1072 "extra": {"branch": "default"},
1073 "modified": [],
1073 "modified": [],
1074 "added": ["fourth", "third"],
1074 "added": ["fourth", "third"],
1075 "removed": ["second"]
1075 "removed": ["second"]
1076 },
1076 },
1077 {
1077 {
1078 "rev": 7,
1078 "rev": 7,
1079 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
1079 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
1080 "branch": "default",
1080 "branch": "default",
1081 "phase": "draft",
1081 "phase": "draft",
1082 "user": "User Name <user@hostname>",
1082 "user": "User Name <user@hostname>",
1083 "date": [1000000, 0],
1083 "date": [1000000, 0],
1084 "desc": "second",
1084 "desc": "second",
1085 "bookmarks": [],
1085 "bookmarks": [],
1086 "tags": [],
1086 "tags": [],
1087 "parents": ["0000000000000000000000000000000000000000"],
1087 "parents": ["0000000000000000000000000000000000000000"],
1088 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
1088 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
1089 "extra": {"branch": "default"},
1089 "extra": {"branch": "default"},
1090 "modified": [],
1090 "modified": [],
1091 "added": ["second"],
1091 "added": ["second"],
1092 "removed": []
1092 "removed": []
1093 },
1093 },
1094 {
1094 {
1095 "rev": 6,
1095 "rev": 6,
1096 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1096 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1097 "branch": "default",
1097 "branch": "default",
1098 "phase": "draft",
1098 "phase": "draft",
1099 "user": "person",
1099 "user": "person",
1100 "date": [1500001, 0],
1100 "date": [1500001, 0],
1101 "desc": "merge",
1101 "desc": "merge",
1102 "bookmarks": [],
1102 "bookmarks": [],
1103 "tags": [],
1103 "tags": [],
1104 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1104 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1105 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1105 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1106 "extra": {"branch": "default"},
1106 "extra": {"branch": "default"},
1107 "modified": [],
1107 "modified": [],
1108 "added": [],
1108 "added": [],
1109 "removed": []
1109 "removed": []
1110 },
1110 },
1111 {
1111 {
1112 "rev": 5,
1112 "rev": 5,
1113 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
1113 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
1114 "branch": "default",
1114 "branch": "default",
1115 "phase": "draft",
1115 "phase": "draft",
1116 "user": "person",
1116 "user": "person",
1117 "date": [1500000, 0],
1117 "date": [1500000, 0],
1118 "desc": "new head",
1118 "desc": "new head",
1119 "bookmarks": [],
1119 "bookmarks": [],
1120 "tags": [],
1120 "tags": [],
1121 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1121 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1122 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1122 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1123 "extra": {"branch": "default"},
1123 "extra": {"branch": "default"},
1124 "modified": [],
1124 "modified": [],
1125 "added": ["d"],
1125 "added": ["d"],
1126 "removed": []
1126 "removed": []
1127 },
1127 },
1128 {
1128 {
1129 "rev": 4,
1129 "rev": 4,
1130 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1130 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1131 "branch": "foo",
1131 "branch": "foo",
1132 "phase": "draft",
1132 "phase": "draft",
1133 "user": "person",
1133 "user": "person",
1134 "date": [1400000, 0],
1134 "date": [1400000, 0],
1135 "desc": "new branch",
1135 "desc": "new branch",
1136 "bookmarks": [],
1136 "bookmarks": [],
1137 "tags": [],
1137 "tags": [],
1138 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1138 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1139 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1139 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1140 "extra": {"branch": "foo"},
1140 "extra": {"branch": "foo"},
1141 "modified": [],
1141 "modified": [],
1142 "added": [],
1142 "added": [],
1143 "removed": []
1143 "removed": []
1144 },
1144 },
1145 {
1145 {
1146 "rev": 3,
1146 "rev": 3,
1147 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
1147 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
1148 "branch": "default",
1148 "branch": "default",
1149 "phase": "draft",
1149 "phase": "draft",
1150 "user": "person",
1150 "user": "person",
1151 "date": [1300000, 0],
1151 "date": [1300000, 0],
1152 "desc": "no user, no domain",
1152 "desc": "no user, no domain",
1153 "bookmarks": [],
1153 "bookmarks": [],
1154 "tags": [],
1154 "tags": [],
1155 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
1155 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
1156 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1156 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1157 "extra": {"branch": "default"},
1157 "extra": {"branch": "default"},
1158 "modified": ["c"],
1158 "modified": ["c"],
1159 "added": [],
1159 "added": [],
1160 "removed": []
1160 "removed": []
1161 },
1161 },
1162 {
1162 {
1163 "rev": 2,
1163 "rev": 2,
1164 "node": "97054abb4ab824450e9164180baf491ae0078465",
1164 "node": "97054abb4ab824450e9164180baf491ae0078465",
1165 "branch": "default",
1165 "branch": "default",
1166 "phase": "draft",
1166 "phase": "draft",
1167 "user": "other@place",
1167 "user": "other@place",
1168 "date": [1200000, 0],
1168 "date": [1200000, 0],
1169 "desc": "no person",
1169 "desc": "no person",
1170 "bookmarks": [],
1170 "bookmarks": [],
1171 "tags": [],
1171 "tags": [],
1172 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
1172 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
1173 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
1173 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
1174 "extra": {"branch": "default"},
1174 "extra": {"branch": "default"},
1175 "modified": [],
1175 "modified": [],
1176 "added": ["c"],
1176 "added": ["c"],
1177 "removed": []
1177 "removed": []
1178 },
1178 },
1179 {
1179 {
1180 "rev": 1,
1180 "rev": 1,
1181 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
1181 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
1182 "branch": "default",
1182 "branch": "default",
1183 "phase": "draft",
1183 "phase": "draft",
1184 "user": "A. N. Other <other@place>",
1184 "user": "A. N. Other <other@place>",
1185 "date": [1100000, 0],
1185 "date": [1100000, 0],
1186 "desc": "other 1\nother 2\n\nother 3",
1186 "desc": "other 1\nother 2\n\nother 3",
1187 "bookmarks": [],
1187 "bookmarks": [],
1188 "tags": [],
1188 "tags": [],
1189 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
1189 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
1190 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
1190 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
1191 "extra": {"branch": "default"},
1191 "extra": {"branch": "default"},
1192 "modified": [],
1192 "modified": [],
1193 "added": ["b"],
1193 "added": ["b"],
1194 "removed": []
1194 "removed": []
1195 },
1195 },
1196 {
1196 {
1197 "rev": 0,
1197 "rev": 0,
1198 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1198 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1199 "branch": "default",
1199 "branch": "default",
1200 "phase": "draft",
1200 "phase": "draft",
1201 "user": "User Name <user@hostname>",
1201 "user": "User Name <user@hostname>",
1202 "date": [1000000, 0],
1202 "date": [1000000, 0],
1203 "desc": "line 1\nline 2",
1203 "desc": "line 1\nline 2",
1204 "bookmarks": [],
1204 "bookmarks": [],
1205 "tags": [],
1205 "tags": [],
1206 "parents": ["0000000000000000000000000000000000000000"],
1206 "parents": ["0000000000000000000000000000000000000000"],
1207 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
1207 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
1208 "extra": {"branch": "default"},
1208 "extra": {"branch": "default"},
1209 "modified": [],
1209 "modified": [],
1210 "added": ["a"],
1210 "added": ["a"],
1211 "removed": []
1211 "removed": []
1212 }
1212 }
1213 ]
1213 ]
1214
1214
1215 Error if style not readable:
1215 Error if style not readable:
1216
1216
1217 #if unix-permissions no-root
1217 #if unix-permissions no-root
1218 $ touch q
1218 $ touch q
1219 $ chmod 0 q
1219 $ chmod 0 q
1220 $ hg log --style ./q
1220 $ hg log --style ./q
1221 abort: Permission denied: ./q
1221 abort: Permission denied: ./q
1222 [255]
1222 [255]
1223 #endif
1223 #endif
1224
1224
1225 Error if no style:
1225 Error if no style:
1226
1226
1227 $ hg log --style notexist
1227 $ hg log --style notexist
1228 abort: style 'notexist' not found
1228 abort: style 'notexist' not found
1229 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1229 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1230 [255]
1230 [255]
1231
1231
1232 $ hg log -T list
1232 $ hg log -T list
1233 available styles: bisect, changelog, compact, default, phases, show, status, xml
1233 available styles: bisect, changelog, compact, default, phases, show, status, xml
1234 abort: specify a template
1234 abort: specify a template
1235 [255]
1235 [255]
1236
1236
1237 Error if style missing key:
1237 Error if style missing key:
1238
1238
1239 $ echo 'q = q' > t
1239 $ echo 'q = q' > t
1240 $ hg log --style ./t
1240 $ hg log --style ./t
1241 abort: "changeset" not in template map
1241 abort: "changeset" not in template map
1242 [255]
1242 [255]
1243
1243
1244 Error if style missing value:
1244 Error if style missing value:
1245
1245
1246 $ echo 'changeset =' > t
1246 $ echo 'changeset =' > t
1247 $ hg log --style t
1247 $ hg log --style t
1248 hg: parse error at t:1: missing value
1248 hg: parse error at t:1: missing value
1249 [255]
1249 [255]
1250
1250
1251 Error if include fails:
1251 Error if include fails:
1252
1252
1253 $ echo 'changeset = q' >> t
1253 $ echo 'changeset = q' >> t
1254 #if unix-permissions no-root
1254 #if unix-permissions no-root
1255 $ hg log --style ./t
1255 $ hg log --style ./t
1256 abort: template file ./q: Permission denied
1256 abort: template file ./q: Permission denied
1257 [255]
1257 [255]
1258 $ rm -f q
1258 $ rm -f q
1259 #endif
1259 #endif
1260
1260
1261 Include works:
1261 Include works:
1262
1262
1263 $ echo '{rev}' > q
1263 $ echo '{rev}' > q
1264 $ hg log --style ./t
1264 $ hg log --style ./t
1265 8
1265 8
1266 7
1266 7
1267 6
1267 6
1268 5
1268 5
1269 4
1269 4
1270 3
1270 3
1271 2
1271 2
1272 1
1272 1
1273 0
1273 0
1274
1274
1275 Check that recursive reference does not fall into RuntimeError (issue4758):
1275 Check that recursive reference does not fall into RuntimeError (issue4758):
1276
1276
1277 common mistake:
1277 common mistake:
1278
1278
1279 $ cat << EOF > issue4758
1279 $ cat << EOF > issue4758
1280 > changeset = '{changeset}\n'
1280 > changeset = '{changeset}\n'
1281 > EOF
1281 > EOF
1282 $ hg log --style ./issue4758
1282 $ hg log --style ./issue4758
1283 abort: recursive reference 'changeset' in template
1283 abort: recursive reference 'changeset' in template
1284 [255]
1284 [255]
1285
1285
1286 circular reference:
1286 circular reference:
1287
1287
1288 $ cat << EOF > issue4758
1288 $ cat << EOF > issue4758
1289 > changeset = '{foo}'
1289 > changeset = '{foo}'
1290 > foo = '{changeset}'
1290 > foo = '{changeset}'
1291 > EOF
1291 > EOF
1292 $ hg log --style ./issue4758
1292 $ hg log --style ./issue4758
1293 abort: recursive reference 'foo' in template
1293 abort: recursive reference 'foo' in template
1294 [255]
1294 [255]
1295
1295
1296 buildmap() -> gettemplate(), where no thunk was made:
1296 buildmap() -> gettemplate(), where no thunk was made:
1297
1297
1298 $ cat << EOF > issue4758
1298 $ cat << EOF > issue4758
1299 > changeset = '{files % changeset}\n'
1299 > changeset = '{files % changeset}\n'
1300 > EOF
1300 > EOF
1301 $ hg log --style ./issue4758
1301 $ hg log --style ./issue4758
1302 abort: recursive reference 'changeset' in template
1302 abort: recursive reference 'changeset' in template
1303 [255]
1303 [255]
1304
1304
1305 not a recursion if a keyword of the same name exists:
1305 not a recursion if a keyword of the same name exists:
1306
1306
1307 $ cat << EOF > issue4758
1307 $ cat << EOF > issue4758
1308 > changeset = '{tags % rev}'
1308 > changeset = '{tags % rev}'
1309 > rev = '{rev} {tag}\n'
1309 > rev = '{rev} {tag}\n'
1310 > EOF
1310 > EOF
1311 $ hg log --style ./issue4758 -r tip
1311 $ hg log --style ./issue4758 -r tip
1312 8 tip
1312 8 tip
1313
1313
1314 Check that {phase} works correctly on parents:
1314 Check that {phase} works correctly on parents:
1315
1315
1316 $ cat << EOF > parentphase
1316 $ cat << EOF > parentphase
1317 > changeset_debug = '{rev} ({phase}):{parents}\n'
1317 > changeset_debug = '{rev} ({phase}):{parents}\n'
1318 > parent = ' {rev} ({phase})'
1318 > parent = ' {rev} ({phase})'
1319 > EOF
1319 > EOF
1320 $ hg phase -r 5 --public
1320 $ hg phase -r 5 --public
1321 $ hg phase -r 7 --secret --force
1321 $ hg phase -r 7 --secret --force
1322 $ hg log --debug -G --style ./parentphase
1322 $ hg log --debug -G --style ./parentphase
1323 @ 8 (secret): 7 (secret) -1 (public)
1323 @ 8 (secret): 7 (secret) -1 (public)
1324 |
1324 |
1325 o 7 (secret): -1 (public) -1 (public)
1325 o 7 (secret): -1 (public) -1 (public)
1326
1326
1327 o 6 (draft): 5 (public) 4 (draft)
1327 o 6 (draft): 5 (public) 4 (draft)
1328 |\
1328 |\
1329 | o 5 (public): 3 (public) -1 (public)
1329 | o 5 (public): 3 (public) -1 (public)
1330 | |
1330 | |
1331 o | 4 (draft): 3 (public) -1 (public)
1331 o | 4 (draft): 3 (public) -1 (public)
1332 |/
1332 |/
1333 o 3 (public): 2 (public) -1 (public)
1333 o 3 (public): 2 (public) -1 (public)
1334 |
1334 |
1335 o 2 (public): 1 (public) -1 (public)
1335 o 2 (public): 1 (public) -1 (public)
1336 |
1336 |
1337 o 1 (public): 0 (public) -1 (public)
1337 o 1 (public): 0 (public) -1 (public)
1338 |
1338 |
1339 o 0 (public): -1 (public) -1 (public)
1339 o 0 (public): -1 (public) -1 (public)
1340
1340
1341
1341
1342 Missing non-standard names give no error (backward compatibility):
1342 Missing non-standard names give no error (backward compatibility):
1343
1343
1344 $ echo "changeset = '{c}'" > t
1344 $ echo "changeset = '{c}'" > t
1345 $ hg log --style ./t
1345 $ hg log --style ./t
1346
1346
1347 Defining non-standard name works:
1347 Defining non-standard name works:
1348
1348
1349 $ cat <<EOF > t
1349 $ cat <<EOF > t
1350 > changeset = '{c}'
1350 > changeset = '{c}'
1351 > c = q
1351 > c = q
1352 > EOF
1352 > EOF
1353 $ hg log --style ./t
1353 $ hg log --style ./t
1354 8
1354 8
1355 7
1355 7
1356 6
1356 6
1357 5
1357 5
1358 4
1358 4
1359 3
1359 3
1360 2
1360 2
1361 1
1361 1
1362 0
1362 0
1363
1363
1364 ui.style works:
1364 ui.style works:
1365
1365
1366 $ echo '[ui]' > .hg/hgrc
1366 $ echo '[ui]' > .hg/hgrc
1367 $ echo 'style = t' >> .hg/hgrc
1367 $ echo 'style = t' >> .hg/hgrc
1368 $ hg log
1368 $ hg log
1369 8
1369 8
1370 7
1370 7
1371 6
1371 6
1372 5
1372 5
1373 4
1373 4
1374 3
1374 3
1375 2
1375 2
1376 1
1376 1
1377 0
1377 0
1378
1378
1379
1379
1380 Issue338:
1380 Issue338:
1381
1381
1382 $ hg log --style=changelog > changelog
1382 $ hg log --style=changelog > changelog
1383
1383
1384 $ cat changelog
1384 $ cat changelog
1385 2020-01-01 test <test>
1385 2020-01-01 test <test>
1386
1386
1387 * fourth, second, third:
1387 * fourth, second, third:
1388 third
1388 third
1389 [95c24699272e] [tip]
1389 [95c24699272e] [tip]
1390
1390
1391 1970-01-12 User Name <user@hostname>
1391 1970-01-12 User Name <user@hostname>
1392
1392
1393 * second:
1393 * second:
1394 second
1394 second
1395 [29114dbae42b]
1395 [29114dbae42b]
1396
1396
1397 1970-01-18 person <person>
1397 1970-01-18 person <person>
1398
1398
1399 * merge
1399 * merge
1400 [d41e714fe50d]
1400 [d41e714fe50d]
1401
1401
1402 * d:
1402 * d:
1403 new head
1403 new head
1404 [13207e5a10d9]
1404 [13207e5a10d9]
1405
1405
1406 1970-01-17 person <person>
1406 1970-01-17 person <person>
1407
1407
1408 * new branch
1408 * new branch
1409 [bbe44766e73d] <foo>
1409 [bbe44766e73d] <foo>
1410
1410
1411 1970-01-16 person <person>
1411 1970-01-16 person <person>
1412
1412
1413 * c:
1413 * c:
1414 no user, no domain
1414 no user, no domain
1415 [10e46f2dcbf4]
1415 [10e46f2dcbf4]
1416
1416
1417 1970-01-14 other <other@place>
1417 1970-01-14 other <other@place>
1418
1418
1419 * c:
1419 * c:
1420 no person
1420 no person
1421 [97054abb4ab8]
1421 [97054abb4ab8]
1422
1422
1423 1970-01-13 A. N. Other <other@place>
1423 1970-01-13 A. N. Other <other@place>
1424
1424
1425 * b:
1425 * b:
1426 other 1 other 2
1426 other 1 other 2
1427
1427
1428 other 3
1428 other 3
1429 [b608e9d1a3f0]
1429 [b608e9d1a3f0]
1430
1430
1431 1970-01-12 User Name <user@hostname>
1431 1970-01-12 User Name <user@hostname>
1432
1432
1433 * a:
1433 * a:
1434 line 1 line 2
1434 line 1 line 2
1435 [1e4e1b8f71e0]
1435 [1e4e1b8f71e0]
1436
1436
1437
1437
1438 Issue2130: xml output for 'hg heads' is malformed
1438 Issue2130: xml output for 'hg heads' is malformed
1439
1439
1440 $ hg heads --style changelog
1440 $ hg heads --style changelog
1441 2020-01-01 test <test>
1441 2020-01-01 test <test>
1442
1442
1443 * fourth, second, third:
1443 * fourth, second, third:
1444 third
1444 third
1445 [95c24699272e] [tip]
1445 [95c24699272e] [tip]
1446
1446
1447 1970-01-18 person <person>
1447 1970-01-18 person <person>
1448
1448
1449 * merge
1449 * merge
1450 [d41e714fe50d]
1450 [d41e714fe50d]
1451
1451
1452 1970-01-17 person <person>
1452 1970-01-17 person <person>
1453
1453
1454 * new branch
1454 * new branch
1455 [bbe44766e73d] <foo>
1455 [bbe44766e73d] <foo>
1456
1456
1457
1457
1458 Keys work:
1458 Keys work:
1459
1459
1460 $ for key in author branch branches date desc file_adds file_dels file_mods \
1460 $ for key in author branch branches date desc file_adds file_dels file_mods \
1461 > file_copies file_copies_switch files \
1461 > file_copies file_copies_switch files \
1462 > manifest node parents rev tags diffstat extras \
1462 > manifest node parents rev tags diffstat extras \
1463 > p1rev p2rev p1node p2node; do
1463 > p1rev p2rev p1node p2node; do
1464 > for mode in '' --verbose --debug; do
1464 > for mode in '' --verbose --debug; do
1465 > hg log $mode --template "$key$mode: {$key}\n"
1465 > hg log $mode --template "$key$mode: {$key}\n"
1466 > done
1466 > done
1467 > done
1467 > done
1468 author: test
1468 author: test
1469 author: User Name <user@hostname>
1469 author: User Name <user@hostname>
1470 author: person
1470 author: person
1471 author: person
1471 author: person
1472 author: person
1472 author: person
1473 author: person
1473 author: person
1474 author: other@place
1474 author: other@place
1475 author: A. N. Other <other@place>
1475 author: A. N. Other <other@place>
1476 author: User Name <user@hostname>
1476 author: User Name <user@hostname>
1477 author--verbose: test
1477 author--verbose: test
1478 author--verbose: User Name <user@hostname>
1478 author--verbose: User Name <user@hostname>
1479 author--verbose: person
1479 author--verbose: person
1480 author--verbose: person
1480 author--verbose: person
1481 author--verbose: person
1481 author--verbose: person
1482 author--verbose: person
1482 author--verbose: person
1483 author--verbose: other@place
1483 author--verbose: other@place
1484 author--verbose: A. N. Other <other@place>
1484 author--verbose: A. N. Other <other@place>
1485 author--verbose: User Name <user@hostname>
1485 author--verbose: User Name <user@hostname>
1486 author--debug: test
1486 author--debug: test
1487 author--debug: User Name <user@hostname>
1487 author--debug: User Name <user@hostname>
1488 author--debug: person
1488 author--debug: person
1489 author--debug: person
1489 author--debug: person
1490 author--debug: person
1490 author--debug: person
1491 author--debug: person
1491 author--debug: person
1492 author--debug: other@place
1492 author--debug: other@place
1493 author--debug: A. N. Other <other@place>
1493 author--debug: A. N. Other <other@place>
1494 author--debug: User Name <user@hostname>
1494 author--debug: User Name <user@hostname>
1495 branch: default
1495 branch: default
1496 branch: default
1496 branch: default
1497 branch: default
1497 branch: default
1498 branch: default
1498 branch: default
1499 branch: foo
1499 branch: foo
1500 branch: default
1500 branch: default
1501 branch: default
1501 branch: default
1502 branch: default
1502 branch: default
1503 branch: default
1503 branch: default
1504 branch--verbose: default
1504 branch--verbose: default
1505 branch--verbose: default
1505 branch--verbose: default
1506 branch--verbose: default
1506 branch--verbose: default
1507 branch--verbose: default
1507 branch--verbose: default
1508 branch--verbose: foo
1508 branch--verbose: foo
1509 branch--verbose: default
1509 branch--verbose: default
1510 branch--verbose: default
1510 branch--verbose: default
1511 branch--verbose: default
1511 branch--verbose: default
1512 branch--verbose: default
1512 branch--verbose: default
1513 branch--debug: default
1513 branch--debug: default
1514 branch--debug: default
1514 branch--debug: default
1515 branch--debug: default
1515 branch--debug: default
1516 branch--debug: default
1516 branch--debug: default
1517 branch--debug: foo
1517 branch--debug: foo
1518 branch--debug: default
1518 branch--debug: default
1519 branch--debug: default
1519 branch--debug: default
1520 branch--debug: default
1520 branch--debug: default
1521 branch--debug: default
1521 branch--debug: default
1522 branches:
1522 branches:
1523 branches:
1523 branches:
1524 branches:
1524 branches:
1525 branches:
1525 branches:
1526 branches: foo
1526 branches: foo
1527 branches:
1527 branches:
1528 branches:
1528 branches:
1529 branches:
1529 branches:
1530 branches:
1530 branches:
1531 branches--verbose:
1531 branches--verbose:
1532 branches--verbose:
1532 branches--verbose:
1533 branches--verbose:
1533 branches--verbose:
1534 branches--verbose:
1534 branches--verbose:
1535 branches--verbose: foo
1535 branches--verbose: foo
1536 branches--verbose:
1536 branches--verbose:
1537 branches--verbose:
1537 branches--verbose:
1538 branches--verbose:
1538 branches--verbose:
1539 branches--verbose:
1539 branches--verbose:
1540 branches--debug:
1540 branches--debug:
1541 branches--debug:
1541 branches--debug:
1542 branches--debug:
1542 branches--debug:
1543 branches--debug:
1543 branches--debug:
1544 branches--debug: foo
1544 branches--debug: foo
1545 branches--debug:
1545 branches--debug:
1546 branches--debug:
1546 branches--debug:
1547 branches--debug:
1547 branches--debug:
1548 branches--debug:
1548 branches--debug:
1549 date: 1577872860.00
1549 date: 1577872860.00
1550 date: 1000000.00
1550 date: 1000000.00
1551 date: 1500001.00
1551 date: 1500001.00
1552 date: 1500000.00
1552 date: 1500000.00
1553 date: 1400000.00
1553 date: 1400000.00
1554 date: 1300000.00
1554 date: 1300000.00
1555 date: 1200000.00
1555 date: 1200000.00
1556 date: 1100000.00
1556 date: 1100000.00
1557 date: 1000000.00
1557 date: 1000000.00
1558 date--verbose: 1577872860.00
1558 date--verbose: 1577872860.00
1559 date--verbose: 1000000.00
1559 date--verbose: 1000000.00
1560 date--verbose: 1500001.00
1560 date--verbose: 1500001.00
1561 date--verbose: 1500000.00
1561 date--verbose: 1500000.00
1562 date--verbose: 1400000.00
1562 date--verbose: 1400000.00
1563 date--verbose: 1300000.00
1563 date--verbose: 1300000.00
1564 date--verbose: 1200000.00
1564 date--verbose: 1200000.00
1565 date--verbose: 1100000.00
1565 date--verbose: 1100000.00
1566 date--verbose: 1000000.00
1566 date--verbose: 1000000.00
1567 date--debug: 1577872860.00
1567 date--debug: 1577872860.00
1568 date--debug: 1000000.00
1568 date--debug: 1000000.00
1569 date--debug: 1500001.00
1569 date--debug: 1500001.00
1570 date--debug: 1500000.00
1570 date--debug: 1500000.00
1571 date--debug: 1400000.00
1571 date--debug: 1400000.00
1572 date--debug: 1300000.00
1572 date--debug: 1300000.00
1573 date--debug: 1200000.00
1573 date--debug: 1200000.00
1574 date--debug: 1100000.00
1574 date--debug: 1100000.00
1575 date--debug: 1000000.00
1575 date--debug: 1000000.00
1576 desc: third
1576 desc: third
1577 desc: second
1577 desc: second
1578 desc: merge
1578 desc: merge
1579 desc: new head
1579 desc: new head
1580 desc: new branch
1580 desc: new branch
1581 desc: no user, no domain
1581 desc: no user, no domain
1582 desc: no person
1582 desc: no person
1583 desc: other 1
1583 desc: other 1
1584 other 2
1584 other 2
1585
1585
1586 other 3
1586 other 3
1587 desc: line 1
1587 desc: line 1
1588 line 2
1588 line 2
1589 desc--verbose: third
1589 desc--verbose: third
1590 desc--verbose: second
1590 desc--verbose: second
1591 desc--verbose: merge
1591 desc--verbose: merge
1592 desc--verbose: new head
1592 desc--verbose: new head
1593 desc--verbose: new branch
1593 desc--verbose: new branch
1594 desc--verbose: no user, no domain
1594 desc--verbose: no user, no domain
1595 desc--verbose: no person
1595 desc--verbose: no person
1596 desc--verbose: other 1
1596 desc--verbose: other 1
1597 other 2
1597 other 2
1598
1598
1599 other 3
1599 other 3
1600 desc--verbose: line 1
1600 desc--verbose: line 1
1601 line 2
1601 line 2
1602 desc--debug: third
1602 desc--debug: third
1603 desc--debug: second
1603 desc--debug: second
1604 desc--debug: merge
1604 desc--debug: merge
1605 desc--debug: new head
1605 desc--debug: new head
1606 desc--debug: new branch
1606 desc--debug: new branch
1607 desc--debug: no user, no domain
1607 desc--debug: no user, no domain
1608 desc--debug: no person
1608 desc--debug: no person
1609 desc--debug: other 1
1609 desc--debug: other 1
1610 other 2
1610 other 2
1611
1611
1612 other 3
1612 other 3
1613 desc--debug: line 1
1613 desc--debug: line 1
1614 line 2
1614 line 2
1615 file_adds: fourth third
1615 file_adds: fourth third
1616 file_adds: second
1616 file_adds: second
1617 file_adds:
1617 file_adds:
1618 file_adds: d
1618 file_adds: d
1619 file_adds:
1619 file_adds:
1620 file_adds:
1620 file_adds:
1621 file_adds: c
1621 file_adds: c
1622 file_adds: b
1622 file_adds: b
1623 file_adds: a
1623 file_adds: a
1624 file_adds--verbose: fourth third
1624 file_adds--verbose: fourth third
1625 file_adds--verbose: second
1625 file_adds--verbose: second
1626 file_adds--verbose:
1626 file_adds--verbose:
1627 file_adds--verbose: d
1627 file_adds--verbose: d
1628 file_adds--verbose:
1628 file_adds--verbose:
1629 file_adds--verbose:
1629 file_adds--verbose:
1630 file_adds--verbose: c
1630 file_adds--verbose: c
1631 file_adds--verbose: b
1631 file_adds--verbose: b
1632 file_adds--verbose: a
1632 file_adds--verbose: a
1633 file_adds--debug: fourth third
1633 file_adds--debug: fourth third
1634 file_adds--debug: second
1634 file_adds--debug: second
1635 file_adds--debug:
1635 file_adds--debug:
1636 file_adds--debug: d
1636 file_adds--debug: d
1637 file_adds--debug:
1637 file_adds--debug:
1638 file_adds--debug:
1638 file_adds--debug:
1639 file_adds--debug: c
1639 file_adds--debug: c
1640 file_adds--debug: b
1640 file_adds--debug: b
1641 file_adds--debug: a
1641 file_adds--debug: a
1642 file_dels: second
1642 file_dels: second
1643 file_dels:
1643 file_dels:
1644 file_dels:
1644 file_dels:
1645 file_dels:
1645 file_dels:
1646 file_dels:
1646 file_dels:
1647 file_dels:
1647 file_dels:
1648 file_dels:
1648 file_dels:
1649 file_dels:
1649 file_dels:
1650 file_dels:
1650 file_dels:
1651 file_dels--verbose: second
1651 file_dels--verbose: second
1652 file_dels--verbose:
1652 file_dels--verbose:
1653 file_dels--verbose:
1653 file_dels--verbose:
1654 file_dels--verbose:
1654 file_dels--verbose:
1655 file_dels--verbose:
1655 file_dels--verbose:
1656 file_dels--verbose:
1656 file_dels--verbose:
1657 file_dels--verbose:
1657 file_dels--verbose:
1658 file_dels--verbose:
1658 file_dels--verbose:
1659 file_dels--verbose:
1659 file_dels--verbose:
1660 file_dels--debug: second
1660 file_dels--debug: second
1661 file_dels--debug:
1661 file_dels--debug:
1662 file_dels--debug:
1662 file_dels--debug:
1663 file_dels--debug:
1663 file_dels--debug:
1664 file_dels--debug:
1664 file_dels--debug:
1665 file_dels--debug:
1665 file_dels--debug:
1666 file_dels--debug:
1666 file_dels--debug:
1667 file_dels--debug:
1667 file_dels--debug:
1668 file_dels--debug:
1668 file_dels--debug:
1669 file_mods:
1669 file_mods:
1670 file_mods:
1670 file_mods:
1671 file_mods:
1671 file_mods:
1672 file_mods:
1672 file_mods:
1673 file_mods:
1673 file_mods:
1674 file_mods: c
1674 file_mods: c
1675 file_mods:
1675 file_mods:
1676 file_mods:
1676 file_mods:
1677 file_mods:
1677 file_mods:
1678 file_mods--verbose:
1678 file_mods--verbose:
1679 file_mods--verbose:
1679 file_mods--verbose:
1680 file_mods--verbose:
1680 file_mods--verbose:
1681 file_mods--verbose:
1681 file_mods--verbose:
1682 file_mods--verbose:
1682 file_mods--verbose:
1683 file_mods--verbose: c
1683 file_mods--verbose: c
1684 file_mods--verbose:
1684 file_mods--verbose:
1685 file_mods--verbose:
1685 file_mods--verbose:
1686 file_mods--verbose:
1686 file_mods--verbose:
1687 file_mods--debug:
1687 file_mods--debug:
1688 file_mods--debug:
1688 file_mods--debug:
1689 file_mods--debug:
1689 file_mods--debug:
1690 file_mods--debug:
1690 file_mods--debug:
1691 file_mods--debug:
1691 file_mods--debug:
1692 file_mods--debug: c
1692 file_mods--debug: c
1693 file_mods--debug:
1693 file_mods--debug:
1694 file_mods--debug:
1694 file_mods--debug:
1695 file_mods--debug:
1695 file_mods--debug:
1696 file_copies: fourth (second)
1696 file_copies: fourth (second)
1697 file_copies:
1697 file_copies:
1698 file_copies:
1698 file_copies:
1699 file_copies:
1699 file_copies:
1700 file_copies:
1700 file_copies:
1701 file_copies:
1701 file_copies:
1702 file_copies:
1702 file_copies:
1703 file_copies:
1703 file_copies:
1704 file_copies:
1704 file_copies:
1705 file_copies--verbose: fourth (second)
1705 file_copies--verbose: fourth (second)
1706 file_copies--verbose:
1706 file_copies--verbose:
1707 file_copies--verbose:
1707 file_copies--verbose:
1708 file_copies--verbose:
1708 file_copies--verbose:
1709 file_copies--verbose:
1709 file_copies--verbose:
1710 file_copies--verbose:
1710 file_copies--verbose:
1711 file_copies--verbose:
1711 file_copies--verbose:
1712 file_copies--verbose:
1712 file_copies--verbose:
1713 file_copies--verbose:
1713 file_copies--verbose:
1714 file_copies--debug: fourth (second)
1714 file_copies--debug: fourth (second)
1715 file_copies--debug:
1715 file_copies--debug:
1716 file_copies--debug:
1716 file_copies--debug:
1717 file_copies--debug:
1717 file_copies--debug:
1718 file_copies--debug:
1718 file_copies--debug:
1719 file_copies--debug:
1719 file_copies--debug:
1720 file_copies--debug:
1720 file_copies--debug:
1721 file_copies--debug:
1721 file_copies--debug:
1722 file_copies--debug:
1722 file_copies--debug:
1723 file_copies_switch:
1723 file_copies_switch:
1724 file_copies_switch:
1724 file_copies_switch:
1725 file_copies_switch:
1725 file_copies_switch:
1726 file_copies_switch:
1726 file_copies_switch:
1727 file_copies_switch:
1727 file_copies_switch:
1728 file_copies_switch:
1728 file_copies_switch:
1729 file_copies_switch:
1729 file_copies_switch:
1730 file_copies_switch:
1730 file_copies_switch:
1731 file_copies_switch:
1731 file_copies_switch:
1732 file_copies_switch--verbose:
1732 file_copies_switch--verbose:
1733 file_copies_switch--verbose:
1733 file_copies_switch--verbose:
1734 file_copies_switch--verbose:
1734 file_copies_switch--verbose:
1735 file_copies_switch--verbose:
1735 file_copies_switch--verbose:
1736 file_copies_switch--verbose:
1736 file_copies_switch--verbose:
1737 file_copies_switch--verbose:
1737 file_copies_switch--verbose:
1738 file_copies_switch--verbose:
1738 file_copies_switch--verbose:
1739 file_copies_switch--verbose:
1739 file_copies_switch--verbose:
1740 file_copies_switch--verbose:
1740 file_copies_switch--verbose:
1741 file_copies_switch--debug:
1741 file_copies_switch--debug:
1742 file_copies_switch--debug:
1742 file_copies_switch--debug:
1743 file_copies_switch--debug:
1743 file_copies_switch--debug:
1744 file_copies_switch--debug:
1744 file_copies_switch--debug:
1745 file_copies_switch--debug:
1745 file_copies_switch--debug:
1746 file_copies_switch--debug:
1746 file_copies_switch--debug:
1747 file_copies_switch--debug:
1747 file_copies_switch--debug:
1748 file_copies_switch--debug:
1748 file_copies_switch--debug:
1749 file_copies_switch--debug:
1749 file_copies_switch--debug:
1750 files: fourth second third
1750 files: fourth second third
1751 files: second
1751 files: second
1752 files:
1752 files:
1753 files: d
1753 files: d
1754 files:
1754 files:
1755 files: c
1755 files: c
1756 files: c
1756 files: c
1757 files: b
1757 files: b
1758 files: a
1758 files: a
1759 files--verbose: fourth second third
1759 files--verbose: fourth second third
1760 files--verbose: second
1760 files--verbose: second
1761 files--verbose:
1761 files--verbose:
1762 files--verbose: d
1762 files--verbose: d
1763 files--verbose:
1763 files--verbose:
1764 files--verbose: c
1764 files--verbose: c
1765 files--verbose: c
1765 files--verbose: c
1766 files--verbose: b
1766 files--verbose: b
1767 files--verbose: a
1767 files--verbose: a
1768 files--debug: fourth second third
1768 files--debug: fourth second third
1769 files--debug: second
1769 files--debug: second
1770 files--debug:
1770 files--debug:
1771 files--debug: d
1771 files--debug: d
1772 files--debug:
1772 files--debug:
1773 files--debug: c
1773 files--debug: c
1774 files--debug: c
1774 files--debug: c
1775 files--debug: b
1775 files--debug: b
1776 files--debug: a
1776 files--debug: a
1777 manifest: 6:94961b75a2da
1777 manifest: 6:94961b75a2da
1778 manifest: 5:f2dbc354b94e
1778 manifest: 5:f2dbc354b94e
1779 manifest: 4:4dc3def4f9b4
1779 manifest: 4:4dc3def4f9b4
1780 manifest: 4:4dc3def4f9b4
1780 manifest: 4:4dc3def4f9b4
1781 manifest: 3:cb5a1327723b
1781 manifest: 3:cb5a1327723b
1782 manifest: 3:cb5a1327723b
1782 manifest: 3:cb5a1327723b
1783 manifest: 2:6e0e82995c35
1783 manifest: 2:6e0e82995c35
1784 manifest: 1:4e8d705b1e53
1784 manifest: 1:4e8d705b1e53
1785 manifest: 0:a0c8bcbbb45c
1785 manifest: 0:a0c8bcbbb45c
1786 manifest--verbose: 6:94961b75a2da
1786 manifest--verbose: 6:94961b75a2da
1787 manifest--verbose: 5:f2dbc354b94e
1787 manifest--verbose: 5:f2dbc354b94e
1788 manifest--verbose: 4:4dc3def4f9b4
1788 manifest--verbose: 4:4dc3def4f9b4
1789 manifest--verbose: 4:4dc3def4f9b4
1789 manifest--verbose: 4:4dc3def4f9b4
1790 manifest--verbose: 3:cb5a1327723b
1790 manifest--verbose: 3:cb5a1327723b
1791 manifest--verbose: 3:cb5a1327723b
1791 manifest--verbose: 3:cb5a1327723b
1792 manifest--verbose: 2:6e0e82995c35
1792 manifest--verbose: 2:6e0e82995c35
1793 manifest--verbose: 1:4e8d705b1e53
1793 manifest--verbose: 1:4e8d705b1e53
1794 manifest--verbose: 0:a0c8bcbbb45c
1794 manifest--verbose: 0:a0c8bcbbb45c
1795 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1795 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1796 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1796 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1797 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1797 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1798 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1798 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1799 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1799 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1800 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1800 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1801 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1801 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1802 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1802 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1803 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1803 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1804 node: 95c24699272ef57d062b8bccc32c878bf841784a
1804 node: 95c24699272ef57d062b8bccc32c878bf841784a
1805 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1805 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1806 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1806 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1807 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1807 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1808 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1808 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1809 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1809 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1810 node: 97054abb4ab824450e9164180baf491ae0078465
1810 node: 97054abb4ab824450e9164180baf491ae0078465
1811 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1811 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1812 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1812 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1813 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1813 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1814 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1814 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1815 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1815 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1816 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1816 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1817 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1817 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1818 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1818 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1819 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1819 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1820 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1820 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1821 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1821 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1822 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1822 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1823 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1823 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1824 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1824 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1825 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1825 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1826 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1826 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1827 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1827 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1828 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1828 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1829 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1829 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1830 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1830 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1831 parents:
1831 parents:
1832 parents: -1:000000000000
1832 parents: -1:000000000000
1833 parents: 5:13207e5a10d9 4:bbe44766e73d
1833 parents: 5:13207e5a10d9 4:bbe44766e73d
1834 parents: 3:10e46f2dcbf4
1834 parents: 3:10e46f2dcbf4
1835 parents:
1835 parents:
1836 parents:
1836 parents:
1837 parents:
1837 parents:
1838 parents:
1838 parents:
1839 parents:
1839 parents:
1840 parents--verbose:
1840 parents--verbose:
1841 parents--verbose: -1:000000000000
1841 parents--verbose: -1:000000000000
1842 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1842 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1843 parents--verbose: 3:10e46f2dcbf4
1843 parents--verbose: 3:10e46f2dcbf4
1844 parents--verbose:
1844 parents--verbose:
1845 parents--verbose:
1845 parents--verbose:
1846 parents--verbose:
1846 parents--verbose:
1847 parents--verbose:
1847 parents--verbose:
1848 parents--verbose:
1848 parents--verbose:
1849 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1849 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1850 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1850 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1851 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1851 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1852 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1852 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1853 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1853 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1854 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1854 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1855 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1855 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1856 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1856 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1857 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1857 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1858 rev: 8
1858 rev: 8
1859 rev: 7
1859 rev: 7
1860 rev: 6
1860 rev: 6
1861 rev: 5
1861 rev: 5
1862 rev: 4
1862 rev: 4
1863 rev: 3
1863 rev: 3
1864 rev: 2
1864 rev: 2
1865 rev: 1
1865 rev: 1
1866 rev: 0
1866 rev: 0
1867 rev--verbose: 8
1867 rev--verbose: 8
1868 rev--verbose: 7
1868 rev--verbose: 7
1869 rev--verbose: 6
1869 rev--verbose: 6
1870 rev--verbose: 5
1870 rev--verbose: 5
1871 rev--verbose: 4
1871 rev--verbose: 4
1872 rev--verbose: 3
1872 rev--verbose: 3
1873 rev--verbose: 2
1873 rev--verbose: 2
1874 rev--verbose: 1
1874 rev--verbose: 1
1875 rev--verbose: 0
1875 rev--verbose: 0
1876 rev--debug: 8
1876 rev--debug: 8
1877 rev--debug: 7
1877 rev--debug: 7
1878 rev--debug: 6
1878 rev--debug: 6
1879 rev--debug: 5
1879 rev--debug: 5
1880 rev--debug: 4
1880 rev--debug: 4
1881 rev--debug: 3
1881 rev--debug: 3
1882 rev--debug: 2
1882 rev--debug: 2
1883 rev--debug: 1
1883 rev--debug: 1
1884 rev--debug: 0
1884 rev--debug: 0
1885 tags: tip
1885 tags: tip
1886 tags:
1886 tags:
1887 tags:
1887 tags:
1888 tags:
1888 tags:
1889 tags:
1889 tags:
1890 tags:
1890 tags:
1891 tags:
1891 tags:
1892 tags:
1892 tags:
1893 tags:
1893 tags:
1894 tags--verbose: tip
1894 tags--verbose: tip
1895 tags--verbose:
1895 tags--verbose:
1896 tags--verbose:
1896 tags--verbose:
1897 tags--verbose:
1897 tags--verbose:
1898 tags--verbose:
1898 tags--verbose:
1899 tags--verbose:
1899 tags--verbose:
1900 tags--verbose:
1900 tags--verbose:
1901 tags--verbose:
1901 tags--verbose:
1902 tags--verbose:
1902 tags--verbose:
1903 tags--debug: tip
1903 tags--debug: tip
1904 tags--debug:
1904 tags--debug:
1905 tags--debug:
1905 tags--debug:
1906 tags--debug:
1906 tags--debug:
1907 tags--debug:
1907 tags--debug:
1908 tags--debug:
1908 tags--debug:
1909 tags--debug:
1909 tags--debug:
1910 tags--debug:
1910 tags--debug:
1911 tags--debug:
1911 tags--debug:
1912 diffstat: 3: +2/-1
1912 diffstat: 3: +2/-1
1913 diffstat: 1: +1/-0
1913 diffstat: 1: +1/-0
1914 diffstat: 0: +0/-0
1914 diffstat: 0: +0/-0
1915 diffstat: 1: +1/-0
1915 diffstat: 1: +1/-0
1916 diffstat: 0: +0/-0
1916 diffstat: 0: +0/-0
1917 diffstat: 1: +1/-0
1917 diffstat: 1: +1/-0
1918 diffstat: 1: +4/-0
1918 diffstat: 1: +4/-0
1919 diffstat: 1: +2/-0
1919 diffstat: 1: +2/-0
1920 diffstat: 1: +1/-0
1920 diffstat: 1: +1/-0
1921 diffstat--verbose: 3: +2/-1
1921 diffstat--verbose: 3: +2/-1
1922 diffstat--verbose: 1: +1/-0
1922 diffstat--verbose: 1: +1/-0
1923 diffstat--verbose: 0: +0/-0
1923 diffstat--verbose: 0: +0/-0
1924 diffstat--verbose: 1: +1/-0
1924 diffstat--verbose: 1: +1/-0
1925 diffstat--verbose: 0: +0/-0
1925 diffstat--verbose: 0: +0/-0
1926 diffstat--verbose: 1: +1/-0
1926 diffstat--verbose: 1: +1/-0
1927 diffstat--verbose: 1: +4/-0
1927 diffstat--verbose: 1: +4/-0
1928 diffstat--verbose: 1: +2/-0
1928 diffstat--verbose: 1: +2/-0
1929 diffstat--verbose: 1: +1/-0
1929 diffstat--verbose: 1: +1/-0
1930 diffstat--debug: 3: +2/-1
1930 diffstat--debug: 3: +2/-1
1931 diffstat--debug: 1: +1/-0
1931 diffstat--debug: 1: +1/-0
1932 diffstat--debug: 0: +0/-0
1932 diffstat--debug: 0: +0/-0
1933 diffstat--debug: 1: +1/-0
1933 diffstat--debug: 1: +1/-0
1934 diffstat--debug: 0: +0/-0
1934 diffstat--debug: 0: +0/-0
1935 diffstat--debug: 1: +1/-0
1935 diffstat--debug: 1: +1/-0
1936 diffstat--debug: 1: +4/-0
1936 diffstat--debug: 1: +4/-0
1937 diffstat--debug: 1: +2/-0
1937 diffstat--debug: 1: +2/-0
1938 diffstat--debug: 1: +1/-0
1938 diffstat--debug: 1: +1/-0
1939 extras: branch=default
1939 extras: branch=default
1940 extras: branch=default
1940 extras: branch=default
1941 extras: branch=default
1941 extras: branch=default
1942 extras: branch=default
1942 extras: branch=default
1943 extras: branch=foo
1943 extras: branch=foo
1944 extras: branch=default
1944 extras: branch=default
1945 extras: branch=default
1945 extras: branch=default
1946 extras: branch=default
1946 extras: branch=default
1947 extras: branch=default
1947 extras: branch=default
1948 extras--verbose: branch=default
1948 extras--verbose: branch=default
1949 extras--verbose: branch=default
1949 extras--verbose: branch=default
1950 extras--verbose: branch=default
1950 extras--verbose: branch=default
1951 extras--verbose: branch=default
1951 extras--verbose: branch=default
1952 extras--verbose: branch=foo
1952 extras--verbose: branch=foo
1953 extras--verbose: branch=default
1953 extras--verbose: branch=default
1954 extras--verbose: branch=default
1954 extras--verbose: branch=default
1955 extras--verbose: branch=default
1955 extras--verbose: branch=default
1956 extras--verbose: branch=default
1956 extras--verbose: branch=default
1957 extras--debug: branch=default
1957 extras--debug: branch=default
1958 extras--debug: branch=default
1958 extras--debug: branch=default
1959 extras--debug: branch=default
1959 extras--debug: branch=default
1960 extras--debug: branch=default
1960 extras--debug: branch=default
1961 extras--debug: branch=foo
1961 extras--debug: branch=foo
1962 extras--debug: branch=default
1962 extras--debug: branch=default
1963 extras--debug: branch=default
1963 extras--debug: branch=default
1964 extras--debug: branch=default
1964 extras--debug: branch=default
1965 extras--debug: branch=default
1965 extras--debug: branch=default
1966 p1rev: 7
1966 p1rev: 7
1967 p1rev: -1
1967 p1rev: -1
1968 p1rev: 5
1968 p1rev: 5
1969 p1rev: 3
1969 p1rev: 3
1970 p1rev: 3
1970 p1rev: 3
1971 p1rev: 2
1971 p1rev: 2
1972 p1rev: 1
1972 p1rev: 1
1973 p1rev: 0
1973 p1rev: 0
1974 p1rev: -1
1974 p1rev: -1
1975 p1rev--verbose: 7
1975 p1rev--verbose: 7
1976 p1rev--verbose: -1
1976 p1rev--verbose: -1
1977 p1rev--verbose: 5
1977 p1rev--verbose: 5
1978 p1rev--verbose: 3
1978 p1rev--verbose: 3
1979 p1rev--verbose: 3
1979 p1rev--verbose: 3
1980 p1rev--verbose: 2
1980 p1rev--verbose: 2
1981 p1rev--verbose: 1
1981 p1rev--verbose: 1
1982 p1rev--verbose: 0
1982 p1rev--verbose: 0
1983 p1rev--verbose: -1
1983 p1rev--verbose: -1
1984 p1rev--debug: 7
1984 p1rev--debug: 7
1985 p1rev--debug: -1
1985 p1rev--debug: -1
1986 p1rev--debug: 5
1986 p1rev--debug: 5
1987 p1rev--debug: 3
1987 p1rev--debug: 3
1988 p1rev--debug: 3
1988 p1rev--debug: 3
1989 p1rev--debug: 2
1989 p1rev--debug: 2
1990 p1rev--debug: 1
1990 p1rev--debug: 1
1991 p1rev--debug: 0
1991 p1rev--debug: 0
1992 p1rev--debug: -1
1992 p1rev--debug: -1
1993 p2rev: -1
1993 p2rev: -1
1994 p2rev: -1
1994 p2rev: -1
1995 p2rev: 4
1995 p2rev: 4
1996 p2rev: -1
1996 p2rev: -1
1997 p2rev: -1
1997 p2rev: -1
1998 p2rev: -1
1998 p2rev: -1
1999 p2rev: -1
1999 p2rev: -1
2000 p2rev: -1
2000 p2rev: -1
2001 p2rev: -1
2001 p2rev: -1
2002 p2rev--verbose: -1
2002 p2rev--verbose: -1
2003 p2rev--verbose: -1
2003 p2rev--verbose: -1
2004 p2rev--verbose: 4
2004 p2rev--verbose: 4
2005 p2rev--verbose: -1
2005 p2rev--verbose: -1
2006 p2rev--verbose: -1
2006 p2rev--verbose: -1
2007 p2rev--verbose: -1
2007 p2rev--verbose: -1
2008 p2rev--verbose: -1
2008 p2rev--verbose: -1
2009 p2rev--verbose: -1
2009 p2rev--verbose: -1
2010 p2rev--verbose: -1
2010 p2rev--verbose: -1
2011 p2rev--debug: -1
2011 p2rev--debug: -1
2012 p2rev--debug: -1
2012 p2rev--debug: -1
2013 p2rev--debug: 4
2013 p2rev--debug: 4
2014 p2rev--debug: -1
2014 p2rev--debug: -1
2015 p2rev--debug: -1
2015 p2rev--debug: -1
2016 p2rev--debug: -1
2016 p2rev--debug: -1
2017 p2rev--debug: -1
2017 p2rev--debug: -1
2018 p2rev--debug: -1
2018 p2rev--debug: -1
2019 p2rev--debug: -1
2019 p2rev--debug: -1
2020 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2020 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2021 p1node: 0000000000000000000000000000000000000000
2021 p1node: 0000000000000000000000000000000000000000
2022 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
2022 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
2023 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2023 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2024 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2024 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2025 p1node: 97054abb4ab824450e9164180baf491ae0078465
2025 p1node: 97054abb4ab824450e9164180baf491ae0078465
2026 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2026 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2027 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
2027 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
2028 p1node: 0000000000000000000000000000000000000000
2028 p1node: 0000000000000000000000000000000000000000
2029 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2029 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2030 p1node--verbose: 0000000000000000000000000000000000000000
2030 p1node--verbose: 0000000000000000000000000000000000000000
2031 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
2031 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
2032 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2032 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2033 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2033 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2034 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
2034 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
2035 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2035 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2036 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
2036 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
2037 p1node--verbose: 0000000000000000000000000000000000000000
2037 p1node--verbose: 0000000000000000000000000000000000000000
2038 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2038 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2039 p1node--debug: 0000000000000000000000000000000000000000
2039 p1node--debug: 0000000000000000000000000000000000000000
2040 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
2040 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
2041 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2041 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2042 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2042 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2043 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
2043 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
2044 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2044 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2045 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
2045 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
2046 p1node--debug: 0000000000000000000000000000000000000000
2046 p1node--debug: 0000000000000000000000000000000000000000
2047 p2node: 0000000000000000000000000000000000000000
2047 p2node: 0000000000000000000000000000000000000000
2048 p2node: 0000000000000000000000000000000000000000
2048 p2node: 0000000000000000000000000000000000000000
2049 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2049 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2050 p2node: 0000000000000000000000000000000000000000
2050 p2node: 0000000000000000000000000000000000000000
2051 p2node: 0000000000000000000000000000000000000000
2051 p2node: 0000000000000000000000000000000000000000
2052 p2node: 0000000000000000000000000000000000000000
2052 p2node: 0000000000000000000000000000000000000000
2053 p2node: 0000000000000000000000000000000000000000
2053 p2node: 0000000000000000000000000000000000000000
2054 p2node: 0000000000000000000000000000000000000000
2054 p2node: 0000000000000000000000000000000000000000
2055 p2node: 0000000000000000000000000000000000000000
2055 p2node: 0000000000000000000000000000000000000000
2056 p2node--verbose: 0000000000000000000000000000000000000000
2056 p2node--verbose: 0000000000000000000000000000000000000000
2057 p2node--verbose: 0000000000000000000000000000000000000000
2057 p2node--verbose: 0000000000000000000000000000000000000000
2058 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2058 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2059 p2node--verbose: 0000000000000000000000000000000000000000
2059 p2node--verbose: 0000000000000000000000000000000000000000
2060 p2node--verbose: 0000000000000000000000000000000000000000
2060 p2node--verbose: 0000000000000000000000000000000000000000
2061 p2node--verbose: 0000000000000000000000000000000000000000
2061 p2node--verbose: 0000000000000000000000000000000000000000
2062 p2node--verbose: 0000000000000000000000000000000000000000
2062 p2node--verbose: 0000000000000000000000000000000000000000
2063 p2node--verbose: 0000000000000000000000000000000000000000
2063 p2node--verbose: 0000000000000000000000000000000000000000
2064 p2node--verbose: 0000000000000000000000000000000000000000
2064 p2node--verbose: 0000000000000000000000000000000000000000
2065 p2node--debug: 0000000000000000000000000000000000000000
2065 p2node--debug: 0000000000000000000000000000000000000000
2066 p2node--debug: 0000000000000000000000000000000000000000
2066 p2node--debug: 0000000000000000000000000000000000000000
2067 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2067 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2068 p2node--debug: 0000000000000000000000000000000000000000
2068 p2node--debug: 0000000000000000000000000000000000000000
2069 p2node--debug: 0000000000000000000000000000000000000000
2069 p2node--debug: 0000000000000000000000000000000000000000
2070 p2node--debug: 0000000000000000000000000000000000000000
2070 p2node--debug: 0000000000000000000000000000000000000000
2071 p2node--debug: 0000000000000000000000000000000000000000
2071 p2node--debug: 0000000000000000000000000000000000000000
2072 p2node--debug: 0000000000000000000000000000000000000000
2072 p2node--debug: 0000000000000000000000000000000000000000
2073 p2node--debug: 0000000000000000000000000000000000000000
2073 p2node--debug: 0000000000000000000000000000000000000000
2074
2074
2075 Filters work:
2075 Filters work:
2076
2076
2077 $ hg log --template '{author|domain}\n'
2077 $ hg log --template '{author|domain}\n'
2078
2078
2079 hostname
2079 hostname
2080
2080
2081
2081
2082
2082
2083
2083
2084 place
2084 place
2085 place
2085 place
2086 hostname
2086 hostname
2087
2087
2088 $ hg log --template '{author|person}\n'
2088 $ hg log --template '{author|person}\n'
2089 test
2089 test
2090 User Name
2090 User Name
2091 person
2091 person
2092 person
2092 person
2093 person
2093 person
2094 person
2094 person
2095 other
2095 other
2096 A. N. Other
2096 A. N. Other
2097 User Name
2097 User Name
2098
2098
2099 $ hg log --template '{author|user}\n'
2099 $ hg log --template '{author|user}\n'
2100 test
2100 test
2101 user
2101 user
2102 person
2102 person
2103 person
2103 person
2104 person
2104 person
2105 person
2105 person
2106 other
2106 other
2107 other
2107 other
2108 user
2108 user
2109
2109
2110 $ hg log --template '{date|date}\n'
2110 $ hg log --template '{date|date}\n'
2111 Wed Jan 01 10:01:00 2020 +0000
2111 Wed Jan 01 10:01:00 2020 +0000
2112 Mon Jan 12 13:46:40 1970 +0000
2112 Mon Jan 12 13:46:40 1970 +0000
2113 Sun Jan 18 08:40:01 1970 +0000
2113 Sun Jan 18 08:40:01 1970 +0000
2114 Sun Jan 18 08:40:00 1970 +0000
2114 Sun Jan 18 08:40:00 1970 +0000
2115 Sat Jan 17 04:53:20 1970 +0000
2115 Sat Jan 17 04:53:20 1970 +0000
2116 Fri Jan 16 01:06:40 1970 +0000
2116 Fri Jan 16 01:06:40 1970 +0000
2117 Wed Jan 14 21:20:00 1970 +0000
2117 Wed Jan 14 21:20:00 1970 +0000
2118 Tue Jan 13 17:33:20 1970 +0000
2118 Tue Jan 13 17:33:20 1970 +0000
2119 Mon Jan 12 13:46:40 1970 +0000
2119 Mon Jan 12 13:46:40 1970 +0000
2120
2120
2121 $ hg log --template '{date|isodate}\n'
2121 $ hg log --template '{date|isodate}\n'
2122 2020-01-01 10:01 +0000
2122 2020-01-01 10:01 +0000
2123 1970-01-12 13:46 +0000
2123 1970-01-12 13:46 +0000
2124 1970-01-18 08:40 +0000
2124 1970-01-18 08:40 +0000
2125 1970-01-18 08:40 +0000
2125 1970-01-18 08:40 +0000
2126 1970-01-17 04:53 +0000
2126 1970-01-17 04:53 +0000
2127 1970-01-16 01:06 +0000
2127 1970-01-16 01:06 +0000
2128 1970-01-14 21:20 +0000
2128 1970-01-14 21:20 +0000
2129 1970-01-13 17:33 +0000
2129 1970-01-13 17:33 +0000
2130 1970-01-12 13:46 +0000
2130 1970-01-12 13:46 +0000
2131
2131
2132 $ hg log --template '{date|isodatesec}\n'
2132 $ hg log --template '{date|isodatesec}\n'
2133 2020-01-01 10:01:00 +0000
2133 2020-01-01 10:01:00 +0000
2134 1970-01-12 13:46:40 +0000
2134 1970-01-12 13:46:40 +0000
2135 1970-01-18 08:40:01 +0000
2135 1970-01-18 08:40:01 +0000
2136 1970-01-18 08:40:00 +0000
2136 1970-01-18 08:40:00 +0000
2137 1970-01-17 04:53:20 +0000
2137 1970-01-17 04:53:20 +0000
2138 1970-01-16 01:06:40 +0000
2138 1970-01-16 01:06:40 +0000
2139 1970-01-14 21:20:00 +0000
2139 1970-01-14 21:20:00 +0000
2140 1970-01-13 17:33:20 +0000
2140 1970-01-13 17:33:20 +0000
2141 1970-01-12 13:46:40 +0000
2141 1970-01-12 13:46:40 +0000
2142
2142
2143 $ hg log --template '{date|rfc822date}\n'
2143 $ hg log --template '{date|rfc822date}\n'
2144 Wed, 01 Jan 2020 10:01:00 +0000
2144 Wed, 01 Jan 2020 10:01:00 +0000
2145 Mon, 12 Jan 1970 13:46:40 +0000
2145 Mon, 12 Jan 1970 13:46:40 +0000
2146 Sun, 18 Jan 1970 08:40:01 +0000
2146 Sun, 18 Jan 1970 08:40:01 +0000
2147 Sun, 18 Jan 1970 08:40:00 +0000
2147 Sun, 18 Jan 1970 08:40:00 +0000
2148 Sat, 17 Jan 1970 04:53:20 +0000
2148 Sat, 17 Jan 1970 04:53:20 +0000
2149 Fri, 16 Jan 1970 01:06:40 +0000
2149 Fri, 16 Jan 1970 01:06:40 +0000
2150 Wed, 14 Jan 1970 21:20:00 +0000
2150 Wed, 14 Jan 1970 21:20:00 +0000
2151 Tue, 13 Jan 1970 17:33:20 +0000
2151 Tue, 13 Jan 1970 17:33:20 +0000
2152 Mon, 12 Jan 1970 13:46:40 +0000
2152 Mon, 12 Jan 1970 13:46:40 +0000
2153
2153
2154 $ hg log --template '{desc|firstline}\n'
2154 $ hg log --template '{desc|firstline}\n'
2155 third
2155 third
2156 second
2156 second
2157 merge
2157 merge
2158 new head
2158 new head
2159 new branch
2159 new branch
2160 no user, no domain
2160 no user, no domain
2161 no person
2161 no person
2162 other 1
2162 other 1
2163 line 1
2163 line 1
2164
2164
2165 $ hg log --template '{node|short}\n'
2165 $ hg log --template '{node|short}\n'
2166 95c24699272e
2166 95c24699272e
2167 29114dbae42b
2167 29114dbae42b
2168 d41e714fe50d
2168 d41e714fe50d
2169 13207e5a10d9
2169 13207e5a10d9
2170 bbe44766e73d
2170 bbe44766e73d
2171 10e46f2dcbf4
2171 10e46f2dcbf4
2172 97054abb4ab8
2172 97054abb4ab8
2173 b608e9d1a3f0
2173 b608e9d1a3f0
2174 1e4e1b8f71e0
2174 1e4e1b8f71e0
2175
2175
2176 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
2176 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
2177 <changeset author="test"/>
2177 <changeset author="test"/>
2178 <changeset author="User Name &lt;user@hostname&gt;"/>
2178 <changeset author="User Name &lt;user@hostname&gt;"/>
2179 <changeset author="person"/>
2179 <changeset author="person"/>
2180 <changeset author="person"/>
2180 <changeset author="person"/>
2181 <changeset author="person"/>
2181 <changeset author="person"/>
2182 <changeset author="person"/>
2182 <changeset author="person"/>
2183 <changeset author="other@place"/>
2183 <changeset author="other@place"/>
2184 <changeset author="A. N. Other &lt;other@place&gt;"/>
2184 <changeset author="A. N. Other &lt;other@place&gt;"/>
2185 <changeset author="User Name &lt;user@hostname&gt;"/>
2185 <changeset author="User Name &lt;user@hostname&gt;"/>
2186
2186
2187 $ hg log --template '{rev}: {children}\n'
2187 $ hg log --template '{rev}: {children}\n'
2188 8:
2188 8:
2189 7: 8:95c24699272e
2189 7: 8:95c24699272e
2190 6:
2190 6:
2191 5: 6:d41e714fe50d
2191 5: 6:d41e714fe50d
2192 4: 6:d41e714fe50d
2192 4: 6:d41e714fe50d
2193 3: 4:bbe44766e73d 5:13207e5a10d9
2193 3: 4:bbe44766e73d 5:13207e5a10d9
2194 2: 3:10e46f2dcbf4
2194 2: 3:10e46f2dcbf4
2195 1: 2:97054abb4ab8
2195 1: 2:97054abb4ab8
2196 0: 1:b608e9d1a3f0
2196 0: 1:b608e9d1a3f0
2197
2197
2198 Formatnode filter works:
2198 Formatnode filter works:
2199
2199
2200 $ hg -q log -r 0 --template '{node|formatnode}\n'
2200 $ hg -q log -r 0 --template '{node|formatnode}\n'
2201 1e4e1b8f71e0
2201 1e4e1b8f71e0
2202
2202
2203 $ hg log -r 0 --template '{node|formatnode}\n'
2203 $ hg log -r 0 --template '{node|formatnode}\n'
2204 1e4e1b8f71e0
2204 1e4e1b8f71e0
2205
2205
2206 $ hg -v log -r 0 --template '{node|formatnode}\n'
2206 $ hg -v log -r 0 --template '{node|formatnode}\n'
2207 1e4e1b8f71e0
2207 1e4e1b8f71e0
2208
2208
2209 $ hg --debug log -r 0 --template '{node|formatnode}\n'
2209 $ hg --debug log -r 0 --template '{node|formatnode}\n'
2210 1e4e1b8f71e05681d422154f5421e385fec3454f
2210 1e4e1b8f71e05681d422154f5421e385fec3454f
2211
2211
2212 Age filter:
2212 Age filter:
2213
2213
2214 $ hg init unstable-hash
2214 $ hg init unstable-hash
2215 $ cd unstable-hash
2215 $ cd unstable-hash
2216 $ hg log --template '{date|age}\n' > /dev/null || exit 1
2216 $ hg log --template '{date|age}\n' > /dev/null || exit 1
2217
2217
2218 >>> from __future__ import absolute_import
2218 >>> from __future__ import absolute_import
2219 >>> import datetime
2219 >>> import datetime
2220 >>> fp = open('a', 'wb')
2220 >>> fp = open('a', 'wb')
2221 >>> n = datetime.datetime.now() + datetime.timedelta(366 * 7)
2221 >>> n = datetime.datetime.now() + datetime.timedelta(366 * 7)
2222 >>> fp.write(b'%d-%d-%d 00:00' % (n.year, n.month, n.day)) and None
2222 >>> fp.write(b'%d-%d-%d 00:00' % (n.year, n.month, n.day)) and None
2223 >>> fp.close()
2223 >>> fp.close()
2224 $ hg add a
2224 $ hg add a
2225 $ hg commit -m future -d "`cat a`"
2225 $ hg commit -m future -d "`cat a`"
2226
2226
2227 $ hg log -l1 --template '{date|age}\n'
2227 $ hg log -l1 --template '{date|age}\n'
2228 7 years from now
2228 7 years from now
2229
2229
2230 $ cd ..
2230 $ cd ..
2231 $ rm -rf unstable-hash
2231 $ rm -rf unstable-hash
2232
2232
2233 Filename filters:
2233 Filename filters:
2234
2234
2235 $ hg debugtemplate '{"foo/bar"|basename}|{"foo/"|basename}|{"foo"|basename}|\n'
2235 $ hg debugtemplate '{"foo/bar"|basename}|{"foo/"|basename}|{"foo"|basename}|\n'
2236 bar||foo|
2236 bar||foo|
2237 $ hg debugtemplate '{"foo/bar"|dirname}|{"foo/"|dirname}|{"foo"|dirname}|\n'
2237 $ hg debugtemplate '{"foo/bar"|dirname}|{"foo/"|dirname}|{"foo"|dirname}|\n'
2238 foo|foo||
2238 foo|foo||
2239 $ hg debugtemplate '{"foo/bar"|stripdir}|{"foo/"|stripdir}|{"foo"|stripdir}|\n'
2239 $ hg debugtemplate '{"foo/bar"|stripdir}|{"foo/"|stripdir}|{"foo"|stripdir}|\n'
2240 foo|foo|foo|
2240 foo|foo|foo|
2241
2241
2242 Add a dummy commit to make up for the instability of the above:
2242 Add a dummy commit to make up for the instability of the above:
2243
2243
2244 $ echo a > a
2244 $ echo a > a
2245 $ hg add a
2245 $ hg add a
2246 $ hg ci -m future
2246 $ hg ci -m future
2247
2247
2248 Count filter:
2248 Count filter:
2249
2249
2250 $ hg log -l1 --template '{node|count} {node|short|count}\n'
2250 $ hg log -l1 --template '{node|count} {node|short|count}\n'
2251 40 12
2251 40 12
2252
2252
2253 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
2253 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
2254 0 1 4
2254 0 1 4
2255
2255
2256 $ hg log -G --template '{rev}: children: {children|count}, \
2256 $ hg log -G --template '{rev}: children: {children|count}, \
2257 > tags: {tags|count}, file_adds: {file_adds|count}, \
2257 > tags: {tags|count}, file_adds: {file_adds|count}, \
2258 > ancestors: {revset("ancestors(%s)", rev)|count}'
2258 > ancestors: {revset("ancestors(%s)", rev)|count}'
2259 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
2259 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
2260 |
2260 |
2261 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
2261 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
2262 |
2262 |
2263 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
2263 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
2264
2264
2265 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
2265 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
2266 |\
2266 |\
2267 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
2267 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
2268 | |
2268 | |
2269 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
2269 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
2270 |/
2270 |/
2271 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
2271 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
2272 |
2272 |
2273 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
2273 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
2274 |
2274 |
2275 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
2275 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
2276 |
2276 |
2277 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
2277 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
2278
2278
2279
2279
2280 Upper/lower filters:
2280 Upper/lower filters:
2281
2281
2282 $ hg log -r0 --template '{branch|upper}\n'
2282 $ hg log -r0 --template '{branch|upper}\n'
2283 DEFAULT
2283 DEFAULT
2284 $ hg log -r0 --template '{author|lower}\n'
2284 $ hg log -r0 --template '{author|lower}\n'
2285 user name <user@hostname>
2285 user name <user@hostname>
2286 $ hg log -r0 --template '{date|upper}\n'
2286 $ hg log -r0 --template '{date|upper}\n'
2287 1000000.00
2287 1000000.00
2288
2288
2289 Add a commit that does all possible modifications at once
2289 Add a commit that does all possible modifications at once
2290
2290
2291 $ echo modify >> third
2291 $ echo modify >> third
2292 $ touch b
2292 $ touch b
2293 $ hg add b
2293 $ hg add b
2294 $ hg mv fourth fifth
2294 $ hg mv fourth fifth
2295 $ hg rm a
2295 $ hg rm a
2296 $ hg ci -m "Modify, add, remove, rename"
2296 $ hg ci -m "Modify, add, remove, rename"
2297
2297
2298 Check the status template
2298 Check the status template
2299
2299
2300 $ cat <<EOF >> $HGRCPATH
2300 $ cat <<EOF >> $HGRCPATH
2301 > [extensions]
2301 > [extensions]
2302 > color=
2302 > color=
2303 > EOF
2303 > EOF
2304
2304
2305 $ hg log -T status -r 10
2305 $ hg log -T status -r 10
2306 changeset: 10:0f9759ec227a
2306 changeset: 10:0f9759ec227a
2307 tag: tip
2307 tag: tip
2308 user: test
2308 user: test
2309 date: Thu Jan 01 00:00:00 1970 +0000
2309 date: Thu Jan 01 00:00:00 1970 +0000
2310 summary: Modify, add, remove, rename
2310 summary: Modify, add, remove, rename
2311 files:
2311 files:
2312 M third
2312 M third
2313 A b
2313 A b
2314 A fifth
2314 A fifth
2315 R a
2315 R a
2316 R fourth
2316 R fourth
2317
2317
2318 $ hg log -T status -C -r 10
2318 $ hg log -T status -C -r 10
2319 changeset: 10:0f9759ec227a
2319 changeset: 10:0f9759ec227a
2320 tag: tip
2320 tag: tip
2321 user: test
2321 user: test
2322 date: Thu Jan 01 00:00:00 1970 +0000
2322 date: Thu Jan 01 00:00:00 1970 +0000
2323 summary: Modify, add, remove, rename
2323 summary: Modify, add, remove, rename
2324 files:
2324 files:
2325 M third
2325 M third
2326 A b
2326 A b
2327 A fifth
2327 A fifth
2328 fourth
2328 fourth
2329 R a
2329 R a
2330 R fourth
2330 R fourth
2331
2331
2332 $ hg log -T status -C -r 10 -v
2332 $ hg log -T status -C -r 10 -v
2333 changeset: 10:0f9759ec227a
2333 changeset: 10:0f9759ec227a
2334 tag: tip
2334 tag: tip
2335 user: test
2335 user: test
2336 date: Thu Jan 01 00:00:00 1970 +0000
2336 date: Thu Jan 01 00:00:00 1970 +0000
2337 description:
2337 description:
2338 Modify, add, remove, rename
2338 Modify, add, remove, rename
2339
2339
2340 files:
2340 files:
2341 M third
2341 M third
2342 A b
2342 A b
2343 A fifth
2343 A fifth
2344 fourth
2344 fourth
2345 R a
2345 R a
2346 R fourth
2346 R fourth
2347
2347
2348 $ hg log -T status -C -r 10 --debug
2348 $ hg log -T status -C -r 10 --debug
2349 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
2349 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
2350 tag: tip
2350 tag: tip
2351 phase: secret
2351 phase: secret
2352 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
2352 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
2353 parent: -1:0000000000000000000000000000000000000000
2353 parent: -1:0000000000000000000000000000000000000000
2354 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
2354 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
2355 user: test
2355 user: test
2356 date: Thu Jan 01 00:00:00 1970 +0000
2356 date: Thu Jan 01 00:00:00 1970 +0000
2357 extra: branch=default
2357 extra: branch=default
2358 description:
2358 description:
2359 Modify, add, remove, rename
2359 Modify, add, remove, rename
2360
2360
2361 files:
2361 files:
2362 M third
2362 M third
2363 A b
2363 A b
2364 A fifth
2364 A fifth
2365 fourth
2365 fourth
2366 R a
2366 R a
2367 R fourth
2367 R fourth
2368
2368
2369 $ hg log -T status -C -r 10 --quiet
2369 $ hg log -T status -C -r 10 --quiet
2370 10:0f9759ec227a
2370 10:0f9759ec227a
2371 $ hg --color=debug log -T status -r 10
2371 $ hg --color=debug log -T status -r 10
2372 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2372 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2373 [log.tag|tag: tip]
2373 [log.tag|tag: tip]
2374 [log.user|user: test]
2374 [log.user|user: test]
2375 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2375 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2376 [log.summary|summary: Modify, add, remove, rename]
2376 [log.summary|summary: Modify, add, remove, rename]
2377 [ui.note log.files|files:]
2377 [ui.note log.files|files:]
2378 [status.modified|M third]
2378 [status.modified|M third]
2379 [status.added|A b]
2379 [status.added|A b]
2380 [status.added|A fifth]
2380 [status.added|A fifth]
2381 [status.removed|R a]
2381 [status.removed|R a]
2382 [status.removed|R fourth]
2382 [status.removed|R fourth]
2383
2383
2384 $ hg --color=debug log -T status -C -r 10
2384 $ hg --color=debug log -T status -C -r 10
2385 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2385 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2386 [log.tag|tag: tip]
2386 [log.tag|tag: tip]
2387 [log.user|user: test]
2387 [log.user|user: test]
2388 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2388 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2389 [log.summary|summary: Modify, add, remove, rename]
2389 [log.summary|summary: Modify, add, remove, rename]
2390 [ui.note log.files|files:]
2390 [ui.note log.files|files:]
2391 [status.modified|M third]
2391 [status.modified|M third]
2392 [status.added|A b]
2392 [status.added|A b]
2393 [status.added|A fifth]
2393 [status.added|A fifth]
2394 [status.copied| fourth]
2394 [status.copied| fourth]
2395 [status.removed|R a]
2395 [status.removed|R a]
2396 [status.removed|R fourth]
2396 [status.removed|R fourth]
2397
2397
2398 $ hg --color=debug log -T status -C -r 10 -v
2398 $ hg --color=debug log -T status -C -r 10 -v
2399 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2399 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2400 [log.tag|tag: tip]
2400 [log.tag|tag: tip]
2401 [log.user|user: test]
2401 [log.user|user: test]
2402 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2402 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2403 [ui.note log.description|description:]
2403 [ui.note log.description|description:]
2404 [ui.note log.description|Modify, add, remove, rename]
2404 [ui.note log.description|Modify, add, remove, rename]
2405
2405
2406 [ui.note log.files|files:]
2406 [ui.note log.files|files:]
2407 [status.modified|M third]
2407 [status.modified|M third]
2408 [status.added|A b]
2408 [status.added|A b]
2409 [status.added|A fifth]
2409 [status.added|A fifth]
2410 [status.copied| fourth]
2410 [status.copied| fourth]
2411 [status.removed|R a]
2411 [status.removed|R a]
2412 [status.removed|R fourth]
2412 [status.removed|R fourth]
2413
2413
2414 $ hg --color=debug log -T status -C -r 10 --debug
2414 $ hg --color=debug log -T status -C -r 10 --debug
2415 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
2415 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
2416 [log.tag|tag: tip]
2416 [log.tag|tag: tip]
2417 [log.phase|phase: secret]
2417 [log.phase|phase: secret]
2418 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
2418 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
2419 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2419 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2420 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
2420 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
2421 [log.user|user: test]
2421 [log.user|user: test]
2422 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2422 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2423 [ui.debug log.extra|extra: branch=default]
2423 [ui.debug log.extra|extra: branch=default]
2424 [ui.note log.description|description:]
2424 [ui.note log.description|description:]
2425 [ui.note log.description|Modify, add, remove, rename]
2425 [ui.note log.description|Modify, add, remove, rename]
2426
2426
2427 [ui.note log.files|files:]
2427 [ui.note log.files|files:]
2428 [status.modified|M third]
2428 [status.modified|M third]
2429 [status.added|A b]
2429 [status.added|A b]
2430 [status.added|A fifth]
2430 [status.added|A fifth]
2431 [status.copied| fourth]
2431 [status.copied| fourth]
2432 [status.removed|R a]
2432 [status.removed|R a]
2433 [status.removed|R fourth]
2433 [status.removed|R fourth]
2434
2434
2435 $ hg --color=debug log -T status -C -r 10 --quiet
2435 $ hg --color=debug log -T status -C -r 10 --quiet
2436 [log.node|10:0f9759ec227a]
2436 [log.node|10:0f9759ec227a]
2437
2437
2438 Check the bisect template
2438 Check the bisect template
2439
2439
2440 $ hg bisect -g 1
2440 $ hg bisect -g 1
2441 $ hg bisect -b 3 --noupdate
2441 $ hg bisect -b 3 --noupdate
2442 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
2442 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
2443 $ hg log -T bisect -r 0:4
2443 $ hg log -T bisect -r 0:4
2444 changeset: 0:1e4e1b8f71e0
2444 changeset: 0:1e4e1b8f71e0
2445 bisect: good (implicit)
2445 bisect: good (implicit)
2446 user: User Name <user@hostname>
2446 user: User Name <user@hostname>
2447 date: Mon Jan 12 13:46:40 1970 +0000
2447 date: Mon Jan 12 13:46:40 1970 +0000
2448 summary: line 1
2448 summary: line 1
2449
2449
2450 changeset: 1:b608e9d1a3f0
2450 changeset: 1:b608e9d1a3f0
2451 bisect: good
2451 bisect: good
2452 user: A. N. Other <other@place>
2452 user: A. N. Other <other@place>
2453 date: Tue Jan 13 17:33:20 1970 +0000
2453 date: Tue Jan 13 17:33:20 1970 +0000
2454 summary: other 1
2454 summary: other 1
2455
2455
2456 changeset: 2:97054abb4ab8
2456 changeset: 2:97054abb4ab8
2457 bisect: untested
2457 bisect: untested
2458 user: other@place
2458 user: other@place
2459 date: Wed Jan 14 21:20:00 1970 +0000
2459 date: Wed Jan 14 21:20:00 1970 +0000
2460 summary: no person
2460 summary: no person
2461
2461
2462 changeset: 3:10e46f2dcbf4
2462 changeset: 3:10e46f2dcbf4
2463 bisect: bad
2463 bisect: bad
2464 user: person
2464 user: person
2465 date: Fri Jan 16 01:06:40 1970 +0000
2465 date: Fri Jan 16 01:06:40 1970 +0000
2466 summary: no user, no domain
2466 summary: no user, no domain
2467
2467
2468 changeset: 4:bbe44766e73d
2468 changeset: 4:bbe44766e73d
2469 bisect: bad (implicit)
2469 bisect: bad (implicit)
2470 branch: foo
2470 branch: foo
2471 user: person
2471 user: person
2472 date: Sat Jan 17 04:53:20 1970 +0000
2472 date: Sat Jan 17 04:53:20 1970 +0000
2473 summary: new branch
2473 summary: new branch
2474
2474
2475 $ hg log --debug -T bisect -r 0:4
2475 $ hg log --debug -T bisect -r 0:4
2476 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2476 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2477 bisect: good (implicit)
2477 bisect: good (implicit)
2478 phase: public
2478 phase: public
2479 parent: -1:0000000000000000000000000000000000000000
2479 parent: -1:0000000000000000000000000000000000000000
2480 parent: -1:0000000000000000000000000000000000000000
2480 parent: -1:0000000000000000000000000000000000000000
2481 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
2481 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
2482 user: User Name <user@hostname>
2482 user: User Name <user@hostname>
2483 date: Mon Jan 12 13:46:40 1970 +0000
2483 date: Mon Jan 12 13:46:40 1970 +0000
2484 files+: a
2484 files+: a
2485 extra: branch=default
2485 extra: branch=default
2486 description:
2486 description:
2487 line 1
2487 line 1
2488 line 2
2488 line 2
2489
2489
2490
2490
2491 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2491 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2492 bisect: good
2492 bisect: good
2493 phase: public
2493 phase: public
2494 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2494 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2495 parent: -1:0000000000000000000000000000000000000000
2495 parent: -1:0000000000000000000000000000000000000000
2496 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
2496 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
2497 user: A. N. Other <other@place>
2497 user: A. N. Other <other@place>
2498 date: Tue Jan 13 17:33:20 1970 +0000
2498 date: Tue Jan 13 17:33:20 1970 +0000
2499 files+: b
2499 files+: b
2500 extra: branch=default
2500 extra: branch=default
2501 description:
2501 description:
2502 other 1
2502 other 1
2503 other 2
2503 other 2
2504
2504
2505 other 3
2505 other 3
2506
2506
2507
2507
2508 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
2508 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
2509 bisect: untested
2509 bisect: untested
2510 phase: public
2510 phase: public
2511 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2511 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2512 parent: -1:0000000000000000000000000000000000000000
2512 parent: -1:0000000000000000000000000000000000000000
2513 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
2513 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
2514 user: other@place
2514 user: other@place
2515 date: Wed Jan 14 21:20:00 1970 +0000
2515 date: Wed Jan 14 21:20:00 1970 +0000
2516 files+: c
2516 files+: c
2517 extra: branch=default
2517 extra: branch=default
2518 description:
2518 description:
2519 no person
2519 no person
2520
2520
2521
2521
2522 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2522 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2523 bisect: bad
2523 bisect: bad
2524 phase: public
2524 phase: public
2525 parent: 2:97054abb4ab824450e9164180baf491ae0078465
2525 parent: 2:97054abb4ab824450e9164180baf491ae0078465
2526 parent: -1:0000000000000000000000000000000000000000
2526 parent: -1:0000000000000000000000000000000000000000
2527 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2527 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2528 user: person
2528 user: person
2529 date: Fri Jan 16 01:06:40 1970 +0000
2529 date: Fri Jan 16 01:06:40 1970 +0000
2530 files: c
2530 files: c
2531 extra: branch=default
2531 extra: branch=default
2532 description:
2532 description:
2533 no user, no domain
2533 no user, no domain
2534
2534
2535
2535
2536 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
2536 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
2537 bisect: bad (implicit)
2537 bisect: bad (implicit)
2538 branch: foo
2538 branch: foo
2539 phase: draft
2539 phase: draft
2540 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2540 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2541 parent: -1:0000000000000000000000000000000000000000
2541 parent: -1:0000000000000000000000000000000000000000
2542 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2542 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2543 user: person
2543 user: person
2544 date: Sat Jan 17 04:53:20 1970 +0000
2544 date: Sat Jan 17 04:53:20 1970 +0000
2545 extra: branch=foo
2545 extra: branch=foo
2546 description:
2546 description:
2547 new branch
2547 new branch
2548
2548
2549
2549
2550 $ hg log -v -T bisect -r 0:4
2550 $ hg log -v -T bisect -r 0:4
2551 changeset: 0:1e4e1b8f71e0
2551 changeset: 0:1e4e1b8f71e0
2552 bisect: good (implicit)
2552 bisect: good (implicit)
2553 user: User Name <user@hostname>
2553 user: User Name <user@hostname>
2554 date: Mon Jan 12 13:46:40 1970 +0000
2554 date: Mon Jan 12 13:46:40 1970 +0000
2555 files: a
2555 files: a
2556 description:
2556 description:
2557 line 1
2557 line 1
2558 line 2
2558 line 2
2559
2559
2560
2560
2561 changeset: 1:b608e9d1a3f0
2561 changeset: 1:b608e9d1a3f0
2562 bisect: good
2562 bisect: good
2563 user: A. N. Other <other@place>
2563 user: A. N. Other <other@place>
2564 date: Tue Jan 13 17:33:20 1970 +0000
2564 date: Tue Jan 13 17:33:20 1970 +0000
2565 files: b
2565 files: b
2566 description:
2566 description:
2567 other 1
2567 other 1
2568 other 2
2568 other 2
2569
2569
2570 other 3
2570 other 3
2571
2571
2572
2572
2573 changeset: 2:97054abb4ab8
2573 changeset: 2:97054abb4ab8
2574 bisect: untested
2574 bisect: untested
2575 user: other@place
2575 user: other@place
2576 date: Wed Jan 14 21:20:00 1970 +0000
2576 date: Wed Jan 14 21:20:00 1970 +0000
2577 files: c
2577 files: c
2578 description:
2578 description:
2579 no person
2579 no person
2580
2580
2581
2581
2582 changeset: 3:10e46f2dcbf4
2582 changeset: 3:10e46f2dcbf4
2583 bisect: bad
2583 bisect: bad
2584 user: person
2584 user: person
2585 date: Fri Jan 16 01:06:40 1970 +0000
2585 date: Fri Jan 16 01:06:40 1970 +0000
2586 files: c
2586 files: c
2587 description:
2587 description:
2588 no user, no domain
2588 no user, no domain
2589
2589
2590
2590
2591 changeset: 4:bbe44766e73d
2591 changeset: 4:bbe44766e73d
2592 bisect: bad (implicit)
2592 bisect: bad (implicit)
2593 branch: foo
2593 branch: foo
2594 user: person
2594 user: person
2595 date: Sat Jan 17 04:53:20 1970 +0000
2595 date: Sat Jan 17 04:53:20 1970 +0000
2596 description:
2596 description:
2597 new branch
2597 new branch
2598
2598
2599
2599
2600 $ hg --color=debug log -T bisect -r 0:4
2600 $ hg --color=debug log -T bisect -r 0:4
2601 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2601 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2602 [log.bisect bisect.good|bisect: good (implicit)]
2602 [log.bisect bisect.good|bisect: good (implicit)]
2603 [log.user|user: User Name <user@hostname>]
2603 [log.user|user: User Name <user@hostname>]
2604 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2604 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2605 [log.summary|summary: line 1]
2605 [log.summary|summary: line 1]
2606
2606
2607 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2607 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2608 [log.bisect bisect.good|bisect: good]
2608 [log.bisect bisect.good|bisect: good]
2609 [log.user|user: A. N. Other <other@place>]
2609 [log.user|user: A. N. Other <other@place>]
2610 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2610 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2611 [log.summary|summary: other 1]
2611 [log.summary|summary: other 1]
2612
2612
2613 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2613 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2614 [log.bisect bisect.untested|bisect: untested]
2614 [log.bisect bisect.untested|bisect: untested]
2615 [log.user|user: other@place]
2615 [log.user|user: other@place]
2616 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2616 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2617 [log.summary|summary: no person]
2617 [log.summary|summary: no person]
2618
2618
2619 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2619 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2620 [log.bisect bisect.bad|bisect: bad]
2620 [log.bisect bisect.bad|bisect: bad]
2621 [log.user|user: person]
2621 [log.user|user: person]
2622 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2622 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2623 [log.summary|summary: no user, no domain]
2623 [log.summary|summary: no user, no domain]
2624
2624
2625 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2625 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2626 [log.bisect bisect.bad|bisect: bad (implicit)]
2626 [log.bisect bisect.bad|bisect: bad (implicit)]
2627 [log.branch|branch: foo]
2627 [log.branch|branch: foo]
2628 [log.user|user: person]
2628 [log.user|user: person]
2629 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2629 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2630 [log.summary|summary: new branch]
2630 [log.summary|summary: new branch]
2631
2631
2632 $ hg --color=debug log --debug -T bisect -r 0:4
2632 $ hg --color=debug log --debug -T bisect -r 0:4
2633 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2633 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2634 [log.bisect bisect.good|bisect: good (implicit)]
2634 [log.bisect bisect.good|bisect: good (implicit)]
2635 [log.phase|phase: public]
2635 [log.phase|phase: public]
2636 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2636 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2637 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2637 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2638 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
2638 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
2639 [log.user|user: User Name <user@hostname>]
2639 [log.user|user: User Name <user@hostname>]
2640 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2640 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2641 [ui.debug log.files|files+: a]
2641 [ui.debug log.files|files+: a]
2642 [ui.debug log.extra|extra: branch=default]
2642 [ui.debug log.extra|extra: branch=default]
2643 [ui.note log.description|description:]
2643 [ui.note log.description|description:]
2644 [ui.note log.description|line 1
2644 [ui.note log.description|line 1
2645 line 2]
2645 line 2]
2646
2646
2647
2647
2648 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2648 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2649 [log.bisect bisect.good|bisect: good]
2649 [log.bisect bisect.good|bisect: good]
2650 [log.phase|phase: public]
2650 [log.phase|phase: public]
2651 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2651 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2652 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2652 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2653 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
2653 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
2654 [log.user|user: A. N. Other <other@place>]
2654 [log.user|user: A. N. Other <other@place>]
2655 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2655 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2656 [ui.debug log.files|files+: b]
2656 [ui.debug log.files|files+: b]
2657 [ui.debug log.extra|extra: branch=default]
2657 [ui.debug log.extra|extra: branch=default]
2658 [ui.note log.description|description:]
2658 [ui.note log.description|description:]
2659 [ui.note log.description|other 1
2659 [ui.note log.description|other 1
2660 other 2
2660 other 2
2661
2661
2662 other 3]
2662 other 3]
2663
2663
2664
2664
2665 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
2665 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
2666 [log.bisect bisect.untested|bisect: untested]
2666 [log.bisect bisect.untested|bisect: untested]
2667 [log.phase|phase: public]
2667 [log.phase|phase: public]
2668 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2668 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2669 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2669 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2670 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
2670 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
2671 [log.user|user: other@place]
2671 [log.user|user: other@place]
2672 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2672 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2673 [ui.debug log.files|files+: c]
2673 [ui.debug log.files|files+: c]
2674 [ui.debug log.extra|extra: branch=default]
2674 [ui.debug log.extra|extra: branch=default]
2675 [ui.note log.description|description:]
2675 [ui.note log.description|description:]
2676 [ui.note log.description|no person]
2676 [ui.note log.description|no person]
2677
2677
2678
2678
2679 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2679 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2680 [log.bisect bisect.bad|bisect: bad]
2680 [log.bisect bisect.bad|bisect: bad]
2681 [log.phase|phase: public]
2681 [log.phase|phase: public]
2682 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
2682 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
2683 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2683 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2684 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2684 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2685 [log.user|user: person]
2685 [log.user|user: person]
2686 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2686 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2687 [ui.debug log.files|files: c]
2687 [ui.debug log.files|files: c]
2688 [ui.debug log.extra|extra: branch=default]
2688 [ui.debug log.extra|extra: branch=default]
2689 [ui.note log.description|description:]
2689 [ui.note log.description|description:]
2690 [ui.note log.description|no user, no domain]
2690 [ui.note log.description|no user, no domain]
2691
2691
2692
2692
2693 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
2693 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
2694 [log.bisect bisect.bad|bisect: bad (implicit)]
2694 [log.bisect bisect.bad|bisect: bad (implicit)]
2695 [log.branch|branch: foo]
2695 [log.branch|branch: foo]
2696 [log.phase|phase: draft]
2696 [log.phase|phase: draft]
2697 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2697 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2698 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2698 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2699 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2699 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2700 [log.user|user: person]
2700 [log.user|user: person]
2701 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2701 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2702 [ui.debug log.extra|extra: branch=foo]
2702 [ui.debug log.extra|extra: branch=foo]
2703 [ui.note log.description|description:]
2703 [ui.note log.description|description:]
2704 [ui.note log.description|new branch]
2704 [ui.note log.description|new branch]
2705
2705
2706
2706
2707 $ hg --color=debug log -v -T bisect -r 0:4
2707 $ hg --color=debug log -v -T bisect -r 0:4
2708 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2708 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2709 [log.bisect bisect.good|bisect: good (implicit)]
2709 [log.bisect bisect.good|bisect: good (implicit)]
2710 [log.user|user: User Name <user@hostname>]
2710 [log.user|user: User Name <user@hostname>]
2711 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2711 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2712 [ui.note log.files|files: a]
2712 [ui.note log.files|files: a]
2713 [ui.note log.description|description:]
2713 [ui.note log.description|description:]
2714 [ui.note log.description|line 1
2714 [ui.note log.description|line 1
2715 line 2]
2715 line 2]
2716
2716
2717
2717
2718 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2718 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2719 [log.bisect bisect.good|bisect: good]
2719 [log.bisect bisect.good|bisect: good]
2720 [log.user|user: A. N. Other <other@place>]
2720 [log.user|user: A. N. Other <other@place>]
2721 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2721 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2722 [ui.note log.files|files: b]
2722 [ui.note log.files|files: b]
2723 [ui.note log.description|description:]
2723 [ui.note log.description|description:]
2724 [ui.note log.description|other 1
2724 [ui.note log.description|other 1
2725 other 2
2725 other 2
2726
2726
2727 other 3]
2727 other 3]
2728
2728
2729
2729
2730 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2730 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2731 [log.bisect bisect.untested|bisect: untested]
2731 [log.bisect bisect.untested|bisect: untested]
2732 [log.user|user: other@place]
2732 [log.user|user: other@place]
2733 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2733 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2734 [ui.note log.files|files: c]
2734 [ui.note log.files|files: c]
2735 [ui.note log.description|description:]
2735 [ui.note log.description|description:]
2736 [ui.note log.description|no person]
2736 [ui.note log.description|no person]
2737
2737
2738
2738
2739 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2739 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2740 [log.bisect bisect.bad|bisect: bad]
2740 [log.bisect bisect.bad|bisect: bad]
2741 [log.user|user: person]
2741 [log.user|user: person]
2742 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2742 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2743 [ui.note log.files|files: c]
2743 [ui.note log.files|files: c]
2744 [ui.note log.description|description:]
2744 [ui.note log.description|description:]
2745 [ui.note log.description|no user, no domain]
2745 [ui.note log.description|no user, no domain]
2746
2746
2747
2747
2748 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2748 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2749 [log.bisect bisect.bad|bisect: bad (implicit)]
2749 [log.bisect bisect.bad|bisect: bad (implicit)]
2750 [log.branch|branch: foo]
2750 [log.branch|branch: foo]
2751 [log.user|user: person]
2751 [log.user|user: person]
2752 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2752 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2753 [ui.note log.description|description:]
2753 [ui.note log.description|description:]
2754 [ui.note log.description|new branch]
2754 [ui.note log.description|new branch]
2755
2755
2756
2756
2757 $ hg bisect --reset
2757 $ hg bisect --reset
2758
2758
2759 Error on syntax:
2759 Error on syntax:
2760
2760
2761 $ echo 'x = "f' >> t
2761 $ echo 'x = "f' >> t
2762 $ hg log
2762 $ hg log
2763 hg: parse error at t:3: unmatched quotes
2763 hg: parse error at t:3: unmatched quotes
2764 [255]
2764 [255]
2765
2765
2766 $ hg log -T '{date'
2766 $ hg log -T '{date'
2767 hg: parse error at 1: unterminated template expansion
2767 hg: parse error at 1: unterminated template expansion
2768 ({date
2768 ({date
2769 ^ here)
2769 ^ here)
2770 [255]
2770 [255]
2771 $ hg log -T '{date(}'
2771 $ hg log -T '{date(}'
2772 hg: parse error at 6: not a prefix: end
2772 hg: parse error at 6: not a prefix: end
2773 ({date(}
2773 ({date(}
2774 ^ here)
2774 ^ here)
2775 [255]
2775 [255]
2776 $ hg log -T '{date)}'
2776 $ hg log -T '{date)}'
2777 hg: parse error at 5: invalid token
2777 hg: parse error at 5: invalid token
2778 ({date)}
2778 ({date)}
2779 ^ here)
2779 ^ here)
2780 [255]
2780 [255]
2781 $ hg log -T '{date date}'
2781 $ hg log -T '{date date}'
2782 hg: parse error at 6: invalid token
2782 hg: parse error at 6: invalid token
2783 ({date date}
2783 ({date date}
2784 ^ here)
2784 ^ here)
2785 [255]
2785 [255]
2786
2786
2787 $ hg log -T '{}'
2787 $ hg log -T '{}'
2788 hg: parse error at 1: not a prefix: end
2788 hg: parse error at 1: not a prefix: end
2789 ({}
2789 ({}
2790 ^ here)
2790 ^ here)
2791 [255]
2791 [255]
2792 $ hg debugtemplate -v '{()}'
2792 $ hg debugtemplate -v '{()}'
2793 (template
2793 (template
2794 (group
2794 (group
2795 None))
2795 None))
2796 hg: parse error: missing argument
2796 hg: parse error: missing argument
2797 [255]
2797 [255]
2798
2798
2799 Behind the scenes, this would throw TypeError without intype=bytes
2799 Behind the scenes, this would throw TypeError without intype=bytes
2800
2800
2801 $ hg log -l 3 --template '{date|obfuscate}\n'
2801 $ hg log -l 3 --template '{date|obfuscate}\n'
2802 &#48;&#46;&#48;&#48;
2802 &#48;&#46;&#48;&#48;
2803 &#48;&#46;&#48;&#48;
2803 &#48;&#46;&#48;&#48;
2804 &#49;&#53;&#55;&#55;&#56;&#55;&#50;&#56;&#54;&#48;&#46;&#48;&#48;
2804 &#49;&#53;&#55;&#55;&#56;&#55;&#50;&#56;&#54;&#48;&#46;&#48;&#48;
2805
2805
2806 Behind the scenes, this will throw a ValueError
2806 Behind the scenes, this will throw a ValueError
2807
2807
2808 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
2808 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
2809 abort: template filter 'shortdate' is not compatible with keyword 'desc'
2809 hg: parse error: invalid date: 'Modify, add, remove, rename'
2810 (template filter 'shortdate' is not compatible with keyword 'desc')
2810 [255]
2811 [255]
2811
2812
2812 Behind the scenes, this would throw AttributeError without intype=bytes
2813 Behind the scenes, this would throw AttributeError without intype=bytes
2813
2814
2814 $ hg log -l 3 --template 'line: {date|escape}\n'
2815 $ hg log -l 3 --template 'line: {date|escape}\n'
2815 line: 0.00
2816 line: 0.00
2816 line: 0.00
2817 line: 0.00
2817 line: 1577872860.00
2818 line: 1577872860.00
2818
2819
2819 $ hg log -l 3 --template 'line: {extras|localdate}\n'
2820 $ hg log -l 3 --template 'line: {extras|localdate}\n'
2820 hg: parse error: localdate expects a date information
2821 hg: parse error: localdate expects a date information
2821 [255]
2822 [255]
2822
2823
2823 Behind the scenes, this will throw ValueError
2824 Behind the scenes, this will throw ValueError
2824
2825
2825 $ hg tip --template '{author|email|date}\n'
2826 $ hg tip --template '{author|email|date}\n'
2826 hg: parse error: date expects a date information
2827 hg: parse error: date expects a date information
2827 [255]
2828 [255]
2828
2829
2829 $ hg tip -T '{author|email|shortdate}\n'
2830 $ hg tip -T '{author|email|shortdate}\n'
2830 abort: template filter 'shortdate' is not compatible with keyword 'author'
2831 hg: parse error: invalid date: 'test'
2832 (template filter 'shortdate' is not compatible with keyword 'author')
2831 [255]
2833 [255]
2832
2834
2833 $ hg tip -T '{get(extras, "branch")|shortdate}\n'
2835 $ hg tip -T '{get(extras, "branch")|shortdate}\n'
2834 abort: incompatible use of template filter 'shortdate'
2836 hg: parse error: invalid date: 'default'
2837 (incompatible use of template filter 'shortdate')
2835 [255]
2838 [255]
2836
2839
2837 Error in nested template:
2840 Error in nested template:
2838
2841
2839 $ hg log -T '{"date'
2842 $ hg log -T '{"date'
2840 hg: parse error at 2: unterminated string
2843 hg: parse error at 2: unterminated string
2841 ({"date
2844 ({"date
2842 ^ here)
2845 ^ here)
2843 [255]
2846 [255]
2844
2847
2845 $ hg log -T '{"foo{date|?}"}'
2848 $ hg log -T '{"foo{date|?}"}'
2846 hg: parse error at 11: syntax error
2849 hg: parse error at 11: syntax error
2847 ({"foo{date|?}"}
2850 ({"foo{date|?}"}
2848 ^ here)
2851 ^ here)
2849 [255]
2852 [255]
2850
2853
2851 Thrown an error if a template function doesn't exist
2854 Thrown an error if a template function doesn't exist
2852
2855
2853 $ hg tip --template '{foo()}\n'
2856 $ hg tip --template '{foo()}\n'
2854 hg: parse error: unknown function 'foo'
2857 hg: parse error: unknown function 'foo'
2855 [255]
2858 [255]
2856
2859
2857 Pass generator object created by template function to filter
2860 Pass generator object created by template function to filter
2858
2861
2859 $ hg log -l 1 --template '{if(author, author)|user}\n'
2862 $ hg log -l 1 --template '{if(author, author)|user}\n'
2860 test
2863 test
2861
2864
2862 Test index keyword:
2865 Test index keyword:
2863
2866
2864 $ hg log -l 2 -T '{index + 10}{files % " {index}:{file}"}\n'
2867 $ hg log -l 2 -T '{index + 10}{files % " {index}:{file}"}\n'
2865 10 0:a 1:b 2:fifth 3:fourth 4:third
2868 10 0:a 1:b 2:fifth 3:fourth 4:third
2866 11 0:a
2869 11 0:a
2867
2870
2868 $ hg branches -T '{index} {branch}\n'
2871 $ hg branches -T '{index} {branch}\n'
2869 0 default
2872 0 default
2870 1 foo
2873 1 foo
2871
2874
2872 Test diff function:
2875 Test diff function:
2873
2876
2874 $ hg diff -c 8
2877 $ hg diff -c 8
2875 diff -r 29114dbae42b -r 95c24699272e fourth
2878 diff -r 29114dbae42b -r 95c24699272e fourth
2876 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2879 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2877 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2880 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2878 @@ -0,0 +1,1 @@
2881 @@ -0,0 +1,1 @@
2879 +second
2882 +second
2880 diff -r 29114dbae42b -r 95c24699272e second
2883 diff -r 29114dbae42b -r 95c24699272e second
2881 --- a/second Mon Jan 12 13:46:40 1970 +0000
2884 --- a/second Mon Jan 12 13:46:40 1970 +0000
2882 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2885 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2883 @@ -1,1 +0,0 @@
2886 @@ -1,1 +0,0 @@
2884 -second
2887 -second
2885 diff -r 29114dbae42b -r 95c24699272e third
2888 diff -r 29114dbae42b -r 95c24699272e third
2886 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2889 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2887 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2890 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2888 @@ -0,0 +1,1 @@
2891 @@ -0,0 +1,1 @@
2889 +third
2892 +third
2890
2893
2891 $ hg log -r 8 -T "{diff()}"
2894 $ hg log -r 8 -T "{diff()}"
2892 diff -r 29114dbae42b -r 95c24699272e fourth
2895 diff -r 29114dbae42b -r 95c24699272e fourth
2893 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2896 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2894 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2897 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2895 @@ -0,0 +1,1 @@
2898 @@ -0,0 +1,1 @@
2896 +second
2899 +second
2897 diff -r 29114dbae42b -r 95c24699272e second
2900 diff -r 29114dbae42b -r 95c24699272e second
2898 --- a/second Mon Jan 12 13:46:40 1970 +0000
2901 --- a/second Mon Jan 12 13:46:40 1970 +0000
2899 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2902 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2900 @@ -1,1 +0,0 @@
2903 @@ -1,1 +0,0 @@
2901 -second
2904 -second
2902 diff -r 29114dbae42b -r 95c24699272e third
2905 diff -r 29114dbae42b -r 95c24699272e third
2903 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2906 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2904 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2907 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2905 @@ -0,0 +1,1 @@
2908 @@ -0,0 +1,1 @@
2906 +third
2909 +third
2907
2910
2908 $ hg log -r 8 -T "{diff('glob:f*')}"
2911 $ hg log -r 8 -T "{diff('glob:f*')}"
2909 diff -r 29114dbae42b -r 95c24699272e fourth
2912 diff -r 29114dbae42b -r 95c24699272e fourth
2910 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2913 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2911 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2914 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2912 @@ -0,0 +1,1 @@
2915 @@ -0,0 +1,1 @@
2913 +second
2916 +second
2914
2917
2915 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2918 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2916 diff -r 29114dbae42b -r 95c24699272e second
2919 diff -r 29114dbae42b -r 95c24699272e second
2917 --- a/second Mon Jan 12 13:46:40 1970 +0000
2920 --- a/second Mon Jan 12 13:46:40 1970 +0000
2918 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2921 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2919 @@ -1,1 +0,0 @@
2922 @@ -1,1 +0,0 @@
2920 -second
2923 -second
2921 diff -r 29114dbae42b -r 95c24699272e third
2924 diff -r 29114dbae42b -r 95c24699272e third
2922 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2925 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2923 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2926 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2924 @@ -0,0 +1,1 @@
2927 @@ -0,0 +1,1 @@
2925 +third
2928 +third
2926
2929
2927 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
2930 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
2928 diff -r 29114dbae42b -r 95c24699272e fourth
2931 diff -r 29114dbae42b -r 95c24699272e fourth
2929 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2932 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2930 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2933 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2931 @@ -0,0 +1,1 @@
2934 @@ -0,0 +1,1 @@
2932 +second
2935 +second
2933
2936
2934 ui verbosity:
2937 ui verbosity:
2935
2938
2936 $ hg log -l1 -T '{verbosity}\n'
2939 $ hg log -l1 -T '{verbosity}\n'
2937
2940
2938 $ hg log -l1 -T '{verbosity}\n' --debug
2941 $ hg log -l1 -T '{verbosity}\n' --debug
2939 debug
2942 debug
2940 $ hg log -l1 -T '{verbosity}\n' --quiet
2943 $ hg log -l1 -T '{verbosity}\n' --quiet
2941 quiet
2944 quiet
2942 $ hg log -l1 -T '{verbosity}\n' --verbose
2945 $ hg log -l1 -T '{verbosity}\n' --verbose
2943 verbose
2946 verbose
2944
2947
2945 $ cd ..
2948 $ cd ..
2946
2949
2947
2950
2948 latesttag:
2951 latesttag:
2949
2952
2950 $ hg init latesttag
2953 $ hg init latesttag
2951 $ cd latesttag
2954 $ cd latesttag
2952
2955
2953 $ echo a > file
2956 $ echo a > file
2954 $ hg ci -Am a -d '0 0'
2957 $ hg ci -Am a -d '0 0'
2955 adding file
2958 adding file
2956
2959
2957 $ echo b >> file
2960 $ echo b >> file
2958 $ hg ci -m b -d '1 0'
2961 $ hg ci -m b -d '1 0'
2959
2962
2960 $ echo c >> head1
2963 $ echo c >> head1
2961 $ hg ci -Am h1c -d '2 0'
2964 $ hg ci -Am h1c -d '2 0'
2962 adding head1
2965 adding head1
2963
2966
2964 $ hg update -q 1
2967 $ hg update -q 1
2965 $ echo d >> head2
2968 $ echo d >> head2
2966 $ hg ci -Am h2d -d '3 0'
2969 $ hg ci -Am h2d -d '3 0'
2967 adding head2
2970 adding head2
2968 created new head
2971 created new head
2969
2972
2970 $ echo e >> head2
2973 $ echo e >> head2
2971 $ hg ci -m h2e -d '4 0'
2974 $ hg ci -m h2e -d '4 0'
2972
2975
2973 $ hg merge -q
2976 $ hg merge -q
2974 $ hg ci -m merge -d '5 -3600'
2977 $ hg ci -m merge -d '5 -3600'
2975
2978
2976 No tag set:
2979 No tag set:
2977
2980
2978 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2981 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2979 @ 5: null+5
2982 @ 5: null+5
2980 |\
2983 |\
2981 | o 4: null+4
2984 | o 4: null+4
2982 | |
2985 | |
2983 | o 3: null+3
2986 | o 3: null+3
2984 | |
2987 | |
2985 o | 2: null+3
2988 o | 2: null+3
2986 |/
2989 |/
2987 o 1: null+2
2990 o 1: null+2
2988 |
2991 |
2989 o 0: null+1
2992 o 0: null+1
2990
2993
2991
2994
2992 One common tag: longest path wins for {latesttagdistance}:
2995 One common tag: longest path wins for {latesttagdistance}:
2993
2996
2994 $ hg tag -r 1 -m t1 -d '6 0' t1
2997 $ hg tag -r 1 -m t1 -d '6 0' t1
2995 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2998 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2996 @ 6: t1+4
2999 @ 6: t1+4
2997 |
3000 |
2998 o 5: t1+3
3001 o 5: t1+3
2999 |\
3002 |\
3000 | o 4: t1+2
3003 | o 4: t1+2
3001 | |
3004 | |
3002 | o 3: t1+1
3005 | o 3: t1+1
3003 | |
3006 | |
3004 o | 2: t1+1
3007 o | 2: t1+1
3005 |/
3008 |/
3006 o 1: t1+0
3009 o 1: t1+0
3007 |
3010 |
3008 o 0: null+1
3011 o 0: null+1
3009
3012
3010
3013
3011 One ancestor tag: closest wins:
3014 One ancestor tag: closest wins:
3012
3015
3013 $ hg tag -r 2 -m t2 -d '7 0' t2
3016 $ hg tag -r 2 -m t2 -d '7 0' t2
3014 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
3017 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
3015 @ 7: t2+3
3018 @ 7: t2+3
3016 |
3019 |
3017 o 6: t2+2
3020 o 6: t2+2
3018 |
3021 |
3019 o 5: t2+1
3022 o 5: t2+1
3020 |\
3023 |\
3021 | o 4: t1+2
3024 | o 4: t1+2
3022 | |
3025 | |
3023 | o 3: t1+1
3026 | o 3: t1+1
3024 | |
3027 | |
3025 o | 2: t2+0
3028 o | 2: t2+0
3026 |/
3029 |/
3027 o 1: t1+0
3030 o 1: t1+0
3028 |
3031 |
3029 o 0: null+1
3032 o 0: null+1
3030
3033
3031
3034
3032 Two branch tags: more recent wins if same number of changes:
3035 Two branch tags: more recent wins if same number of changes:
3033
3036
3034 $ hg tag -r 3 -m t3 -d '8 0' t3
3037 $ hg tag -r 3 -m t3 -d '8 0' t3
3035 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
3038 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
3036 @ 8: t3+5
3039 @ 8: t3+5
3037 |
3040 |
3038 o 7: t3+4
3041 o 7: t3+4
3039 |
3042 |
3040 o 6: t3+3
3043 o 6: t3+3
3041 |
3044 |
3042 o 5: t3+2
3045 o 5: t3+2
3043 |\
3046 |\
3044 | o 4: t3+1
3047 | o 4: t3+1
3045 | |
3048 | |
3046 | o 3: t3+0
3049 | o 3: t3+0
3047 | |
3050 | |
3048 o | 2: t2+0
3051 o | 2: t2+0
3049 |/
3052 |/
3050 o 1: t1+0
3053 o 1: t1+0
3051 |
3054 |
3052 o 0: null+1
3055 o 0: null+1
3053
3056
3054
3057
3055 Two branch tags: fewest changes wins:
3058 Two branch tags: fewest changes wins:
3056
3059
3057 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
3060 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
3058 $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
3061 $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
3059 @ 9: t4+5,6
3062 @ 9: t4+5,6
3060 |
3063 |
3061 o 8: t4+4,5
3064 o 8: t4+4,5
3062 |
3065 |
3063 o 7: t4+3,4
3066 o 7: t4+3,4
3064 |
3067 |
3065 o 6: t4+2,3
3068 o 6: t4+2,3
3066 |
3069 |
3067 o 5: t4+1,2
3070 o 5: t4+1,2
3068 |\
3071 |\
3069 | o 4: t4+0,0
3072 | o 4: t4+0,0
3070 | |
3073 | |
3071 | o 3: t3+0,0
3074 | o 3: t3+0,0
3072 | |
3075 | |
3073 o | 2: t2+0,0
3076 o | 2: t2+0,0
3074 |/
3077 |/
3075 o 1: t1+0,0
3078 o 1: t1+0,0
3076 |
3079 |
3077 o 0: null+1,1
3080 o 0: null+1,1
3078
3081
3079
3082
3080 Merged tag overrides:
3083 Merged tag overrides:
3081
3084
3082 $ hg tag -r 5 -m t5 -d '9 0' t5
3085 $ hg tag -r 5 -m t5 -d '9 0' t5
3083 $ hg tag -r 3 -m at3 -d '10 0' at3
3086 $ hg tag -r 3 -m at3 -d '10 0' at3
3084 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
3087 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
3085 @ 11: t5+6
3088 @ 11: t5+6
3086 |
3089 |
3087 o 10: t5+5
3090 o 10: t5+5
3088 |
3091 |
3089 o 9: t5+4
3092 o 9: t5+4
3090 |
3093 |
3091 o 8: t5+3
3094 o 8: t5+3
3092 |
3095 |
3093 o 7: t5+2
3096 o 7: t5+2
3094 |
3097 |
3095 o 6: t5+1
3098 o 6: t5+1
3096 |
3099 |
3097 o 5: t5+0
3100 o 5: t5+0
3098 |\
3101 |\
3099 | o 4: t4+0
3102 | o 4: t4+0
3100 | |
3103 | |
3101 | o 3: at3:t3+0
3104 | o 3: at3:t3+0
3102 | |
3105 | |
3103 o | 2: t2+0
3106 o | 2: t2+0
3104 |/
3107 |/
3105 o 1: t1+0
3108 o 1: t1+0
3106 |
3109 |
3107 o 0: null+1
3110 o 0: null+1
3108
3111
3109
3112
3110 $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
3113 $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
3111 @ 11: t5+6,6
3114 @ 11: t5+6,6
3112 |
3115 |
3113 o 10: t5+5,5
3116 o 10: t5+5,5
3114 |
3117 |
3115 o 9: t5+4,4
3118 o 9: t5+4,4
3116 |
3119 |
3117 o 8: t5+3,3
3120 o 8: t5+3,3
3118 |
3121 |
3119 o 7: t5+2,2
3122 o 7: t5+2,2
3120 |
3123 |
3121 o 6: t5+1,1
3124 o 6: t5+1,1
3122 |
3125 |
3123 o 5: t5+0,0
3126 o 5: t5+0,0
3124 |\
3127 |\
3125 | o 4: t4+0,0
3128 | o 4: t4+0,0
3126 | |
3129 | |
3127 | o 3: at3+0,0 t3+0,0
3130 | o 3: at3+0,0 t3+0,0
3128 | |
3131 | |
3129 o | 2: t2+0,0
3132 o | 2: t2+0,0
3130 |/
3133 |/
3131 o 1: t1+0,0
3134 o 1: t1+0,0
3132 |
3135 |
3133 o 0: null+1,1
3136 o 0: null+1,1
3134
3137
3135
3138
3136 $ hg log -G --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
3139 $ hg log -G --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
3137 @ 11: t3, C: 9, D: 8
3140 @ 11: t3, C: 9, D: 8
3138 |
3141 |
3139 o 10: t3, C: 8, D: 7
3142 o 10: t3, C: 8, D: 7
3140 |
3143 |
3141 o 9: t3, C: 7, D: 6
3144 o 9: t3, C: 7, D: 6
3142 |
3145 |
3143 o 8: t3, C: 6, D: 5
3146 o 8: t3, C: 6, D: 5
3144 |
3147 |
3145 o 7: t3, C: 5, D: 4
3148 o 7: t3, C: 5, D: 4
3146 |
3149 |
3147 o 6: t3, C: 4, D: 3
3150 o 6: t3, C: 4, D: 3
3148 |
3151 |
3149 o 5: t3, C: 3, D: 2
3152 o 5: t3, C: 3, D: 2
3150 |\
3153 |\
3151 | o 4: t3, C: 1, D: 1
3154 | o 4: t3, C: 1, D: 1
3152 | |
3155 | |
3153 | o 3: t3, C: 0, D: 0
3156 | o 3: t3, C: 0, D: 0
3154 | |
3157 | |
3155 o | 2: t1, C: 1, D: 1
3158 o | 2: t1, C: 1, D: 1
3156 |/
3159 |/
3157 o 1: t1, C: 0, D: 0
3160 o 1: t1, C: 0, D: 0
3158 |
3161 |
3159 o 0: null, C: 1, D: 1
3162 o 0: null, C: 1, D: 1
3160
3163
3161
3164
3162 $ cd ..
3165 $ cd ..
3163
3166
3164
3167
3165 Style path expansion: issue1948 - ui.style option doesn't work on OSX
3168 Style path expansion: issue1948 - ui.style option doesn't work on OSX
3166 if it is a relative path
3169 if it is a relative path
3167
3170
3168 $ mkdir -p home/styles
3171 $ mkdir -p home/styles
3169
3172
3170 $ cat > home/styles/teststyle <<EOF
3173 $ cat > home/styles/teststyle <<EOF
3171 > changeset = 'test {rev}:{node|short}\n'
3174 > changeset = 'test {rev}:{node|short}\n'
3172 > EOF
3175 > EOF
3173
3176
3174 $ HOME=`pwd`/home; export HOME
3177 $ HOME=`pwd`/home; export HOME
3175
3178
3176 $ cat > latesttag/.hg/hgrc <<EOF
3179 $ cat > latesttag/.hg/hgrc <<EOF
3177 > [ui]
3180 > [ui]
3178 > style = ~/styles/teststyle
3181 > style = ~/styles/teststyle
3179 > EOF
3182 > EOF
3180
3183
3181 $ hg -R latesttag tip
3184 $ hg -R latesttag tip
3182 test 11:97e5943b523a
3185 test 11:97e5943b523a
3183
3186
3184 Test recursive showlist template (issue1989):
3187 Test recursive showlist template (issue1989):
3185
3188
3186 $ cat > style1989 <<EOF
3189 $ cat > style1989 <<EOF
3187 > changeset = '{file_mods}{manifest}{extras}'
3190 > changeset = '{file_mods}{manifest}{extras}'
3188 > file_mod = 'M|{author|person}\n'
3191 > file_mod = 'M|{author|person}\n'
3189 > manifest = '{rev},{author}\n'
3192 > manifest = '{rev},{author}\n'
3190 > extra = '{key}: {author}\n'
3193 > extra = '{key}: {author}\n'
3191 > EOF
3194 > EOF
3192
3195
3193 $ hg -R latesttag log -r tip --style=style1989
3196 $ hg -R latesttag log -r tip --style=style1989
3194 M|test
3197 M|test
3195 11,test
3198 11,test
3196 branch: test
3199 branch: test
3197
3200
3198 Test new-style inline templating:
3201 Test new-style inline templating:
3199
3202
3200 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
3203 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
3201 modified files: .hgtags
3204 modified files: .hgtags
3202
3205
3203
3206
3204 $ hg log -R latesttag -r tip -T '{rev % "a"}\n'
3207 $ hg log -R latesttag -r tip -T '{rev % "a"}\n'
3205 hg: parse error: keyword 'rev' is not iterable
3208 hg: parse error: keyword 'rev' is not iterable
3206 [255]
3209 [255]
3207 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "a"}\n'
3210 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "a"}\n'
3208 hg: parse error: None is not iterable
3211 hg: parse error: None is not iterable
3209 [255]
3212 [255]
3210
3213
3211 Test new-style inline templating of non-list/dict type:
3214 Test new-style inline templating of non-list/dict type:
3212
3215
3213 $ hg log -R latesttag -r tip -T '{manifest}\n'
3216 $ hg log -R latesttag -r tip -T '{manifest}\n'
3214 11:2bc6e9006ce2
3217 11:2bc6e9006ce2
3215 $ hg log -R latesttag -r tip -T 'string length: {manifest|count}\n'
3218 $ hg log -R latesttag -r tip -T 'string length: {manifest|count}\n'
3216 string length: 15
3219 string length: 15
3217 $ hg log -R latesttag -r tip -T '{manifest % "{rev}:{node}"}\n'
3220 $ hg log -R latesttag -r tip -T '{manifest % "{rev}:{node}"}\n'
3218 11:2bc6e9006ce29882383a22d39fd1f4e66dd3e2fc
3221 11:2bc6e9006ce29882383a22d39fd1f4e66dd3e2fc
3219
3222
3220 $ hg log -R latesttag -r tip -T '{get(extras, "branch") % "{key}: {value}\n"}'
3223 $ hg log -R latesttag -r tip -T '{get(extras, "branch") % "{key}: {value}\n"}'
3221 branch: default
3224 branch: default
3222 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "{key}\n"}'
3225 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "{key}\n"}'
3223 hg: parse error: None is not iterable
3226 hg: parse error: None is not iterable
3224 [255]
3227 [255]
3225 $ hg log -R latesttag -r tip -T '{min(extras) % "{key}: {value}\n"}'
3228 $ hg log -R latesttag -r tip -T '{min(extras) % "{key}: {value}\n"}'
3226 branch: default
3229 branch: default
3227 $ hg log -R latesttag -l1 -T '{min(revset("0:9")) % "{rev}:{node|short}\n"}'
3230 $ hg log -R latesttag -l1 -T '{min(revset("0:9")) % "{rev}:{node|short}\n"}'
3228 0:ce3cec86e6c2
3231 0:ce3cec86e6c2
3229 $ hg log -R latesttag -l1 -T '{max(revset("0:9")) % "{rev}:{node|short}\n"}'
3232 $ hg log -R latesttag -l1 -T '{max(revset("0:9")) % "{rev}:{node|short}\n"}'
3230 9:fbc7cd862e9c
3233 9:fbc7cd862e9c
3231
3234
3232 Test manifest/get() can be join()-ed as before, though it's silly:
3235 Test manifest/get() can be join()-ed as before, though it's silly:
3233
3236
3234 $ hg log -R latesttag -r tip -T '{join(manifest, "")}\n'
3237 $ hg log -R latesttag -r tip -T '{join(manifest, "")}\n'
3235 11:2bc6e9006ce2
3238 11:2bc6e9006ce2
3236 $ hg log -R latesttag -r tip -T '{join(get(extras, "branch"), "")}\n'
3239 $ hg log -R latesttag -r tip -T '{join(get(extras, "branch"), "")}\n'
3237 default
3240 default
3238
3241
3239 Test min/max of integers
3242 Test min/max of integers
3240
3243
3241 $ hg log -R latesttag -l1 -T '{min(revset("9:10"))}\n'
3244 $ hg log -R latesttag -l1 -T '{min(revset("9:10"))}\n'
3242 9
3245 9
3243 $ hg log -R latesttag -l1 -T '{max(revset("9:10"))}\n'
3246 $ hg log -R latesttag -l1 -T '{max(revset("9:10"))}\n'
3244 10
3247 10
3245
3248
3246 Test min/max of if() result
3249 Test min/max of if() result
3247
3250
3248 $ cd latesttag
3251 $ cd latesttag
3249 $ hg log -l1 -T '{min(if(true, revset("9:10"), ""))}\n'
3252 $ hg log -l1 -T '{min(if(true, revset("9:10"), ""))}\n'
3250 9
3253 9
3251 $ hg log -l1 -T '{max(if(false, "", revset("9:10")))}\n'
3254 $ hg log -l1 -T '{max(if(false, "", revset("9:10")))}\n'
3252 10
3255 10
3253 $ hg log -l1 -T '{min(ifcontains("a", "aa", revset("9:10"), ""))}\n'
3256 $ hg log -l1 -T '{min(ifcontains("a", "aa", revset("9:10"), ""))}\n'
3254 9
3257 9
3255 $ hg log -l1 -T '{max(ifcontains("a", "bb", "", revset("9:10")))}\n'
3258 $ hg log -l1 -T '{max(ifcontains("a", "bb", "", revset("9:10")))}\n'
3256 10
3259 10
3257 $ hg log -l1 -T '{min(ifeq(0, 0, revset("9:10"), ""))}\n'
3260 $ hg log -l1 -T '{min(ifeq(0, 0, revset("9:10"), ""))}\n'
3258 9
3261 9
3259 $ hg log -l1 -T '{max(ifeq(0, 1, "", revset("9:10")))}\n'
3262 $ hg log -l1 -T '{max(ifeq(0, 1, "", revset("9:10")))}\n'
3260 10
3263 10
3261 $ cd ..
3264 $ cd ..
3262
3265
3263 Test laziness of if() then/else clause
3266 Test laziness of if() then/else clause
3264
3267
3265 $ hg debugtemplate '{count(0)}'
3268 $ hg debugtemplate '{count(0)}'
3266 abort: incompatible use of template filter 'count'
3269 abort: incompatible use of template filter 'count'
3267 [255]
3270 [255]
3268 $ hg debugtemplate '{if(true, "", count(0))}'
3271 $ hg debugtemplate '{if(true, "", count(0))}'
3269 $ hg debugtemplate '{if(false, count(0), "")}'
3272 $ hg debugtemplate '{if(false, count(0), "")}'
3270 $ hg debugtemplate '{ifcontains("a", "aa", "", count(0))}'
3273 $ hg debugtemplate '{ifcontains("a", "aa", "", count(0))}'
3271 $ hg debugtemplate '{ifcontains("a", "bb", count(0), "")}'
3274 $ hg debugtemplate '{ifcontains("a", "bb", count(0), "")}'
3272 $ hg debugtemplate '{ifeq(0, 0, "", count(0))}'
3275 $ hg debugtemplate '{ifeq(0, 0, "", count(0))}'
3273 $ hg debugtemplate '{ifeq(0, 1, count(0), "")}'
3276 $ hg debugtemplate '{ifeq(0, 1, count(0), "")}'
3274
3277
3275 Test dot operator precedence:
3278 Test dot operator precedence:
3276
3279
3277 $ hg debugtemplate -R latesttag -r0 -v '{manifest.node|short}\n'
3280 $ hg debugtemplate -R latesttag -r0 -v '{manifest.node|short}\n'
3278 (template
3281 (template
3279 (|
3282 (|
3280 (.
3283 (.
3281 (symbol 'manifest')
3284 (symbol 'manifest')
3282 (symbol 'node'))
3285 (symbol 'node'))
3283 (symbol 'short'))
3286 (symbol 'short'))
3284 (string '\n'))
3287 (string '\n'))
3285 89f4071fec70
3288 89f4071fec70
3286
3289
3287 (the following examples are invalid, but seem natural in parsing POV)
3290 (the following examples are invalid, but seem natural in parsing POV)
3288
3291
3289 $ hg debugtemplate -R latesttag -r0 -v '{foo|bar.baz}\n' 2> /dev/null
3292 $ hg debugtemplate -R latesttag -r0 -v '{foo|bar.baz}\n' 2> /dev/null
3290 (template
3293 (template
3291 (|
3294 (|
3292 (symbol 'foo')
3295 (symbol 'foo')
3293 (.
3296 (.
3294 (symbol 'bar')
3297 (symbol 'bar')
3295 (symbol 'baz')))
3298 (symbol 'baz')))
3296 (string '\n'))
3299 (string '\n'))
3297 [255]
3300 [255]
3298 $ hg debugtemplate -R latesttag -r0 -v '{foo.bar()}\n' 2> /dev/null
3301 $ hg debugtemplate -R latesttag -r0 -v '{foo.bar()}\n' 2> /dev/null
3299 (template
3302 (template
3300 (.
3303 (.
3301 (symbol 'foo')
3304 (symbol 'foo')
3302 (func
3305 (func
3303 (symbol 'bar')
3306 (symbol 'bar')
3304 None))
3307 None))
3305 (string '\n'))
3308 (string '\n'))
3306 [255]
3309 [255]
3307
3310
3308 Test evaluation of dot operator:
3311 Test evaluation of dot operator:
3309
3312
3310 $ hg log -R latesttag -l1 -T '{min(revset("0:9")).node}\n'
3313 $ hg log -R latesttag -l1 -T '{min(revset("0:9")).node}\n'
3311 ce3cec86e6c26bd9bdfc590a6b92abc9680f1796
3314 ce3cec86e6c26bd9bdfc590a6b92abc9680f1796
3312 $ hg log -R latesttag -r0 -T '{extras.branch}\n'
3315 $ hg log -R latesttag -r0 -T '{extras.branch}\n'
3313 default
3316 default
3314
3317
3315 $ hg log -R latesttag -l1 -T '{author.invalid}\n'
3318 $ hg log -R latesttag -l1 -T '{author.invalid}\n'
3316 hg: parse error: keyword 'author' has no member
3319 hg: parse error: keyword 'author' has no member
3317 [255]
3320 [255]
3318 $ hg log -R latesttag -l1 -T '{min("abc").invalid}\n'
3321 $ hg log -R latesttag -l1 -T '{min("abc").invalid}\n'
3319 hg: parse error: 'a' has no member
3322 hg: parse error: 'a' has no member
3320 [255]
3323 [255]
3321
3324
3322 Test the sub function of templating for expansion:
3325 Test the sub function of templating for expansion:
3323
3326
3324 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
3327 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
3325 xx
3328 xx
3326
3329
3327 $ hg log -R latesttag -r 10 -T '{sub("[", "x", rev)}\n'
3330 $ hg log -R latesttag -r 10 -T '{sub("[", "x", rev)}\n'
3328 hg: parse error: sub got an invalid pattern: [
3331 hg: parse error: sub got an invalid pattern: [
3329 [255]
3332 [255]
3330 $ hg log -R latesttag -r 10 -T '{sub("[0-9]", r"\1", rev)}\n'
3333 $ hg log -R latesttag -r 10 -T '{sub("[0-9]", r"\1", rev)}\n'
3331 hg: parse error: sub got an invalid replacement: \1
3334 hg: parse error: sub got an invalid replacement: \1
3332 [255]
3335 [255]
3333
3336
3334 Test the strip function with chars specified:
3337 Test the strip function with chars specified:
3335
3338
3336 $ hg log -R latesttag --template '{desc}\n'
3339 $ hg log -R latesttag --template '{desc}\n'
3337 at3
3340 at3
3338 t5
3341 t5
3339 t4
3342 t4
3340 t3
3343 t3
3341 t2
3344 t2
3342 t1
3345 t1
3343 merge
3346 merge
3344 h2e
3347 h2e
3345 h2d
3348 h2d
3346 h1c
3349 h1c
3347 b
3350 b
3348 a
3351 a
3349
3352
3350 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
3353 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
3351 at3
3354 at3
3352 5
3355 5
3353 4
3356 4
3354 3
3357 3
3355 2
3358 2
3356 1
3359 1
3357 merg
3360 merg
3358 h2
3361 h2
3359 h2d
3362 h2d
3360 h1c
3363 h1c
3361 b
3364 b
3362 a
3365 a
3363
3366
3364 Test date format:
3367 Test date format:
3365
3368
3366 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
3369 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
3367 date: 70 01 01 10 +0000
3370 date: 70 01 01 10 +0000
3368 date: 70 01 01 09 +0000
3371 date: 70 01 01 09 +0000
3369 date: 70 01 01 04 +0000
3372 date: 70 01 01 04 +0000
3370 date: 70 01 01 08 +0000
3373 date: 70 01 01 08 +0000
3371 date: 70 01 01 07 +0000
3374 date: 70 01 01 07 +0000
3372 date: 70 01 01 06 +0000
3375 date: 70 01 01 06 +0000
3373 date: 70 01 01 05 +0100
3376 date: 70 01 01 05 +0100
3374 date: 70 01 01 04 +0000
3377 date: 70 01 01 04 +0000
3375 date: 70 01 01 03 +0000
3378 date: 70 01 01 03 +0000
3376 date: 70 01 01 02 +0000
3379 date: 70 01 01 02 +0000
3377 date: 70 01 01 01 +0000
3380 date: 70 01 01 01 +0000
3378 date: 70 01 01 00 +0000
3381 date: 70 01 01 00 +0000
3379
3382
3380 Test invalid date:
3383 Test invalid date:
3381
3384
3382 $ hg log -R latesttag -T '{date(rev)}\n'
3385 $ hg log -R latesttag -T '{date(rev)}\n'
3383 hg: parse error: date expects a date information
3386 hg: parse error: date expects a date information
3384 [255]
3387 [255]
3385
3388
3386 Test integer literal:
3389 Test integer literal:
3387
3390
3388 $ hg debugtemplate -v '{(0)}\n'
3391 $ hg debugtemplate -v '{(0)}\n'
3389 (template
3392 (template
3390 (group
3393 (group
3391 (integer '0'))
3394 (integer '0'))
3392 (string '\n'))
3395 (string '\n'))
3393 0
3396 0
3394 $ hg debugtemplate -v '{(123)}\n'
3397 $ hg debugtemplate -v '{(123)}\n'
3395 (template
3398 (template
3396 (group
3399 (group
3397 (integer '123'))
3400 (integer '123'))
3398 (string '\n'))
3401 (string '\n'))
3399 123
3402 123
3400 $ hg debugtemplate -v '{(-4)}\n'
3403 $ hg debugtemplate -v '{(-4)}\n'
3401 (template
3404 (template
3402 (group
3405 (group
3403 (negate
3406 (negate
3404 (integer '4')))
3407 (integer '4')))
3405 (string '\n'))
3408 (string '\n'))
3406 -4
3409 -4
3407 $ hg debugtemplate '{(-)}\n'
3410 $ hg debugtemplate '{(-)}\n'
3408 hg: parse error at 3: not a prefix: )
3411 hg: parse error at 3: not a prefix: )
3409 ({(-)}\n
3412 ({(-)}\n
3410 ^ here)
3413 ^ here)
3411 [255]
3414 [255]
3412 $ hg debugtemplate '{(-a)}\n'
3415 $ hg debugtemplate '{(-a)}\n'
3413 hg: parse error: negation needs an integer argument
3416 hg: parse error: negation needs an integer argument
3414 [255]
3417 [255]
3415
3418
3416 top-level integer literal is interpreted as symbol (i.e. variable name):
3419 top-level integer literal is interpreted as symbol (i.e. variable name):
3417
3420
3418 $ hg debugtemplate -D 1=one -v '{1}\n'
3421 $ hg debugtemplate -D 1=one -v '{1}\n'
3419 (template
3422 (template
3420 (integer '1')
3423 (integer '1')
3421 (string '\n'))
3424 (string '\n'))
3422 one
3425 one
3423 $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
3426 $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
3424 (template
3427 (template
3425 (func
3428 (func
3426 (symbol 'if')
3429 (symbol 'if')
3427 (list
3430 (list
3428 (string 't')
3431 (string 't')
3429 (template
3432 (template
3430 (integer '1'))))
3433 (integer '1'))))
3431 (string '\n'))
3434 (string '\n'))
3432 one
3435 one
3433 $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
3436 $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
3434 (template
3437 (template
3435 (|
3438 (|
3436 (integer '1')
3439 (integer '1')
3437 (symbol 'stringify'))
3440 (symbol 'stringify'))
3438 (string '\n'))
3441 (string '\n'))
3439 one
3442 one
3440
3443
3441 unless explicit symbol is expected:
3444 unless explicit symbol is expected:
3442
3445
3443 $ hg log -Ra -r0 -T '{desc|1}\n'
3446 $ hg log -Ra -r0 -T '{desc|1}\n'
3444 hg: parse error: expected a symbol, got 'integer'
3447 hg: parse error: expected a symbol, got 'integer'
3445 [255]
3448 [255]
3446 $ hg log -Ra -r0 -T '{1()}\n'
3449 $ hg log -Ra -r0 -T '{1()}\n'
3447 hg: parse error: expected a symbol, got 'integer'
3450 hg: parse error: expected a symbol, got 'integer'
3448 [255]
3451 [255]
3449
3452
3450 Test string literal:
3453 Test string literal:
3451
3454
3452 $ hg debugtemplate -Ra -r0 -v '{"string with no template fragment"}\n'
3455 $ hg debugtemplate -Ra -r0 -v '{"string with no template fragment"}\n'
3453 (template
3456 (template
3454 (string 'string with no template fragment')
3457 (string 'string with no template fragment')
3455 (string '\n'))
3458 (string '\n'))
3456 string with no template fragment
3459 string with no template fragment
3457 $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
3460 $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
3458 (template
3461 (template
3459 (template
3462 (template
3460 (string 'template: ')
3463 (string 'template: ')
3461 (symbol 'rev'))
3464 (symbol 'rev'))
3462 (string '\n'))
3465 (string '\n'))
3463 template: 0
3466 template: 0
3464 $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
3467 $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
3465 (template
3468 (template
3466 (string 'rawstring: {rev}')
3469 (string 'rawstring: {rev}')
3467 (string '\n'))
3470 (string '\n'))
3468 rawstring: {rev}
3471 rawstring: {rev}
3469 $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
3472 $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
3470 (template
3473 (template
3471 (%
3474 (%
3472 (symbol 'files')
3475 (symbol 'files')
3473 (string 'rawstring: {file}'))
3476 (string 'rawstring: {file}'))
3474 (string '\n'))
3477 (string '\n'))
3475 rawstring: {file}
3478 rawstring: {file}
3476
3479
3477 Test string escaping:
3480 Test string escaping:
3478
3481
3479 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3482 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3480 >
3483 >
3481 <>\n<[>
3484 <>\n<[>
3482 <>\n<]>
3485 <>\n<]>
3483 <>\n<
3486 <>\n<
3484
3487
3485 $ hg log -R latesttag -r 0 \
3488 $ hg log -R latesttag -r 0 \
3486 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3489 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3487 >
3490 >
3488 <>\n<[>
3491 <>\n<[>
3489 <>\n<]>
3492 <>\n<]>
3490 <>\n<
3493 <>\n<
3491
3494
3492 $ hg log -R latesttag -r 0 -T esc \
3495 $ hg log -R latesttag -r 0 -T esc \
3493 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3496 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3494 >
3497 >
3495 <>\n<[>
3498 <>\n<[>
3496 <>\n<]>
3499 <>\n<]>
3497 <>\n<
3500 <>\n<
3498
3501
3499 $ cat <<'EOF' > esctmpl
3502 $ cat <<'EOF' > esctmpl
3500 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3503 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3501 > EOF
3504 > EOF
3502 $ hg log -R latesttag -r 0 --style ./esctmpl
3505 $ hg log -R latesttag -r 0 --style ./esctmpl
3503 >
3506 >
3504 <>\n<[>
3507 <>\n<[>
3505 <>\n<]>
3508 <>\n<]>
3506 <>\n<
3509 <>\n<
3507
3510
3508 Test string escaping of quotes:
3511 Test string escaping of quotes:
3509
3512
3510 $ hg log -Ra -r0 -T '{"\""}\n'
3513 $ hg log -Ra -r0 -T '{"\""}\n'
3511 "
3514 "
3512 $ hg log -Ra -r0 -T '{"\\\""}\n'
3515 $ hg log -Ra -r0 -T '{"\\\""}\n'
3513 \"
3516 \"
3514 $ hg log -Ra -r0 -T '{r"\""}\n'
3517 $ hg log -Ra -r0 -T '{r"\""}\n'
3515 \"
3518 \"
3516 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3519 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3517 \\\"
3520 \\\"
3518
3521
3519
3522
3520 $ hg log -Ra -r0 -T '{"\""}\n'
3523 $ hg log -Ra -r0 -T '{"\""}\n'
3521 "
3524 "
3522 $ hg log -Ra -r0 -T '{"\\\""}\n'
3525 $ hg log -Ra -r0 -T '{"\\\""}\n'
3523 \"
3526 \"
3524 $ hg log -Ra -r0 -T '{r"\""}\n'
3527 $ hg log -Ra -r0 -T '{r"\""}\n'
3525 \"
3528 \"
3526 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3529 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3527 \\\"
3530 \\\"
3528
3531
3529 Test exception in quoted template. single backslash before quotation mark is
3532 Test exception in quoted template. single backslash before quotation mark is
3530 stripped before parsing:
3533 stripped before parsing:
3531
3534
3532 $ cat <<'EOF' > escquotetmpl
3535 $ cat <<'EOF' > escquotetmpl
3533 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
3536 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
3534 > EOF
3537 > EOF
3535 $ cd latesttag
3538 $ cd latesttag
3536 $ hg log -r 2 --style ../escquotetmpl
3539 $ hg log -r 2 --style ../escquotetmpl
3537 " \" \" \\" head1
3540 " \" \" \\" head1
3538
3541
3539 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
3542 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
3540 valid
3543 valid
3541 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
3544 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
3542 valid
3545 valid
3543
3546
3544 Test compatibility with 2.9.2-3.4 of escaped quoted strings in nested
3547 Test compatibility with 2.9.2-3.4 of escaped quoted strings in nested
3545 _evalifliteral() templates (issue4733):
3548 _evalifliteral() templates (issue4733):
3546
3549
3547 $ hg log -r 2 -T '{if(rev, "\"{rev}")}\n'
3550 $ hg log -r 2 -T '{if(rev, "\"{rev}")}\n'
3548 "2
3551 "2
3549 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\"{rev}\")}")}\n'
3552 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\"{rev}\")}")}\n'
3550 "2
3553 "2
3551 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\"{rev}\\\")}\")}")}\n'
3554 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\"{rev}\\\")}\")}")}\n'
3552 "2
3555 "2
3553
3556
3554 $ hg log -r 2 -T '{if(rev, "\\\"")}\n'
3557 $ hg log -r 2 -T '{if(rev, "\\\"")}\n'
3555 \"
3558 \"
3556 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\\\\\"\")}")}\n'
3559 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\\\\\"\")}")}\n'
3557 \"
3560 \"
3558 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3561 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3559 \"
3562 \"
3560
3563
3561 $ hg log -r 2 -T '{if(rev, r"\\\"")}\n'
3564 $ hg log -r 2 -T '{if(rev, r"\\\"")}\n'
3562 \\\"
3565 \\\"
3563 $ hg log -r 2 -T '{if(rev, "{if(rev, r\"\\\\\\\"\")}")}\n'
3566 $ hg log -r 2 -T '{if(rev, "{if(rev, r\"\\\\\\\"\")}")}\n'
3564 \\\"
3567 \\\"
3565 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, r\\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3568 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, r\\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3566 \\\"
3569 \\\"
3567
3570
3568 escaped single quotes and errors:
3571 escaped single quotes and errors:
3569
3572
3570 $ hg log -r 2 -T "{if(rev, '{if(rev, \'foo\')}')}"'\n'
3573 $ hg log -r 2 -T "{if(rev, '{if(rev, \'foo\')}')}"'\n'
3571 foo
3574 foo
3572 $ hg log -r 2 -T "{if(rev, '{if(rev, r\'foo\')}')}"'\n'
3575 $ hg log -r 2 -T "{if(rev, '{if(rev, r\'foo\')}')}"'\n'
3573 foo
3576 foo
3574 $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n'
3577 $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n'
3575 hg: parse error at 21: unterminated string
3578 hg: parse error at 21: unterminated string
3576 ({if(rev, "{if(rev, \")}")}\n
3579 ({if(rev, "{if(rev, \")}")}\n
3577 ^ here)
3580 ^ here)
3578 [255]
3581 [255]
3579 $ hg log -r 2 -T '{if(rev, \"\\"")}\n'
3582 $ hg log -r 2 -T '{if(rev, \"\\"")}\n'
3580 hg: parse error: trailing \ in string
3583 hg: parse error: trailing \ in string
3581 [255]
3584 [255]
3582 $ hg log -r 2 -T '{if(rev, r\"\\"")}\n'
3585 $ hg log -r 2 -T '{if(rev, r\"\\"")}\n'
3583 hg: parse error: trailing \ in string
3586 hg: parse error: trailing \ in string
3584 [255]
3587 [255]
3585
3588
3586 $ cd ..
3589 $ cd ..
3587
3590
3588 Test leading backslashes:
3591 Test leading backslashes:
3589
3592
3590 $ cd latesttag
3593 $ cd latesttag
3591 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
3594 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
3592 {rev} {file}
3595 {rev} {file}
3593 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
3596 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
3594 \2 \head1
3597 \2 \head1
3595 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
3598 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
3596 \{rev} \{file}
3599 \{rev} \{file}
3597 $ cd ..
3600 $ cd ..
3598
3601
3599 Test leading backslashes in "if" expression (issue4714):
3602 Test leading backslashes in "if" expression (issue4714):
3600
3603
3601 $ cd latesttag
3604 $ cd latesttag
3602 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
3605 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
3603 {rev} \{rev}
3606 {rev} \{rev}
3604 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
3607 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
3605 \2 \\{rev}
3608 \2 \\{rev}
3606 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
3609 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
3607 \{rev} \\\{rev}
3610 \{rev} \\\{rev}
3608 $ cd ..
3611 $ cd ..
3609
3612
3610 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
3613 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
3611
3614
3612 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
3615 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
3613 \x6e
3616 \x6e
3614 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
3617 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
3615 \x5c\x786e
3618 \x5c\x786e
3616 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
3619 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
3617 \x6e
3620 \x6e
3618 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
3621 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
3619 \x5c\x786e
3622 \x5c\x786e
3620
3623
3621 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
3624 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
3622 \x6e
3625 \x6e
3623 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
3626 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
3624 \x5c\x786e
3627 \x5c\x786e
3625 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
3628 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
3626 \x6e
3629 \x6e
3627 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
3630 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
3628 \x5c\x786e
3631 \x5c\x786e
3629
3632
3630 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
3633 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
3631 fourth
3634 fourth
3632 second
3635 second
3633 third
3636 third
3634 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
3637 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
3635 fourth\nsecond\nthird
3638 fourth\nsecond\nthird
3636
3639
3637 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
3640 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
3638 <p>
3641 <p>
3639 1st
3642 1st
3640 </p>
3643 </p>
3641 <p>
3644 <p>
3642 2nd
3645 2nd
3643 </p>
3646 </p>
3644 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
3647 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
3645 <p>
3648 <p>
3646 1st\n\n2nd
3649 1st\n\n2nd
3647 </p>
3650 </p>
3648 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
3651 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
3649 1st
3652 1st
3650
3653
3651 2nd
3654 2nd
3652
3655
3653 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
3656 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
3654 o perso
3657 o perso
3655 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
3658 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
3656 no person
3659 no person
3657 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
3660 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
3658 o perso
3661 o perso
3659 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
3662 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
3660 no perso
3663 no perso
3661
3664
3662 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
3665 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
3663 -o perso-
3666 -o perso-
3664 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
3667 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
3665 no person
3668 no person
3666 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
3669 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
3667 \x2do perso\x2d
3670 \x2do perso\x2d
3668 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
3671 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
3669 -o perso-
3672 -o perso-
3670 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
3673 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
3671 \x2do perso\x6e
3674 \x2do perso\x6e
3672
3675
3673 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
3676 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
3674 fourth
3677 fourth
3675 second
3678 second
3676 third
3679 third
3677
3680
3678 Test string escaping in nested expression:
3681 Test string escaping in nested expression:
3679
3682
3680 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
3683 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
3681 fourth\x6esecond\x6ethird
3684 fourth\x6esecond\x6ethird
3682 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
3685 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
3683 fourth\x6esecond\x6ethird
3686 fourth\x6esecond\x6ethird
3684
3687
3685 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
3688 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
3686 fourth\x6esecond\x6ethird
3689 fourth\x6esecond\x6ethird
3687 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
3690 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
3688 fourth\x5c\x786esecond\x5c\x786ethird
3691 fourth\x5c\x786esecond\x5c\x786ethird
3689
3692
3690 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
3693 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
3691 3:\x6eo user, \x6eo domai\x6e
3694 3:\x6eo user, \x6eo domai\x6e
3692 4:\x5c\x786eew bra\x5c\x786ech
3695 4:\x5c\x786eew bra\x5c\x786ech
3693
3696
3694 Test quotes in nested expression are evaluated just like a $(command)
3697 Test quotes in nested expression are evaluated just like a $(command)
3695 substitution in POSIX shells:
3698 substitution in POSIX shells:
3696
3699
3697 $ hg log -R a -r 8 -T '{"{"{rev}:{node|short}"}"}\n'
3700 $ hg log -R a -r 8 -T '{"{"{rev}:{node|short}"}"}\n'
3698 8:95c24699272e
3701 8:95c24699272e
3699 $ hg log -R a -r 8 -T '{"{"\{{rev}} \"{node|short}\""}"}\n'
3702 $ hg log -R a -r 8 -T '{"{"\{{rev}} \"{node|short}\""}"}\n'
3700 {8} "95c24699272e"
3703 {8} "95c24699272e"
3701
3704
3702 Test recursive evaluation:
3705 Test recursive evaluation:
3703
3706
3704 $ hg init r
3707 $ hg init r
3705 $ cd r
3708 $ cd r
3706 $ echo a > a
3709 $ echo a > a
3707 $ hg ci -Am '{rev}'
3710 $ hg ci -Am '{rev}'
3708 adding a
3711 adding a
3709 $ hg log -r 0 --template '{if(rev, desc)}\n'
3712 $ hg log -r 0 --template '{if(rev, desc)}\n'
3710 {rev}
3713 {rev}
3711 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
3714 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
3712 test 0
3715 test 0
3713
3716
3714 $ hg branch -q 'text.{rev}'
3717 $ hg branch -q 'text.{rev}'
3715 $ echo aa >> aa
3718 $ echo aa >> aa
3716 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
3719 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
3717
3720
3718 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
3721 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
3719 {node|short}desc to
3722 {node|short}desc to
3720 text.{rev}be wrapped
3723 text.{rev}be wrapped
3721 text.{rev}desc to be
3724 text.{rev}desc to be
3722 text.{rev}wrapped (no-eol)
3725 text.{rev}wrapped (no-eol)
3723 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
3726 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
3724 bcc7ff960b8e:desc to
3727 bcc7ff960b8e:desc to
3725 text.1:be wrapped
3728 text.1:be wrapped
3726 text.1:desc to be
3729 text.1:desc to be
3727 text.1:wrapped (no-eol)
3730 text.1:wrapped (no-eol)
3728 $ hg log -l1 -T '{fill(desc, date, "", "")}\n'
3731 $ hg log -l1 -T '{fill(desc, date, "", "")}\n'
3729 hg: parse error: fill expects an integer width
3732 hg: parse error: fill expects an integer width
3730 [255]
3733 [255]
3731
3734
3732 $ COLUMNS=25 hg log -l1 --template '{fill(desc, termwidth, "{node|short}:", "termwidth.{rev}:")}'
3735 $ COLUMNS=25 hg log -l1 --template '{fill(desc, termwidth, "{node|short}:", "termwidth.{rev}:")}'
3733 bcc7ff960b8e:desc to be
3736 bcc7ff960b8e:desc to be
3734 termwidth.1:wrapped desc
3737 termwidth.1:wrapped desc
3735 termwidth.1:to be wrapped (no-eol)
3738 termwidth.1:to be wrapped (no-eol)
3736
3739
3737 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
3740 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
3738 {node|short} (no-eol)
3741 {node|short} (no-eol)
3739 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
3742 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
3740 bcc-ff---b-e (no-eol)
3743 bcc-ff---b-e (no-eol)
3741
3744
3742 $ cat >> .hg/hgrc <<EOF
3745 $ cat >> .hg/hgrc <<EOF
3743 > [extensions]
3746 > [extensions]
3744 > color=
3747 > color=
3745 > [color]
3748 > [color]
3746 > mode=ansi
3749 > mode=ansi
3747 > text.{rev} = red
3750 > text.{rev} = red
3748 > text.1 = green
3751 > text.1 = green
3749 > EOF
3752 > EOF
3750 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
3753 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
3751 \x1b[0;31mtext\x1b[0m (esc)
3754 \x1b[0;31mtext\x1b[0m (esc)
3752 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
3755 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
3753 \x1b[0;32mtext\x1b[0m (esc)
3756 \x1b[0;32mtext\x1b[0m (esc)
3754
3757
3755 color effect can be specified without quoting:
3758 color effect can be specified without quoting:
3756
3759
3757 $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
3760 $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
3758 \x1b[0;31mtext\x1b[0m (esc)
3761 \x1b[0;31mtext\x1b[0m (esc)
3759
3762
3760 color effects can be nested (issue5413)
3763 color effects can be nested (issue5413)
3761
3764
3762 $ hg debugtemplate --color=always \
3765 $ hg debugtemplate --color=always \
3763 > '{label(red, "red{label(magenta, "ma{label(cyan, "cyan")}{label(yellow, "yellow")}genta")}")}\n'
3766 > '{label(red, "red{label(magenta, "ma{label(cyan, "cyan")}{label(yellow, "yellow")}genta")}")}\n'
3764 \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)
3767 \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)
3765
3768
3766 pad() should interact well with color codes (issue5416)
3769 pad() should interact well with color codes (issue5416)
3767
3770
3768 $ hg debugtemplate --color=always \
3771 $ hg debugtemplate --color=always \
3769 > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n'
3772 > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n'
3770 \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc)
3773 \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc)
3771
3774
3772 label should be no-op if color is disabled:
3775 label should be no-op if color is disabled:
3773
3776
3774 $ hg log --color=never -l 1 --template '{label(red, "text\n")}'
3777 $ hg log --color=never -l 1 --template '{label(red, "text\n")}'
3775 text
3778 text
3776 $ hg log --config extensions.color=! -l 1 --template '{label(red, "text\n")}'
3779 $ hg log --config extensions.color=! -l 1 --template '{label(red, "text\n")}'
3777 text
3780 text
3778
3781
3779 Test branches inside if statement:
3782 Test branches inside if statement:
3780
3783
3781 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
3784 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
3782 no
3785 no
3783
3786
3784 Test dict constructor:
3787 Test dict constructor:
3785
3788
3786 $ hg log -r 0 -T '{dict(y=node|short, x=rev)}\n'
3789 $ hg log -r 0 -T '{dict(y=node|short, x=rev)}\n'
3787 y=f7769ec2ab97 x=0
3790 y=f7769ec2ab97 x=0
3788 $ hg log -r 0 -T '{dict(x=rev, y=node|short) % "{key}={value}\n"}'
3791 $ hg log -r 0 -T '{dict(x=rev, y=node|short) % "{key}={value}\n"}'
3789 x=0
3792 x=0
3790 y=f7769ec2ab97
3793 y=f7769ec2ab97
3791 $ hg log -r 0 -T '{dict(x=rev, y=node|short)|json}\n'
3794 $ hg log -r 0 -T '{dict(x=rev, y=node|short)|json}\n'
3792 {"x": 0, "y": "f7769ec2ab97"}
3795 {"x": 0, "y": "f7769ec2ab97"}
3793 $ hg log -r 0 -T '{dict()|json}\n'
3796 $ hg log -r 0 -T '{dict()|json}\n'
3794 {}
3797 {}
3795
3798
3796 $ hg log -r 0 -T '{dict(rev, node=node|short)}\n'
3799 $ hg log -r 0 -T '{dict(rev, node=node|short)}\n'
3797 rev=0 node=f7769ec2ab97
3800 rev=0 node=f7769ec2ab97
3798 $ hg log -r 0 -T '{dict(rev, node|short)}\n'
3801 $ hg log -r 0 -T '{dict(rev, node|short)}\n'
3799 rev=0 node=f7769ec2ab97
3802 rev=0 node=f7769ec2ab97
3800
3803
3801 $ hg log -r 0 -T '{dict(rev, rev=rev)}\n'
3804 $ hg log -r 0 -T '{dict(rev, rev=rev)}\n'
3802 hg: parse error: duplicated dict key 'rev' inferred
3805 hg: parse error: duplicated dict key 'rev' inferred
3803 [255]
3806 [255]
3804 $ hg log -r 0 -T '{dict(node, node|short)}\n'
3807 $ hg log -r 0 -T '{dict(node, node|short)}\n'
3805 hg: parse error: duplicated dict key 'node' inferred
3808 hg: parse error: duplicated dict key 'node' inferred
3806 [255]
3809 [255]
3807 $ hg log -r 0 -T '{dict(1 + 2)}'
3810 $ hg log -r 0 -T '{dict(1 + 2)}'
3808 hg: parse error: dict key cannot be inferred
3811 hg: parse error: dict key cannot be inferred
3809 [255]
3812 [255]
3810
3813
3811 $ hg log -r 0 -T '{dict(x=rev, x=node)}'
3814 $ hg log -r 0 -T '{dict(x=rev, x=node)}'
3812 hg: parse error: dict got multiple values for keyword argument 'x'
3815 hg: parse error: dict got multiple values for keyword argument 'x'
3813 [255]
3816 [255]
3814
3817
3815 Test get function:
3818 Test get function:
3816
3819
3817 $ hg log -r 0 --template '{get(extras, "branch")}\n'
3820 $ hg log -r 0 --template '{get(extras, "branch")}\n'
3818 default
3821 default
3819 $ hg log -r 0 --template '{get(extras, "br{"anch"}")}\n'
3822 $ hg log -r 0 --template '{get(extras, "br{"anch"}")}\n'
3820 default
3823 default
3821 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3824 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3822 hg: parse error: get() expects a dict as first argument
3825 hg: parse error: get() expects a dict as first argument
3823 [255]
3826 [255]
3824
3827
3825 Test json filter applied to hybrid object:
3828 Test json filter applied to hybrid object:
3826
3829
3827 $ hg log -r0 -T '{files|json}\n'
3830 $ hg log -r0 -T '{files|json}\n'
3828 ["a"]
3831 ["a"]
3829 $ hg log -r0 -T '{extras|json}\n'
3832 $ hg log -r0 -T '{extras|json}\n'
3830 {"branch": "default"}
3833 {"branch": "default"}
3831
3834
3832 Test localdate(date, tz) function:
3835 Test localdate(date, tz) function:
3833
3836
3834 $ TZ=JST-09 hg log -r0 -T '{date|localdate|isodate}\n'
3837 $ TZ=JST-09 hg log -r0 -T '{date|localdate|isodate}\n'
3835 1970-01-01 09:00 +0900
3838 1970-01-01 09:00 +0900
3836 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "UTC")|isodate}\n'
3839 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "UTC")|isodate}\n'
3837 1970-01-01 00:00 +0000
3840 1970-01-01 00:00 +0000
3838 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n'
3841 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n'
3839 hg: parse error: localdate expects a timezone
3842 hg: parse error: localdate expects a timezone
3840 [255]
3843 [255]
3841 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n'
3844 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n'
3842 1970-01-01 02:00 +0200
3845 1970-01-01 02:00 +0200
3843 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n'
3846 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n'
3844 1970-01-01 00:00 +0000
3847 1970-01-01 00:00 +0000
3845 $ TZ=JST-09 hg log -r0 -T '{localdate(date, 0)|isodate}\n'
3848 $ TZ=JST-09 hg log -r0 -T '{localdate(date, 0)|isodate}\n'
3846 1970-01-01 00:00 +0000
3849 1970-01-01 00:00 +0000
3847 $ hg log -r0 -T '{localdate(date, "invalid")|isodate}\n'
3850 $ hg log -r0 -T '{localdate(date, "invalid")|isodate}\n'
3848 hg: parse error: localdate expects a timezone
3851 hg: parse error: localdate expects a timezone
3849 [255]
3852 [255]
3850 $ hg log -r0 -T '{localdate(date, date)|isodate}\n'
3853 $ hg log -r0 -T '{localdate(date, date)|isodate}\n'
3851 hg: parse error: localdate expects a timezone
3854 hg: parse error: localdate expects a timezone
3852 [255]
3855 [255]
3853
3856
3854 Test shortest(node) function:
3857 Test shortest(node) function:
3855
3858
3856 $ echo b > b
3859 $ echo b > b
3857 $ hg ci -qAm b
3860 $ hg ci -qAm b
3858 $ hg log --template '{shortest(node)}\n'
3861 $ hg log --template '{shortest(node)}\n'
3859 e777
3862 e777
3860 bcc7
3863 bcc7
3861 f776
3864 f776
3862 $ hg log --template '{shortest(node, 10)}\n'
3865 $ hg log --template '{shortest(node, 10)}\n'
3863 e777603221
3866 e777603221
3864 bcc7ff960b
3867 bcc7ff960b
3865 f7769ec2ab
3868 f7769ec2ab
3866 $ hg log --template '{node|shortest}\n' -l1
3869 $ hg log --template '{node|shortest}\n' -l1
3867 e777
3870 e777
3868
3871
3869 $ hg log -r 0 -T '{shortest(node, "1{"0"}")}\n'
3872 $ hg log -r 0 -T '{shortest(node, "1{"0"}")}\n'
3870 f7769ec2ab
3873 f7769ec2ab
3871 $ hg log -r 0 -T '{shortest(node, "not an int")}\n'
3874 $ hg log -r 0 -T '{shortest(node, "not an int")}\n'
3872 hg: parse error: shortest() expects an integer minlength
3875 hg: parse error: shortest() expects an integer minlength
3873 [255]
3876 [255]
3874
3877
3875 $ hg log -r 'wdir()' -T '{node|shortest}\n'
3878 $ hg log -r 'wdir()' -T '{node|shortest}\n'
3876 ffff
3879 ffff
3877
3880
3878 $ cd ..
3881 $ cd ..
3879
3882
3880 Test shortest(node) with the repo having short hash collision:
3883 Test shortest(node) with the repo having short hash collision:
3881
3884
3882 $ hg init hashcollision
3885 $ hg init hashcollision
3883 $ cd hashcollision
3886 $ cd hashcollision
3884 $ cat <<EOF >> .hg/hgrc
3887 $ cat <<EOF >> .hg/hgrc
3885 > [experimental]
3888 > [experimental]
3886 > evolution.createmarkers=True
3889 > evolution.createmarkers=True
3887 > EOF
3890 > EOF
3888 $ echo 0 > a
3891 $ echo 0 > a
3889 $ hg ci -qAm 0
3892 $ hg ci -qAm 0
3890 $ for i in 17 129 248 242 480 580 617 1057 2857 4025; do
3893 $ for i in 17 129 248 242 480 580 617 1057 2857 4025; do
3891 > hg up -q 0
3894 > hg up -q 0
3892 > echo $i > a
3895 > echo $i > a
3893 > hg ci -qm $i
3896 > hg ci -qm $i
3894 > done
3897 > done
3895 $ hg up -q null
3898 $ hg up -q null
3896 $ hg log -r0: -T '{rev}:{node}\n'
3899 $ hg log -r0: -T '{rev}:{node}\n'
3897 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
3900 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
3898 1:11424df6dc1dd4ea255eae2b58eaca7831973bbc
3901 1:11424df6dc1dd4ea255eae2b58eaca7831973bbc
3899 2:11407b3f1b9c3e76a79c1ec5373924df096f0499
3902 2:11407b3f1b9c3e76a79c1ec5373924df096f0499
3900 3:11dd92fe0f39dfdaacdaa5f3997edc533875cfc4
3903 3:11dd92fe0f39dfdaacdaa5f3997edc533875cfc4
3901 4:10776689e627b465361ad5c296a20a487e153ca4
3904 4:10776689e627b465361ad5c296a20a487e153ca4
3902 5:a00be79088084cb3aff086ab799f8790e01a976b
3905 5:a00be79088084cb3aff086ab799f8790e01a976b
3903 6:a0b0acd79b4498d0052993d35a6a748dd51d13e6
3906 6:a0b0acd79b4498d0052993d35a6a748dd51d13e6
3904 7:a0457b3450b8e1b778f1163b31a435802987fe5d
3907 7:a0457b3450b8e1b778f1163b31a435802987fe5d
3905 8:c56256a09cd28e5764f32e8e2810d0f01e2e357a
3908 8:c56256a09cd28e5764f32e8e2810d0f01e2e357a
3906 9:c5623987d205cd6d9d8389bfc40fff9dbb670b48
3909 9:c5623987d205cd6d9d8389bfc40fff9dbb670b48
3907 10:c562ddd9c94164376c20b86b0b4991636a3bf84f
3910 10:c562ddd9c94164376c20b86b0b4991636a3bf84f
3908 $ hg debugobsolete a00be79088084cb3aff086ab799f8790e01a976b
3911 $ hg debugobsolete a00be79088084cb3aff086ab799f8790e01a976b
3909 obsoleted 1 changesets
3912 obsoleted 1 changesets
3910 $ hg debugobsolete c5623987d205cd6d9d8389bfc40fff9dbb670b48
3913 $ hg debugobsolete c5623987d205cd6d9d8389bfc40fff9dbb670b48
3911 obsoleted 1 changesets
3914 obsoleted 1 changesets
3912 $ hg debugobsolete c562ddd9c94164376c20b86b0b4991636a3bf84f
3915 $ hg debugobsolete c562ddd9c94164376c20b86b0b4991636a3bf84f
3913 obsoleted 1 changesets
3916 obsoleted 1 changesets
3914
3917
3915 nodes starting with '11' (we don't have the revision number '11' though)
3918 nodes starting with '11' (we don't have the revision number '11' though)
3916
3919
3917 $ hg log -r 1:3 -T '{rev}:{shortest(node, 0)}\n'
3920 $ hg log -r 1:3 -T '{rev}:{shortest(node, 0)}\n'
3918 1:1142
3921 1:1142
3919 2:1140
3922 2:1140
3920 3:11d
3923 3:11d
3921
3924
3922 '5:a00' is hidden, but still we have two nodes starting with 'a0'
3925 '5:a00' is hidden, but still we have two nodes starting with 'a0'
3923
3926
3924 $ hg log -r 6:7 -T '{rev}:{shortest(node, 0)}\n'
3927 $ hg log -r 6:7 -T '{rev}:{shortest(node, 0)}\n'
3925 6:a0b
3928 6:a0b
3926 7:a04
3929 7:a04
3927
3930
3928 node '10' conflicts with the revision number '10' even if it is hidden
3931 node '10' conflicts with the revision number '10' even if it is hidden
3929 (we could exclude hidden revision numbers, but currently we don't)
3932 (we could exclude hidden revision numbers, but currently we don't)
3930
3933
3931 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n'
3934 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n'
3932 4:107
3935 4:107
3933 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
3936 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
3934 4:107
3937 4:107
3935
3938
3936 node 'c562' should be unique if the other 'c562' nodes are hidden
3939 node 'c562' should be unique if the other 'c562' nodes are hidden
3937 (but we don't try the slow path to filter out hidden nodes for now)
3940 (but we don't try the slow path to filter out hidden nodes for now)
3938
3941
3939 $ hg log -r 8 -T '{rev}:{node|shortest}\n'
3942 $ hg log -r 8 -T '{rev}:{node|shortest}\n'
3940 8:c5625
3943 8:c5625
3941 $ hg log -r 8:10 -T '{rev}:{node|shortest}\n' --hidden
3944 $ hg log -r 8:10 -T '{rev}:{node|shortest}\n' --hidden
3942 8:c5625
3945 8:c5625
3943 9:c5623
3946 9:c5623
3944 10:c562d
3947 10:c562d
3945
3948
3946 $ cd ..
3949 $ cd ..
3947
3950
3948 Test pad function
3951 Test pad function
3949
3952
3950 $ cd r
3953 $ cd r
3951
3954
3952 $ hg log --template '{pad(rev, 20)} {author|user}\n'
3955 $ hg log --template '{pad(rev, 20)} {author|user}\n'
3953 2 test
3956 2 test
3954 1 {node|short}
3957 1 {node|short}
3955 0 test
3958 0 test
3956
3959
3957 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
3960 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
3958 2 test
3961 2 test
3959 1 {node|short}
3962 1 {node|short}
3960 0 test
3963 0 test
3961
3964
3962 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
3965 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
3963 2------------------- test
3966 2------------------- test
3964 1------------------- {node|short}
3967 1------------------- {node|short}
3965 0------------------- test
3968 0------------------- test
3966
3969
3967 Test template string in pad function
3970 Test template string in pad function
3968
3971
3969 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
3972 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
3970 {0} test
3973 {0} test
3971
3974
3972 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
3975 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
3973 \{rev} test
3976 \{rev} test
3974
3977
3975 Test width argument passed to pad function
3978 Test width argument passed to pad function
3976
3979
3977 $ hg log -r 0 -T '{pad(rev, "1{"0"}")} {author|user}\n'
3980 $ hg log -r 0 -T '{pad(rev, "1{"0"}")} {author|user}\n'
3978 0 test
3981 0 test
3979 $ hg log -r 0 -T '{pad(rev, "not an int")}\n'
3982 $ hg log -r 0 -T '{pad(rev, "not an int")}\n'
3980 hg: parse error: pad() expects an integer width
3983 hg: parse error: pad() expects an integer width
3981 [255]
3984 [255]
3982
3985
3983 Test invalid fillchar passed to pad function
3986 Test invalid fillchar passed to pad function
3984
3987
3985 $ hg log -r 0 -T '{pad(rev, 10, "")}\n'
3988 $ hg log -r 0 -T '{pad(rev, 10, "")}\n'
3986 hg: parse error: pad() expects a single fill character
3989 hg: parse error: pad() expects a single fill character
3987 [255]
3990 [255]
3988 $ hg log -r 0 -T '{pad(rev, 10, "--")}\n'
3991 $ hg log -r 0 -T '{pad(rev, 10, "--")}\n'
3989 hg: parse error: pad() expects a single fill character
3992 hg: parse error: pad() expects a single fill character
3990 [255]
3993 [255]
3991
3994
3992 Test boolean argument passed to pad function
3995 Test boolean argument passed to pad function
3993
3996
3994 no crash
3997 no crash
3995
3998
3996 $ hg log -r 0 -T '{pad(rev, 10, "-", "f{"oo"}")}\n'
3999 $ hg log -r 0 -T '{pad(rev, 10, "-", "f{"oo"}")}\n'
3997 ---------0
4000 ---------0
3998
4001
3999 string/literal
4002 string/literal
4000
4003
4001 $ hg log -r 0 -T '{pad(rev, 10, "-", "false")}\n'
4004 $ hg log -r 0 -T '{pad(rev, 10, "-", "false")}\n'
4002 ---------0
4005 ---------0
4003 $ hg log -r 0 -T '{pad(rev, 10, "-", false)}\n'
4006 $ hg log -r 0 -T '{pad(rev, 10, "-", false)}\n'
4004 0---------
4007 0---------
4005 $ hg log -r 0 -T '{pad(rev, 10, "-", "")}\n'
4008 $ hg log -r 0 -T '{pad(rev, 10, "-", "")}\n'
4006 0---------
4009 0---------
4007
4010
4008 unknown keyword is evaluated to ''
4011 unknown keyword is evaluated to ''
4009
4012
4010 $ hg log -r 0 -T '{pad(rev, 10, "-", unknownkeyword)}\n'
4013 $ hg log -r 0 -T '{pad(rev, 10, "-", unknownkeyword)}\n'
4011 0---------
4014 0---------
4012
4015
4013 Test separate function
4016 Test separate function
4014
4017
4015 $ hg log -r 0 -T '{separate("-", "", "a", "b", "", "", "c", "")}\n'
4018 $ hg log -r 0 -T '{separate("-", "", "a", "b", "", "", "c", "")}\n'
4016 a-b-c
4019 a-b-c
4017 $ hg log -r 0 -T '{separate(" ", "{rev}:{node|short}", author|user, branch)}\n'
4020 $ hg log -r 0 -T '{separate(" ", "{rev}:{node|short}", author|user, branch)}\n'
4018 0:f7769ec2ab97 test default
4021 0:f7769ec2ab97 test default
4019 $ hg log -r 0 --color=always -T '{separate(" ", "a", label(red, "b"), "c", label(red, ""), "d")}\n'
4022 $ hg log -r 0 --color=always -T '{separate(" ", "a", label(red, "b"), "c", label(red, ""), "d")}\n'
4020 a \x1b[0;31mb\x1b[0m c d (esc)
4023 a \x1b[0;31mb\x1b[0m c d (esc)
4021
4024
4022 Test boolean expression/literal passed to if function
4025 Test boolean expression/literal passed to if function
4023
4026
4024 $ hg log -r 0 -T '{if(rev, "rev 0 is True")}\n'
4027 $ hg log -r 0 -T '{if(rev, "rev 0 is True")}\n'
4025 rev 0 is True
4028 rev 0 is True
4026 $ hg log -r 0 -T '{if(0, "literal 0 is True as well")}\n'
4029 $ hg log -r 0 -T '{if(0, "literal 0 is True as well")}\n'
4027 literal 0 is True as well
4030 literal 0 is True as well
4028 $ hg log -r 0 -T '{if("", "", "empty string is False")}\n'
4031 $ hg log -r 0 -T '{if("", "", "empty string is False")}\n'
4029 empty string is False
4032 empty string is False
4030 $ hg log -r 0 -T '{if(revset(r"0 - 0"), "", "empty list is False")}\n'
4033 $ hg log -r 0 -T '{if(revset(r"0 - 0"), "", "empty list is False")}\n'
4031 empty list is False
4034 empty list is False
4032 $ hg log -r 0 -T '{if(true, "true is True")}\n'
4035 $ hg log -r 0 -T '{if(true, "true is True")}\n'
4033 true is True
4036 true is True
4034 $ hg log -r 0 -T '{if(false, "", "false is False")}\n'
4037 $ hg log -r 0 -T '{if(false, "", "false is False")}\n'
4035 false is False
4038 false is False
4036 $ hg log -r 0 -T '{if("false", "non-empty string is True")}\n'
4039 $ hg log -r 0 -T '{if("false", "non-empty string is True")}\n'
4037 non-empty string is True
4040 non-empty string is True
4038
4041
4039 Test ifcontains function
4042 Test ifcontains function
4040
4043
4041 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
4044 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
4042 2 is in the string
4045 2 is in the string
4043 1 is not
4046 1 is not
4044 0 is in the string
4047 0 is in the string
4045
4048
4046 $ hg log -T '{rev} {ifcontains(rev, "2 two{" 0"}", "is in the string", "is not")}\n'
4049 $ hg log -T '{rev} {ifcontains(rev, "2 two{" 0"}", "is in the string", "is not")}\n'
4047 2 is in the string
4050 2 is in the string
4048 1 is not
4051 1 is not
4049 0 is in the string
4052 0 is in the string
4050
4053
4051 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
4054 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
4052 2 did not add a
4055 2 did not add a
4053 1 did not add a
4056 1 did not add a
4054 0 added a
4057 0 added a
4055
4058
4056 $ hg log --debug -T '{rev}{ifcontains(1, parents, " is parent of 1")}\n'
4059 $ hg log --debug -T '{rev}{ifcontains(1, parents, " is parent of 1")}\n'
4057 2 is parent of 1
4060 2 is parent of 1
4058 1
4061 1
4059 0
4062 0
4060
4063
4061 Test revset function
4064 Test revset function
4062
4065
4063 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
4066 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
4064 2 current rev
4067 2 current rev
4065 1 not current rev
4068 1 not current rev
4066 0 not current rev
4069 0 not current rev
4067
4070
4068 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
4071 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
4069 2 match rev
4072 2 match rev
4070 1 match rev
4073 1 match rev
4071 0 not match rev
4074 0 not match rev
4072
4075
4073 $ hg log -T '{ifcontains(desc, revset(":"), "", "type not match")}\n' -l1
4076 $ hg log -T '{ifcontains(desc, revset(":"), "", "type not match")}\n' -l1
4074 type not match
4077 type not match
4075
4078
4076 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
4079 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
4077 2 Parents: 1
4080 2 Parents: 1
4078 1 Parents: 0
4081 1 Parents: 0
4079 0 Parents:
4082 0 Parents:
4080
4083
4081 $ cat >> .hg/hgrc <<EOF
4084 $ cat >> .hg/hgrc <<EOF
4082 > [revsetalias]
4085 > [revsetalias]
4083 > myparents(\$1) = parents(\$1)
4086 > myparents(\$1) = parents(\$1)
4084 > EOF
4087 > EOF
4085 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
4088 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
4086 2 Parents: 1
4089 2 Parents: 1
4087 1 Parents: 0
4090 1 Parents: 0
4088 0 Parents:
4091 0 Parents:
4089
4092
4090 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
4093 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
4091 Rev: 2
4094 Rev: 2
4092 Ancestor: 0
4095 Ancestor: 0
4093 Ancestor: 1
4096 Ancestor: 1
4094 Ancestor: 2
4097 Ancestor: 2
4095
4098
4096 Rev: 1
4099 Rev: 1
4097 Ancestor: 0
4100 Ancestor: 0
4098 Ancestor: 1
4101 Ancestor: 1
4099
4102
4100 Rev: 0
4103 Rev: 0
4101 Ancestor: 0
4104 Ancestor: 0
4102
4105
4103 $ hg log --template '{revset("TIP"|lower)}\n' -l1
4106 $ hg log --template '{revset("TIP"|lower)}\n' -l1
4104 2
4107 2
4105
4108
4106 $ hg log -T '{revset("%s", "t{"ip"}")}\n' -l1
4109 $ hg log -T '{revset("%s", "t{"ip"}")}\n' -l1
4107 2
4110 2
4108
4111
4109 a list template is evaluated for each item of revset/parents
4112 a list template is evaluated for each item of revset/parents
4110
4113
4111 $ hg log -T '{rev} p: {revset("p1(%s)", rev) % "{rev}:{node|short}"}\n'
4114 $ hg log -T '{rev} p: {revset("p1(%s)", rev) % "{rev}:{node|short}"}\n'
4112 2 p: 1:bcc7ff960b8e
4115 2 p: 1:bcc7ff960b8e
4113 1 p: 0:f7769ec2ab97
4116 1 p: 0:f7769ec2ab97
4114 0 p:
4117 0 p:
4115
4118
4116 $ hg log --debug -T '{rev} p:{parents % " {rev}:{node|short}"}\n'
4119 $ hg log --debug -T '{rev} p:{parents % " {rev}:{node|short}"}\n'
4117 2 p: 1:bcc7ff960b8e -1:000000000000
4120 2 p: 1:bcc7ff960b8e -1:000000000000
4118 1 p: 0:f7769ec2ab97 -1:000000000000
4121 1 p: 0:f7769ec2ab97 -1:000000000000
4119 0 p: -1:000000000000 -1:000000000000
4122 0 p: -1:000000000000 -1:000000000000
4120
4123
4121 therefore, 'revcache' should be recreated for each rev
4124 therefore, 'revcache' should be recreated for each rev
4122
4125
4123 $ hg log -T '{rev} {file_adds}\np {revset("p1(%s)", rev) % "{file_adds}"}\n'
4126 $ hg log -T '{rev} {file_adds}\np {revset("p1(%s)", rev) % "{file_adds}"}\n'
4124 2 aa b
4127 2 aa b
4125 p
4128 p
4126 1
4129 1
4127 p a
4130 p a
4128 0 a
4131 0 a
4129 p
4132 p
4130
4133
4131 $ hg log --debug -T '{rev} {file_adds}\np {parents % "{file_adds}"}\n'
4134 $ hg log --debug -T '{rev} {file_adds}\np {parents % "{file_adds}"}\n'
4132 2 aa b
4135 2 aa b
4133 p
4136 p
4134 1
4137 1
4135 p a
4138 p a
4136 0 a
4139 0 a
4137 p
4140 p
4138
4141
4139 a revset item must be evaluated as an integer revision, not an offset from tip
4142 a revset item must be evaluated as an integer revision, not an offset from tip
4140
4143
4141 $ hg log -l 1 -T '{revset("null") % "{rev}:{node|short}"}\n'
4144 $ hg log -l 1 -T '{revset("null") % "{rev}:{node|short}"}\n'
4142 -1:000000000000
4145 -1:000000000000
4143 $ hg log -l 1 -T '{revset("%s", "null") % "{rev}:{node|short}"}\n'
4146 $ hg log -l 1 -T '{revset("%s", "null") % "{rev}:{node|short}"}\n'
4144 -1:000000000000
4147 -1:000000000000
4145
4148
4146 join() should pick '{rev}' from revset items:
4149 join() should pick '{rev}' from revset items:
4147
4150
4148 $ hg log -R ../a -T '{join(revset("parents(%d)", rev), ", ")}\n' -r6
4151 $ hg log -R ../a -T '{join(revset("parents(%d)", rev), ", ")}\n' -r6
4149 4, 5
4152 4, 5
4150
4153
4151 on the other hand, parents are formatted as '{rev}:{node|formatnode}' by
4154 on the other hand, parents are formatted as '{rev}:{node|formatnode}' by
4152 default. join() should agree with the default formatting:
4155 default. join() should agree with the default formatting:
4153
4156
4154 $ hg log -R ../a -T '{join(parents, ", ")}\n' -r6
4157 $ hg log -R ../a -T '{join(parents, ", ")}\n' -r6
4155 5:13207e5a10d9, 4:bbe44766e73d
4158 5:13207e5a10d9, 4:bbe44766e73d
4156
4159
4157 $ hg log -R ../a -T '{join(parents, ",\n")}\n' -r6 --debug
4160 $ hg log -R ../a -T '{join(parents, ",\n")}\n' -r6 --debug
4158 5:13207e5a10d9fd28ec424934298e176197f2c67f,
4161 5:13207e5a10d9fd28ec424934298e176197f2c67f,
4159 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
4162 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
4160
4163
4161 Invalid arguments passed to revset()
4164 Invalid arguments passed to revset()
4162
4165
4163 $ hg log -T '{revset("%whatever", 0)}\n'
4166 $ hg log -T '{revset("%whatever", 0)}\n'
4164 hg: parse error: unexpected revspec format character w
4167 hg: parse error: unexpected revspec format character w
4165 [255]
4168 [255]
4166 $ hg log -T '{revset("%lwhatever", files)}\n'
4169 $ hg log -T '{revset("%lwhatever", files)}\n'
4167 hg: parse error: unexpected revspec format character w
4170 hg: parse error: unexpected revspec format character w
4168 [255]
4171 [255]
4169 $ hg log -T '{revset("%s %s", 0)}\n'
4172 $ hg log -T '{revset("%s %s", 0)}\n'
4170 hg: parse error: missing argument for revspec
4173 hg: parse error: missing argument for revspec
4171 [255]
4174 [255]
4172 $ hg log -T '{revset("", 0)}\n'
4175 $ hg log -T '{revset("", 0)}\n'
4173 hg: parse error: too many revspec arguments specified
4176 hg: parse error: too many revspec arguments specified
4174 [255]
4177 [255]
4175 $ hg log -T '{revset("%s", 0, 1)}\n'
4178 $ hg log -T '{revset("%s", 0, 1)}\n'
4176 hg: parse error: too many revspec arguments specified
4179 hg: parse error: too many revspec arguments specified
4177 [255]
4180 [255]
4178 $ hg log -T '{revset("%", 0)}\n'
4181 $ hg log -T '{revset("%", 0)}\n'
4179 hg: parse error: incomplete revspec format character
4182 hg: parse error: incomplete revspec format character
4180 [255]
4183 [255]
4181 $ hg log -T '{revset("%l", 0)}\n'
4184 $ hg log -T '{revset("%l", 0)}\n'
4182 hg: parse error: incomplete revspec format character
4185 hg: parse error: incomplete revspec format character
4183 [255]
4186 [255]
4184 $ hg log -T '{revset("%d", 'foo')}\n'
4187 $ hg log -T '{revset("%d", 'foo')}\n'
4185 hg: parse error: invalid argument for revspec
4188 hg: parse error: invalid argument for revspec
4186 [255]
4189 [255]
4187 $ hg log -T '{revset("%ld", files)}\n'
4190 $ hg log -T '{revset("%ld", files)}\n'
4188 hg: parse error: invalid argument for revspec
4191 hg: parse error: invalid argument for revspec
4189 [255]
4192 [255]
4190 $ hg log -T '{revset("%ls", 0)}\n'
4193 $ hg log -T '{revset("%ls", 0)}\n'
4191 hg: parse error: invalid argument for revspec
4194 hg: parse error: invalid argument for revspec
4192 [255]
4195 [255]
4193 $ hg log -T '{revset("%b", 'foo')}\n'
4196 $ hg log -T '{revset("%b", 'foo')}\n'
4194 hg: parse error: invalid argument for revspec
4197 hg: parse error: invalid argument for revspec
4195 [255]
4198 [255]
4196 $ hg log -T '{revset("%lb", files)}\n'
4199 $ hg log -T '{revset("%lb", files)}\n'
4197 hg: parse error: invalid argument for revspec
4200 hg: parse error: invalid argument for revspec
4198 [255]
4201 [255]
4199 $ hg log -T '{revset("%r", 0)}\n'
4202 $ hg log -T '{revset("%r", 0)}\n'
4200 hg: parse error: invalid argument for revspec
4203 hg: parse error: invalid argument for revspec
4201 [255]
4204 [255]
4202
4205
4203 Test 'originalnode'
4206 Test 'originalnode'
4204
4207
4205 $ hg log -r 1 -T '{revset("null") % "{node|short} {originalnode|short}"}\n'
4208 $ hg log -r 1 -T '{revset("null") % "{node|short} {originalnode|short}"}\n'
4206 000000000000 bcc7ff960b8e
4209 000000000000 bcc7ff960b8e
4207 $ hg log -r 0 -T '{manifest % "{node} {originalnode}"}\n'
4210 $ hg log -r 0 -T '{manifest % "{node} {originalnode}"}\n'
4208 a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 f7769ec2ab975ad19684098ad1ffd9b81ecc71a1
4211 a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 f7769ec2ab975ad19684098ad1ffd9b81ecc71a1
4209
4212
4210 Test files function
4213 Test files function
4211
4214
4212 $ hg log -T "{rev}\n{join(files('*'), '\n')}\n"
4215 $ hg log -T "{rev}\n{join(files('*'), '\n')}\n"
4213 2
4216 2
4214 a
4217 a
4215 aa
4218 aa
4216 b
4219 b
4217 1
4220 1
4218 a
4221 a
4219 0
4222 0
4220 a
4223 a
4221
4224
4222 $ hg log -T "{rev}\n{join(files('aa'), '\n')}\n"
4225 $ hg log -T "{rev}\n{join(files('aa'), '\n')}\n"
4223 2
4226 2
4224 aa
4227 aa
4225 1
4228 1
4226
4229
4227 0
4230 0
4228
4231
4229
4232
4230 Test relpath function
4233 Test relpath function
4231
4234
4232 $ hg log -r0 -T '{files % "{file|relpath}\n"}'
4235 $ hg log -r0 -T '{files % "{file|relpath}\n"}'
4233 a
4236 a
4234 $ cd ..
4237 $ cd ..
4235 $ hg log -R r -r0 -T '{files % "{file|relpath}\n"}'
4238 $ hg log -R r -r0 -T '{files % "{file|relpath}\n"}'
4236 r/a
4239 r/a
4237 $ cd r
4240 $ cd r
4238
4241
4239 Test active bookmark templating
4242 Test active bookmark templating
4240
4243
4241 $ hg book foo
4244 $ hg book foo
4242 $ hg book bar
4245 $ hg book bar
4243 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
4246 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
4244 2 bar* foo
4247 2 bar* foo
4245 1
4248 1
4246 0
4249 0
4247 $ hg log --template "{rev} {activebookmark}\n"
4250 $ hg log --template "{rev} {activebookmark}\n"
4248 2 bar
4251 2 bar
4249 1
4252 1
4250 0
4253 0
4251 $ hg bookmarks --inactive bar
4254 $ hg bookmarks --inactive bar
4252 $ hg log --template "{rev} {activebookmark}\n"
4255 $ hg log --template "{rev} {activebookmark}\n"
4253 2
4256 2
4254 1
4257 1
4255 0
4258 0
4256 $ hg book -r1 baz
4259 $ hg book -r1 baz
4257 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
4260 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
4258 2 bar foo
4261 2 bar foo
4259 1 baz
4262 1 baz
4260 0
4263 0
4261 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
4264 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
4262 2 t
4265 2 t
4263 1 f
4266 1 f
4264 0 f
4267 0 f
4265
4268
4266 Test namespaces dict
4269 Test namespaces dict
4267
4270
4268 $ hg --config extensions.revnamesext=$TESTDIR/revnamesext.py log -T '{rev}\n{namespaces % " {namespace} color={colorname} builtin={builtin}\n {join(names, ",")}\n"}\n'
4271 $ hg --config extensions.revnamesext=$TESTDIR/revnamesext.py log -T '{rev}\n{namespaces % " {namespace} color={colorname} builtin={builtin}\n {join(names, ",")}\n"}\n'
4269 2
4272 2
4270 bookmarks color=bookmark builtin=True
4273 bookmarks color=bookmark builtin=True
4271 bar,foo
4274 bar,foo
4272 tags color=tag builtin=True
4275 tags color=tag builtin=True
4273 tip
4276 tip
4274 branches color=branch builtin=True
4277 branches color=branch builtin=True
4275 text.{rev}
4278 text.{rev}
4276 revnames color=revname builtin=False
4279 revnames color=revname builtin=False
4277 r2
4280 r2
4278
4281
4279 1
4282 1
4280 bookmarks color=bookmark builtin=True
4283 bookmarks color=bookmark builtin=True
4281 baz
4284 baz
4282 tags color=tag builtin=True
4285 tags color=tag builtin=True
4283
4286
4284 branches color=branch builtin=True
4287 branches color=branch builtin=True
4285 text.{rev}
4288 text.{rev}
4286 revnames color=revname builtin=False
4289 revnames color=revname builtin=False
4287 r1
4290 r1
4288
4291
4289 0
4292 0
4290 bookmarks color=bookmark builtin=True
4293 bookmarks color=bookmark builtin=True
4291
4294
4292 tags color=tag builtin=True
4295 tags color=tag builtin=True
4293
4296
4294 branches color=branch builtin=True
4297 branches color=branch builtin=True
4295 default
4298 default
4296 revnames color=revname builtin=False
4299 revnames color=revname builtin=False
4297 r0
4300 r0
4298
4301
4299 $ hg log -r2 -T '{namespaces % "{namespace}: {names}\n"}'
4302 $ hg log -r2 -T '{namespaces % "{namespace}: {names}\n"}'
4300 bookmarks: bar foo
4303 bookmarks: bar foo
4301 tags: tip
4304 tags: tip
4302 branches: text.{rev}
4305 branches: text.{rev}
4303 $ hg log -r2 -T '{namespaces % "{namespace}:\n{names % " {name}\n"}"}'
4306 $ hg log -r2 -T '{namespaces % "{namespace}:\n{names % " {name}\n"}"}'
4304 bookmarks:
4307 bookmarks:
4305 bar
4308 bar
4306 foo
4309 foo
4307 tags:
4310 tags:
4308 tip
4311 tip
4309 branches:
4312 branches:
4310 text.{rev}
4313 text.{rev}
4311 $ hg log -r2 -T '{get(namespaces, "bookmarks") % "{name}\n"}'
4314 $ hg log -r2 -T '{get(namespaces, "bookmarks") % "{name}\n"}'
4312 bar
4315 bar
4313 foo
4316 foo
4314 $ hg log -r2 -T '{namespaces.bookmarks % "{bookmark}\n"}'
4317 $ hg log -r2 -T '{namespaces.bookmarks % "{bookmark}\n"}'
4315 bar
4318 bar
4316 foo
4319 foo
4317
4320
4318 Test stringify on sub expressions
4321 Test stringify on sub expressions
4319
4322
4320 $ cd ..
4323 $ cd ..
4321 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
4324 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
4322 fourth, second, third
4325 fourth, second, third
4323 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
4326 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
4324 abc
4327 abc
4325
4328
4326 Test splitlines
4329 Test splitlines
4327
4330
4328 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
4331 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
4329 @ foo Modify, add, remove, rename
4332 @ foo Modify, add, remove, rename
4330 |
4333 |
4331 o foo future
4334 o foo future
4332 |
4335 |
4333 o foo third
4336 o foo third
4334 |
4337 |
4335 o foo second
4338 o foo second
4336
4339
4337 o foo merge
4340 o foo merge
4338 |\
4341 |\
4339 | o foo new head
4342 | o foo new head
4340 | |
4343 | |
4341 o | foo new branch
4344 o | foo new branch
4342 |/
4345 |/
4343 o foo no user, no domain
4346 o foo no user, no domain
4344 |
4347 |
4345 o foo no person
4348 o foo no person
4346 |
4349 |
4347 o foo other 1
4350 o foo other 1
4348 | foo other 2
4351 | foo other 2
4349 | foo
4352 | foo
4350 | foo other 3
4353 | foo other 3
4351 o foo line 1
4354 o foo line 1
4352 foo line 2
4355 foo line 2
4353
4356
4354 $ hg log -R a -r0 -T '{desc|splitlines}\n'
4357 $ hg log -R a -r0 -T '{desc|splitlines}\n'
4355 line 1 line 2
4358 line 1 line 2
4356 $ hg log -R a -r0 -T '{join(desc|splitlines, "|")}\n'
4359 $ hg log -R a -r0 -T '{join(desc|splitlines, "|")}\n'
4357 line 1|line 2
4360 line 1|line 2
4358
4361
4359 Test startswith
4362 Test startswith
4360 $ hg log -Gv -R a --template "{startswith(desc)}"
4363 $ hg log -Gv -R a --template "{startswith(desc)}"
4361 hg: parse error: startswith expects two arguments
4364 hg: parse error: startswith expects two arguments
4362 [255]
4365 [255]
4363
4366
4364 $ hg log -Gv -R a --template "{startswith('line', desc)}"
4367 $ hg log -Gv -R a --template "{startswith('line', desc)}"
4365 @
4368 @
4366 |
4369 |
4367 o
4370 o
4368 |
4371 |
4369 o
4372 o
4370 |
4373 |
4371 o
4374 o
4372
4375
4373 o
4376 o
4374 |\
4377 |\
4375 | o
4378 | o
4376 | |
4379 | |
4377 o |
4380 o |
4378 |/
4381 |/
4379 o
4382 o
4380 |
4383 |
4381 o
4384 o
4382 |
4385 |
4383 o
4386 o
4384 |
4387 |
4385 o line 1
4388 o line 1
4386 line 2
4389 line 2
4387
4390
4388 Test bad template with better error message
4391 Test bad template with better error message
4389
4392
4390 $ hg log -Gv -R a --template '{desc|user()}'
4393 $ hg log -Gv -R a --template '{desc|user()}'
4391 hg: parse error: expected a symbol, got 'func'
4394 hg: parse error: expected a symbol, got 'func'
4392 [255]
4395 [255]
4393
4396
4394 Test word function (including index out of bounds graceful failure)
4397 Test word function (including index out of bounds graceful failure)
4395
4398
4396 $ hg log -Gv -R a --template "{word('1', desc)}"
4399 $ hg log -Gv -R a --template "{word('1', desc)}"
4397 @ add,
4400 @ add,
4398 |
4401 |
4399 o
4402 o
4400 |
4403 |
4401 o
4404 o
4402 |
4405 |
4403 o
4406 o
4404
4407
4405 o
4408 o
4406 |\
4409 |\
4407 | o head
4410 | o head
4408 | |
4411 | |
4409 o | branch
4412 o | branch
4410 |/
4413 |/
4411 o user,
4414 o user,
4412 |
4415 |
4413 o person
4416 o person
4414 |
4417 |
4415 o 1
4418 o 1
4416 |
4419 |
4417 o 1
4420 o 1
4418
4421
4419
4422
4420 Test word third parameter used as splitter
4423 Test word third parameter used as splitter
4421
4424
4422 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
4425 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
4423 @ M
4426 @ M
4424 |
4427 |
4425 o future
4428 o future
4426 |
4429 |
4427 o third
4430 o third
4428 |
4431 |
4429 o sec
4432 o sec
4430
4433
4431 o merge
4434 o merge
4432 |\
4435 |\
4433 | o new head
4436 | o new head
4434 | |
4437 | |
4435 o | new branch
4438 o | new branch
4436 |/
4439 |/
4437 o n
4440 o n
4438 |
4441 |
4439 o n
4442 o n
4440 |
4443 |
4441 o
4444 o
4442 |
4445 |
4443 o line 1
4446 o line 1
4444 line 2
4447 line 2
4445
4448
4446 Test word error messages for not enough and too many arguments
4449 Test word error messages for not enough and too many arguments
4447
4450
4448 $ hg log -Gv -R a --template "{word('0')}"
4451 $ hg log -Gv -R a --template "{word('0')}"
4449 hg: parse error: word expects two or three arguments, got 1
4452 hg: parse error: word expects two or three arguments, got 1
4450 [255]
4453 [255]
4451
4454
4452 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
4455 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
4453 hg: parse error: word expects two or three arguments, got 7
4456 hg: parse error: word expects two or three arguments, got 7
4454 [255]
4457 [255]
4455
4458
4456 Test word for integer literal
4459 Test word for integer literal
4457
4460
4458 $ hg log -R a --template "{word(2, desc)}\n" -r0
4461 $ hg log -R a --template "{word(2, desc)}\n" -r0
4459 line
4462 line
4460
4463
4461 Test word for invalid numbers
4464 Test word for invalid numbers
4462
4465
4463 $ hg log -Gv -R a --template "{word('a', desc)}"
4466 $ hg log -Gv -R a --template "{word('a', desc)}"
4464 hg: parse error: word expects an integer index
4467 hg: parse error: word expects an integer index
4465 [255]
4468 [255]
4466
4469
4467 Test word for out of range
4470 Test word for out of range
4468
4471
4469 $ hg log -R a --template "{word(10000, desc)}"
4472 $ hg log -R a --template "{word(10000, desc)}"
4470 $ hg log -R a --template "{word(-10000, desc)}"
4473 $ hg log -R a --template "{word(-10000, desc)}"
4471
4474
4472 Test indent and not adding to empty lines
4475 Test indent and not adding to empty lines
4473
4476
4474 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
4477 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
4475 -----
4478 -----
4476 > line 1
4479 > line 1
4477 >> line 2
4480 >> line 2
4478 -----
4481 -----
4479 > other 1
4482 > other 1
4480 >> other 2
4483 >> other 2
4481
4484
4482 >> other 3
4485 >> other 3
4483
4486
4484 Test with non-strings like dates
4487 Test with non-strings like dates
4485
4488
4486 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
4489 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
4487 1200000.00
4490 1200000.00
4488 1300000.00
4491 1300000.00
4489
4492
4490 Test broken string escapes:
4493 Test broken string escapes:
4491
4494
4492 $ hg log -T "bogus\\" -R a
4495 $ hg log -T "bogus\\" -R a
4493 hg: parse error: trailing \ in string
4496 hg: parse error: trailing \ in string
4494 [255]
4497 [255]
4495 $ hg log -T "\\xy" -R a
4498 $ hg log -T "\\xy" -R a
4496 hg: parse error: invalid \x escape* (glob)
4499 hg: parse error: invalid \x escape* (glob)
4497 [255]
4500 [255]
4498
4501
4499 json filter should escape HTML tags so that the output can be embedded in hgweb:
4502 json filter should escape HTML tags so that the output can be embedded in hgweb:
4500
4503
4501 $ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1
4504 $ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1
4502 "\u003cfoo@example.org\u003e"
4505 "\u003cfoo@example.org\u003e"
4503
4506
4504 Templater supports aliases of symbol and func() styles:
4507 Templater supports aliases of symbol and func() styles:
4505
4508
4506 $ hg clone -q a aliases
4509 $ hg clone -q a aliases
4507 $ cd aliases
4510 $ cd aliases
4508 $ cat <<EOF >> .hg/hgrc
4511 $ cat <<EOF >> .hg/hgrc
4509 > [templatealias]
4512 > [templatealias]
4510 > r = rev
4513 > r = rev
4511 > rn = "{r}:{node|short}"
4514 > rn = "{r}:{node|short}"
4512 > status(c, files) = files % "{c} {file}\n"
4515 > status(c, files) = files % "{c} {file}\n"
4513 > utcdate(d) = localdate(d, "UTC")
4516 > utcdate(d) = localdate(d, "UTC")
4514 > EOF
4517 > EOF
4515
4518
4516 $ hg debugtemplate -vr0 '{rn} {utcdate(date)|isodate}\n'
4519 $ hg debugtemplate -vr0 '{rn} {utcdate(date)|isodate}\n'
4517 (template
4520 (template
4518 (symbol 'rn')
4521 (symbol 'rn')
4519 (string ' ')
4522 (string ' ')
4520 (|
4523 (|
4521 (func
4524 (func
4522 (symbol 'utcdate')
4525 (symbol 'utcdate')
4523 (symbol 'date'))
4526 (symbol 'date'))
4524 (symbol 'isodate'))
4527 (symbol 'isodate'))
4525 (string '\n'))
4528 (string '\n'))
4526 * expanded:
4529 * expanded:
4527 (template
4530 (template
4528 (template
4531 (template
4529 (symbol 'rev')
4532 (symbol 'rev')
4530 (string ':')
4533 (string ':')
4531 (|
4534 (|
4532 (symbol 'node')
4535 (symbol 'node')
4533 (symbol 'short')))
4536 (symbol 'short')))
4534 (string ' ')
4537 (string ' ')
4535 (|
4538 (|
4536 (func
4539 (func
4537 (symbol 'localdate')
4540 (symbol 'localdate')
4538 (list
4541 (list
4539 (symbol 'date')
4542 (symbol 'date')
4540 (string 'UTC')))
4543 (string 'UTC')))
4541 (symbol 'isodate'))
4544 (symbol 'isodate'))
4542 (string '\n'))
4545 (string '\n'))
4543 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4546 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4544
4547
4545 $ hg debugtemplate -vr0 '{status("A", file_adds)}'
4548 $ hg debugtemplate -vr0 '{status("A", file_adds)}'
4546 (template
4549 (template
4547 (func
4550 (func
4548 (symbol 'status')
4551 (symbol 'status')
4549 (list
4552 (list
4550 (string 'A')
4553 (string 'A')
4551 (symbol 'file_adds'))))
4554 (symbol 'file_adds'))))
4552 * expanded:
4555 * expanded:
4553 (template
4556 (template
4554 (%
4557 (%
4555 (symbol 'file_adds')
4558 (symbol 'file_adds')
4556 (template
4559 (template
4557 (string 'A')
4560 (string 'A')
4558 (string ' ')
4561 (string ' ')
4559 (symbol 'file')
4562 (symbol 'file')
4560 (string '\n'))))
4563 (string '\n'))))
4561 A a
4564 A a
4562
4565
4563 A unary function alias can be called as a filter:
4566 A unary function alias can be called as a filter:
4564
4567
4565 $ hg debugtemplate -vr0 '{date|utcdate|isodate}\n'
4568 $ hg debugtemplate -vr0 '{date|utcdate|isodate}\n'
4566 (template
4569 (template
4567 (|
4570 (|
4568 (|
4571 (|
4569 (symbol 'date')
4572 (symbol 'date')
4570 (symbol 'utcdate'))
4573 (symbol 'utcdate'))
4571 (symbol 'isodate'))
4574 (symbol 'isodate'))
4572 (string '\n'))
4575 (string '\n'))
4573 * expanded:
4576 * expanded:
4574 (template
4577 (template
4575 (|
4578 (|
4576 (func
4579 (func
4577 (symbol 'localdate')
4580 (symbol 'localdate')
4578 (list
4581 (list
4579 (symbol 'date')
4582 (symbol 'date')
4580 (string 'UTC')))
4583 (string 'UTC')))
4581 (symbol 'isodate'))
4584 (symbol 'isodate'))
4582 (string '\n'))
4585 (string '\n'))
4583 1970-01-12 13:46 +0000
4586 1970-01-12 13:46 +0000
4584
4587
4585 Aliases should be applied only to command arguments and templates in hgrc.
4588 Aliases should be applied only to command arguments and templates in hgrc.
4586 Otherwise, our stock styles and web templates could be corrupted:
4589 Otherwise, our stock styles and web templates could be corrupted:
4587
4590
4588 $ hg log -r0 -T '{rn} {utcdate(date)|isodate}\n'
4591 $ hg log -r0 -T '{rn} {utcdate(date)|isodate}\n'
4589 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4592 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4590
4593
4591 $ hg log -r0 --config ui.logtemplate='"{rn} {utcdate(date)|isodate}\n"'
4594 $ hg log -r0 --config ui.logtemplate='"{rn} {utcdate(date)|isodate}\n"'
4592 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4595 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4593
4596
4594 $ cat <<EOF > tmpl
4597 $ cat <<EOF > tmpl
4595 > changeset = 'nothing expanded:{rn}\n'
4598 > changeset = 'nothing expanded:{rn}\n'
4596 > EOF
4599 > EOF
4597 $ hg log -r0 --style ./tmpl
4600 $ hg log -r0 --style ./tmpl
4598 nothing expanded:
4601 nothing expanded:
4599
4602
4600 Aliases in formatter:
4603 Aliases in formatter:
4601
4604
4602 $ hg branches -T '{pad(branch, 7)} {rn}\n'
4605 $ hg branches -T '{pad(branch, 7)} {rn}\n'
4603 default 6:d41e714fe50d
4606 default 6:d41e714fe50d
4604 foo 4:bbe44766e73d
4607 foo 4:bbe44766e73d
4605
4608
4606 Aliases should honor HGPLAIN:
4609 Aliases should honor HGPLAIN:
4607
4610
4608 $ HGPLAIN= hg log -r0 -T 'nothing expanded:{rn}\n'
4611 $ HGPLAIN= hg log -r0 -T 'nothing expanded:{rn}\n'
4609 nothing expanded:
4612 nothing expanded:
4610 $ HGPLAINEXCEPT=templatealias hg log -r0 -T '{rn}\n'
4613 $ HGPLAINEXCEPT=templatealias hg log -r0 -T '{rn}\n'
4611 0:1e4e1b8f71e0
4614 0:1e4e1b8f71e0
4612
4615
4613 Unparsable alias:
4616 Unparsable alias:
4614
4617
4615 $ hg debugtemplate --config templatealias.bad='x(' -v '{bad}'
4618 $ hg debugtemplate --config templatealias.bad='x(' -v '{bad}'
4616 (template
4619 (template
4617 (symbol 'bad'))
4620 (symbol 'bad'))
4618 abort: bad definition of template alias "bad": at 2: not a prefix: end
4621 abort: bad definition of template alias "bad": at 2: not a prefix: end
4619 [255]
4622 [255]
4620 $ hg log --config templatealias.bad='x(' -T '{bad}'
4623 $ hg log --config templatealias.bad='x(' -T '{bad}'
4621 abort: bad definition of template alias "bad": at 2: not a prefix: end
4624 abort: bad definition of template alias "bad": at 2: not a prefix: end
4622 [255]
4625 [255]
4623
4626
4624 $ cd ..
4627 $ cd ..
4625
4628
4626 Set up repository for non-ascii encoding tests:
4629 Set up repository for non-ascii encoding tests:
4627
4630
4628 $ hg init nonascii
4631 $ hg init nonascii
4629 $ cd nonascii
4632 $ cd nonascii
4630 $ $PYTHON <<EOF
4633 $ $PYTHON <<EOF
4631 > open('latin1', 'wb').write(b'\xe9')
4634 > open('latin1', 'wb').write(b'\xe9')
4632 > open('utf-8', 'wb').write(b'\xc3\xa9')
4635 > open('utf-8', 'wb').write(b'\xc3\xa9')
4633 > EOF
4636 > EOF
4634 $ HGENCODING=utf-8 hg branch -q `cat utf-8`
4637 $ HGENCODING=utf-8 hg branch -q `cat utf-8`
4635 $ HGENCODING=utf-8 hg ci -qAm "non-ascii branch: `cat utf-8`" utf-8
4638 $ HGENCODING=utf-8 hg ci -qAm "non-ascii branch: `cat utf-8`" utf-8
4636
4639
4637 json filter should try round-trip conversion to utf-8:
4640 json filter should try round-trip conversion to utf-8:
4638
4641
4639 $ HGENCODING=ascii hg log -T "{branch|json}\n" -r0
4642 $ HGENCODING=ascii hg log -T "{branch|json}\n" -r0
4640 "\u00e9"
4643 "\u00e9"
4641 $ HGENCODING=ascii hg log -T "{desc|json}\n" -r0
4644 $ HGENCODING=ascii hg log -T "{desc|json}\n" -r0
4642 "non-ascii branch: \u00e9"
4645 "non-ascii branch: \u00e9"
4643
4646
4644 json filter takes input as utf-8b:
4647 json filter takes input as utf-8b:
4645
4648
4646 $ HGENCODING=ascii hg log -T "{'`cat utf-8`'|json}\n" -l1
4649 $ HGENCODING=ascii hg log -T "{'`cat utf-8`'|json}\n" -l1
4647 "\u00e9"
4650 "\u00e9"
4648 $ HGENCODING=ascii hg log -T "{'`cat latin1`'|json}\n" -l1
4651 $ HGENCODING=ascii hg log -T "{'`cat latin1`'|json}\n" -l1
4649 "\udce9"
4652 "\udce9"
4650
4653
4651 utf8 filter:
4654 utf8 filter:
4652
4655
4653 $ HGENCODING=ascii hg log -T "round-trip: {branch|utf8|hex}\n" -r0
4656 $ HGENCODING=ascii hg log -T "round-trip: {branch|utf8|hex}\n" -r0
4654 round-trip: c3a9
4657 round-trip: c3a9
4655 $ HGENCODING=latin1 hg log -T "decoded: {'`cat latin1`'|utf8|hex}\n" -l1
4658 $ HGENCODING=latin1 hg log -T "decoded: {'`cat latin1`'|utf8|hex}\n" -l1
4656 decoded: c3a9
4659 decoded: c3a9
4657 $ HGENCODING=ascii hg log -T "replaced: {'`cat latin1`'|utf8|hex}\n" -l1
4660 $ HGENCODING=ascii hg log -T "replaced: {'`cat latin1`'|utf8|hex}\n" -l1
4658 abort: decoding near * (glob)
4661 abort: decoding near * (glob)
4659 [255]
4662 [255]
4660 $ hg log -T "coerced to string: {rev|utf8}\n" -r0
4663 $ hg log -T "coerced to string: {rev|utf8}\n" -r0
4661 coerced to string: 0
4664 coerced to string: 0
4662
4665
4663 pad width:
4666 pad width:
4664
4667
4665 $ HGENCODING=utf-8 hg debugtemplate "{pad('`cat utf-8`', 2, '-')}\n"
4668 $ HGENCODING=utf-8 hg debugtemplate "{pad('`cat utf-8`', 2, '-')}\n"
4666 \xc3\xa9- (esc)
4669 \xc3\xa9- (esc)
4667
4670
4668 $ cd ..
4671 $ cd ..
4669
4672
4670 Test that template function in extension is registered as expected
4673 Test that template function in extension is registered as expected
4671
4674
4672 $ cd a
4675 $ cd a
4673
4676
4674 $ cat <<EOF > $TESTTMP/customfunc.py
4677 $ cat <<EOF > $TESTTMP/customfunc.py
4675 > from mercurial import registrar
4678 > from mercurial import registrar
4676 >
4679 >
4677 > templatefunc = registrar.templatefunc()
4680 > templatefunc = registrar.templatefunc()
4678 >
4681 >
4679 > @templatefunc(b'custom()')
4682 > @templatefunc(b'custom()')
4680 > def custom(context, mapping, args):
4683 > def custom(context, mapping, args):
4681 > return b'custom'
4684 > return b'custom'
4682 > EOF
4685 > EOF
4683 $ cat <<EOF > .hg/hgrc
4686 $ cat <<EOF > .hg/hgrc
4684 > [extensions]
4687 > [extensions]
4685 > customfunc = $TESTTMP/customfunc.py
4688 > customfunc = $TESTTMP/customfunc.py
4686 > EOF
4689 > EOF
4687
4690
4688 $ hg log -r . -T "{custom()}\n" --config customfunc.enabled=true
4691 $ hg log -r . -T "{custom()}\n" --config customfunc.enabled=true
4689 custom
4692 custom
4690
4693
4691 $ cd ..
4694 $ cd ..
4692
4695
4693 Test 'graphwidth' in 'hg log' on various topologies. The key here is that the
4696 Test 'graphwidth' in 'hg log' on various topologies. The key here is that the
4694 printed graphwidths 3, 5, 7, etc. should all line up in their respective
4697 printed graphwidths 3, 5, 7, etc. should all line up in their respective
4695 columns. We don't care about other aspects of the graph rendering here.
4698 columns. We don't care about other aspects of the graph rendering here.
4696
4699
4697 $ hg init graphwidth
4700 $ hg init graphwidth
4698 $ cd graphwidth
4701 $ cd graphwidth
4699
4702
4700 $ wrappabletext="a a a a a a a a a a a a"
4703 $ wrappabletext="a a a a a a a a a a a a"
4701
4704
4702 $ printf "first\n" > file
4705 $ printf "first\n" > file
4703 $ hg add file
4706 $ hg add file
4704 $ hg commit -m "$wrappabletext"
4707 $ hg commit -m "$wrappabletext"
4705
4708
4706 $ printf "first\nsecond\n" > file
4709 $ printf "first\nsecond\n" > file
4707 $ hg commit -m "$wrappabletext"
4710 $ hg commit -m "$wrappabletext"
4708
4711
4709 $ hg checkout 0
4712 $ hg checkout 0
4710 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4713 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4711 $ printf "third\nfirst\n" > file
4714 $ printf "third\nfirst\n" > file
4712 $ hg commit -m "$wrappabletext"
4715 $ hg commit -m "$wrappabletext"
4713 created new head
4716 created new head
4714
4717
4715 $ hg merge
4718 $ hg merge
4716 merging file
4719 merging file
4717 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
4720 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
4718 (branch merge, don't forget to commit)
4721 (branch merge, don't forget to commit)
4719
4722
4720 $ hg log --graph -T "{graphwidth}"
4723 $ hg log --graph -T "{graphwidth}"
4721 @ 3
4724 @ 3
4722 |
4725 |
4723 | @ 5
4726 | @ 5
4724 |/
4727 |/
4725 o 3
4728 o 3
4726
4729
4727 $ hg commit -m "$wrappabletext"
4730 $ hg commit -m "$wrappabletext"
4728
4731
4729 $ hg log --graph -T "{graphwidth}"
4732 $ hg log --graph -T "{graphwidth}"
4730 @ 5
4733 @ 5
4731 |\
4734 |\
4732 | o 5
4735 | o 5
4733 | |
4736 | |
4734 o | 5
4737 o | 5
4735 |/
4738 |/
4736 o 3
4739 o 3
4737
4740
4738
4741
4739 $ hg checkout 0
4742 $ hg checkout 0
4740 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4743 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4741 $ printf "third\nfirst\nsecond\n" > file
4744 $ printf "third\nfirst\nsecond\n" > file
4742 $ hg commit -m "$wrappabletext"
4745 $ hg commit -m "$wrappabletext"
4743 created new head
4746 created new head
4744
4747
4745 $ hg log --graph -T "{graphwidth}"
4748 $ hg log --graph -T "{graphwidth}"
4746 @ 3
4749 @ 3
4747 |
4750 |
4748 | o 7
4751 | o 7
4749 | |\
4752 | |\
4750 +---o 7
4753 +---o 7
4751 | |
4754 | |
4752 | o 5
4755 | o 5
4753 |/
4756 |/
4754 o 3
4757 o 3
4755
4758
4756
4759
4757 $ hg log --graph -T "{graphwidth}" -r 3
4760 $ hg log --graph -T "{graphwidth}" -r 3
4758 o 5
4761 o 5
4759 |\
4762 |\
4760 ~ ~
4763 ~ ~
4761
4764
4762 $ hg log --graph -T "{graphwidth}" -r 1
4765 $ hg log --graph -T "{graphwidth}" -r 1
4763 o 3
4766 o 3
4764 |
4767 |
4765 ~
4768 ~
4766
4769
4767 $ hg merge
4770 $ hg merge
4768 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4771 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4769 (branch merge, don't forget to commit)
4772 (branch merge, don't forget to commit)
4770 $ hg commit -m "$wrappabletext"
4773 $ hg commit -m "$wrappabletext"
4771
4774
4772 $ printf "seventh\n" >> file
4775 $ printf "seventh\n" >> file
4773 $ hg commit -m "$wrappabletext"
4776 $ hg commit -m "$wrappabletext"
4774
4777
4775 $ hg log --graph -T "{graphwidth}"
4778 $ hg log --graph -T "{graphwidth}"
4776 @ 3
4779 @ 3
4777 |
4780 |
4778 o 5
4781 o 5
4779 |\
4782 |\
4780 | o 5
4783 | o 5
4781 | |
4784 | |
4782 o | 7
4785 o | 7
4783 |\ \
4786 |\ \
4784 | o | 7
4787 | o | 7
4785 | |/
4788 | |/
4786 o / 5
4789 o / 5
4787 |/
4790 |/
4788 o 3
4791 o 3
4789
4792
4790
4793
4791 The point of graphwidth is to allow wrapping that accounts for the space taken
4794 The point of graphwidth is to allow wrapping that accounts for the space taken
4792 by the graph.
4795 by the graph.
4793
4796
4794 $ COLUMNS=10 hg log --graph -T "{fill(desc, termwidth - graphwidth)}"
4797 $ COLUMNS=10 hg log --graph -T "{fill(desc, termwidth - graphwidth)}"
4795 @ a a a a
4798 @ a a a a
4796 | a a a a
4799 | a a a a
4797 | a a a a
4800 | a a a a
4798 o a a a
4801 o a a a
4799 |\ a a a
4802 |\ a a a
4800 | | a a a
4803 | | a a a
4801 | | a a a
4804 | | a a a
4802 | o a a a
4805 | o a a a
4803 | | a a a
4806 | | a a a
4804 | | a a a
4807 | | a a a
4805 | | a a a
4808 | | a a a
4806 o | a a
4809 o | a a
4807 |\ \ a a
4810 |\ \ a a
4808 | | | a a
4811 | | | a a
4809 | | | a a
4812 | | | a a
4810 | | | a a
4813 | | | a a
4811 | | | a a
4814 | | | a a
4812 | o | a a
4815 | o | a a
4813 | |/ a a
4816 | |/ a a
4814 | | a a
4817 | | a a
4815 | | a a
4818 | | a a
4816 | | a a
4819 | | a a
4817 | | a a
4820 | | a a
4818 o | a a a
4821 o | a a a
4819 |/ a a a
4822 |/ a a a
4820 | a a a
4823 | a a a
4821 | a a a
4824 | a a a
4822 o a a a a
4825 o a a a a
4823 a a a a
4826 a a a a
4824 a a a a
4827 a a a a
4825
4828
4826 Something tricky happens when there are elided nodes; the next drawn row of
4829 Something tricky happens when there are elided nodes; the next drawn row of
4827 edges can be more than one column wider, but the graph width only increases by
4830 edges can be more than one column wider, but the graph width only increases by
4828 one column. The remaining columns are added in between the nodes.
4831 one column. The remaining columns are added in between the nodes.
4829
4832
4830 $ hg log --graph -T "{graphwidth}" -r "0|2|4|5"
4833 $ hg log --graph -T "{graphwidth}" -r "0|2|4|5"
4831 o 5
4834 o 5
4832 |\
4835 |\
4833 | \
4836 | \
4834 | :\
4837 | :\
4835 o : : 7
4838 o : : 7
4836 :/ /
4839 :/ /
4837 : o 5
4840 : o 5
4838 :/
4841 :/
4839 o 3
4842 o 3
4840
4843
4841
4844
4842 $ cd ..
4845 $ cd ..
4843
4846
General Comments 0
You need to be logged in to leave comments. Login now