##// END OF EJS Templates
templates: adding a config() function for template customization...
rdamazio@google.com -
r41869:67046961 default
parent child Browse files
Show More
@@ -1,1445 +1,1449
1 # configitems.py - centralized declaration of configuration option
1 # configitems.py - centralized declaration of configuration option
2 #
2 #
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
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 functools
10 import functools
11 import re
11 import re
12
12
13 from . import (
13 from . import (
14 encoding,
14 encoding,
15 error,
15 error,
16 )
16 )
17
17
18 def loadconfigtable(ui, extname, configtable):
18 def loadconfigtable(ui, extname, configtable):
19 """update config item known to the ui with the extension ones"""
19 """update config item known to the ui with the extension ones"""
20 for section, items in sorted(configtable.items()):
20 for section, items in sorted(configtable.items()):
21 knownitems = ui._knownconfig.setdefault(section, itemregister())
21 knownitems = ui._knownconfig.setdefault(section, itemregister())
22 knownkeys = set(knownitems)
22 knownkeys = set(knownitems)
23 newkeys = set(items)
23 newkeys = set(items)
24 for key in sorted(knownkeys & newkeys):
24 for key in sorted(knownkeys & newkeys):
25 msg = "extension '%s' overwrite config item '%s.%s'"
25 msg = "extension '%s' overwrite config item '%s.%s'"
26 msg %= (extname, section, key)
26 msg %= (extname, section, key)
27 ui.develwarn(msg, config='warn-config')
27 ui.develwarn(msg, config='warn-config')
28
28
29 knownitems.update(items)
29 knownitems.update(items)
30
30
31 class configitem(object):
31 class configitem(object):
32 """represent a known config item
32 """represent a known config item
33
33
34 :section: the official config section where to find this item,
34 :section: the official config section where to find this item,
35 :name: the official name within the section,
35 :name: the official name within the section,
36 :default: default value for this item,
36 :default: default value for this item,
37 :alias: optional list of tuples as alternatives,
37 :alias: optional list of tuples as alternatives,
38 :generic: this is a generic definition, match name using regular expression.
38 :generic: this is a generic definition, match name using regular expression.
39 """
39 """
40
40
41 def __init__(self, section, name, default=None, alias=(),
41 def __init__(self, section, name, default=None, alias=(),
42 generic=False, priority=0):
42 generic=False, priority=0):
43 self.section = section
43 self.section = section
44 self.name = name
44 self.name = name
45 self.default = default
45 self.default = default
46 self.alias = list(alias)
46 self.alias = list(alias)
47 self.generic = generic
47 self.generic = generic
48 self.priority = priority
48 self.priority = priority
49 self._re = None
49 self._re = None
50 if generic:
50 if generic:
51 self._re = re.compile(self.name)
51 self._re = re.compile(self.name)
52
52
53 class itemregister(dict):
53 class itemregister(dict):
54 """A specialized dictionary that can handle wild-card selection"""
54 """A specialized dictionary that can handle wild-card selection"""
55
55
56 def __init__(self):
56 def __init__(self):
57 super(itemregister, self).__init__()
57 super(itemregister, self).__init__()
58 self._generics = set()
58 self._generics = set()
59
59
60 def update(self, other):
60 def update(self, other):
61 super(itemregister, self).update(other)
61 super(itemregister, self).update(other)
62 self._generics.update(other._generics)
62 self._generics.update(other._generics)
63
63
64 def __setitem__(self, key, item):
64 def __setitem__(self, key, item):
65 super(itemregister, self).__setitem__(key, item)
65 super(itemregister, self).__setitem__(key, item)
66 if item.generic:
66 if item.generic:
67 self._generics.add(item)
67 self._generics.add(item)
68
68
69 def get(self, key):
69 def get(self, key):
70 baseitem = super(itemregister, self).get(key)
70 baseitem = super(itemregister, self).get(key)
71 if baseitem is not None and not baseitem.generic:
71 if baseitem is not None and not baseitem.generic:
72 return baseitem
72 return baseitem
73
73
74 # search for a matching generic item
74 # search for a matching generic item
75 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
75 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
76 for item in generics:
76 for item in generics:
77 # we use 'match' instead of 'search' to make the matching simpler
77 # we use 'match' instead of 'search' to make the matching simpler
78 # for people unfamiliar with regular expression. Having the match
78 # for people unfamiliar with regular expression. Having the match
79 # rooted to the start of the string will produce less surprising
79 # rooted to the start of the string will produce less surprising
80 # result for user writing simple regex for sub-attribute.
80 # result for user writing simple regex for sub-attribute.
81 #
81 #
82 # For example using "color\..*" match produces an unsurprising
82 # For example using "color\..*" match produces an unsurprising
83 # result, while using search could suddenly match apparently
83 # result, while using search could suddenly match apparently
84 # unrelated configuration that happens to contains "color."
84 # unrelated configuration that happens to contains "color."
85 # anywhere. This is a tradeoff where we favor requiring ".*" on
85 # anywhere. This is a tradeoff where we favor requiring ".*" on
86 # some match to avoid the need to prefix most pattern with "^".
86 # some match to avoid the need to prefix most pattern with "^".
87 # The "^" seems more error prone.
87 # The "^" seems more error prone.
88 if item._re.match(key):
88 if item._re.match(key):
89 return item
89 return item
90
90
91 return None
91 return None
92
92
93 coreitems = {}
93 coreitems = {}
94
94
95 def _register(configtable, *args, **kwargs):
95 def _register(configtable, *args, **kwargs):
96 item = configitem(*args, **kwargs)
96 item = configitem(*args, **kwargs)
97 section = configtable.setdefault(item.section, itemregister())
97 section = configtable.setdefault(item.section, itemregister())
98 if item.name in section:
98 if item.name in section:
99 msg = "duplicated config item registration for '%s.%s'"
99 msg = "duplicated config item registration for '%s.%s'"
100 raise error.ProgrammingError(msg % (item.section, item.name))
100 raise error.ProgrammingError(msg % (item.section, item.name))
101 section[item.name] = item
101 section[item.name] = item
102
102
103 # special value for case where the default is derived from other values
103 # special value for case where the default is derived from other values
104 dynamicdefault = object()
104 dynamicdefault = object()
105
105
106 # Registering actual config items
106 # Registering actual config items
107
107
108 def getitemregister(configtable):
108 def getitemregister(configtable):
109 f = functools.partial(_register, configtable)
109 f = functools.partial(_register, configtable)
110 # export pseudo enum as configitem.*
110 # export pseudo enum as configitem.*
111 f.dynamicdefault = dynamicdefault
111 f.dynamicdefault = dynamicdefault
112 return f
112 return f
113
113
114 coreconfigitem = getitemregister(coreitems)
114 coreconfigitem = getitemregister(coreitems)
115
115
116 def _registerdiffopts(section, configprefix=''):
116 def _registerdiffopts(section, configprefix=''):
117 coreconfigitem(section, configprefix + 'nodates',
117 coreconfigitem(section, configprefix + 'nodates',
118 default=False,
118 default=False,
119 )
119 )
120 coreconfigitem(section, configprefix + 'showfunc',
120 coreconfigitem(section, configprefix + 'showfunc',
121 default=False,
121 default=False,
122 )
122 )
123 coreconfigitem(section, configprefix + 'unified',
123 coreconfigitem(section, configprefix + 'unified',
124 default=None,
124 default=None,
125 )
125 )
126 coreconfigitem(section, configprefix + 'git',
126 coreconfigitem(section, configprefix + 'git',
127 default=False,
127 default=False,
128 )
128 )
129 coreconfigitem(section, configprefix + 'ignorews',
129 coreconfigitem(section, configprefix + 'ignorews',
130 default=False,
130 default=False,
131 )
131 )
132 coreconfigitem(section, configprefix + 'ignorewsamount',
132 coreconfigitem(section, configprefix + 'ignorewsamount',
133 default=False,
133 default=False,
134 )
134 )
135 coreconfigitem(section, configprefix + 'ignoreblanklines',
135 coreconfigitem(section, configprefix + 'ignoreblanklines',
136 default=False,
136 default=False,
137 )
137 )
138 coreconfigitem(section, configprefix + 'ignorewseol',
138 coreconfigitem(section, configprefix + 'ignorewseol',
139 default=False,
139 default=False,
140 )
140 )
141 coreconfigitem(section, configprefix + 'nobinary',
141 coreconfigitem(section, configprefix + 'nobinary',
142 default=False,
142 default=False,
143 )
143 )
144 coreconfigitem(section, configprefix + 'noprefix',
144 coreconfigitem(section, configprefix + 'noprefix',
145 default=False,
145 default=False,
146 )
146 )
147 coreconfigitem(section, configprefix + 'word-diff',
147 coreconfigitem(section, configprefix + 'word-diff',
148 default=False,
148 default=False,
149 )
149 )
150
150
151 coreconfigitem('alias', '.*',
151 coreconfigitem('alias', '.*',
152 default=dynamicdefault,
152 default=dynamicdefault,
153 generic=True,
153 generic=True,
154 )
154 )
155 coreconfigitem('auth', 'cookiefile',
155 coreconfigitem('auth', 'cookiefile',
156 default=None,
156 default=None,
157 )
157 )
158 _registerdiffopts(section='annotate')
158 _registerdiffopts(section='annotate')
159 # bookmarks.pushing: internal hack for discovery
159 # bookmarks.pushing: internal hack for discovery
160 coreconfigitem('bookmarks', 'pushing',
160 coreconfigitem('bookmarks', 'pushing',
161 default=list,
161 default=list,
162 )
162 )
163 # bundle.mainreporoot: internal hack for bundlerepo
163 # bundle.mainreporoot: internal hack for bundlerepo
164 coreconfigitem('bundle', 'mainreporoot',
164 coreconfigitem('bundle', 'mainreporoot',
165 default='',
165 default='',
166 )
166 )
167 coreconfigitem('censor', 'policy',
167 coreconfigitem('censor', 'policy',
168 default='abort',
168 default='abort',
169 )
169 )
170 coreconfigitem('chgserver', 'idletimeout',
170 coreconfigitem('chgserver', 'idletimeout',
171 default=3600,
171 default=3600,
172 )
172 )
173 coreconfigitem('chgserver', 'skiphash',
173 coreconfigitem('chgserver', 'skiphash',
174 default=False,
174 default=False,
175 )
175 )
176 coreconfigitem('cmdserver', 'log',
176 coreconfigitem('cmdserver', 'log',
177 default=None,
177 default=None,
178 )
178 )
179 coreconfigitem('cmdserver', 'max-log-files',
179 coreconfigitem('cmdserver', 'max-log-files',
180 default=7,
180 default=7,
181 )
181 )
182 coreconfigitem('cmdserver', 'max-log-size',
182 coreconfigitem('cmdserver', 'max-log-size',
183 default='1 MB',
183 default='1 MB',
184 )
184 )
185 coreconfigitem('cmdserver', 'max-repo-cache',
185 coreconfigitem('cmdserver', 'max-repo-cache',
186 default=0,
186 default=0,
187 )
187 )
188 coreconfigitem('cmdserver', 'message-encodings',
188 coreconfigitem('cmdserver', 'message-encodings',
189 default=list,
189 default=list,
190 )
190 )
191 coreconfigitem('cmdserver', 'track-log',
191 coreconfigitem('cmdserver', 'track-log',
192 default=lambda: ['chgserver', 'cmdserver', 'repocache'],
192 default=lambda: ['chgserver', 'cmdserver', 'repocache'],
193 )
193 )
194 coreconfigitem('color', '.*',
194 coreconfigitem('color', '.*',
195 default=None,
195 default=None,
196 generic=True,
196 generic=True,
197 )
197 )
198 coreconfigitem('color', 'mode',
198 coreconfigitem('color', 'mode',
199 default='auto',
199 default='auto',
200 )
200 )
201 coreconfigitem('color', 'pagermode',
201 coreconfigitem('color', 'pagermode',
202 default=dynamicdefault,
202 default=dynamicdefault,
203 )
203 )
204 _registerdiffopts(section='commands', configprefix='commit.interactive.')
204 _registerdiffopts(section='commands', configprefix='commit.interactive.')
205 coreconfigitem('commands', 'grep.all-files',
205 coreconfigitem('commands', 'grep.all-files',
206 default=False,
206 default=False,
207 )
207 )
208 coreconfigitem('commands', 'resolve.confirm',
208 coreconfigitem('commands', 'resolve.confirm',
209 default=False,
209 default=False,
210 )
210 )
211 coreconfigitem('commands', 'resolve.explicit-re-merge',
211 coreconfigitem('commands', 'resolve.explicit-re-merge',
212 default=False,
212 default=False,
213 )
213 )
214 coreconfigitem('commands', 'resolve.mark-check',
214 coreconfigitem('commands', 'resolve.mark-check',
215 default='none',
215 default='none',
216 )
216 )
217 _registerdiffopts(section='commands', configprefix='revert.interactive.')
217 _registerdiffopts(section='commands', configprefix='revert.interactive.')
218 coreconfigitem('commands', 'show.aliasprefix',
218 coreconfigitem('commands', 'show.aliasprefix',
219 default=list,
219 default=list,
220 )
220 )
221 coreconfigitem('commands', 'status.relative',
221 coreconfigitem('commands', 'status.relative',
222 default=False,
222 default=False,
223 )
223 )
224 coreconfigitem('commands', 'status.skipstates',
224 coreconfigitem('commands', 'status.skipstates',
225 default=[],
225 default=[],
226 )
226 )
227 coreconfigitem('commands', 'status.terse',
227 coreconfigitem('commands', 'status.terse',
228 default='',
228 default='',
229 )
229 )
230 coreconfigitem('commands', 'status.verbose',
230 coreconfigitem('commands', 'status.verbose',
231 default=False,
231 default=False,
232 )
232 )
233 coreconfigitem('commands', 'update.check',
233 coreconfigitem('commands', 'update.check',
234 default=None,
234 default=None,
235 )
235 )
236 coreconfigitem('commands', 'update.requiredest',
236 coreconfigitem('commands', 'update.requiredest',
237 default=False,
237 default=False,
238 )
238 )
239 coreconfigitem('committemplate', '.*',
239 coreconfigitem('committemplate', '.*',
240 default=None,
240 default=None,
241 generic=True,
241 generic=True,
242 )
242 )
243 coreconfigitem('convert', 'bzr.saverev',
243 coreconfigitem('convert', 'bzr.saverev',
244 default=True,
244 default=True,
245 )
245 )
246 coreconfigitem('convert', 'cvsps.cache',
246 coreconfigitem('convert', 'cvsps.cache',
247 default=True,
247 default=True,
248 )
248 )
249 coreconfigitem('convert', 'cvsps.fuzz',
249 coreconfigitem('convert', 'cvsps.fuzz',
250 default=60,
250 default=60,
251 )
251 )
252 coreconfigitem('convert', 'cvsps.logencoding',
252 coreconfigitem('convert', 'cvsps.logencoding',
253 default=None,
253 default=None,
254 )
254 )
255 coreconfigitem('convert', 'cvsps.mergefrom',
255 coreconfigitem('convert', 'cvsps.mergefrom',
256 default=None,
256 default=None,
257 )
257 )
258 coreconfigitem('convert', 'cvsps.mergeto',
258 coreconfigitem('convert', 'cvsps.mergeto',
259 default=None,
259 default=None,
260 )
260 )
261 coreconfigitem('convert', 'git.committeractions',
261 coreconfigitem('convert', 'git.committeractions',
262 default=lambda: ['messagedifferent'],
262 default=lambda: ['messagedifferent'],
263 )
263 )
264 coreconfigitem('convert', 'git.extrakeys',
264 coreconfigitem('convert', 'git.extrakeys',
265 default=list,
265 default=list,
266 )
266 )
267 coreconfigitem('convert', 'git.findcopiesharder',
267 coreconfigitem('convert', 'git.findcopiesharder',
268 default=False,
268 default=False,
269 )
269 )
270 coreconfigitem('convert', 'git.remoteprefix',
270 coreconfigitem('convert', 'git.remoteprefix',
271 default='remote',
271 default='remote',
272 )
272 )
273 coreconfigitem('convert', 'git.renamelimit',
273 coreconfigitem('convert', 'git.renamelimit',
274 default=400,
274 default=400,
275 )
275 )
276 coreconfigitem('convert', 'git.saverev',
276 coreconfigitem('convert', 'git.saverev',
277 default=True,
277 default=True,
278 )
278 )
279 coreconfigitem('convert', 'git.similarity',
279 coreconfigitem('convert', 'git.similarity',
280 default=50,
280 default=50,
281 )
281 )
282 coreconfigitem('convert', 'git.skipsubmodules',
282 coreconfigitem('convert', 'git.skipsubmodules',
283 default=False,
283 default=False,
284 )
284 )
285 coreconfigitem('convert', 'hg.clonebranches',
285 coreconfigitem('convert', 'hg.clonebranches',
286 default=False,
286 default=False,
287 )
287 )
288 coreconfigitem('convert', 'hg.ignoreerrors',
288 coreconfigitem('convert', 'hg.ignoreerrors',
289 default=False,
289 default=False,
290 )
290 )
291 coreconfigitem('convert', 'hg.revs',
291 coreconfigitem('convert', 'hg.revs',
292 default=None,
292 default=None,
293 )
293 )
294 coreconfigitem('convert', 'hg.saverev',
294 coreconfigitem('convert', 'hg.saverev',
295 default=False,
295 default=False,
296 )
296 )
297 coreconfigitem('convert', 'hg.sourcename',
297 coreconfigitem('convert', 'hg.sourcename',
298 default=None,
298 default=None,
299 )
299 )
300 coreconfigitem('convert', 'hg.startrev',
300 coreconfigitem('convert', 'hg.startrev',
301 default=None,
301 default=None,
302 )
302 )
303 coreconfigitem('convert', 'hg.tagsbranch',
303 coreconfigitem('convert', 'hg.tagsbranch',
304 default='default',
304 default='default',
305 )
305 )
306 coreconfigitem('convert', 'hg.usebranchnames',
306 coreconfigitem('convert', 'hg.usebranchnames',
307 default=True,
307 default=True,
308 )
308 )
309 coreconfigitem('convert', 'ignoreancestorcheck',
309 coreconfigitem('convert', 'ignoreancestorcheck',
310 default=False,
310 default=False,
311 )
311 )
312 coreconfigitem('convert', 'localtimezone',
312 coreconfigitem('convert', 'localtimezone',
313 default=False,
313 default=False,
314 )
314 )
315 coreconfigitem('convert', 'p4.encoding',
315 coreconfigitem('convert', 'p4.encoding',
316 default=dynamicdefault,
316 default=dynamicdefault,
317 )
317 )
318 coreconfigitem('convert', 'p4.startrev',
318 coreconfigitem('convert', 'p4.startrev',
319 default=0,
319 default=0,
320 )
320 )
321 coreconfigitem('convert', 'skiptags',
321 coreconfigitem('convert', 'skiptags',
322 default=False,
322 default=False,
323 )
323 )
324 coreconfigitem('convert', 'svn.debugsvnlog',
324 coreconfigitem('convert', 'svn.debugsvnlog',
325 default=True,
325 default=True,
326 )
326 )
327 coreconfigitem('convert', 'svn.trunk',
327 coreconfigitem('convert', 'svn.trunk',
328 default=None,
328 default=None,
329 )
329 )
330 coreconfigitem('convert', 'svn.tags',
330 coreconfigitem('convert', 'svn.tags',
331 default=None,
331 default=None,
332 )
332 )
333 coreconfigitem('convert', 'svn.branches',
333 coreconfigitem('convert', 'svn.branches',
334 default=None,
334 default=None,
335 )
335 )
336 coreconfigitem('convert', 'svn.startrev',
336 coreconfigitem('convert', 'svn.startrev',
337 default=0,
337 default=0,
338 )
338 )
339 coreconfigitem('debug', 'dirstate.delaywrite',
339 coreconfigitem('debug', 'dirstate.delaywrite',
340 default=0,
340 default=0,
341 )
341 )
342 coreconfigitem('defaults', '.*',
342 coreconfigitem('defaults', '.*',
343 default=None,
343 default=None,
344 generic=True,
344 generic=True,
345 )
345 )
346 coreconfigitem('devel', 'all-warnings',
346 coreconfigitem('devel', 'all-warnings',
347 default=False,
347 default=False,
348 )
348 )
349 coreconfigitem('devel', 'bundle2.debug',
349 coreconfigitem('devel', 'bundle2.debug',
350 default=False,
350 default=False,
351 )
351 )
352 coreconfigitem('devel', 'bundle.delta',
352 coreconfigitem('devel', 'bundle.delta',
353 default='',
353 default='',
354 )
354 )
355 coreconfigitem('devel', 'cache-vfs',
355 coreconfigitem('devel', 'cache-vfs',
356 default=None,
356 default=None,
357 )
357 )
358 coreconfigitem('devel', 'check-locks',
358 coreconfigitem('devel', 'check-locks',
359 default=False,
359 default=False,
360 )
360 )
361 coreconfigitem('devel', 'check-relroot',
361 coreconfigitem('devel', 'check-relroot',
362 default=False,
362 default=False,
363 )
363 )
364 coreconfigitem('devel', 'default-date',
364 coreconfigitem('devel', 'default-date',
365 default=None,
365 default=None,
366 )
366 )
367 coreconfigitem('devel', 'deprec-warn',
367 coreconfigitem('devel', 'deprec-warn',
368 default=False,
368 default=False,
369 )
369 )
370 coreconfigitem('devel', 'disableloaddefaultcerts',
370 coreconfigitem('devel', 'disableloaddefaultcerts',
371 default=False,
371 default=False,
372 )
372 )
373 coreconfigitem('devel', 'warn-empty-changegroup',
373 coreconfigitem('devel', 'warn-empty-changegroup',
374 default=False,
374 default=False,
375 )
375 )
376 coreconfigitem('devel', 'legacy.exchange',
376 coreconfigitem('devel', 'legacy.exchange',
377 default=list,
377 default=list,
378 )
378 )
379 coreconfigitem('devel', 'servercafile',
379 coreconfigitem('devel', 'servercafile',
380 default='',
380 default='',
381 )
381 )
382 coreconfigitem('devel', 'serverexactprotocol',
382 coreconfigitem('devel', 'serverexactprotocol',
383 default='',
383 default='',
384 )
384 )
385 coreconfigitem('devel', 'serverrequirecert',
385 coreconfigitem('devel', 'serverrequirecert',
386 default=False,
386 default=False,
387 )
387 )
388 coreconfigitem('devel', 'strip-obsmarkers',
388 coreconfigitem('devel', 'strip-obsmarkers',
389 default=True,
389 default=True,
390 )
390 )
391 coreconfigitem('devel', 'warn-config',
391 coreconfigitem('devel', 'warn-config',
392 default=None,
392 default=None,
393 )
393 )
394 coreconfigitem('devel', 'warn-config-default',
394 coreconfigitem('devel', 'warn-config-default',
395 default=None,
395 default=None,
396 )
396 )
397 coreconfigitem('devel', 'user.obsmarker',
397 coreconfigitem('devel', 'user.obsmarker',
398 default=None,
398 default=None,
399 )
399 )
400 coreconfigitem('devel', 'warn-config-unknown',
400 coreconfigitem('devel', 'warn-config-unknown',
401 default=None,
401 default=None,
402 )
402 )
403 coreconfigitem('devel', 'debug.copies',
403 coreconfigitem('devel', 'debug.copies',
404 default=False,
404 default=False,
405 )
405 )
406 coreconfigitem('devel', 'debug.extensions',
406 coreconfigitem('devel', 'debug.extensions',
407 default=False,
407 default=False,
408 )
408 )
409 coreconfigitem('devel', 'debug.peer-request',
409 coreconfigitem('devel', 'debug.peer-request',
410 default=False,
410 default=False,
411 )
411 )
412 _registerdiffopts(section='diff')
412 _registerdiffopts(section='diff')
413 coreconfigitem('email', 'bcc',
413 coreconfigitem('email', 'bcc',
414 default=None,
414 default=None,
415 )
415 )
416 coreconfigitem('email', 'cc',
416 coreconfigitem('email', 'cc',
417 default=None,
417 default=None,
418 )
418 )
419 coreconfigitem('email', 'charsets',
419 coreconfigitem('email', 'charsets',
420 default=list,
420 default=list,
421 )
421 )
422 coreconfigitem('email', 'from',
422 coreconfigitem('email', 'from',
423 default=None,
423 default=None,
424 )
424 )
425 coreconfigitem('email', 'method',
425 coreconfigitem('email', 'method',
426 default='smtp',
426 default='smtp',
427 )
427 )
428 coreconfigitem('email', 'reply-to',
428 coreconfigitem('email', 'reply-to',
429 default=None,
429 default=None,
430 )
430 )
431 coreconfigitem('email', 'to',
431 coreconfigitem('email', 'to',
432 default=None,
432 default=None,
433 )
433 )
434 coreconfigitem('experimental', 'archivemetatemplate',
434 coreconfigitem('experimental', 'archivemetatemplate',
435 default=dynamicdefault,
435 default=dynamicdefault,
436 )
436 )
437 coreconfigitem('experimental', 'auto-publish',
437 coreconfigitem('experimental', 'auto-publish',
438 default='publish',
438 default='publish',
439 )
439 )
440 coreconfigitem('experimental', 'bundle-phases',
440 coreconfigitem('experimental', 'bundle-phases',
441 default=False,
441 default=False,
442 )
442 )
443 coreconfigitem('experimental', 'bundle2-advertise',
443 coreconfigitem('experimental', 'bundle2-advertise',
444 default=True,
444 default=True,
445 )
445 )
446 coreconfigitem('experimental', 'bundle2-output-capture',
446 coreconfigitem('experimental', 'bundle2-output-capture',
447 default=False,
447 default=False,
448 )
448 )
449 coreconfigitem('experimental', 'bundle2.pushback',
449 coreconfigitem('experimental', 'bundle2.pushback',
450 default=False,
450 default=False,
451 )
451 )
452 coreconfigitem('experimental', 'bundle2lazylocking',
452 coreconfigitem('experimental', 'bundle2lazylocking',
453 default=False,
453 default=False,
454 )
454 )
455 coreconfigitem('experimental', 'bundlecomplevel',
455 coreconfigitem('experimental', 'bundlecomplevel',
456 default=None,
456 default=None,
457 )
457 )
458 coreconfigitem('experimental', 'bundlecomplevel.bzip2',
458 coreconfigitem('experimental', 'bundlecomplevel.bzip2',
459 default=None,
459 default=None,
460 )
460 )
461 coreconfigitem('experimental', 'bundlecomplevel.gzip',
461 coreconfigitem('experimental', 'bundlecomplevel.gzip',
462 default=None,
462 default=None,
463 )
463 )
464 coreconfigitem('experimental', 'bundlecomplevel.none',
464 coreconfigitem('experimental', 'bundlecomplevel.none',
465 default=None,
465 default=None,
466 )
466 )
467 coreconfigitem('experimental', 'bundlecomplevel.zstd',
467 coreconfigitem('experimental', 'bundlecomplevel.zstd',
468 default=None,
468 default=None,
469 )
469 )
470 coreconfigitem('experimental', 'changegroup3',
470 coreconfigitem('experimental', 'changegroup3',
471 default=False,
471 default=False,
472 )
472 )
473 coreconfigitem('experimental', 'clientcompressionengines',
473 coreconfigitem('experimental', 'clientcompressionengines',
474 default=list,
474 default=list,
475 )
475 )
476 coreconfigitem('experimental', 'copytrace',
476 coreconfigitem('experimental', 'copytrace',
477 default='on',
477 default='on',
478 )
478 )
479 coreconfigitem('experimental', 'copytrace.movecandidateslimit',
479 coreconfigitem('experimental', 'copytrace.movecandidateslimit',
480 default=100,
480 default=100,
481 )
481 )
482 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
482 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
483 default=100,
483 default=100,
484 )
484 )
485 coreconfigitem('experimental', 'crecordtest',
485 coreconfigitem('experimental', 'crecordtest',
486 default=None,
486 default=None,
487 )
487 )
488 coreconfigitem('experimental', 'directaccess',
488 coreconfigitem('experimental', 'directaccess',
489 default=False,
489 default=False,
490 )
490 )
491 coreconfigitem('experimental', 'directaccess.revnums',
491 coreconfigitem('experimental', 'directaccess.revnums',
492 default=False,
492 default=False,
493 )
493 )
494 coreconfigitem('experimental', 'editortmpinhg',
494 coreconfigitem('experimental', 'editortmpinhg',
495 default=False,
495 default=False,
496 )
496 )
497 coreconfigitem('experimental', 'evolution',
497 coreconfigitem('experimental', 'evolution',
498 default=list,
498 default=list,
499 )
499 )
500 coreconfigitem('experimental', 'evolution.allowdivergence',
500 coreconfigitem('experimental', 'evolution.allowdivergence',
501 default=False,
501 default=False,
502 alias=[('experimental', 'allowdivergence')]
502 alias=[('experimental', 'allowdivergence')]
503 )
503 )
504 coreconfigitem('experimental', 'evolution.allowunstable',
504 coreconfigitem('experimental', 'evolution.allowunstable',
505 default=None,
505 default=None,
506 )
506 )
507 coreconfigitem('experimental', 'evolution.createmarkers',
507 coreconfigitem('experimental', 'evolution.createmarkers',
508 default=None,
508 default=None,
509 )
509 )
510 coreconfigitem('experimental', 'evolution.effect-flags',
510 coreconfigitem('experimental', 'evolution.effect-flags',
511 default=True,
511 default=True,
512 alias=[('experimental', 'effect-flags')]
512 alias=[('experimental', 'effect-flags')]
513 )
513 )
514 coreconfigitem('experimental', 'evolution.exchange',
514 coreconfigitem('experimental', 'evolution.exchange',
515 default=None,
515 default=None,
516 )
516 )
517 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
517 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
518 default=False,
518 default=False,
519 )
519 )
520 coreconfigitem('experimental', 'evolution.report-instabilities',
520 coreconfigitem('experimental', 'evolution.report-instabilities',
521 default=True,
521 default=True,
522 )
522 )
523 coreconfigitem('experimental', 'evolution.track-operation',
523 coreconfigitem('experimental', 'evolution.track-operation',
524 default=True,
524 default=True,
525 )
525 )
526 coreconfigitem('experimental', 'maxdeltachainspan',
526 coreconfigitem('experimental', 'maxdeltachainspan',
527 default=-1,
527 default=-1,
528 )
528 )
529 coreconfigitem('experimental', 'mergetempdirprefix',
529 coreconfigitem('experimental', 'mergetempdirprefix',
530 default=None,
530 default=None,
531 )
531 )
532 coreconfigitem('experimental', 'mmapindexthreshold',
532 coreconfigitem('experimental', 'mmapindexthreshold',
533 default=None,
533 default=None,
534 )
534 )
535 coreconfigitem('experimental', 'narrow',
535 coreconfigitem('experimental', 'narrow',
536 default=False,
536 default=False,
537 )
537 )
538 coreconfigitem('experimental', 'nonnormalparanoidcheck',
538 coreconfigitem('experimental', 'nonnormalparanoidcheck',
539 default=False,
539 default=False,
540 )
540 )
541 coreconfigitem('experimental', 'exportableenviron',
541 coreconfigitem('experimental', 'exportableenviron',
542 default=list,
542 default=list,
543 )
543 )
544 coreconfigitem('experimental', 'extendedheader.index',
544 coreconfigitem('experimental', 'extendedheader.index',
545 default=None,
545 default=None,
546 )
546 )
547 coreconfigitem('experimental', 'extendedheader.similarity',
547 coreconfigitem('experimental', 'extendedheader.similarity',
548 default=False,
548 default=False,
549 )
549 )
550 coreconfigitem('experimental', 'format.compression',
550 coreconfigitem('experimental', 'format.compression',
551 default='zlib',
551 default='zlib',
552 )
552 )
553 coreconfigitem('experimental', 'graphshorten',
553 coreconfigitem('experimental', 'graphshorten',
554 default=False,
554 default=False,
555 )
555 )
556 coreconfigitem('experimental', 'graphstyle.parent',
556 coreconfigitem('experimental', 'graphstyle.parent',
557 default=dynamicdefault,
557 default=dynamicdefault,
558 )
558 )
559 coreconfigitem('experimental', 'graphstyle.missing',
559 coreconfigitem('experimental', 'graphstyle.missing',
560 default=dynamicdefault,
560 default=dynamicdefault,
561 )
561 )
562 coreconfigitem('experimental', 'graphstyle.grandparent',
562 coreconfigitem('experimental', 'graphstyle.grandparent',
563 default=dynamicdefault,
563 default=dynamicdefault,
564 )
564 )
565 coreconfigitem('experimental', 'hook-track-tags',
565 coreconfigitem('experimental', 'hook-track-tags',
566 default=False,
566 default=False,
567 )
567 )
568 coreconfigitem('experimental', 'httppeer.advertise-v2',
568 coreconfigitem('experimental', 'httppeer.advertise-v2',
569 default=False,
569 default=False,
570 )
570 )
571 coreconfigitem('experimental', 'httppeer.v2-encoder-order',
571 coreconfigitem('experimental', 'httppeer.v2-encoder-order',
572 default=None,
572 default=None,
573 )
573 )
574 coreconfigitem('experimental', 'httppostargs',
574 coreconfigitem('experimental', 'httppostargs',
575 default=False,
575 default=False,
576 )
576 )
577 coreconfigitem('experimental', 'mergedriver',
577 coreconfigitem('experimental', 'mergedriver',
578 default=None,
578 default=None,
579 )
579 )
580 coreconfigitem('experimental', 'nointerrupt', default=False)
580 coreconfigitem('experimental', 'nointerrupt', default=False)
581 coreconfigitem('experimental', 'nointerrupt-interactiveonly', default=True)
581 coreconfigitem('experimental', 'nointerrupt-interactiveonly', default=True)
582
582
583 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
583 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
584 default=False,
584 default=False,
585 )
585 )
586 coreconfigitem('experimental', 'remotenames',
586 coreconfigitem('experimental', 'remotenames',
587 default=False,
587 default=False,
588 )
588 )
589 coreconfigitem('experimental', 'removeemptydirs',
589 coreconfigitem('experimental', 'removeemptydirs',
590 default=True,
590 default=True,
591 )
591 )
592 coreconfigitem('experimental', 'revisions.prefixhexnode',
592 coreconfigitem('experimental', 'revisions.prefixhexnode',
593 default=False,
593 default=False,
594 )
594 )
595 coreconfigitem('experimental', 'revlogv2',
595 coreconfigitem('experimental', 'revlogv2',
596 default=None,
596 default=None,
597 )
597 )
598 coreconfigitem('experimental', 'revisions.disambiguatewithin',
598 coreconfigitem('experimental', 'revisions.disambiguatewithin',
599 default=None,
599 default=None,
600 )
600 )
601 coreconfigitem('experimental', 'server.filesdata.recommended-batch-size',
601 coreconfigitem('experimental', 'server.filesdata.recommended-batch-size',
602 default=50000,
602 default=50000,
603 )
603 )
604 coreconfigitem('experimental', 'server.manifestdata.recommended-batch-size',
604 coreconfigitem('experimental', 'server.manifestdata.recommended-batch-size',
605 default=100000,
605 default=100000,
606 )
606 )
607 coreconfigitem('experimental', 'server.stream-narrow-clones',
607 coreconfigitem('experimental', 'server.stream-narrow-clones',
608 default=False,
608 default=False,
609 )
609 )
610 coreconfigitem('experimental', 'single-head-per-branch',
610 coreconfigitem('experimental', 'single-head-per-branch',
611 default=False,
611 default=False,
612 )
612 )
613 coreconfigitem('experimental', 'sshserver.support-v2',
613 coreconfigitem('experimental', 'sshserver.support-v2',
614 default=False,
614 default=False,
615 )
615 )
616 coreconfigitem('experimental', 'sparse-read',
616 coreconfigitem('experimental', 'sparse-read',
617 default=False,
617 default=False,
618 )
618 )
619 coreconfigitem('experimental', 'sparse-read.density-threshold',
619 coreconfigitem('experimental', 'sparse-read.density-threshold',
620 default=0.50,
620 default=0.50,
621 )
621 )
622 coreconfigitem('experimental', 'sparse-read.min-gap-size',
622 coreconfigitem('experimental', 'sparse-read.min-gap-size',
623 default='65K',
623 default='65K',
624 )
624 )
625 coreconfigitem('experimental', 'treemanifest',
625 coreconfigitem('experimental', 'treemanifest',
626 default=False,
626 default=False,
627 )
627 )
628 coreconfigitem('experimental', 'update.atomic-file',
628 coreconfigitem('experimental', 'update.atomic-file',
629 default=False,
629 default=False,
630 )
630 )
631 coreconfigitem('experimental', 'sshpeer.advertise-v2',
631 coreconfigitem('experimental', 'sshpeer.advertise-v2',
632 default=False,
632 default=False,
633 )
633 )
634 coreconfigitem('experimental', 'web.apiserver',
634 coreconfigitem('experimental', 'web.apiserver',
635 default=False,
635 default=False,
636 )
636 )
637 coreconfigitem('experimental', 'web.api.http-v2',
637 coreconfigitem('experimental', 'web.api.http-v2',
638 default=False,
638 default=False,
639 )
639 )
640 coreconfigitem('experimental', 'web.api.debugreflect',
640 coreconfigitem('experimental', 'web.api.debugreflect',
641 default=False,
641 default=False,
642 )
642 )
643 coreconfigitem('experimental', 'worker.wdir-get-thread-safe',
643 coreconfigitem('experimental', 'worker.wdir-get-thread-safe',
644 default=False,
644 default=False,
645 )
645 )
646 coreconfigitem('experimental', 'xdiff',
646 coreconfigitem('experimental', 'xdiff',
647 default=False,
647 default=False,
648 )
648 )
649 coreconfigitem('extensions', '.*',
649 coreconfigitem('extensions', '.*',
650 default=None,
650 default=None,
651 generic=True,
651 generic=True,
652 )
652 )
653 coreconfigitem('extdata', '.*',
653 coreconfigitem('extdata', '.*',
654 default=None,
654 default=None,
655 generic=True,
655 generic=True,
656 )
656 )
657 coreconfigitem('format', 'chunkcachesize',
657 coreconfigitem('format', 'chunkcachesize',
658 default=None,
658 default=None,
659 )
659 )
660 coreconfigitem('format', 'dotencode',
660 coreconfigitem('format', 'dotencode',
661 default=True,
661 default=True,
662 )
662 )
663 coreconfigitem('format', 'generaldelta',
663 coreconfigitem('format', 'generaldelta',
664 default=False,
664 default=False,
665 )
665 )
666 coreconfigitem('format', 'manifestcachesize',
666 coreconfigitem('format', 'manifestcachesize',
667 default=None,
667 default=None,
668 )
668 )
669 coreconfigitem('format', 'maxchainlen',
669 coreconfigitem('format', 'maxchainlen',
670 default=dynamicdefault,
670 default=dynamicdefault,
671 )
671 )
672 coreconfigitem('format', 'obsstore-version',
672 coreconfigitem('format', 'obsstore-version',
673 default=None,
673 default=None,
674 )
674 )
675 coreconfigitem('format', 'sparse-revlog',
675 coreconfigitem('format', 'sparse-revlog',
676 default=True,
676 default=True,
677 )
677 )
678 coreconfigitem('format', 'usefncache',
678 coreconfigitem('format', 'usefncache',
679 default=True,
679 default=True,
680 )
680 )
681 coreconfigitem('format', 'usegeneraldelta',
681 coreconfigitem('format', 'usegeneraldelta',
682 default=True,
682 default=True,
683 )
683 )
684 coreconfigitem('format', 'usestore',
684 coreconfigitem('format', 'usestore',
685 default=True,
685 default=True,
686 )
686 )
687 coreconfigitem('format', 'internal-phase',
687 coreconfigitem('format', 'internal-phase',
688 default=False,
688 default=False,
689 )
689 )
690 coreconfigitem('fsmonitor', 'warn_when_unused',
690 coreconfigitem('fsmonitor', 'warn_when_unused',
691 default=True,
691 default=True,
692 )
692 )
693 coreconfigitem('fsmonitor', 'warn_update_file_count',
693 coreconfigitem('fsmonitor', 'warn_update_file_count',
694 default=50000,
694 default=50000,
695 )
695 )
696 coreconfigitem('help', br'hidden-command\..*',
696 coreconfigitem('help', br'hidden-command\..*',
697 default=False,
697 default=False,
698 generic=True,
698 generic=True,
699 )
699 )
700 coreconfigitem('help', br'hidden-topic\..*',
700 coreconfigitem('help', br'hidden-topic\..*',
701 default=False,
701 default=False,
702 generic=True,
702 generic=True,
703 )
703 )
704 coreconfigitem('hooks', '.*',
704 coreconfigitem('hooks', '.*',
705 default=dynamicdefault,
705 default=dynamicdefault,
706 generic=True,
706 generic=True,
707 )
707 )
708 coreconfigitem('hgweb-paths', '.*',
708 coreconfigitem('hgweb-paths', '.*',
709 default=list,
709 default=list,
710 generic=True,
710 generic=True,
711 )
711 )
712 coreconfigitem('hostfingerprints', '.*',
712 coreconfigitem('hostfingerprints', '.*',
713 default=list,
713 default=list,
714 generic=True,
714 generic=True,
715 )
715 )
716 coreconfigitem('hostsecurity', 'ciphers',
716 coreconfigitem('hostsecurity', 'ciphers',
717 default=None,
717 default=None,
718 )
718 )
719 coreconfigitem('hostsecurity', 'disabletls10warning',
719 coreconfigitem('hostsecurity', 'disabletls10warning',
720 default=False,
720 default=False,
721 )
721 )
722 coreconfigitem('hostsecurity', 'minimumprotocol',
722 coreconfigitem('hostsecurity', 'minimumprotocol',
723 default=dynamicdefault,
723 default=dynamicdefault,
724 )
724 )
725 coreconfigitem('hostsecurity', '.*:minimumprotocol$',
725 coreconfigitem('hostsecurity', '.*:minimumprotocol$',
726 default=dynamicdefault,
726 default=dynamicdefault,
727 generic=True,
727 generic=True,
728 )
728 )
729 coreconfigitem('hostsecurity', '.*:ciphers$',
729 coreconfigitem('hostsecurity', '.*:ciphers$',
730 default=dynamicdefault,
730 default=dynamicdefault,
731 generic=True,
731 generic=True,
732 )
732 )
733 coreconfigitem('hostsecurity', '.*:fingerprints$',
733 coreconfigitem('hostsecurity', '.*:fingerprints$',
734 default=list,
734 default=list,
735 generic=True,
735 generic=True,
736 )
736 )
737 coreconfigitem('hostsecurity', '.*:verifycertsfile$',
737 coreconfigitem('hostsecurity', '.*:verifycertsfile$',
738 default=None,
738 default=None,
739 generic=True,
739 generic=True,
740 )
740 )
741
741
742 coreconfigitem('http_proxy', 'always',
742 coreconfigitem('http_proxy', 'always',
743 default=False,
743 default=False,
744 )
744 )
745 coreconfigitem('http_proxy', 'host',
745 coreconfigitem('http_proxy', 'host',
746 default=None,
746 default=None,
747 )
747 )
748 coreconfigitem('http_proxy', 'no',
748 coreconfigitem('http_proxy', 'no',
749 default=list,
749 default=list,
750 )
750 )
751 coreconfigitem('http_proxy', 'passwd',
751 coreconfigitem('http_proxy', 'passwd',
752 default=None,
752 default=None,
753 )
753 )
754 coreconfigitem('http_proxy', 'user',
754 coreconfigitem('http_proxy', 'user',
755 default=None,
755 default=None,
756 )
756 )
757
757
758 coreconfigitem('http', 'timeout',
758 coreconfigitem('http', 'timeout',
759 default=None,
759 default=None,
760 )
760 )
761
761
762 coreconfigitem('logtoprocess', 'commandexception',
762 coreconfigitem('logtoprocess', 'commandexception',
763 default=None,
763 default=None,
764 )
764 )
765 coreconfigitem('logtoprocess', 'commandfinish',
765 coreconfigitem('logtoprocess', 'commandfinish',
766 default=None,
766 default=None,
767 )
767 )
768 coreconfigitem('logtoprocess', 'command',
768 coreconfigitem('logtoprocess', 'command',
769 default=None,
769 default=None,
770 )
770 )
771 coreconfigitem('logtoprocess', 'develwarn',
771 coreconfigitem('logtoprocess', 'develwarn',
772 default=None,
772 default=None,
773 )
773 )
774 coreconfigitem('logtoprocess', 'uiblocked',
774 coreconfigitem('logtoprocess', 'uiblocked',
775 default=None,
775 default=None,
776 )
776 )
777 coreconfigitem('merge', 'checkunknown',
777 coreconfigitem('merge', 'checkunknown',
778 default='abort',
778 default='abort',
779 )
779 )
780 coreconfigitem('merge', 'checkignored',
780 coreconfigitem('merge', 'checkignored',
781 default='abort',
781 default='abort',
782 )
782 )
783 coreconfigitem('experimental', 'merge.checkpathconflicts',
783 coreconfigitem('experimental', 'merge.checkpathconflicts',
784 default=False,
784 default=False,
785 )
785 )
786 coreconfigitem('merge', 'followcopies',
786 coreconfigitem('merge', 'followcopies',
787 default=True,
787 default=True,
788 )
788 )
789 coreconfigitem('merge', 'on-failure',
789 coreconfigitem('merge', 'on-failure',
790 default='continue',
790 default='continue',
791 )
791 )
792 coreconfigitem('merge', 'preferancestor',
792 coreconfigitem('merge', 'preferancestor',
793 default=lambda: ['*'],
793 default=lambda: ['*'],
794 )
794 )
795 coreconfigitem('merge', 'strict-capability-check',
795 coreconfigitem('merge', 'strict-capability-check',
796 default=False,
796 default=False,
797 )
797 )
798 coreconfigitem('merge-tools', '.*',
798 coreconfigitem('merge-tools', '.*',
799 default=None,
799 default=None,
800 generic=True,
800 generic=True,
801 )
801 )
802 coreconfigitem('merge-tools', br'.*\.args$',
802 coreconfigitem('merge-tools', br'.*\.args$',
803 default="$local $base $other",
803 default="$local $base $other",
804 generic=True,
804 generic=True,
805 priority=-1,
805 priority=-1,
806 )
806 )
807 coreconfigitem('merge-tools', br'.*\.binary$',
807 coreconfigitem('merge-tools', br'.*\.binary$',
808 default=False,
808 default=False,
809 generic=True,
809 generic=True,
810 priority=-1,
810 priority=-1,
811 )
811 )
812 coreconfigitem('merge-tools', br'.*\.check$',
812 coreconfigitem('merge-tools', br'.*\.check$',
813 default=list,
813 default=list,
814 generic=True,
814 generic=True,
815 priority=-1,
815 priority=-1,
816 )
816 )
817 coreconfigitem('merge-tools', br'.*\.checkchanged$',
817 coreconfigitem('merge-tools', br'.*\.checkchanged$',
818 default=False,
818 default=False,
819 generic=True,
819 generic=True,
820 priority=-1,
820 priority=-1,
821 )
821 )
822 coreconfigitem('merge-tools', br'.*\.executable$',
822 coreconfigitem('merge-tools', br'.*\.executable$',
823 default=dynamicdefault,
823 default=dynamicdefault,
824 generic=True,
824 generic=True,
825 priority=-1,
825 priority=-1,
826 )
826 )
827 coreconfigitem('merge-tools', br'.*\.fixeol$',
827 coreconfigitem('merge-tools', br'.*\.fixeol$',
828 default=False,
828 default=False,
829 generic=True,
829 generic=True,
830 priority=-1,
830 priority=-1,
831 )
831 )
832 coreconfigitem('merge-tools', br'.*\.gui$',
832 coreconfigitem('merge-tools', br'.*\.gui$',
833 default=False,
833 default=False,
834 generic=True,
834 generic=True,
835 priority=-1,
835 priority=-1,
836 )
836 )
837 coreconfigitem('merge-tools', br'.*\.mergemarkers$',
837 coreconfigitem('merge-tools', br'.*\.mergemarkers$',
838 default='basic',
838 default='basic',
839 generic=True,
839 generic=True,
840 priority=-1,
840 priority=-1,
841 )
841 )
842 coreconfigitem('merge-tools', br'.*\.mergemarkertemplate$',
842 coreconfigitem('merge-tools', br'.*\.mergemarkertemplate$',
843 default=dynamicdefault, # take from ui.mergemarkertemplate
843 default=dynamicdefault, # take from ui.mergemarkertemplate
844 generic=True,
844 generic=True,
845 priority=-1,
845 priority=-1,
846 )
846 )
847 coreconfigitem('merge-tools', br'.*\.priority$',
847 coreconfigitem('merge-tools', br'.*\.priority$',
848 default=0,
848 default=0,
849 generic=True,
849 generic=True,
850 priority=-1,
850 priority=-1,
851 )
851 )
852 coreconfigitem('merge-tools', br'.*\.premerge$',
852 coreconfigitem('merge-tools', br'.*\.premerge$',
853 default=dynamicdefault,
853 default=dynamicdefault,
854 generic=True,
854 generic=True,
855 priority=-1,
855 priority=-1,
856 )
856 )
857 coreconfigitem('merge-tools', br'.*\.symlink$',
857 coreconfigitem('merge-tools', br'.*\.symlink$',
858 default=False,
858 default=False,
859 generic=True,
859 generic=True,
860 priority=-1,
860 priority=-1,
861 )
861 )
862 coreconfigitem('pager', 'attend-.*',
862 coreconfigitem('pager', 'attend-.*',
863 default=dynamicdefault,
863 default=dynamicdefault,
864 generic=True,
864 generic=True,
865 )
865 )
866 coreconfigitem('pager', 'ignore',
866 coreconfigitem('pager', 'ignore',
867 default=list,
867 default=list,
868 )
868 )
869 coreconfigitem('pager', 'pager',
869 coreconfigitem('pager', 'pager',
870 default=dynamicdefault,
870 default=dynamicdefault,
871 )
871 )
872 coreconfigitem('patch', 'eol',
872 coreconfigitem('patch', 'eol',
873 default='strict',
873 default='strict',
874 )
874 )
875 coreconfigitem('patch', 'fuzz',
875 coreconfigitem('patch', 'fuzz',
876 default=2,
876 default=2,
877 )
877 )
878 coreconfigitem('paths', 'default',
878 coreconfigitem('paths', 'default',
879 default=None,
879 default=None,
880 )
880 )
881 coreconfigitem('paths', 'default-push',
881 coreconfigitem('paths', 'default-push',
882 default=None,
882 default=None,
883 )
883 )
884 coreconfigitem('paths', '.*',
884 coreconfigitem('paths', '.*',
885 default=None,
885 default=None,
886 generic=True,
886 generic=True,
887 )
887 )
888 coreconfigitem('phases', 'checksubrepos',
888 coreconfigitem('phases', 'checksubrepos',
889 default='follow',
889 default='follow',
890 )
890 )
891 coreconfigitem('phases', 'new-commit',
891 coreconfigitem('phases', 'new-commit',
892 default='draft',
892 default='draft',
893 )
893 )
894 coreconfigitem('phases', 'publish',
894 coreconfigitem('phases', 'publish',
895 default=True,
895 default=True,
896 )
896 )
897 coreconfigitem('profiling', 'enabled',
897 coreconfigitem('profiling', 'enabled',
898 default=False,
898 default=False,
899 )
899 )
900 coreconfigitem('profiling', 'format',
900 coreconfigitem('profiling', 'format',
901 default='text',
901 default='text',
902 )
902 )
903 coreconfigitem('profiling', 'freq',
903 coreconfigitem('profiling', 'freq',
904 default=1000,
904 default=1000,
905 )
905 )
906 coreconfigitem('profiling', 'limit',
906 coreconfigitem('profiling', 'limit',
907 default=30,
907 default=30,
908 )
908 )
909 coreconfigitem('profiling', 'nested',
909 coreconfigitem('profiling', 'nested',
910 default=0,
910 default=0,
911 )
911 )
912 coreconfigitem('profiling', 'output',
912 coreconfigitem('profiling', 'output',
913 default=None,
913 default=None,
914 )
914 )
915 coreconfigitem('profiling', 'showmax',
915 coreconfigitem('profiling', 'showmax',
916 default=0.999,
916 default=0.999,
917 )
917 )
918 coreconfigitem('profiling', 'showmin',
918 coreconfigitem('profiling', 'showmin',
919 default=dynamicdefault,
919 default=dynamicdefault,
920 )
920 )
921 coreconfigitem('profiling', 'sort',
921 coreconfigitem('profiling', 'sort',
922 default='inlinetime',
922 default='inlinetime',
923 )
923 )
924 coreconfigitem('profiling', 'statformat',
924 coreconfigitem('profiling', 'statformat',
925 default='hotpath',
925 default='hotpath',
926 )
926 )
927 coreconfigitem('profiling', 'time-track',
927 coreconfigitem('profiling', 'time-track',
928 default=dynamicdefault,
928 default=dynamicdefault,
929 )
929 )
930 coreconfigitem('profiling', 'type',
930 coreconfigitem('profiling', 'type',
931 default='stat',
931 default='stat',
932 )
932 )
933 coreconfigitem('progress', 'assume-tty',
933 coreconfigitem('progress', 'assume-tty',
934 default=False,
934 default=False,
935 )
935 )
936 coreconfigitem('progress', 'changedelay',
936 coreconfigitem('progress', 'changedelay',
937 default=1,
937 default=1,
938 )
938 )
939 coreconfigitem('progress', 'clear-complete',
939 coreconfigitem('progress', 'clear-complete',
940 default=True,
940 default=True,
941 )
941 )
942 coreconfigitem('progress', 'debug',
942 coreconfigitem('progress', 'debug',
943 default=False,
943 default=False,
944 )
944 )
945 coreconfigitem('progress', 'delay',
945 coreconfigitem('progress', 'delay',
946 default=3,
946 default=3,
947 )
947 )
948 coreconfigitem('progress', 'disable',
948 coreconfigitem('progress', 'disable',
949 default=False,
949 default=False,
950 )
950 )
951 coreconfigitem('progress', 'estimateinterval',
951 coreconfigitem('progress', 'estimateinterval',
952 default=60.0,
952 default=60.0,
953 )
953 )
954 coreconfigitem('progress', 'format',
954 coreconfigitem('progress', 'format',
955 default=lambda: ['topic', 'bar', 'number', 'estimate'],
955 default=lambda: ['topic', 'bar', 'number', 'estimate'],
956 )
956 )
957 coreconfigitem('progress', 'refresh',
957 coreconfigitem('progress', 'refresh',
958 default=0.1,
958 default=0.1,
959 )
959 )
960 coreconfigitem('progress', 'width',
960 coreconfigitem('progress', 'width',
961 default=dynamicdefault,
961 default=dynamicdefault,
962 )
962 )
963 coreconfigitem('push', 'pushvars.server',
963 coreconfigitem('push', 'pushvars.server',
964 default=False,
964 default=False,
965 )
965 )
966 coreconfigitem('rewrite', 'backup-bundle',
966 coreconfigitem('rewrite', 'backup-bundle',
967 default=True,
967 default=True,
968 alias=[('ui', 'history-editing-backup')],
968 alias=[('ui', 'history-editing-backup')],
969 )
969 )
970 coreconfigitem('rewrite', 'update-timestamp',
970 coreconfigitem('rewrite', 'update-timestamp',
971 default=False,
971 default=False,
972 )
972 )
973 coreconfigitem('storage', 'new-repo-backend',
973 coreconfigitem('storage', 'new-repo-backend',
974 default='revlogv1',
974 default='revlogv1',
975 )
975 )
976 coreconfigitem('storage', 'revlog.optimize-delta-parent-choice',
976 coreconfigitem('storage', 'revlog.optimize-delta-parent-choice',
977 default=True,
977 default=True,
978 alias=[('format', 'aggressivemergedeltas')],
978 alias=[('format', 'aggressivemergedeltas')],
979 )
979 )
980 coreconfigitem('server', 'bookmarks-pushkey-compat',
980 coreconfigitem('server', 'bookmarks-pushkey-compat',
981 default=True,
981 default=True,
982 )
982 )
983 coreconfigitem('server', 'bundle1',
983 coreconfigitem('server', 'bundle1',
984 default=True,
984 default=True,
985 )
985 )
986 coreconfigitem('server', 'bundle1gd',
986 coreconfigitem('server', 'bundle1gd',
987 default=None,
987 default=None,
988 )
988 )
989 coreconfigitem('server', 'bundle1.pull',
989 coreconfigitem('server', 'bundle1.pull',
990 default=None,
990 default=None,
991 )
991 )
992 coreconfigitem('server', 'bundle1gd.pull',
992 coreconfigitem('server', 'bundle1gd.pull',
993 default=None,
993 default=None,
994 )
994 )
995 coreconfigitem('server', 'bundle1.push',
995 coreconfigitem('server', 'bundle1.push',
996 default=None,
996 default=None,
997 )
997 )
998 coreconfigitem('server', 'bundle1gd.push',
998 coreconfigitem('server', 'bundle1gd.push',
999 default=None,
999 default=None,
1000 )
1000 )
1001 coreconfigitem('server', 'bundle2.stream',
1001 coreconfigitem('server', 'bundle2.stream',
1002 default=True,
1002 default=True,
1003 alias=[('experimental', 'bundle2.stream')]
1003 alias=[('experimental', 'bundle2.stream')]
1004 )
1004 )
1005 coreconfigitem('server', 'compressionengines',
1005 coreconfigitem('server', 'compressionengines',
1006 default=list,
1006 default=list,
1007 )
1007 )
1008 coreconfigitem('server', 'concurrent-push-mode',
1008 coreconfigitem('server', 'concurrent-push-mode',
1009 default='strict',
1009 default='strict',
1010 )
1010 )
1011 coreconfigitem('server', 'disablefullbundle',
1011 coreconfigitem('server', 'disablefullbundle',
1012 default=False,
1012 default=False,
1013 )
1013 )
1014 coreconfigitem('server', 'maxhttpheaderlen',
1014 coreconfigitem('server', 'maxhttpheaderlen',
1015 default=1024,
1015 default=1024,
1016 )
1016 )
1017 coreconfigitem('server', 'pullbundle',
1017 coreconfigitem('server', 'pullbundle',
1018 default=False,
1018 default=False,
1019 )
1019 )
1020 coreconfigitem('server', 'preferuncompressed',
1020 coreconfigitem('server', 'preferuncompressed',
1021 default=False,
1021 default=False,
1022 )
1022 )
1023 coreconfigitem('server', 'streamunbundle',
1023 coreconfigitem('server', 'streamunbundle',
1024 default=False,
1024 default=False,
1025 )
1025 )
1026 coreconfigitem('server', 'uncompressed',
1026 coreconfigitem('server', 'uncompressed',
1027 default=True,
1027 default=True,
1028 )
1028 )
1029 coreconfigitem('server', 'uncompressedallowsecret',
1029 coreconfigitem('server', 'uncompressedallowsecret',
1030 default=False,
1030 default=False,
1031 )
1031 )
1032 coreconfigitem('server', 'validate',
1032 coreconfigitem('server', 'validate',
1033 default=False,
1033 default=False,
1034 )
1034 )
1035 coreconfigitem('server', 'zliblevel',
1035 coreconfigitem('server', 'zliblevel',
1036 default=-1,
1036 default=-1,
1037 )
1037 )
1038 coreconfigitem('server', 'zstdlevel',
1038 coreconfigitem('server', 'zstdlevel',
1039 default=3,
1039 default=3,
1040 )
1040 )
1041 coreconfigitem('share', 'pool',
1041 coreconfigitem('share', 'pool',
1042 default=None,
1042 default=None,
1043 )
1043 )
1044 coreconfigitem('share', 'poolnaming',
1044 coreconfigitem('share', 'poolnaming',
1045 default='identity',
1045 default='identity',
1046 )
1046 )
1047 coreconfigitem('smtp', 'host',
1047 coreconfigitem('smtp', 'host',
1048 default=None,
1048 default=None,
1049 )
1049 )
1050 coreconfigitem('smtp', 'local_hostname',
1050 coreconfigitem('smtp', 'local_hostname',
1051 default=None,
1051 default=None,
1052 )
1052 )
1053 coreconfigitem('smtp', 'password',
1053 coreconfigitem('smtp', 'password',
1054 default=None,
1054 default=None,
1055 )
1055 )
1056 coreconfigitem('smtp', 'port',
1056 coreconfigitem('smtp', 'port',
1057 default=dynamicdefault,
1057 default=dynamicdefault,
1058 )
1058 )
1059 coreconfigitem('smtp', 'tls',
1059 coreconfigitem('smtp', 'tls',
1060 default='none',
1060 default='none',
1061 )
1061 )
1062 coreconfigitem('smtp', 'username',
1062 coreconfigitem('smtp', 'username',
1063 default=None,
1063 default=None,
1064 )
1064 )
1065 coreconfigitem('sparse', 'missingwarning',
1065 coreconfigitem('sparse', 'missingwarning',
1066 default=True,
1066 default=True,
1067 )
1067 )
1068 coreconfigitem('subrepos', 'allowed',
1068 coreconfigitem('subrepos', 'allowed',
1069 default=dynamicdefault, # to make backporting simpler
1069 default=dynamicdefault, # to make backporting simpler
1070 )
1070 )
1071 coreconfigitem('subrepos', 'hg:allowed',
1071 coreconfigitem('subrepos', 'hg:allowed',
1072 default=dynamicdefault,
1072 default=dynamicdefault,
1073 )
1073 )
1074 coreconfigitem('subrepos', 'git:allowed',
1074 coreconfigitem('subrepos', 'git:allowed',
1075 default=dynamicdefault,
1075 default=dynamicdefault,
1076 )
1076 )
1077 coreconfigitem('subrepos', 'svn:allowed',
1077 coreconfigitem('subrepos', 'svn:allowed',
1078 default=dynamicdefault,
1078 default=dynamicdefault,
1079 )
1079 )
1080 coreconfigitem('templates', '.*',
1080 coreconfigitem('templates', '.*',
1081 default=None,
1081 default=None,
1082 generic=True,
1082 generic=True,
1083 )
1083 )
1084 coreconfigitem('templateconfig', '.*',
1085 default=dynamicdefault,
1086 generic=True,
1087 )
1084 coreconfigitem('trusted', 'groups',
1088 coreconfigitem('trusted', 'groups',
1085 default=list,
1089 default=list,
1086 )
1090 )
1087 coreconfigitem('trusted', 'users',
1091 coreconfigitem('trusted', 'users',
1088 default=list,
1092 default=list,
1089 )
1093 )
1090 coreconfigitem('ui', '_usedassubrepo',
1094 coreconfigitem('ui', '_usedassubrepo',
1091 default=False,
1095 default=False,
1092 )
1096 )
1093 coreconfigitem('ui', 'allowemptycommit',
1097 coreconfigitem('ui', 'allowemptycommit',
1094 default=False,
1098 default=False,
1095 )
1099 )
1096 coreconfigitem('ui', 'archivemeta',
1100 coreconfigitem('ui', 'archivemeta',
1097 default=True,
1101 default=True,
1098 )
1102 )
1099 coreconfigitem('ui', 'askusername',
1103 coreconfigitem('ui', 'askusername',
1100 default=False,
1104 default=False,
1101 )
1105 )
1102 coreconfigitem('ui', 'clonebundlefallback',
1106 coreconfigitem('ui', 'clonebundlefallback',
1103 default=False,
1107 default=False,
1104 )
1108 )
1105 coreconfigitem('ui', 'clonebundleprefers',
1109 coreconfigitem('ui', 'clonebundleprefers',
1106 default=list,
1110 default=list,
1107 )
1111 )
1108 coreconfigitem('ui', 'clonebundles',
1112 coreconfigitem('ui', 'clonebundles',
1109 default=True,
1113 default=True,
1110 )
1114 )
1111 coreconfigitem('ui', 'color',
1115 coreconfigitem('ui', 'color',
1112 default='auto',
1116 default='auto',
1113 )
1117 )
1114 coreconfigitem('ui', 'commitsubrepos',
1118 coreconfigitem('ui', 'commitsubrepos',
1115 default=False,
1119 default=False,
1116 )
1120 )
1117 coreconfigitem('ui', 'debug',
1121 coreconfigitem('ui', 'debug',
1118 default=False,
1122 default=False,
1119 )
1123 )
1120 coreconfigitem('ui', 'debugger',
1124 coreconfigitem('ui', 'debugger',
1121 default=None,
1125 default=None,
1122 )
1126 )
1123 coreconfigitem('ui', 'editor',
1127 coreconfigitem('ui', 'editor',
1124 default=dynamicdefault,
1128 default=dynamicdefault,
1125 )
1129 )
1126 coreconfigitem('ui', 'fallbackencoding',
1130 coreconfigitem('ui', 'fallbackencoding',
1127 default=None,
1131 default=None,
1128 )
1132 )
1129 coreconfigitem('ui', 'forcecwd',
1133 coreconfigitem('ui', 'forcecwd',
1130 default=None,
1134 default=None,
1131 )
1135 )
1132 coreconfigitem('ui', 'forcemerge',
1136 coreconfigitem('ui', 'forcemerge',
1133 default=None,
1137 default=None,
1134 )
1138 )
1135 coreconfigitem('ui', 'formatdebug',
1139 coreconfigitem('ui', 'formatdebug',
1136 default=False,
1140 default=False,
1137 )
1141 )
1138 coreconfigitem('ui', 'formatjson',
1142 coreconfigitem('ui', 'formatjson',
1139 default=False,
1143 default=False,
1140 )
1144 )
1141 coreconfigitem('ui', 'formatted',
1145 coreconfigitem('ui', 'formatted',
1142 default=None,
1146 default=None,
1143 )
1147 )
1144 coreconfigitem('ui', 'graphnodetemplate',
1148 coreconfigitem('ui', 'graphnodetemplate',
1145 default=None,
1149 default=None,
1146 )
1150 )
1147 coreconfigitem('ui', 'interactive',
1151 coreconfigitem('ui', 'interactive',
1148 default=None,
1152 default=None,
1149 )
1153 )
1150 coreconfigitem('ui', 'interface',
1154 coreconfigitem('ui', 'interface',
1151 default=None,
1155 default=None,
1152 )
1156 )
1153 coreconfigitem('ui', 'interface.chunkselector',
1157 coreconfigitem('ui', 'interface.chunkselector',
1154 default=None,
1158 default=None,
1155 )
1159 )
1156 coreconfigitem('ui', 'large-file-limit',
1160 coreconfigitem('ui', 'large-file-limit',
1157 default=10000000,
1161 default=10000000,
1158 )
1162 )
1159 coreconfigitem('ui', 'logblockedtimes',
1163 coreconfigitem('ui', 'logblockedtimes',
1160 default=False,
1164 default=False,
1161 )
1165 )
1162 coreconfigitem('ui', 'logtemplate',
1166 coreconfigitem('ui', 'logtemplate',
1163 default=None,
1167 default=None,
1164 )
1168 )
1165 coreconfigitem('ui', 'merge',
1169 coreconfigitem('ui', 'merge',
1166 default=None,
1170 default=None,
1167 )
1171 )
1168 coreconfigitem('ui', 'mergemarkers',
1172 coreconfigitem('ui', 'mergemarkers',
1169 default='basic',
1173 default='basic',
1170 )
1174 )
1171 coreconfigitem('ui', 'mergemarkertemplate',
1175 coreconfigitem('ui', 'mergemarkertemplate',
1172 default=('{node|short} '
1176 default=('{node|short} '
1173 '{ifeq(tags, "tip", "", '
1177 '{ifeq(tags, "tip", "", '
1174 'ifeq(tags, "", "", "{tags} "))}'
1178 'ifeq(tags, "", "", "{tags} "))}'
1175 '{if(bookmarks, "{bookmarks} ")}'
1179 '{if(bookmarks, "{bookmarks} ")}'
1176 '{ifeq(branch, "default", "", "{branch} ")}'
1180 '{ifeq(branch, "default", "", "{branch} ")}'
1177 '- {author|user}: {desc|firstline}')
1181 '- {author|user}: {desc|firstline}')
1178 )
1182 )
1179 coreconfigitem('ui', 'message-output',
1183 coreconfigitem('ui', 'message-output',
1180 default='stdio',
1184 default='stdio',
1181 )
1185 )
1182 coreconfigitem('ui', 'nontty',
1186 coreconfigitem('ui', 'nontty',
1183 default=False,
1187 default=False,
1184 )
1188 )
1185 coreconfigitem('ui', 'origbackuppath',
1189 coreconfigitem('ui', 'origbackuppath',
1186 default=None,
1190 default=None,
1187 )
1191 )
1188 coreconfigitem('ui', 'paginate',
1192 coreconfigitem('ui', 'paginate',
1189 default=True,
1193 default=True,
1190 )
1194 )
1191 coreconfigitem('ui', 'patch',
1195 coreconfigitem('ui', 'patch',
1192 default=None,
1196 default=None,
1193 )
1197 )
1194 coreconfigitem('ui', 'pre-merge-tool-output-template',
1198 coreconfigitem('ui', 'pre-merge-tool-output-template',
1195 default=None,
1199 default=None,
1196 )
1200 )
1197 coreconfigitem('ui', 'portablefilenames',
1201 coreconfigitem('ui', 'portablefilenames',
1198 default='warn',
1202 default='warn',
1199 )
1203 )
1200 coreconfigitem('ui', 'promptecho',
1204 coreconfigitem('ui', 'promptecho',
1201 default=False,
1205 default=False,
1202 )
1206 )
1203 coreconfigitem('ui', 'quiet',
1207 coreconfigitem('ui', 'quiet',
1204 default=False,
1208 default=False,
1205 )
1209 )
1206 coreconfigitem('ui', 'quietbookmarkmove',
1210 coreconfigitem('ui', 'quietbookmarkmove',
1207 default=False,
1211 default=False,
1208 )
1212 )
1209 coreconfigitem('ui', 'relative-paths',
1213 coreconfigitem('ui', 'relative-paths',
1210 default='legacy',
1214 default='legacy',
1211 )
1215 )
1212 coreconfigitem('ui', 'remotecmd',
1216 coreconfigitem('ui', 'remotecmd',
1213 default='hg',
1217 default='hg',
1214 )
1218 )
1215 coreconfigitem('ui', 'report_untrusted',
1219 coreconfigitem('ui', 'report_untrusted',
1216 default=True,
1220 default=True,
1217 )
1221 )
1218 coreconfigitem('ui', 'rollback',
1222 coreconfigitem('ui', 'rollback',
1219 default=True,
1223 default=True,
1220 )
1224 )
1221 coreconfigitem('ui', 'signal-safe-lock',
1225 coreconfigitem('ui', 'signal-safe-lock',
1222 default=True,
1226 default=True,
1223 )
1227 )
1224 coreconfigitem('ui', 'slash',
1228 coreconfigitem('ui', 'slash',
1225 default=False,
1229 default=False,
1226 )
1230 )
1227 coreconfigitem('ui', 'ssh',
1231 coreconfigitem('ui', 'ssh',
1228 default='ssh',
1232 default='ssh',
1229 )
1233 )
1230 coreconfigitem('ui', 'ssherrorhint',
1234 coreconfigitem('ui', 'ssherrorhint',
1231 default=None,
1235 default=None,
1232 )
1236 )
1233 coreconfigitem('ui', 'statuscopies',
1237 coreconfigitem('ui', 'statuscopies',
1234 default=False,
1238 default=False,
1235 )
1239 )
1236 coreconfigitem('ui', 'strict',
1240 coreconfigitem('ui', 'strict',
1237 default=False,
1241 default=False,
1238 )
1242 )
1239 coreconfigitem('ui', 'style',
1243 coreconfigitem('ui', 'style',
1240 default='',
1244 default='',
1241 )
1245 )
1242 coreconfigitem('ui', 'supportcontact',
1246 coreconfigitem('ui', 'supportcontact',
1243 default=None,
1247 default=None,
1244 )
1248 )
1245 coreconfigitem('ui', 'textwidth',
1249 coreconfigitem('ui', 'textwidth',
1246 default=78,
1250 default=78,
1247 )
1251 )
1248 coreconfigitem('ui', 'timeout',
1252 coreconfigitem('ui', 'timeout',
1249 default='600',
1253 default='600',
1250 )
1254 )
1251 coreconfigitem('ui', 'timeout.warn',
1255 coreconfigitem('ui', 'timeout.warn',
1252 default=0,
1256 default=0,
1253 )
1257 )
1254 coreconfigitem('ui', 'traceback',
1258 coreconfigitem('ui', 'traceback',
1255 default=False,
1259 default=False,
1256 )
1260 )
1257 coreconfigitem('ui', 'tweakdefaults',
1261 coreconfigitem('ui', 'tweakdefaults',
1258 default=False,
1262 default=False,
1259 )
1263 )
1260 coreconfigitem('ui', 'username',
1264 coreconfigitem('ui', 'username',
1261 alias=[('ui', 'user')]
1265 alias=[('ui', 'user')]
1262 )
1266 )
1263 coreconfigitem('ui', 'verbose',
1267 coreconfigitem('ui', 'verbose',
1264 default=False,
1268 default=False,
1265 )
1269 )
1266 coreconfigitem('verify', 'skipflags',
1270 coreconfigitem('verify', 'skipflags',
1267 default=None,
1271 default=None,
1268 )
1272 )
1269 coreconfigitem('web', 'allowbz2',
1273 coreconfigitem('web', 'allowbz2',
1270 default=False,
1274 default=False,
1271 )
1275 )
1272 coreconfigitem('web', 'allowgz',
1276 coreconfigitem('web', 'allowgz',
1273 default=False,
1277 default=False,
1274 )
1278 )
1275 coreconfigitem('web', 'allow-pull',
1279 coreconfigitem('web', 'allow-pull',
1276 alias=[('web', 'allowpull')],
1280 alias=[('web', 'allowpull')],
1277 default=True,
1281 default=True,
1278 )
1282 )
1279 coreconfigitem('web', 'allow-push',
1283 coreconfigitem('web', 'allow-push',
1280 alias=[('web', 'allow_push')],
1284 alias=[('web', 'allow_push')],
1281 default=list,
1285 default=list,
1282 )
1286 )
1283 coreconfigitem('web', 'allowzip',
1287 coreconfigitem('web', 'allowzip',
1284 default=False,
1288 default=False,
1285 )
1289 )
1286 coreconfigitem('web', 'archivesubrepos',
1290 coreconfigitem('web', 'archivesubrepos',
1287 default=False,
1291 default=False,
1288 )
1292 )
1289 coreconfigitem('web', 'cache',
1293 coreconfigitem('web', 'cache',
1290 default=True,
1294 default=True,
1291 )
1295 )
1292 coreconfigitem('web', 'comparisoncontext',
1296 coreconfigitem('web', 'comparisoncontext',
1293 default=5,
1297 default=5,
1294 )
1298 )
1295 coreconfigitem('web', 'contact',
1299 coreconfigitem('web', 'contact',
1296 default=None,
1300 default=None,
1297 )
1301 )
1298 coreconfigitem('web', 'deny_push',
1302 coreconfigitem('web', 'deny_push',
1299 default=list,
1303 default=list,
1300 )
1304 )
1301 coreconfigitem('web', 'guessmime',
1305 coreconfigitem('web', 'guessmime',
1302 default=False,
1306 default=False,
1303 )
1307 )
1304 coreconfigitem('web', 'hidden',
1308 coreconfigitem('web', 'hidden',
1305 default=False,
1309 default=False,
1306 )
1310 )
1307 coreconfigitem('web', 'labels',
1311 coreconfigitem('web', 'labels',
1308 default=list,
1312 default=list,
1309 )
1313 )
1310 coreconfigitem('web', 'logoimg',
1314 coreconfigitem('web', 'logoimg',
1311 default='hglogo.png',
1315 default='hglogo.png',
1312 )
1316 )
1313 coreconfigitem('web', 'logourl',
1317 coreconfigitem('web', 'logourl',
1314 default='https://mercurial-scm.org/',
1318 default='https://mercurial-scm.org/',
1315 )
1319 )
1316 coreconfigitem('web', 'accesslog',
1320 coreconfigitem('web', 'accesslog',
1317 default='-',
1321 default='-',
1318 )
1322 )
1319 coreconfigitem('web', 'address',
1323 coreconfigitem('web', 'address',
1320 default='',
1324 default='',
1321 )
1325 )
1322 coreconfigitem('web', 'allow-archive',
1326 coreconfigitem('web', 'allow-archive',
1323 alias=[('web', 'allow_archive')],
1327 alias=[('web', 'allow_archive')],
1324 default=list,
1328 default=list,
1325 )
1329 )
1326 coreconfigitem('web', 'allow_read',
1330 coreconfigitem('web', 'allow_read',
1327 default=list,
1331 default=list,
1328 )
1332 )
1329 coreconfigitem('web', 'baseurl',
1333 coreconfigitem('web', 'baseurl',
1330 default=None,
1334 default=None,
1331 )
1335 )
1332 coreconfigitem('web', 'cacerts',
1336 coreconfigitem('web', 'cacerts',
1333 default=None,
1337 default=None,
1334 )
1338 )
1335 coreconfigitem('web', 'certificate',
1339 coreconfigitem('web', 'certificate',
1336 default=None,
1340 default=None,
1337 )
1341 )
1338 coreconfigitem('web', 'collapse',
1342 coreconfigitem('web', 'collapse',
1339 default=False,
1343 default=False,
1340 )
1344 )
1341 coreconfigitem('web', 'csp',
1345 coreconfigitem('web', 'csp',
1342 default=None,
1346 default=None,
1343 )
1347 )
1344 coreconfigitem('web', 'deny_read',
1348 coreconfigitem('web', 'deny_read',
1345 default=list,
1349 default=list,
1346 )
1350 )
1347 coreconfigitem('web', 'descend',
1351 coreconfigitem('web', 'descend',
1348 default=True,
1352 default=True,
1349 )
1353 )
1350 coreconfigitem('web', 'description',
1354 coreconfigitem('web', 'description',
1351 default="",
1355 default="",
1352 )
1356 )
1353 coreconfigitem('web', 'encoding',
1357 coreconfigitem('web', 'encoding',
1354 default=lambda: encoding.encoding,
1358 default=lambda: encoding.encoding,
1355 )
1359 )
1356 coreconfigitem('web', 'errorlog',
1360 coreconfigitem('web', 'errorlog',
1357 default='-',
1361 default='-',
1358 )
1362 )
1359 coreconfigitem('web', 'ipv6',
1363 coreconfigitem('web', 'ipv6',
1360 default=False,
1364 default=False,
1361 )
1365 )
1362 coreconfigitem('web', 'maxchanges',
1366 coreconfigitem('web', 'maxchanges',
1363 default=10,
1367 default=10,
1364 )
1368 )
1365 coreconfigitem('web', 'maxfiles',
1369 coreconfigitem('web', 'maxfiles',
1366 default=10,
1370 default=10,
1367 )
1371 )
1368 coreconfigitem('web', 'maxshortchanges',
1372 coreconfigitem('web', 'maxshortchanges',
1369 default=60,
1373 default=60,
1370 )
1374 )
1371 coreconfigitem('web', 'motd',
1375 coreconfigitem('web', 'motd',
1372 default='',
1376 default='',
1373 )
1377 )
1374 coreconfigitem('web', 'name',
1378 coreconfigitem('web', 'name',
1375 default=dynamicdefault,
1379 default=dynamicdefault,
1376 )
1380 )
1377 coreconfigitem('web', 'port',
1381 coreconfigitem('web', 'port',
1378 default=8000,
1382 default=8000,
1379 )
1383 )
1380 coreconfigitem('web', 'prefix',
1384 coreconfigitem('web', 'prefix',
1381 default='',
1385 default='',
1382 )
1386 )
1383 coreconfigitem('web', 'push_ssl',
1387 coreconfigitem('web', 'push_ssl',
1384 default=True,
1388 default=True,
1385 )
1389 )
1386 coreconfigitem('web', 'refreshinterval',
1390 coreconfigitem('web', 'refreshinterval',
1387 default=20,
1391 default=20,
1388 )
1392 )
1389 coreconfigitem('web', 'server-header',
1393 coreconfigitem('web', 'server-header',
1390 default=None,
1394 default=None,
1391 )
1395 )
1392 coreconfigitem('web', 'static',
1396 coreconfigitem('web', 'static',
1393 default=None,
1397 default=None,
1394 )
1398 )
1395 coreconfigitem('web', 'staticurl',
1399 coreconfigitem('web', 'staticurl',
1396 default=None,
1400 default=None,
1397 )
1401 )
1398 coreconfigitem('web', 'stripes',
1402 coreconfigitem('web', 'stripes',
1399 default=1,
1403 default=1,
1400 )
1404 )
1401 coreconfigitem('web', 'style',
1405 coreconfigitem('web', 'style',
1402 default='paper',
1406 default='paper',
1403 )
1407 )
1404 coreconfigitem('web', 'templates',
1408 coreconfigitem('web', 'templates',
1405 default=None,
1409 default=None,
1406 )
1410 )
1407 coreconfigitem('web', 'view',
1411 coreconfigitem('web', 'view',
1408 default='served',
1412 default='served',
1409 )
1413 )
1410 coreconfigitem('worker', 'backgroundclose',
1414 coreconfigitem('worker', 'backgroundclose',
1411 default=dynamicdefault,
1415 default=dynamicdefault,
1412 )
1416 )
1413 # Windows defaults to a limit of 512 open files. A buffer of 128
1417 # Windows defaults to a limit of 512 open files. A buffer of 128
1414 # should give us enough headway.
1418 # should give us enough headway.
1415 coreconfigitem('worker', 'backgroundclosemaxqueue',
1419 coreconfigitem('worker', 'backgroundclosemaxqueue',
1416 default=384,
1420 default=384,
1417 )
1421 )
1418 coreconfigitem('worker', 'backgroundcloseminfilecount',
1422 coreconfigitem('worker', 'backgroundcloseminfilecount',
1419 default=2048,
1423 default=2048,
1420 )
1424 )
1421 coreconfigitem('worker', 'backgroundclosethreadcount',
1425 coreconfigitem('worker', 'backgroundclosethreadcount',
1422 default=4,
1426 default=4,
1423 )
1427 )
1424 coreconfigitem('worker', 'enabled',
1428 coreconfigitem('worker', 'enabled',
1425 default=True,
1429 default=True,
1426 )
1430 )
1427 coreconfigitem('worker', 'numcpus',
1431 coreconfigitem('worker', 'numcpus',
1428 default=None,
1432 default=None,
1429 )
1433 )
1430
1434
1431 # Rebase related configuration moved to core because other extension are doing
1435 # Rebase related configuration moved to core because other extension are doing
1432 # strange things. For example, shelve import the extensions to reuse some bit
1436 # strange things. For example, shelve import the extensions to reuse some bit
1433 # without formally loading it.
1437 # without formally loading it.
1434 coreconfigitem('commands', 'rebase.requiredest',
1438 coreconfigitem('commands', 'rebase.requiredest',
1435 default=False,
1439 default=False,
1436 )
1440 )
1437 coreconfigitem('experimental', 'rebaseskipobsolete',
1441 coreconfigitem('experimental', 'rebaseskipobsolete',
1438 default=True,
1442 default=True,
1439 )
1443 )
1440 coreconfigitem('rebase', 'singletransaction',
1444 coreconfigitem('rebase', 'singletransaction',
1441 default=False,
1445 default=False,
1442 )
1446 )
1443 coreconfigitem('rebase', 'experimental.inmemory',
1447 coreconfigitem('rebase', 'experimental.inmemory',
1444 default=False,
1448 default=False,
1445 )
1449 )
@@ -1,757 +1,790
1 # templatefuncs.py - common template functions
1 # templatefuncs.py - common template functions
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 re
10 import re
11
11
12 from .i18n import _
12 from .i18n import _
13 from .node import (
13 from .node import (
14 bin,
14 bin,
15 wdirid,
15 wdirid,
16 )
16 )
17 from . import (
17 from . import (
18 color,
18 color,
19 encoding,
19 encoding,
20 error,
20 error,
21 minirst,
21 minirst,
22 obsutil,
22 obsutil,
23 pycompat,
23 pycompat,
24 registrar,
24 registrar,
25 revset as revsetmod,
25 revset as revsetmod,
26 revsetlang,
26 revsetlang,
27 scmutil,
27 scmutil,
28 templatefilters,
28 templatefilters,
29 templatekw,
29 templatekw,
30 templateutil,
30 templateutil,
31 util,
31 util,
32 )
32 )
33 from .utils import (
33 from .utils import (
34 dateutil,
34 dateutil,
35 stringutil,
35 stringutil,
36 )
36 )
37
37
38 evalrawexp = templateutil.evalrawexp
38 evalrawexp = templateutil.evalrawexp
39 evalwrapped = templateutil.evalwrapped
39 evalwrapped = templateutil.evalwrapped
40 evalfuncarg = templateutil.evalfuncarg
40 evalfuncarg = templateutil.evalfuncarg
41 evalboolean = templateutil.evalboolean
41 evalboolean = templateutil.evalboolean
42 evaldate = templateutil.evaldate
42 evaldate = templateutil.evaldate
43 evalinteger = templateutil.evalinteger
43 evalinteger = templateutil.evalinteger
44 evalstring = templateutil.evalstring
44 evalstring = templateutil.evalstring
45 evalstringliteral = templateutil.evalstringliteral
45 evalstringliteral = templateutil.evalstringliteral
46
46
47 # dict of template built-in functions
47 # dict of template built-in functions
48 funcs = {}
48 funcs = {}
49 templatefunc = registrar.templatefunc(funcs)
49 templatefunc = registrar.templatefunc(funcs)
50
50
51 @templatefunc('date(date[, fmt])')
51 @templatefunc('date(date[, fmt])')
52 def date(context, mapping, args):
52 def date(context, mapping, args):
53 """Format a date. See :hg:`help dates` for formatting
53 """Format a date. See :hg:`help dates` for formatting
54 strings. The default is a Unix date format, including the timezone:
54 strings. The default is a Unix date format, including the timezone:
55 "Mon Sep 04 15:13:13 2006 0700"."""
55 "Mon Sep 04 15:13:13 2006 0700"."""
56 if not (1 <= len(args) <= 2):
56 if not (1 <= len(args) <= 2):
57 # i18n: "date" is a keyword
57 # i18n: "date" is a keyword
58 raise error.ParseError(_("date expects one or two arguments"))
58 raise error.ParseError(_("date expects one or two arguments"))
59
59
60 date = evaldate(context, mapping, args[0],
60 date = evaldate(context, mapping, args[0],
61 # i18n: "date" is a keyword
61 # i18n: "date" is a keyword
62 _("date expects a date information"))
62 _("date expects a date information"))
63 fmt = None
63 fmt = None
64 if len(args) == 2:
64 if len(args) == 2:
65 fmt = evalstring(context, mapping, args[1])
65 fmt = evalstring(context, mapping, args[1])
66 if fmt is None:
66 if fmt is None:
67 return dateutil.datestr(date)
67 return dateutil.datestr(date)
68 else:
68 else:
69 return dateutil.datestr(date, fmt)
69 return dateutil.datestr(date, fmt)
70
70
71 @templatefunc('dict([[key=]value...])', argspec='*args **kwargs')
71 @templatefunc('dict([[key=]value...])', argspec='*args **kwargs')
72 def dict_(context, mapping, args):
72 def dict_(context, mapping, args):
73 """Construct a dict from key-value pairs. A key may be omitted if
73 """Construct a dict from key-value pairs. A key may be omitted if
74 a value expression can provide an unambiguous name."""
74 a value expression can provide an unambiguous name."""
75 data = util.sortdict()
75 data = util.sortdict()
76
76
77 for v in args['args']:
77 for v in args['args']:
78 k = templateutil.findsymbolicname(v)
78 k = templateutil.findsymbolicname(v)
79 if not k:
79 if not k:
80 raise error.ParseError(_('dict key cannot be inferred'))
80 raise error.ParseError(_('dict key cannot be inferred'))
81 if k in data or k in args['kwargs']:
81 if k in data or k in args['kwargs']:
82 raise error.ParseError(_("duplicated dict key '%s' inferred") % k)
82 raise error.ParseError(_("duplicated dict key '%s' inferred") % k)
83 data[k] = evalfuncarg(context, mapping, v)
83 data[k] = evalfuncarg(context, mapping, v)
84
84
85 data.update((k, evalfuncarg(context, mapping, v))
85 data.update((k, evalfuncarg(context, mapping, v))
86 for k, v in args['kwargs'].iteritems())
86 for k, v in args['kwargs'].iteritems())
87 return templateutil.hybriddict(data)
87 return templateutil.hybriddict(data)
88
88
89 @templatefunc('diff([includepattern [, excludepattern]])', requires={'ctx'})
89 @templatefunc('diff([includepattern [, excludepattern]])', requires={'ctx'})
90 def diff(context, mapping, args):
90 def diff(context, mapping, args):
91 """Show a diff, optionally
91 """Show a diff, optionally
92 specifying files to include or exclude."""
92 specifying files to include or exclude."""
93 if len(args) > 2:
93 if len(args) > 2:
94 # i18n: "diff" is a keyword
94 # i18n: "diff" is a keyword
95 raise error.ParseError(_("diff expects zero, one, or two arguments"))
95 raise error.ParseError(_("diff expects zero, one, or two arguments"))
96
96
97 def getpatterns(i):
97 def getpatterns(i):
98 if i < len(args):
98 if i < len(args):
99 s = evalstring(context, mapping, args[i]).strip()
99 s = evalstring(context, mapping, args[i]).strip()
100 if s:
100 if s:
101 return [s]
101 return [s]
102 return []
102 return []
103
103
104 ctx = context.resource(mapping, 'ctx')
104 ctx = context.resource(mapping, 'ctx')
105 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
105 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
106
106
107 return ''.join(chunks)
107 return ''.join(chunks)
108
108
109 @templatefunc('extdata(source)', argspec='source', requires={'ctx', 'cache'})
109 @templatefunc('extdata(source)', argspec='source', requires={'ctx', 'cache'})
110 def extdata(context, mapping, args):
110 def extdata(context, mapping, args):
111 """Show a text read from the specified extdata source. (EXPERIMENTAL)"""
111 """Show a text read from the specified extdata source. (EXPERIMENTAL)"""
112 if 'source' not in args:
112 if 'source' not in args:
113 # i18n: "extdata" is a keyword
113 # i18n: "extdata" is a keyword
114 raise error.ParseError(_('extdata expects one argument'))
114 raise error.ParseError(_('extdata expects one argument'))
115
115
116 source = evalstring(context, mapping, args['source'])
116 source = evalstring(context, mapping, args['source'])
117 if not source:
117 if not source:
118 sym = templateutil.findsymbolicname(args['source'])
118 sym = templateutil.findsymbolicname(args['source'])
119 if sym:
119 if sym:
120 raise error.ParseError(_('empty data source specified'),
120 raise error.ParseError(_('empty data source specified'),
121 hint=_("did you mean extdata('%s')?") % sym)
121 hint=_("did you mean extdata('%s')?") % sym)
122 else:
122 else:
123 raise error.ParseError(_('empty data source specified'))
123 raise error.ParseError(_('empty data source specified'))
124 cache = context.resource(mapping, 'cache').setdefault('extdata', {})
124 cache = context.resource(mapping, 'cache').setdefault('extdata', {})
125 ctx = context.resource(mapping, 'ctx')
125 ctx = context.resource(mapping, 'ctx')
126 if source in cache:
126 if source in cache:
127 data = cache[source]
127 data = cache[source]
128 else:
128 else:
129 data = cache[source] = scmutil.extdatasource(ctx.repo(), source)
129 data = cache[source] = scmutil.extdatasource(ctx.repo(), source)
130 return data.get(ctx.rev(), '')
130 return data.get(ctx.rev(), '')
131
131
132 @templatefunc('files(pattern)', requires={'ctx'})
132 @templatefunc('files(pattern)', requires={'ctx'})
133 def files(context, mapping, args):
133 def files(context, mapping, args):
134 """All files of the current changeset matching the pattern. See
134 """All files of the current changeset matching the pattern. See
135 :hg:`help patterns`."""
135 :hg:`help patterns`."""
136 if not len(args) == 1:
136 if not len(args) == 1:
137 # i18n: "files" is a keyword
137 # i18n: "files" is a keyword
138 raise error.ParseError(_("files expects one argument"))
138 raise error.ParseError(_("files expects one argument"))
139
139
140 raw = evalstring(context, mapping, args[0])
140 raw = evalstring(context, mapping, args[0])
141 ctx = context.resource(mapping, 'ctx')
141 ctx = context.resource(mapping, 'ctx')
142 m = ctx.match([raw])
142 m = ctx.match([raw])
143 files = list(ctx.matches(m))
143 files = list(ctx.matches(m))
144 return templateutil.compatfileslist(context, mapping, "file", files)
144 return templateutil.compatfileslist(context, mapping, "file", files)
145
145
146 @templatefunc('fill(text[, width[, initialident[, hangindent]]])')
146 @templatefunc('fill(text[, width[, initialident[, hangindent]]])')
147 def fill(context, mapping, args):
147 def fill(context, mapping, args):
148 """Fill many
148 """Fill many
149 paragraphs with optional indentation. See the "fill" filter."""
149 paragraphs with optional indentation. See the "fill" filter."""
150 if not (1 <= len(args) <= 4):
150 if not (1 <= len(args) <= 4):
151 # i18n: "fill" is a keyword
151 # i18n: "fill" is a keyword
152 raise error.ParseError(_("fill expects one to four arguments"))
152 raise error.ParseError(_("fill expects one to four arguments"))
153
153
154 text = evalstring(context, mapping, args[0])
154 text = evalstring(context, mapping, args[0])
155 width = 76
155 width = 76
156 initindent = ''
156 initindent = ''
157 hangindent = ''
157 hangindent = ''
158 if 2 <= len(args) <= 4:
158 if 2 <= len(args) <= 4:
159 width = evalinteger(context, mapping, args[1],
159 width = evalinteger(context, mapping, args[1],
160 # i18n: "fill" is a keyword
160 # i18n: "fill" is a keyword
161 _("fill expects an integer width"))
161 _("fill expects an integer width"))
162 try:
162 try:
163 initindent = evalstring(context, mapping, args[2])
163 initindent = evalstring(context, mapping, args[2])
164 hangindent = evalstring(context, mapping, args[3])
164 hangindent = evalstring(context, mapping, args[3])
165 except IndexError:
165 except IndexError:
166 pass
166 pass
167
167
168 return templatefilters.fill(text, width, initindent, hangindent)
168 return templatefilters.fill(text, width, initindent, hangindent)
169
169
170 @templatefunc('filter(iterable[, expr])')
170 @templatefunc('filter(iterable[, expr])')
171 def filter_(context, mapping, args):
171 def filter_(context, mapping, args):
172 """Remove empty elements from a list or a dict. If expr specified, it's
172 """Remove empty elements from a list or a dict. If expr specified, it's
173 applied to each element to test emptiness."""
173 applied to each element to test emptiness."""
174 if not (1 <= len(args) <= 2):
174 if not (1 <= len(args) <= 2):
175 # i18n: "filter" is a keyword
175 # i18n: "filter" is a keyword
176 raise error.ParseError(_("filter expects one or two arguments"))
176 raise error.ParseError(_("filter expects one or two arguments"))
177 iterable = evalwrapped(context, mapping, args[0])
177 iterable = evalwrapped(context, mapping, args[0])
178 if len(args) == 1:
178 if len(args) == 1:
179 def select(w):
179 def select(w):
180 return w.tobool(context, mapping)
180 return w.tobool(context, mapping)
181 else:
181 else:
182 def select(w):
182 def select(w):
183 if not isinstance(w, templateutil.mappable):
183 if not isinstance(w, templateutil.mappable):
184 raise error.ParseError(_("not filterable by expression"))
184 raise error.ParseError(_("not filterable by expression"))
185 lm = context.overlaymap(mapping, w.tomap(context))
185 lm = context.overlaymap(mapping, w.tomap(context))
186 return evalboolean(context, lm, args[1])
186 return evalboolean(context, lm, args[1])
187 return iterable.filter(context, mapping, select)
187 return iterable.filter(context, mapping, select)
188
188
189 @templatefunc('formatnode(node)', requires={'ui'})
189 @templatefunc('formatnode(node)', requires={'ui'})
190 def formatnode(context, mapping, args):
190 def formatnode(context, mapping, args):
191 """Obtain the preferred form of a changeset hash. (DEPRECATED)"""
191 """Obtain the preferred form of a changeset hash. (DEPRECATED)"""
192 if len(args) != 1:
192 if len(args) != 1:
193 # i18n: "formatnode" is a keyword
193 # i18n: "formatnode" is a keyword
194 raise error.ParseError(_("formatnode expects one argument"))
194 raise error.ParseError(_("formatnode expects one argument"))
195
195
196 ui = context.resource(mapping, 'ui')
196 ui = context.resource(mapping, 'ui')
197 node = evalstring(context, mapping, args[0])
197 node = evalstring(context, mapping, args[0])
198 if ui.debugflag:
198 if ui.debugflag:
199 return node
199 return node
200 return templatefilters.short(node)
200 return templatefilters.short(node)
201
201
202 @templatefunc('mailmap(author)', requires={'repo', 'cache'})
202 @templatefunc('mailmap(author)', requires={'repo', 'cache'})
203 def mailmap(context, mapping, args):
203 def mailmap(context, mapping, args):
204 """Return the author, updated according to the value
204 """Return the author, updated according to the value
205 set in the .mailmap file"""
205 set in the .mailmap file"""
206 if len(args) != 1:
206 if len(args) != 1:
207 raise error.ParseError(_("mailmap expects one argument"))
207 raise error.ParseError(_("mailmap expects one argument"))
208
208
209 author = evalstring(context, mapping, args[0])
209 author = evalstring(context, mapping, args[0])
210
210
211 cache = context.resource(mapping, 'cache')
211 cache = context.resource(mapping, 'cache')
212 repo = context.resource(mapping, 'repo')
212 repo = context.resource(mapping, 'repo')
213
213
214 if 'mailmap' not in cache:
214 if 'mailmap' not in cache:
215 data = repo.wvfs.tryread('.mailmap')
215 data = repo.wvfs.tryread('.mailmap')
216 cache['mailmap'] = stringutil.parsemailmap(data)
216 cache['mailmap'] = stringutil.parsemailmap(data)
217
217
218 return stringutil.mapname(cache['mailmap'], author)
218 return stringutil.mapname(cache['mailmap'], author)
219
219
220 @templatefunc(
220 @templatefunc(
221 'pad(text, width[, fillchar=\' \'[, left=False[, truncate=False]]])',
221 'pad(text, width[, fillchar=\' \'[, left=False[, truncate=False]]])',
222 argspec='text width fillchar left truncate')
222 argspec='text width fillchar left truncate')
223 def pad(context, mapping, args):
223 def pad(context, mapping, args):
224 """Pad text with a
224 """Pad text with a
225 fill character."""
225 fill character."""
226 if 'text' not in args or 'width' not in args:
226 if 'text' not in args or 'width' not in args:
227 # i18n: "pad" is a keyword
227 # i18n: "pad" is a keyword
228 raise error.ParseError(_("pad() expects two to four arguments"))
228 raise error.ParseError(_("pad() expects two to four arguments"))
229
229
230 width = evalinteger(context, mapping, args['width'],
230 width = evalinteger(context, mapping, args['width'],
231 # i18n: "pad" is a keyword
231 # i18n: "pad" is a keyword
232 _("pad() expects an integer width"))
232 _("pad() expects an integer width"))
233
233
234 text = evalstring(context, mapping, args['text'])
234 text = evalstring(context, mapping, args['text'])
235
235
236 truncate = False
236 truncate = False
237 left = False
237 left = False
238 fillchar = ' '
238 fillchar = ' '
239 if 'fillchar' in args:
239 if 'fillchar' in args:
240 fillchar = evalstring(context, mapping, args['fillchar'])
240 fillchar = evalstring(context, mapping, args['fillchar'])
241 if len(color.stripeffects(fillchar)) != 1:
241 if len(color.stripeffects(fillchar)) != 1:
242 # i18n: "pad" is a keyword
242 # i18n: "pad" is a keyword
243 raise error.ParseError(_("pad() expects a single fill character"))
243 raise error.ParseError(_("pad() expects a single fill character"))
244 if 'left' in args:
244 if 'left' in args:
245 left = evalboolean(context, mapping, args['left'])
245 left = evalboolean(context, mapping, args['left'])
246 if 'truncate' in args:
246 if 'truncate' in args:
247 truncate = evalboolean(context, mapping, args['truncate'])
247 truncate = evalboolean(context, mapping, args['truncate'])
248
248
249 fillwidth = width - encoding.colwidth(color.stripeffects(text))
249 fillwidth = width - encoding.colwidth(color.stripeffects(text))
250 if fillwidth < 0 and truncate:
250 if fillwidth < 0 and truncate:
251 return encoding.trim(color.stripeffects(text), width, leftside=left)
251 return encoding.trim(color.stripeffects(text), width, leftside=left)
252 if fillwidth <= 0:
252 if fillwidth <= 0:
253 return text
253 return text
254 if left:
254 if left:
255 return fillchar * fillwidth + text
255 return fillchar * fillwidth + text
256 else:
256 else:
257 return text + fillchar * fillwidth
257 return text + fillchar * fillwidth
258
258
259 @templatefunc('indent(text, indentchars[, firstline])')
259 @templatefunc('indent(text, indentchars[, firstline])')
260 def indent(context, mapping, args):
260 def indent(context, mapping, args):
261 """Indents all non-empty lines
261 """Indents all non-empty lines
262 with the characters given in the indentchars string. An optional
262 with the characters given in the indentchars string. An optional
263 third parameter will override the indent for the first line only
263 third parameter will override the indent for the first line only
264 if present."""
264 if present."""
265 if not (2 <= len(args) <= 3):
265 if not (2 <= len(args) <= 3):
266 # i18n: "indent" is a keyword
266 # i18n: "indent" is a keyword
267 raise error.ParseError(_("indent() expects two or three arguments"))
267 raise error.ParseError(_("indent() expects two or three arguments"))
268
268
269 text = evalstring(context, mapping, args[0])
269 text = evalstring(context, mapping, args[0])
270 indent = evalstring(context, mapping, args[1])
270 indent = evalstring(context, mapping, args[1])
271
271
272 if len(args) == 3:
272 if len(args) == 3:
273 firstline = evalstring(context, mapping, args[2])
273 firstline = evalstring(context, mapping, args[2])
274 else:
274 else:
275 firstline = indent
275 firstline = indent
276
276
277 # the indent function doesn't indent the first line, so we do it here
277 # the indent function doesn't indent the first line, so we do it here
278 return templatefilters.indent(firstline + text, indent)
278 return templatefilters.indent(firstline + text, indent)
279
279
280 @templatefunc('get(dict, key)')
280 @templatefunc('get(dict, key)')
281 def get(context, mapping, args):
281 def get(context, mapping, args):
282 """Get an attribute/key from an object. Some keywords
282 """Get an attribute/key from an object. Some keywords
283 are complex types. This function allows you to obtain the value of an
283 are complex types. This function allows you to obtain the value of an
284 attribute on these types."""
284 attribute on these types."""
285 if len(args) != 2:
285 if len(args) != 2:
286 # i18n: "get" is a keyword
286 # i18n: "get" is a keyword
287 raise error.ParseError(_("get() expects two arguments"))
287 raise error.ParseError(_("get() expects two arguments"))
288
288
289 dictarg = evalwrapped(context, mapping, args[0])
289 dictarg = evalwrapped(context, mapping, args[0])
290 key = evalrawexp(context, mapping, args[1])
290 key = evalrawexp(context, mapping, args[1])
291 try:
291 try:
292 return dictarg.getmember(context, mapping, key)
292 return dictarg.getmember(context, mapping, key)
293 except error.ParseError as err:
293 except error.ParseError as err:
294 # i18n: "get" is a keyword
294 # i18n: "get" is a keyword
295 hint = _("get() expects a dict as first argument")
295 hint = _("get() expects a dict as first argument")
296 raise error.ParseError(bytes(err), hint=hint)
296 raise error.ParseError(bytes(err), hint=hint)
297
297
298 @templatefunc('config(section, name[, default])', requires={'ui'})
299 def config(context, mapping, args):
300 """Returns the requested hgrc config option as a string."""
301 fn = context.resource(mapping, 'ui').config
302 return _config(context, mapping, args, fn, evalstring)
303
304 @templatefunc('configbool(section, name[, default])', requires={'ui'})
305 def configbool(context, mapping, args):
306 """Returns the requested hgrc config option as a boolean."""
307 fn = context.resource(mapping, 'ui').configbool
308 return _config(context, mapping, args, fn, evalboolean)
309
310 @templatefunc('configint(section, name[, default])', requires={'ui'})
311 def configint(context, mapping, args):
312 """Returns the requested hgrc config option as an integer."""
313 fn = context.resource(mapping, 'ui').configint
314 return _config(context, mapping, args, fn, evalinteger)
315
316 def _config(context, mapping, args, configfn, defaultfn):
317 if not (2 <= len(args) <= 3):
318 raise error.ParseError(_("config expects two or three arguments"))
319
320 # The config option can come from any section, though we specifically
321 # reserve the [templateconfig] section for dynamically defining options
322 # for this function without also requiring an extension.
323 section = evalstringliteral(context, mapping, args[0])
324 name = evalstringliteral(context, mapping, args[1])
325 if len(args) == 3:
326 default = defaultfn(context, mapping, args[2])
327 return configfn(section, name, default)
328 else:
329 return configfn(section, name)
330
298 @templatefunc('if(expr, then[, else])')
331 @templatefunc('if(expr, then[, else])')
299 def if_(context, mapping, args):
332 def if_(context, mapping, args):
300 """Conditionally execute based on the result of
333 """Conditionally execute based on the result of
301 an expression."""
334 an expression."""
302 if not (2 <= len(args) <= 3):
335 if not (2 <= len(args) <= 3):
303 # i18n: "if" is a keyword
336 # i18n: "if" is a keyword
304 raise error.ParseError(_("if expects two or three arguments"))
337 raise error.ParseError(_("if expects two or three arguments"))
305
338
306 test = evalboolean(context, mapping, args[0])
339 test = evalboolean(context, mapping, args[0])
307 if test:
340 if test:
308 return evalrawexp(context, mapping, args[1])
341 return evalrawexp(context, mapping, args[1])
309 elif len(args) == 3:
342 elif len(args) == 3:
310 return evalrawexp(context, mapping, args[2])
343 return evalrawexp(context, mapping, args[2])
311
344
312 @templatefunc('ifcontains(needle, haystack, then[, else])')
345 @templatefunc('ifcontains(needle, haystack, then[, else])')
313 def ifcontains(context, mapping, args):
346 def ifcontains(context, mapping, args):
314 """Conditionally execute based
347 """Conditionally execute based
315 on whether the item "needle" is in "haystack"."""
348 on whether the item "needle" is in "haystack"."""
316 if not (3 <= len(args) <= 4):
349 if not (3 <= len(args) <= 4):
317 # i18n: "ifcontains" is a keyword
350 # i18n: "ifcontains" is a keyword
318 raise error.ParseError(_("ifcontains expects three or four arguments"))
351 raise error.ParseError(_("ifcontains expects three or four arguments"))
319
352
320 haystack = evalwrapped(context, mapping, args[1])
353 haystack = evalwrapped(context, mapping, args[1])
321 try:
354 try:
322 needle = evalrawexp(context, mapping, args[0])
355 needle = evalrawexp(context, mapping, args[0])
323 found = haystack.contains(context, mapping, needle)
356 found = haystack.contains(context, mapping, needle)
324 except error.ParseError:
357 except error.ParseError:
325 found = False
358 found = False
326
359
327 if found:
360 if found:
328 return evalrawexp(context, mapping, args[2])
361 return evalrawexp(context, mapping, args[2])
329 elif len(args) == 4:
362 elif len(args) == 4:
330 return evalrawexp(context, mapping, args[3])
363 return evalrawexp(context, mapping, args[3])
331
364
332 @templatefunc('ifeq(expr1, expr2, then[, else])')
365 @templatefunc('ifeq(expr1, expr2, then[, else])')
333 def ifeq(context, mapping, args):
366 def ifeq(context, mapping, args):
334 """Conditionally execute based on
367 """Conditionally execute based on
335 whether 2 items are equivalent."""
368 whether 2 items are equivalent."""
336 if not (3 <= len(args) <= 4):
369 if not (3 <= len(args) <= 4):
337 # i18n: "ifeq" is a keyword
370 # i18n: "ifeq" is a keyword
338 raise error.ParseError(_("ifeq expects three or four arguments"))
371 raise error.ParseError(_("ifeq expects three or four arguments"))
339
372
340 test = evalstring(context, mapping, args[0])
373 test = evalstring(context, mapping, args[0])
341 match = evalstring(context, mapping, args[1])
374 match = evalstring(context, mapping, args[1])
342 if test == match:
375 if test == match:
343 return evalrawexp(context, mapping, args[2])
376 return evalrawexp(context, mapping, args[2])
344 elif len(args) == 4:
377 elif len(args) == 4:
345 return evalrawexp(context, mapping, args[3])
378 return evalrawexp(context, mapping, args[3])
346
379
347 @templatefunc('join(list, sep)')
380 @templatefunc('join(list, sep)')
348 def join(context, mapping, args):
381 def join(context, mapping, args):
349 """Join items in a list with a delimiter."""
382 """Join items in a list with a delimiter."""
350 if not (1 <= len(args) <= 2):
383 if not (1 <= len(args) <= 2):
351 # i18n: "join" is a keyword
384 # i18n: "join" is a keyword
352 raise error.ParseError(_("join expects one or two arguments"))
385 raise error.ParseError(_("join expects one or two arguments"))
353
386
354 joinset = evalwrapped(context, mapping, args[0])
387 joinset = evalwrapped(context, mapping, args[0])
355 joiner = " "
388 joiner = " "
356 if len(args) > 1:
389 if len(args) > 1:
357 joiner = evalstring(context, mapping, args[1])
390 joiner = evalstring(context, mapping, args[1])
358 return joinset.join(context, mapping, joiner)
391 return joinset.join(context, mapping, joiner)
359
392
360 @templatefunc('label(label, expr)', requires={'ui'})
393 @templatefunc('label(label, expr)', requires={'ui'})
361 def label(context, mapping, args):
394 def label(context, mapping, args):
362 """Apply a label to generated content. Content with
395 """Apply a label to generated content. Content with
363 a label applied can result in additional post-processing, such as
396 a label applied can result in additional post-processing, such as
364 automatic colorization."""
397 automatic colorization."""
365 if len(args) != 2:
398 if len(args) != 2:
366 # i18n: "label" is a keyword
399 # i18n: "label" is a keyword
367 raise error.ParseError(_("label expects two arguments"))
400 raise error.ParseError(_("label expects two arguments"))
368
401
369 ui = context.resource(mapping, 'ui')
402 ui = context.resource(mapping, 'ui')
370 thing = evalstring(context, mapping, args[1])
403 thing = evalstring(context, mapping, args[1])
371 # preserve unknown symbol as literal so effects like 'red', 'bold',
404 # preserve unknown symbol as literal so effects like 'red', 'bold',
372 # etc. don't need to be quoted
405 # etc. don't need to be quoted
373 label = evalstringliteral(context, mapping, args[0])
406 label = evalstringliteral(context, mapping, args[0])
374
407
375 return ui.label(thing, label)
408 return ui.label(thing, label)
376
409
377 @templatefunc('latesttag([pattern])')
410 @templatefunc('latesttag([pattern])')
378 def latesttag(context, mapping, args):
411 def latesttag(context, mapping, args):
379 """The global tags matching the given pattern on the
412 """The global tags matching the given pattern on the
380 most recent globally tagged ancestor of this changeset.
413 most recent globally tagged ancestor of this changeset.
381 If no such tags exist, the "{tag}" template resolves to
414 If no such tags exist, the "{tag}" template resolves to
382 the string "null". See :hg:`help revisions.patterns` for the pattern
415 the string "null". See :hg:`help revisions.patterns` for the pattern
383 syntax.
416 syntax.
384 """
417 """
385 if len(args) > 1:
418 if len(args) > 1:
386 # i18n: "latesttag" is a keyword
419 # i18n: "latesttag" is a keyword
387 raise error.ParseError(_("latesttag expects at most one argument"))
420 raise error.ParseError(_("latesttag expects at most one argument"))
388
421
389 pattern = None
422 pattern = None
390 if len(args) == 1:
423 if len(args) == 1:
391 pattern = evalstring(context, mapping, args[0])
424 pattern = evalstring(context, mapping, args[0])
392 return templatekw.showlatesttags(context, mapping, pattern)
425 return templatekw.showlatesttags(context, mapping, pattern)
393
426
394 @templatefunc('localdate(date[, tz])')
427 @templatefunc('localdate(date[, tz])')
395 def localdate(context, mapping, args):
428 def localdate(context, mapping, args):
396 """Converts a date to the specified timezone.
429 """Converts a date to the specified timezone.
397 The default is local date."""
430 The default is local date."""
398 if not (1 <= len(args) <= 2):
431 if not (1 <= len(args) <= 2):
399 # i18n: "localdate" is a keyword
432 # i18n: "localdate" is a keyword
400 raise error.ParseError(_("localdate expects one or two arguments"))
433 raise error.ParseError(_("localdate expects one or two arguments"))
401
434
402 date = evaldate(context, mapping, args[0],
435 date = evaldate(context, mapping, args[0],
403 # i18n: "localdate" is a keyword
436 # i18n: "localdate" is a keyword
404 _("localdate expects a date information"))
437 _("localdate expects a date information"))
405 if len(args) >= 2:
438 if len(args) >= 2:
406 tzoffset = None
439 tzoffset = None
407 tz = evalfuncarg(context, mapping, args[1])
440 tz = evalfuncarg(context, mapping, args[1])
408 if isinstance(tz, bytes):
441 if isinstance(tz, bytes):
409 tzoffset, remainder = dateutil.parsetimezone(tz)
442 tzoffset, remainder = dateutil.parsetimezone(tz)
410 if remainder:
443 if remainder:
411 tzoffset = None
444 tzoffset = None
412 if tzoffset is None:
445 if tzoffset is None:
413 try:
446 try:
414 tzoffset = int(tz)
447 tzoffset = int(tz)
415 except (TypeError, ValueError):
448 except (TypeError, ValueError):
416 # i18n: "localdate" is a keyword
449 # i18n: "localdate" is a keyword
417 raise error.ParseError(_("localdate expects a timezone"))
450 raise error.ParseError(_("localdate expects a timezone"))
418 else:
451 else:
419 tzoffset = dateutil.makedate()[1]
452 tzoffset = dateutil.makedate()[1]
420 return templateutil.date((date[0], tzoffset))
453 return templateutil.date((date[0], tzoffset))
421
454
422 @templatefunc('max(iterable)')
455 @templatefunc('max(iterable)')
423 def max_(context, mapping, args, **kwargs):
456 def max_(context, mapping, args, **kwargs):
424 """Return the max of an iterable"""
457 """Return the max of an iterable"""
425 if len(args) != 1:
458 if len(args) != 1:
426 # i18n: "max" is a keyword
459 # i18n: "max" is a keyword
427 raise error.ParseError(_("max expects one argument"))
460 raise error.ParseError(_("max expects one argument"))
428
461
429 iterable = evalwrapped(context, mapping, args[0])
462 iterable = evalwrapped(context, mapping, args[0])
430 try:
463 try:
431 return iterable.getmax(context, mapping)
464 return iterable.getmax(context, mapping)
432 except error.ParseError as err:
465 except error.ParseError as err:
433 # i18n: "max" is a keyword
466 # i18n: "max" is a keyword
434 hint = _("max first argument should be an iterable")
467 hint = _("max first argument should be an iterable")
435 raise error.ParseError(bytes(err), hint=hint)
468 raise error.ParseError(bytes(err), hint=hint)
436
469
437 @templatefunc('min(iterable)')
470 @templatefunc('min(iterable)')
438 def min_(context, mapping, args, **kwargs):
471 def min_(context, mapping, args, **kwargs):
439 """Return the min of an iterable"""
472 """Return the min of an iterable"""
440 if len(args) != 1:
473 if len(args) != 1:
441 # i18n: "min" is a keyword
474 # i18n: "min" is a keyword
442 raise error.ParseError(_("min expects one argument"))
475 raise error.ParseError(_("min expects one argument"))
443
476
444 iterable = evalwrapped(context, mapping, args[0])
477 iterable = evalwrapped(context, mapping, args[0])
445 try:
478 try:
446 return iterable.getmin(context, mapping)
479 return iterable.getmin(context, mapping)
447 except error.ParseError as err:
480 except error.ParseError as err:
448 # i18n: "min" is a keyword
481 # i18n: "min" is a keyword
449 hint = _("min first argument should be an iterable")
482 hint = _("min first argument should be an iterable")
450 raise error.ParseError(bytes(err), hint=hint)
483 raise error.ParseError(bytes(err), hint=hint)
451
484
452 @templatefunc('mod(a, b)')
485 @templatefunc('mod(a, b)')
453 def mod(context, mapping, args):
486 def mod(context, mapping, args):
454 """Calculate a mod b such that a / b + a mod b == a"""
487 """Calculate a mod b such that a / b + a mod b == a"""
455 if not len(args) == 2:
488 if not len(args) == 2:
456 # i18n: "mod" is a keyword
489 # i18n: "mod" is a keyword
457 raise error.ParseError(_("mod expects two arguments"))
490 raise error.ParseError(_("mod expects two arguments"))
458
491
459 func = lambda a, b: a % b
492 func = lambda a, b: a % b
460 return templateutil.runarithmetic(context, mapping,
493 return templateutil.runarithmetic(context, mapping,
461 (func, args[0], args[1]))
494 (func, args[0], args[1]))
462
495
463 @templatefunc('obsfateoperations(markers)')
496 @templatefunc('obsfateoperations(markers)')
464 def obsfateoperations(context, mapping, args):
497 def obsfateoperations(context, mapping, args):
465 """Compute obsfate related information based on markers (EXPERIMENTAL)"""
498 """Compute obsfate related information based on markers (EXPERIMENTAL)"""
466 if len(args) != 1:
499 if len(args) != 1:
467 # i18n: "obsfateoperations" is a keyword
500 # i18n: "obsfateoperations" is a keyword
468 raise error.ParseError(_("obsfateoperations expects one argument"))
501 raise error.ParseError(_("obsfateoperations expects one argument"))
469
502
470 markers = evalfuncarg(context, mapping, args[0])
503 markers = evalfuncarg(context, mapping, args[0])
471
504
472 try:
505 try:
473 data = obsutil.markersoperations(markers)
506 data = obsutil.markersoperations(markers)
474 return templateutil.hybridlist(data, name='operation')
507 return templateutil.hybridlist(data, name='operation')
475 except (TypeError, KeyError):
508 except (TypeError, KeyError):
476 # i18n: "obsfateoperations" is a keyword
509 # i18n: "obsfateoperations" is a keyword
477 errmsg = _("obsfateoperations first argument should be an iterable")
510 errmsg = _("obsfateoperations first argument should be an iterable")
478 raise error.ParseError(errmsg)
511 raise error.ParseError(errmsg)
479
512
480 @templatefunc('obsfatedate(markers)')
513 @templatefunc('obsfatedate(markers)')
481 def obsfatedate(context, mapping, args):
514 def obsfatedate(context, mapping, args):
482 """Compute obsfate related information based on markers (EXPERIMENTAL)"""
515 """Compute obsfate related information based on markers (EXPERIMENTAL)"""
483 if len(args) != 1:
516 if len(args) != 1:
484 # i18n: "obsfatedate" is a keyword
517 # i18n: "obsfatedate" is a keyword
485 raise error.ParseError(_("obsfatedate expects one argument"))
518 raise error.ParseError(_("obsfatedate expects one argument"))
486
519
487 markers = evalfuncarg(context, mapping, args[0])
520 markers = evalfuncarg(context, mapping, args[0])
488
521
489 try:
522 try:
490 # TODO: maybe this has to be a wrapped list of date wrappers?
523 # TODO: maybe this has to be a wrapped list of date wrappers?
491 data = obsutil.markersdates(markers)
524 data = obsutil.markersdates(markers)
492 return templateutil.hybridlist(data, name='date', fmt='%d %d')
525 return templateutil.hybridlist(data, name='date', fmt='%d %d')
493 except (TypeError, KeyError):
526 except (TypeError, KeyError):
494 # i18n: "obsfatedate" is a keyword
527 # i18n: "obsfatedate" is a keyword
495 errmsg = _("obsfatedate first argument should be an iterable")
528 errmsg = _("obsfatedate first argument should be an iterable")
496 raise error.ParseError(errmsg)
529 raise error.ParseError(errmsg)
497
530
498 @templatefunc('obsfateusers(markers)')
531 @templatefunc('obsfateusers(markers)')
499 def obsfateusers(context, mapping, args):
532 def obsfateusers(context, mapping, args):
500 """Compute obsfate related information based on markers (EXPERIMENTAL)"""
533 """Compute obsfate related information based on markers (EXPERIMENTAL)"""
501 if len(args) != 1:
534 if len(args) != 1:
502 # i18n: "obsfateusers" is a keyword
535 # i18n: "obsfateusers" is a keyword
503 raise error.ParseError(_("obsfateusers expects one argument"))
536 raise error.ParseError(_("obsfateusers expects one argument"))
504
537
505 markers = evalfuncarg(context, mapping, args[0])
538 markers = evalfuncarg(context, mapping, args[0])
506
539
507 try:
540 try:
508 data = obsutil.markersusers(markers)
541 data = obsutil.markersusers(markers)
509 return templateutil.hybridlist(data, name='user')
542 return templateutil.hybridlist(data, name='user')
510 except (TypeError, KeyError, ValueError):
543 except (TypeError, KeyError, ValueError):
511 # i18n: "obsfateusers" is a keyword
544 # i18n: "obsfateusers" is a keyword
512 msg = _("obsfateusers first argument should be an iterable of "
545 msg = _("obsfateusers first argument should be an iterable of "
513 "obsmakers")
546 "obsmakers")
514 raise error.ParseError(msg)
547 raise error.ParseError(msg)
515
548
516 @templatefunc('obsfateverb(successors, markers)')
549 @templatefunc('obsfateverb(successors, markers)')
517 def obsfateverb(context, mapping, args):
550 def obsfateverb(context, mapping, args):
518 """Compute obsfate related information based on successors (EXPERIMENTAL)"""
551 """Compute obsfate related information based on successors (EXPERIMENTAL)"""
519 if len(args) != 2:
552 if len(args) != 2:
520 # i18n: "obsfateverb" is a keyword
553 # i18n: "obsfateverb" is a keyword
521 raise error.ParseError(_("obsfateverb expects two arguments"))
554 raise error.ParseError(_("obsfateverb expects two arguments"))
522
555
523 successors = evalfuncarg(context, mapping, args[0])
556 successors = evalfuncarg(context, mapping, args[0])
524 markers = evalfuncarg(context, mapping, args[1])
557 markers = evalfuncarg(context, mapping, args[1])
525
558
526 try:
559 try:
527 return obsutil.obsfateverb(successors, markers)
560 return obsutil.obsfateverb(successors, markers)
528 except TypeError:
561 except TypeError:
529 # i18n: "obsfateverb" is a keyword
562 # i18n: "obsfateverb" is a keyword
530 errmsg = _("obsfateverb first argument should be countable")
563 errmsg = _("obsfateverb first argument should be countable")
531 raise error.ParseError(errmsg)
564 raise error.ParseError(errmsg)
532
565
533 @templatefunc('relpath(path)', requires={'repo'})
566 @templatefunc('relpath(path)', requires={'repo'})
534 def relpath(context, mapping, args):
567 def relpath(context, mapping, args):
535 """Convert a repository-absolute path into a filesystem path relative to
568 """Convert a repository-absolute path into a filesystem path relative to
536 the current working directory."""
569 the current working directory."""
537 if len(args) != 1:
570 if len(args) != 1:
538 # i18n: "relpath" is a keyword
571 # i18n: "relpath" is a keyword
539 raise error.ParseError(_("relpath expects one argument"))
572 raise error.ParseError(_("relpath expects one argument"))
540
573
541 repo = context.resource(mapping, 'repo')
574 repo = context.resource(mapping, 'repo')
542 path = evalstring(context, mapping, args[0])
575 path = evalstring(context, mapping, args[0])
543 return repo.pathto(path)
576 return repo.pathto(path)
544
577
545 @templatefunc('revset(query[, formatargs...])', requires={'repo', 'cache'})
578 @templatefunc('revset(query[, formatargs...])', requires={'repo', 'cache'})
546 def revset(context, mapping, args):
579 def revset(context, mapping, args):
547 """Execute a revision set query. See
580 """Execute a revision set query. See
548 :hg:`help revset`."""
581 :hg:`help revset`."""
549 if not len(args) > 0:
582 if not len(args) > 0:
550 # i18n: "revset" is a keyword
583 # i18n: "revset" is a keyword
551 raise error.ParseError(_("revset expects one or more arguments"))
584 raise error.ParseError(_("revset expects one or more arguments"))
552
585
553 raw = evalstring(context, mapping, args[0])
586 raw = evalstring(context, mapping, args[0])
554 repo = context.resource(mapping, 'repo')
587 repo = context.resource(mapping, 'repo')
555
588
556 def query(expr):
589 def query(expr):
557 m = revsetmod.match(repo.ui, expr, lookup=revsetmod.lookupfn(repo))
590 m = revsetmod.match(repo.ui, expr, lookup=revsetmod.lookupfn(repo))
558 return m(repo)
591 return m(repo)
559
592
560 if len(args) > 1:
593 if len(args) > 1:
561 formatargs = [evalfuncarg(context, mapping, a) for a in args[1:]]
594 formatargs = [evalfuncarg(context, mapping, a) for a in args[1:]]
562 revs = query(revsetlang.formatspec(raw, *formatargs))
595 revs = query(revsetlang.formatspec(raw, *formatargs))
563 else:
596 else:
564 cache = context.resource(mapping, 'cache')
597 cache = context.resource(mapping, 'cache')
565 revsetcache = cache.setdefault("revsetcache", {})
598 revsetcache = cache.setdefault("revsetcache", {})
566 if raw in revsetcache:
599 if raw in revsetcache:
567 revs = revsetcache[raw]
600 revs = revsetcache[raw]
568 else:
601 else:
569 revs = query(raw)
602 revs = query(raw)
570 revsetcache[raw] = revs
603 revsetcache[raw] = revs
571 return templatekw.showrevslist(context, mapping, "revision", revs)
604 return templatekw.showrevslist(context, mapping, "revision", revs)
572
605
573 @templatefunc('rstdoc(text, style)')
606 @templatefunc('rstdoc(text, style)')
574 def rstdoc(context, mapping, args):
607 def rstdoc(context, mapping, args):
575 """Format reStructuredText."""
608 """Format reStructuredText."""
576 if len(args) != 2:
609 if len(args) != 2:
577 # i18n: "rstdoc" is a keyword
610 # i18n: "rstdoc" is a keyword
578 raise error.ParseError(_("rstdoc expects two arguments"))
611 raise error.ParseError(_("rstdoc expects two arguments"))
579
612
580 text = evalstring(context, mapping, args[0])
613 text = evalstring(context, mapping, args[0])
581 style = evalstring(context, mapping, args[1])
614 style = evalstring(context, mapping, args[1])
582
615
583 return minirst.format(text, style=style, keep=['verbose'])
616 return minirst.format(text, style=style, keep=['verbose'])
584
617
585 @templatefunc('search(pattern, text)')
618 @templatefunc('search(pattern, text)')
586 def search(context, mapping, args):
619 def search(context, mapping, args):
587 """Look for the first text matching the regular expression pattern.
620 """Look for the first text matching the regular expression pattern.
588 Groups are accessible as ``{1}``, ``{2}``, ... in %-mapped template."""
621 Groups are accessible as ``{1}``, ``{2}``, ... in %-mapped template."""
589 if len(args) != 2:
622 if len(args) != 2:
590 # i18n: "search" is a keyword
623 # i18n: "search" is a keyword
591 raise error.ParseError(_(b'search expects two arguments'))
624 raise error.ParseError(_(b'search expects two arguments'))
592
625
593 pat = evalstring(context, mapping, args[0])
626 pat = evalstring(context, mapping, args[0])
594 src = evalstring(context, mapping, args[1])
627 src = evalstring(context, mapping, args[1])
595 try:
628 try:
596 patre = re.compile(pat)
629 patre = re.compile(pat)
597 except re.error:
630 except re.error:
598 # i18n: "search" is a keyword
631 # i18n: "search" is a keyword
599 raise error.ParseError(_(b'search got an invalid pattern: %s') % pat)
632 raise error.ParseError(_(b'search got an invalid pattern: %s') % pat)
600 # named groups shouldn't shadow *reserved* resource keywords
633 # named groups shouldn't shadow *reserved* resource keywords
601 badgroups = (context.knownresourcekeys()
634 badgroups = (context.knownresourcekeys()
602 & set(pycompat.byteskwargs(patre.groupindex)))
635 & set(pycompat.byteskwargs(patre.groupindex)))
603 if badgroups:
636 if badgroups:
604 raise error.ParseError(
637 raise error.ParseError(
605 # i18n: "search" is a keyword
638 # i18n: "search" is a keyword
606 _(b'invalid group %(group)s in search pattern: %(pat)s')
639 _(b'invalid group %(group)s in search pattern: %(pat)s')
607 % {b'group': b', '.join("'%s'" % g for g in sorted(badgroups)),
640 % {b'group': b', '.join("'%s'" % g for g in sorted(badgroups)),
608 b'pat': pat})
641 b'pat': pat})
609
642
610 match = patre.search(src)
643 match = patre.search(src)
611 if not match:
644 if not match:
612 return templateutil.mappingnone()
645 return templateutil.mappingnone()
613
646
614 lm = {b'0': match.group(0)}
647 lm = {b'0': match.group(0)}
615 lm.update((b'%d' % i, v) for i, v in enumerate(match.groups(), 1))
648 lm.update((b'%d' % i, v) for i, v in enumerate(match.groups(), 1))
616 lm.update(pycompat.byteskwargs(match.groupdict()))
649 lm.update(pycompat.byteskwargs(match.groupdict()))
617 return templateutil.mappingdict(lm, tmpl=b'{0}')
650 return templateutil.mappingdict(lm, tmpl=b'{0}')
618
651
619 @templatefunc('separate(sep, args...)', argspec='sep *args')
652 @templatefunc('separate(sep, args...)', argspec='sep *args')
620 def separate(context, mapping, args):
653 def separate(context, mapping, args):
621 """Add a separator between non-empty arguments."""
654 """Add a separator between non-empty arguments."""
622 if 'sep' not in args:
655 if 'sep' not in args:
623 # i18n: "separate" is a keyword
656 # i18n: "separate" is a keyword
624 raise error.ParseError(_("separate expects at least one argument"))
657 raise error.ParseError(_("separate expects at least one argument"))
625
658
626 sep = evalstring(context, mapping, args['sep'])
659 sep = evalstring(context, mapping, args['sep'])
627 first = True
660 first = True
628 for arg in args['args']:
661 for arg in args['args']:
629 argstr = evalstring(context, mapping, arg)
662 argstr = evalstring(context, mapping, arg)
630 if not argstr:
663 if not argstr:
631 continue
664 continue
632 if first:
665 if first:
633 first = False
666 first = False
634 else:
667 else:
635 yield sep
668 yield sep
636 yield argstr
669 yield argstr
637
670
638 @templatefunc('shortest(node, minlength=4)', requires={'repo', 'cache'})
671 @templatefunc('shortest(node, minlength=4)', requires={'repo', 'cache'})
639 def shortest(context, mapping, args):
672 def shortest(context, mapping, args):
640 """Obtain the shortest representation of
673 """Obtain the shortest representation of
641 a node."""
674 a node."""
642 if not (1 <= len(args) <= 2):
675 if not (1 <= len(args) <= 2):
643 # i18n: "shortest" is a keyword
676 # i18n: "shortest" is a keyword
644 raise error.ParseError(_("shortest() expects one or two arguments"))
677 raise error.ParseError(_("shortest() expects one or two arguments"))
645
678
646 hexnode = evalstring(context, mapping, args[0])
679 hexnode = evalstring(context, mapping, args[0])
647
680
648 minlength = 4
681 minlength = 4
649 if len(args) > 1:
682 if len(args) > 1:
650 minlength = evalinteger(context, mapping, args[1],
683 minlength = evalinteger(context, mapping, args[1],
651 # i18n: "shortest" is a keyword
684 # i18n: "shortest" is a keyword
652 _("shortest() expects an integer minlength"))
685 _("shortest() expects an integer minlength"))
653
686
654 repo = context.resource(mapping, 'repo')
687 repo = context.resource(mapping, 'repo')
655 if len(hexnode) > 40:
688 if len(hexnode) > 40:
656 return hexnode
689 return hexnode
657 elif len(hexnode) == 40:
690 elif len(hexnode) == 40:
658 try:
691 try:
659 node = bin(hexnode)
692 node = bin(hexnode)
660 except TypeError:
693 except TypeError:
661 return hexnode
694 return hexnode
662 else:
695 else:
663 try:
696 try:
664 node = scmutil.resolvehexnodeidprefix(repo, hexnode)
697 node = scmutil.resolvehexnodeidprefix(repo, hexnode)
665 except error.WdirUnsupported:
698 except error.WdirUnsupported:
666 node = wdirid
699 node = wdirid
667 except error.LookupError:
700 except error.LookupError:
668 return hexnode
701 return hexnode
669 if not node:
702 if not node:
670 return hexnode
703 return hexnode
671 cache = context.resource(mapping, 'cache')
704 cache = context.resource(mapping, 'cache')
672 try:
705 try:
673 return scmutil.shortesthexnodeidprefix(repo, node, minlength, cache)
706 return scmutil.shortesthexnodeidprefix(repo, node, minlength, cache)
674 except error.RepoLookupError:
707 except error.RepoLookupError:
675 return hexnode
708 return hexnode
676
709
677 @templatefunc('strip(text[, chars])')
710 @templatefunc('strip(text[, chars])')
678 def strip(context, mapping, args):
711 def strip(context, mapping, args):
679 """Strip characters from a string. By default,
712 """Strip characters from a string. By default,
680 strips all leading and trailing whitespace."""
713 strips all leading and trailing whitespace."""
681 if not (1 <= len(args) <= 2):
714 if not (1 <= len(args) <= 2):
682 # i18n: "strip" is a keyword
715 # i18n: "strip" is a keyword
683 raise error.ParseError(_("strip expects one or two arguments"))
716 raise error.ParseError(_("strip expects one or two arguments"))
684
717
685 text = evalstring(context, mapping, args[0])
718 text = evalstring(context, mapping, args[0])
686 if len(args) == 2:
719 if len(args) == 2:
687 chars = evalstring(context, mapping, args[1])
720 chars = evalstring(context, mapping, args[1])
688 return text.strip(chars)
721 return text.strip(chars)
689 return text.strip()
722 return text.strip()
690
723
691 @templatefunc('sub(pattern, replacement, expression)')
724 @templatefunc('sub(pattern, replacement, expression)')
692 def sub(context, mapping, args):
725 def sub(context, mapping, args):
693 """Perform text substitution
726 """Perform text substitution
694 using regular expressions."""
727 using regular expressions."""
695 if len(args) != 3:
728 if len(args) != 3:
696 # i18n: "sub" is a keyword
729 # i18n: "sub" is a keyword
697 raise error.ParseError(_("sub expects three arguments"))
730 raise error.ParseError(_("sub expects three arguments"))
698
731
699 pat = evalstring(context, mapping, args[0])
732 pat = evalstring(context, mapping, args[0])
700 rpl = evalstring(context, mapping, args[1])
733 rpl = evalstring(context, mapping, args[1])
701 src = evalstring(context, mapping, args[2])
734 src = evalstring(context, mapping, args[2])
702 try:
735 try:
703 patre = re.compile(pat)
736 patre = re.compile(pat)
704 except re.error:
737 except re.error:
705 # i18n: "sub" is a keyword
738 # i18n: "sub" is a keyword
706 raise error.ParseError(_("sub got an invalid pattern: %s") % pat)
739 raise error.ParseError(_("sub got an invalid pattern: %s") % pat)
707 try:
740 try:
708 yield patre.sub(rpl, src)
741 yield patre.sub(rpl, src)
709 except re.error:
742 except re.error:
710 # i18n: "sub" is a keyword
743 # i18n: "sub" is a keyword
711 raise error.ParseError(_("sub got an invalid replacement: %s") % rpl)
744 raise error.ParseError(_("sub got an invalid replacement: %s") % rpl)
712
745
713 @templatefunc('startswith(pattern, text)')
746 @templatefunc('startswith(pattern, text)')
714 def startswith(context, mapping, args):
747 def startswith(context, mapping, args):
715 """Returns the value from the "text" argument
748 """Returns the value from the "text" argument
716 if it begins with the content from the "pattern" argument."""
749 if it begins with the content from the "pattern" argument."""
717 if len(args) != 2:
750 if len(args) != 2:
718 # i18n: "startswith" is a keyword
751 # i18n: "startswith" is a keyword
719 raise error.ParseError(_("startswith expects two arguments"))
752 raise error.ParseError(_("startswith expects two arguments"))
720
753
721 patn = evalstring(context, mapping, args[0])
754 patn = evalstring(context, mapping, args[0])
722 text = evalstring(context, mapping, args[1])
755 text = evalstring(context, mapping, args[1])
723 if text.startswith(patn):
756 if text.startswith(patn):
724 return text
757 return text
725 return ''
758 return ''
726
759
727 @templatefunc('word(number, text[, separator])')
760 @templatefunc('word(number, text[, separator])')
728 def word(context, mapping, args):
761 def word(context, mapping, args):
729 """Return the nth word from a string."""
762 """Return the nth word from a string."""
730 if not (2 <= len(args) <= 3):
763 if not (2 <= len(args) <= 3):
731 # i18n: "word" is a keyword
764 # i18n: "word" is a keyword
732 raise error.ParseError(_("word expects two or three arguments, got %d")
765 raise error.ParseError(_("word expects two or three arguments, got %d")
733 % len(args))
766 % len(args))
734
767
735 num = evalinteger(context, mapping, args[0],
768 num = evalinteger(context, mapping, args[0],
736 # i18n: "word" is a keyword
769 # i18n: "word" is a keyword
737 _("word expects an integer index"))
770 _("word expects an integer index"))
738 text = evalstring(context, mapping, args[1])
771 text = evalstring(context, mapping, args[1])
739 if len(args) == 3:
772 if len(args) == 3:
740 splitter = evalstring(context, mapping, args[2])
773 splitter = evalstring(context, mapping, args[2])
741 else:
774 else:
742 splitter = None
775 splitter = None
743
776
744 tokens = text.split(splitter)
777 tokens = text.split(splitter)
745 if num >= len(tokens) or num < -len(tokens):
778 if num >= len(tokens) or num < -len(tokens):
746 return ''
779 return ''
747 else:
780 else:
748 return tokens[num]
781 return tokens[num]
749
782
750 def loadfunction(ui, extname, registrarobj):
783 def loadfunction(ui, extname, registrarobj):
751 """Load template function from specified registrarobj
784 """Load template function from specified registrarobj
752 """
785 """
753 for name, func in registrarobj._table.iteritems():
786 for name, func in registrarobj._table.iteritems():
754 funcs[name] = func
787 funcs[name] = func
755
788
756 # tell hggettext to extract docstrings from these functions:
789 # tell hggettext to extract docstrings from these functions:
757 i18nfunctions = funcs.values()
790 i18nfunctions = funcs.values()
@@ -1,1552 +1,1579
1 Test template filters and functions
1 Test template filters and functions
2 ===================================
2 ===================================
3
3
4 $ hg init a
4 $ hg init a
5 $ cd a
5 $ cd a
6 $ echo a > a
6 $ echo a > a
7 $ hg add a
7 $ hg add a
8 $ echo line 1 > b
8 $ echo line 1 > b
9 $ echo line 2 >> b
9 $ echo line 2 >> b
10 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
10 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
11
11
12 $ hg add b
12 $ hg add b
13 $ echo other 1 > c
13 $ echo other 1 > c
14 $ echo other 2 >> c
14 $ echo other 2 >> c
15 $ echo >> c
15 $ echo >> c
16 $ echo other 3 >> c
16 $ echo other 3 >> c
17 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
17 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
18
18
19 $ hg add c
19 $ hg add c
20 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
20 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
21 $ echo c >> c
21 $ echo c >> c
22 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
22 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
23
23
24 $ echo foo > .hg/branch
24 $ echo foo > .hg/branch
25 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
25 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
26
26
27 $ hg co -q 3
27 $ hg co -q 3
28 $ echo other 4 >> d
28 $ echo other 4 >> d
29 $ hg add d
29 $ hg add d
30 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
30 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
31
31
32 $ hg merge -q foo
32 $ hg merge -q foo
33 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
33 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
34
34
35 Second branch starting at nullrev:
35 Second branch starting at nullrev:
36
36
37 $ hg update null
37 $ hg update null
38 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
38 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
39 $ echo second > second
39 $ echo second > second
40 $ hg add second
40 $ hg add second
41 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
41 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
42 created new head
42 created new head
43
43
44 $ echo third > third
44 $ echo third > third
45 $ hg add third
45 $ hg add third
46 $ hg mv second fourth
46 $ hg mv second fourth
47 $ hg commit -m third -d "2020-01-01 10:01"
47 $ hg commit -m third -d "2020-01-01 10:01"
48
48
49 $ hg phase -r 5 --public
49 $ hg phase -r 5 --public
50 $ hg phase -r 7 --secret --force
50 $ hg phase -r 7 --secret --force
51
51
52 Filters work:
52 Filters work:
53
53
54 $ hg log --template '{author|domain}\n'
54 $ hg log --template '{author|domain}\n'
55
55
56 hostname
56 hostname
57
57
58
58
59
59
60
60
61 place
61 place
62 place
62 place
63 hostname
63 hostname
64
64
65 $ hg log --template '{author|person}\n'
65 $ hg log --template '{author|person}\n'
66 test
66 test
67 User Name
67 User Name
68 person
68 person
69 person
69 person
70 person
70 person
71 person
71 person
72 other
72 other
73 A. N. Other
73 A. N. Other
74 User Name
74 User Name
75
75
76 $ hg log --template '{author|user}\n'
76 $ hg log --template '{author|user}\n'
77 test
77 test
78 user
78 user
79 person
79 person
80 person
80 person
81 person
81 person
82 person
82 person
83 other
83 other
84 other
84 other
85 user
85 user
86
86
87 $ hg log --template '{date|date}\n'
87 $ hg log --template '{date|date}\n'
88 Wed Jan 01 10:01:00 2020 +0000
88 Wed Jan 01 10:01:00 2020 +0000
89 Mon Jan 12 13:46:40 1970 +0000
89 Mon Jan 12 13:46:40 1970 +0000
90 Sun Jan 18 08:40:01 1970 +0000
90 Sun Jan 18 08:40:01 1970 +0000
91 Sun Jan 18 08:40:00 1970 +0000
91 Sun Jan 18 08:40:00 1970 +0000
92 Sat Jan 17 04:53:20 1970 +0000
92 Sat Jan 17 04:53:20 1970 +0000
93 Fri Jan 16 01:06:40 1970 +0000
93 Fri Jan 16 01:06:40 1970 +0000
94 Wed Jan 14 21:20:00 1970 +0000
94 Wed Jan 14 21:20:00 1970 +0000
95 Tue Jan 13 17:33:20 1970 +0000
95 Tue Jan 13 17:33:20 1970 +0000
96 Mon Jan 12 13:46:40 1970 +0000
96 Mon Jan 12 13:46:40 1970 +0000
97
97
98 $ hg log --template '{date|isodate}\n'
98 $ hg log --template '{date|isodate}\n'
99 2020-01-01 10:01 +0000
99 2020-01-01 10:01 +0000
100 1970-01-12 13:46 +0000
100 1970-01-12 13:46 +0000
101 1970-01-18 08:40 +0000
101 1970-01-18 08:40 +0000
102 1970-01-18 08:40 +0000
102 1970-01-18 08:40 +0000
103 1970-01-17 04:53 +0000
103 1970-01-17 04:53 +0000
104 1970-01-16 01:06 +0000
104 1970-01-16 01:06 +0000
105 1970-01-14 21:20 +0000
105 1970-01-14 21:20 +0000
106 1970-01-13 17:33 +0000
106 1970-01-13 17:33 +0000
107 1970-01-12 13:46 +0000
107 1970-01-12 13:46 +0000
108
108
109 $ hg log --template '{date|isodatesec}\n'
109 $ hg log --template '{date|isodatesec}\n'
110 2020-01-01 10:01:00 +0000
110 2020-01-01 10:01:00 +0000
111 1970-01-12 13:46:40 +0000
111 1970-01-12 13:46:40 +0000
112 1970-01-18 08:40:01 +0000
112 1970-01-18 08:40:01 +0000
113 1970-01-18 08:40:00 +0000
113 1970-01-18 08:40:00 +0000
114 1970-01-17 04:53:20 +0000
114 1970-01-17 04:53:20 +0000
115 1970-01-16 01:06:40 +0000
115 1970-01-16 01:06:40 +0000
116 1970-01-14 21:20:00 +0000
116 1970-01-14 21:20:00 +0000
117 1970-01-13 17:33:20 +0000
117 1970-01-13 17:33:20 +0000
118 1970-01-12 13:46:40 +0000
118 1970-01-12 13:46:40 +0000
119
119
120 $ hg log --template '{date|rfc822date}\n'
120 $ hg log --template '{date|rfc822date}\n'
121 Wed, 01 Jan 2020 10:01:00 +0000
121 Wed, 01 Jan 2020 10:01:00 +0000
122 Mon, 12 Jan 1970 13:46:40 +0000
122 Mon, 12 Jan 1970 13:46:40 +0000
123 Sun, 18 Jan 1970 08:40:01 +0000
123 Sun, 18 Jan 1970 08:40:01 +0000
124 Sun, 18 Jan 1970 08:40:00 +0000
124 Sun, 18 Jan 1970 08:40:00 +0000
125 Sat, 17 Jan 1970 04:53:20 +0000
125 Sat, 17 Jan 1970 04:53:20 +0000
126 Fri, 16 Jan 1970 01:06:40 +0000
126 Fri, 16 Jan 1970 01:06:40 +0000
127 Wed, 14 Jan 1970 21:20:00 +0000
127 Wed, 14 Jan 1970 21:20:00 +0000
128 Tue, 13 Jan 1970 17:33:20 +0000
128 Tue, 13 Jan 1970 17:33:20 +0000
129 Mon, 12 Jan 1970 13:46:40 +0000
129 Mon, 12 Jan 1970 13:46:40 +0000
130
130
131 $ hg log --template '{desc|firstline}\n'
131 $ hg log --template '{desc|firstline}\n'
132 third
132 third
133 second
133 second
134 merge
134 merge
135 new head
135 new head
136 new branch
136 new branch
137 no user, no domain
137 no user, no domain
138 no person
138 no person
139 other 1
139 other 1
140 line 1
140 line 1
141
141
142 $ hg log --template '{node|short}\n'
142 $ hg log --template '{node|short}\n'
143 95c24699272e
143 95c24699272e
144 29114dbae42b
144 29114dbae42b
145 d41e714fe50d
145 d41e714fe50d
146 13207e5a10d9
146 13207e5a10d9
147 bbe44766e73d
147 bbe44766e73d
148 10e46f2dcbf4
148 10e46f2dcbf4
149 97054abb4ab8
149 97054abb4ab8
150 b608e9d1a3f0
150 b608e9d1a3f0
151 1e4e1b8f71e0
151 1e4e1b8f71e0
152
152
153 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
153 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
154 <changeset author="test"/>
154 <changeset author="test"/>
155 <changeset author="User Name &lt;user@hostname&gt;"/>
155 <changeset author="User Name &lt;user@hostname&gt;"/>
156 <changeset author="person"/>
156 <changeset author="person"/>
157 <changeset author="person"/>
157 <changeset author="person"/>
158 <changeset author="person"/>
158 <changeset author="person"/>
159 <changeset author="person"/>
159 <changeset author="person"/>
160 <changeset author="other@place"/>
160 <changeset author="other@place"/>
161 <changeset author="A. N. Other &lt;other@place&gt;"/>
161 <changeset author="A. N. Other &lt;other@place&gt;"/>
162 <changeset author="User Name &lt;user@hostname&gt;"/>
162 <changeset author="User Name &lt;user@hostname&gt;"/>
163
163
164 $ hg log --template '{rev}: {children}\n'
164 $ hg log --template '{rev}: {children}\n'
165 8:
165 8:
166 7: 8:95c24699272e
166 7: 8:95c24699272e
167 6:
167 6:
168 5: 6:d41e714fe50d
168 5: 6:d41e714fe50d
169 4: 6:d41e714fe50d
169 4: 6:d41e714fe50d
170 3: 4:bbe44766e73d 5:13207e5a10d9
170 3: 4:bbe44766e73d 5:13207e5a10d9
171 2: 3:10e46f2dcbf4
171 2: 3:10e46f2dcbf4
172 1: 2:97054abb4ab8
172 1: 2:97054abb4ab8
173 0: 1:b608e9d1a3f0
173 0: 1:b608e9d1a3f0
174
174
175 Formatnode filter works:
175 Formatnode filter works:
176
176
177 $ hg -q log -r 0 --template '{node|formatnode}\n'
177 $ hg -q log -r 0 --template '{node|formatnode}\n'
178 1e4e1b8f71e0
178 1e4e1b8f71e0
179
179
180 $ hg log -r 0 --template '{node|formatnode}\n'
180 $ hg log -r 0 --template '{node|formatnode}\n'
181 1e4e1b8f71e0
181 1e4e1b8f71e0
182
182
183 $ hg -v log -r 0 --template '{node|formatnode}\n'
183 $ hg -v log -r 0 --template '{node|formatnode}\n'
184 1e4e1b8f71e0
184 1e4e1b8f71e0
185
185
186 $ hg --debug log -r 0 --template '{node|formatnode}\n'
186 $ hg --debug log -r 0 --template '{node|formatnode}\n'
187 1e4e1b8f71e05681d422154f5421e385fec3454f
187 1e4e1b8f71e05681d422154f5421e385fec3454f
188
188
189 Age filter:
189 Age filter:
190
190
191 $ hg init unstable-hash
191 $ hg init unstable-hash
192 $ cd unstable-hash
192 $ cd unstable-hash
193 $ hg log --template '{date|age}\n' > /dev/null || exit 1
193 $ hg log --template '{date|age}\n' > /dev/null || exit 1
194
194
195 >>> from __future__ import absolute_import
195 >>> from __future__ import absolute_import
196 >>> import datetime
196 >>> import datetime
197 >>> fp = open('a', 'wb')
197 >>> fp = open('a', 'wb')
198 >>> n = datetime.datetime.now() + datetime.timedelta(366 * 7)
198 >>> n = datetime.datetime.now() + datetime.timedelta(366 * 7)
199 >>> fp.write(b'%d-%d-%d 00:00' % (n.year, n.month, n.day)) and None
199 >>> fp.write(b'%d-%d-%d 00:00' % (n.year, n.month, n.day)) and None
200 >>> fp.close()
200 >>> fp.close()
201 $ hg add a
201 $ hg add a
202 $ hg commit -m future -d "`cat a`"
202 $ hg commit -m future -d "`cat a`"
203
203
204 $ hg log -l1 --template '{date|age}\n'
204 $ hg log -l1 --template '{date|age}\n'
205 7 years from now
205 7 years from now
206
206
207 $ cd ..
207 $ cd ..
208 $ rm -rf unstable-hash
208 $ rm -rf unstable-hash
209
209
210 Filename filters:
210 Filename filters:
211
211
212 $ hg debugtemplate '{"foo/bar"|basename}|{"foo/"|basename}|{"foo"|basename}|\n'
212 $ hg debugtemplate '{"foo/bar"|basename}|{"foo/"|basename}|{"foo"|basename}|\n'
213 bar||foo|
213 bar||foo|
214 $ hg debugtemplate '{"foo/bar"|dirname}|{"foo/"|dirname}|{"foo"|dirname}|\n'
214 $ hg debugtemplate '{"foo/bar"|dirname}|{"foo/"|dirname}|{"foo"|dirname}|\n'
215 foo|foo||
215 foo|foo||
216 $ hg debugtemplate '{"foo/bar"|stripdir}|{"foo/"|stripdir}|{"foo"|stripdir}|\n'
216 $ hg debugtemplate '{"foo/bar"|stripdir}|{"foo/"|stripdir}|{"foo"|stripdir}|\n'
217 foo|foo|foo|
217 foo|foo|foo|
218
218
219 commondir() filter:
219 commondir() filter:
220
220
221 $ hg debugtemplate '{""|splitlines|commondir}\n'
221 $ hg debugtemplate '{""|splitlines|commondir}\n'
222
222
223 $ hg debugtemplate '{"foo/bar\nfoo/baz\nfoo/foobar\n"|splitlines|commondir}\n'
223 $ hg debugtemplate '{"foo/bar\nfoo/baz\nfoo/foobar\n"|splitlines|commondir}\n'
224 foo
224 foo
225 $ hg debugtemplate '{"foo/bar\nfoo/bar\n"|splitlines|commondir}\n'
225 $ hg debugtemplate '{"foo/bar\nfoo/bar\n"|splitlines|commondir}\n'
226 foo
226 foo
227 $ hg debugtemplate '{"/foo/bar\n/foo/bar\n"|splitlines|commondir}\n'
227 $ hg debugtemplate '{"/foo/bar\n/foo/bar\n"|splitlines|commondir}\n'
228 foo
228 foo
229 $ hg debugtemplate '{"/foo\n/foo\n"|splitlines|commondir}\n'
229 $ hg debugtemplate '{"/foo\n/foo\n"|splitlines|commondir}\n'
230
230
231 $ hg debugtemplate '{"foo/bar\nbar/baz"|splitlines|commondir}\n'
231 $ hg debugtemplate '{"foo/bar\nbar/baz"|splitlines|commondir}\n'
232
232
233 $ hg debugtemplate '{"foo/bar\nbar/baz\nbar/foo\n"|splitlines|commondir}\n'
233 $ hg debugtemplate '{"foo/bar\nbar/baz\nbar/foo\n"|splitlines|commondir}\n'
234
234
235 $ hg debugtemplate '{"foo/../bar\nfoo/bar"|splitlines|commondir}\n'
235 $ hg debugtemplate '{"foo/../bar\nfoo/bar"|splitlines|commondir}\n'
236 foo
236 foo
237 $ hg debugtemplate '{"foo\n/foo"|splitlines|commondir}\n'
237 $ hg debugtemplate '{"foo\n/foo"|splitlines|commondir}\n'
238
238
239
239
240 $ hg log -r null -T '{rev|commondir}'
240 $ hg log -r null -T '{rev|commondir}'
241 hg: parse error: argument is not a list of text
241 hg: parse error: argument is not a list of text
242 (template filter 'commondir' is not compatible with keyword 'rev')
242 (template filter 'commondir' is not compatible with keyword 'rev')
243 [255]
243 [255]
244
244
245 Add a dummy commit to make up for the instability of the above:
245 Add a dummy commit to make up for the instability of the above:
246
246
247 $ echo a > a
247 $ echo a > a
248 $ hg add a
248 $ hg add a
249 $ hg ci -m future
249 $ hg ci -m future
250
250
251 Count filter:
251 Count filter:
252
252
253 $ hg log -l1 --template '{node|count} {node|short|count}\n'
253 $ hg log -l1 --template '{node|count} {node|short|count}\n'
254 40 12
254 40 12
255
255
256 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
256 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
257 0 1 4
257 0 1 4
258
258
259 $ hg log -G --template '{rev}: children: {children|count}, \
259 $ hg log -G --template '{rev}: children: {children|count}, \
260 > tags: {tags|count}, file_adds: {file_adds|count}, \
260 > tags: {tags|count}, file_adds: {file_adds|count}, \
261 > ancestors: {revset("ancestors(%s)", rev)|count}'
261 > ancestors: {revset("ancestors(%s)", rev)|count}'
262 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
262 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
263 |
263 |
264 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
264 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
265 |
265 |
266 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
266 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
267
267
268 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
268 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
269 |\
269 |\
270 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
270 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
271 | |
271 | |
272 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
272 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
273 |/
273 |/
274 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
274 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
275 |
275 |
276 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
276 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
277 |
277 |
278 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
278 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
279 |
279 |
280 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
280 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
281
281
282
282
283 $ hg log -l1 -T '{termwidth|count}\n'
283 $ hg log -l1 -T '{termwidth|count}\n'
284 hg: parse error: not countable
284 hg: parse error: not countable
285 (template filter 'count' is not compatible with keyword 'termwidth')
285 (template filter 'count' is not compatible with keyword 'termwidth')
286 [255]
286 [255]
287
287
288 Upper/lower filters:
288 Upper/lower filters:
289
289
290 $ hg log -r0 --template '{branch|upper}\n'
290 $ hg log -r0 --template '{branch|upper}\n'
291 DEFAULT
291 DEFAULT
292 $ hg log -r0 --template '{author|lower}\n'
292 $ hg log -r0 --template '{author|lower}\n'
293 user name <user@hostname>
293 user name <user@hostname>
294 $ hg log -r0 --template '{date|upper}\n'
294 $ hg log -r0 --template '{date|upper}\n'
295 1000000.00
295 1000000.00
296
296
297 Add a commit that does all possible modifications at once
297 Add a commit that does all possible modifications at once
298
298
299 $ echo modify >> third
299 $ echo modify >> third
300 $ touch b
300 $ touch b
301 $ hg add b
301 $ hg add b
302 $ hg mv fourth fifth
302 $ hg mv fourth fifth
303 $ hg rm a
303 $ hg rm a
304 $ hg ci -m "Modify, add, remove, rename"
304 $ hg ci -m "Modify, add, remove, rename"
305
305
306 Pass generator object created by template function to filter
306 Pass generator object created by template function to filter
307
307
308 $ hg log -l 1 --template '{if(author, author)|user}\n'
308 $ hg log -l 1 --template '{if(author, author)|user}\n'
309 test
309 test
310
310
311 Test diff function:
311 Test diff function:
312
312
313 $ hg diff -c 8
313 $ hg diff -c 8
314 diff -r 29114dbae42b -r 95c24699272e fourth
314 diff -r 29114dbae42b -r 95c24699272e fourth
315 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
315 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
316 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
316 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
317 @@ -0,0 +1,1 @@
317 @@ -0,0 +1,1 @@
318 +second
318 +second
319 diff -r 29114dbae42b -r 95c24699272e second
319 diff -r 29114dbae42b -r 95c24699272e second
320 --- a/second Mon Jan 12 13:46:40 1970 +0000
320 --- a/second Mon Jan 12 13:46:40 1970 +0000
321 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
321 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
322 @@ -1,1 +0,0 @@
322 @@ -1,1 +0,0 @@
323 -second
323 -second
324 diff -r 29114dbae42b -r 95c24699272e third
324 diff -r 29114dbae42b -r 95c24699272e third
325 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
325 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
326 +++ b/third Wed Jan 01 10:01:00 2020 +0000
326 +++ b/third Wed Jan 01 10:01:00 2020 +0000
327 @@ -0,0 +1,1 @@
327 @@ -0,0 +1,1 @@
328 +third
328 +third
329
329
330 $ hg log -r 8 -T "{diff()}"
330 $ hg log -r 8 -T "{diff()}"
331 diff -r 29114dbae42b -r 95c24699272e fourth
331 diff -r 29114dbae42b -r 95c24699272e fourth
332 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
332 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
333 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
333 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
334 @@ -0,0 +1,1 @@
334 @@ -0,0 +1,1 @@
335 +second
335 +second
336 diff -r 29114dbae42b -r 95c24699272e second
336 diff -r 29114dbae42b -r 95c24699272e second
337 --- a/second Mon Jan 12 13:46:40 1970 +0000
337 --- a/second Mon Jan 12 13:46:40 1970 +0000
338 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
338 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
339 @@ -1,1 +0,0 @@
339 @@ -1,1 +0,0 @@
340 -second
340 -second
341 diff -r 29114dbae42b -r 95c24699272e third
341 diff -r 29114dbae42b -r 95c24699272e third
342 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
342 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
343 +++ b/third Wed Jan 01 10:01:00 2020 +0000
343 +++ b/third Wed Jan 01 10:01:00 2020 +0000
344 @@ -0,0 +1,1 @@
344 @@ -0,0 +1,1 @@
345 +third
345 +third
346
346
347 $ hg log -r 8 -T "{diff('glob:f*')}"
347 $ hg log -r 8 -T "{diff('glob:f*')}"
348 diff -r 29114dbae42b -r 95c24699272e fourth
348 diff -r 29114dbae42b -r 95c24699272e fourth
349 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
349 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
350 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
350 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
351 @@ -0,0 +1,1 @@
351 @@ -0,0 +1,1 @@
352 +second
352 +second
353
353
354 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
354 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
355 diff -r 29114dbae42b -r 95c24699272e second
355 diff -r 29114dbae42b -r 95c24699272e second
356 --- a/second Mon Jan 12 13:46:40 1970 +0000
356 --- a/second Mon Jan 12 13:46:40 1970 +0000
357 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
357 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
358 @@ -1,1 +0,0 @@
358 @@ -1,1 +0,0 @@
359 -second
359 -second
360 diff -r 29114dbae42b -r 95c24699272e third
360 diff -r 29114dbae42b -r 95c24699272e third
361 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
361 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
362 +++ b/third Wed Jan 01 10:01:00 2020 +0000
362 +++ b/third Wed Jan 01 10:01:00 2020 +0000
363 @@ -0,0 +1,1 @@
363 @@ -0,0 +1,1 @@
364 +third
364 +third
365
365
366 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
366 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
367 diff -r 29114dbae42b -r 95c24699272e fourth
367 diff -r 29114dbae42b -r 95c24699272e fourth
368 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
368 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
369 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
369 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
370 @@ -0,0 +1,1 @@
370 @@ -0,0 +1,1 @@
371 +second
371 +second
372
372
373 $ cd ..
373 $ cd ..
374
374
375 latesttag() function:
375 latesttag() function:
376
376
377 $ hg init latesttag
377 $ hg init latesttag
378 $ cd latesttag
378 $ cd latesttag
379
379
380 $ echo a > file
380 $ echo a > file
381 $ hg ci -Am a -d '0 0'
381 $ hg ci -Am a -d '0 0'
382 adding file
382 adding file
383
383
384 $ echo b >> file
384 $ echo b >> file
385 $ hg ci -m b -d '1 0'
385 $ hg ci -m b -d '1 0'
386
386
387 $ echo c >> head1
387 $ echo c >> head1
388 $ hg ci -Am h1c -d '2 0'
388 $ hg ci -Am h1c -d '2 0'
389 adding head1
389 adding head1
390
390
391 $ hg update -q 1
391 $ hg update -q 1
392 $ echo d >> head2
392 $ echo d >> head2
393 $ hg ci -Am h2d -d '3 0'
393 $ hg ci -Am h2d -d '3 0'
394 adding head2
394 adding head2
395 created new head
395 created new head
396
396
397 $ echo e >> head2
397 $ echo e >> head2
398 $ hg ci -m h2e -d '4 0'
398 $ hg ci -m h2e -d '4 0'
399
399
400 $ hg merge -q
400 $ hg merge -q
401 $ hg ci -m merge -d '5 -3600'
401 $ hg ci -m merge -d '5 -3600'
402
402
403 $ hg tag -r 1 -m t1 -d '6 0' t1
403 $ hg tag -r 1 -m t1 -d '6 0' t1
404 $ hg tag -r 2 -m t2 -d '7 0' t2
404 $ hg tag -r 2 -m t2 -d '7 0' t2
405 $ hg tag -r 3 -m t3 -d '8 0' t3
405 $ hg tag -r 3 -m t3 -d '8 0' t3
406 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
406 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
407 $ hg tag -r 5 -m t5 -d '9 0' t5
407 $ hg tag -r 5 -m t5 -d '9 0' t5
408 $ hg tag -r 3 -m at3 -d '10 0' at3
408 $ hg tag -r 3 -m at3 -d '10 0' at3
409
409
410 $ hg log -G --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
410 $ hg log -G --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
411 @ 11: t3, C: 9, D: 8
411 @ 11: t3, C: 9, D: 8
412 |
412 |
413 o 10: t3, C: 8, D: 7
413 o 10: t3, C: 8, D: 7
414 |
414 |
415 o 9: t3, C: 7, D: 6
415 o 9: t3, C: 7, D: 6
416 |
416 |
417 o 8: t3, C: 6, D: 5
417 o 8: t3, C: 6, D: 5
418 |
418 |
419 o 7: t3, C: 5, D: 4
419 o 7: t3, C: 5, D: 4
420 |
420 |
421 o 6: t3, C: 4, D: 3
421 o 6: t3, C: 4, D: 3
422 |
422 |
423 o 5: t3, C: 3, D: 2
423 o 5: t3, C: 3, D: 2
424 |\
424 |\
425 | o 4: t3, C: 1, D: 1
425 | o 4: t3, C: 1, D: 1
426 | |
426 | |
427 | o 3: t3, C: 0, D: 0
427 | o 3: t3, C: 0, D: 0
428 | |
428 | |
429 o | 2: t1, C: 1, D: 1
429 o | 2: t1, C: 1, D: 1
430 |/
430 |/
431 o 1: t1, C: 0, D: 0
431 o 1: t1, C: 0, D: 0
432 |
432 |
433 o 0: null, C: 1, D: 1
433 o 0: null, C: 1, D: 1
434
434
435
435
436 $ cd ..
436 $ cd ..
437
437
438 Test filter() empty values:
438 Test filter() empty values:
439
439
440 $ hg log -R a -r 1 -T '{filter(desc|splitlines) % "{line}\n"}'
440 $ hg log -R a -r 1 -T '{filter(desc|splitlines) % "{line}\n"}'
441 other 1
441 other 1
442 other 2
442 other 2
443 other 3
443 other 3
444 $ hg log -R a -r 0 -T '{filter(dict(a=0, b=1) % "{ifeq(key, "a", "{value}\n")}")}'
444 $ hg log -R a -r 0 -T '{filter(dict(a=0, b=1) % "{ifeq(key, "a", "{value}\n")}")}'
445 0
445 0
446
446
447 0 should not be falsy
447 0 should not be falsy
448
448
449 $ hg log -R a -r 0 -T '{filter(revset("0:2"))}\n'
449 $ hg log -R a -r 0 -T '{filter(revset("0:2"))}\n'
450 0 1 2
450 0 1 2
451
451
452 Test filter() by expression:
452 Test filter() by expression:
453
453
454 $ hg log -R a -r 1 -T '{filter(desc|splitlines, ifcontains("1", line, "t"))}\n'
454 $ hg log -R a -r 1 -T '{filter(desc|splitlines, ifcontains("1", line, "t"))}\n'
455 other 1
455 other 1
456 $ hg log -R a -r 0 -T '{filter(dict(a=0, b=1), ifeq(key, "b", "t"))}\n'
456 $ hg log -R a -r 0 -T '{filter(dict(a=0, b=1), ifeq(key, "b", "t"))}\n'
457 b=1
457 b=1
458
458
459 Test filter() shouldn't crash:
459 Test filter() shouldn't crash:
460
460
461 $ hg log -R a -r 0 -T '{filter(extras)}\n'
461 $ hg log -R a -r 0 -T '{filter(extras)}\n'
462 branch=default
462 branch=default
463 $ hg log -R a -r 0 -T '{filter(files)}\n'
463 $ hg log -R a -r 0 -T '{filter(files)}\n'
464 a
464 a
465
465
466 Test filter() unsupported arguments:
466 Test filter() unsupported arguments:
467
467
468 $ hg log -R a -r 0 -T '{filter()}\n'
468 $ hg log -R a -r 0 -T '{filter()}\n'
469 hg: parse error: filter expects one or two arguments
469 hg: parse error: filter expects one or two arguments
470 [255]
470 [255]
471 $ hg log -R a -r 0 -T '{filter(date)}\n'
471 $ hg log -R a -r 0 -T '{filter(date)}\n'
472 hg: parse error: date is not iterable
472 hg: parse error: date is not iterable
473 [255]
473 [255]
474 $ hg log -R a -r 0 -T '{filter(rev)}\n'
474 $ hg log -R a -r 0 -T '{filter(rev)}\n'
475 hg: parse error: 0 is not iterable
475 hg: parse error: 0 is not iterable
476 [255]
476 [255]
477 $ hg log -R a -r 0 -T '{filter(desc|firstline)}\n'
477 $ hg log -R a -r 0 -T '{filter(desc|firstline)}\n'
478 hg: parse error: 'line 1' is not filterable
478 hg: parse error: 'line 1' is not filterable
479 [255]
479 [255]
480 $ hg log -R a -r 0 -T '{filter(manifest)}\n'
480 $ hg log -R a -r 0 -T '{filter(manifest)}\n'
481 hg: parse error: '0:a0c8bcbbb45c' is not filterable
481 hg: parse error: '0:a0c8bcbbb45c' is not filterable
482 [255]
482 [255]
483 $ hg log -R a -r 0 -T '{filter(succsandmarkers)}\n'
483 $ hg log -R a -r 0 -T '{filter(succsandmarkers)}\n'
484 hg: parse error: not filterable without template
484 hg: parse error: not filterable without template
485 [255]
485 [255]
486 $ hg log -R a -r 0 -T '{filter(desc|splitlines % "{line}", "")}\n'
486 $ hg log -R a -r 0 -T '{filter(desc|splitlines % "{line}", "")}\n'
487 hg: parse error: not filterable by expression
487 hg: parse error: not filterable by expression
488 [255]
488 [255]
489
489
490 Test manifest/get() can be join()-ed as string, though it's silly:
490 Test manifest/get() can be join()-ed as string, though it's silly:
491
491
492 $ hg log -R latesttag -r tip -T '{join(manifest, ".")}\n'
492 $ hg log -R latesttag -r tip -T '{join(manifest, ".")}\n'
493 1.1.:.2.b.c.6.e.9.0.0.6.c.e.2
493 1.1.:.2.b.c.6.e.9.0.0.6.c.e.2
494 $ hg log -R latesttag -r tip -T '{join(get(extras, "branch"), ".")}\n'
494 $ hg log -R latesttag -r tip -T '{join(get(extras, "branch"), ".")}\n'
495 d.e.f.a.u.l.t
495 d.e.f.a.u.l.t
496
496
497 Test join() over string
497 Test join() over string
498
498
499 $ hg log -R latesttag -r tip -T '{join(rev|stringify, ".")}\n'
499 $ hg log -R latesttag -r tip -T '{join(rev|stringify, ".")}\n'
500 1.1
500 1.1
501
501
502 Test join() over uniterable
502 Test join() over uniterable
503
503
504 $ hg log -R latesttag -r tip -T '{join(rev, "")}\n'
504 $ hg log -R latesttag -r tip -T '{join(rev, "")}\n'
505 hg: parse error: 11 is not iterable
505 hg: parse error: 11 is not iterable
506 [255]
506 [255]
507
507
508 Test min/max of integers
508 Test min/max of integers
509
509
510 $ hg log -R latesttag -l1 -T '{min(revset("9:10"))}\n'
510 $ hg log -R latesttag -l1 -T '{min(revset("9:10"))}\n'
511 9
511 9
512 $ hg log -R latesttag -l1 -T '{max(revset("9:10"))}\n'
512 $ hg log -R latesttag -l1 -T '{max(revset("9:10"))}\n'
513 10
513 10
514
514
515 Test min/max over map operation:
515 Test min/max over map operation:
516
516
517 $ hg log -R latesttag -r3 -T '{min(tags % "{tag}")}\n'
517 $ hg log -R latesttag -r3 -T '{min(tags % "{tag}")}\n'
518 at3
518 at3
519 $ hg log -R latesttag -r3 -T '{max(tags % "{tag}")}\n'
519 $ hg log -R latesttag -r3 -T '{max(tags % "{tag}")}\n'
520 t3
520 t3
521
521
522 Test min/max of strings:
522 Test min/max of strings:
523
523
524 $ hg log -R latesttag -l1 -T '{min(desc)}\n'
524 $ hg log -R latesttag -l1 -T '{min(desc)}\n'
525 3
525 3
526 $ hg log -R latesttag -l1 -T '{max(desc)}\n'
526 $ hg log -R latesttag -l1 -T '{max(desc)}\n'
527 t
527 t
528
528
529 Test min/max of non-iterable:
529 Test min/max of non-iterable:
530
530
531 $ hg debugtemplate '{min(1)}'
531 $ hg debugtemplate '{min(1)}'
532 hg: parse error: 1 is not iterable
532 hg: parse error: 1 is not iterable
533 (min first argument should be an iterable)
533 (min first argument should be an iterable)
534 [255]
534 [255]
535 $ hg debugtemplate '{max(2)}'
535 $ hg debugtemplate '{max(2)}'
536 hg: parse error: 2 is not iterable
536 hg: parse error: 2 is not iterable
537 (max first argument should be an iterable)
537 (max first argument should be an iterable)
538 [255]
538 [255]
539
539
540 $ hg log -R latesttag -l1 -T '{min(date)}'
540 $ hg log -R latesttag -l1 -T '{min(date)}'
541 hg: parse error: date is not iterable
541 hg: parse error: date is not iterable
542 (min first argument should be an iterable)
542 (min first argument should be an iterable)
543 [255]
543 [255]
544 $ hg log -R latesttag -l1 -T '{max(date)}'
544 $ hg log -R latesttag -l1 -T '{max(date)}'
545 hg: parse error: date is not iterable
545 hg: parse error: date is not iterable
546 (max first argument should be an iterable)
546 (max first argument should be an iterable)
547 [255]
547 [255]
548
548
549 Test min/max of empty sequence:
549 Test min/max of empty sequence:
550
550
551 $ hg debugtemplate '{min("")}'
551 $ hg debugtemplate '{min("")}'
552 hg: parse error: empty string
552 hg: parse error: empty string
553 (min first argument should be an iterable)
553 (min first argument should be an iterable)
554 [255]
554 [255]
555 $ hg debugtemplate '{max("")}'
555 $ hg debugtemplate '{max("")}'
556 hg: parse error: empty string
556 hg: parse error: empty string
557 (max first argument should be an iterable)
557 (max first argument should be an iterable)
558 [255]
558 [255]
559 $ hg debugtemplate '{min(dict())}'
559 $ hg debugtemplate '{min(dict())}'
560 hg: parse error: empty sequence
560 hg: parse error: empty sequence
561 (min first argument should be an iterable)
561 (min first argument should be an iterable)
562 [255]
562 [255]
563 $ hg debugtemplate '{max(dict())}'
563 $ hg debugtemplate '{max(dict())}'
564 hg: parse error: empty sequence
564 hg: parse error: empty sequence
565 (max first argument should be an iterable)
565 (max first argument should be an iterable)
566 [255]
566 [255]
567 $ hg debugtemplate '{min(dict() % "")}'
567 $ hg debugtemplate '{min(dict() % "")}'
568 hg: parse error: empty sequence
568 hg: parse error: empty sequence
569 (min first argument should be an iterable)
569 (min first argument should be an iterable)
570 [255]
570 [255]
571 $ hg debugtemplate '{max(dict() % "")}'
571 $ hg debugtemplate '{max(dict() % "")}'
572 hg: parse error: empty sequence
572 hg: parse error: empty sequence
573 (max first argument should be an iterable)
573 (max first argument should be an iterable)
574 [255]
574 [255]
575
575
576 Test min/max of if() result
576 Test min/max of if() result
577
577
578 $ cd latesttag
578 $ cd latesttag
579 $ hg log -l1 -T '{min(if(true, revset("9:10"), ""))}\n'
579 $ hg log -l1 -T '{min(if(true, revset("9:10"), ""))}\n'
580 9
580 9
581 $ hg log -l1 -T '{max(if(false, "", revset("9:10")))}\n'
581 $ hg log -l1 -T '{max(if(false, "", revset("9:10")))}\n'
582 10
582 10
583 $ hg log -l1 -T '{min(ifcontains("a", "aa", revset("9:10"), ""))}\n'
583 $ hg log -l1 -T '{min(ifcontains("a", "aa", revset("9:10"), ""))}\n'
584 9
584 9
585 $ hg log -l1 -T '{max(ifcontains("a", "bb", "", revset("9:10")))}\n'
585 $ hg log -l1 -T '{max(ifcontains("a", "bb", "", revset("9:10")))}\n'
586 10
586 10
587 $ hg log -l1 -T '{min(ifeq(0, 0, revset("9:10"), ""))}\n'
587 $ hg log -l1 -T '{min(ifeq(0, 0, revset("9:10"), ""))}\n'
588 9
588 9
589 $ hg log -l1 -T '{max(ifeq(0, 1, "", revset("9:10")))}\n'
589 $ hg log -l1 -T '{max(ifeq(0, 1, "", revset("9:10")))}\n'
590 10
590 10
591 $ cd ..
591 $ cd ..
592
592
593 Test laziness of if() then/else clause
593 Test laziness of if() then/else clause
594
594
595 $ hg debugtemplate '{count(0)}'
595 $ hg debugtemplate '{count(0)}'
596 hg: parse error: not countable
596 hg: parse error: not countable
597 (incompatible use of template filter 'count')
597 (incompatible use of template filter 'count')
598 [255]
598 [255]
599 $ hg debugtemplate '{if(true, "", count(0))}'
599 $ hg debugtemplate '{if(true, "", count(0))}'
600 $ hg debugtemplate '{if(false, count(0), "")}'
600 $ hg debugtemplate '{if(false, count(0), "")}'
601 $ hg debugtemplate '{ifcontains("a", "aa", "", count(0))}'
601 $ hg debugtemplate '{ifcontains("a", "aa", "", count(0))}'
602 $ hg debugtemplate '{ifcontains("a", "bb", count(0), "")}'
602 $ hg debugtemplate '{ifcontains("a", "bb", count(0), "")}'
603 $ hg debugtemplate '{ifeq(0, 0, "", count(0))}'
603 $ hg debugtemplate '{ifeq(0, 0, "", count(0))}'
604 $ hg debugtemplate '{ifeq(0, 1, count(0), "")}'
604 $ hg debugtemplate '{ifeq(0, 1, count(0), "")}'
605
605
606 Test search() function:
606 Test search() function:
607
607
608 $ hg log -R a -r2 -T '{desc}\n'
608 $ hg log -R a -r2 -T '{desc}\n'
609 no person
609 no person
610
610
611 $ hg log -R a -r2 -T '{search(r"p.*", desc)}\n'
611 $ hg log -R a -r2 -T '{search(r"p.*", desc)}\n'
612 person
612 person
613
613
614 as bool
614 as bool
615
615
616 $ hg log -R a -r2 -T '{if(search(r"p.*", desc), "", "not ")}found\n'
616 $ hg log -R a -r2 -T '{if(search(r"p.*", desc), "", "not ")}found\n'
617 found
617 found
618 $ hg log -R a -r2 -T '{if(search(r"q", desc), "", "not ")}found\n'
618 $ hg log -R a -r2 -T '{if(search(r"q", desc), "", "not ")}found\n'
619 not found
619 not found
620
620
621 match as json
621 match as json
622
622
623 $ hg log -R a -r2 -T '{search(r"(no) p.*", desc)|json}\n'
623 $ hg log -R a -r2 -T '{search(r"(no) p.*", desc)|json}\n'
624 {"0": "no person", "1": "no"}
624 {"0": "no person", "1": "no"}
625 $ hg log -R a -r2 -T '{search(r"q", desc)|json}\n'
625 $ hg log -R a -r2 -T '{search(r"q", desc)|json}\n'
626 null
626 null
627
627
628 group reference
628 group reference
629
629
630 $ hg log -R a -r2 -T '{search(r"(no) (p.*)", desc) % "{1|upper} {2|hex}"}\n'
630 $ hg log -R a -r2 -T '{search(r"(no) (p.*)", desc) % "{1|upper} {2|hex}"}\n'
631 NO 706572736f6e
631 NO 706572736f6e
632 $ hg log -R a -r2 -T '{search(r"(?P<foo>[a-z]*)", desc) % "{foo}"}\n'
632 $ hg log -R a -r2 -T '{search(r"(?P<foo>[a-z]*)", desc) % "{foo}"}\n'
633 no
633 no
634 $ hg log -R a -r2 -T '{search(r"(?P<foo>[a-z]*)", desc).foo}\n'
634 $ hg log -R a -r2 -T '{search(r"(?P<foo>[a-z]*)", desc).foo}\n'
635 no
635 no
636
636
637 group reference with no match
637 group reference with no match
638
638
639 $ hg log -R a -r2 -T '{search(r"q", desc) % "match: {0}"}\n'
639 $ hg log -R a -r2 -T '{search(r"q", desc) % "match: {0}"}\n'
640
640
641
641
642 bad group names
642 bad group names
643
643
644 $ hg log -R a -r2 -T '{search(r"(?P<0>.)", desc) % "{0}"}\n'
644 $ hg log -R a -r2 -T '{search(r"(?P<0>.)", desc) % "{0}"}\n'
645 hg: parse error: search got an invalid pattern: (?P<0>.)
645 hg: parse error: search got an invalid pattern: (?P<0>.)
646 [255]
646 [255]
647 $ hg log -R a -r2 -T '{search(r"(?P<repo>.)", desc) % "{repo}"}\n'
647 $ hg log -R a -r2 -T '{search(r"(?P<repo>.)", desc) % "{repo}"}\n'
648 hg: parse error: invalid group 'repo' in search pattern: (?P<repo>.)
648 hg: parse error: invalid group 'repo' in search pattern: (?P<repo>.)
649 [255]
649 [255]
650
650
651 Test the sub function of templating for expansion:
651 Test the sub function of templating for expansion:
652
652
653 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
653 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
654 xx
654 xx
655
655
656 $ hg log -R latesttag -r 10 -T '{sub("[", "x", rev)}\n'
656 $ hg log -R latesttag -r 10 -T '{sub("[", "x", rev)}\n'
657 hg: parse error: sub got an invalid pattern: [
657 hg: parse error: sub got an invalid pattern: [
658 [255]
658 [255]
659 $ hg log -R latesttag -r 10 -T '{sub("[0-9]", r"\1", rev)}\n'
659 $ hg log -R latesttag -r 10 -T '{sub("[0-9]", r"\1", rev)}\n'
660 hg: parse error: sub got an invalid replacement: \1
660 hg: parse error: sub got an invalid replacement: \1
661 [255]
661 [255]
662
662
663 Test the strip function with chars specified:
663 Test the strip function with chars specified:
664
664
665 $ hg log -R latesttag --template '{desc}\n'
665 $ hg log -R latesttag --template '{desc}\n'
666 at3
666 at3
667 t5
667 t5
668 t4
668 t4
669 t3
669 t3
670 t2
670 t2
671 t1
671 t1
672 merge
672 merge
673 h2e
673 h2e
674 h2d
674 h2d
675 h1c
675 h1c
676 b
676 b
677 a
677 a
678
678
679 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
679 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
680 at3
680 at3
681 5
681 5
682 4
682 4
683 3
683 3
684 2
684 2
685 1
685 1
686 merg
686 merg
687 h2
687 h2
688 h2d
688 h2d
689 h1c
689 h1c
690 b
690 b
691 a
691 a
692
692
693 Test date format:
693 Test date format:
694
694
695 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
695 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
696 date: 70 01 01 10 +0000
696 date: 70 01 01 10 +0000
697 date: 70 01 01 09 +0000
697 date: 70 01 01 09 +0000
698 date: 70 01 01 04 +0000
698 date: 70 01 01 04 +0000
699 date: 70 01 01 08 +0000
699 date: 70 01 01 08 +0000
700 date: 70 01 01 07 +0000
700 date: 70 01 01 07 +0000
701 date: 70 01 01 06 +0000
701 date: 70 01 01 06 +0000
702 date: 70 01 01 05 +0100
702 date: 70 01 01 05 +0100
703 date: 70 01 01 04 +0000
703 date: 70 01 01 04 +0000
704 date: 70 01 01 03 +0000
704 date: 70 01 01 03 +0000
705 date: 70 01 01 02 +0000
705 date: 70 01 01 02 +0000
706 date: 70 01 01 01 +0000
706 date: 70 01 01 01 +0000
707 date: 70 01 01 00 +0000
707 date: 70 01 01 00 +0000
708
708
709 Test invalid date:
709 Test invalid date:
710
710
711 $ hg log -R latesttag -T '{date(rev)}\n'
711 $ hg log -R latesttag -T '{date(rev)}\n'
712 hg: parse error: date expects a date information
712 hg: parse error: date expects a date information
713 [255]
713 [255]
714
714
715 Set up repository containing template fragments in commit metadata:
715 Set up repository containing template fragments in commit metadata:
716
716
717 $ hg init r
717 $ hg init r
718 $ cd r
718 $ cd r
719 $ echo a > a
719 $ echo a > a
720 $ hg ci -Am '{rev}'
720 $ hg ci -Am '{rev}'
721 adding a
721 adding a
722
722
723 $ hg branch -q 'text.{rev}'
723 $ hg branch -q 'text.{rev}'
724 $ echo aa >> aa
724 $ echo aa >> aa
725 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
725 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
726
726
727 color effect can be specified without quoting:
727 color effect can be specified without quoting:
728
728
729 $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
729 $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
730 \x1b[0;31mtext\x1b[0m (esc)
730 \x1b[0;31mtext\x1b[0m (esc)
731
731
732 color effects can be nested (issue5413)
732 color effects can be nested (issue5413)
733
733
734 $ hg debugtemplate --color=always \
734 $ hg debugtemplate --color=always \
735 > '{label(red, "red{label(magenta, "ma{label(cyan, "cyan")}{label(yellow, "yellow")}genta")}")}\n'
735 > '{label(red, "red{label(magenta, "ma{label(cyan, "cyan")}{label(yellow, "yellow")}genta")}")}\n'
736 \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)
736 \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)
737
737
738 pad() should interact well with color codes (issue5416)
738 pad() should interact well with color codes (issue5416)
739
739
740 $ hg debugtemplate --color=always \
740 $ hg debugtemplate --color=always \
741 > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n'
741 > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n'
742 \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc)
742 \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc)
743
743
744 pad() with truncate has to strip color codes, though
744 pad() with truncate has to strip color codes, though
745
745
746 $ hg debugtemplate --color=always \
746 $ hg debugtemplate --color=always \
747 > '{pad(label(red, "scarlet"), 5, truncate=true)}\n'
747 > '{pad(label(red, "scarlet"), 5, truncate=true)}\n'
748 scarl
748 scarl
749
749
750 label should be no-op if color is disabled:
750 label should be no-op if color is disabled:
751
751
752 $ hg log --color=never -l 1 --template '{label(red, "text\n")}'
752 $ hg log --color=never -l 1 --template '{label(red, "text\n")}'
753 text
753 text
754 $ hg log --config extensions.color=! -l 1 --template '{label(red, "text\n")}'
754 $ hg log --config extensions.color=! -l 1 --template '{label(red, "text\n")}'
755 text
755 text
756
756
757 Test branches inside if statement:
757 Test branches inside if statement:
758
758
759 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
759 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
760 no
760 no
761
761
762 Test dict constructor:
762 Test dict constructor:
763
763
764 $ hg log -r 0 -T '{dict(y=node|short, x=rev)}\n'
764 $ hg log -r 0 -T '{dict(y=node|short, x=rev)}\n'
765 y=f7769ec2ab97 x=0
765 y=f7769ec2ab97 x=0
766 $ hg log -r 0 -T '{dict(x=rev, y=node|short) % "{key}={value}\n"}'
766 $ hg log -r 0 -T '{dict(x=rev, y=node|short) % "{key}={value}\n"}'
767 x=0
767 x=0
768 y=f7769ec2ab97
768 y=f7769ec2ab97
769 $ hg log -r 0 -T '{dict(x=rev, y=node|short)|json}\n'
769 $ hg log -r 0 -T '{dict(x=rev, y=node|short)|json}\n'
770 {"x": 0, "y": "f7769ec2ab97"}
770 {"x": 0, "y": "f7769ec2ab97"}
771 $ hg log -r 0 -T '{dict()|json}\n'
771 $ hg log -r 0 -T '{dict()|json}\n'
772 {}
772 {}
773
773
774 $ hg log -r 0 -T '{dict(rev, node=node|short)}\n'
774 $ hg log -r 0 -T '{dict(rev, node=node|short)}\n'
775 rev=0 node=f7769ec2ab97
775 rev=0 node=f7769ec2ab97
776 $ hg log -r 0 -T '{dict(rev, node|short)}\n'
776 $ hg log -r 0 -T '{dict(rev, node|short)}\n'
777 rev=0 node=f7769ec2ab97
777 rev=0 node=f7769ec2ab97
778
778
779 $ hg log -r 0 -T '{dict(rev, rev=rev)}\n'
779 $ hg log -r 0 -T '{dict(rev, rev=rev)}\n'
780 hg: parse error: duplicated dict key 'rev' inferred
780 hg: parse error: duplicated dict key 'rev' inferred
781 [255]
781 [255]
782 $ hg log -r 0 -T '{dict(node, node|short)}\n'
782 $ hg log -r 0 -T '{dict(node, node|short)}\n'
783 hg: parse error: duplicated dict key 'node' inferred
783 hg: parse error: duplicated dict key 'node' inferred
784 [255]
784 [255]
785 $ hg log -r 0 -T '{dict(1 + 2)}'
785 $ hg log -r 0 -T '{dict(1 + 2)}'
786 hg: parse error: dict key cannot be inferred
786 hg: parse error: dict key cannot be inferred
787 [255]
787 [255]
788
788
789 $ hg log -r 0 -T '{dict(x=rev, x=node)}'
789 $ hg log -r 0 -T '{dict(x=rev, x=node)}'
790 hg: parse error: dict got multiple values for keyword argument 'x'
790 hg: parse error: dict got multiple values for keyword argument 'x'
791 [255]
791 [255]
792
792
793 Test get function:
793 Test get function:
794
794
795 $ hg log -r 0 --template '{get(extras, "branch")}\n'
795 $ hg log -r 0 --template '{get(extras, "branch")}\n'
796 default
796 default
797 $ hg log -r 0 --template '{get(extras, "br{"anch"}")}\n'
797 $ hg log -r 0 --template '{get(extras, "br{"anch"}")}\n'
798 default
798 default
799 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
799 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
800 hg: parse error: not a dictionary
800 hg: parse error: not a dictionary
801 (get() expects a dict as first argument)
801 (get() expects a dict as first argument)
802 [255]
802 [255]
803
803
804 Test json filter applied to wrapped object:
804 Test json filter applied to wrapped object:
805
805
806 $ hg log -r0 -T '{files|json}\n'
806 $ hg log -r0 -T '{files|json}\n'
807 ["a"]
807 ["a"]
808 $ hg log -r0 -T '{extras|json}\n'
808 $ hg log -r0 -T '{extras|json}\n'
809 {"branch": "default"}
809 {"branch": "default"}
810 $ hg log -r0 -T '{date|json}\n'
810 $ hg log -r0 -T '{date|json}\n'
811 [0, 0]
811 [0, 0]
812
812
813 Test json filter applied to map result:
813 Test json filter applied to map result:
814
814
815 $ hg log -r0 -T '{json(extras % "{key}")}\n'
815 $ hg log -r0 -T '{json(extras % "{key}")}\n'
816 ["branch"]
816 ["branch"]
817
817
818 Test localdate(date, tz) function:
818 Test localdate(date, tz) function:
819
819
820 $ TZ=JST-09 hg log -r0 -T '{date|localdate|isodate}\n'
820 $ TZ=JST-09 hg log -r0 -T '{date|localdate|isodate}\n'
821 1970-01-01 09:00 +0900
821 1970-01-01 09:00 +0900
822 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "UTC")|isodate}\n'
822 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "UTC")|isodate}\n'
823 1970-01-01 00:00 +0000
823 1970-01-01 00:00 +0000
824 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n'
824 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n'
825 hg: parse error: localdate expects a timezone
825 hg: parse error: localdate expects a timezone
826 [255]
826 [255]
827 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n'
827 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n'
828 1970-01-01 02:00 +0200
828 1970-01-01 02:00 +0200
829 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n'
829 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n'
830 1970-01-01 00:00 +0000
830 1970-01-01 00:00 +0000
831 $ TZ=JST-09 hg log -r0 -T '{localdate(date, 0)|isodate}\n'
831 $ TZ=JST-09 hg log -r0 -T '{localdate(date, 0)|isodate}\n'
832 1970-01-01 00:00 +0000
832 1970-01-01 00:00 +0000
833 $ hg log -r0 -T '{localdate(date, "invalid")|isodate}\n'
833 $ hg log -r0 -T '{localdate(date, "invalid")|isodate}\n'
834 hg: parse error: localdate expects a timezone
834 hg: parse error: localdate expects a timezone
835 [255]
835 [255]
836 $ hg log -r0 -T '{localdate(date, date)|isodate}\n'
836 $ hg log -r0 -T '{localdate(date, date)|isodate}\n'
837 hg: parse error: localdate expects a timezone
837 hg: parse error: localdate expects a timezone
838 [255]
838 [255]
839
839
840 Test shortest(node) function:
840 Test shortest(node) function:
841
841
842 $ echo b > b
842 $ echo b > b
843 $ hg ci -qAm b
843 $ hg ci -qAm b
844 $ hg log --template '{shortest(node)}\n'
844 $ hg log --template '{shortest(node)}\n'
845 e777
845 e777
846 bcc7
846 bcc7
847 f776
847 f776
848 $ hg log --template '{shortest(node, 10)}\n'
848 $ hg log --template '{shortest(node, 10)}\n'
849 e777603221
849 e777603221
850 bcc7ff960b
850 bcc7ff960b
851 f7769ec2ab
851 f7769ec2ab
852 $ hg log --template '{shortest(node, 1)}\n' -r null
852 $ hg log --template '{shortest(node, 1)}\n' -r null
853 00
853 00
854 $ hg log --template '{node|shortest}\n' -l1
854 $ hg log --template '{node|shortest}\n' -l1
855 e777
855 e777
856
856
857 $ hg log -r 0 -T '{shortest(node, "1{"0"}")}\n'
857 $ hg log -r 0 -T '{shortest(node, "1{"0"}")}\n'
858 f7769ec2ab
858 f7769ec2ab
859 $ hg log -r 0 -T '{shortest(node, "not an int")}\n'
859 $ hg log -r 0 -T '{shortest(node, "not an int")}\n'
860 hg: parse error: shortest() expects an integer minlength
860 hg: parse error: shortest() expects an integer minlength
861 [255]
861 [255]
862
862
863 $ hg log -r 'wdir()' -T '{node|shortest}\n'
863 $ hg log -r 'wdir()' -T '{node|shortest}\n'
864 ffff
864 ffff
865
865
866 $ hg log --template '{shortest("f")}\n' -l1
866 $ hg log --template '{shortest("f")}\n' -l1
867 f
867 f
868
868
869 $ hg log --template '{shortest("0123456789012345678901234567890123456789")}\n' -l1
869 $ hg log --template '{shortest("0123456789012345678901234567890123456789")}\n' -l1
870 0123456789012345678901234567890123456789
870 0123456789012345678901234567890123456789
871
871
872 $ hg log --template '{shortest("01234567890123456789012345678901234567890123456789")}\n' -l1
872 $ hg log --template '{shortest("01234567890123456789012345678901234567890123456789")}\n' -l1
873 01234567890123456789012345678901234567890123456789
873 01234567890123456789012345678901234567890123456789
874
874
875 $ hg log --template '{shortest("not a hex string")}\n' -l1
875 $ hg log --template '{shortest("not a hex string")}\n' -l1
876 not a hex string
876 not a hex string
877
877
878 $ hg log --template '{shortest("not a hex string, but it'\''s 40 bytes long")}\n' -l1
878 $ hg log --template '{shortest("not a hex string, but it'\''s 40 bytes long")}\n' -l1
879 not a hex string, but it's 40 bytes long
879 not a hex string, but it's 40 bytes long
880
880
881 $ hg log --template '{shortest("ffffffffffffffffffffffffffffffffffffffff")}\n' -l1
881 $ hg log --template '{shortest("ffffffffffffffffffffffffffffffffffffffff")}\n' -l1
882 ffff
882 ffff
883
883
884 $ hg log --template '{shortest("fffffff")}\n' -l1
884 $ hg log --template '{shortest("fffffff")}\n' -l1
885 ffff
885 ffff
886
886
887 $ hg log --template '{shortest("ff")}\n' -l1
887 $ hg log --template '{shortest("ff")}\n' -l1
888 ffff
888 ffff
889
889
890 $ cd ..
890 $ cd ..
891
891
892 Test shortest(node) with the repo having short hash collision:
892 Test shortest(node) with the repo having short hash collision:
893
893
894 $ hg init hashcollision
894 $ hg init hashcollision
895 $ cd hashcollision
895 $ cd hashcollision
896 $ cat <<EOF >> .hg/hgrc
896 $ cat <<EOF >> .hg/hgrc
897 > [experimental]
897 > [experimental]
898 > evolution.createmarkers=True
898 > evolution.createmarkers=True
899 > EOF
899 > EOF
900 $ echo 0 > a
900 $ echo 0 > a
901 $ hg ci -qAm 0
901 $ hg ci -qAm 0
902 $ for i in 17 129 248 242 480 580 617 1057 2857 4025; do
902 $ for i in 17 129 248 242 480 580 617 1057 2857 4025; do
903 > hg up -q 0
903 > hg up -q 0
904 > echo $i > a
904 > echo $i > a
905 > hg ci -qm $i
905 > hg ci -qm $i
906 > done
906 > done
907 $ hg up -q null
907 $ hg up -q null
908 $ hg log -r0: -T '{rev}:{node}\n'
908 $ hg log -r0: -T '{rev}:{node}\n'
909 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
909 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
910 1:11424df6dc1dd4ea255eae2b58eaca7831973bbc
910 1:11424df6dc1dd4ea255eae2b58eaca7831973bbc
911 2:11407b3f1b9c3e76a79c1ec5373924df096f0499
911 2:11407b3f1b9c3e76a79c1ec5373924df096f0499
912 3:11dd92fe0f39dfdaacdaa5f3997edc533875cfc4
912 3:11dd92fe0f39dfdaacdaa5f3997edc533875cfc4
913 4:10776689e627b465361ad5c296a20a487e153ca4
913 4:10776689e627b465361ad5c296a20a487e153ca4
914 5:a00be79088084cb3aff086ab799f8790e01a976b
914 5:a00be79088084cb3aff086ab799f8790e01a976b
915 6:a0b0acd79b4498d0052993d35a6a748dd51d13e6
915 6:a0b0acd79b4498d0052993d35a6a748dd51d13e6
916 7:a0457b3450b8e1b778f1163b31a435802987fe5d
916 7:a0457b3450b8e1b778f1163b31a435802987fe5d
917 8:c56256a09cd28e5764f32e8e2810d0f01e2e357a
917 8:c56256a09cd28e5764f32e8e2810d0f01e2e357a
918 9:c5623987d205cd6d9d8389bfc40fff9dbb670b48
918 9:c5623987d205cd6d9d8389bfc40fff9dbb670b48
919 10:c562ddd9c94164376c20b86b0b4991636a3bf84f
919 10:c562ddd9c94164376c20b86b0b4991636a3bf84f
920 $ hg debugobsolete a00be79088084cb3aff086ab799f8790e01a976b
920 $ hg debugobsolete a00be79088084cb3aff086ab799f8790e01a976b
921 obsoleted 1 changesets
921 obsoleted 1 changesets
922 $ hg debugobsolete c5623987d205cd6d9d8389bfc40fff9dbb670b48
922 $ hg debugobsolete c5623987d205cd6d9d8389bfc40fff9dbb670b48
923 obsoleted 1 changesets
923 obsoleted 1 changesets
924 $ hg debugobsolete c562ddd9c94164376c20b86b0b4991636a3bf84f
924 $ hg debugobsolete c562ddd9c94164376c20b86b0b4991636a3bf84f
925 obsoleted 1 changesets
925 obsoleted 1 changesets
926
926
927 nodes starting with '11' (we don't have the revision number '11' though)
927 nodes starting with '11' (we don't have the revision number '11' though)
928
928
929 $ hg log -r 1:3 -T '{rev}:{shortest(node, 0)}\n'
929 $ hg log -r 1:3 -T '{rev}:{shortest(node, 0)}\n'
930 1:1142
930 1:1142
931 2:1140
931 2:1140
932 3:11d
932 3:11d
933
933
934 '5:a00' is hidden, but still we have two nodes starting with 'a0'
934 '5:a00' is hidden, but still we have two nodes starting with 'a0'
935
935
936 $ hg log -r 6:7 -T '{rev}:{shortest(node, 0)}\n'
936 $ hg log -r 6:7 -T '{rev}:{shortest(node, 0)}\n'
937 6:a0b
937 6:a0b
938 7:a04
938 7:a04
939
939
940 node '10' conflicts with the revision number '10' even if it is hidden
940 node '10' conflicts with the revision number '10' even if it is hidden
941 (we could exclude hidden revision numbers, but currently we don't)
941 (we could exclude hidden revision numbers, but currently we don't)
942
942
943 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n'
943 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n'
944 4:107
944 4:107
945 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
945 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
946 4:107
946 4:107
947
947
948 $ hg --config experimental.revisions.prefixhexnode=yes log -r 4 -T '{rev}:{shortest(node, 0)}\n'
948 $ hg --config experimental.revisions.prefixhexnode=yes log -r 4 -T '{rev}:{shortest(node, 0)}\n'
949 4:x10
949 4:x10
950 $ hg --config experimental.revisions.prefixhexnode=yes log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
950 $ hg --config experimental.revisions.prefixhexnode=yes log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
951 4:x10
951 4:x10
952
952
953 node 'c562' should be unique if the other 'c562' nodes are hidden
953 node 'c562' should be unique if the other 'c562' nodes are hidden
954 (but we don't try the slow path to filter out hidden nodes for now)
954 (but we don't try the slow path to filter out hidden nodes for now)
955
955
956 $ hg log -r 8 -T '{rev}:{node|shortest}\n'
956 $ hg log -r 8 -T '{rev}:{node|shortest}\n'
957 8:c5625
957 8:c5625
958 $ hg log -r 8:10 -T '{rev}:{node|shortest}\n' --hidden
958 $ hg log -r 8:10 -T '{rev}:{node|shortest}\n' --hidden
959 8:c5625
959 8:c5625
960 9:c5623
960 9:c5623
961 10:c562d
961 10:c562d
962
962
963 $ cd ..
963 $ cd ..
964
964
965 Test prefixhexnode when the first character of the hash is 0.
965 Test prefixhexnode when the first character of the hash is 0.
966 $ hg init hashcollision2
966 $ hg init hashcollision2
967 $ cd hashcollision2
967 $ cd hashcollision2
968 $ cat <<EOF >> .hg/hgrc
968 $ cat <<EOF >> .hg/hgrc
969 > [experimental]
969 > [experimental]
970 > evolution.createmarkers=True
970 > evolution.createmarkers=True
971 > EOF
971 > EOF
972 $ echo 0 > a
972 $ echo 0 > a
973 $ hg ci -qAm 0
973 $ hg ci -qAm 0
974 $ echo 21 > a
974 $ echo 21 > a
975 $ hg ci -qm 21
975 $ hg ci -qm 21
976 $ hg up -q null
976 $ hg up -q null
977 $ hg log -r0: -T '{rev}:{node}\n'
977 $ hg log -r0: -T '{rev}:{node}\n'
978 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
978 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
979 1:0cf177ba2b1dc3862a00fb81715fec90950201be
979 1:0cf177ba2b1dc3862a00fb81715fec90950201be
980
980
981 we need the 'x' prefix to ensure we aren't colliding with rev0. We identify
981 we need the 'x' prefix to ensure we aren't colliding with rev0. We identify
982 the collision with nullid if we aren't using disambiguatewithin, so we need to set
982 the collision with nullid if we aren't using disambiguatewithin, so we need to set
983 that as well.
983 that as well.
984 $ hg --config experimental.revisions.disambiguatewithin='descendants(0)' \
984 $ hg --config experimental.revisions.disambiguatewithin='descendants(0)' \
985 > --config experimental.revisions.prefixhexnode=yes \
985 > --config experimental.revisions.prefixhexnode=yes \
986 > log -r 1 -T '{rev}:{shortest(node, 0)}\n'
986 > log -r 1 -T '{rev}:{shortest(node, 0)}\n'
987 1:x0
987 1:x0
988
988
989 $ hg debugobsolete 0cf177ba2b1dc3862a00fb81715fec90950201be
989 $ hg debugobsolete 0cf177ba2b1dc3862a00fb81715fec90950201be
990 obsoleted 1 changesets
990 obsoleted 1 changesets
991 $ hg up -q 0
991 $ hg up -q 0
992 $ echo 61 > a
992 $ echo 61 > a
993 $ hg ci -m 61
993 $ hg ci -m 61
994 $ hg log -r0: -T '{rev}:{node}\n'
994 $ hg log -r0: -T '{rev}:{node}\n'
995 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
995 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
996 2:01384dde84b3a511ae0835f35ac40bd806c99bb8
996 2:01384dde84b3a511ae0835f35ac40bd806c99bb8
997
997
998 we still have the 'x' prefix because '0' is still the shortest prefix, since
998 we still have the 'x' prefix because '0' is still the shortest prefix, since
999 rev1's '0c' is hidden.
999 rev1's '0c' is hidden.
1000 $ hg --config experimental.revisions.disambiguatewithin=0:-1-0 \
1000 $ hg --config experimental.revisions.disambiguatewithin=0:-1-0 \
1001 > --config experimental.revisions.prefixhexnode=yes \
1001 > --config experimental.revisions.prefixhexnode=yes \
1002 > log -r 0:-1-0 -T '{rev}:{shortest(node, 0)}\n'
1002 > log -r 0:-1-0 -T '{rev}:{shortest(node, 0)}\n'
1003 2:x0
1003 2:x0
1004
1004
1005 we don't have the 'x' prefix on 2 because '01' is not a synonym for rev1.
1005 we don't have the 'x' prefix on 2 because '01' is not a synonym for rev1.
1006 $ hg --config experimental.revisions.disambiguatewithin=0:-1-0 \
1006 $ hg --config experimental.revisions.disambiguatewithin=0:-1-0 \
1007 > --config experimental.revisions.prefixhexnode=yes \
1007 > --config experimental.revisions.prefixhexnode=yes \
1008 > log -r 0:-1-0 -T '{rev}:{shortest(node, 0)}\n' --hidden
1008 > log -r 0:-1-0 -T '{rev}:{shortest(node, 0)}\n' --hidden
1009 1:0c
1009 1:0c
1010 2:01
1010 2:01
1011
1011
1012 $ cd ..
1012 $ cd ..
1013
1013
1014 Test pad function
1014 Test pad function
1015
1015
1016 $ cd r
1016 $ cd r
1017
1017
1018 $ hg log --template '{pad(rev, 20)} {author|user}\n'
1018 $ hg log --template '{pad(rev, 20)} {author|user}\n'
1019 2 test
1019 2 test
1020 1 {node|short}
1020 1 {node|short}
1021 0 test
1021 0 test
1022
1022
1023 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
1023 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
1024 2 test
1024 2 test
1025 1 {node|short}
1025 1 {node|short}
1026 0 test
1026 0 test
1027
1027
1028 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
1028 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
1029 2------------------- test
1029 2------------------- test
1030 1------------------- {node|short}
1030 1------------------- {node|short}
1031 0------------------- test
1031 0------------------- test
1032
1032
1033 $ hg log --template '{pad(author, 5, "-", False, True)}\n'
1033 $ hg log --template '{pad(author, 5, "-", False, True)}\n'
1034 test-
1034 test-
1035 {node
1035 {node
1036 test-
1036 test-
1037 $ hg log --template '{pad(author, 5, "-", True, True)}\n'
1037 $ hg log --template '{pad(author, 5, "-", True, True)}\n'
1038 -test
1038 -test
1039 hort}
1039 hort}
1040 -test
1040 -test
1041
1041
1042 Test template string in pad function
1042 Test template string in pad function
1043
1043
1044 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
1044 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
1045 {0} test
1045 {0} test
1046
1046
1047 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
1047 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
1048 \{rev} test
1048 \{rev} test
1049
1049
1050 Test width argument passed to pad function
1050 Test width argument passed to pad function
1051
1051
1052 $ hg log -r 0 -T '{pad(rev, "1{"0"}")} {author|user}\n'
1052 $ hg log -r 0 -T '{pad(rev, "1{"0"}")} {author|user}\n'
1053 0 test
1053 0 test
1054 $ hg log -r 0 -T '{pad(rev, "not an int")}\n'
1054 $ hg log -r 0 -T '{pad(rev, "not an int")}\n'
1055 hg: parse error: pad() expects an integer width
1055 hg: parse error: pad() expects an integer width
1056 [255]
1056 [255]
1057
1057
1058 Test invalid fillchar passed to pad function
1058 Test invalid fillchar passed to pad function
1059
1059
1060 $ hg log -r 0 -T '{pad(rev, 10, "")}\n'
1060 $ hg log -r 0 -T '{pad(rev, 10, "")}\n'
1061 hg: parse error: pad() expects a single fill character
1061 hg: parse error: pad() expects a single fill character
1062 [255]
1062 [255]
1063 $ hg log -r 0 -T '{pad(rev, 10, "--")}\n'
1063 $ hg log -r 0 -T '{pad(rev, 10, "--")}\n'
1064 hg: parse error: pad() expects a single fill character
1064 hg: parse error: pad() expects a single fill character
1065 [255]
1065 [255]
1066
1066
1067 Test boolean argument passed to pad function
1067 Test boolean argument passed to pad function
1068
1068
1069 no crash
1069 no crash
1070
1070
1071 $ hg log -r 0 -T '{pad(rev, 10, "-", "f{"oo"}")}\n'
1071 $ hg log -r 0 -T '{pad(rev, 10, "-", "f{"oo"}")}\n'
1072 ---------0
1072 ---------0
1073
1073
1074 string/literal
1074 string/literal
1075
1075
1076 $ hg log -r 0 -T '{pad(rev, 10, "-", "false")}\n'
1076 $ hg log -r 0 -T '{pad(rev, 10, "-", "false")}\n'
1077 ---------0
1077 ---------0
1078 $ hg log -r 0 -T '{pad(rev, 10, "-", false)}\n'
1078 $ hg log -r 0 -T '{pad(rev, 10, "-", false)}\n'
1079 0---------
1079 0---------
1080 $ hg log -r 0 -T '{pad(rev, 10, "-", "")}\n'
1080 $ hg log -r 0 -T '{pad(rev, 10, "-", "")}\n'
1081 0---------
1081 0---------
1082
1082
1083 unknown keyword is evaluated to ''
1083 unknown keyword is evaluated to ''
1084
1084
1085 $ hg log -r 0 -T '{pad(rev, 10, "-", unknownkeyword)}\n'
1085 $ hg log -r 0 -T '{pad(rev, 10, "-", unknownkeyword)}\n'
1086 0---------
1086 0---------
1087
1087
1088 Test separate function
1088 Test separate function
1089
1089
1090 $ hg log -r 0 -T '{separate("-", "", "a", "b", "", "", "c", "")}\n'
1090 $ hg log -r 0 -T '{separate("-", "", "a", "b", "", "", "c", "")}\n'
1091 a-b-c
1091 a-b-c
1092 $ hg log -r 0 -T '{separate(" ", "{rev}:{node|short}", author|user, branch)}\n'
1092 $ hg log -r 0 -T '{separate(" ", "{rev}:{node|short}", author|user, branch)}\n'
1093 0:f7769ec2ab97 test default
1093 0:f7769ec2ab97 test default
1094 $ hg log -r 0 --color=always -T '{separate(" ", "a", label(red, "b"), "c", label(red, ""), "d")}\n'
1094 $ hg log -r 0 --color=always -T '{separate(" ", "a", label(red, "b"), "c", label(red, ""), "d")}\n'
1095 a \x1b[0;31mb\x1b[0m c d (esc)
1095 a \x1b[0;31mb\x1b[0m c d (esc)
1096
1096
1097 Test boolean expression/literal passed to if function
1097 Test boolean expression/literal passed to if function
1098
1098
1099 $ hg log -r 0 -T '{if(rev, "rev 0 is True")}\n'
1099 $ hg log -r 0 -T '{if(rev, "rev 0 is True")}\n'
1100 rev 0 is True
1100 rev 0 is True
1101 $ hg log -r 0 -T '{if(0, "literal 0 is True as well")}\n'
1101 $ hg log -r 0 -T '{if(0, "literal 0 is True as well")}\n'
1102 literal 0 is True as well
1102 literal 0 is True as well
1103 $ hg log -r 0 -T '{if(min(revset(r"0")), "0 of hybriditem is also True")}\n'
1103 $ hg log -r 0 -T '{if(min(revset(r"0")), "0 of hybriditem is also True")}\n'
1104 0 of hybriditem is also True
1104 0 of hybriditem is also True
1105 $ hg log -r 0 -T '{if("", "", "empty string is False")}\n'
1105 $ hg log -r 0 -T '{if("", "", "empty string is False")}\n'
1106 empty string is False
1106 empty string is False
1107 $ hg log -r 0 -T '{if(revset(r"0 - 0"), "", "empty list is False")}\n'
1107 $ hg log -r 0 -T '{if(revset(r"0 - 0"), "", "empty list is False")}\n'
1108 empty list is False
1108 empty list is False
1109 $ hg log -r 0 -T '{if(revset(r"0"), "non-empty list is True")}\n'
1109 $ hg log -r 0 -T '{if(revset(r"0"), "non-empty list is True")}\n'
1110 non-empty list is True
1110 non-empty list is True
1111 $ hg log -r 0 -T '{if(revset(r"0") % "", "list of empty strings is True")}\n'
1111 $ hg log -r 0 -T '{if(revset(r"0") % "", "list of empty strings is True")}\n'
1112 list of empty strings is True
1112 list of empty strings is True
1113 $ hg log -r 0 -T '{if(true, "true is True")}\n'
1113 $ hg log -r 0 -T '{if(true, "true is True")}\n'
1114 true is True
1114 true is True
1115 $ hg log -r 0 -T '{if(false, "", "false is False")}\n'
1115 $ hg log -r 0 -T '{if(false, "", "false is False")}\n'
1116 false is False
1116 false is False
1117 $ hg log -r 0 -T '{if("false", "non-empty string is True")}\n'
1117 $ hg log -r 0 -T '{if("false", "non-empty string is True")}\n'
1118 non-empty string is True
1118 non-empty string is True
1119
1119
1120 Test ifcontains function
1120 Test ifcontains function
1121
1121
1122 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
1122 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
1123 2 is in the string
1123 2 is in the string
1124 1 is not
1124 1 is not
1125 0 is in the string
1125 0 is in the string
1126
1126
1127 $ hg log -T '{rev} {ifcontains(rev, "2 two{" 0"}", "is in the string", "is not")}\n'
1127 $ hg log -T '{rev} {ifcontains(rev, "2 two{" 0"}", "is in the string", "is not")}\n'
1128 2 is in the string
1128 2 is in the string
1129 1 is not
1129 1 is not
1130 0 is in the string
1130 0 is in the string
1131
1131
1132 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
1132 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
1133 2 did not add a
1133 2 did not add a
1134 1 did not add a
1134 1 did not add a
1135 0 added a
1135 0 added a
1136
1136
1137 $ hg log --debug -T '{rev}{ifcontains(1, parents, " is parent of 1")}\n'
1137 $ hg log --debug -T '{rev}{ifcontains(1, parents, " is parent of 1")}\n'
1138 2 is parent of 1
1138 2 is parent of 1
1139 1
1139 1
1140 0
1140 0
1141
1141
1142 $ hg log -l1 -T '{ifcontains("branch", extras, "t", "f")}\n'
1142 $ hg log -l1 -T '{ifcontains("branch", extras, "t", "f")}\n'
1143 t
1143 t
1144 $ hg log -l1 -T '{ifcontains("branch", extras % "{key}", "t", "f")}\n'
1144 $ hg log -l1 -T '{ifcontains("branch", extras % "{key}", "t", "f")}\n'
1145 t
1145 t
1146 $ hg log -l1 -T '{ifcontains("branc", extras % "{key}", "t", "f")}\n'
1146 $ hg log -l1 -T '{ifcontains("branc", extras % "{key}", "t", "f")}\n'
1147 f
1147 f
1148 $ hg log -l1 -T '{ifcontains("branc", stringify(extras % "{key}"), "t", "f")}\n'
1148 $ hg log -l1 -T '{ifcontains("branc", stringify(extras % "{key}"), "t", "f")}\n'
1149 t
1149 t
1150
1150
1151 Test revset function
1151 Test revset function
1152
1152
1153 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
1153 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
1154 2 current rev
1154 2 current rev
1155 1 not current rev
1155 1 not current rev
1156 0 not current rev
1156 0 not current rev
1157
1157
1158 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
1158 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
1159 2 match rev
1159 2 match rev
1160 1 match rev
1160 1 match rev
1161 0 not match rev
1161 0 not match rev
1162
1162
1163 $ hg log -T '{ifcontains(desc, revset(":"), "", "type not match")}\n' -l1
1163 $ hg log -T '{ifcontains(desc, revset(":"), "", "type not match")}\n' -l1
1164 type not match
1164 type not match
1165
1165
1166 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
1166 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
1167 2 Parents: 1
1167 2 Parents: 1
1168 1 Parents: 0
1168 1 Parents: 0
1169 0 Parents:
1169 0 Parents:
1170
1170
1171 $ cat >> .hg/hgrc <<EOF
1171 $ cat >> .hg/hgrc <<EOF
1172 > [revsetalias]
1172 > [revsetalias]
1173 > myparents(\$1) = parents(\$1)
1173 > myparents(\$1) = parents(\$1)
1174 > EOF
1174 > EOF
1175 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
1175 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
1176 2 Parents: 1
1176 2 Parents: 1
1177 1 Parents: 0
1177 1 Parents: 0
1178 0 Parents:
1178 0 Parents:
1179
1179
1180 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
1180 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
1181 Rev: 2
1181 Rev: 2
1182 Ancestor: 0
1182 Ancestor: 0
1183 Ancestor: 1
1183 Ancestor: 1
1184 Ancestor: 2
1184 Ancestor: 2
1185
1185
1186 Rev: 1
1186 Rev: 1
1187 Ancestor: 0
1187 Ancestor: 0
1188 Ancestor: 1
1188 Ancestor: 1
1189
1189
1190 Rev: 0
1190 Rev: 0
1191 Ancestor: 0
1191 Ancestor: 0
1192
1192
1193 $ hg log --template '{revset("TIP"|lower)}\n' -l1
1193 $ hg log --template '{revset("TIP"|lower)}\n' -l1
1194 2
1194 2
1195
1195
1196 $ hg log -T '{revset("%s", "t{"ip"}")}\n' -l1
1196 $ hg log -T '{revset("%s", "t{"ip"}")}\n' -l1
1197 2
1197 2
1198
1198
1199 a list template is evaluated for each item of revset/parents
1199 a list template is evaluated for each item of revset/parents
1200
1200
1201 $ hg log -T '{rev} p: {revset("p1(%s)", rev) % "{rev}:{node|short}"}\n'
1201 $ hg log -T '{rev} p: {revset("p1(%s)", rev) % "{rev}:{node|short}"}\n'
1202 2 p: 1:bcc7ff960b8e
1202 2 p: 1:bcc7ff960b8e
1203 1 p: 0:f7769ec2ab97
1203 1 p: 0:f7769ec2ab97
1204 0 p:
1204 0 p:
1205
1205
1206 $ hg log --debug -T '{rev} p:{parents % " {rev}:{node|short}"}\n'
1206 $ hg log --debug -T '{rev} p:{parents % " {rev}:{node|short}"}\n'
1207 2 p: 1:bcc7ff960b8e -1:000000000000
1207 2 p: 1:bcc7ff960b8e -1:000000000000
1208 1 p: 0:f7769ec2ab97 -1:000000000000
1208 1 p: 0:f7769ec2ab97 -1:000000000000
1209 0 p: -1:000000000000 -1:000000000000
1209 0 p: -1:000000000000 -1:000000000000
1210
1210
1211 therefore, 'revcache' should be recreated for each rev
1211 therefore, 'revcache' should be recreated for each rev
1212
1212
1213 $ hg log -T '{rev} {file_adds}\np {revset("p1(%s)", rev) % "{file_adds}"}\n'
1213 $ hg log -T '{rev} {file_adds}\np {revset("p1(%s)", rev) % "{file_adds}"}\n'
1214 2 aa b
1214 2 aa b
1215 p
1215 p
1216 1
1216 1
1217 p a
1217 p a
1218 0 a
1218 0 a
1219 p
1219 p
1220
1220
1221 $ hg log --debug -T '{rev} {file_adds}\np {parents % "{file_adds}"}\n'
1221 $ hg log --debug -T '{rev} {file_adds}\np {parents % "{file_adds}"}\n'
1222 2 aa b
1222 2 aa b
1223 p
1223 p
1224 1
1224 1
1225 p a
1225 p a
1226 0 a
1226 0 a
1227 p
1227 p
1228
1228
1229 a revset item must be evaluated as an integer revision, not an offset from tip
1229 a revset item must be evaluated as an integer revision, not an offset from tip
1230
1230
1231 $ hg log -l 1 -T '{revset("null") % "{rev}:{node|short}"}\n'
1231 $ hg log -l 1 -T '{revset("null") % "{rev}:{node|short}"}\n'
1232 -1:000000000000
1232 -1:000000000000
1233 $ hg log -l 1 -T '{revset("%s", "null") % "{rev}:{node|short}"}\n'
1233 $ hg log -l 1 -T '{revset("%s", "null") % "{rev}:{node|short}"}\n'
1234 -1:000000000000
1234 -1:000000000000
1235
1235
1236 join() should pick '{rev}' from revset items:
1236 join() should pick '{rev}' from revset items:
1237
1237
1238 $ hg log -R ../a -T '{join(revset("parents(%d)", rev), ", ")}\n' -r6
1238 $ hg log -R ../a -T '{join(revset("parents(%d)", rev), ", ")}\n' -r6
1239 4, 5
1239 4, 5
1240
1240
1241 on the other hand, parents are formatted as '{rev}:{node|formatnode}' by
1241 on the other hand, parents are formatted as '{rev}:{node|formatnode}' by
1242 default. join() should agree with the default formatting:
1242 default. join() should agree with the default formatting:
1243
1243
1244 $ hg log -R ../a -T '{join(parents, ", ")}\n' -r6
1244 $ hg log -R ../a -T '{join(parents, ", ")}\n' -r6
1245 5:13207e5a10d9, 4:bbe44766e73d
1245 5:13207e5a10d9, 4:bbe44766e73d
1246
1246
1247 $ hg log -R ../a -T '{join(parents, ",\n")}\n' -r6 --debug
1247 $ hg log -R ../a -T '{join(parents, ",\n")}\n' -r6 --debug
1248 5:13207e5a10d9fd28ec424934298e176197f2c67f,
1248 5:13207e5a10d9fd28ec424934298e176197f2c67f,
1249 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1249 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1250
1250
1251 Invalid arguments passed to revset()
1251 Invalid arguments passed to revset()
1252
1252
1253 $ hg log -T '{revset("%whatever", 0)}\n'
1253 $ hg log -T '{revset("%whatever", 0)}\n'
1254 hg: parse error: unexpected revspec format character w
1254 hg: parse error: unexpected revspec format character w
1255 [255]
1255 [255]
1256 $ hg log -T '{revset("%lwhatever", files)}\n'
1256 $ hg log -T '{revset("%lwhatever", files)}\n'
1257 hg: parse error: unexpected revspec format character w
1257 hg: parse error: unexpected revspec format character w
1258 [255]
1258 [255]
1259 $ hg log -T '{revset("%s %s", 0)}\n'
1259 $ hg log -T '{revset("%s %s", 0)}\n'
1260 hg: parse error: missing argument for revspec
1260 hg: parse error: missing argument for revspec
1261 [255]
1261 [255]
1262 $ hg log -T '{revset("", 0)}\n'
1262 $ hg log -T '{revset("", 0)}\n'
1263 hg: parse error: too many revspec arguments specified
1263 hg: parse error: too many revspec arguments specified
1264 [255]
1264 [255]
1265 $ hg log -T '{revset("%s", 0, 1)}\n'
1265 $ hg log -T '{revset("%s", 0, 1)}\n'
1266 hg: parse error: too many revspec arguments specified
1266 hg: parse error: too many revspec arguments specified
1267 [255]
1267 [255]
1268 $ hg log -T '{revset("%", 0)}\n'
1268 $ hg log -T '{revset("%", 0)}\n'
1269 hg: parse error: incomplete revspec format character
1269 hg: parse error: incomplete revspec format character
1270 [255]
1270 [255]
1271 $ hg log -T '{revset("%l", 0)}\n'
1271 $ hg log -T '{revset("%l", 0)}\n'
1272 hg: parse error: incomplete revspec format character
1272 hg: parse error: incomplete revspec format character
1273 [255]
1273 [255]
1274 $ hg log -T '{revset("%d", 'foo')}\n'
1274 $ hg log -T '{revset("%d", 'foo')}\n'
1275 hg: parse error: invalid argument for revspec
1275 hg: parse error: invalid argument for revspec
1276 [255]
1276 [255]
1277 $ hg log -T '{revset("%ld", files)}\n'
1277 $ hg log -T '{revset("%ld", files)}\n'
1278 hg: parse error: invalid argument for revspec
1278 hg: parse error: invalid argument for revspec
1279 [255]
1279 [255]
1280 $ hg log -T '{revset("%ls", 0)}\n'
1280 $ hg log -T '{revset("%ls", 0)}\n'
1281 hg: parse error: invalid argument for revspec
1281 hg: parse error: invalid argument for revspec
1282 [255]
1282 [255]
1283 $ hg log -T '{revset("%b", 'foo')}\n'
1283 $ hg log -T '{revset("%b", 'foo')}\n'
1284 hg: parse error: invalid argument for revspec
1284 hg: parse error: invalid argument for revspec
1285 [255]
1285 [255]
1286 $ hg log -T '{revset("%lb", files)}\n'
1286 $ hg log -T '{revset("%lb", files)}\n'
1287 hg: parse error: invalid argument for revspec
1287 hg: parse error: invalid argument for revspec
1288 [255]
1288 [255]
1289 $ hg log -T '{revset("%r", 0)}\n'
1289 $ hg log -T '{revset("%r", 0)}\n'
1290 hg: parse error: invalid argument for revspec
1290 hg: parse error: invalid argument for revspec
1291 [255]
1291 [255]
1292
1292
1293 Test files function
1293 Test files function
1294
1294
1295 $ hg log -T "{rev}\n{join(files('*'), '\n')}\n"
1295 $ hg log -T "{rev}\n{join(files('*'), '\n')}\n"
1296 2
1296 2
1297 a
1297 a
1298 aa
1298 aa
1299 b
1299 b
1300 1
1300 1
1301 a
1301 a
1302 0
1302 0
1303 a
1303 a
1304
1304
1305 $ hg log -T "{rev}\n{join(files('aa'), '\n')}\n"
1305 $ hg log -T "{rev}\n{join(files('aa'), '\n')}\n"
1306 2
1306 2
1307 aa
1307 aa
1308 1
1308 1
1309
1309
1310 0
1310 0
1311
1311
1312
1312
1313 $ hg log -l1 -T "{files('aa') % '{file}\n'}"
1313 $ hg log -l1 -T "{files('aa') % '{file}\n'}"
1314 aa
1314 aa
1315 $ hg log -l1 -T "{files('aa') % '{path}\n'}"
1315 $ hg log -l1 -T "{files('aa') % '{path}\n'}"
1316 aa
1316 aa
1317
1317
1318 $ hg rm a
1318 $ hg rm a
1319 $ hg log -r "wdir()" -T "{rev}\n{join(files('*'), '\n')}\n"
1319 $ hg log -r "wdir()" -T "{rev}\n{join(files('*'), '\n')}\n"
1320 2147483647
1320 2147483647
1321 aa
1321 aa
1322 b
1322 b
1323 $ hg revert a
1323 $ hg revert a
1324
1324
1325 Test relpath function
1325 Test relpath function
1326
1326
1327 $ hg log -r0 -T '{files % "{file|relpath}\n"}'
1327 $ hg log -r0 -T '{files % "{file|relpath}\n"}'
1328 a
1328 a
1329 $ cd ..
1329 $ cd ..
1330 $ hg log -R r -r0 -T '{files % "{file|relpath}\n"}'
1330 $ hg log -R r -r0 -T '{files % "{file|relpath}\n"}'
1331 r/a
1331 r/a
1332
1332
1333 Test stringify on sub expressions
1333 Test stringify on sub expressions
1334
1334
1335 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
1335 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
1336 fourth, second, third
1336 fourth, second, third
1337 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
1337 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
1338 abc
1338 abc
1339
1339
1340 Test splitlines
1340 Test splitlines
1341
1341
1342 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
1342 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
1343 @ foo Modify, add, remove, rename
1343 @ foo Modify, add, remove, rename
1344 |
1344 |
1345 o foo future
1345 o foo future
1346 |
1346 |
1347 o foo third
1347 o foo third
1348 |
1348 |
1349 o foo second
1349 o foo second
1350
1350
1351 o foo merge
1351 o foo merge
1352 |\
1352 |\
1353 | o foo new head
1353 | o foo new head
1354 | |
1354 | |
1355 o | foo new branch
1355 o | foo new branch
1356 |/
1356 |/
1357 o foo no user, no domain
1357 o foo no user, no domain
1358 |
1358 |
1359 o foo no person
1359 o foo no person
1360 |
1360 |
1361 o foo other 1
1361 o foo other 1
1362 | foo other 2
1362 | foo other 2
1363 | foo
1363 | foo
1364 | foo other 3
1364 | foo other 3
1365 o foo line 1
1365 o foo line 1
1366 foo line 2
1366 foo line 2
1367
1367
1368 $ hg log -R a -r0 -T '{desc|splitlines}\n'
1368 $ hg log -R a -r0 -T '{desc|splitlines}\n'
1369 line 1 line 2
1369 line 1 line 2
1370 $ hg log -R a -r0 -T '{join(desc|splitlines, "|")}\n'
1370 $ hg log -R a -r0 -T '{join(desc|splitlines, "|")}\n'
1371 line 1|line 2
1371 line 1|line 2
1372
1372
1373 Test startswith
1373 Test startswith
1374 $ hg log -Gv -R a --template "{startswith(desc)}"
1374 $ hg log -Gv -R a --template "{startswith(desc)}"
1375 hg: parse error: startswith expects two arguments
1375 hg: parse error: startswith expects two arguments
1376 [255]
1376 [255]
1377
1377
1378 $ hg log -Gv -R a --template "{startswith('line', desc)}"
1378 $ hg log -Gv -R a --template "{startswith('line', desc)}"
1379 @
1379 @
1380 |
1380 |
1381 o
1381 o
1382 |
1382 |
1383 o
1383 o
1384 |
1384 |
1385 o
1385 o
1386
1386
1387 o
1387 o
1388 |\
1388 |\
1389 | o
1389 | o
1390 | |
1390 | |
1391 o |
1391 o |
1392 |/
1392 |/
1393 o
1393 o
1394 |
1394 |
1395 o
1395 o
1396 |
1396 |
1397 o
1397 o
1398 |
1398 |
1399 o line 1
1399 o line 1
1400 line 2
1400 line 2
1401
1401
1402 Test word function (including index out of bounds graceful failure)
1402 Test word function (including index out of bounds graceful failure)
1403
1403
1404 $ hg log -Gv -R a --template "{word('1', desc)}"
1404 $ hg log -Gv -R a --template "{word('1', desc)}"
1405 @ add,
1405 @ add,
1406 |
1406 |
1407 o
1407 o
1408 |
1408 |
1409 o
1409 o
1410 |
1410 |
1411 o
1411 o
1412
1412
1413 o
1413 o
1414 |\
1414 |\
1415 | o head
1415 | o head
1416 | |
1416 | |
1417 o | branch
1417 o | branch
1418 |/
1418 |/
1419 o user,
1419 o user,
1420 |
1420 |
1421 o person
1421 o person
1422 |
1422 |
1423 o 1
1423 o 1
1424 |
1424 |
1425 o 1
1425 o 1
1426
1426
1427
1427
1428 Test word third parameter used as splitter
1428 Test word third parameter used as splitter
1429
1429
1430 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
1430 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
1431 @ M
1431 @ M
1432 |
1432 |
1433 o future
1433 o future
1434 |
1434 |
1435 o third
1435 o third
1436 |
1436 |
1437 o sec
1437 o sec
1438
1438
1439 o merge
1439 o merge
1440 |\
1440 |\
1441 | o new head
1441 | o new head
1442 | |
1442 | |
1443 o | new branch
1443 o | new branch
1444 |/
1444 |/
1445 o n
1445 o n
1446 |
1446 |
1447 o n
1447 o n
1448 |
1448 |
1449 o
1449 o
1450 |
1450 |
1451 o line 1
1451 o line 1
1452 line 2
1452 line 2
1453
1453
1454 Test word error messages for not enough and too many arguments
1454 Test word error messages for not enough and too many arguments
1455
1455
1456 $ hg log -Gv -R a --template "{word('0')}"
1456 $ hg log -Gv -R a --template "{word('0')}"
1457 hg: parse error: word expects two or three arguments, got 1
1457 hg: parse error: word expects two or three arguments, got 1
1458 [255]
1458 [255]
1459
1459
1460 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
1460 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
1461 hg: parse error: word expects two or three arguments, got 7
1461 hg: parse error: word expects two or three arguments, got 7
1462 [255]
1462 [255]
1463
1463
1464 Test word for integer literal
1464 Test word for integer literal
1465
1465
1466 $ hg log -R a --template "{word(2, desc)}\n" -r0
1466 $ hg log -R a --template "{word(2, desc)}\n" -r0
1467 line
1467 line
1468
1468
1469 Test word for invalid numbers
1469 Test word for invalid numbers
1470
1470
1471 $ hg log -Gv -R a --template "{word('a', desc)}"
1471 $ hg log -Gv -R a --template "{word('a', desc)}"
1472 hg: parse error: word expects an integer index
1472 hg: parse error: word expects an integer index
1473 [255]
1473 [255]
1474
1474
1475 Test word for out of range
1475 Test word for out of range
1476
1476
1477 $ hg log -R a --template "{word(10000, desc)}"
1477 $ hg log -R a --template "{word(10000, desc)}"
1478 $ hg log -R a --template "{word(-10000, desc)}"
1478 $ hg log -R a --template "{word(-10000, desc)}"
1479
1479
1480 Test indent and not adding to empty lines
1480 Test indent and not adding to empty lines
1481
1481
1482 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
1482 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
1483 -----
1483 -----
1484 > line 1
1484 > line 1
1485 >> line 2
1485 >> line 2
1486 -----
1486 -----
1487 > other 1
1487 > other 1
1488 >> other 2
1488 >> other 2
1489
1489
1490 >> other 3
1490 >> other 3
1491
1491
1492 Test with non-strings like dates
1492 Test with non-strings like dates
1493
1493
1494 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
1494 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
1495 1200000.00
1495 1200000.00
1496 1300000.00
1496 1300000.00
1497
1497
1498 json filter should escape HTML tags so that the output can be embedded in hgweb:
1498 json filter should escape HTML tags so that the output can be embedded in hgweb:
1499
1499
1500 $ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1
1500 $ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1
1501 "\u003cfoo@example.org\u003e"
1501 "\u003cfoo@example.org\u003e"
1502
1502
1503 Set up repository for non-ascii encoding tests:
1503 Set up repository for non-ascii encoding tests:
1504
1504
1505 $ hg init nonascii
1505 $ hg init nonascii
1506 $ cd nonascii
1506 $ cd nonascii
1507 $ "$PYTHON" <<EOF
1507 $ "$PYTHON" <<EOF
1508 > open('latin1', 'wb').write(b'\xe9')
1508 > open('latin1', 'wb').write(b'\xe9')
1509 > open('utf-8', 'wb').write(b'\xc3\xa9')
1509 > open('utf-8', 'wb').write(b'\xc3\xa9')
1510 > EOF
1510 > EOF
1511 $ HGENCODING=utf-8 hg branch -q `cat utf-8`
1511 $ HGENCODING=utf-8 hg branch -q `cat utf-8`
1512 $ HGENCODING=utf-8 hg ci -qAm "non-ascii branch: `cat utf-8`" utf-8
1512 $ HGENCODING=utf-8 hg ci -qAm "non-ascii branch: `cat utf-8`" utf-8
1513
1513
1514 json filter should try round-trip conversion to utf-8:
1514 json filter should try round-trip conversion to utf-8:
1515
1515
1516 $ HGENCODING=ascii hg log -T "{branch|json}\n" -r0
1516 $ HGENCODING=ascii hg log -T "{branch|json}\n" -r0
1517 "\u00e9"
1517 "\u00e9"
1518 $ HGENCODING=ascii hg log -T "{desc|json}\n" -r0
1518 $ HGENCODING=ascii hg log -T "{desc|json}\n" -r0
1519 "non-ascii branch: \u00e9"
1519 "non-ascii branch: \u00e9"
1520
1520
1521 json filter should take input as utf-8 if it was converted from utf-8:
1521 json filter should take input as utf-8 if it was converted from utf-8:
1522
1522
1523 $ HGENCODING=latin-1 hg log -T "{branch|json}\n" -r0
1523 $ HGENCODING=latin-1 hg log -T "{branch|json}\n" -r0
1524 "\u00e9"
1524 "\u00e9"
1525 $ HGENCODING=latin-1 hg log -T "{desc|json}\n" -r0
1525 $ HGENCODING=latin-1 hg log -T "{desc|json}\n" -r0
1526 "non-ascii branch: \u00e9"
1526 "non-ascii branch: \u00e9"
1527
1527
1528 json filter takes input as utf-8b:
1528 json filter takes input as utf-8b:
1529
1529
1530 $ HGENCODING=ascii hg log -T "{'`cat utf-8`'|json}\n" -l1
1530 $ HGENCODING=ascii hg log -T "{'`cat utf-8`'|json}\n" -l1
1531 "\u00e9"
1531 "\u00e9"
1532 $ HGENCODING=ascii hg log -T "{'`cat latin1`'|json}\n" -l1
1532 $ HGENCODING=ascii hg log -T "{'`cat latin1`'|json}\n" -l1
1533 "\udce9"
1533 "\udce9"
1534
1534
1535 utf8 filter:
1535 utf8 filter:
1536
1536
1537 $ HGENCODING=ascii hg log -T "round-trip: {branch|utf8|hex}\n" -r0
1537 $ HGENCODING=ascii hg log -T "round-trip: {branch|utf8|hex}\n" -r0
1538 round-trip: c3a9
1538 round-trip: c3a9
1539 $ HGENCODING=latin1 hg log -T "decoded: {'`cat latin1`'|utf8|hex}\n" -l1
1539 $ HGENCODING=latin1 hg log -T "decoded: {'`cat latin1`'|utf8|hex}\n" -l1
1540 decoded: c3a9
1540 decoded: c3a9
1541 $ HGENCODING=ascii hg log -T "replaced: {'`cat latin1`'|utf8|hex}\n" -l1
1541 $ HGENCODING=ascii hg log -T "replaced: {'`cat latin1`'|utf8|hex}\n" -l1
1542 abort: decoding near * (glob)
1542 abort: decoding near * (glob)
1543 [255]
1543 [255]
1544 $ hg log -T "coerced to string: {rev|utf8}\n" -r0
1544 $ hg log -T "coerced to string: {rev|utf8}\n" -r0
1545 coerced to string: 0
1545 coerced to string: 0
1546
1546
1547 pad width:
1547 pad width:
1548
1548
1549 $ HGENCODING=utf-8 hg debugtemplate "{pad('`cat utf-8`', 2, '-')}\n"
1549 $ HGENCODING=utf-8 hg debugtemplate "{pad('`cat utf-8`', 2, '-')}\n"
1550 \xc3\xa9- (esc)
1550 \xc3\xa9- (esc)
1551
1551
1552 read config options:
1553
1554 $ hg log -T "{config('templateconfig', 'knob', 'foo')}\n"
1555 foo
1556 $ hg log -T "{config('templateconfig', 'knob', 'foo')}\n" \
1557 > --config templateconfig.knob=bar
1558 bar
1559 $ hg log -T "{configbool('templateconfig', 'knob', True)}\n"
1560 True
1561 $ hg log -T "{configbool('templateconfig', 'knob', True)}\n" \
1562 > --config templateconfig.knob=0
1563 False
1564 $ hg log -T "{configint('templateconfig', 'knob', 123)}\n"
1565 123
1566 $ hg log -T "{configint('templateconfig', 'knob', 123)}\n" \
1567 > --config templateconfig.knob=456
1568 456
1569 $ hg log -T "{config('templateconfig', 'knob')}\n"
1570 devel-warn: config item requires an explicit default value: 'templateconfig.knob' at: * (glob)
1571
1572 $ hg log -T "{configbool('ui', 'interactive')}\n"
1573 False
1574 $ hg log -T "{configbool('ui', 'interactive')}\n" --config ui.interactive=1
1575 True
1576 $ hg log -T "{config('templateconfig', 'knob', if(true, 'foo', 'bar'))}\n"
1577 foo
1578
1552 $ cd ..
1579 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now