##// END OF EJS Templates
templater: do not reevaluate rawstring as template (BC)...
Yuya Nishihara -
r25597:fd5bc660 default
parent child Browse files
Show More
@@ -1,688 +1,688
1 # color.py color output for Mercurial commands
1 # color.py color output for Mercurial commands
2 #
2 #
3 # Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.com>
3 # Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.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 '''colorize output from some commands
8 '''colorize output from some commands
9
9
10 The color extension colorizes output from several Mercurial commands.
10 The color extension colorizes output from several Mercurial commands.
11 For example, the diff command shows additions in green and deletions
11 For example, the diff command shows additions in green and deletions
12 in red, while the status command shows modified files in magenta. Many
12 in red, while the status command shows modified files in magenta. Many
13 other commands have analogous colors. It is possible to customize
13 other commands have analogous colors. It is possible to customize
14 these colors.
14 these colors.
15
15
16 Effects
16 Effects
17 -------
17 -------
18
18
19 Other effects in addition to color, like bold and underlined text, are
19 Other effects in addition to color, like bold and underlined text, are
20 also available. By default, the terminfo database is used to find the
20 also available. By default, the terminfo database is used to find the
21 terminal codes used to change color and effect. If terminfo is not
21 terminal codes used to change color and effect. If terminfo is not
22 available, then effects are rendered with the ECMA-48 SGR control
22 available, then effects are rendered with the ECMA-48 SGR control
23 function (aka ANSI escape codes).
23 function (aka ANSI escape codes).
24
24
25 The available effects in terminfo mode are 'blink', 'bold', 'dim',
25 The available effects in terminfo mode are 'blink', 'bold', 'dim',
26 'inverse', 'invisible', 'italic', 'standout', and 'underline'; in
26 'inverse', 'invisible', 'italic', 'standout', and 'underline'; in
27 ECMA-48 mode, the options are 'bold', 'inverse', 'italic', and
27 ECMA-48 mode, the options are 'bold', 'inverse', 'italic', and
28 'underline'. How each is rendered depends on the terminal emulator.
28 'underline'. How each is rendered depends on the terminal emulator.
29 Some may not be available for a given terminal type, and will be
29 Some may not be available for a given terminal type, and will be
30 silently ignored.
30 silently ignored.
31
31
32 Labels
32 Labels
33 ------
33 ------
34
34
35 Text receives color effects depending on the labels that it has. Many
35 Text receives color effects depending on the labels that it has. Many
36 default Mercurial commands emit labelled text. You can also define
36 default Mercurial commands emit labelled text. You can also define
37 your own labels in templates using the label function, see :hg:`help
37 your own labels in templates using the label function, see :hg:`help
38 templates`. A single portion of text may have more than one label. In
38 templates`. A single portion of text may have more than one label. In
39 that case, effects given to the last label will override any other
39 that case, effects given to the last label will override any other
40 effects. This includes the special "none" effect, which nullifies
40 effects. This includes the special "none" effect, which nullifies
41 other effects.
41 other effects.
42
42
43 Labels are normally invisible. In order to see these labels and their
43 Labels are normally invisible. In order to see these labels and their
44 position in the text, use the global --color=debug option. The same
44 position in the text, use the global --color=debug option. The same
45 anchor text may be associated to multiple labels, e.g.
45 anchor text may be associated to multiple labels, e.g.
46
46
47 [log.changeset changeset.secret|changeset: 22611:6f0a53c8f587]
47 [log.changeset changeset.secret|changeset: 22611:6f0a53c8f587]
48
48
49 The following are the default effects for some default labels. Default
49 The following are the default effects for some default labels. Default
50 effects may be overridden from your configuration file::
50 effects may be overridden from your configuration file::
51
51
52 [color]
52 [color]
53 status.modified = blue bold underline red_background
53 status.modified = blue bold underline red_background
54 status.added = green bold
54 status.added = green bold
55 status.removed = red bold blue_background
55 status.removed = red bold blue_background
56 status.deleted = cyan bold underline
56 status.deleted = cyan bold underline
57 status.unknown = magenta bold underline
57 status.unknown = magenta bold underline
58 status.ignored = black bold
58 status.ignored = black bold
59
59
60 # 'none' turns off all effects
60 # 'none' turns off all effects
61 status.clean = none
61 status.clean = none
62 status.copied = none
62 status.copied = none
63
63
64 qseries.applied = blue bold underline
64 qseries.applied = blue bold underline
65 qseries.unapplied = black bold
65 qseries.unapplied = black bold
66 qseries.missing = red bold
66 qseries.missing = red bold
67
67
68 diff.diffline = bold
68 diff.diffline = bold
69 diff.extended = cyan bold
69 diff.extended = cyan bold
70 diff.file_a = red bold
70 diff.file_a = red bold
71 diff.file_b = green bold
71 diff.file_b = green bold
72 diff.hunk = magenta
72 diff.hunk = magenta
73 diff.deleted = red
73 diff.deleted = red
74 diff.inserted = green
74 diff.inserted = green
75 diff.changed = white
75 diff.changed = white
76 diff.tab =
76 diff.tab =
77 diff.trailingwhitespace = bold red_background
77 diff.trailingwhitespace = bold red_background
78
78
79 # Blank so it inherits the style of the surrounding label
79 # Blank so it inherits the style of the surrounding label
80 changeset.public =
80 changeset.public =
81 changeset.draft =
81 changeset.draft =
82 changeset.secret =
82 changeset.secret =
83
83
84 resolve.unresolved = red bold
84 resolve.unresolved = red bold
85 resolve.resolved = green bold
85 resolve.resolved = green bold
86
86
87 bookmarks.active = green
87 bookmarks.active = green
88
88
89 branches.active = none
89 branches.active = none
90 branches.closed = black bold
90 branches.closed = black bold
91 branches.current = green
91 branches.current = green
92 branches.inactive = none
92 branches.inactive = none
93
93
94 tags.normal = green
94 tags.normal = green
95 tags.local = black bold
95 tags.local = black bold
96
96
97 rebase.rebased = blue
97 rebase.rebased = blue
98 rebase.remaining = red bold
98 rebase.remaining = red bold
99
99
100 shelve.age = cyan
100 shelve.age = cyan
101 shelve.newest = green bold
101 shelve.newest = green bold
102 shelve.name = blue bold
102 shelve.name = blue bold
103
103
104 histedit.remaining = red bold
104 histedit.remaining = red bold
105
105
106 Custom colors
106 Custom colors
107 -------------
107 -------------
108
108
109 Because there are only eight standard colors, this module allows you
109 Because there are only eight standard colors, this module allows you
110 to define color names for other color slots which might be available
110 to define color names for other color slots which might be available
111 for your terminal type, assuming terminfo mode. For instance::
111 for your terminal type, assuming terminfo mode. For instance::
112
112
113 color.brightblue = 12
113 color.brightblue = 12
114 color.pink = 207
114 color.pink = 207
115 color.orange = 202
115 color.orange = 202
116
116
117 to set 'brightblue' to color slot 12 (useful for 16 color terminals
117 to set 'brightblue' to color slot 12 (useful for 16 color terminals
118 that have brighter colors defined in the upper eight) and, 'pink' and
118 that have brighter colors defined in the upper eight) and, 'pink' and
119 'orange' to colors in 256-color xterm's default color cube. These
119 'orange' to colors in 256-color xterm's default color cube. These
120 defined colors may then be used as any of the pre-defined eight,
120 defined colors may then be used as any of the pre-defined eight,
121 including appending '_background' to set the background to that color.
121 including appending '_background' to set the background to that color.
122
122
123 Modes
123 Modes
124 -----
124 -----
125
125
126 By default, the color extension will use ANSI mode (or win32 mode on
126 By default, the color extension will use ANSI mode (or win32 mode on
127 Windows) if it detects a terminal. To override auto mode (to enable
127 Windows) if it detects a terminal. To override auto mode (to enable
128 terminfo mode, for example), set the following configuration option::
128 terminfo mode, for example), set the following configuration option::
129
129
130 [color]
130 [color]
131 mode = terminfo
131 mode = terminfo
132
132
133 Any value other than 'ansi', 'win32', 'terminfo', or 'auto' will
133 Any value other than 'ansi', 'win32', 'terminfo', or 'auto' will
134 disable color.
134 disable color.
135
135
136 Note that on some systems, terminfo mode may cause problems when using
136 Note that on some systems, terminfo mode may cause problems when using
137 color with the pager extension and less -R. less with the -R option
137 color with the pager extension and less -R. less with the -R option
138 will only display ECMA-48 color codes, and terminfo mode may sometimes
138 will only display ECMA-48 color codes, and terminfo mode may sometimes
139 emit codes that less doesn't understand. You can work around this by
139 emit codes that less doesn't understand. You can work around this by
140 either using ansi mode (or auto mode), or by using less -r (which will
140 either using ansi mode (or auto mode), or by using less -r (which will
141 pass through all terminal control codes, not just color control
141 pass through all terminal control codes, not just color control
142 codes).
142 codes).
143
143
144 On some systems (such as MSYS in Windows), the terminal may support
144 On some systems (such as MSYS in Windows), the terminal may support
145 a different color mode than the pager (activated via the "pager"
145 a different color mode than the pager (activated via the "pager"
146 extension). It is possible to define separate modes depending on whether
146 extension). It is possible to define separate modes depending on whether
147 the pager is active::
147 the pager is active::
148
148
149 [color]
149 [color]
150 mode = auto
150 mode = auto
151 pagermode = ansi
151 pagermode = ansi
152
152
153 If ``pagermode`` is not defined, the ``mode`` will be used.
153 If ``pagermode`` is not defined, the ``mode`` will be used.
154 '''
154 '''
155
155
156 import os
156 import os
157
157
158 from mercurial import cmdutil, commands, dispatch, extensions, subrepo, util
158 from mercurial import cmdutil, commands, dispatch, extensions, subrepo, util
159 from mercurial import ui as uimod
159 from mercurial import ui as uimod
160 from mercurial import templater, error
160 from mercurial import templater, error
161 from mercurial.i18n import _
161 from mercurial.i18n import _
162
162
163 cmdtable = {}
163 cmdtable = {}
164 command = cmdutil.command(cmdtable)
164 command = cmdutil.command(cmdtable)
165 # Note for extension authors: ONLY specify testedwith = 'internal' for
165 # Note for extension authors: ONLY specify testedwith = 'internal' for
166 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
166 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
167 # be specifying the version(s) of Mercurial they are tested with, or
167 # be specifying the version(s) of Mercurial they are tested with, or
168 # leave the attribute unspecified.
168 # leave the attribute unspecified.
169 testedwith = 'internal'
169 testedwith = 'internal'
170
170
171 # start and stop parameters for effects
171 # start and stop parameters for effects
172 _effects = {'none': 0, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33,
172 _effects = {'none': 0, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33,
173 'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37, 'bold': 1,
173 'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37, 'bold': 1,
174 'italic': 3, 'underline': 4, 'inverse': 7, 'dim': 2,
174 'italic': 3, 'underline': 4, 'inverse': 7, 'dim': 2,
175 'black_background': 40, 'red_background': 41,
175 'black_background': 40, 'red_background': 41,
176 'green_background': 42, 'yellow_background': 43,
176 'green_background': 42, 'yellow_background': 43,
177 'blue_background': 44, 'purple_background': 45,
177 'blue_background': 44, 'purple_background': 45,
178 'cyan_background': 46, 'white_background': 47}
178 'cyan_background': 46, 'white_background': 47}
179
179
180 def _terminfosetup(ui, mode):
180 def _terminfosetup(ui, mode):
181 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
181 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
182
182
183 global _terminfo_params
183 global _terminfo_params
184 # If we failed to load curses, we go ahead and return.
184 # If we failed to load curses, we go ahead and return.
185 if not _terminfo_params:
185 if not _terminfo_params:
186 return
186 return
187 # Otherwise, see what the config file says.
187 # Otherwise, see what the config file says.
188 if mode not in ('auto', 'terminfo'):
188 if mode not in ('auto', 'terminfo'):
189 return
189 return
190
190
191 _terminfo_params.update((key[6:], (False, int(val)))
191 _terminfo_params.update((key[6:], (False, int(val)))
192 for key, val in ui.configitems('color')
192 for key, val in ui.configitems('color')
193 if key.startswith('color.'))
193 if key.startswith('color.'))
194
194
195 try:
195 try:
196 curses.setupterm()
196 curses.setupterm()
197 except curses.error, e:
197 except curses.error, e:
198 _terminfo_params = {}
198 _terminfo_params = {}
199 return
199 return
200
200
201 for key, (b, e) in _terminfo_params.items():
201 for key, (b, e) in _terminfo_params.items():
202 if not b:
202 if not b:
203 continue
203 continue
204 if not curses.tigetstr(e):
204 if not curses.tigetstr(e):
205 # Most terminals don't support dim, invis, etc, so don't be
205 # Most terminals don't support dim, invis, etc, so don't be
206 # noisy and use ui.debug().
206 # noisy and use ui.debug().
207 ui.debug("no terminfo entry for %s\n" % e)
207 ui.debug("no terminfo entry for %s\n" % e)
208 del _terminfo_params[key]
208 del _terminfo_params[key]
209 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
209 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
210 # Only warn about missing terminfo entries if we explicitly asked for
210 # Only warn about missing terminfo entries if we explicitly asked for
211 # terminfo mode.
211 # terminfo mode.
212 if mode == "terminfo":
212 if mode == "terminfo":
213 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
213 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
214 "ECMA-48 color\n"))
214 "ECMA-48 color\n"))
215 _terminfo_params = {}
215 _terminfo_params = {}
216
216
217 def _modesetup(ui, coloropt):
217 def _modesetup(ui, coloropt):
218 global _terminfo_params
218 global _terminfo_params
219
219
220 if coloropt == 'debug':
220 if coloropt == 'debug':
221 return 'debug'
221 return 'debug'
222
222
223 auto = (coloropt == 'auto')
223 auto = (coloropt == 'auto')
224 always = not auto and util.parsebool(coloropt)
224 always = not auto and util.parsebool(coloropt)
225 if not always and not auto:
225 if not always and not auto:
226 return None
226 return None
227
227
228 formatted = always or (os.environ.get('TERM') != 'dumb' and ui.formatted())
228 formatted = always or (os.environ.get('TERM') != 'dumb' and ui.formatted())
229
229
230 mode = ui.config('color', 'mode', 'auto')
230 mode = ui.config('color', 'mode', 'auto')
231
231
232 # If pager is active, color.pagermode overrides color.mode.
232 # If pager is active, color.pagermode overrides color.mode.
233 if getattr(ui, 'pageractive', False):
233 if getattr(ui, 'pageractive', False):
234 mode = ui.config('color', 'pagermode', mode)
234 mode = ui.config('color', 'pagermode', mode)
235
235
236 realmode = mode
236 realmode = mode
237 if mode == 'auto':
237 if mode == 'auto':
238 if os.name == 'nt':
238 if os.name == 'nt':
239 term = os.environ.get('TERM')
239 term = os.environ.get('TERM')
240 # TERM won't be defined in a vanilla cmd.exe environment.
240 # TERM won't be defined in a vanilla cmd.exe environment.
241
241
242 # UNIX-like environments on Windows such as Cygwin and MSYS will
242 # UNIX-like environments on Windows such as Cygwin and MSYS will
243 # set TERM. They appear to make a best effort attempt at setting it
243 # set TERM. They appear to make a best effort attempt at setting it
244 # to something appropriate. However, not all environments with TERM
244 # to something appropriate. However, not all environments with TERM
245 # defined support ANSI. Since "ansi" could result in terminal
245 # defined support ANSI. Since "ansi" could result in terminal
246 # gibberish, we error on the side of selecting "win32". However, if
246 # gibberish, we error on the side of selecting "win32". However, if
247 # w32effects is not defined, we almost certainly don't support
247 # w32effects is not defined, we almost certainly don't support
248 # "win32", so don't even try.
248 # "win32", so don't even try.
249 if (term and 'xterm' in term) or not w32effects:
249 if (term and 'xterm' in term) or not w32effects:
250 realmode = 'ansi'
250 realmode = 'ansi'
251 else:
251 else:
252 realmode = 'win32'
252 realmode = 'win32'
253 else:
253 else:
254 realmode = 'ansi'
254 realmode = 'ansi'
255
255
256 def modewarn():
256 def modewarn():
257 # only warn if color.mode was explicitly set and we're in
257 # only warn if color.mode was explicitly set and we're in
258 # an interactive terminal
258 # an interactive terminal
259 if mode == realmode and ui.interactive():
259 if mode == realmode and ui.interactive():
260 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
260 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
261
261
262 if realmode == 'win32':
262 if realmode == 'win32':
263 _terminfo_params = {}
263 _terminfo_params = {}
264 if not w32effects:
264 if not w32effects:
265 modewarn()
265 modewarn()
266 return None
266 return None
267 _effects.update(w32effects)
267 _effects.update(w32effects)
268 elif realmode == 'ansi':
268 elif realmode == 'ansi':
269 _terminfo_params = {}
269 _terminfo_params = {}
270 elif realmode == 'terminfo':
270 elif realmode == 'terminfo':
271 _terminfosetup(ui, mode)
271 _terminfosetup(ui, mode)
272 if not _terminfo_params:
272 if not _terminfo_params:
273 ## FIXME Shouldn't we return None in this case too?
273 ## FIXME Shouldn't we return None in this case too?
274 modewarn()
274 modewarn()
275 realmode = 'ansi'
275 realmode = 'ansi'
276 else:
276 else:
277 return None
277 return None
278
278
279 if always or (auto and formatted):
279 if always or (auto and formatted):
280 return realmode
280 return realmode
281 return None
281 return None
282
282
283 try:
283 try:
284 import curses
284 import curses
285 # Mapping from effect name to terminfo attribute name or color number.
285 # Mapping from effect name to terminfo attribute name or color number.
286 # This will also force-load the curses module.
286 # This will also force-load the curses module.
287 _terminfo_params = {'none': (True, 'sgr0'),
287 _terminfo_params = {'none': (True, 'sgr0'),
288 'standout': (True, 'smso'),
288 'standout': (True, 'smso'),
289 'underline': (True, 'smul'),
289 'underline': (True, 'smul'),
290 'reverse': (True, 'rev'),
290 'reverse': (True, 'rev'),
291 'inverse': (True, 'rev'),
291 'inverse': (True, 'rev'),
292 'blink': (True, 'blink'),
292 'blink': (True, 'blink'),
293 'dim': (True, 'dim'),
293 'dim': (True, 'dim'),
294 'bold': (True, 'bold'),
294 'bold': (True, 'bold'),
295 'invisible': (True, 'invis'),
295 'invisible': (True, 'invis'),
296 'italic': (True, 'sitm'),
296 'italic': (True, 'sitm'),
297 'black': (False, curses.COLOR_BLACK),
297 'black': (False, curses.COLOR_BLACK),
298 'red': (False, curses.COLOR_RED),
298 'red': (False, curses.COLOR_RED),
299 'green': (False, curses.COLOR_GREEN),
299 'green': (False, curses.COLOR_GREEN),
300 'yellow': (False, curses.COLOR_YELLOW),
300 'yellow': (False, curses.COLOR_YELLOW),
301 'blue': (False, curses.COLOR_BLUE),
301 'blue': (False, curses.COLOR_BLUE),
302 'magenta': (False, curses.COLOR_MAGENTA),
302 'magenta': (False, curses.COLOR_MAGENTA),
303 'cyan': (False, curses.COLOR_CYAN),
303 'cyan': (False, curses.COLOR_CYAN),
304 'white': (False, curses.COLOR_WHITE)}
304 'white': (False, curses.COLOR_WHITE)}
305 except ImportError:
305 except ImportError:
306 _terminfo_params = {}
306 _terminfo_params = {}
307
307
308 _styles = {'grep.match': 'red bold',
308 _styles = {'grep.match': 'red bold',
309 'grep.linenumber': 'green',
309 'grep.linenumber': 'green',
310 'grep.rev': 'green',
310 'grep.rev': 'green',
311 'grep.change': 'green',
311 'grep.change': 'green',
312 'grep.sep': 'cyan',
312 'grep.sep': 'cyan',
313 'grep.filename': 'magenta',
313 'grep.filename': 'magenta',
314 'grep.user': 'magenta',
314 'grep.user': 'magenta',
315 'grep.date': 'magenta',
315 'grep.date': 'magenta',
316 'bookmarks.active': 'green',
316 'bookmarks.active': 'green',
317 'branches.active': 'none',
317 'branches.active': 'none',
318 'branches.closed': 'black bold',
318 'branches.closed': 'black bold',
319 'branches.current': 'green',
319 'branches.current': 'green',
320 'branches.inactive': 'none',
320 'branches.inactive': 'none',
321 'diff.changed': 'white',
321 'diff.changed': 'white',
322 'diff.deleted': 'red',
322 'diff.deleted': 'red',
323 'diff.diffline': 'bold',
323 'diff.diffline': 'bold',
324 'diff.extended': 'cyan bold',
324 'diff.extended': 'cyan bold',
325 'diff.file_a': 'red bold',
325 'diff.file_a': 'red bold',
326 'diff.file_b': 'green bold',
326 'diff.file_b': 'green bold',
327 'diff.hunk': 'magenta',
327 'diff.hunk': 'magenta',
328 'diff.inserted': 'green',
328 'diff.inserted': 'green',
329 'diff.tab': '',
329 'diff.tab': '',
330 'diff.trailingwhitespace': 'bold red_background',
330 'diff.trailingwhitespace': 'bold red_background',
331 'changeset.public' : '',
331 'changeset.public' : '',
332 'changeset.draft' : '',
332 'changeset.draft' : '',
333 'changeset.secret' : '',
333 'changeset.secret' : '',
334 'diffstat.deleted': 'red',
334 'diffstat.deleted': 'red',
335 'diffstat.inserted': 'green',
335 'diffstat.inserted': 'green',
336 'histedit.remaining': 'red bold',
336 'histedit.remaining': 'red bold',
337 'ui.prompt': 'yellow',
337 'ui.prompt': 'yellow',
338 'log.changeset': 'yellow',
338 'log.changeset': 'yellow',
339 'patchbomb.finalsummary': '',
339 'patchbomb.finalsummary': '',
340 'patchbomb.from': 'magenta',
340 'patchbomb.from': 'magenta',
341 'patchbomb.to': 'cyan',
341 'patchbomb.to': 'cyan',
342 'patchbomb.subject': 'green',
342 'patchbomb.subject': 'green',
343 'patchbomb.diffstats': '',
343 'patchbomb.diffstats': '',
344 'rebase.rebased': 'blue',
344 'rebase.rebased': 'blue',
345 'rebase.remaining': 'red bold',
345 'rebase.remaining': 'red bold',
346 'resolve.resolved': 'green bold',
346 'resolve.resolved': 'green bold',
347 'resolve.unresolved': 'red bold',
347 'resolve.unresolved': 'red bold',
348 'shelve.age': 'cyan',
348 'shelve.age': 'cyan',
349 'shelve.newest': 'green bold',
349 'shelve.newest': 'green bold',
350 'shelve.name': 'blue bold',
350 'shelve.name': 'blue bold',
351 'status.added': 'green bold',
351 'status.added': 'green bold',
352 'status.clean': 'none',
352 'status.clean': 'none',
353 'status.copied': 'none',
353 'status.copied': 'none',
354 'status.deleted': 'cyan bold underline',
354 'status.deleted': 'cyan bold underline',
355 'status.ignored': 'black bold',
355 'status.ignored': 'black bold',
356 'status.modified': 'blue bold',
356 'status.modified': 'blue bold',
357 'status.removed': 'red bold',
357 'status.removed': 'red bold',
358 'status.unknown': 'magenta bold underline',
358 'status.unknown': 'magenta bold underline',
359 'tags.normal': 'green',
359 'tags.normal': 'green',
360 'tags.local': 'black bold'}
360 'tags.local': 'black bold'}
361
361
362
362
363 def _effect_str(effect):
363 def _effect_str(effect):
364 '''Helper function for render_effects().'''
364 '''Helper function for render_effects().'''
365
365
366 bg = False
366 bg = False
367 if effect.endswith('_background'):
367 if effect.endswith('_background'):
368 bg = True
368 bg = True
369 effect = effect[:-11]
369 effect = effect[:-11]
370 attr, val = _terminfo_params[effect]
370 attr, val = _terminfo_params[effect]
371 if attr:
371 if attr:
372 return curses.tigetstr(val)
372 return curses.tigetstr(val)
373 elif bg:
373 elif bg:
374 return curses.tparm(curses.tigetstr('setab'), val)
374 return curses.tparm(curses.tigetstr('setab'), val)
375 else:
375 else:
376 return curses.tparm(curses.tigetstr('setaf'), val)
376 return curses.tparm(curses.tigetstr('setaf'), val)
377
377
378 def render_effects(text, effects):
378 def render_effects(text, effects):
379 'Wrap text in commands to turn on each effect.'
379 'Wrap text in commands to turn on each effect.'
380 if not text:
380 if not text:
381 return text
381 return text
382 if not _terminfo_params:
382 if not _terminfo_params:
383 start = [str(_effects[e]) for e in ['none'] + effects.split()]
383 start = [str(_effects[e]) for e in ['none'] + effects.split()]
384 start = '\033[' + ';'.join(start) + 'm'
384 start = '\033[' + ';'.join(start) + 'm'
385 stop = '\033[' + str(_effects['none']) + 'm'
385 stop = '\033[' + str(_effects['none']) + 'm'
386 else:
386 else:
387 start = ''.join(_effect_str(effect)
387 start = ''.join(_effect_str(effect)
388 for effect in ['none'] + effects.split())
388 for effect in ['none'] + effects.split())
389 stop = _effect_str('none')
389 stop = _effect_str('none')
390 return ''.join([start, text, stop])
390 return ''.join([start, text, stop])
391
391
392 def extstyles():
392 def extstyles():
393 for name, ext in extensions.extensions():
393 for name, ext in extensions.extensions():
394 _styles.update(getattr(ext, 'colortable', {}))
394 _styles.update(getattr(ext, 'colortable', {}))
395
395
396 def valideffect(effect):
396 def valideffect(effect):
397 'Determine if the effect is valid or not.'
397 'Determine if the effect is valid or not.'
398 good = False
398 good = False
399 if not _terminfo_params and effect in _effects:
399 if not _terminfo_params and effect in _effects:
400 good = True
400 good = True
401 elif effect in _terminfo_params or effect[:-11] in _terminfo_params:
401 elif effect in _terminfo_params or effect[:-11] in _terminfo_params:
402 good = True
402 good = True
403 return good
403 return good
404
404
405 def configstyles(ui):
405 def configstyles(ui):
406 for status, cfgeffects in ui.configitems('color'):
406 for status, cfgeffects in ui.configitems('color'):
407 if '.' not in status or status.startswith('color.'):
407 if '.' not in status or status.startswith('color.'):
408 continue
408 continue
409 cfgeffects = ui.configlist('color', status)
409 cfgeffects = ui.configlist('color', status)
410 if cfgeffects:
410 if cfgeffects:
411 good = []
411 good = []
412 for e in cfgeffects:
412 for e in cfgeffects:
413 if valideffect(e):
413 if valideffect(e):
414 good.append(e)
414 good.append(e)
415 else:
415 else:
416 ui.warn(_("ignoring unknown color/effect %r "
416 ui.warn(_("ignoring unknown color/effect %r "
417 "(configured in color.%s)\n")
417 "(configured in color.%s)\n")
418 % (e, status))
418 % (e, status))
419 _styles[status] = ' '.join(good)
419 _styles[status] = ' '.join(good)
420
420
421 class colorui(uimod.ui):
421 class colorui(uimod.ui):
422 def popbuffer(self, labeled=False):
422 def popbuffer(self, labeled=False):
423 if self._colormode is None:
423 if self._colormode is None:
424 return super(colorui, self).popbuffer(labeled)
424 return super(colorui, self).popbuffer(labeled)
425
425
426 self._bufferstates.pop()
426 self._bufferstates.pop()
427 if labeled:
427 if labeled:
428 return ''.join(self.label(a, label) for a, label
428 return ''.join(self.label(a, label) for a, label
429 in self._buffers.pop())
429 in self._buffers.pop())
430 return ''.join(a for a, label in self._buffers.pop())
430 return ''.join(a for a, label in self._buffers.pop())
431
431
432 _colormode = 'ansi'
432 _colormode = 'ansi'
433 def write(self, *args, **opts):
433 def write(self, *args, **opts):
434 if self._colormode is None:
434 if self._colormode is None:
435 return super(colorui, self).write(*args, **opts)
435 return super(colorui, self).write(*args, **opts)
436
436
437 label = opts.get('label', '')
437 label = opts.get('label', '')
438 if self._buffers:
438 if self._buffers:
439 self._buffers[-1].extend([(str(a), label) for a in args])
439 self._buffers[-1].extend([(str(a), label) for a in args])
440 elif self._colormode == 'win32':
440 elif self._colormode == 'win32':
441 for a in args:
441 for a in args:
442 win32print(a, super(colorui, self).write, **opts)
442 win32print(a, super(colorui, self).write, **opts)
443 else:
443 else:
444 return super(colorui, self).write(
444 return super(colorui, self).write(
445 *[self.label(str(a), label) for a in args], **opts)
445 *[self.label(str(a), label) for a in args], **opts)
446
446
447 def write_err(self, *args, **opts):
447 def write_err(self, *args, **opts):
448 if self._colormode is None:
448 if self._colormode is None:
449 return super(colorui, self).write_err(*args, **opts)
449 return super(colorui, self).write_err(*args, **opts)
450
450
451 label = opts.get('label', '')
451 label = opts.get('label', '')
452 if self._bufferstates and self._bufferstates[-1][0]:
452 if self._bufferstates and self._bufferstates[-1][0]:
453 return self.write(*args, **opts)
453 return self.write(*args, **opts)
454 if self._colormode == 'win32':
454 if self._colormode == 'win32':
455 for a in args:
455 for a in args:
456 win32print(a, super(colorui, self).write_err, **opts)
456 win32print(a, super(colorui, self).write_err, **opts)
457 else:
457 else:
458 return super(colorui, self).write_err(
458 return super(colorui, self).write_err(
459 *[self.label(str(a), label) for a in args], **opts)
459 *[self.label(str(a), label) for a in args], **opts)
460
460
461 def showlabel(self, msg, label):
461 def showlabel(self, msg, label):
462 if label and msg:
462 if label and msg:
463 if msg[-1] == '\n':
463 if msg[-1] == '\n':
464 return "[%s|%s]\n" % (label, msg[:-1])
464 return "[%s|%s]\n" % (label, msg[:-1])
465 else:
465 else:
466 return "[%s|%s]" % (label, msg)
466 return "[%s|%s]" % (label, msg)
467 else:
467 else:
468 return msg
468 return msg
469
469
470 def label(self, msg, label):
470 def label(self, msg, label):
471 if self._colormode is None:
471 if self._colormode is None:
472 return super(colorui, self).label(msg, label)
472 return super(colorui, self).label(msg, label)
473
473
474 if self._colormode == 'debug':
474 if self._colormode == 'debug':
475 return self.showlabel(msg, label)
475 return self.showlabel(msg, label)
476
476
477 effects = []
477 effects = []
478 for l in label.split():
478 for l in label.split():
479 s = _styles.get(l, '')
479 s = _styles.get(l, '')
480 if s:
480 if s:
481 effects.append(s)
481 effects.append(s)
482 elif valideffect(l):
482 elif valideffect(l):
483 effects.append(l)
483 effects.append(l)
484 effects = ' '.join(effects)
484 effects = ' '.join(effects)
485 if effects:
485 if effects:
486 return '\n'.join([render_effects(s, effects)
486 return '\n'.join([render_effects(s, effects)
487 for s in msg.split('\n')])
487 for s in msg.split('\n')])
488 return msg
488 return msg
489
489
490 def templatelabel(context, mapping, args):
490 def templatelabel(context, mapping, args):
491 if len(args) != 2:
491 if len(args) != 2:
492 # i18n: "label" is a keyword
492 # i18n: "label" is a keyword
493 raise error.ParseError(_("label expects two arguments"))
493 raise error.ParseError(_("label expects two arguments"))
494
494
495 # add known effects to the mapping so symbols like 'red', 'bold',
495 # add known effects to the mapping so symbols like 'red', 'bold',
496 # etc. don't need to be quoted
496 # etc. don't need to be quoted
497 mapping.update(dict([(k, k) for k in _effects]))
497 mapping.update(dict([(k, k) for k in _effects]))
498
498
499 thing = templater._evalifliteral(args[1], context, mapping)
499 thing = args[1][0](context, mapping, args[1][1])
500
500
501 # apparently, repo could be a string that is the favicon?
501 # apparently, repo could be a string that is the favicon?
502 repo = mapping.get('repo', '')
502 repo = mapping.get('repo', '')
503 if isinstance(repo, str):
503 if isinstance(repo, str):
504 return thing
504 return thing
505
505
506 label = templater._evalifliteral(args[0], context, mapping)
506 label = args[0][0](context, mapping, args[0][1])
507
507
508 thing = templater.stringify(thing)
508 thing = templater.stringify(thing)
509 label = templater.stringify(label)
509 label = templater.stringify(label)
510
510
511 return repo.ui.label(thing, label)
511 return repo.ui.label(thing, label)
512
512
513 def uisetup(ui):
513 def uisetup(ui):
514 if ui.plain():
514 if ui.plain():
515 return
515 return
516 if not isinstance(ui, colorui):
516 if not isinstance(ui, colorui):
517 colorui.__bases__ = (ui.__class__,)
517 colorui.__bases__ = (ui.__class__,)
518 ui.__class__ = colorui
518 ui.__class__ = colorui
519 def colorcmd(orig, ui_, opts, cmd, cmdfunc):
519 def colorcmd(orig, ui_, opts, cmd, cmdfunc):
520 mode = _modesetup(ui_, opts['color'])
520 mode = _modesetup(ui_, opts['color'])
521 colorui._colormode = mode
521 colorui._colormode = mode
522 if mode and mode != 'debug':
522 if mode and mode != 'debug':
523 extstyles()
523 extstyles()
524 configstyles(ui_)
524 configstyles(ui_)
525 return orig(ui_, opts, cmd, cmdfunc)
525 return orig(ui_, opts, cmd, cmdfunc)
526 def colorgit(orig, gitsub, commands, env=None, stream=False, cwd=None):
526 def colorgit(orig, gitsub, commands, env=None, stream=False, cwd=None):
527 if gitsub.ui._colormode and len(commands) and commands[0] == "diff":
527 if gitsub.ui._colormode and len(commands) and commands[0] == "diff":
528 # insert the argument in the front,
528 # insert the argument in the front,
529 # the end of git diff arguments is used for paths
529 # the end of git diff arguments is used for paths
530 commands.insert(1, '--color')
530 commands.insert(1, '--color')
531 return orig(gitsub, commands, env, stream, cwd)
531 return orig(gitsub, commands, env, stream, cwd)
532 extensions.wrapfunction(dispatch, '_runcommand', colorcmd)
532 extensions.wrapfunction(dispatch, '_runcommand', colorcmd)
533 extensions.wrapfunction(subrepo.gitsubrepo, '_gitnodir', colorgit)
533 extensions.wrapfunction(subrepo.gitsubrepo, '_gitnodir', colorgit)
534 templatelabel.__doc__ = templater.funcs['label'].__doc__
534 templatelabel.__doc__ = templater.funcs['label'].__doc__
535 templater.funcs['label'] = templatelabel
535 templater.funcs['label'] = templatelabel
536
536
537 def extsetup(ui):
537 def extsetup(ui):
538 commands.globalopts.append(
538 commands.globalopts.append(
539 ('', 'color', 'auto',
539 ('', 'color', 'auto',
540 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
540 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
541 # and should not be translated
541 # and should not be translated
542 _("when to colorize (boolean, always, auto, never, or debug)"),
542 _("when to colorize (boolean, always, auto, never, or debug)"),
543 _('TYPE')))
543 _('TYPE')))
544
544
545 @command('debugcolor', [], 'hg debugcolor')
545 @command('debugcolor', [], 'hg debugcolor')
546 def debugcolor(ui, repo, **opts):
546 def debugcolor(ui, repo, **opts):
547 global _styles
547 global _styles
548 _styles = {}
548 _styles = {}
549 for effect in _effects.keys():
549 for effect in _effects.keys():
550 _styles[effect] = effect
550 _styles[effect] = effect
551 ui.write(('color mode: %s\n') % ui._colormode)
551 ui.write(('color mode: %s\n') % ui._colormode)
552 ui.write(_('available colors:\n'))
552 ui.write(_('available colors:\n'))
553 for label, colors in _styles.items():
553 for label, colors in _styles.items():
554 ui.write(('%s\n') % colors, label=label)
554 ui.write(('%s\n') % colors, label=label)
555
555
556 if os.name != 'nt':
556 if os.name != 'nt':
557 w32effects = None
557 w32effects = None
558 else:
558 else:
559 import re, ctypes
559 import re, ctypes
560
560
561 _kernel32 = ctypes.windll.kernel32
561 _kernel32 = ctypes.windll.kernel32
562
562
563 _WORD = ctypes.c_ushort
563 _WORD = ctypes.c_ushort
564
564
565 _INVALID_HANDLE_VALUE = -1
565 _INVALID_HANDLE_VALUE = -1
566
566
567 class _COORD(ctypes.Structure):
567 class _COORD(ctypes.Structure):
568 _fields_ = [('X', ctypes.c_short),
568 _fields_ = [('X', ctypes.c_short),
569 ('Y', ctypes.c_short)]
569 ('Y', ctypes.c_short)]
570
570
571 class _SMALL_RECT(ctypes.Structure):
571 class _SMALL_RECT(ctypes.Structure):
572 _fields_ = [('Left', ctypes.c_short),
572 _fields_ = [('Left', ctypes.c_short),
573 ('Top', ctypes.c_short),
573 ('Top', ctypes.c_short),
574 ('Right', ctypes.c_short),
574 ('Right', ctypes.c_short),
575 ('Bottom', ctypes.c_short)]
575 ('Bottom', ctypes.c_short)]
576
576
577 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
577 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
578 _fields_ = [('dwSize', _COORD),
578 _fields_ = [('dwSize', _COORD),
579 ('dwCursorPosition', _COORD),
579 ('dwCursorPosition', _COORD),
580 ('wAttributes', _WORD),
580 ('wAttributes', _WORD),
581 ('srWindow', _SMALL_RECT),
581 ('srWindow', _SMALL_RECT),
582 ('dwMaximumWindowSize', _COORD)]
582 ('dwMaximumWindowSize', _COORD)]
583
583
584 _STD_OUTPUT_HANDLE = 0xfffffff5L # (DWORD)-11
584 _STD_OUTPUT_HANDLE = 0xfffffff5L # (DWORD)-11
585 _STD_ERROR_HANDLE = 0xfffffff4L # (DWORD)-12
585 _STD_ERROR_HANDLE = 0xfffffff4L # (DWORD)-12
586
586
587 _FOREGROUND_BLUE = 0x0001
587 _FOREGROUND_BLUE = 0x0001
588 _FOREGROUND_GREEN = 0x0002
588 _FOREGROUND_GREEN = 0x0002
589 _FOREGROUND_RED = 0x0004
589 _FOREGROUND_RED = 0x0004
590 _FOREGROUND_INTENSITY = 0x0008
590 _FOREGROUND_INTENSITY = 0x0008
591
591
592 _BACKGROUND_BLUE = 0x0010
592 _BACKGROUND_BLUE = 0x0010
593 _BACKGROUND_GREEN = 0x0020
593 _BACKGROUND_GREEN = 0x0020
594 _BACKGROUND_RED = 0x0040
594 _BACKGROUND_RED = 0x0040
595 _BACKGROUND_INTENSITY = 0x0080
595 _BACKGROUND_INTENSITY = 0x0080
596
596
597 _COMMON_LVB_REVERSE_VIDEO = 0x4000
597 _COMMON_LVB_REVERSE_VIDEO = 0x4000
598 _COMMON_LVB_UNDERSCORE = 0x8000
598 _COMMON_LVB_UNDERSCORE = 0x8000
599
599
600 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
600 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
601 w32effects = {
601 w32effects = {
602 'none': -1,
602 'none': -1,
603 'black': 0,
603 'black': 0,
604 'red': _FOREGROUND_RED,
604 'red': _FOREGROUND_RED,
605 'green': _FOREGROUND_GREEN,
605 'green': _FOREGROUND_GREEN,
606 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
606 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
607 'blue': _FOREGROUND_BLUE,
607 'blue': _FOREGROUND_BLUE,
608 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
608 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
609 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
609 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
610 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
610 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
611 'bold': _FOREGROUND_INTENSITY,
611 'bold': _FOREGROUND_INTENSITY,
612 'black_background': 0x100, # unused value > 0x0f
612 'black_background': 0x100, # unused value > 0x0f
613 'red_background': _BACKGROUND_RED,
613 'red_background': _BACKGROUND_RED,
614 'green_background': _BACKGROUND_GREEN,
614 'green_background': _BACKGROUND_GREEN,
615 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
615 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
616 'blue_background': _BACKGROUND_BLUE,
616 'blue_background': _BACKGROUND_BLUE,
617 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
617 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
618 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
618 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
619 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
619 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
620 _BACKGROUND_BLUE),
620 _BACKGROUND_BLUE),
621 'bold_background': _BACKGROUND_INTENSITY,
621 'bold_background': _BACKGROUND_INTENSITY,
622 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
622 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
623 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
623 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
624 }
624 }
625
625
626 passthrough = set([_FOREGROUND_INTENSITY,
626 passthrough = set([_FOREGROUND_INTENSITY,
627 _BACKGROUND_INTENSITY,
627 _BACKGROUND_INTENSITY,
628 _COMMON_LVB_UNDERSCORE,
628 _COMMON_LVB_UNDERSCORE,
629 _COMMON_LVB_REVERSE_VIDEO])
629 _COMMON_LVB_REVERSE_VIDEO])
630
630
631 stdout = _kernel32.GetStdHandle(
631 stdout = _kernel32.GetStdHandle(
632 _STD_OUTPUT_HANDLE) # don't close the handle returned
632 _STD_OUTPUT_HANDLE) # don't close the handle returned
633 if stdout is None or stdout == _INVALID_HANDLE_VALUE:
633 if stdout is None or stdout == _INVALID_HANDLE_VALUE:
634 w32effects = None
634 w32effects = None
635 else:
635 else:
636 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
636 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
637 if not _kernel32.GetConsoleScreenBufferInfo(
637 if not _kernel32.GetConsoleScreenBufferInfo(
638 stdout, ctypes.byref(csbi)):
638 stdout, ctypes.byref(csbi)):
639 # stdout may not support GetConsoleScreenBufferInfo()
639 # stdout may not support GetConsoleScreenBufferInfo()
640 # when called from subprocess or redirected
640 # when called from subprocess or redirected
641 w32effects = None
641 w32effects = None
642 else:
642 else:
643 origattr = csbi.wAttributes
643 origattr = csbi.wAttributes
644 ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)',
644 ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)',
645 re.MULTILINE | re.DOTALL)
645 re.MULTILINE | re.DOTALL)
646
646
647 def win32print(text, orig, **opts):
647 def win32print(text, orig, **opts):
648 label = opts.get('label', '')
648 label = opts.get('label', '')
649 attr = origattr
649 attr = origattr
650
650
651 def mapcolor(val, attr):
651 def mapcolor(val, attr):
652 if val == -1:
652 if val == -1:
653 return origattr
653 return origattr
654 elif val in passthrough:
654 elif val in passthrough:
655 return attr | val
655 return attr | val
656 elif val > 0x0f:
656 elif val > 0x0f:
657 return (val & 0x70) | (attr & 0x8f)
657 return (val & 0x70) | (attr & 0x8f)
658 else:
658 else:
659 return (val & 0x07) | (attr & 0xf8)
659 return (val & 0x07) | (attr & 0xf8)
660
660
661 # determine console attributes based on labels
661 # determine console attributes based on labels
662 for l in label.split():
662 for l in label.split():
663 style = _styles.get(l, '')
663 style = _styles.get(l, '')
664 for effect in style.split():
664 for effect in style.split():
665 try:
665 try:
666 attr = mapcolor(w32effects[effect], attr)
666 attr = mapcolor(w32effects[effect], attr)
667 except KeyError:
667 except KeyError:
668 # w32effects could not have certain attributes so we skip
668 # w32effects could not have certain attributes so we skip
669 # them if not found
669 # them if not found
670 pass
670 pass
671 # hack to ensure regexp finds data
671 # hack to ensure regexp finds data
672 if not text.startswith('\033['):
672 if not text.startswith('\033['):
673 text = '\033[m' + text
673 text = '\033[m' + text
674
674
675 # Look for ANSI-like codes embedded in text
675 # Look for ANSI-like codes embedded in text
676 m = re.match(ansire, text)
676 m = re.match(ansire, text)
677
677
678 try:
678 try:
679 while m:
679 while m:
680 for sattr in m.group(1).split(';'):
680 for sattr in m.group(1).split(';'):
681 if sattr:
681 if sattr:
682 attr = mapcolor(int(sattr), attr)
682 attr = mapcolor(int(sattr), attr)
683 _kernel32.SetConsoleTextAttribute(stdout, attr)
683 _kernel32.SetConsoleTextAttribute(stdout, attr)
684 orig(m.group(2), **opts)
684 orig(m.group(2), **opts)
685 m = re.match(ansire, m.group(3))
685 m = re.match(ansire, m.group(3))
686 finally:
686 finally:
687 # Explicitly reset original attributes
687 # Explicitly reset original attributes
688 _kernel32.SetConsoleTextAttribute(stdout, origattr)
688 _kernel32.SetConsoleTextAttribute(stdout, origattr)
@@ -1,872 +1,861
1 # templater.py - template expansion for output
1 # templater.py - template expansion for output
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 i18n import _
8 from i18n import _
9 import os, re
9 import os, re
10 import util, config, templatefilters, templatekw, parser, error
10 import util, config, templatefilters, templatekw, parser, error
11 import revset as revsetmod
11 import revset as revsetmod
12 import types
12 import types
13 import minirst
13 import minirst
14
14
15 # template parsing
15 # template parsing
16
16
17 elements = {
17 elements = {
18 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
18 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
19 ",": (2, None, ("list", 2)),
19 ",": (2, None, ("list", 2)),
20 "|": (5, None, ("|", 5)),
20 "|": (5, None, ("|", 5)),
21 "%": (6, None, ("%", 6)),
21 "%": (6, None, ("%", 6)),
22 ")": (0, None, None),
22 ")": (0, None, None),
23 "integer": (0, ("integer",), None),
23 "integer": (0, ("integer",), None),
24 "symbol": (0, ("symbol",), None),
24 "symbol": (0, ("symbol",), None),
25 "string": (0, ("template",), None),
25 "string": (0, ("template",), None),
26 "rawstring": (0, ("rawstring",), None),
26 "rawstring": (0, ("rawstring",), None),
27 "end": (0, None, None),
27 "end": (0, None, None),
28 }
28 }
29
29
30 def tokenizer(data):
30 def tokenizer(data):
31 program, start, end = data
31 program, start, end = data
32 pos = start
32 pos = start
33 while pos < end:
33 while pos < end:
34 c = program[pos]
34 c = program[pos]
35 if c.isspace(): # skip inter-token whitespace
35 if c.isspace(): # skip inter-token whitespace
36 pass
36 pass
37 elif c in "(,)%|": # handle simple operators
37 elif c in "(,)%|": # handle simple operators
38 yield (c, None, pos)
38 yield (c, None, pos)
39 elif (c in '"\'' or c == 'r' and
39 elif (c in '"\'' or c == 'r' and
40 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
40 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
41 if c == 'r':
41 if c == 'r':
42 pos += 1
42 pos += 1
43 c = program[pos]
43 c = program[pos]
44 decode = False
44 decode = False
45 else:
45 else:
46 decode = True
46 decode = True
47 pos += 1
47 pos += 1
48 s = pos
48 s = pos
49 while pos < end: # find closing quote
49 while pos < end: # find closing quote
50 d = program[pos]
50 d = program[pos]
51 if decode and d == '\\': # skip over escaped characters
51 if decode and d == '\\': # skip over escaped characters
52 pos += 2
52 pos += 2
53 continue
53 continue
54 if d == c:
54 if d == c:
55 if not decode:
55 if not decode:
56 yield ('rawstring', program[s:pos], s)
56 yield ('rawstring', program[s:pos], s)
57 break
57 break
58 yield ('string', program[s:pos], s)
58 yield ('string', program[s:pos], s)
59 break
59 break
60 pos += 1
60 pos += 1
61 else:
61 else:
62 raise error.ParseError(_("unterminated string"), s)
62 raise error.ParseError(_("unterminated string"), s)
63 elif c.isdigit() or c == '-':
63 elif c.isdigit() or c == '-':
64 s = pos
64 s = pos
65 if c == '-': # simply take negate operator as part of integer
65 if c == '-': # simply take negate operator as part of integer
66 pos += 1
66 pos += 1
67 if pos >= end or not program[pos].isdigit():
67 if pos >= end or not program[pos].isdigit():
68 raise error.ParseError(_("integer literal without digits"), s)
68 raise error.ParseError(_("integer literal without digits"), s)
69 pos += 1
69 pos += 1
70 while pos < end:
70 while pos < end:
71 d = program[pos]
71 d = program[pos]
72 if not d.isdigit():
72 if not d.isdigit():
73 break
73 break
74 pos += 1
74 pos += 1
75 yield ('integer', program[s:pos], s)
75 yield ('integer', program[s:pos], s)
76 pos -= 1
76 pos -= 1
77 elif c.isalnum() or c in '_':
77 elif c.isalnum() or c in '_':
78 s = pos
78 s = pos
79 pos += 1
79 pos += 1
80 while pos < end: # find end of symbol
80 while pos < end: # find end of symbol
81 d = program[pos]
81 d = program[pos]
82 if not (d.isalnum() or d == "_"):
82 if not (d.isalnum() or d == "_"):
83 break
83 break
84 pos += 1
84 pos += 1
85 sym = program[s:pos]
85 sym = program[s:pos]
86 yield ('symbol', sym, s)
86 yield ('symbol', sym, s)
87 pos -= 1
87 pos -= 1
88 elif c == '}':
88 elif c == '}':
89 pos += 1
89 pos += 1
90 break
90 break
91 else:
91 else:
92 raise error.ParseError(_("syntax error"), pos)
92 raise error.ParseError(_("syntax error"), pos)
93 pos += 1
93 pos += 1
94 yield ('end', None, pos)
94 yield ('end', None, pos)
95
95
96 def compiletemplate(tmpl, context, strtoken="string"):
96 def compiletemplate(tmpl, context, strtoken="string"):
97 parsed = []
97 parsed = []
98 pos, stop = 0, len(tmpl)
98 pos, stop = 0, len(tmpl)
99 p = parser.parser(tokenizer, elements)
99 p = parser.parser(tokenizer, elements)
100 while pos < stop:
100 while pos < stop:
101 n = tmpl.find('{', pos)
101 n = tmpl.find('{', pos)
102 if n < 0:
102 if n < 0:
103 parsed.append((strtoken, tmpl[pos:]))
103 parsed.append((strtoken, tmpl[pos:]))
104 break
104 break
105 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
105 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
106 if strtoken == 'string' and bs % 2 == 1:
106 if strtoken == 'string' and bs % 2 == 1:
107 # escaped (e.g. '\{', '\\\{', but not '\\{' nor r'\{')
107 # escaped (e.g. '\{', '\\\{', but not '\\{' nor r'\{')
108 parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
108 parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
109 pos = n + 1
109 pos = n + 1
110 continue
110 continue
111 if n > pos:
111 if n > pos:
112 parsed.append((strtoken, tmpl[pos:n]))
112 parsed.append((strtoken, tmpl[pos:n]))
113
113
114 pd = [tmpl, n + 1, stop]
114 pd = [tmpl, n + 1, stop]
115 parseres, pos = p.parse(pd)
115 parseres, pos = p.parse(pd)
116 parsed.append(parseres)
116 parsed.append(parseres)
117
117
118 return [compileexp(e, context, methods) for e in parsed]
118 return [compileexp(e, context, methods) for e in parsed]
119
119
120 def compileexp(exp, context, curmethods):
120 def compileexp(exp, context, curmethods):
121 t = exp[0]
121 t = exp[0]
122 if t in curmethods:
122 if t in curmethods:
123 return curmethods[t](exp, context)
123 return curmethods[t](exp, context)
124 raise error.ParseError(_("unknown method '%s'") % t)
124 raise error.ParseError(_("unknown method '%s'") % t)
125
125
126 # template evaluation
126 # template evaluation
127
127
128 def getsymbol(exp):
128 def getsymbol(exp):
129 if exp[0] == 'symbol':
129 if exp[0] == 'symbol':
130 return exp[1]
130 return exp[1]
131 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
131 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
132
132
133 def getlist(x):
133 def getlist(x):
134 if not x:
134 if not x:
135 return []
135 return []
136 if x[0] == 'list':
136 if x[0] == 'list':
137 return getlist(x[1]) + [x[2]]
137 return getlist(x[1]) + [x[2]]
138 return [x]
138 return [x]
139
139
140 def getfilter(exp, context):
140 def getfilter(exp, context):
141 f = getsymbol(exp)
141 f = getsymbol(exp)
142 if f not in context._filters:
142 if f not in context._filters:
143 raise error.ParseError(_("unknown function '%s'") % f)
143 raise error.ParseError(_("unknown function '%s'") % f)
144 return context._filters[f]
144 return context._filters[f]
145
145
146 def gettemplate(exp, context):
146 def gettemplate(exp, context):
147 if exp[0] == 'template':
147 if exp[0] == 'template':
148 return compiletemplate(exp[1], context)
148 return compiletemplate(exp[1], context)
149 if exp[0] == 'rawstring':
150 return compiletemplate(exp[1], context, strtoken=exp[0])
151 if exp[0] == 'symbol':
149 if exp[0] == 'symbol':
152 return context._load(exp[1])
150 return context._load(exp[1])
153 raise error.ParseError(_("expected template specifier"))
151 raise error.ParseError(_("expected template specifier"))
154
152
155 def runinteger(context, mapping, data):
153 def runinteger(context, mapping, data):
156 return int(data)
154 return int(data)
157
155
158 def runstring(context, mapping, data):
156 def runstring(context, mapping, data):
159 return data.decode("string-escape")
157 return data.decode("string-escape")
160
158
161 def runrawstring(context, mapping, data):
159 def runrawstring(context, mapping, data):
162 return data
160 return data
163
161
164 def runsymbol(context, mapping, key):
162 def runsymbol(context, mapping, key):
165 v = mapping.get(key)
163 v = mapping.get(key)
166 if v is None:
164 if v is None:
167 v = context._defaults.get(key)
165 v = context._defaults.get(key)
168 if v is None:
166 if v is None:
169 try:
167 try:
170 v = context.process(key, mapping)
168 v = context.process(key, mapping)
171 except TemplateNotFound:
169 except TemplateNotFound:
172 v = ''
170 v = ''
173 if callable(v):
171 if callable(v):
174 return v(**mapping)
172 return v(**mapping)
175 if isinstance(v, types.GeneratorType):
173 if isinstance(v, types.GeneratorType):
176 v = list(v)
174 v = list(v)
177 return v
175 return v
178
176
179 def buildtemplate(exp, context):
177 def buildtemplate(exp, context):
180 ctmpl = compiletemplate(exp[1], context)
178 ctmpl = compiletemplate(exp[1], context)
181 if len(ctmpl) == 1:
179 if len(ctmpl) == 1:
182 return ctmpl[0] # fast path for string with no template fragment
180 return ctmpl[0] # fast path for string with no template fragment
183 return (runtemplate, ctmpl)
181 return (runtemplate, ctmpl)
184
182
185 def runtemplate(context, mapping, template):
183 def runtemplate(context, mapping, template):
186 for func, data in template:
184 for func, data in template:
187 yield func(context, mapping, data)
185 yield func(context, mapping, data)
188
186
189 def buildfilter(exp, context):
187 def buildfilter(exp, context):
190 func, data = compileexp(exp[1], context, methods)
188 func, data = compileexp(exp[1], context, methods)
191 filt = getfilter(exp[2], context)
189 filt = getfilter(exp[2], context)
192 return (runfilter, (func, data, filt))
190 return (runfilter, (func, data, filt))
193
191
194 def runfilter(context, mapping, data):
192 def runfilter(context, mapping, data):
195 func, data, filt = data
193 func, data, filt = data
196 # func() may return string, generator of strings or arbitrary object such
194 # func() may return string, generator of strings or arbitrary object such
197 # as date tuple, but filter does not want generator.
195 # as date tuple, but filter does not want generator.
198 thing = func(context, mapping, data)
196 thing = func(context, mapping, data)
199 if isinstance(thing, types.GeneratorType):
197 if isinstance(thing, types.GeneratorType):
200 thing = stringify(thing)
198 thing = stringify(thing)
201 try:
199 try:
202 return filt(thing)
200 return filt(thing)
203 except (ValueError, AttributeError, TypeError):
201 except (ValueError, AttributeError, TypeError):
204 if isinstance(data, tuple):
202 if isinstance(data, tuple):
205 dt = data[1]
203 dt = data[1]
206 else:
204 else:
207 dt = data
205 dt = data
208 raise util.Abort(_("template filter '%s' is not compatible with "
206 raise util.Abort(_("template filter '%s' is not compatible with "
209 "keyword '%s'") % (filt.func_name, dt))
207 "keyword '%s'") % (filt.func_name, dt))
210
208
211 def buildmap(exp, context):
209 def buildmap(exp, context):
212 func, data = compileexp(exp[1], context, methods)
210 func, data = compileexp(exp[1], context, methods)
213 ctmpl = gettemplate(exp[2], context)
211 ctmpl = gettemplate(exp[2], context)
214 return (runmap, (func, data, ctmpl))
212 return (runmap, (func, data, ctmpl))
215
213
216 def runmap(context, mapping, data):
214 def runmap(context, mapping, data):
217 func, data, ctmpl = data
215 func, data, ctmpl = data
218 d = func(context, mapping, data)
216 d = func(context, mapping, data)
219 if callable(d):
217 if callable(d):
220 d = d()
218 d = d()
221
219
222 lm = mapping.copy()
220 lm = mapping.copy()
223
221
224 for i in d:
222 for i in d:
225 if isinstance(i, dict):
223 if isinstance(i, dict):
226 lm.update(i)
224 lm.update(i)
227 lm['originalnode'] = mapping.get('node')
225 lm['originalnode'] = mapping.get('node')
228 yield runtemplate(context, lm, ctmpl)
226 yield runtemplate(context, lm, ctmpl)
229 else:
227 else:
230 # v is not an iterable of dicts, this happen when 'key'
228 # v is not an iterable of dicts, this happen when 'key'
231 # has been fully expanded already and format is useless.
229 # has been fully expanded already and format is useless.
232 # If so, return the expanded value.
230 # If so, return the expanded value.
233 yield i
231 yield i
234
232
235 def buildfunc(exp, context):
233 def buildfunc(exp, context):
236 n = getsymbol(exp[1])
234 n = getsymbol(exp[1])
237 args = [compileexp(x, context, exprmethods) for x in getlist(exp[2])]
235 args = [compileexp(x, context, exprmethods) for x in getlist(exp[2])]
238 if n in funcs:
236 if n in funcs:
239 f = funcs[n]
237 f = funcs[n]
240 return (f, args)
238 return (f, args)
241 if n in context._filters:
239 if n in context._filters:
242 if len(args) != 1:
240 if len(args) != 1:
243 raise error.ParseError(_("filter %s expects one argument") % n)
241 raise error.ParseError(_("filter %s expects one argument") % n)
244 f = context._filters[n]
242 f = context._filters[n]
245 return (runfilter, (args[0][0], args[0][1], f))
243 return (runfilter, (args[0][0], args[0][1], f))
246 raise error.ParseError(_("unknown function '%s'") % n)
244 raise error.ParseError(_("unknown function '%s'") % n)
247
245
248 def date(context, mapping, args):
246 def date(context, mapping, args):
249 """:date(date[, fmt]): Format a date. See :hg:`help dates` for formatting
247 """:date(date[, fmt]): Format a date. See :hg:`help dates` for formatting
250 strings."""
248 strings."""
251 if not (1 <= len(args) <= 2):
249 if not (1 <= len(args) <= 2):
252 # i18n: "date" is a keyword
250 # i18n: "date" is a keyword
253 raise error.ParseError(_("date expects one or two arguments"))
251 raise error.ParseError(_("date expects one or two arguments"))
254
252
255 date = args[0][0](context, mapping, args[0][1])
253 date = args[0][0](context, mapping, args[0][1])
256 fmt = None
254 fmt = None
257 if len(args) == 2:
255 if len(args) == 2:
258 fmt = stringify(args[1][0](context, mapping, args[1][1]))
256 fmt = stringify(args[1][0](context, mapping, args[1][1]))
259 try:
257 try:
260 if fmt is None:
258 if fmt is None:
261 return util.datestr(date)
259 return util.datestr(date)
262 else:
260 else:
263 return util.datestr(date, fmt)
261 return util.datestr(date, fmt)
264 except (TypeError, ValueError):
262 except (TypeError, ValueError):
265 # i18n: "date" is a keyword
263 # i18n: "date" is a keyword
266 raise error.ParseError(_("date expects a date information"))
264 raise error.ParseError(_("date expects a date information"))
267
265
268 def diff(context, mapping, args):
266 def diff(context, mapping, args):
269 """:diff([includepattern [, excludepattern]]): Show a diff, optionally
267 """:diff([includepattern [, excludepattern]]): Show a diff, optionally
270 specifying files to include or exclude."""
268 specifying files to include or exclude."""
271 if len(args) > 2:
269 if len(args) > 2:
272 # i18n: "diff" is a keyword
270 # i18n: "diff" is a keyword
273 raise error.ParseError(_("diff expects one, two or no arguments"))
271 raise error.ParseError(_("diff expects one, two or no arguments"))
274
272
275 def getpatterns(i):
273 def getpatterns(i):
276 if i < len(args):
274 if i < len(args):
277 s = stringify(args[i][0](context, mapping, args[i][1])).strip()
275 s = stringify(args[i][0](context, mapping, args[i][1])).strip()
278 if s:
276 if s:
279 return [s]
277 return [s]
280 return []
278 return []
281
279
282 ctx = mapping['ctx']
280 ctx = mapping['ctx']
283 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
281 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
284
282
285 return ''.join(chunks)
283 return ''.join(chunks)
286
284
287 def fill(context, mapping, args):
285 def fill(context, mapping, args):
288 """:fill(text[, width[, initialident[, hangindent]]]): Fill many
286 """:fill(text[, width[, initialident[, hangindent]]]): Fill many
289 paragraphs with optional indentation. See the "fill" filter."""
287 paragraphs with optional indentation. See the "fill" filter."""
290 if not (1 <= len(args) <= 4):
288 if not (1 <= len(args) <= 4):
291 # i18n: "fill" is a keyword
289 # i18n: "fill" is a keyword
292 raise error.ParseError(_("fill expects one to four arguments"))
290 raise error.ParseError(_("fill expects one to four arguments"))
293
291
294 text = stringify(args[0][0](context, mapping, args[0][1]))
292 text = stringify(args[0][0](context, mapping, args[0][1]))
295 width = 76
293 width = 76
296 initindent = ''
294 initindent = ''
297 hangindent = ''
295 hangindent = ''
298 if 2 <= len(args) <= 4:
296 if 2 <= len(args) <= 4:
299 try:
297 try:
300 width = int(stringify(args[1][0](context, mapping, args[1][1])))
298 width = int(stringify(args[1][0](context, mapping, args[1][1])))
301 except ValueError:
299 except ValueError:
302 # i18n: "fill" is a keyword
300 # i18n: "fill" is a keyword
303 raise error.ParseError(_("fill expects an integer width"))
301 raise error.ParseError(_("fill expects an integer width"))
304 try:
302 try:
305 initindent = stringify(_evalifliteral(args[2], context, mapping))
303 initindent = stringify(args[2][0](context, mapping, args[2][1]))
306 hangindent = stringify(_evalifliteral(args[3], context, mapping))
304 hangindent = stringify(args[3][0](context, mapping, args[3][1]))
307 except IndexError:
305 except IndexError:
308 pass
306 pass
309
307
310 return templatefilters.fill(text, width, initindent, hangindent)
308 return templatefilters.fill(text, width, initindent, hangindent)
311
309
312 def pad(context, mapping, args):
310 def pad(context, mapping, args):
313 """:pad(text, width[, fillchar=' '[, right=False]]): Pad text with a
311 """:pad(text, width[, fillchar=' '[, right=False]]): Pad text with a
314 fill character."""
312 fill character."""
315 if not (2 <= len(args) <= 4):
313 if not (2 <= len(args) <= 4):
316 # i18n: "pad" is a keyword
314 # i18n: "pad" is a keyword
317 raise error.ParseError(_("pad() expects two to four arguments"))
315 raise error.ParseError(_("pad() expects two to four arguments"))
318
316
319 width = int(args[1][1])
317 width = int(args[1][1])
320
318
321 text = stringify(_evalifliteral(args[0], context, mapping))
319 text = stringify(args[0][0](context, mapping, args[0][1]))
322
320
323 right = False
321 right = False
324 fillchar = ' '
322 fillchar = ' '
325 if len(args) > 2:
323 if len(args) > 2:
326 fillchar = stringify(args[2][0](context, mapping, args[2][1]))
324 fillchar = stringify(args[2][0](context, mapping, args[2][1]))
327 if len(args) > 3:
325 if len(args) > 3:
328 right = util.parsebool(args[3][1])
326 right = util.parsebool(args[3][1])
329
327
330 if right:
328 if right:
331 return text.rjust(width, fillchar)
329 return text.rjust(width, fillchar)
332 else:
330 else:
333 return text.ljust(width, fillchar)
331 return text.ljust(width, fillchar)
334
332
335 def indent(context, mapping, args):
333 def indent(context, mapping, args):
336 """:indent(text, indentchars[, firstline]): Indents all non-empty lines
334 """:indent(text, indentchars[, firstline]): Indents all non-empty lines
337 with the characters given in the indentchars string. An optional
335 with the characters given in the indentchars string. An optional
338 third parameter will override the indent for the first line only
336 third parameter will override the indent for the first line only
339 if present."""
337 if present."""
340 if not (2 <= len(args) <= 3):
338 if not (2 <= len(args) <= 3):
341 # i18n: "indent" is a keyword
339 # i18n: "indent" is a keyword
342 raise error.ParseError(_("indent() expects two or three arguments"))
340 raise error.ParseError(_("indent() expects two or three arguments"))
343
341
344 text = stringify(args[0][0](context, mapping, args[0][1]))
342 text = stringify(args[0][0](context, mapping, args[0][1]))
345 indent = stringify(args[1][0](context, mapping, args[1][1]))
343 indent = stringify(args[1][0](context, mapping, args[1][1]))
346
344
347 if len(args) == 3:
345 if len(args) == 3:
348 firstline = stringify(args[2][0](context, mapping, args[2][1]))
346 firstline = stringify(args[2][0](context, mapping, args[2][1]))
349 else:
347 else:
350 firstline = indent
348 firstline = indent
351
349
352 # the indent function doesn't indent the first line, so we do it here
350 # the indent function doesn't indent the first line, so we do it here
353 return templatefilters.indent(firstline + text, indent)
351 return templatefilters.indent(firstline + text, indent)
354
352
355 def get(context, mapping, args):
353 def get(context, mapping, args):
356 """:get(dict, key): Get an attribute/key from an object. Some keywords
354 """:get(dict, key): Get an attribute/key from an object. Some keywords
357 are complex types. This function allows you to obtain the value of an
355 are complex types. This function allows you to obtain the value of an
358 attribute on these type."""
356 attribute on these type."""
359 if len(args) != 2:
357 if len(args) != 2:
360 # i18n: "get" is a keyword
358 # i18n: "get" is a keyword
361 raise error.ParseError(_("get() expects two arguments"))
359 raise error.ParseError(_("get() expects two arguments"))
362
360
363 dictarg = args[0][0](context, mapping, args[0][1])
361 dictarg = args[0][0](context, mapping, args[0][1])
364 if not util.safehasattr(dictarg, 'get'):
362 if not util.safehasattr(dictarg, 'get'):
365 # i18n: "get" is a keyword
363 # i18n: "get" is a keyword
366 raise error.ParseError(_("get() expects a dict as first argument"))
364 raise error.ParseError(_("get() expects a dict as first argument"))
367
365
368 key = args[1][0](context, mapping, args[1][1])
366 key = args[1][0](context, mapping, args[1][1])
369 yield dictarg.get(key)
367 yield dictarg.get(key)
370
368
371 def _evalifliteral(arg, context, mapping):
372 # get back to token tag to reinterpret string as template
373 strtoken = {runrawstring: 'rawstring'}.get(arg[0])
374 if strtoken:
375 yield runtemplate(context, mapping,
376 compiletemplate(arg[1], context, strtoken))
377 else:
378 yield stringify(arg[0](context, mapping, arg[1]))
379
380 def if_(context, mapping, args):
369 def if_(context, mapping, args):
381 """:if(expr, then[, else]): Conditionally execute based on the result of
370 """:if(expr, then[, else]): Conditionally execute based on the result of
382 an expression."""
371 an expression."""
383 if not (2 <= len(args) <= 3):
372 if not (2 <= len(args) <= 3):
384 # i18n: "if" is a keyword
373 # i18n: "if" is a keyword
385 raise error.ParseError(_("if expects two or three arguments"))
374 raise error.ParseError(_("if expects two or three arguments"))
386
375
387 test = stringify(args[0][0](context, mapping, args[0][1]))
376 test = stringify(args[0][0](context, mapping, args[0][1]))
388 if test:
377 if test:
389 yield _evalifliteral(args[1], context, mapping)
378 yield args[1][0](context, mapping, args[1][1])
390 elif len(args) == 3:
379 elif len(args) == 3:
391 yield _evalifliteral(args[2], context, mapping)
380 yield args[2][0](context, mapping, args[2][1])
392
381
393 def ifcontains(context, mapping, args):
382 def ifcontains(context, mapping, args):
394 """:ifcontains(search, thing, then[, else]): Conditionally execute based
383 """:ifcontains(search, thing, then[, else]): Conditionally execute based
395 on whether the item "search" is in "thing"."""
384 on whether the item "search" is in "thing"."""
396 if not (3 <= len(args) <= 4):
385 if not (3 <= len(args) <= 4):
397 # i18n: "ifcontains" is a keyword
386 # i18n: "ifcontains" is a keyword
398 raise error.ParseError(_("ifcontains expects three or four arguments"))
387 raise error.ParseError(_("ifcontains expects three or four arguments"))
399
388
400 item = stringify(args[0][0](context, mapping, args[0][1]))
389 item = stringify(args[0][0](context, mapping, args[0][1]))
401 items = args[1][0](context, mapping, args[1][1])
390 items = args[1][0](context, mapping, args[1][1])
402
391
403 if item in items:
392 if item in items:
404 yield _evalifliteral(args[2], context, mapping)
393 yield args[2][0](context, mapping, args[2][1])
405 elif len(args) == 4:
394 elif len(args) == 4:
406 yield _evalifliteral(args[3], context, mapping)
395 yield args[3][0](context, mapping, args[3][1])
407
396
408 def ifeq(context, mapping, args):
397 def ifeq(context, mapping, args):
409 """:ifeq(expr1, expr2, then[, else]): Conditionally execute based on
398 """:ifeq(expr1, expr2, then[, else]): Conditionally execute based on
410 whether 2 items are equivalent."""
399 whether 2 items are equivalent."""
411 if not (3 <= len(args) <= 4):
400 if not (3 <= len(args) <= 4):
412 # i18n: "ifeq" is a keyword
401 # i18n: "ifeq" is a keyword
413 raise error.ParseError(_("ifeq expects three or four arguments"))
402 raise error.ParseError(_("ifeq expects three or four arguments"))
414
403
415 test = stringify(args[0][0](context, mapping, args[0][1]))
404 test = stringify(args[0][0](context, mapping, args[0][1]))
416 match = stringify(args[1][0](context, mapping, args[1][1]))
405 match = stringify(args[1][0](context, mapping, args[1][1]))
417 if test == match:
406 if test == match:
418 yield _evalifliteral(args[2], context, mapping)
407 yield args[2][0](context, mapping, args[2][1])
419 elif len(args) == 4:
408 elif len(args) == 4:
420 yield _evalifliteral(args[3], context, mapping)
409 yield args[3][0](context, mapping, args[3][1])
421
410
422 def join(context, mapping, args):
411 def join(context, mapping, args):
423 """:join(list, sep): Join items in a list with a delimiter."""
412 """:join(list, sep): Join items in a list with a delimiter."""
424 if not (1 <= len(args) <= 2):
413 if not (1 <= len(args) <= 2):
425 # i18n: "join" is a keyword
414 # i18n: "join" is a keyword
426 raise error.ParseError(_("join expects one or two arguments"))
415 raise error.ParseError(_("join expects one or two arguments"))
427
416
428 joinset = args[0][0](context, mapping, args[0][1])
417 joinset = args[0][0](context, mapping, args[0][1])
429 if callable(joinset):
418 if callable(joinset):
430 jf = joinset.joinfmt
419 jf = joinset.joinfmt
431 joinset = [jf(x) for x in joinset()]
420 joinset = [jf(x) for x in joinset()]
432
421
433 joiner = " "
422 joiner = " "
434 if len(args) > 1:
423 if len(args) > 1:
435 joiner = stringify(args[1][0](context, mapping, args[1][1]))
424 joiner = stringify(args[1][0](context, mapping, args[1][1]))
436
425
437 first = True
426 first = True
438 for x in joinset:
427 for x in joinset:
439 if first:
428 if first:
440 first = False
429 first = False
441 else:
430 else:
442 yield joiner
431 yield joiner
443 yield x
432 yield x
444
433
445 def label(context, mapping, args):
434 def label(context, mapping, args):
446 """:label(label, expr): Apply a label to generated content. Content with
435 """:label(label, expr): Apply a label to generated content. Content with
447 a label applied can result in additional post-processing, such as
436 a label applied can result in additional post-processing, such as
448 automatic colorization."""
437 automatic colorization."""
449 if len(args) != 2:
438 if len(args) != 2:
450 # i18n: "label" is a keyword
439 # i18n: "label" is a keyword
451 raise error.ParseError(_("label expects two arguments"))
440 raise error.ParseError(_("label expects two arguments"))
452
441
453 # ignore args[0] (the label string) since this is supposed to be a a no-op
442 # ignore args[0] (the label string) since this is supposed to be a a no-op
454 yield _evalifliteral(args[1], context, mapping)
443 yield args[1][0](context, mapping, args[1][1])
455
444
456 def revset(context, mapping, args):
445 def revset(context, mapping, args):
457 """:revset(query[, formatargs...]): Execute a revision set query. See
446 """:revset(query[, formatargs...]): Execute a revision set query. See
458 :hg:`help revset`."""
447 :hg:`help revset`."""
459 if not len(args) > 0:
448 if not len(args) > 0:
460 # i18n: "revset" is a keyword
449 # i18n: "revset" is a keyword
461 raise error.ParseError(_("revset expects one or more arguments"))
450 raise error.ParseError(_("revset expects one or more arguments"))
462
451
463 raw = args[0][1]
452 raw = args[0][1]
464 ctx = mapping['ctx']
453 ctx = mapping['ctx']
465 repo = ctx.repo()
454 repo = ctx.repo()
466
455
467 def query(expr):
456 def query(expr):
468 m = revsetmod.match(repo.ui, expr)
457 m = revsetmod.match(repo.ui, expr)
469 return m(repo)
458 return m(repo)
470
459
471 if len(args) > 1:
460 if len(args) > 1:
472 formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
461 formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
473 revs = query(revsetmod.formatspec(raw, *formatargs))
462 revs = query(revsetmod.formatspec(raw, *formatargs))
474 revs = list([str(r) for r in revs])
463 revs = list([str(r) for r in revs])
475 else:
464 else:
476 revsetcache = mapping['cache'].setdefault("revsetcache", {})
465 revsetcache = mapping['cache'].setdefault("revsetcache", {})
477 if raw in revsetcache:
466 if raw in revsetcache:
478 revs = revsetcache[raw]
467 revs = revsetcache[raw]
479 else:
468 else:
480 revs = query(raw)
469 revs = query(raw)
481 revs = list([str(r) for r in revs])
470 revs = list([str(r) for r in revs])
482 revsetcache[raw] = revs
471 revsetcache[raw] = revs
483
472
484 return templatekw.showlist("revision", revs, **mapping)
473 return templatekw.showlist("revision", revs, **mapping)
485
474
486 def rstdoc(context, mapping, args):
475 def rstdoc(context, mapping, args):
487 """:rstdoc(text, style): Format ReStructuredText."""
476 """:rstdoc(text, style): Format ReStructuredText."""
488 if len(args) != 2:
477 if len(args) != 2:
489 # i18n: "rstdoc" is a keyword
478 # i18n: "rstdoc" is a keyword
490 raise error.ParseError(_("rstdoc expects two arguments"))
479 raise error.ParseError(_("rstdoc expects two arguments"))
491
480
492 text = stringify(args[0][0](context, mapping, args[0][1]))
481 text = stringify(args[0][0](context, mapping, args[0][1]))
493 style = stringify(args[1][0](context, mapping, args[1][1]))
482 style = stringify(args[1][0](context, mapping, args[1][1]))
494
483
495 return minirst.format(text, style=style, keep=['verbose'])
484 return minirst.format(text, style=style, keep=['verbose'])
496
485
497 def shortest(context, mapping, args):
486 def shortest(context, mapping, args):
498 """:shortest(node, minlength=4): Obtain the shortest representation of
487 """:shortest(node, minlength=4): Obtain the shortest representation of
499 a node."""
488 a node."""
500 if not (1 <= len(args) <= 2):
489 if not (1 <= len(args) <= 2):
501 # i18n: "shortest" is a keyword
490 # i18n: "shortest" is a keyword
502 raise error.ParseError(_("shortest() expects one or two arguments"))
491 raise error.ParseError(_("shortest() expects one or two arguments"))
503
492
504 node = stringify(args[0][0](context, mapping, args[0][1]))
493 node = stringify(args[0][0](context, mapping, args[0][1]))
505
494
506 minlength = 4
495 minlength = 4
507 if len(args) > 1:
496 if len(args) > 1:
508 minlength = int(args[1][1])
497 minlength = int(args[1][1])
509
498
510 cl = mapping['ctx']._repo.changelog
499 cl = mapping['ctx']._repo.changelog
511 def isvalid(test):
500 def isvalid(test):
512 try:
501 try:
513 try:
502 try:
514 cl.index.partialmatch(test)
503 cl.index.partialmatch(test)
515 except AttributeError:
504 except AttributeError:
516 # Pure mercurial doesn't support partialmatch on the index.
505 # Pure mercurial doesn't support partialmatch on the index.
517 # Fallback to the slow way.
506 # Fallback to the slow way.
518 if cl._partialmatch(test) is None:
507 if cl._partialmatch(test) is None:
519 return False
508 return False
520
509
521 try:
510 try:
522 i = int(test)
511 i = int(test)
523 # if we are a pure int, then starting with zero will not be
512 # if we are a pure int, then starting with zero will not be
524 # confused as a rev; or, obviously, if the int is larger than
513 # confused as a rev; or, obviously, if the int is larger than
525 # the value of the tip rev
514 # the value of the tip rev
526 if test[0] == '0' or i > len(cl):
515 if test[0] == '0' or i > len(cl):
527 return True
516 return True
528 return False
517 return False
529 except ValueError:
518 except ValueError:
530 return True
519 return True
531 except error.RevlogError:
520 except error.RevlogError:
532 return False
521 return False
533
522
534 shortest = node
523 shortest = node
535 startlength = max(6, minlength)
524 startlength = max(6, minlength)
536 length = startlength
525 length = startlength
537 while True:
526 while True:
538 test = node[:length]
527 test = node[:length]
539 if isvalid(test):
528 if isvalid(test):
540 shortest = test
529 shortest = test
541 if length == minlength or length > startlength:
530 if length == minlength or length > startlength:
542 return shortest
531 return shortest
543 length -= 1
532 length -= 1
544 else:
533 else:
545 length += 1
534 length += 1
546 if len(shortest) <= length:
535 if len(shortest) <= length:
547 return shortest
536 return shortest
548
537
549 def strip(context, mapping, args):
538 def strip(context, mapping, args):
550 """:strip(text[, chars]): Strip characters from a string."""
539 """:strip(text[, chars]): Strip characters from a string."""
551 if not (1 <= len(args) <= 2):
540 if not (1 <= len(args) <= 2):
552 # i18n: "strip" is a keyword
541 # i18n: "strip" is a keyword
553 raise error.ParseError(_("strip expects one or two arguments"))
542 raise error.ParseError(_("strip expects one or two arguments"))
554
543
555 text = stringify(args[0][0](context, mapping, args[0][1]))
544 text = stringify(args[0][0](context, mapping, args[0][1]))
556 if len(args) == 2:
545 if len(args) == 2:
557 chars = stringify(args[1][0](context, mapping, args[1][1]))
546 chars = stringify(args[1][0](context, mapping, args[1][1]))
558 return text.strip(chars)
547 return text.strip(chars)
559 return text.strip()
548 return text.strip()
560
549
561 def sub(context, mapping, args):
550 def sub(context, mapping, args):
562 """:sub(pattern, replacement, expression): Perform text substitution
551 """:sub(pattern, replacement, expression): Perform text substitution
563 using regular expressions."""
552 using regular expressions."""
564 if len(args) != 3:
553 if len(args) != 3:
565 # i18n: "sub" is a keyword
554 # i18n: "sub" is a keyword
566 raise error.ParseError(_("sub expects three arguments"))
555 raise error.ParseError(_("sub expects three arguments"))
567
556
568 pat = stringify(args[0][0](context, mapping, args[0][1]))
557 pat = stringify(args[0][0](context, mapping, args[0][1]))
569 rpl = stringify(args[1][0](context, mapping, args[1][1]))
558 rpl = stringify(args[1][0](context, mapping, args[1][1]))
570 src = stringify(_evalifliteral(args[2], context, mapping))
559 src = stringify(args[2][0](context, mapping, args[2][1]))
571 yield re.sub(pat, rpl, src)
560 yield re.sub(pat, rpl, src)
572
561
573 def startswith(context, mapping, args):
562 def startswith(context, mapping, args):
574 """:startswith(pattern, text): Returns the value from the "text" argument
563 """:startswith(pattern, text): Returns the value from the "text" argument
575 if it begins with the content from the "pattern" argument."""
564 if it begins with the content from the "pattern" argument."""
576 if len(args) != 2:
565 if len(args) != 2:
577 # i18n: "startswith" is a keyword
566 # i18n: "startswith" is a keyword
578 raise error.ParseError(_("startswith expects two arguments"))
567 raise error.ParseError(_("startswith expects two arguments"))
579
568
580 patn = stringify(args[0][0](context, mapping, args[0][1]))
569 patn = stringify(args[0][0](context, mapping, args[0][1]))
581 text = stringify(args[1][0](context, mapping, args[1][1]))
570 text = stringify(args[1][0](context, mapping, args[1][1]))
582 if text.startswith(patn):
571 if text.startswith(patn):
583 return text
572 return text
584 return ''
573 return ''
585
574
586
575
587 def word(context, mapping, args):
576 def word(context, mapping, args):
588 """:word(number, text[, separator]): Return the nth word from a string."""
577 """:word(number, text[, separator]): Return the nth word from a string."""
589 if not (2 <= len(args) <= 3):
578 if not (2 <= len(args) <= 3):
590 # i18n: "word" is a keyword
579 # i18n: "word" is a keyword
591 raise error.ParseError(_("word expects two or three arguments, got %d")
580 raise error.ParseError(_("word expects two or three arguments, got %d")
592 % len(args))
581 % len(args))
593
582
594 try:
583 try:
595 num = int(stringify(args[0][0](context, mapping, args[0][1])))
584 num = int(stringify(args[0][0](context, mapping, args[0][1])))
596 except ValueError:
585 except ValueError:
597 # i18n: "word" is a keyword
586 # i18n: "word" is a keyword
598 raise error.ParseError(_("word expects an integer index"))
587 raise error.ParseError(_("word expects an integer index"))
599 text = stringify(args[1][0](context, mapping, args[1][1]))
588 text = stringify(args[1][0](context, mapping, args[1][1]))
600 if len(args) == 3:
589 if len(args) == 3:
601 splitter = stringify(args[2][0](context, mapping, args[2][1]))
590 splitter = stringify(args[2][0](context, mapping, args[2][1]))
602 else:
591 else:
603 splitter = None
592 splitter = None
604
593
605 tokens = text.split(splitter)
594 tokens = text.split(splitter)
606 if num >= len(tokens):
595 if num >= len(tokens):
607 return ''
596 return ''
608 else:
597 else:
609 return tokens[num]
598 return tokens[num]
610
599
611 # methods to interpret function arguments or inner expressions (e.g. {_(x)})
600 # methods to interpret function arguments or inner expressions (e.g. {_(x)})
612 exprmethods = {
601 exprmethods = {
613 "integer": lambda e, c: (runinteger, e[1]),
602 "integer": lambda e, c: (runinteger, e[1]),
614 "string": lambda e, c: (runstring, e[1]),
603 "string": lambda e, c: (runstring, e[1]),
615 "rawstring": lambda e, c: (runrawstring, e[1]),
604 "rawstring": lambda e, c: (runrawstring, e[1]),
616 "symbol": lambda e, c: (runsymbol, e[1]),
605 "symbol": lambda e, c: (runsymbol, e[1]),
617 "template": buildtemplate,
606 "template": buildtemplate,
618 "group": lambda e, c: compileexp(e[1], c, exprmethods),
607 "group": lambda e, c: compileexp(e[1], c, exprmethods),
619 # ".": buildmember,
608 # ".": buildmember,
620 "|": buildfilter,
609 "|": buildfilter,
621 "%": buildmap,
610 "%": buildmap,
622 "func": buildfunc,
611 "func": buildfunc,
623 }
612 }
624
613
625 # methods to interpret top-level template (e.g. {x}, {x|_}, {x % "y"})
614 # methods to interpret top-level template (e.g. {x}, {x|_}, {x % "y"})
626 methods = exprmethods.copy()
615 methods = exprmethods.copy()
627 methods["integer"] = exprmethods["symbol"] # '{1}' as variable
616 methods["integer"] = exprmethods["symbol"] # '{1}' as variable
628
617
629 funcs = {
618 funcs = {
630 "date": date,
619 "date": date,
631 "diff": diff,
620 "diff": diff,
632 "fill": fill,
621 "fill": fill,
633 "get": get,
622 "get": get,
634 "if": if_,
623 "if": if_,
635 "ifcontains": ifcontains,
624 "ifcontains": ifcontains,
636 "ifeq": ifeq,
625 "ifeq": ifeq,
637 "indent": indent,
626 "indent": indent,
638 "join": join,
627 "join": join,
639 "label": label,
628 "label": label,
640 "pad": pad,
629 "pad": pad,
641 "revset": revset,
630 "revset": revset,
642 "rstdoc": rstdoc,
631 "rstdoc": rstdoc,
643 "shortest": shortest,
632 "shortest": shortest,
644 "startswith": startswith,
633 "startswith": startswith,
645 "strip": strip,
634 "strip": strip,
646 "sub": sub,
635 "sub": sub,
647 "word": word,
636 "word": word,
648 }
637 }
649
638
650 # template engine
639 # template engine
651
640
652 stringify = templatefilters.stringify
641 stringify = templatefilters.stringify
653
642
654 def _flatten(thing):
643 def _flatten(thing):
655 '''yield a single stream from a possibly nested set of iterators'''
644 '''yield a single stream from a possibly nested set of iterators'''
656 if isinstance(thing, str):
645 if isinstance(thing, str):
657 yield thing
646 yield thing
658 elif not util.safehasattr(thing, '__iter__'):
647 elif not util.safehasattr(thing, '__iter__'):
659 if thing is not None:
648 if thing is not None:
660 yield str(thing)
649 yield str(thing)
661 else:
650 else:
662 for i in thing:
651 for i in thing:
663 if isinstance(i, str):
652 if isinstance(i, str):
664 yield i
653 yield i
665 elif not util.safehasattr(i, '__iter__'):
654 elif not util.safehasattr(i, '__iter__'):
666 if i is not None:
655 if i is not None:
667 yield str(i)
656 yield str(i)
668 elif i is not None:
657 elif i is not None:
669 for j in _flatten(i):
658 for j in _flatten(i):
670 yield j
659 yield j
671
660
672 def unquotestring(s):
661 def unquotestring(s):
673 '''unwrap quotes'''
662 '''unwrap quotes'''
674 if len(s) < 2 or s[0] != s[-1]:
663 if len(s) < 2 or s[0] != s[-1]:
675 raise SyntaxError(_('unmatched quotes'))
664 raise SyntaxError(_('unmatched quotes'))
676 # de-backslash-ify only <\">. it is invalid syntax in non-string part of
665 # de-backslash-ify only <\">. it is invalid syntax in non-string part of
677 # template, but we are likely to escape <"> in quoted string and it was
666 # template, but we are likely to escape <"> in quoted string and it was
678 # accepted before, thanks to issue4290. <\\"> is unmodified because it
667 # accepted before, thanks to issue4290. <\\"> is unmodified because it
679 # is ambiguous and it was processed as such before 2.8.1.
668 # is ambiguous and it was processed as such before 2.8.1.
680 #
669 #
681 # template result
670 # template result
682 # --------- ------------------------
671 # --------- ------------------------
683 # {\"\"} parse error
672 # {\"\"} parse error
684 # "{""}" {""} -> <>
673 # "{""}" {""} -> <>
685 # "{\"\"}" {""} -> <>
674 # "{\"\"}" {""} -> <>
686 # {"\""} {"\""} -> <">
675 # {"\""} {"\""} -> <">
687 # '{"\""}' {"\""} -> <">
676 # '{"\""}' {"\""} -> <">
688 # "{"\""}" parse error (don't care)
677 # "{"\""}" parse error (don't care)
689 q = s[0]
678 q = s[0]
690 return s[1:-1].replace('\\\\' + q, '\\\\\\' + q).replace('\\' + q, q)
679 return s[1:-1].replace('\\\\' + q, '\\\\\\' + q).replace('\\' + q, q)
691
680
692 class engine(object):
681 class engine(object):
693 '''template expansion engine.
682 '''template expansion engine.
694
683
695 template expansion works like this. a map file contains key=value
684 template expansion works like this. a map file contains key=value
696 pairs. if value is quoted, it is treated as string. otherwise, it
685 pairs. if value is quoted, it is treated as string. otherwise, it
697 is treated as name of template file.
686 is treated as name of template file.
698
687
699 templater is asked to expand a key in map. it looks up key, and
688 templater is asked to expand a key in map. it looks up key, and
700 looks for strings like this: {foo}. it expands {foo} by looking up
689 looks for strings like this: {foo}. it expands {foo} by looking up
701 foo in map, and substituting it. expansion is recursive: it stops
690 foo in map, and substituting it. expansion is recursive: it stops
702 when there is no more {foo} to replace.
691 when there is no more {foo} to replace.
703
692
704 expansion also allows formatting and filtering.
693 expansion also allows formatting and filtering.
705
694
706 format uses key to expand each item in list. syntax is
695 format uses key to expand each item in list. syntax is
707 {key%format}.
696 {key%format}.
708
697
709 filter uses function to transform value. syntax is
698 filter uses function to transform value. syntax is
710 {key|filter1|filter2|...}.'''
699 {key|filter1|filter2|...}.'''
711
700
712 def __init__(self, loader, filters={}, defaults={}):
701 def __init__(self, loader, filters={}, defaults={}):
713 self._loader = loader
702 self._loader = loader
714 self._filters = filters
703 self._filters = filters
715 self._defaults = defaults
704 self._defaults = defaults
716 self._cache = {}
705 self._cache = {}
717
706
718 def _load(self, t):
707 def _load(self, t):
719 '''load, parse, and cache a template'''
708 '''load, parse, and cache a template'''
720 if t not in self._cache:
709 if t not in self._cache:
721 self._cache[t] = compiletemplate(self._loader(t), self)
710 self._cache[t] = compiletemplate(self._loader(t), self)
722 return self._cache[t]
711 return self._cache[t]
723
712
724 def process(self, t, mapping):
713 def process(self, t, mapping):
725 '''Perform expansion. t is name of map element to expand.
714 '''Perform expansion. t is name of map element to expand.
726 mapping contains added elements for use during expansion. Is a
715 mapping contains added elements for use during expansion. Is a
727 generator.'''
716 generator.'''
728 return _flatten(runtemplate(self, mapping, self._load(t)))
717 return _flatten(runtemplate(self, mapping, self._load(t)))
729
718
730 engines = {'default': engine}
719 engines = {'default': engine}
731
720
732 def stylelist():
721 def stylelist():
733 paths = templatepaths()
722 paths = templatepaths()
734 if not paths:
723 if not paths:
735 return _('no templates found, try `hg debuginstall` for more info')
724 return _('no templates found, try `hg debuginstall` for more info')
736 dirlist = os.listdir(paths[0])
725 dirlist = os.listdir(paths[0])
737 stylelist = []
726 stylelist = []
738 for file in dirlist:
727 for file in dirlist:
739 split = file.split(".")
728 split = file.split(".")
740 if split[0] == "map-cmdline":
729 if split[0] == "map-cmdline":
741 stylelist.append(split[1])
730 stylelist.append(split[1])
742 return ", ".join(sorted(stylelist))
731 return ", ".join(sorted(stylelist))
743
732
744 class TemplateNotFound(util.Abort):
733 class TemplateNotFound(util.Abort):
745 pass
734 pass
746
735
747 class templater(object):
736 class templater(object):
748
737
749 def __init__(self, mapfile, filters={}, defaults={}, cache={},
738 def __init__(self, mapfile, filters={}, defaults={}, cache={},
750 minchunk=1024, maxchunk=65536):
739 minchunk=1024, maxchunk=65536):
751 '''set up template engine.
740 '''set up template engine.
752 mapfile is name of file to read map definitions from.
741 mapfile is name of file to read map definitions from.
753 filters is dict of functions. each transforms a value into another.
742 filters is dict of functions. each transforms a value into another.
754 defaults is dict of default map definitions.'''
743 defaults is dict of default map definitions.'''
755 self.mapfile = mapfile or 'template'
744 self.mapfile = mapfile or 'template'
756 self.cache = cache.copy()
745 self.cache = cache.copy()
757 self.map = {}
746 self.map = {}
758 if mapfile:
747 if mapfile:
759 self.base = os.path.dirname(mapfile)
748 self.base = os.path.dirname(mapfile)
760 else:
749 else:
761 self.base = ''
750 self.base = ''
762 self.filters = templatefilters.filters.copy()
751 self.filters = templatefilters.filters.copy()
763 self.filters.update(filters)
752 self.filters.update(filters)
764 self.defaults = defaults
753 self.defaults = defaults
765 self.minchunk, self.maxchunk = minchunk, maxchunk
754 self.minchunk, self.maxchunk = minchunk, maxchunk
766 self.ecache = {}
755 self.ecache = {}
767
756
768 if not mapfile:
757 if not mapfile:
769 return
758 return
770 if not os.path.exists(mapfile):
759 if not os.path.exists(mapfile):
771 raise util.Abort(_("style '%s' not found") % mapfile,
760 raise util.Abort(_("style '%s' not found") % mapfile,
772 hint=_("available styles: %s") % stylelist())
761 hint=_("available styles: %s") % stylelist())
773
762
774 conf = config.config(includepaths=templatepaths())
763 conf = config.config(includepaths=templatepaths())
775 conf.read(mapfile)
764 conf.read(mapfile)
776
765
777 for key, val in conf[''].items():
766 for key, val in conf[''].items():
778 if not val:
767 if not val:
779 raise SyntaxError(_('%s: missing value') % conf.source('', key))
768 raise SyntaxError(_('%s: missing value') % conf.source('', key))
780 if val[0] in "'\"":
769 if val[0] in "'\"":
781 try:
770 try:
782 self.cache[key] = unquotestring(val)
771 self.cache[key] = unquotestring(val)
783 except SyntaxError, inst:
772 except SyntaxError, inst:
784 raise SyntaxError('%s: %s' %
773 raise SyntaxError('%s: %s' %
785 (conf.source('', key), inst.args[0]))
774 (conf.source('', key), inst.args[0]))
786 else:
775 else:
787 val = 'default', val
776 val = 'default', val
788 if ':' in val[1]:
777 if ':' in val[1]:
789 val = val[1].split(':', 1)
778 val = val[1].split(':', 1)
790 self.map[key] = val[0], os.path.join(self.base, val[1])
779 self.map[key] = val[0], os.path.join(self.base, val[1])
791
780
792 def __contains__(self, key):
781 def __contains__(self, key):
793 return key in self.cache or key in self.map
782 return key in self.cache or key in self.map
794
783
795 def load(self, t):
784 def load(self, t):
796 '''Get the template for the given template name. Use a local cache.'''
785 '''Get the template for the given template name. Use a local cache.'''
797 if t not in self.cache:
786 if t not in self.cache:
798 try:
787 try:
799 self.cache[t] = util.readfile(self.map[t][1])
788 self.cache[t] = util.readfile(self.map[t][1])
800 except KeyError, inst:
789 except KeyError, inst:
801 raise TemplateNotFound(_('"%s" not in template map') %
790 raise TemplateNotFound(_('"%s" not in template map') %
802 inst.args[0])
791 inst.args[0])
803 except IOError, inst:
792 except IOError, inst:
804 raise IOError(inst.args[0], _('template file %s: %s') %
793 raise IOError(inst.args[0], _('template file %s: %s') %
805 (self.map[t][1], inst.args[1]))
794 (self.map[t][1], inst.args[1]))
806 return self.cache[t]
795 return self.cache[t]
807
796
808 def __call__(self, t, **mapping):
797 def __call__(self, t, **mapping):
809 ttype = t in self.map and self.map[t][0] or 'default'
798 ttype = t in self.map and self.map[t][0] or 'default'
810 if ttype not in self.ecache:
799 if ttype not in self.ecache:
811 self.ecache[ttype] = engines[ttype](self.load,
800 self.ecache[ttype] = engines[ttype](self.load,
812 self.filters, self.defaults)
801 self.filters, self.defaults)
813 proc = self.ecache[ttype]
802 proc = self.ecache[ttype]
814
803
815 stream = proc.process(t, mapping)
804 stream = proc.process(t, mapping)
816 if self.minchunk:
805 if self.minchunk:
817 stream = util.increasingchunks(stream, min=self.minchunk,
806 stream = util.increasingchunks(stream, min=self.minchunk,
818 max=self.maxchunk)
807 max=self.maxchunk)
819 return stream
808 return stream
820
809
821 def templatepaths():
810 def templatepaths():
822 '''return locations used for template files.'''
811 '''return locations used for template files.'''
823 pathsrel = ['templates']
812 pathsrel = ['templates']
824 paths = [os.path.normpath(os.path.join(util.datapath, f))
813 paths = [os.path.normpath(os.path.join(util.datapath, f))
825 for f in pathsrel]
814 for f in pathsrel]
826 return [p for p in paths if os.path.isdir(p)]
815 return [p for p in paths if os.path.isdir(p)]
827
816
828 def templatepath(name):
817 def templatepath(name):
829 '''return location of template file. returns None if not found.'''
818 '''return location of template file. returns None if not found.'''
830 for p in templatepaths():
819 for p in templatepaths():
831 f = os.path.join(p, name)
820 f = os.path.join(p, name)
832 if os.path.exists(f):
821 if os.path.exists(f):
833 return f
822 return f
834 return None
823 return None
835
824
836 def stylemap(styles, paths=None):
825 def stylemap(styles, paths=None):
837 """Return path to mapfile for a given style.
826 """Return path to mapfile for a given style.
838
827
839 Searches mapfile in the following locations:
828 Searches mapfile in the following locations:
840 1. templatepath/style/map
829 1. templatepath/style/map
841 2. templatepath/map-style
830 2. templatepath/map-style
842 3. templatepath/map
831 3. templatepath/map
843 """
832 """
844
833
845 if paths is None:
834 if paths is None:
846 paths = templatepaths()
835 paths = templatepaths()
847 elif isinstance(paths, str):
836 elif isinstance(paths, str):
848 paths = [paths]
837 paths = [paths]
849
838
850 if isinstance(styles, str):
839 if isinstance(styles, str):
851 styles = [styles]
840 styles = [styles]
852
841
853 for style in styles:
842 for style in styles:
854 # only plain name is allowed to honor template paths
843 # only plain name is allowed to honor template paths
855 if (not style
844 if (not style
856 or style in (os.curdir, os.pardir)
845 or style in (os.curdir, os.pardir)
857 or os.sep in style
846 or os.sep in style
858 or os.altsep and os.altsep in style):
847 or os.altsep and os.altsep in style):
859 continue
848 continue
860 locations = [os.path.join(style, 'map'), 'map-' + style]
849 locations = [os.path.join(style, 'map'), 'map-' + style]
861 locations.append('map')
850 locations.append('map')
862
851
863 for path in paths:
852 for path in paths:
864 for location in locations:
853 for location in locations:
865 mapfile = os.path.join(path, location)
854 mapfile = os.path.join(path, location)
866 if os.path.isfile(mapfile):
855 if os.path.isfile(mapfile):
867 return style, mapfile
856 return style, mapfile
868
857
869 raise RuntimeError("No hgweb templates found in %r" % paths)
858 raise RuntimeError("No hgweb templates found in %r" % paths)
870
859
871 # tell hggettext to extract docstrings from these functions:
860 # tell hggettext to extract docstrings from these functions:
872 i18nfunctions = funcs.values()
861 i18nfunctions = funcs.values()
@@ -1,3307 +1,3311
1 $ hg init a
1 $ hg init a
2 $ cd a
2 $ cd a
3 $ echo a > a
3 $ echo a > a
4 $ hg add a
4 $ hg add a
5 $ echo line 1 > b
5 $ echo line 1 > b
6 $ echo line 2 >> b
6 $ echo line 2 >> b
7 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
7 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
8
8
9 $ hg add b
9 $ hg add b
10 $ echo other 1 > c
10 $ echo other 1 > c
11 $ echo other 2 >> c
11 $ echo other 2 >> c
12 $ echo >> c
12 $ echo >> c
13 $ echo other 3 >> c
13 $ echo other 3 >> c
14 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
14 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
15
15
16 $ hg add c
16 $ hg add c
17 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
17 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
18 $ echo c >> c
18 $ echo c >> c
19 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
19 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
20
20
21 $ echo foo > .hg/branch
21 $ echo foo > .hg/branch
22 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
22 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
23
23
24 $ hg co -q 3
24 $ hg co -q 3
25 $ echo other 4 >> d
25 $ echo other 4 >> d
26 $ hg add d
26 $ hg add d
27 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
27 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
28
28
29 $ hg merge -q foo
29 $ hg merge -q foo
30 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
30 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
31
31
32 Second branch starting at nullrev:
32 Second branch starting at nullrev:
33
33
34 $ hg update null
34 $ hg update null
35 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
35 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
36 $ echo second > second
36 $ echo second > second
37 $ hg add second
37 $ hg add second
38 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
38 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
39 created new head
39 created new head
40
40
41 $ echo third > third
41 $ echo third > third
42 $ hg add third
42 $ hg add third
43 $ hg mv second fourth
43 $ hg mv second fourth
44 $ hg commit -m third -d "2020-01-01 10:01"
44 $ hg commit -m third -d "2020-01-01 10:01"
45
45
46 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
46 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
47 fourth (second)
47 fourth (second)
48 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
48 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
49 second -> fourth
49 second -> fourth
50 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
50 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
51 8 t
51 8 t
52 7 f
52 7 f
53
53
54 Quoting for ui.logtemplate
54 Quoting for ui.logtemplate
55
55
56 $ hg tip --config "ui.logtemplate={rev}\n"
56 $ hg tip --config "ui.logtemplate={rev}\n"
57 8
57 8
58 $ hg tip --config "ui.logtemplate='{rev}\n'"
58 $ hg tip --config "ui.logtemplate='{rev}\n'"
59 8
59 8
60 $ hg tip --config 'ui.logtemplate="{rev}\n"'
60 $ hg tip --config 'ui.logtemplate="{rev}\n"'
61 8
61 8
62
62
63 Make sure user/global hgrc does not affect tests
63 Make sure user/global hgrc does not affect tests
64
64
65 $ echo '[ui]' > .hg/hgrc
65 $ echo '[ui]' > .hg/hgrc
66 $ echo 'logtemplate =' >> .hg/hgrc
66 $ echo 'logtemplate =' >> .hg/hgrc
67 $ echo 'style =' >> .hg/hgrc
67 $ echo 'style =' >> .hg/hgrc
68
68
69 Add some simple styles to settings
69 Add some simple styles to settings
70
70
71 $ echo '[templates]' >> .hg/hgrc
71 $ echo '[templates]' >> .hg/hgrc
72 $ printf 'simple = "{rev}\\n"\n' >> .hg/hgrc
72 $ printf 'simple = "{rev}\\n"\n' >> .hg/hgrc
73 $ printf 'simple2 = {rev}\\n\n' >> .hg/hgrc
73 $ printf 'simple2 = {rev}\\n\n' >> .hg/hgrc
74
74
75 $ hg log -l1 -Tsimple
75 $ hg log -l1 -Tsimple
76 8
76 8
77 $ hg log -l1 -Tsimple2
77 $ hg log -l1 -Tsimple2
78 8
78 8
79
79
80 Test templates and style maps in files:
80 Test templates and style maps in files:
81
81
82 $ echo "{rev}" > tmpl
82 $ echo "{rev}" > tmpl
83 $ hg log -l1 -T./tmpl
83 $ hg log -l1 -T./tmpl
84 8
84 8
85 $ hg log -l1 -Tblah/blah
85 $ hg log -l1 -Tblah/blah
86 blah/blah (no-eol)
86 blah/blah (no-eol)
87
87
88 $ printf 'changeset = "{rev}\\n"\n' > map-simple
88 $ printf 'changeset = "{rev}\\n"\n' > map-simple
89 $ hg log -l1 -T./map-simple
89 $ hg log -l1 -T./map-simple
90 8
90 8
91
91
92 Template should precede style option
92 Template should precede style option
93
93
94 $ hg log -l1 --style default -T '{rev}\n'
94 $ hg log -l1 --style default -T '{rev}\n'
95 8
95 8
96
96
97 Add a commit with empty description, to ensure that the templates
97 Add a commit with empty description, to ensure that the templates
98 below will omit the description line.
98 below will omit the description line.
99
99
100 $ echo c >> c
100 $ echo c >> c
101 $ hg add c
101 $ hg add c
102 $ hg commit -qm ' '
102 $ hg commit -qm ' '
103
103
104 Default style is like normal output. Phases style should be the same
104 Default style is like normal output. Phases style should be the same
105 as default style, except for extra phase lines.
105 as default style, except for extra phase lines.
106
106
107 $ hg log > log.out
107 $ hg log > log.out
108 $ hg log --style default > style.out
108 $ hg log --style default > style.out
109 $ cmp log.out style.out || diff -u log.out style.out
109 $ cmp log.out style.out || diff -u log.out style.out
110 $ hg log -T phases > phases.out
110 $ hg log -T phases > phases.out
111 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
111 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
112 @@ -2,0 +3 @@
112 @@ -2,0 +3 @@
113 +phase: draft
113 +phase: draft
114 @@ -6,0 +8 @@
114 @@ -6,0 +8 @@
115 +phase: draft
115 +phase: draft
116 @@ -11,0 +14 @@
116 @@ -11,0 +14 @@
117 +phase: draft
117 +phase: draft
118 @@ -17,0 +21 @@
118 @@ -17,0 +21 @@
119 +phase: draft
119 +phase: draft
120 @@ -24,0 +29 @@
120 @@ -24,0 +29 @@
121 +phase: draft
121 +phase: draft
122 @@ -31,0 +37 @@
122 @@ -31,0 +37 @@
123 +phase: draft
123 +phase: draft
124 @@ -36,0 +43 @@
124 @@ -36,0 +43 @@
125 +phase: draft
125 +phase: draft
126 @@ -41,0 +49 @@
126 @@ -41,0 +49 @@
127 +phase: draft
127 +phase: draft
128 @@ -46,0 +55 @@
128 @@ -46,0 +55 @@
129 +phase: draft
129 +phase: draft
130 @@ -51,0 +61 @@
130 @@ -51,0 +61 @@
131 +phase: draft
131 +phase: draft
132
132
133 $ hg log -v > log.out
133 $ hg log -v > log.out
134 $ hg log -v --style default > style.out
134 $ hg log -v --style default > style.out
135 $ cmp log.out style.out || diff -u log.out style.out
135 $ cmp log.out style.out || diff -u log.out style.out
136 $ hg log -v -T phases > phases.out
136 $ hg log -v -T phases > phases.out
137 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
137 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
138 @@ -2,0 +3 @@
138 @@ -2,0 +3 @@
139 +phase: draft
139 +phase: draft
140 @@ -7,0 +9 @@
140 @@ -7,0 +9 @@
141 +phase: draft
141 +phase: draft
142 @@ -15,0 +18 @@
142 @@ -15,0 +18 @@
143 +phase: draft
143 +phase: draft
144 @@ -24,0 +28 @@
144 @@ -24,0 +28 @@
145 +phase: draft
145 +phase: draft
146 @@ -33,0 +38 @@
146 @@ -33,0 +38 @@
147 +phase: draft
147 +phase: draft
148 @@ -43,0 +49 @@
148 @@ -43,0 +49 @@
149 +phase: draft
149 +phase: draft
150 @@ -50,0 +57 @@
150 @@ -50,0 +57 @@
151 +phase: draft
151 +phase: draft
152 @@ -58,0 +66 @@
152 @@ -58,0 +66 @@
153 +phase: draft
153 +phase: draft
154 @@ -66,0 +75 @@
154 @@ -66,0 +75 @@
155 +phase: draft
155 +phase: draft
156 @@ -77,0 +87 @@
156 @@ -77,0 +87 @@
157 +phase: draft
157 +phase: draft
158
158
159 $ hg log -q > log.out
159 $ hg log -q > log.out
160 $ hg log -q --style default > style.out
160 $ hg log -q --style default > style.out
161 $ cmp log.out style.out || diff -u log.out style.out
161 $ cmp log.out style.out || diff -u log.out style.out
162 $ hg log -q -T phases > phases.out
162 $ hg log -q -T phases > phases.out
163 $ cmp log.out phases.out || diff -u log.out phases.out
163 $ cmp log.out phases.out || diff -u log.out phases.out
164
164
165 $ hg log --debug > log.out
165 $ hg log --debug > log.out
166 $ hg log --debug --style default > style.out
166 $ hg log --debug --style default > style.out
167 $ cmp log.out style.out || diff -u log.out style.out
167 $ cmp log.out style.out || diff -u log.out style.out
168 $ hg log --debug -T phases > phases.out
168 $ hg log --debug -T phases > phases.out
169 $ cmp log.out phases.out || diff -u log.out phases.out
169 $ cmp log.out phases.out || diff -u log.out phases.out
170
170
171 Default style should also preserve color information (issue2866):
171 Default style should also preserve color information (issue2866):
172
172
173 $ cp $HGRCPATH $HGRCPATH-bak
173 $ cp $HGRCPATH $HGRCPATH-bak
174 $ cat <<EOF >> $HGRCPATH
174 $ cat <<EOF >> $HGRCPATH
175 > [extensions]
175 > [extensions]
176 > color=
176 > color=
177 > EOF
177 > EOF
178
178
179 $ hg --color=debug log > log.out
179 $ hg --color=debug log > log.out
180 $ hg --color=debug log --style default > style.out
180 $ hg --color=debug log --style default > style.out
181 $ cmp log.out style.out || diff -u log.out style.out
181 $ cmp log.out style.out || diff -u log.out style.out
182 $ hg --color=debug log -T phases > phases.out
182 $ hg --color=debug log -T phases > phases.out
183 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
183 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
184 @@ -2,0 +3 @@
184 @@ -2,0 +3 @@
185 +[log.phase|phase: draft]
185 +[log.phase|phase: draft]
186 @@ -6,0 +8 @@
186 @@ -6,0 +8 @@
187 +[log.phase|phase: draft]
187 +[log.phase|phase: draft]
188 @@ -11,0 +14 @@
188 @@ -11,0 +14 @@
189 +[log.phase|phase: draft]
189 +[log.phase|phase: draft]
190 @@ -17,0 +21 @@
190 @@ -17,0 +21 @@
191 +[log.phase|phase: draft]
191 +[log.phase|phase: draft]
192 @@ -24,0 +29 @@
192 @@ -24,0 +29 @@
193 +[log.phase|phase: draft]
193 +[log.phase|phase: draft]
194 @@ -31,0 +37 @@
194 @@ -31,0 +37 @@
195 +[log.phase|phase: draft]
195 +[log.phase|phase: draft]
196 @@ -36,0 +43 @@
196 @@ -36,0 +43 @@
197 +[log.phase|phase: draft]
197 +[log.phase|phase: draft]
198 @@ -41,0 +49 @@
198 @@ -41,0 +49 @@
199 +[log.phase|phase: draft]
199 +[log.phase|phase: draft]
200 @@ -46,0 +55 @@
200 @@ -46,0 +55 @@
201 +[log.phase|phase: draft]
201 +[log.phase|phase: draft]
202 @@ -51,0 +61 @@
202 @@ -51,0 +61 @@
203 +[log.phase|phase: draft]
203 +[log.phase|phase: draft]
204
204
205 $ hg --color=debug -v log > log.out
205 $ hg --color=debug -v log > log.out
206 $ hg --color=debug -v log --style default > style.out
206 $ hg --color=debug -v log --style default > style.out
207 $ cmp log.out style.out || diff -u log.out style.out
207 $ cmp log.out style.out || diff -u log.out style.out
208 $ hg --color=debug -v log -T phases > phases.out
208 $ hg --color=debug -v log -T phases > phases.out
209 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
209 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
210 @@ -2,0 +3 @@
210 @@ -2,0 +3 @@
211 +[log.phase|phase: draft]
211 +[log.phase|phase: draft]
212 @@ -7,0 +9 @@
212 @@ -7,0 +9 @@
213 +[log.phase|phase: draft]
213 +[log.phase|phase: draft]
214 @@ -15,0 +18 @@
214 @@ -15,0 +18 @@
215 +[log.phase|phase: draft]
215 +[log.phase|phase: draft]
216 @@ -24,0 +28 @@
216 @@ -24,0 +28 @@
217 +[log.phase|phase: draft]
217 +[log.phase|phase: draft]
218 @@ -33,0 +38 @@
218 @@ -33,0 +38 @@
219 +[log.phase|phase: draft]
219 +[log.phase|phase: draft]
220 @@ -43,0 +49 @@
220 @@ -43,0 +49 @@
221 +[log.phase|phase: draft]
221 +[log.phase|phase: draft]
222 @@ -50,0 +57 @@
222 @@ -50,0 +57 @@
223 +[log.phase|phase: draft]
223 +[log.phase|phase: draft]
224 @@ -58,0 +66 @@
224 @@ -58,0 +66 @@
225 +[log.phase|phase: draft]
225 +[log.phase|phase: draft]
226 @@ -66,0 +75 @@
226 @@ -66,0 +75 @@
227 +[log.phase|phase: draft]
227 +[log.phase|phase: draft]
228 @@ -77,0 +87 @@
228 @@ -77,0 +87 @@
229 +[log.phase|phase: draft]
229 +[log.phase|phase: draft]
230
230
231 $ hg --color=debug -q log > log.out
231 $ hg --color=debug -q log > log.out
232 $ hg --color=debug -q log --style default > style.out
232 $ hg --color=debug -q log --style default > style.out
233 $ cmp log.out style.out || diff -u log.out style.out
233 $ cmp log.out style.out || diff -u log.out style.out
234 $ hg --color=debug -q log -T phases > phases.out
234 $ hg --color=debug -q log -T phases > phases.out
235 $ cmp log.out phases.out || diff -u log.out phases.out
235 $ cmp log.out phases.out || diff -u log.out phases.out
236
236
237 $ hg --color=debug --debug log > log.out
237 $ hg --color=debug --debug log > log.out
238 $ hg --color=debug --debug log --style default > style.out
238 $ hg --color=debug --debug log --style default > style.out
239 $ cmp log.out style.out || diff -u log.out style.out
239 $ cmp log.out style.out || diff -u log.out style.out
240 $ hg --color=debug --debug log -T phases > phases.out
240 $ hg --color=debug --debug log -T phases > phases.out
241 $ cmp log.out phases.out || diff -u log.out phases.out
241 $ cmp log.out phases.out || diff -u log.out phases.out
242
242
243 $ mv $HGRCPATH-bak $HGRCPATH
243 $ mv $HGRCPATH-bak $HGRCPATH
244
244
245 Remove commit with empty commit message, so as to not pollute further
245 Remove commit with empty commit message, so as to not pollute further
246 tests.
246 tests.
247
247
248 $ hg --config extensions.strip= strip -q .
248 $ hg --config extensions.strip= strip -q .
249
249
250 Revision with no copies (used to print a traceback):
250 Revision with no copies (used to print a traceback):
251
251
252 $ hg tip -v --template '\n'
252 $ hg tip -v --template '\n'
253
253
254
254
255 Compact style works:
255 Compact style works:
256
256
257 $ hg log -Tcompact
257 $ hg log -Tcompact
258 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
258 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
259 third
259 third
260
260
261 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
261 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
262 second
262 second
263
263
264 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
264 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
265 merge
265 merge
266
266
267 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
267 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
268 new head
268 new head
269
269
270 4 bbe44766e73d 1970-01-17 04:53 +0000 person
270 4 bbe44766e73d 1970-01-17 04:53 +0000 person
271 new branch
271 new branch
272
272
273 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
273 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
274 no user, no domain
274 no user, no domain
275
275
276 2 97054abb4ab8 1970-01-14 21:20 +0000 other
276 2 97054abb4ab8 1970-01-14 21:20 +0000 other
277 no person
277 no person
278
278
279 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
279 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
280 other 1
280 other 1
281
281
282 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
282 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
283 line 1
283 line 1
284
284
285
285
286 $ hg log -v --style compact
286 $ hg log -v --style compact
287 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
287 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
288 third
288 third
289
289
290 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
290 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
291 second
291 second
292
292
293 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
293 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
294 merge
294 merge
295
295
296 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
296 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
297 new head
297 new head
298
298
299 4 bbe44766e73d 1970-01-17 04:53 +0000 person
299 4 bbe44766e73d 1970-01-17 04:53 +0000 person
300 new branch
300 new branch
301
301
302 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
302 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
303 no user, no domain
303 no user, no domain
304
304
305 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
305 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
306 no person
306 no person
307
307
308 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
308 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
309 other 1
309 other 1
310 other 2
310 other 2
311
311
312 other 3
312 other 3
313
313
314 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
314 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
315 line 1
315 line 1
316 line 2
316 line 2
317
317
318
318
319 $ hg log --debug --style compact
319 $ hg log --debug --style compact
320 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
320 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
321 third
321 third
322
322
323 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
323 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
324 second
324 second
325
325
326 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
326 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
327 merge
327 merge
328
328
329 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
329 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
330 new head
330 new head
331
331
332 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
332 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
333 new branch
333 new branch
334
334
335 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
335 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
336 no user, no domain
336 no user, no domain
337
337
338 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
338 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
339 no person
339 no person
340
340
341 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
341 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
342 other 1
342 other 1
343 other 2
343 other 2
344
344
345 other 3
345 other 3
346
346
347 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
347 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
348 line 1
348 line 1
349 line 2
349 line 2
350
350
351
351
352 Test xml styles:
352 Test xml styles:
353
353
354 $ hg log --style xml
354 $ hg log --style xml
355 <?xml version="1.0"?>
355 <?xml version="1.0"?>
356 <log>
356 <log>
357 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
357 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
358 <tag>tip</tag>
358 <tag>tip</tag>
359 <author email="test">test</author>
359 <author email="test">test</author>
360 <date>2020-01-01T10:01:00+00:00</date>
360 <date>2020-01-01T10:01:00+00:00</date>
361 <msg xml:space="preserve">third</msg>
361 <msg xml:space="preserve">third</msg>
362 </logentry>
362 </logentry>
363 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
363 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
364 <parent revision="-1" node="0000000000000000000000000000000000000000" />
364 <parent revision="-1" node="0000000000000000000000000000000000000000" />
365 <author email="user@hostname">User Name</author>
365 <author email="user@hostname">User Name</author>
366 <date>1970-01-12T13:46:40+00:00</date>
366 <date>1970-01-12T13:46:40+00:00</date>
367 <msg xml:space="preserve">second</msg>
367 <msg xml:space="preserve">second</msg>
368 </logentry>
368 </logentry>
369 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
369 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
370 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
370 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
371 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
371 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
372 <author email="person">person</author>
372 <author email="person">person</author>
373 <date>1970-01-18T08:40:01+00:00</date>
373 <date>1970-01-18T08:40:01+00:00</date>
374 <msg xml:space="preserve">merge</msg>
374 <msg xml:space="preserve">merge</msg>
375 </logentry>
375 </logentry>
376 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
376 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
377 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
377 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
378 <author email="person">person</author>
378 <author email="person">person</author>
379 <date>1970-01-18T08:40:00+00:00</date>
379 <date>1970-01-18T08:40:00+00:00</date>
380 <msg xml:space="preserve">new head</msg>
380 <msg xml:space="preserve">new head</msg>
381 </logentry>
381 </logentry>
382 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
382 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
383 <branch>foo</branch>
383 <branch>foo</branch>
384 <author email="person">person</author>
384 <author email="person">person</author>
385 <date>1970-01-17T04:53:20+00:00</date>
385 <date>1970-01-17T04:53:20+00:00</date>
386 <msg xml:space="preserve">new branch</msg>
386 <msg xml:space="preserve">new branch</msg>
387 </logentry>
387 </logentry>
388 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
388 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
389 <author email="person">person</author>
389 <author email="person">person</author>
390 <date>1970-01-16T01:06:40+00:00</date>
390 <date>1970-01-16T01:06:40+00:00</date>
391 <msg xml:space="preserve">no user, no domain</msg>
391 <msg xml:space="preserve">no user, no domain</msg>
392 </logentry>
392 </logentry>
393 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
393 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
394 <author email="other@place">other</author>
394 <author email="other@place">other</author>
395 <date>1970-01-14T21:20:00+00:00</date>
395 <date>1970-01-14T21:20:00+00:00</date>
396 <msg xml:space="preserve">no person</msg>
396 <msg xml:space="preserve">no person</msg>
397 </logentry>
397 </logentry>
398 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
398 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
399 <author email="other@place">A. N. Other</author>
399 <author email="other@place">A. N. Other</author>
400 <date>1970-01-13T17:33:20+00:00</date>
400 <date>1970-01-13T17:33:20+00:00</date>
401 <msg xml:space="preserve">other 1
401 <msg xml:space="preserve">other 1
402 other 2
402 other 2
403
403
404 other 3</msg>
404 other 3</msg>
405 </logentry>
405 </logentry>
406 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
406 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
407 <author email="user@hostname">User Name</author>
407 <author email="user@hostname">User Name</author>
408 <date>1970-01-12T13:46:40+00:00</date>
408 <date>1970-01-12T13:46:40+00:00</date>
409 <msg xml:space="preserve">line 1
409 <msg xml:space="preserve">line 1
410 line 2</msg>
410 line 2</msg>
411 </logentry>
411 </logentry>
412 </log>
412 </log>
413
413
414 $ hg log -v --style xml
414 $ hg log -v --style xml
415 <?xml version="1.0"?>
415 <?xml version="1.0"?>
416 <log>
416 <log>
417 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
417 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
418 <tag>tip</tag>
418 <tag>tip</tag>
419 <author email="test">test</author>
419 <author email="test">test</author>
420 <date>2020-01-01T10:01:00+00:00</date>
420 <date>2020-01-01T10:01:00+00:00</date>
421 <msg xml:space="preserve">third</msg>
421 <msg xml:space="preserve">third</msg>
422 <paths>
422 <paths>
423 <path action="A">fourth</path>
423 <path action="A">fourth</path>
424 <path action="A">third</path>
424 <path action="A">third</path>
425 <path action="R">second</path>
425 <path action="R">second</path>
426 </paths>
426 </paths>
427 <copies>
427 <copies>
428 <copy source="second">fourth</copy>
428 <copy source="second">fourth</copy>
429 </copies>
429 </copies>
430 </logentry>
430 </logentry>
431 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
431 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
432 <parent revision="-1" node="0000000000000000000000000000000000000000" />
432 <parent revision="-1" node="0000000000000000000000000000000000000000" />
433 <author email="user@hostname">User Name</author>
433 <author email="user@hostname">User Name</author>
434 <date>1970-01-12T13:46:40+00:00</date>
434 <date>1970-01-12T13:46:40+00:00</date>
435 <msg xml:space="preserve">second</msg>
435 <msg xml:space="preserve">second</msg>
436 <paths>
436 <paths>
437 <path action="A">second</path>
437 <path action="A">second</path>
438 </paths>
438 </paths>
439 </logentry>
439 </logentry>
440 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
440 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
441 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
441 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
442 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
442 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
443 <author email="person">person</author>
443 <author email="person">person</author>
444 <date>1970-01-18T08:40:01+00:00</date>
444 <date>1970-01-18T08:40:01+00:00</date>
445 <msg xml:space="preserve">merge</msg>
445 <msg xml:space="preserve">merge</msg>
446 <paths>
446 <paths>
447 </paths>
447 </paths>
448 </logentry>
448 </logentry>
449 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
449 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
450 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
450 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
451 <author email="person">person</author>
451 <author email="person">person</author>
452 <date>1970-01-18T08:40:00+00:00</date>
452 <date>1970-01-18T08:40:00+00:00</date>
453 <msg xml:space="preserve">new head</msg>
453 <msg xml:space="preserve">new head</msg>
454 <paths>
454 <paths>
455 <path action="A">d</path>
455 <path action="A">d</path>
456 </paths>
456 </paths>
457 </logentry>
457 </logentry>
458 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
458 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
459 <branch>foo</branch>
459 <branch>foo</branch>
460 <author email="person">person</author>
460 <author email="person">person</author>
461 <date>1970-01-17T04:53:20+00:00</date>
461 <date>1970-01-17T04:53:20+00:00</date>
462 <msg xml:space="preserve">new branch</msg>
462 <msg xml:space="preserve">new branch</msg>
463 <paths>
463 <paths>
464 </paths>
464 </paths>
465 </logentry>
465 </logentry>
466 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
466 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
467 <author email="person">person</author>
467 <author email="person">person</author>
468 <date>1970-01-16T01:06:40+00:00</date>
468 <date>1970-01-16T01:06:40+00:00</date>
469 <msg xml:space="preserve">no user, no domain</msg>
469 <msg xml:space="preserve">no user, no domain</msg>
470 <paths>
470 <paths>
471 <path action="M">c</path>
471 <path action="M">c</path>
472 </paths>
472 </paths>
473 </logentry>
473 </logentry>
474 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
474 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
475 <author email="other@place">other</author>
475 <author email="other@place">other</author>
476 <date>1970-01-14T21:20:00+00:00</date>
476 <date>1970-01-14T21:20:00+00:00</date>
477 <msg xml:space="preserve">no person</msg>
477 <msg xml:space="preserve">no person</msg>
478 <paths>
478 <paths>
479 <path action="A">c</path>
479 <path action="A">c</path>
480 </paths>
480 </paths>
481 </logentry>
481 </logentry>
482 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
482 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
483 <author email="other@place">A. N. Other</author>
483 <author email="other@place">A. N. Other</author>
484 <date>1970-01-13T17:33:20+00:00</date>
484 <date>1970-01-13T17:33:20+00:00</date>
485 <msg xml:space="preserve">other 1
485 <msg xml:space="preserve">other 1
486 other 2
486 other 2
487
487
488 other 3</msg>
488 other 3</msg>
489 <paths>
489 <paths>
490 <path action="A">b</path>
490 <path action="A">b</path>
491 </paths>
491 </paths>
492 </logentry>
492 </logentry>
493 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
493 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
494 <author email="user@hostname">User Name</author>
494 <author email="user@hostname">User Name</author>
495 <date>1970-01-12T13:46:40+00:00</date>
495 <date>1970-01-12T13:46:40+00:00</date>
496 <msg xml:space="preserve">line 1
496 <msg xml:space="preserve">line 1
497 line 2</msg>
497 line 2</msg>
498 <paths>
498 <paths>
499 <path action="A">a</path>
499 <path action="A">a</path>
500 </paths>
500 </paths>
501 </logentry>
501 </logentry>
502 </log>
502 </log>
503
503
504 $ hg log --debug --style xml
504 $ hg log --debug --style xml
505 <?xml version="1.0"?>
505 <?xml version="1.0"?>
506 <log>
506 <log>
507 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
507 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
508 <tag>tip</tag>
508 <tag>tip</tag>
509 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
509 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
510 <parent revision="-1" node="0000000000000000000000000000000000000000" />
510 <parent revision="-1" node="0000000000000000000000000000000000000000" />
511 <author email="test">test</author>
511 <author email="test">test</author>
512 <date>2020-01-01T10:01:00+00:00</date>
512 <date>2020-01-01T10:01:00+00:00</date>
513 <msg xml:space="preserve">third</msg>
513 <msg xml:space="preserve">third</msg>
514 <paths>
514 <paths>
515 <path action="A">fourth</path>
515 <path action="A">fourth</path>
516 <path action="A">third</path>
516 <path action="A">third</path>
517 <path action="R">second</path>
517 <path action="R">second</path>
518 </paths>
518 </paths>
519 <copies>
519 <copies>
520 <copy source="second">fourth</copy>
520 <copy source="second">fourth</copy>
521 </copies>
521 </copies>
522 <extra key="branch">default</extra>
522 <extra key="branch">default</extra>
523 </logentry>
523 </logentry>
524 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
524 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
525 <parent revision="-1" node="0000000000000000000000000000000000000000" />
525 <parent revision="-1" node="0000000000000000000000000000000000000000" />
526 <parent revision="-1" node="0000000000000000000000000000000000000000" />
526 <parent revision="-1" node="0000000000000000000000000000000000000000" />
527 <author email="user@hostname">User Name</author>
527 <author email="user@hostname">User Name</author>
528 <date>1970-01-12T13:46:40+00:00</date>
528 <date>1970-01-12T13:46:40+00:00</date>
529 <msg xml:space="preserve">second</msg>
529 <msg xml:space="preserve">second</msg>
530 <paths>
530 <paths>
531 <path action="A">second</path>
531 <path action="A">second</path>
532 </paths>
532 </paths>
533 <extra key="branch">default</extra>
533 <extra key="branch">default</extra>
534 </logentry>
534 </logentry>
535 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
535 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
536 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
536 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
537 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
537 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
538 <author email="person">person</author>
538 <author email="person">person</author>
539 <date>1970-01-18T08:40:01+00:00</date>
539 <date>1970-01-18T08:40:01+00:00</date>
540 <msg xml:space="preserve">merge</msg>
540 <msg xml:space="preserve">merge</msg>
541 <paths>
541 <paths>
542 </paths>
542 </paths>
543 <extra key="branch">default</extra>
543 <extra key="branch">default</extra>
544 </logentry>
544 </logentry>
545 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
545 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
546 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
546 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
547 <parent revision="-1" node="0000000000000000000000000000000000000000" />
547 <parent revision="-1" node="0000000000000000000000000000000000000000" />
548 <author email="person">person</author>
548 <author email="person">person</author>
549 <date>1970-01-18T08:40:00+00:00</date>
549 <date>1970-01-18T08:40:00+00:00</date>
550 <msg xml:space="preserve">new head</msg>
550 <msg xml:space="preserve">new head</msg>
551 <paths>
551 <paths>
552 <path action="A">d</path>
552 <path action="A">d</path>
553 </paths>
553 </paths>
554 <extra key="branch">default</extra>
554 <extra key="branch">default</extra>
555 </logentry>
555 </logentry>
556 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
556 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
557 <branch>foo</branch>
557 <branch>foo</branch>
558 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
558 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
559 <parent revision="-1" node="0000000000000000000000000000000000000000" />
559 <parent revision="-1" node="0000000000000000000000000000000000000000" />
560 <author email="person">person</author>
560 <author email="person">person</author>
561 <date>1970-01-17T04:53:20+00:00</date>
561 <date>1970-01-17T04:53:20+00:00</date>
562 <msg xml:space="preserve">new branch</msg>
562 <msg xml:space="preserve">new branch</msg>
563 <paths>
563 <paths>
564 </paths>
564 </paths>
565 <extra key="branch">foo</extra>
565 <extra key="branch">foo</extra>
566 </logentry>
566 </logentry>
567 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
567 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
568 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
568 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
569 <parent revision="-1" node="0000000000000000000000000000000000000000" />
569 <parent revision="-1" node="0000000000000000000000000000000000000000" />
570 <author email="person">person</author>
570 <author email="person">person</author>
571 <date>1970-01-16T01:06:40+00:00</date>
571 <date>1970-01-16T01:06:40+00:00</date>
572 <msg xml:space="preserve">no user, no domain</msg>
572 <msg xml:space="preserve">no user, no domain</msg>
573 <paths>
573 <paths>
574 <path action="M">c</path>
574 <path action="M">c</path>
575 </paths>
575 </paths>
576 <extra key="branch">default</extra>
576 <extra key="branch">default</extra>
577 </logentry>
577 </logentry>
578 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
578 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
579 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
579 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
580 <parent revision="-1" node="0000000000000000000000000000000000000000" />
580 <parent revision="-1" node="0000000000000000000000000000000000000000" />
581 <author email="other@place">other</author>
581 <author email="other@place">other</author>
582 <date>1970-01-14T21:20:00+00:00</date>
582 <date>1970-01-14T21:20:00+00:00</date>
583 <msg xml:space="preserve">no person</msg>
583 <msg xml:space="preserve">no person</msg>
584 <paths>
584 <paths>
585 <path action="A">c</path>
585 <path action="A">c</path>
586 </paths>
586 </paths>
587 <extra key="branch">default</extra>
587 <extra key="branch">default</extra>
588 </logentry>
588 </logentry>
589 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
589 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
590 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
590 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
591 <parent revision="-1" node="0000000000000000000000000000000000000000" />
591 <parent revision="-1" node="0000000000000000000000000000000000000000" />
592 <author email="other@place">A. N. Other</author>
592 <author email="other@place">A. N. Other</author>
593 <date>1970-01-13T17:33:20+00:00</date>
593 <date>1970-01-13T17:33:20+00:00</date>
594 <msg xml:space="preserve">other 1
594 <msg xml:space="preserve">other 1
595 other 2
595 other 2
596
596
597 other 3</msg>
597 other 3</msg>
598 <paths>
598 <paths>
599 <path action="A">b</path>
599 <path action="A">b</path>
600 </paths>
600 </paths>
601 <extra key="branch">default</extra>
601 <extra key="branch">default</extra>
602 </logentry>
602 </logentry>
603 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
603 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
604 <parent revision="-1" node="0000000000000000000000000000000000000000" />
604 <parent revision="-1" node="0000000000000000000000000000000000000000" />
605 <parent revision="-1" node="0000000000000000000000000000000000000000" />
605 <parent revision="-1" node="0000000000000000000000000000000000000000" />
606 <author email="user@hostname">User Name</author>
606 <author email="user@hostname">User Name</author>
607 <date>1970-01-12T13:46:40+00:00</date>
607 <date>1970-01-12T13:46:40+00:00</date>
608 <msg xml:space="preserve">line 1
608 <msg xml:space="preserve">line 1
609 line 2</msg>
609 line 2</msg>
610 <paths>
610 <paths>
611 <path action="A">a</path>
611 <path action="A">a</path>
612 </paths>
612 </paths>
613 <extra key="branch">default</extra>
613 <extra key="branch">default</extra>
614 </logentry>
614 </logentry>
615 </log>
615 </log>
616
616
617
617
618 Test JSON style:
618 Test JSON style:
619
619
620 $ hg log -k nosuch -Tjson
620 $ hg log -k nosuch -Tjson
621 []
621 []
622
622
623 $ hg log -qr . -Tjson
623 $ hg log -qr . -Tjson
624 [
624 [
625 {
625 {
626 "rev": 8,
626 "rev": 8,
627 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
627 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
628 }
628 }
629 ]
629 ]
630
630
631 $ hg log -vpr . -Tjson --stat
631 $ hg log -vpr . -Tjson --stat
632 [
632 [
633 {
633 {
634 "rev": 8,
634 "rev": 8,
635 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
635 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
636 "branch": "default",
636 "branch": "default",
637 "phase": "draft",
637 "phase": "draft",
638 "user": "test",
638 "user": "test",
639 "date": [1577872860, 0],
639 "date": [1577872860, 0],
640 "desc": "third",
640 "desc": "third",
641 "bookmarks": [],
641 "bookmarks": [],
642 "tags": ["tip"],
642 "tags": ["tip"],
643 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
643 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
644 "files": ["fourth", "second", "third"],
644 "files": ["fourth", "second", "third"],
645 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
645 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
646 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"
646 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"
647 }
647 }
648 ]
648 ]
649
649
650 honor --git but not format-breaking diffopts
650 honor --git but not format-breaking diffopts
651 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
651 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
652 [
652 [
653 {
653 {
654 "rev": 8,
654 "rev": 8,
655 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
655 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
656 "branch": "default",
656 "branch": "default",
657 "phase": "draft",
657 "phase": "draft",
658 "user": "test",
658 "user": "test",
659 "date": [1577872860, 0],
659 "date": [1577872860, 0],
660 "desc": "third",
660 "desc": "third",
661 "bookmarks": [],
661 "bookmarks": [],
662 "tags": ["tip"],
662 "tags": ["tip"],
663 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
663 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
664 "files": ["fourth", "second", "third"],
664 "files": ["fourth", "second", "third"],
665 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n"
665 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n"
666 }
666 }
667 ]
667 ]
668
668
669 $ hg log -T json
669 $ hg log -T json
670 [
670 [
671 {
671 {
672 "rev": 8,
672 "rev": 8,
673 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
673 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
674 "branch": "default",
674 "branch": "default",
675 "phase": "draft",
675 "phase": "draft",
676 "user": "test",
676 "user": "test",
677 "date": [1577872860, 0],
677 "date": [1577872860, 0],
678 "desc": "third",
678 "desc": "third",
679 "bookmarks": [],
679 "bookmarks": [],
680 "tags": ["tip"],
680 "tags": ["tip"],
681 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
681 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
682 },
682 },
683 {
683 {
684 "rev": 7,
684 "rev": 7,
685 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
685 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
686 "branch": "default",
686 "branch": "default",
687 "phase": "draft",
687 "phase": "draft",
688 "user": "User Name <user@hostname>",
688 "user": "User Name <user@hostname>",
689 "date": [1000000, 0],
689 "date": [1000000, 0],
690 "desc": "second",
690 "desc": "second",
691 "bookmarks": [],
691 "bookmarks": [],
692 "tags": [],
692 "tags": [],
693 "parents": ["0000000000000000000000000000000000000000"]
693 "parents": ["0000000000000000000000000000000000000000"]
694 },
694 },
695 {
695 {
696 "rev": 6,
696 "rev": 6,
697 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
697 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
698 "branch": "default",
698 "branch": "default",
699 "phase": "draft",
699 "phase": "draft",
700 "user": "person",
700 "user": "person",
701 "date": [1500001, 0],
701 "date": [1500001, 0],
702 "desc": "merge",
702 "desc": "merge",
703 "bookmarks": [],
703 "bookmarks": [],
704 "tags": [],
704 "tags": [],
705 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
705 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
706 },
706 },
707 {
707 {
708 "rev": 5,
708 "rev": 5,
709 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
709 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
710 "branch": "default",
710 "branch": "default",
711 "phase": "draft",
711 "phase": "draft",
712 "user": "person",
712 "user": "person",
713 "date": [1500000, 0],
713 "date": [1500000, 0],
714 "desc": "new head",
714 "desc": "new head",
715 "bookmarks": [],
715 "bookmarks": [],
716 "tags": [],
716 "tags": [],
717 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
717 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
718 },
718 },
719 {
719 {
720 "rev": 4,
720 "rev": 4,
721 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
721 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
722 "branch": "foo",
722 "branch": "foo",
723 "phase": "draft",
723 "phase": "draft",
724 "user": "person",
724 "user": "person",
725 "date": [1400000, 0],
725 "date": [1400000, 0],
726 "desc": "new branch",
726 "desc": "new branch",
727 "bookmarks": [],
727 "bookmarks": [],
728 "tags": [],
728 "tags": [],
729 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
729 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
730 },
730 },
731 {
731 {
732 "rev": 3,
732 "rev": 3,
733 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
733 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
734 "branch": "default",
734 "branch": "default",
735 "phase": "draft",
735 "phase": "draft",
736 "user": "person",
736 "user": "person",
737 "date": [1300000, 0],
737 "date": [1300000, 0],
738 "desc": "no user, no domain",
738 "desc": "no user, no domain",
739 "bookmarks": [],
739 "bookmarks": [],
740 "tags": [],
740 "tags": [],
741 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
741 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
742 },
742 },
743 {
743 {
744 "rev": 2,
744 "rev": 2,
745 "node": "97054abb4ab824450e9164180baf491ae0078465",
745 "node": "97054abb4ab824450e9164180baf491ae0078465",
746 "branch": "default",
746 "branch": "default",
747 "phase": "draft",
747 "phase": "draft",
748 "user": "other@place",
748 "user": "other@place",
749 "date": [1200000, 0],
749 "date": [1200000, 0],
750 "desc": "no person",
750 "desc": "no person",
751 "bookmarks": [],
751 "bookmarks": [],
752 "tags": [],
752 "tags": [],
753 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
753 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
754 },
754 },
755 {
755 {
756 "rev": 1,
756 "rev": 1,
757 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
757 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
758 "branch": "default",
758 "branch": "default",
759 "phase": "draft",
759 "phase": "draft",
760 "user": "A. N. Other <other@place>",
760 "user": "A. N. Other <other@place>",
761 "date": [1100000, 0],
761 "date": [1100000, 0],
762 "desc": "other 1\nother 2\n\nother 3",
762 "desc": "other 1\nother 2\n\nother 3",
763 "bookmarks": [],
763 "bookmarks": [],
764 "tags": [],
764 "tags": [],
765 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
765 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
766 },
766 },
767 {
767 {
768 "rev": 0,
768 "rev": 0,
769 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
769 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
770 "branch": "default",
770 "branch": "default",
771 "phase": "draft",
771 "phase": "draft",
772 "user": "User Name <user@hostname>",
772 "user": "User Name <user@hostname>",
773 "date": [1000000, 0],
773 "date": [1000000, 0],
774 "desc": "line 1\nline 2",
774 "desc": "line 1\nline 2",
775 "bookmarks": [],
775 "bookmarks": [],
776 "tags": [],
776 "tags": [],
777 "parents": ["0000000000000000000000000000000000000000"]
777 "parents": ["0000000000000000000000000000000000000000"]
778 }
778 }
779 ]
779 ]
780
780
781 $ hg heads -v -Tjson
781 $ hg heads -v -Tjson
782 [
782 [
783 {
783 {
784 "rev": 8,
784 "rev": 8,
785 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
785 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
786 "branch": "default",
786 "branch": "default",
787 "phase": "draft",
787 "phase": "draft",
788 "user": "test",
788 "user": "test",
789 "date": [1577872860, 0],
789 "date": [1577872860, 0],
790 "desc": "third",
790 "desc": "third",
791 "bookmarks": [],
791 "bookmarks": [],
792 "tags": ["tip"],
792 "tags": ["tip"],
793 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
793 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
794 "files": ["fourth", "second", "third"]
794 "files": ["fourth", "second", "third"]
795 },
795 },
796 {
796 {
797 "rev": 6,
797 "rev": 6,
798 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
798 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
799 "branch": "default",
799 "branch": "default",
800 "phase": "draft",
800 "phase": "draft",
801 "user": "person",
801 "user": "person",
802 "date": [1500001, 0],
802 "date": [1500001, 0],
803 "desc": "merge",
803 "desc": "merge",
804 "bookmarks": [],
804 "bookmarks": [],
805 "tags": [],
805 "tags": [],
806 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
806 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
807 "files": []
807 "files": []
808 },
808 },
809 {
809 {
810 "rev": 4,
810 "rev": 4,
811 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
811 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
812 "branch": "foo",
812 "branch": "foo",
813 "phase": "draft",
813 "phase": "draft",
814 "user": "person",
814 "user": "person",
815 "date": [1400000, 0],
815 "date": [1400000, 0],
816 "desc": "new branch",
816 "desc": "new branch",
817 "bookmarks": [],
817 "bookmarks": [],
818 "tags": [],
818 "tags": [],
819 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
819 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
820 "files": []
820 "files": []
821 }
821 }
822 ]
822 ]
823
823
824 $ hg log --debug -Tjson
824 $ hg log --debug -Tjson
825 [
825 [
826 {
826 {
827 "rev": 8,
827 "rev": 8,
828 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
828 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
829 "branch": "default",
829 "branch": "default",
830 "phase": "draft",
830 "phase": "draft",
831 "user": "test",
831 "user": "test",
832 "date": [1577872860, 0],
832 "date": [1577872860, 0],
833 "desc": "third",
833 "desc": "third",
834 "bookmarks": [],
834 "bookmarks": [],
835 "tags": ["tip"],
835 "tags": ["tip"],
836 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
836 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
837 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
837 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
838 "extra": {"branch": "default"},
838 "extra": {"branch": "default"},
839 "modified": [],
839 "modified": [],
840 "added": ["fourth", "third"],
840 "added": ["fourth", "third"],
841 "removed": ["second"]
841 "removed": ["second"]
842 },
842 },
843 {
843 {
844 "rev": 7,
844 "rev": 7,
845 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
845 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
846 "branch": "default",
846 "branch": "default",
847 "phase": "draft",
847 "phase": "draft",
848 "user": "User Name <user@hostname>",
848 "user": "User Name <user@hostname>",
849 "date": [1000000, 0],
849 "date": [1000000, 0],
850 "desc": "second",
850 "desc": "second",
851 "bookmarks": [],
851 "bookmarks": [],
852 "tags": [],
852 "tags": [],
853 "parents": ["0000000000000000000000000000000000000000"],
853 "parents": ["0000000000000000000000000000000000000000"],
854 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
854 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
855 "extra": {"branch": "default"},
855 "extra": {"branch": "default"},
856 "modified": [],
856 "modified": [],
857 "added": ["second"],
857 "added": ["second"],
858 "removed": []
858 "removed": []
859 },
859 },
860 {
860 {
861 "rev": 6,
861 "rev": 6,
862 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
862 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
863 "branch": "default",
863 "branch": "default",
864 "phase": "draft",
864 "phase": "draft",
865 "user": "person",
865 "user": "person",
866 "date": [1500001, 0],
866 "date": [1500001, 0],
867 "desc": "merge",
867 "desc": "merge",
868 "bookmarks": [],
868 "bookmarks": [],
869 "tags": [],
869 "tags": [],
870 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
870 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
871 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
871 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
872 "extra": {"branch": "default"},
872 "extra": {"branch": "default"},
873 "modified": [],
873 "modified": [],
874 "added": [],
874 "added": [],
875 "removed": []
875 "removed": []
876 },
876 },
877 {
877 {
878 "rev": 5,
878 "rev": 5,
879 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
879 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
880 "branch": "default",
880 "branch": "default",
881 "phase": "draft",
881 "phase": "draft",
882 "user": "person",
882 "user": "person",
883 "date": [1500000, 0],
883 "date": [1500000, 0],
884 "desc": "new head",
884 "desc": "new head",
885 "bookmarks": [],
885 "bookmarks": [],
886 "tags": [],
886 "tags": [],
887 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
887 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
888 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
888 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
889 "extra": {"branch": "default"},
889 "extra": {"branch": "default"},
890 "modified": [],
890 "modified": [],
891 "added": ["d"],
891 "added": ["d"],
892 "removed": []
892 "removed": []
893 },
893 },
894 {
894 {
895 "rev": 4,
895 "rev": 4,
896 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
896 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
897 "branch": "foo",
897 "branch": "foo",
898 "phase": "draft",
898 "phase": "draft",
899 "user": "person",
899 "user": "person",
900 "date": [1400000, 0],
900 "date": [1400000, 0],
901 "desc": "new branch",
901 "desc": "new branch",
902 "bookmarks": [],
902 "bookmarks": [],
903 "tags": [],
903 "tags": [],
904 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
904 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
905 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
905 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
906 "extra": {"branch": "foo"},
906 "extra": {"branch": "foo"},
907 "modified": [],
907 "modified": [],
908 "added": [],
908 "added": [],
909 "removed": []
909 "removed": []
910 },
910 },
911 {
911 {
912 "rev": 3,
912 "rev": 3,
913 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
913 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
914 "branch": "default",
914 "branch": "default",
915 "phase": "draft",
915 "phase": "draft",
916 "user": "person",
916 "user": "person",
917 "date": [1300000, 0],
917 "date": [1300000, 0],
918 "desc": "no user, no domain",
918 "desc": "no user, no domain",
919 "bookmarks": [],
919 "bookmarks": [],
920 "tags": [],
920 "tags": [],
921 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
921 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
922 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
922 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
923 "extra": {"branch": "default"},
923 "extra": {"branch": "default"},
924 "modified": ["c"],
924 "modified": ["c"],
925 "added": [],
925 "added": [],
926 "removed": []
926 "removed": []
927 },
927 },
928 {
928 {
929 "rev": 2,
929 "rev": 2,
930 "node": "97054abb4ab824450e9164180baf491ae0078465",
930 "node": "97054abb4ab824450e9164180baf491ae0078465",
931 "branch": "default",
931 "branch": "default",
932 "phase": "draft",
932 "phase": "draft",
933 "user": "other@place",
933 "user": "other@place",
934 "date": [1200000, 0],
934 "date": [1200000, 0],
935 "desc": "no person",
935 "desc": "no person",
936 "bookmarks": [],
936 "bookmarks": [],
937 "tags": [],
937 "tags": [],
938 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
938 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
939 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
939 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
940 "extra": {"branch": "default"},
940 "extra": {"branch": "default"},
941 "modified": [],
941 "modified": [],
942 "added": ["c"],
942 "added": ["c"],
943 "removed": []
943 "removed": []
944 },
944 },
945 {
945 {
946 "rev": 1,
946 "rev": 1,
947 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
947 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
948 "branch": "default",
948 "branch": "default",
949 "phase": "draft",
949 "phase": "draft",
950 "user": "A. N. Other <other@place>",
950 "user": "A. N. Other <other@place>",
951 "date": [1100000, 0],
951 "date": [1100000, 0],
952 "desc": "other 1\nother 2\n\nother 3",
952 "desc": "other 1\nother 2\n\nother 3",
953 "bookmarks": [],
953 "bookmarks": [],
954 "tags": [],
954 "tags": [],
955 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
955 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
956 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
956 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
957 "extra": {"branch": "default"},
957 "extra": {"branch": "default"},
958 "modified": [],
958 "modified": [],
959 "added": ["b"],
959 "added": ["b"],
960 "removed": []
960 "removed": []
961 },
961 },
962 {
962 {
963 "rev": 0,
963 "rev": 0,
964 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
964 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
965 "branch": "default",
965 "branch": "default",
966 "phase": "draft",
966 "phase": "draft",
967 "user": "User Name <user@hostname>",
967 "user": "User Name <user@hostname>",
968 "date": [1000000, 0],
968 "date": [1000000, 0],
969 "desc": "line 1\nline 2",
969 "desc": "line 1\nline 2",
970 "bookmarks": [],
970 "bookmarks": [],
971 "tags": [],
971 "tags": [],
972 "parents": ["0000000000000000000000000000000000000000"],
972 "parents": ["0000000000000000000000000000000000000000"],
973 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
973 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
974 "extra": {"branch": "default"},
974 "extra": {"branch": "default"},
975 "modified": [],
975 "modified": [],
976 "added": ["a"],
976 "added": ["a"],
977 "removed": []
977 "removed": []
978 }
978 }
979 ]
979 ]
980
980
981 Error if style not readable:
981 Error if style not readable:
982
982
983 #if unix-permissions no-root
983 #if unix-permissions no-root
984 $ touch q
984 $ touch q
985 $ chmod 0 q
985 $ chmod 0 q
986 $ hg log --style ./q
986 $ hg log --style ./q
987 abort: Permission denied: ./q
987 abort: Permission denied: ./q
988 [255]
988 [255]
989 #endif
989 #endif
990
990
991 Error if no style:
991 Error if no style:
992
992
993 $ hg log --style notexist
993 $ hg log --style notexist
994 abort: style 'notexist' not found
994 abort: style 'notexist' not found
995 (available styles: bisect, changelog, compact, default, phases, status, xml)
995 (available styles: bisect, changelog, compact, default, phases, status, xml)
996 [255]
996 [255]
997
997
998 $ hg log -T list
998 $ hg log -T list
999 available styles: bisect, changelog, compact, default, phases, status, xml
999 available styles: bisect, changelog, compact, default, phases, status, xml
1000 abort: specify a template
1000 abort: specify a template
1001 [255]
1001 [255]
1002
1002
1003 Error if style missing key:
1003 Error if style missing key:
1004
1004
1005 $ echo 'q = q' > t
1005 $ echo 'q = q' > t
1006 $ hg log --style ./t
1006 $ hg log --style ./t
1007 abort: "changeset" not in template map
1007 abort: "changeset" not in template map
1008 [255]
1008 [255]
1009
1009
1010 Error if style missing value:
1010 Error if style missing value:
1011
1011
1012 $ echo 'changeset =' > t
1012 $ echo 'changeset =' > t
1013 $ hg log --style t
1013 $ hg log --style t
1014 abort: t:1: missing value
1014 abort: t:1: missing value
1015 [255]
1015 [255]
1016
1016
1017 Error if include fails:
1017 Error if include fails:
1018
1018
1019 $ echo 'changeset = q' >> t
1019 $ echo 'changeset = q' >> t
1020 #if unix-permissions no-root
1020 #if unix-permissions no-root
1021 $ hg log --style ./t
1021 $ hg log --style ./t
1022 abort: template file ./q: Permission denied
1022 abort: template file ./q: Permission denied
1023 [255]
1023 [255]
1024 $ rm q
1024 $ rm q
1025 #endif
1025 #endif
1026
1026
1027 Include works:
1027 Include works:
1028
1028
1029 $ echo '{rev}' > q
1029 $ echo '{rev}' > q
1030 $ hg log --style ./t
1030 $ hg log --style ./t
1031 8
1031 8
1032 7
1032 7
1033 6
1033 6
1034 5
1034 5
1035 4
1035 4
1036 3
1036 3
1037 2
1037 2
1038 1
1038 1
1039 0
1039 0
1040
1040
1041 Check that {phase} works correctly on parents:
1041 Check that {phase} works correctly on parents:
1042
1042
1043 $ cat << EOF > parentphase
1043 $ cat << EOF > parentphase
1044 > changeset_debug = '{rev} ({phase}):{parents}\n'
1044 > changeset_debug = '{rev} ({phase}):{parents}\n'
1045 > parent = ' {rev} ({phase})'
1045 > parent = ' {rev} ({phase})'
1046 > EOF
1046 > EOF
1047 $ hg phase -r 5 --public
1047 $ hg phase -r 5 --public
1048 $ hg phase -r 7 --secret --force
1048 $ hg phase -r 7 --secret --force
1049 $ hg log --debug -G --style ./parentphase
1049 $ hg log --debug -G --style ./parentphase
1050 @ 8 (secret): 7 (secret) -1 (public)
1050 @ 8 (secret): 7 (secret) -1 (public)
1051 |
1051 |
1052 o 7 (secret): -1 (public) -1 (public)
1052 o 7 (secret): -1 (public) -1 (public)
1053
1053
1054 o 6 (draft): 5 (public) 4 (draft)
1054 o 6 (draft): 5 (public) 4 (draft)
1055 |\
1055 |\
1056 | o 5 (public): 3 (public) -1 (public)
1056 | o 5 (public): 3 (public) -1 (public)
1057 | |
1057 | |
1058 o | 4 (draft): 3 (public) -1 (public)
1058 o | 4 (draft): 3 (public) -1 (public)
1059 |/
1059 |/
1060 o 3 (public): 2 (public) -1 (public)
1060 o 3 (public): 2 (public) -1 (public)
1061 |
1061 |
1062 o 2 (public): 1 (public) -1 (public)
1062 o 2 (public): 1 (public) -1 (public)
1063 |
1063 |
1064 o 1 (public): 0 (public) -1 (public)
1064 o 1 (public): 0 (public) -1 (public)
1065 |
1065 |
1066 o 0 (public): -1 (public) -1 (public)
1066 o 0 (public): -1 (public) -1 (public)
1067
1067
1068
1068
1069 Missing non-standard names give no error (backward compatibility):
1069 Missing non-standard names give no error (backward compatibility):
1070
1070
1071 $ echo "changeset = '{c}'" > t
1071 $ echo "changeset = '{c}'" > t
1072 $ hg log --style ./t
1072 $ hg log --style ./t
1073
1073
1074 Defining non-standard name works:
1074 Defining non-standard name works:
1075
1075
1076 $ cat <<EOF > t
1076 $ cat <<EOF > t
1077 > changeset = '{c}'
1077 > changeset = '{c}'
1078 > c = q
1078 > c = q
1079 > EOF
1079 > EOF
1080 $ hg log --style ./t
1080 $ hg log --style ./t
1081 8
1081 8
1082 7
1082 7
1083 6
1083 6
1084 5
1084 5
1085 4
1085 4
1086 3
1086 3
1087 2
1087 2
1088 1
1088 1
1089 0
1089 0
1090
1090
1091 ui.style works:
1091 ui.style works:
1092
1092
1093 $ echo '[ui]' > .hg/hgrc
1093 $ echo '[ui]' > .hg/hgrc
1094 $ echo 'style = t' >> .hg/hgrc
1094 $ echo 'style = t' >> .hg/hgrc
1095 $ hg log
1095 $ hg log
1096 8
1096 8
1097 7
1097 7
1098 6
1098 6
1099 5
1099 5
1100 4
1100 4
1101 3
1101 3
1102 2
1102 2
1103 1
1103 1
1104 0
1104 0
1105
1105
1106
1106
1107 Issue338:
1107 Issue338:
1108
1108
1109 $ hg log --style=changelog > changelog
1109 $ hg log --style=changelog > changelog
1110
1110
1111 $ cat changelog
1111 $ cat changelog
1112 2020-01-01 test <test>
1112 2020-01-01 test <test>
1113
1113
1114 * fourth, second, third:
1114 * fourth, second, third:
1115 third
1115 third
1116 [95c24699272e] [tip]
1116 [95c24699272e] [tip]
1117
1117
1118 1970-01-12 User Name <user@hostname>
1118 1970-01-12 User Name <user@hostname>
1119
1119
1120 * second:
1120 * second:
1121 second
1121 second
1122 [29114dbae42b]
1122 [29114dbae42b]
1123
1123
1124 1970-01-18 person <person>
1124 1970-01-18 person <person>
1125
1125
1126 * merge
1126 * merge
1127 [d41e714fe50d]
1127 [d41e714fe50d]
1128
1128
1129 * d:
1129 * d:
1130 new head
1130 new head
1131 [13207e5a10d9]
1131 [13207e5a10d9]
1132
1132
1133 1970-01-17 person <person>
1133 1970-01-17 person <person>
1134
1134
1135 * new branch
1135 * new branch
1136 [bbe44766e73d] <foo>
1136 [bbe44766e73d] <foo>
1137
1137
1138 1970-01-16 person <person>
1138 1970-01-16 person <person>
1139
1139
1140 * c:
1140 * c:
1141 no user, no domain
1141 no user, no domain
1142 [10e46f2dcbf4]
1142 [10e46f2dcbf4]
1143
1143
1144 1970-01-14 other <other@place>
1144 1970-01-14 other <other@place>
1145
1145
1146 * c:
1146 * c:
1147 no person
1147 no person
1148 [97054abb4ab8]
1148 [97054abb4ab8]
1149
1149
1150 1970-01-13 A. N. Other <other@place>
1150 1970-01-13 A. N. Other <other@place>
1151
1151
1152 * b:
1152 * b:
1153 other 1 other 2
1153 other 1 other 2
1154
1154
1155 other 3
1155 other 3
1156 [b608e9d1a3f0]
1156 [b608e9d1a3f0]
1157
1157
1158 1970-01-12 User Name <user@hostname>
1158 1970-01-12 User Name <user@hostname>
1159
1159
1160 * a:
1160 * a:
1161 line 1 line 2
1161 line 1 line 2
1162 [1e4e1b8f71e0]
1162 [1e4e1b8f71e0]
1163
1163
1164
1164
1165 Issue2130: xml output for 'hg heads' is malformed
1165 Issue2130: xml output for 'hg heads' is malformed
1166
1166
1167 $ hg heads --style changelog
1167 $ hg heads --style changelog
1168 2020-01-01 test <test>
1168 2020-01-01 test <test>
1169
1169
1170 * fourth, second, third:
1170 * fourth, second, third:
1171 third
1171 third
1172 [95c24699272e] [tip]
1172 [95c24699272e] [tip]
1173
1173
1174 1970-01-18 person <person>
1174 1970-01-18 person <person>
1175
1175
1176 * merge
1176 * merge
1177 [d41e714fe50d]
1177 [d41e714fe50d]
1178
1178
1179 1970-01-17 person <person>
1179 1970-01-17 person <person>
1180
1180
1181 * new branch
1181 * new branch
1182 [bbe44766e73d] <foo>
1182 [bbe44766e73d] <foo>
1183
1183
1184
1184
1185 Keys work:
1185 Keys work:
1186
1186
1187 $ for key in author branch branches date desc file_adds file_dels file_mods \
1187 $ for key in author branch branches date desc file_adds file_dels file_mods \
1188 > file_copies file_copies_switch files \
1188 > file_copies file_copies_switch files \
1189 > manifest node parents rev tags diffstat extras \
1189 > manifest node parents rev tags diffstat extras \
1190 > p1rev p2rev p1node p2node; do
1190 > p1rev p2rev p1node p2node; do
1191 > for mode in '' --verbose --debug; do
1191 > for mode in '' --verbose --debug; do
1192 > hg log $mode --template "$key$mode: {$key}\n"
1192 > hg log $mode --template "$key$mode: {$key}\n"
1193 > done
1193 > done
1194 > done
1194 > done
1195 author: test
1195 author: test
1196 author: User Name <user@hostname>
1196 author: User Name <user@hostname>
1197 author: person
1197 author: person
1198 author: person
1198 author: person
1199 author: person
1199 author: person
1200 author: person
1200 author: person
1201 author: other@place
1201 author: other@place
1202 author: A. N. Other <other@place>
1202 author: A. N. Other <other@place>
1203 author: User Name <user@hostname>
1203 author: User Name <user@hostname>
1204 author--verbose: test
1204 author--verbose: test
1205 author--verbose: User Name <user@hostname>
1205 author--verbose: User Name <user@hostname>
1206 author--verbose: person
1206 author--verbose: person
1207 author--verbose: person
1207 author--verbose: person
1208 author--verbose: person
1208 author--verbose: person
1209 author--verbose: person
1209 author--verbose: person
1210 author--verbose: other@place
1210 author--verbose: other@place
1211 author--verbose: A. N. Other <other@place>
1211 author--verbose: A. N. Other <other@place>
1212 author--verbose: User Name <user@hostname>
1212 author--verbose: User Name <user@hostname>
1213 author--debug: test
1213 author--debug: test
1214 author--debug: User Name <user@hostname>
1214 author--debug: User Name <user@hostname>
1215 author--debug: person
1215 author--debug: person
1216 author--debug: person
1216 author--debug: person
1217 author--debug: person
1217 author--debug: person
1218 author--debug: person
1218 author--debug: person
1219 author--debug: other@place
1219 author--debug: other@place
1220 author--debug: A. N. Other <other@place>
1220 author--debug: A. N. Other <other@place>
1221 author--debug: User Name <user@hostname>
1221 author--debug: User Name <user@hostname>
1222 branch: default
1222 branch: default
1223 branch: default
1223 branch: default
1224 branch: default
1224 branch: default
1225 branch: default
1225 branch: default
1226 branch: foo
1226 branch: foo
1227 branch: default
1227 branch: default
1228 branch: default
1228 branch: default
1229 branch: default
1229 branch: default
1230 branch: default
1230 branch: default
1231 branch--verbose: default
1231 branch--verbose: default
1232 branch--verbose: default
1232 branch--verbose: default
1233 branch--verbose: default
1233 branch--verbose: default
1234 branch--verbose: default
1234 branch--verbose: default
1235 branch--verbose: foo
1235 branch--verbose: foo
1236 branch--verbose: default
1236 branch--verbose: default
1237 branch--verbose: default
1237 branch--verbose: default
1238 branch--verbose: default
1238 branch--verbose: default
1239 branch--verbose: default
1239 branch--verbose: default
1240 branch--debug: default
1240 branch--debug: default
1241 branch--debug: default
1241 branch--debug: default
1242 branch--debug: default
1242 branch--debug: default
1243 branch--debug: default
1243 branch--debug: default
1244 branch--debug: foo
1244 branch--debug: foo
1245 branch--debug: default
1245 branch--debug: default
1246 branch--debug: default
1246 branch--debug: default
1247 branch--debug: default
1247 branch--debug: default
1248 branch--debug: default
1248 branch--debug: default
1249 branches:
1249 branches:
1250 branches:
1250 branches:
1251 branches:
1251 branches:
1252 branches:
1252 branches:
1253 branches: foo
1253 branches: foo
1254 branches:
1254 branches:
1255 branches:
1255 branches:
1256 branches:
1256 branches:
1257 branches:
1257 branches:
1258 branches--verbose:
1258 branches--verbose:
1259 branches--verbose:
1259 branches--verbose:
1260 branches--verbose:
1260 branches--verbose:
1261 branches--verbose:
1261 branches--verbose:
1262 branches--verbose: foo
1262 branches--verbose: foo
1263 branches--verbose:
1263 branches--verbose:
1264 branches--verbose:
1264 branches--verbose:
1265 branches--verbose:
1265 branches--verbose:
1266 branches--verbose:
1266 branches--verbose:
1267 branches--debug:
1267 branches--debug:
1268 branches--debug:
1268 branches--debug:
1269 branches--debug:
1269 branches--debug:
1270 branches--debug:
1270 branches--debug:
1271 branches--debug: foo
1271 branches--debug: foo
1272 branches--debug:
1272 branches--debug:
1273 branches--debug:
1273 branches--debug:
1274 branches--debug:
1274 branches--debug:
1275 branches--debug:
1275 branches--debug:
1276 date: 1577872860.00
1276 date: 1577872860.00
1277 date: 1000000.00
1277 date: 1000000.00
1278 date: 1500001.00
1278 date: 1500001.00
1279 date: 1500000.00
1279 date: 1500000.00
1280 date: 1400000.00
1280 date: 1400000.00
1281 date: 1300000.00
1281 date: 1300000.00
1282 date: 1200000.00
1282 date: 1200000.00
1283 date: 1100000.00
1283 date: 1100000.00
1284 date: 1000000.00
1284 date: 1000000.00
1285 date--verbose: 1577872860.00
1285 date--verbose: 1577872860.00
1286 date--verbose: 1000000.00
1286 date--verbose: 1000000.00
1287 date--verbose: 1500001.00
1287 date--verbose: 1500001.00
1288 date--verbose: 1500000.00
1288 date--verbose: 1500000.00
1289 date--verbose: 1400000.00
1289 date--verbose: 1400000.00
1290 date--verbose: 1300000.00
1290 date--verbose: 1300000.00
1291 date--verbose: 1200000.00
1291 date--verbose: 1200000.00
1292 date--verbose: 1100000.00
1292 date--verbose: 1100000.00
1293 date--verbose: 1000000.00
1293 date--verbose: 1000000.00
1294 date--debug: 1577872860.00
1294 date--debug: 1577872860.00
1295 date--debug: 1000000.00
1295 date--debug: 1000000.00
1296 date--debug: 1500001.00
1296 date--debug: 1500001.00
1297 date--debug: 1500000.00
1297 date--debug: 1500000.00
1298 date--debug: 1400000.00
1298 date--debug: 1400000.00
1299 date--debug: 1300000.00
1299 date--debug: 1300000.00
1300 date--debug: 1200000.00
1300 date--debug: 1200000.00
1301 date--debug: 1100000.00
1301 date--debug: 1100000.00
1302 date--debug: 1000000.00
1302 date--debug: 1000000.00
1303 desc: third
1303 desc: third
1304 desc: second
1304 desc: second
1305 desc: merge
1305 desc: merge
1306 desc: new head
1306 desc: new head
1307 desc: new branch
1307 desc: new branch
1308 desc: no user, no domain
1308 desc: no user, no domain
1309 desc: no person
1309 desc: no person
1310 desc: other 1
1310 desc: other 1
1311 other 2
1311 other 2
1312
1312
1313 other 3
1313 other 3
1314 desc: line 1
1314 desc: line 1
1315 line 2
1315 line 2
1316 desc--verbose: third
1316 desc--verbose: third
1317 desc--verbose: second
1317 desc--verbose: second
1318 desc--verbose: merge
1318 desc--verbose: merge
1319 desc--verbose: new head
1319 desc--verbose: new head
1320 desc--verbose: new branch
1320 desc--verbose: new branch
1321 desc--verbose: no user, no domain
1321 desc--verbose: no user, no domain
1322 desc--verbose: no person
1322 desc--verbose: no person
1323 desc--verbose: other 1
1323 desc--verbose: other 1
1324 other 2
1324 other 2
1325
1325
1326 other 3
1326 other 3
1327 desc--verbose: line 1
1327 desc--verbose: line 1
1328 line 2
1328 line 2
1329 desc--debug: third
1329 desc--debug: third
1330 desc--debug: second
1330 desc--debug: second
1331 desc--debug: merge
1331 desc--debug: merge
1332 desc--debug: new head
1332 desc--debug: new head
1333 desc--debug: new branch
1333 desc--debug: new branch
1334 desc--debug: no user, no domain
1334 desc--debug: no user, no domain
1335 desc--debug: no person
1335 desc--debug: no person
1336 desc--debug: other 1
1336 desc--debug: other 1
1337 other 2
1337 other 2
1338
1338
1339 other 3
1339 other 3
1340 desc--debug: line 1
1340 desc--debug: line 1
1341 line 2
1341 line 2
1342 file_adds: fourth third
1342 file_adds: fourth third
1343 file_adds: second
1343 file_adds: second
1344 file_adds:
1344 file_adds:
1345 file_adds: d
1345 file_adds: d
1346 file_adds:
1346 file_adds:
1347 file_adds:
1347 file_adds:
1348 file_adds: c
1348 file_adds: c
1349 file_adds: b
1349 file_adds: b
1350 file_adds: a
1350 file_adds: a
1351 file_adds--verbose: fourth third
1351 file_adds--verbose: fourth third
1352 file_adds--verbose: second
1352 file_adds--verbose: second
1353 file_adds--verbose:
1353 file_adds--verbose:
1354 file_adds--verbose: d
1354 file_adds--verbose: d
1355 file_adds--verbose:
1355 file_adds--verbose:
1356 file_adds--verbose:
1356 file_adds--verbose:
1357 file_adds--verbose: c
1357 file_adds--verbose: c
1358 file_adds--verbose: b
1358 file_adds--verbose: b
1359 file_adds--verbose: a
1359 file_adds--verbose: a
1360 file_adds--debug: fourth third
1360 file_adds--debug: fourth third
1361 file_adds--debug: second
1361 file_adds--debug: second
1362 file_adds--debug:
1362 file_adds--debug:
1363 file_adds--debug: d
1363 file_adds--debug: d
1364 file_adds--debug:
1364 file_adds--debug:
1365 file_adds--debug:
1365 file_adds--debug:
1366 file_adds--debug: c
1366 file_adds--debug: c
1367 file_adds--debug: b
1367 file_adds--debug: b
1368 file_adds--debug: a
1368 file_adds--debug: a
1369 file_dels: second
1369 file_dels: second
1370 file_dels:
1370 file_dels:
1371 file_dels:
1371 file_dels:
1372 file_dels:
1372 file_dels:
1373 file_dels:
1373 file_dels:
1374 file_dels:
1374 file_dels:
1375 file_dels:
1375 file_dels:
1376 file_dels:
1376 file_dels:
1377 file_dels:
1377 file_dels:
1378 file_dels--verbose: second
1378 file_dels--verbose: second
1379 file_dels--verbose:
1379 file_dels--verbose:
1380 file_dels--verbose:
1380 file_dels--verbose:
1381 file_dels--verbose:
1381 file_dels--verbose:
1382 file_dels--verbose:
1382 file_dels--verbose:
1383 file_dels--verbose:
1383 file_dels--verbose:
1384 file_dels--verbose:
1384 file_dels--verbose:
1385 file_dels--verbose:
1385 file_dels--verbose:
1386 file_dels--verbose:
1386 file_dels--verbose:
1387 file_dels--debug: second
1387 file_dels--debug: second
1388 file_dels--debug:
1388 file_dels--debug:
1389 file_dels--debug:
1389 file_dels--debug:
1390 file_dels--debug:
1390 file_dels--debug:
1391 file_dels--debug:
1391 file_dels--debug:
1392 file_dels--debug:
1392 file_dels--debug:
1393 file_dels--debug:
1393 file_dels--debug:
1394 file_dels--debug:
1394 file_dels--debug:
1395 file_dels--debug:
1395 file_dels--debug:
1396 file_mods:
1396 file_mods:
1397 file_mods:
1397 file_mods:
1398 file_mods:
1398 file_mods:
1399 file_mods:
1399 file_mods:
1400 file_mods:
1400 file_mods:
1401 file_mods: c
1401 file_mods: c
1402 file_mods:
1402 file_mods:
1403 file_mods:
1403 file_mods:
1404 file_mods:
1404 file_mods:
1405 file_mods--verbose:
1405 file_mods--verbose:
1406 file_mods--verbose:
1406 file_mods--verbose:
1407 file_mods--verbose:
1407 file_mods--verbose:
1408 file_mods--verbose:
1408 file_mods--verbose:
1409 file_mods--verbose:
1409 file_mods--verbose:
1410 file_mods--verbose: c
1410 file_mods--verbose: c
1411 file_mods--verbose:
1411 file_mods--verbose:
1412 file_mods--verbose:
1412 file_mods--verbose:
1413 file_mods--verbose:
1413 file_mods--verbose:
1414 file_mods--debug:
1414 file_mods--debug:
1415 file_mods--debug:
1415 file_mods--debug:
1416 file_mods--debug:
1416 file_mods--debug:
1417 file_mods--debug:
1417 file_mods--debug:
1418 file_mods--debug:
1418 file_mods--debug:
1419 file_mods--debug: c
1419 file_mods--debug: c
1420 file_mods--debug:
1420 file_mods--debug:
1421 file_mods--debug:
1421 file_mods--debug:
1422 file_mods--debug:
1422 file_mods--debug:
1423 file_copies: fourth (second)
1423 file_copies: fourth (second)
1424 file_copies:
1424 file_copies:
1425 file_copies:
1425 file_copies:
1426 file_copies:
1426 file_copies:
1427 file_copies:
1427 file_copies:
1428 file_copies:
1428 file_copies:
1429 file_copies:
1429 file_copies:
1430 file_copies:
1430 file_copies:
1431 file_copies:
1431 file_copies:
1432 file_copies--verbose: fourth (second)
1432 file_copies--verbose: fourth (second)
1433 file_copies--verbose:
1433 file_copies--verbose:
1434 file_copies--verbose:
1434 file_copies--verbose:
1435 file_copies--verbose:
1435 file_copies--verbose:
1436 file_copies--verbose:
1436 file_copies--verbose:
1437 file_copies--verbose:
1437 file_copies--verbose:
1438 file_copies--verbose:
1438 file_copies--verbose:
1439 file_copies--verbose:
1439 file_copies--verbose:
1440 file_copies--verbose:
1440 file_copies--verbose:
1441 file_copies--debug: fourth (second)
1441 file_copies--debug: fourth (second)
1442 file_copies--debug:
1442 file_copies--debug:
1443 file_copies--debug:
1443 file_copies--debug:
1444 file_copies--debug:
1444 file_copies--debug:
1445 file_copies--debug:
1445 file_copies--debug:
1446 file_copies--debug:
1446 file_copies--debug:
1447 file_copies--debug:
1447 file_copies--debug:
1448 file_copies--debug:
1448 file_copies--debug:
1449 file_copies--debug:
1449 file_copies--debug:
1450 file_copies_switch:
1450 file_copies_switch:
1451 file_copies_switch:
1451 file_copies_switch:
1452 file_copies_switch:
1452 file_copies_switch:
1453 file_copies_switch:
1453 file_copies_switch:
1454 file_copies_switch:
1454 file_copies_switch:
1455 file_copies_switch:
1455 file_copies_switch:
1456 file_copies_switch:
1456 file_copies_switch:
1457 file_copies_switch:
1457 file_copies_switch:
1458 file_copies_switch:
1458 file_copies_switch:
1459 file_copies_switch--verbose:
1459 file_copies_switch--verbose:
1460 file_copies_switch--verbose:
1460 file_copies_switch--verbose:
1461 file_copies_switch--verbose:
1461 file_copies_switch--verbose:
1462 file_copies_switch--verbose:
1462 file_copies_switch--verbose:
1463 file_copies_switch--verbose:
1463 file_copies_switch--verbose:
1464 file_copies_switch--verbose:
1464 file_copies_switch--verbose:
1465 file_copies_switch--verbose:
1465 file_copies_switch--verbose:
1466 file_copies_switch--verbose:
1466 file_copies_switch--verbose:
1467 file_copies_switch--verbose:
1467 file_copies_switch--verbose:
1468 file_copies_switch--debug:
1468 file_copies_switch--debug:
1469 file_copies_switch--debug:
1469 file_copies_switch--debug:
1470 file_copies_switch--debug:
1470 file_copies_switch--debug:
1471 file_copies_switch--debug:
1471 file_copies_switch--debug:
1472 file_copies_switch--debug:
1472 file_copies_switch--debug:
1473 file_copies_switch--debug:
1473 file_copies_switch--debug:
1474 file_copies_switch--debug:
1474 file_copies_switch--debug:
1475 file_copies_switch--debug:
1475 file_copies_switch--debug:
1476 file_copies_switch--debug:
1476 file_copies_switch--debug:
1477 files: fourth second third
1477 files: fourth second third
1478 files: second
1478 files: second
1479 files:
1479 files:
1480 files: d
1480 files: d
1481 files:
1481 files:
1482 files: c
1482 files: c
1483 files: c
1483 files: c
1484 files: b
1484 files: b
1485 files: a
1485 files: a
1486 files--verbose: fourth second third
1486 files--verbose: fourth second third
1487 files--verbose: second
1487 files--verbose: second
1488 files--verbose:
1488 files--verbose:
1489 files--verbose: d
1489 files--verbose: d
1490 files--verbose:
1490 files--verbose:
1491 files--verbose: c
1491 files--verbose: c
1492 files--verbose: c
1492 files--verbose: c
1493 files--verbose: b
1493 files--verbose: b
1494 files--verbose: a
1494 files--verbose: a
1495 files--debug: fourth second third
1495 files--debug: fourth second third
1496 files--debug: second
1496 files--debug: second
1497 files--debug:
1497 files--debug:
1498 files--debug: d
1498 files--debug: d
1499 files--debug:
1499 files--debug:
1500 files--debug: c
1500 files--debug: c
1501 files--debug: c
1501 files--debug: c
1502 files--debug: b
1502 files--debug: b
1503 files--debug: a
1503 files--debug: a
1504 manifest: 6:94961b75a2da
1504 manifest: 6:94961b75a2da
1505 manifest: 5:f2dbc354b94e
1505 manifest: 5:f2dbc354b94e
1506 manifest: 4:4dc3def4f9b4
1506 manifest: 4:4dc3def4f9b4
1507 manifest: 4:4dc3def4f9b4
1507 manifest: 4:4dc3def4f9b4
1508 manifest: 3:cb5a1327723b
1508 manifest: 3:cb5a1327723b
1509 manifest: 3:cb5a1327723b
1509 manifest: 3:cb5a1327723b
1510 manifest: 2:6e0e82995c35
1510 manifest: 2:6e0e82995c35
1511 manifest: 1:4e8d705b1e53
1511 manifest: 1:4e8d705b1e53
1512 manifest: 0:a0c8bcbbb45c
1512 manifest: 0:a0c8bcbbb45c
1513 manifest--verbose: 6:94961b75a2da
1513 manifest--verbose: 6:94961b75a2da
1514 manifest--verbose: 5:f2dbc354b94e
1514 manifest--verbose: 5:f2dbc354b94e
1515 manifest--verbose: 4:4dc3def4f9b4
1515 manifest--verbose: 4:4dc3def4f9b4
1516 manifest--verbose: 4:4dc3def4f9b4
1516 manifest--verbose: 4:4dc3def4f9b4
1517 manifest--verbose: 3:cb5a1327723b
1517 manifest--verbose: 3:cb5a1327723b
1518 manifest--verbose: 3:cb5a1327723b
1518 manifest--verbose: 3:cb5a1327723b
1519 manifest--verbose: 2:6e0e82995c35
1519 manifest--verbose: 2:6e0e82995c35
1520 manifest--verbose: 1:4e8d705b1e53
1520 manifest--verbose: 1:4e8d705b1e53
1521 manifest--verbose: 0:a0c8bcbbb45c
1521 manifest--verbose: 0:a0c8bcbbb45c
1522 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1522 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1523 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1523 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1524 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1524 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1525 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1525 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1526 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1526 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1527 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1527 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1528 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1528 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1529 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1529 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1530 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1530 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1531 node: 95c24699272ef57d062b8bccc32c878bf841784a
1531 node: 95c24699272ef57d062b8bccc32c878bf841784a
1532 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1532 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1533 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1533 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1534 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1534 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1535 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1535 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1536 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1536 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1537 node: 97054abb4ab824450e9164180baf491ae0078465
1537 node: 97054abb4ab824450e9164180baf491ae0078465
1538 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1538 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1539 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1539 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1540 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1540 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1541 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1541 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1542 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1542 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1543 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1543 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1544 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1544 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1545 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1545 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1546 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1546 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1547 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1547 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1548 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1548 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1549 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1549 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1550 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1550 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1551 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1551 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1552 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1552 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1553 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1553 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1554 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1554 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1555 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1555 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1556 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1556 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1557 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1557 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1558 parents:
1558 parents:
1559 parents: -1:000000000000
1559 parents: -1:000000000000
1560 parents: 5:13207e5a10d9 4:bbe44766e73d
1560 parents: 5:13207e5a10d9 4:bbe44766e73d
1561 parents: 3:10e46f2dcbf4
1561 parents: 3:10e46f2dcbf4
1562 parents:
1562 parents:
1563 parents:
1563 parents:
1564 parents:
1564 parents:
1565 parents:
1565 parents:
1566 parents:
1566 parents:
1567 parents--verbose:
1567 parents--verbose:
1568 parents--verbose: -1:000000000000
1568 parents--verbose: -1:000000000000
1569 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1569 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1570 parents--verbose: 3:10e46f2dcbf4
1570 parents--verbose: 3:10e46f2dcbf4
1571 parents--verbose:
1571 parents--verbose:
1572 parents--verbose:
1572 parents--verbose:
1573 parents--verbose:
1573 parents--verbose:
1574 parents--verbose:
1574 parents--verbose:
1575 parents--verbose:
1575 parents--verbose:
1576 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1576 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1577 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1577 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1578 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1578 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1579 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1579 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1580 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1580 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1581 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1581 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1582 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1582 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1583 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1583 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1584 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1584 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1585 rev: 8
1585 rev: 8
1586 rev: 7
1586 rev: 7
1587 rev: 6
1587 rev: 6
1588 rev: 5
1588 rev: 5
1589 rev: 4
1589 rev: 4
1590 rev: 3
1590 rev: 3
1591 rev: 2
1591 rev: 2
1592 rev: 1
1592 rev: 1
1593 rev: 0
1593 rev: 0
1594 rev--verbose: 8
1594 rev--verbose: 8
1595 rev--verbose: 7
1595 rev--verbose: 7
1596 rev--verbose: 6
1596 rev--verbose: 6
1597 rev--verbose: 5
1597 rev--verbose: 5
1598 rev--verbose: 4
1598 rev--verbose: 4
1599 rev--verbose: 3
1599 rev--verbose: 3
1600 rev--verbose: 2
1600 rev--verbose: 2
1601 rev--verbose: 1
1601 rev--verbose: 1
1602 rev--verbose: 0
1602 rev--verbose: 0
1603 rev--debug: 8
1603 rev--debug: 8
1604 rev--debug: 7
1604 rev--debug: 7
1605 rev--debug: 6
1605 rev--debug: 6
1606 rev--debug: 5
1606 rev--debug: 5
1607 rev--debug: 4
1607 rev--debug: 4
1608 rev--debug: 3
1608 rev--debug: 3
1609 rev--debug: 2
1609 rev--debug: 2
1610 rev--debug: 1
1610 rev--debug: 1
1611 rev--debug: 0
1611 rev--debug: 0
1612 tags: tip
1612 tags: tip
1613 tags:
1613 tags:
1614 tags:
1614 tags:
1615 tags:
1615 tags:
1616 tags:
1616 tags:
1617 tags:
1617 tags:
1618 tags:
1618 tags:
1619 tags:
1619 tags:
1620 tags:
1620 tags:
1621 tags--verbose: tip
1621 tags--verbose: tip
1622 tags--verbose:
1622 tags--verbose:
1623 tags--verbose:
1623 tags--verbose:
1624 tags--verbose:
1624 tags--verbose:
1625 tags--verbose:
1625 tags--verbose:
1626 tags--verbose:
1626 tags--verbose:
1627 tags--verbose:
1627 tags--verbose:
1628 tags--verbose:
1628 tags--verbose:
1629 tags--verbose:
1629 tags--verbose:
1630 tags--debug: tip
1630 tags--debug: tip
1631 tags--debug:
1631 tags--debug:
1632 tags--debug:
1632 tags--debug:
1633 tags--debug:
1633 tags--debug:
1634 tags--debug:
1634 tags--debug:
1635 tags--debug:
1635 tags--debug:
1636 tags--debug:
1636 tags--debug:
1637 tags--debug:
1637 tags--debug:
1638 tags--debug:
1638 tags--debug:
1639 diffstat: 3: +2/-1
1639 diffstat: 3: +2/-1
1640 diffstat: 1: +1/-0
1640 diffstat: 1: +1/-0
1641 diffstat: 0: +0/-0
1641 diffstat: 0: +0/-0
1642 diffstat: 1: +1/-0
1642 diffstat: 1: +1/-0
1643 diffstat: 0: +0/-0
1643 diffstat: 0: +0/-0
1644 diffstat: 1: +1/-0
1644 diffstat: 1: +1/-0
1645 diffstat: 1: +4/-0
1645 diffstat: 1: +4/-0
1646 diffstat: 1: +2/-0
1646 diffstat: 1: +2/-0
1647 diffstat: 1: +1/-0
1647 diffstat: 1: +1/-0
1648 diffstat--verbose: 3: +2/-1
1648 diffstat--verbose: 3: +2/-1
1649 diffstat--verbose: 1: +1/-0
1649 diffstat--verbose: 1: +1/-0
1650 diffstat--verbose: 0: +0/-0
1650 diffstat--verbose: 0: +0/-0
1651 diffstat--verbose: 1: +1/-0
1651 diffstat--verbose: 1: +1/-0
1652 diffstat--verbose: 0: +0/-0
1652 diffstat--verbose: 0: +0/-0
1653 diffstat--verbose: 1: +1/-0
1653 diffstat--verbose: 1: +1/-0
1654 diffstat--verbose: 1: +4/-0
1654 diffstat--verbose: 1: +4/-0
1655 diffstat--verbose: 1: +2/-0
1655 diffstat--verbose: 1: +2/-0
1656 diffstat--verbose: 1: +1/-0
1656 diffstat--verbose: 1: +1/-0
1657 diffstat--debug: 3: +2/-1
1657 diffstat--debug: 3: +2/-1
1658 diffstat--debug: 1: +1/-0
1658 diffstat--debug: 1: +1/-0
1659 diffstat--debug: 0: +0/-0
1659 diffstat--debug: 0: +0/-0
1660 diffstat--debug: 1: +1/-0
1660 diffstat--debug: 1: +1/-0
1661 diffstat--debug: 0: +0/-0
1661 diffstat--debug: 0: +0/-0
1662 diffstat--debug: 1: +1/-0
1662 diffstat--debug: 1: +1/-0
1663 diffstat--debug: 1: +4/-0
1663 diffstat--debug: 1: +4/-0
1664 diffstat--debug: 1: +2/-0
1664 diffstat--debug: 1: +2/-0
1665 diffstat--debug: 1: +1/-0
1665 diffstat--debug: 1: +1/-0
1666 extras: branch=default
1666 extras: branch=default
1667 extras: branch=default
1667 extras: branch=default
1668 extras: branch=default
1668 extras: branch=default
1669 extras: branch=default
1669 extras: branch=default
1670 extras: branch=foo
1670 extras: branch=foo
1671 extras: branch=default
1671 extras: branch=default
1672 extras: branch=default
1672 extras: branch=default
1673 extras: branch=default
1673 extras: branch=default
1674 extras: branch=default
1674 extras: branch=default
1675 extras--verbose: branch=default
1675 extras--verbose: branch=default
1676 extras--verbose: branch=default
1676 extras--verbose: branch=default
1677 extras--verbose: branch=default
1677 extras--verbose: branch=default
1678 extras--verbose: branch=default
1678 extras--verbose: branch=default
1679 extras--verbose: branch=foo
1679 extras--verbose: branch=foo
1680 extras--verbose: branch=default
1680 extras--verbose: branch=default
1681 extras--verbose: branch=default
1681 extras--verbose: branch=default
1682 extras--verbose: branch=default
1682 extras--verbose: branch=default
1683 extras--verbose: branch=default
1683 extras--verbose: branch=default
1684 extras--debug: branch=default
1684 extras--debug: branch=default
1685 extras--debug: branch=default
1685 extras--debug: branch=default
1686 extras--debug: branch=default
1686 extras--debug: branch=default
1687 extras--debug: branch=default
1687 extras--debug: branch=default
1688 extras--debug: branch=foo
1688 extras--debug: branch=foo
1689 extras--debug: branch=default
1689 extras--debug: branch=default
1690 extras--debug: branch=default
1690 extras--debug: branch=default
1691 extras--debug: branch=default
1691 extras--debug: branch=default
1692 extras--debug: branch=default
1692 extras--debug: branch=default
1693 p1rev: 7
1693 p1rev: 7
1694 p1rev: -1
1694 p1rev: -1
1695 p1rev: 5
1695 p1rev: 5
1696 p1rev: 3
1696 p1rev: 3
1697 p1rev: 3
1697 p1rev: 3
1698 p1rev: 2
1698 p1rev: 2
1699 p1rev: 1
1699 p1rev: 1
1700 p1rev: 0
1700 p1rev: 0
1701 p1rev: -1
1701 p1rev: -1
1702 p1rev--verbose: 7
1702 p1rev--verbose: 7
1703 p1rev--verbose: -1
1703 p1rev--verbose: -1
1704 p1rev--verbose: 5
1704 p1rev--verbose: 5
1705 p1rev--verbose: 3
1705 p1rev--verbose: 3
1706 p1rev--verbose: 3
1706 p1rev--verbose: 3
1707 p1rev--verbose: 2
1707 p1rev--verbose: 2
1708 p1rev--verbose: 1
1708 p1rev--verbose: 1
1709 p1rev--verbose: 0
1709 p1rev--verbose: 0
1710 p1rev--verbose: -1
1710 p1rev--verbose: -1
1711 p1rev--debug: 7
1711 p1rev--debug: 7
1712 p1rev--debug: -1
1712 p1rev--debug: -1
1713 p1rev--debug: 5
1713 p1rev--debug: 5
1714 p1rev--debug: 3
1714 p1rev--debug: 3
1715 p1rev--debug: 3
1715 p1rev--debug: 3
1716 p1rev--debug: 2
1716 p1rev--debug: 2
1717 p1rev--debug: 1
1717 p1rev--debug: 1
1718 p1rev--debug: 0
1718 p1rev--debug: 0
1719 p1rev--debug: -1
1719 p1rev--debug: -1
1720 p2rev: -1
1720 p2rev: -1
1721 p2rev: -1
1721 p2rev: -1
1722 p2rev: 4
1722 p2rev: 4
1723 p2rev: -1
1723 p2rev: -1
1724 p2rev: -1
1724 p2rev: -1
1725 p2rev: -1
1725 p2rev: -1
1726 p2rev: -1
1726 p2rev: -1
1727 p2rev: -1
1727 p2rev: -1
1728 p2rev: -1
1728 p2rev: -1
1729 p2rev--verbose: -1
1729 p2rev--verbose: -1
1730 p2rev--verbose: -1
1730 p2rev--verbose: -1
1731 p2rev--verbose: 4
1731 p2rev--verbose: 4
1732 p2rev--verbose: -1
1732 p2rev--verbose: -1
1733 p2rev--verbose: -1
1733 p2rev--verbose: -1
1734 p2rev--verbose: -1
1734 p2rev--verbose: -1
1735 p2rev--verbose: -1
1735 p2rev--verbose: -1
1736 p2rev--verbose: -1
1736 p2rev--verbose: -1
1737 p2rev--verbose: -1
1737 p2rev--verbose: -1
1738 p2rev--debug: -1
1738 p2rev--debug: -1
1739 p2rev--debug: -1
1739 p2rev--debug: -1
1740 p2rev--debug: 4
1740 p2rev--debug: 4
1741 p2rev--debug: -1
1741 p2rev--debug: -1
1742 p2rev--debug: -1
1742 p2rev--debug: -1
1743 p2rev--debug: -1
1743 p2rev--debug: -1
1744 p2rev--debug: -1
1744 p2rev--debug: -1
1745 p2rev--debug: -1
1745 p2rev--debug: -1
1746 p2rev--debug: -1
1746 p2rev--debug: -1
1747 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1747 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1748 p1node: 0000000000000000000000000000000000000000
1748 p1node: 0000000000000000000000000000000000000000
1749 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1749 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1750 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1750 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1751 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1751 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1752 p1node: 97054abb4ab824450e9164180baf491ae0078465
1752 p1node: 97054abb4ab824450e9164180baf491ae0078465
1753 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1753 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1754 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1754 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1755 p1node: 0000000000000000000000000000000000000000
1755 p1node: 0000000000000000000000000000000000000000
1756 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1756 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1757 p1node--verbose: 0000000000000000000000000000000000000000
1757 p1node--verbose: 0000000000000000000000000000000000000000
1758 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1758 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1759 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1759 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1760 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1760 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1761 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1761 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1762 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1762 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1763 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1763 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1764 p1node--verbose: 0000000000000000000000000000000000000000
1764 p1node--verbose: 0000000000000000000000000000000000000000
1765 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1765 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1766 p1node--debug: 0000000000000000000000000000000000000000
1766 p1node--debug: 0000000000000000000000000000000000000000
1767 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1767 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1768 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1768 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1769 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1769 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1770 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1770 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1771 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1771 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1772 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1772 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1773 p1node--debug: 0000000000000000000000000000000000000000
1773 p1node--debug: 0000000000000000000000000000000000000000
1774 p2node: 0000000000000000000000000000000000000000
1774 p2node: 0000000000000000000000000000000000000000
1775 p2node: 0000000000000000000000000000000000000000
1775 p2node: 0000000000000000000000000000000000000000
1776 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1776 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1777 p2node: 0000000000000000000000000000000000000000
1777 p2node: 0000000000000000000000000000000000000000
1778 p2node: 0000000000000000000000000000000000000000
1778 p2node: 0000000000000000000000000000000000000000
1779 p2node: 0000000000000000000000000000000000000000
1779 p2node: 0000000000000000000000000000000000000000
1780 p2node: 0000000000000000000000000000000000000000
1780 p2node: 0000000000000000000000000000000000000000
1781 p2node: 0000000000000000000000000000000000000000
1781 p2node: 0000000000000000000000000000000000000000
1782 p2node: 0000000000000000000000000000000000000000
1782 p2node: 0000000000000000000000000000000000000000
1783 p2node--verbose: 0000000000000000000000000000000000000000
1783 p2node--verbose: 0000000000000000000000000000000000000000
1784 p2node--verbose: 0000000000000000000000000000000000000000
1784 p2node--verbose: 0000000000000000000000000000000000000000
1785 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1785 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1786 p2node--verbose: 0000000000000000000000000000000000000000
1786 p2node--verbose: 0000000000000000000000000000000000000000
1787 p2node--verbose: 0000000000000000000000000000000000000000
1787 p2node--verbose: 0000000000000000000000000000000000000000
1788 p2node--verbose: 0000000000000000000000000000000000000000
1788 p2node--verbose: 0000000000000000000000000000000000000000
1789 p2node--verbose: 0000000000000000000000000000000000000000
1789 p2node--verbose: 0000000000000000000000000000000000000000
1790 p2node--verbose: 0000000000000000000000000000000000000000
1790 p2node--verbose: 0000000000000000000000000000000000000000
1791 p2node--verbose: 0000000000000000000000000000000000000000
1791 p2node--verbose: 0000000000000000000000000000000000000000
1792 p2node--debug: 0000000000000000000000000000000000000000
1792 p2node--debug: 0000000000000000000000000000000000000000
1793 p2node--debug: 0000000000000000000000000000000000000000
1793 p2node--debug: 0000000000000000000000000000000000000000
1794 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1794 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1795 p2node--debug: 0000000000000000000000000000000000000000
1795 p2node--debug: 0000000000000000000000000000000000000000
1796 p2node--debug: 0000000000000000000000000000000000000000
1796 p2node--debug: 0000000000000000000000000000000000000000
1797 p2node--debug: 0000000000000000000000000000000000000000
1797 p2node--debug: 0000000000000000000000000000000000000000
1798 p2node--debug: 0000000000000000000000000000000000000000
1798 p2node--debug: 0000000000000000000000000000000000000000
1799 p2node--debug: 0000000000000000000000000000000000000000
1799 p2node--debug: 0000000000000000000000000000000000000000
1800 p2node--debug: 0000000000000000000000000000000000000000
1800 p2node--debug: 0000000000000000000000000000000000000000
1801
1801
1802 Filters work:
1802 Filters work:
1803
1803
1804 $ hg log --template '{author|domain}\n'
1804 $ hg log --template '{author|domain}\n'
1805
1805
1806 hostname
1806 hostname
1807
1807
1808
1808
1809
1809
1810
1810
1811 place
1811 place
1812 place
1812 place
1813 hostname
1813 hostname
1814
1814
1815 $ hg log --template '{author|person}\n'
1815 $ hg log --template '{author|person}\n'
1816 test
1816 test
1817 User Name
1817 User Name
1818 person
1818 person
1819 person
1819 person
1820 person
1820 person
1821 person
1821 person
1822 other
1822 other
1823 A. N. Other
1823 A. N. Other
1824 User Name
1824 User Name
1825
1825
1826 $ hg log --template '{author|user}\n'
1826 $ hg log --template '{author|user}\n'
1827 test
1827 test
1828 user
1828 user
1829 person
1829 person
1830 person
1830 person
1831 person
1831 person
1832 person
1832 person
1833 other
1833 other
1834 other
1834 other
1835 user
1835 user
1836
1836
1837 $ hg log --template '{date|date}\n'
1837 $ hg log --template '{date|date}\n'
1838 Wed Jan 01 10:01:00 2020 +0000
1838 Wed Jan 01 10:01:00 2020 +0000
1839 Mon Jan 12 13:46:40 1970 +0000
1839 Mon Jan 12 13:46:40 1970 +0000
1840 Sun Jan 18 08:40:01 1970 +0000
1840 Sun Jan 18 08:40:01 1970 +0000
1841 Sun Jan 18 08:40:00 1970 +0000
1841 Sun Jan 18 08:40:00 1970 +0000
1842 Sat Jan 17 04:53:20 1970 +0000
1842 Sat Jan 17 04:53:20 1970 +0000
1843 Fri Jan 16 01:06:40 1970 +0000
1843 Fri Jan 16 01:06:40 1970 +0000
1844 Wed Jan 14 21:20:00 1970 +0000
1844 Wed Jan 14 21:20:00 1970 +0000
1845 Tue Jan 13 17:33:20 1970 +0000
1845 Tue Jan 13 17:33:20 1970 +0000
1846 Mon Jan 12 13:46:40 1970 +0000
1846 Mon Jan 12 13:46:40 1970 +0000
1847
1847
1848 $ hg log --template '{date|isodate}\n'
1848 $ hg log --template '{date|isodate}\n'
1849 2020-01-01 10:01 +0000
1849 2020-01-01 10:01 +0000
1850 1970-01-12 13:46 +0000
1850 1970-01-12 13:46 +0000
1851 1970-01-18 08:40 +0000
1851 1970-01-18 08:40 +0000
1852 1970-01-18 08:40 +0000
1852 1970-01-18 08:40 +0000
1853 1970-01-17 04:53 +0000
1853 1970-01-17 04:53 +0000
1854 1970-01-16 01:06 +0000
1854 1970-01-16 01:06 +0000
1855 1970-01-14 21:20 +0000
1855 1970-01-14 21:20 +0000
1856 1970-01-13 17:33 +0000
1856 1970-01-13 17:33 +0000
1857 1970-01-12 13:46 +0000
1857 1970-01-12 13:46 +0000
1858
1858
1859 $ hg log --template '{date|isodatesec}\n'
1859 $ hg log --template '{date|isodatesec}\n'
1860 2020-01-01 10:01:00 +0000
1860 2020-01-01 10:01:00 +0000
1861 1970-01-12 13:46:40 +0000
1861 1970-01-12 13:46:40 +0000
1862 1970-01-18 08:40:01 +0000
1862 1970-01-18 08:40:01 +0000
1863 1970-01-18 08:40:00 +0000
1863 1970-01-18 08:40:00 +0000
1864 1970-01-17 04:53:20 +0000
1864 1970-01-17 04:53:20 +0000
1865 1970-01-16 01:06:40 +0000
1865 1970-01-16 01:06:40 +0000
1866 1970-01-14 21:20:00 +0000
1866 1970-01-14 21:20:00 +0000
1867 1970-01-13 17:33:20 +0000
1867 1970-01-13 17:33:20 +0000
1868 1970-01-12 13:46:40 +0000
1868 1970-01-12 13:46:40 +0000
1869
1869
1870 $ hg log --template '{date|rfc822date}\n'
1870 $ hg log --template '{date|rfc822date}\n'
1871 Wed, 01 Jan 2020 10:01:00 +0000
1871 Wed, 01 Jan 2020 10:01:00 +0000
1872 Mon, 12 Jan 1970 13:46:40 +0000
1872 Mon, 12 Jan 1970 13:46:40 +0000
1873 Sun, 18 Jan 1970 08:40:01 +0000
1873 Sun, 18 Jan 1970 08:40:01 +0000
1874 Sun, 18 Jan 1970 08:40:00 +0000
1874 Sun, 18 Jan 1970 08:40:00 +0000
1875 Sat, 17 Jan 1970 04:53:20 +0000
1875 Sat, 17 Jan 1970 04:53:20 +0000
1876 Fri, 16 Jan 1970 01:06:40 +0000
1876 Fri, 16 Jan 1970 01:06:40 +0000
1877 Wed, 14 Jan 1970 21:20:00 +0000
1877 Wed, 14 Jan 1970 21:20:00 +0000
1878 Tue, 13 Jan 1970 17:33:20 +0000
1878 Tue, 13 Jan 1970 17:33:20 +0000
1879 Mon, 12 Jan 1970 13:46:40 +0000
1879 Mon, 12 Jan 1970 13:46:40 +0000
1880
1880
1881 $ hg log --template '{desc|firstline}\n'
1881 $ hg log --template '{desc|firstline}\n'
1882 third
1882 third
1883 second
1883 second
1884 merge
1884 merge
1885 new head
1885 new head
1886 new branch
1886 new branch
1887 no user, no domain
1887 no user, no domain
1888 no person
1888 no person
1889 other 1
1889 other 1
1890 line 1
1890 line 1
1891
1891
1892 $ hg log --template '{node|short}\n'
1892 $ hg log --template '{node|short}\n'
1893 95c24699272e
1893 95c24699272e
1894 29114dbae42b
1894 29114dbae42b
1895 d41e714fe50d
1895 d41e714fe50d
1896 13207e5a10d9
1896 13207e5a10d9
1897 bbe44766e73d
1897 bbe44766e73d
1898 10e46f2dcbf4
1898 10e46f2dcbf4
1899 97054abb4ab8
1899 97054abb4ab8
1900 b608e9d1a3f0
1900 b608e9d1a3f0
1901 1e4e1b8f71e0
1901 1e4e1b8f71e0
1902
1902
1903 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1903 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1904 <changeset author="test"/>
1904 <changeset author="test"/>
1905 <changeset author="User Name &lt;user@hostname&gt;"/>
1905 <changeset author="User Name &lt;user@hostname&gt;"/>
1906 <changeset author="person"/>
1906 <changeset author="person"/>
1907 <changeset author="person"/>
1907 <changeset author="person"/>
1908 <changeset author="person"/>
1908 <changeset author="person"/>
1909 <changeset author="person"/>
1909 <changeset author="person"/>
1910 <changeset author="other@place"/>
1910 <changeset author="other@place"/>
1911 <changeset author="A. N. Other &lt;other@place&gt;"/>
1911 <changeset author="A. N. Other &lt;other@place&gt;"/>
1912 <changeset author="User Name &lt;user@hostname&gt;"/>
1912 <changeset author="User Name &lt;user@hostname&gt;"/>
1913
1913
1914 $ hg log --template '{rev}: {children}\n'
1914 $ hg log --template '{rev}: {children}\n'
1915 8:
1915 8:
1916 7: 8:95c24699272e
1916 7: 8:95c24699272e
1917 6:
1917 6:
1918 5: 6:d41e714fe50d
1918 5: 6:d41e714fe50d
1919 4: 6:d41e714fe50d
1919 4: 6:d41e714fe50d
1920 3: 4:bbe44766e73d 5:13207e5a10d9
1920 3: 4:bbe44766e73d 5:13207e5a10d9
1921 2: 3:10e46f2dcbf4
1921 2: 3:10e46f2dcbf4
1922 1: 2:97054abb4ab8
1922 1: 2:97054abb4ab8
1923 0: 1:b608e9d1a3f0
1923 0: 1:b608e9d1a3f0
1924
1924
1925 Formatnode filter works:
1925 Formatnode filter works:
1926
1926
1927 $ hg -q log -r 0 --template '{node|formatnode}\n'
1927 $ hg -q log -r 0 --template '{node|formatnode}\n'
1928 1e4e1b8f71e0
1928 1e4e1b8f71e0
1929
1929
1930 $ hg log -r 0 --template '{node|formatnode}\n'
1930 $ hg log -r 0 --template '{node|formatnode}\n'
1931 1e4e1b8f71e0
1931 1e4e1b8f71e0
1932
1932
1933 $ hg -v log -r 0 --template '{node|formatnode}\n'
1933 $ hg -v log -r 0 --template '{node|formatnode}\n'
1934 1e4e1b8f71e0
1934 1e4e1b8f71e0
1935
1935
1936 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1936 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1937 1e4e1b8f71e05681d422154f5421e385fec3454f
1937 1e4e1b8f71e05681d422154f5421e385fec3454f
1938
1938
1939 Age filter:
1939 Age filter:
1940
1940
1941 $ hg init unstable-hash
1941 $ hg init unstable-hash
1942 $ cd unstable-hash
1942 $ cd unstable-hash
1943 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1943 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1944
1944
1945 >>> from datetime import datetime, timedelta
1945 >>> from datetime import datetime, timedelta
1946 >>> fp = open('a', 'w')
1946 >>> fp = open('a', 'w')
1947 >>> n = datetime.now() + timedelta(366 * 7)
1947 >>> n = datetime.now() + timedelta(366 * 7)
1948 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
1948 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
1949 >>> fp.close()
1949 >>> fp.close()
1950 $ hg add a
1950 $ hg add a
1951 $ hg commit -m future -d "`cat a`"
1951 $ hg commit -m future -d "`cat a`"
1952
1952
1953 $ hg log -l1 --template '{date|age}\n'
1953 $ hg log -l1 --template '{date|age}\n'
1954 7 years from now
1954 7 years from now
1955
1955
1956 $ cd ..
1956 $ cd ..
1957 $ rm -rf unstable-hash
1957 $ rm -rf unstable-hash
1958
1958
1959 Add a dummy commit to make up for the instability of the above:
1959 Add a dummy commit to make up for the instability of the above:
1960
1960
1961 $ echo a > a
1961 $ echo a > a
1962 $ hg add a
1962 $ hg add a
1963 $ hg ci -m future
1963 $ hg ci -m future
1964
1964
1965 Count filter:
1965 Count filter:
1966
1966
1967 $ hg log -l1 --template '{node|count} {node|short|count}\n'
1967 $ hg log -l1 --template '{node|count} {node|short|count}\n'
1968 40 12
1968 40 12
1969
1969
1970 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
1970 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
1971 0 1 4
1971 0 1 4
1972
1972
1973 $ hg log -G --template '{rev}: children: {children|count}, \
1973 $ hg log -G --template '{rev}: children: {children|count}, \
1974 > tags: {tags|count}, file_adds: {file_adds|count}, \
1974 > tags: {tags|count}, file_adds: {file_adds|count}, \
1975 > ancestors: {revset("ancestors(%s)", rev)|count}'
1975 > ancestors: {revset("ancestors(%s)", rev)|count}'
1976 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
1976 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
1977 |
1977 |
1978 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
1978 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
1979 |
1979 |
1980 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
1980 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
1981
1981
1982 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
1982 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
1983 |\
1983 |\
1984 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
1984 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
1985 | |
1985 | |
1986 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
1986 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
1987 |/
1987 |/
1988 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
1988 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
1989 |
1989 |
1990 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
1990 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
1991 |
1991 |
1992 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
1992 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
1993 |
1993 |
1994 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
1994 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
1995
1995
1996
1996
1997 Upper/lower filters:
1997 Upper/lower filters:
1998
1998
1999 $ hg log -r0 --template '{branch|upper}\n'
1999 $ hg log -r0 --template '{branch|upper}\n'
2000 DEFAULT
2000 DEFAULT
2001 $ hg log -r0 --template '{author|lower}\n'
2001 $ hg log -r0 --template '{author|lower}\n'
2002 user name <user@hostname>
2002 user name <user@hostname>
2003 $ hg log -r0 --template '{date|upper}\n'
2003 $ hg log -r0 --template '{date|upper}\n'
2004 abort: template filter 'upper' is not compatible with keyword 'date'
2004 abort: template filter 'upper' is not compatible with keyword 'date'
2005 [255]
2005 [255]
2006
2006
2007 Add a commit that does all possible modifications at once
2007 Add a commit that does all possible modifications at once
2008
2008
2009 $ echo modify >> third
2009 $ echo modify >> third
2010 $ touch b
2010 $ touch b
2011 $ hg add b
2011 $ hg add b
2012 $ hg mv fourth fifth
2012 $ hg mv fourth fifth
2013 $ hg rm a
2013 $ hg rm a
2014 $ hg ci -m "Modify, add, remove, rename"
2014 $ hg ci -m "Modify, add, remove, rename"
2015
2015
2016 Check the status template
2016 Check the status template
2017
2017
2018 $ cat <<EOF >> $HGRCPATH
2018 $ cat <<EOF >> $HGRCPATH
2019 > [extensions]
2019 > [extensions]
2020 > color=
2020 > color=
2021 > EOF
2021 > EOF
2022
2022
2023 $ hg log -T status -r 10
2023 $ hg log -T status -r 10
2024 changeset: 10:0f9759ec227a
2024 changeset: 10:0f9759ec227a
2025 tag: tip
2025 tag: tip
2026 user: test
2026 user: test
2027 date: Thu Jan 01 00:00:00 1970 +0000
2027 date: Thu Jan 01 00:00:00 1970 +0000
2028 summary: Modify, add, remove, rename
2028 summary: Modify, add, remove, rename
2029 files:
2029 files:
2030 M third
2030 M third
2031 A b
2031 A b
2032 A fifth
2032 A fifth
2033 R a
2033 R a
2034 R fourth
2034 R fourth
2035
2035
2036 $ hg log -T status -C -r 10
2036 $ hg log -T status -C -r 10
2037 changeset: 10:0f9759ec227a
2037 changeset: 10:0f9759ec227a
2038 tag: tip
2038 tag: tip
2039 user: test
2039 user: test
2040 date: Thu Jan 01 00:00:00 1970 +0000
2040 date: Thu Jan 01 00:00:00 1970 +0000
2041 summary: Modify, add, remove, rename
2041 summary: Modify, add, remove, rename
2042 files:
2042 files:
2043 M third
2043 M third
2044 A b
2044 A b
2045 A fifth
2045 A fifth
2046 fourth
2046 fourth
2047 R a
2047 R a
2048 R fourth
2048 R fourth
2049
2049
2050 $ hg log -T status -C -r 10 -v
2050 $ hg log -T status -C -r 10 -v
2051 changeset: 10:0f9759ec227a
2051 changeset: 10:0f9759ec227a
2052 tag: tip
2052 tag: tip
2053 user: test
2053 user: test
2054 date: Thu Jan 01 00:00:00 1970 +0000
2054 date: Thu Jan 01 00:00:00 1970 +0000
2055 description:
2055 description:
2056 Modify, add, remove, rename
2056 Modify, add, remove, rename
2057
2057
2058 files:
2058 files:
2059 M third
2059 M third
2060 A b
2060 A b
2061 A fifth
2061 A fifth
2062 fourth
2062 fourth
2063 R a
2063 R a
2064 R fourth
2064 R fourth
2065
2065
2066 $ hg log -T status -C -r 10 --debug
2066 $ hg log -T status -C -r 10 --debug
2067 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
2067 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
2068 tag: tip
2068 tag: tip
2069 phase: secret
2069 phase: secret
2070 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
2070 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
2071 parent: -1:0000000000000000000000000000000000000000
2071 parent: -1:0000000000000000000000000000000000000000
2072 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
2072 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
2073 user: test
2073 user: test
2074 date: Thu Jan 01 00:00:00 1970 +0000
2074 date: Thu Jan 01 00:00:00 1970 +0000
2075 extra: branch=default
2075 extra: branch=default
2076 description:
2076 description:
2077 Modify, add, remove, rename
2077 Modify, add, remove, rename
2078
2078
2079 files:
2079 files:
2080 M third
2080 M third
2081 A b
2081 A b
2082 A fifth
2082 A fifth
2083 fourth
2083 fourth
2084 R a
2084 R a
2085 R fourth
2085 R fourth
2086
2086
2087 $ hg log -T status -C -r 10 --quiet
2087 $ hg log -T status -C -r 10 --quiet
2088 10:0f9759ec227a
2088 10:0f9759ec227a
2089 $ hg --color=debug log -T status -r 10
2089 $ hg --color=debug log -T status -r 10
2090 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2090 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2091 [log.tag|tag: tip]
2091 [log.tag|tag: tip]
2092 [log.user|user: test]
2092 [log.user|user: test]
2093 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2093 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2094 [log.summary|summary: Modify, add, remove, rename]
2094 [log.summary|summary: Modify, add, remove, rename]
2095 [ui.note log.files|files:]
2095 [ui.note log.files|files:]
2096 [status.modified|M third]
2096 [status.modified|M third]
2097 [status.added|A b]
2097 [status.added|A b]
2098 [status.added|A fifth]
2098 [status.added|A fifth]
2099 [status.removed|R a]
2099 [status.removed|R a]
2100 [status.removed|R fourth]
2100 [status.removed|R fourth]
2101
2101
2102 $ hg --color=debug log -T status -C -r 10
2102 $ hg --color=debug log -T status -C -r 10
2103 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2103 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2104 [log.tag|tag: tip]
2104 [log.tag|tag: tip]
2105 [log.user|user: test]
2105 [log.user|user: test]
2106 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2106 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2107 [log.summary|summary: Modify, add, remove, rename]
2107 [log.summary|summary: Modify, add, remove, rename]
2108 [ui.note log.files|files:]
2108 [ui.note log.files|files:]
2109 [status.modified|M third]
2109 [status.modified|M third]
2110 [status.added|A b]
2110 [status.added|A b]
2111 [status.added|A fifth]
2111 [status.added|A fifth]
2112 [status.copied| fourth]
2112 [status.copied| fourth]
2113 [status.removed|R a]
2113 [status.removed|R a]
2114 [status.removed|R fourth]
2114 [status.removed|R fourth]
2115
2115
2116 $ hg --color=debug log -T status -C -r 10 -v
2116 $ hg --color=debug log -T status -C -r 10 -v
2117 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2117 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2118 [log.tag|tag: tip]
2118 [log.tag|tag: tip]
2119 [log.user|user: test]
2119 [log.user|user: test]
2120 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2120 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2121 [ui.note log.description|description:]
2121 [ui.note log.description|description:]
2122 [ui.note log.description|Modify, add, remove, rename]
2122 [ui.note log.description|Modify, add, remove, rename]
2123
2123
2124 [ui.note log.files|files:]
2124 [ui.note log.files|files:]
2125 [status.modified|M third]
2125 [status.modified|M third]
2126 [status.added|A b]
2126 [status.added|A b]
2127 [status.added|A fifth]
2127 [status.added|A fifth]
2128 [status.copied| fourth]
2128 [status.copied| fourth]
2129 [status.removed|R a]
2129 [status.removed|R a]
2130 [status.removed|R fourth]
2130 [status.removed|R fourth]
2131
2131
2132 $ hg --color=debug log -T status -C -r 10 --debug
2132 $ hg --color=debug log -T status -C -r 10 --debug
2133 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
2133 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
2134 [log.tag|tag: tip]
2134 [log.tag|tag: tip]
2135 [log.phase|phase: secret]
2135 [log.phase|phase: secret]
2136 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
2136 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
2137 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2137 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2138 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
2138 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
2139 [log.user|user: test]
2139 [log.user|user: test]
2140 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2140 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2141 [ui.debug log.extra|extra: branch=default]
2141 [ui.debug log.extra|extra: branch=default]
2142 [ui.note log.description|description:]
2142 [ui.note log.description|description:]
2143 [ui.note log.description|Modify, add, remove, rename]
2143 [ui.note log.description|Modify, add, remove, rename]
2144
2144
2145 [ui.note log.files|files:]
2145 [ui.note log.files|files:]
2146 [status.modified|M third]
2146 [status.modified|M third]
2147 [status.added|A b]
2147 [status.added|A b]
2148 [status.added|A fifth]
2148 [status.added|A fifth]
2149 [status.copied| fourth]
2149 [status.copied| fourth]
2150 [status.removed|R a]
2150 [status.removed|R a]
2151 [status.removed|R fourth]
2151 [status.removed|R fourth]
2152
2152
2153 $ hg --color=debug log -T status -C -r 10 --quiet
2153 $ hg --color=debug log -T status -C -r 10 --quiet
2154 [log.node|10:0f9759ec227a]
2154 [log.node|10:0f9759ec227a]
2155
2155
2156 Check the bisect template
2156 Check the bisect template
2157
2157
2158 $ hg bisect -g 1
2158 $ hg bisect -g 1
2159 $ hg bisect -b 3 --noupdate
2159 $ hg bisect -b 3 --noupdate
2160 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
2160 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
2161 $ hg log -T bisect -r 0:4
2161 $ hg log -T bisect -r 0:4
2162 changeset: 0:1e4e1b8f71e0
2162 changeset: 0:1e4e1b8f71e0
2163 bisect: good (implicit)
2163 bisect: good (implicit)
2164 user: User Name <user@hostname>
2164 user: User Name <user@hostname>
2165 date: Mon Jan 12 13:46:40 1970 +0000
2165 date: Mon Jan 12 13:46:40 1970 +0000
2166 summary: line 1
2166 summary: line 1
2167
2167
2168 changeset: 1:b608e9d1a3f0
2168 changeset: 1:b608e9d1a3f0
2169 bisect: good
2169 bisect: good
2170 user: A. N. Other <other@place>
2170 user: A. N. Other <other@place>
2171 date: Tue Jan 13 17:33:20 1970 +0000
2171 date: Tue Jan 13 17:33:20 1970 +0000
2172 summary: other 1
2172 summary: other 1
2173
2173
2174 changeset: 2:97054abb4ab8
2174 changeset: 2:97054abb4ab8
2175 bisect: untested
2175 bisect: untested
2176 user: other@place
2176 user: other@place
2177 date: Wed Jan 14 21:20:00 1970 +0000
2177 date: Wed Jan 14 21:20:00 1970 +0000
2178 summary: no person
2178 summary: no person
2179
2179
2180 changeset: 3:10e46f2dcbf4
2180 changeset: 3:10e46f2dcbf4
2181 bisect: bad
2181 bisect: bad
2182 user: person
2182 user: person
2183 date: Fri Jan 16 01:06:40 1970 +0000
2183 date: Fri Jan 16 01:06:40 1970 +0000
2184 summary: no user, no domain
2184 summary: no user, no domain
2185
2185
2186 changeset: 4:bbe44766e73d
2186 changeset: 4:bbe44766e73d
2187 bisect: bad (implicit)
2187 bisect: bad (implicit)
2188 branch: foo
2188 branch: foo
2189 user: person
2189 user: person
2190 date: Sat Jan 17 04:53:20 1970 +0000
2190 date: Sat Jan 17 04:53:20 1970 +0000
2191 summary: new branch
2191 summary: new branch
2192
2192
2193 $ hg log --debug -T bisect -r 0:4
2193 $ hg log --debug -T bisect -r 0:4
2194 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2194 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2195 bisect: good (implicit)
2195 bisect: good (implicit)
2196 phase: public
2196 phase: public
2197 parent: -1:0000000000000000000000000000000000000000
2197 parent: -1:0000000000000000000000000000000000000000
2198 parent: -1:0000000000000000000000000000000000000000
2198 parent: -1:0000000000000000000000000000000000000000
2199 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
2199 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
2200 user: User Name <user@hostname>
2200 user: User Name <user@hostname>
2201 date: Mon Jan 12 13:46:40 1970 +0000
2201 date: Mon Jan 12 13:46:40 1970 +0000
2202 files+: a
2202 files+: a
2203 extra: branch=default
2203 extra: branch=default
2204 description:
2204 description:
2205 line 1
2205 line 1
2206 line 2
2206 line 2
2207
2207
2208
2208
2209 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2209 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2210 bisect: good
2210 bisect: good
2211 phase: public
2211 phase: public
2212 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2212 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2213 parent: -1:0000000000000000000000000000000000000000
2213 parent: -1:0000000000000000000000000000000000000000
2214 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
2214 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
2215 user: A. N. Other <other@place>
2215 user: A. N. Other <other@place>
2216 date: Tue Jan 13 17:33:20 1970 +0000
2216 date: Tue Jan 13 17:33:20 1970 +0000
2217 files+: b
2217 files+: b
2218 extra: branch=default
2218 extra: branch=default
2219 description:
2219 description:
2220 other 1
2220 other 1
2221 other 2
2221 other 2
2222
2222
2223 other 3
2223 other 3
2224
2224
2225
2225
2226 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
2226 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
2227 bisect: untested
2227 bisect: untested
2228 phase: public
2228 phase: public
2229 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2229 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2230 parent: -1:0000000000000000000000000000000000000000
2230 parent: -1:0000000000000000000000000000000000000000
2231 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
2231 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
2232 user: other@place
2232 user: other@place
2233 date: Wed Jan 14 21:20:00 1970 +0000
2233 date: Wed Jan 14 21:20:00 1970 +0000
2234 files+: c
2234 files+: c
2235 extra: branch=default
2235 extra: branch=default
2236 description:
2236 description:
2237 no person
2237 no person
2238
2238
2239
2239
2240 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2240 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2241 bisect: bad
2241 bisect: bad
2242 phase: public
2242 phase: public
2243 parent: 2:97054abb4ab824450e9164180baf491ae0078465
2243 parent: 2:97054abb4ab824450e9164180baf491ae0078465
2244 parent: -1:0000000000000000000000000000000000000000
2244 parent: -1:0000000000000000000000000000000000000000
2245 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2245 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2246 user: person
2246 user: person
2247 date: Fri Jan 16 01:06:40 1970 +0000
2247 date: Fri Jan 16 01:06:40 1970 +0000
2248 files: c
2248 files: c
2249 extra: branch=default
2249 extra: branch=default
2250 description:
2250 description:
2251 no user, no domain
2251 no user, no domain
2252
2252
2253
2253
2254 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
2254 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
2255 bisect: bad (implicit)
2255 bisect: bad (implicit)
2256 branch: foo
2256 branch: foo
2257 phase: draft
2257 phase: draft
2258 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2258 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2259 parent: -1:0000000000000000000000000000000000000000
2259 parent: -1:0000000000000000000000000000000000000000
2260 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2260 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2261 user: person
2261 user: person
2262 date: Sat Jan 17 04:53:20 1970 +0000
2262 date: Sat Jan 17 04:53:20 1970 +0000
2263 extra: branch=foo
2263 extra: branch=foo
2264 description:
2264 description:
2265 new branch
2265 new branch
2266
2266
2267
2267
2268 $ hg log -v -T bisect -r 0:4
2268 $ hg log -v -T bisect -r 0:4
2269 changeset: 0:1e4e1b8f71e0
2269 changeset: 0:1e4e1b8f71e0
2270 bisect: good (implicit)
2270 bisect: good (implicit)
2271 user: User Name <user@hostname>
2271 user: User Name <user@hostname>
2272 date: Mon Jan 12 13:46:40 1970 +0000
2272 date: Mon Jan 12 13:46:40 1970 +0000
2273 files: a
2273 files: a
2274 description:
2274 description:
2275 line 1
2275 line 1
2276 line 2
2276 line 2
2277
2277
2278
2278
2279 changeset: 1:b608e9d1a3f0
2279 changeset: 1:b608e9d1a3f0
2280 bisect: good
2280 bisect: good
2281 user: A. N. Other <other@place>
2281 user: A. N. Other <other@place>
2282 date: Tue Jan 13 17:33:20 1970 +0000
2282 date: Tue Jan 13 17:33:20 1970 +0000
2283 files: b
2283 files: b
2284 description:
2284 description:
2285 other 1
2285 other 1
2286 other 2
2286 other 2
2287
2287
2288 other 3
2288 other 3
2289
2289
2290
2290
2291 changeset: 2:97054abb4ab8
2291 changeset: 2:97054abb4ab8
2292 bisect: untested
2292 bisect: untested
2293 user: other@place
2293 user: other@place
2294 date: Wed Jan 14 21:20:00 1970 +0000
2294 date: Wed Jan 14 21:20:00 1970 +0000
2295 files: c
2295 files: c
2296 description:
2296 description:
2297 no person
2297 no person
2298
2298
2299
2299
2300 changeset: 3:10e46f2dcbf4
2300 changeset: 3:10e46f2dcbf4
2301 bisect: bad
2301 bisect: bad
2302 user: person
2302 user: person
2303 date: Fri Jan 16 01:06:40 1970 +0000
2303 date: Fri Jan 16 01:06:40 1970 +0000
2304 files: c
2304 files: c
2305 description:
2305 description:
2306 no user, no domain
2306 no user, no domain
2307
2307
2308
2308
2309 changeset: 4:bbe44766e73d
2309 changeset: 4:bbe44766e73d
2310 bisect: bad (implicit)
2310 bisect: bad (implicit)
2311 branch: foo
2311 branch: foo
2312 user: person
2312 user: person
2313 date: Sat Jan 17 04:53:20 1970 +0000
2313 date: Sat Jan 17 04:53:20 1970 +0000
2314 description:
2314 description:
2315 new branch
2315 new branch
2316
2316
2317
2317
2318 $ hg --color=debug log -T bisect -r 0:4
2318 $ hg --color=debug log -T bisect -r 0:4
2319 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2319 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2320 [log.bisect bisect.good|bisect: good (implicit)]
2320 [log.bisect bisect.good|bisect: good (implicit)]
2321 [log.user|user: User Name <user@hostname>]
2321 [log.user|user: User Name <user@hostname>]
2322 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2322 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2323 [log.summary|summary: line 1]
2323 [log.summary|summary: line 1]
2324
2324
2325 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2325 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2326 [log.bisect bisect.good|bisect: good]
2326 [log.bisect bisect.good|bisect: good]
2327 [log.user|user: A. N. Other <other@place>]
2327 [log.user|user: A. N. Other <other@place>]
2328 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2328 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2329 [log.summary|summary: other 1]
2329 [log.summary|summary: other 1]
2330
2330
2331 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2331 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2332 [log.bisect bisect.untested|bisect: untested]
2332 [log.bisect bisect.untested|bisect: untested]
2333 [log.user|user: other@place]
2333 [log.user|user: other@place]
2334 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2334 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2335 [log.summary|summary: no person]
2335 [log.summary|summary: no person]
2336
2336
2337 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2337 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2338 [log.bisect bisect.bad|bisect: bad]
2338 [log.bisect bisect.bad|bisect: bad]
2339 [log.user|user: person]
2339 [log.user|user: person]
2340 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2340 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2341 [log.summary|summary: no user, no domain]
2341 [log.summary|summary: no user, no domain]
2342
2342
2343 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2343 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2344 [log.bisect bisect.bad|bisect: bad (implicit)]
2344 [log.bisect bisect.bad|bisect: bad (implicit)]
2345 [log.branch|branch: foo]
2345 [log.branch|branch: foo]
2346 [log.user|user: person]
2346 [log.user|user: person]
2347 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2347 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2348 [log.summary|summary: new branch]
2348 [log.summary|summary: new branch]
2349
2349
2350 $ hg --color=debug log --debug -T bisect -r 0:4
2350 $ hg --color=debug log --debug -T bisect -r 0:4
2351 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2351 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2352 [log.bisect bisect.good|bisect: good (implicit)]
2352 [log.bisect bisect.good|bisect: good (implicit)]
2353 [log.phase|phase: public]
2353 [log.phase|phase: public]
2354 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2354 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2355 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2355 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2356 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
2356 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
2357 [log.user|user: User Name <user@hostname>]
2357 [log.user|user: User Name <user@hostname>]
2358 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2358 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2359 [ui.debug log.files|files+: a]
2359 [ui.debug log.files|files+: a]
2360 [ui.debug log.extra|extra: branch=default]
2360 [ui.debug log.extra|extra: branch=default]
2361 [ui.note log.description|description:]
2361 [ui.note log.description|description:]
2362 [ui.note log.description|line 1
2362 [ui.note log.description|line 1
2363 line 2]
2363 line 2]
2364
2364
2365
2365
2366 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2366 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2367 [log.bisect bisect.good|bisect: good]
2367 [log.bisect bisect.good|bisect: good]
2368 [log.phase|phase: public]
2368 [log.phase|phase: public]
2369 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2369 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2370 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2370 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2371 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
2371 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
2372 [log.user|user: A. N. Other <other@place>]
2372 [log.user|user: A. N. Other <other@place>]
2373 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2373 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2374 [ui.debug log.files|files+: b]
2374 [ui.debug log.files|files+: b]
2375 [ui.debug log.extra|extra: branch=default]
2375 [ui.debug log.extra|extra: branch=default]
2376 [ui.note log.description|description:]
2376 [ui.note log.description|description:]
2377 [ui.note log.description|other 1
2377 [ui.note log.description|other 1
2378 other 2
2378 other 2
2379
2379
2380 other 3]
2380 other 3]
2381
2381
2382
2382
2383 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
2383 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
2384 [log.bisect bisect.untested|bisect: untested]
2384 [log.bisect bisect.untested|bisect: untested]
2385 [log.phase|phase: public]
2385 [log.phase|phase: public]
2386 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2386 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2387 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2387 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2388 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
2388 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
2389 [log.user|user: other@place]
2389 [log.user|user: other@place]
2390 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2390 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2391 [ui.debug log.files|files+: c]
2391 [ui.debug log.files|files+: c]
2392 [ui.debug log.extra|extra: branch=default]
2392 [ui.debug log.extra|extra: branch=default]
2393 [ui.note log.description|description:]
2393 [ui.note log.description|description:]
2394 [ui.note log.description|no person]
2394 [ui.note log.description|no person]
2395
2395
2396
2396
2397 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2397 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2398 [log.bisect bisect.bad|bisect: bad]
2398 [log.bisect bisect.bad|bisect: bad]
2399 [log.phase|phase: public]
2399 [log.phase|phase: public]
2400 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
2400 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
2401 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2401 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2402 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2402 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2403 [log.user|user: person]
2403 [log.user|user: person]
2404 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2404 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2405 [ui.debug log.files|files: c]
2405 [ui.debug log.files|files: c]
2406 [ui.debug log.extra|extra: branch=default]
2406 [ui.debug log.extra|extra: branch=default]
2407 [ui.note log.description|description:]
2407 [ui.note log.description|description:]
2408 [ui.note log.description|no user, no domain]
2408 [ui.note log.description|no user, no domain]
2409
2409
2410
2410
2411 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
2411 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
2412 [log.bisect bisect.bad|bisect: bad (implicit)]
2412 [log.bisect bisect.bad|bisect: bad (implicit)]
2413 [log.branch|branch: foo]
2413 [log.branch|branch: foo]
2414 [log.phase|phase: draft]
2414 [log.phase|phase: draft]
2415 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2415 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2416 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2416 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2417 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2417 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2418 [log.user|user: person]
2418 [log.user|user: person]
2419 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2419 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2420 [ui.debug log.extra|extra: branch=foo]
2420 [ui.debug log.extra|extra: branch=foo]
2421 [ui.note log.description|description:]
2421 [ui.note log.description|description:]
2422 [ui.note log.description|new branch]
2422 [ui.note log.description|new branch]
2423
2423
2424
2424
2425 $ hg --color=debug log -v -T bisect -r 0:4
2425 $ hg --color=debug log -v -T bisect -r 0:4
2426 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2426 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2427 [log.bisect bisect.good|bisect: good (implicit)]
2427 [log.bisect bisect.good|bisect: good (implicit)]
2428 [log.user|user: User Name <user@hostname>]
2428 [log.user|user: User Name <user@hostname>]
2429 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2429 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2430 [ui.note log.files|files: a]
2430 [ui.note log.files|files: a]
2431 [ui.note log.description|description:]
2431 [ui.note log.description|description:]
2432 [ui.note log.description|line 1
2432 [ui.note log.description|line 1
2433 line 2]
2433 line 2]
2434
2434
2435
2435
2436 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2436 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2437 [log.bisect bisect.good|bisect: good]
2437 [log.bisect bisect.good|bisect: good]
2438 [log.user|user: A. N. Other <other@place>]
2438 [log.user|user: A. N. Other <other@place>]
2439 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2439 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2440 [ui.note log.files|files: b]
2440 [ui.note log.files|files: b]
2441 [ui.note log.description|description:]
2441 [ui.note log.description|description:]
2442 [ui.note log.description|other 1
2442 [ui.note log.description|other 1
2443 other 2
2443 other 2
2444
2444
2445 other 3]
2445 other 3]
2446
2446
2447
2447
2448 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2448 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2449 [log.bisect bisect.untested|bisect: untested]
2449 [log.bisect bisect.untested|bisect: untested]
2450 [log.user|user: other@place]
2450 [log.user|user: other@place]
2451 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2451 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2452 [ui.note log.files|files: c]
2452 [ui.note log.files|files: c]
2453 [ui.note log.description|description:]
2453 [ui.note log.description|description:]
2454 [ui.note log.description|no person]
2454 [ui.note log.description|no person]
2455
2455
2456
2456
2457 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2457 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2458 [log.bisect bisect.bad|bisect: bad]
2458 [log.bisect bisect.bad|bisect: bad]
2459 [log.user|user: person]
2459 [log.user|user: person]
2460 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2460 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2461 [ui.note log.files|files: c]
2461 [ui.note log.files|files: c]
2462 [ui.note log.description|description:]
2462 [ui.note log.description|description:]
2463 [ui.note log.description|no user, no domain]
2463 [ui.note log.description|no user, no domain]
2464
2464
2465
2465
2466 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2466 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2467 [log.bisect bisect.bad|bisect: bad (implicit)]
2467 [log.bisect bisect.bad|bisect: bad (implicit)]
2468 [log.branch|branch: foo]
2468 [log.branch|branch: foo]
2469 [log.user|user: person]
2469 [log.user|user: person]
2470 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2470 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2471 [ui.note log.description|description:]
2471 [ui.note log.description|description:]
2472 [ui.note log.description|new branch]
2472 [ui.note log.description|new branch]
2473
2473
2474
2474
2475 $ hg bisect --reset
2475 $ hg bisect --reset
2476
2476
2477 Error on syntax:
2477 Error on syntax:
2478
2478
2479 $ echo 'x = "f' >> t
2479 $ echo 'x = "f' >> t
2480 $ hg log
2480 $ hg log
2481 abort: t:3: unmatched quotes
2481 abort: t:3: unmatched quotes
2482 [255]
2482 [255]
2483
2483
2484 Behind the scenes, this will throw TypeError
2484 Behind the scenes, this will throw TypeError
2485
2485
2486 $ hg log -l 3 --template '{date|obfuscate}\n'
2486 $ hg log -l 3 --template '{date|obfuscate}\n'
2487 abort: template filter 'obfuscate' is not compatible with keyword 'date'
2487 abort: template filter 'obfuscate' is not compatible with keyword 'date'
2488 [255]
2488 [255]
2489
2489
2490 Behind the scenes, this will throw a ValueError
2490 Behind the scenes, this will throw a ValueError
2491
2491
2492 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
2492 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
2493 abort: template filter 'shortdate' is not compatible with keyword 'desc'
2493 abort: template filter 'shortdate' is not compatible with keyword 'desc'
2494 [255]
2494 [255]
2495
2495
2496 Behind the scenes, this will throw AttributeError
2496 Behind the scenes, this will throw AttributeError
2497
2497
2498 $ hg log -l 3 --template 'line: {date|escape}\n'
2498 $ hg log -l 3 --template 'line: {date|escape}\n'
2499 abort: template filter 'escape' is not compatible with keyword 'date'
2499 abort: template filter 'escape' is not compatible with keyword 'date'
2500 [255]
2500 [255]
2501
2501
2502 Behind the scenes, this will throw ValueError
2502 Behind the scenes, this will throw ValueError
2503
2503
2504 $ hg tip --template '{author|email|date}\n'
2504 $ hg tip --template '{author|email|date}\n'
2505 abort: template filter 'datefilter' is not compatible with keyword 'author'
2505 abort: template filter 'datefilter' is not compatible with keyword 'author'
2506 [255]
2506 [255]
2507
2507
2508 Thrown an error if a template function doesn't exist
2508 Thrown an error if a template function doesn't exist
2509
2509
2510 $ hg tip --template '{foo()}\n'
2510 $ hg tip --template '{foo()}\n'
2511 hg: parse error: unknown function 'foo'
2511 hg: parse error: unknown function 'foo'
2512 [255]
2512 [255]
2513
2513
2514 Pass generator object created by template function to filter
2514 Pass generator object created by template function to filter
2515
2515
2516 $ hg log -l 1 --template '{if(author, author)|user}\n'
2516 $ hg log -l 1 --template '{if(author, author)|user}\n'
2517 test
2517 test
2518
2518
2519 Test diff function:
2519 Test diff function:
2520
2520
2521 $ hg diff -c 8
2521 $ hg diff -c 8
2522 diff -r 29114dbae42b -r 95c24699272e fourth
2522 diff -r 29114dbae42b -r 95c24699272e fourth
2523 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2523 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2524 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2524 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2525 @@ -0,0 +1,1 @@
2525 @@ -0,0 +1,1 @@
2526 +second
2526 +second
2527 diff -r 29114dbae42b -r 95c24699272e second
2527 diff -r 29114dbae42b -r 95c24699272e second
2528 --- a/second Mon Jan 12 13:46:40 1970 +0000
2528 --- a/second Mon Jan 12 13:46:40 1970 +0000
2529 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2529 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2530 @@ -1,1 +0,0 @@
2530 @@ -1,1 +0,0 @@
2531 -second
2531 -second
2532 diff -r 29114dbae42b -r 95c24699272e third
2532 diff -r 29114dbae42b -r 95c24699272e third
2533 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2533 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2534 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2534 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2535 @@ -0,0 +1,1 @@
2535 @@ -0,0 +1,1 @@
2536 +third
2536 +third
2537
2537
2538 $ hg log -r 8 -T "{diff()}"
2538 $ hg log -r 8 -T "{diff()}"
2539 diff -r 29114dbae42b -r 95c24699272e fourth
2539 diff -r 29114dbae42b -r 95c24699272e fourth
2540 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2540 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2541 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2541 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2542 @@ -0,0 +1,1 @@
2542 @@ -0,0 +1,1 @@
2543 +second
2543 +second
2544 diff -r 29114dbae42b -r 95c24699272e second
2544 diff -r 29114dbae42b -r 95c24699272e second
2545 --- a/second Mon Jan 12 13:46:40 1970 +0000
2545 --- a/second Mon Jan 12 13:46:40 1970 +0000
2546 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2546 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2547 @@ -1,1 +0,0 @@
2547 @@ -1,1 +0,0 @@
2548 -second
2548 -second
2549 diff -r 29114dbae42b -r 95c24699272e third
2549 diff -r 29114dbae42b -r 95c24699272e third
2550 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2550 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2551 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2551 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2552 @@ -0,0 +1,1 @@
2552 @@ -0,0 +1,1 @@
2553 +third
2553 +third
2554
2554
2555 $ hg log -r 8 -T "{diff('glob:f*')}"
2555 $ hg log -r 8 -T "{diff('glob:f*')}"
2556 diff -r 29114dbae42b -r 95c24699272e fourth
2556 diff -r 29114dbae42b -r 95c24699272e fourth
2557 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2557 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2558 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2558 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2559 @@ -0,0 +1,1 @@
2559 @@ -0,0 +1,1 @@
2560 +second
2560 +second
2561
2561
2562 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2562 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2563 diff -r 29114dbae42b -r 95c24699272e second
2563 diff -r 29114dbae42b -r 95c24699272e second
2564 --- a/second Mon Jan 12 13:46:40 1970 +0000
2564 --- a/second Mon Jan 12 13:46:40 1970 +0000
2565 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2565 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2566 @@ -1,1 +0,0 @@
2566 @@ -1,1 +0,0 @@
2567 -second
2567 -second
2568 diff -r 29114dbae42b -r 95c24699272e third
2568 diff -r 29114dbae42b -r 95c24699272e third
2569 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2569 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2570 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2570 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2571 @@ -0,0 +1,1 @@
2571 @@ -0,0 +1,1 @@
2572 +third
2572 +third
2573
2573
2574 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
2574 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
2575 diff -r 29114dbae42b -r 95c24699272e fourth
2575 diff -r 29114dbae42b -r 95c24699272e fourth
2576 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2576 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2577 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2577 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2578 @@ -0,0 +1,1 @@
2578 @@ -0,0 +1,1 @@
2579 +second
2579 +second
2580
2580
2581 $ cd ..
2581 $ cd ..
2582
2582
2583
2583
2584 latesttag:
2584 latesttag:
2585
2585
2586 $ hg init latesttag
2586 $ hg init latesttag
2587 $ cd latesttag
2587 $ cd latesttag
2588
2588
2589 $ echo a > file
2589 $ echo a > file
2590 $ hg ci -Am a -d '0 0'
2590 $ hg ci -Am a -d '0 0'
2591 adding file
2591 adding file
2592
2592
2593 $ echo b >> file
2593 $ echo b >> file
2594 $ hg ci -m b -d '1 0'
2594 $ hg ci -m b -d '1 0'
2595
2595
2596 $ echo c >> head1
2596 $ echo c >> head1
2597 $ hg ci -Am h1c -d '2 0'
2597 $ hg ci -Am h1c -d '2 0'
2598 adding head1
2598 adding head1
2599
2599
2600 $ hg update -q 1
2600 $ hg update -q 1
2601 $ echo d >> head2
2601 $ echo d >> head2
2602 $ hg ci -Am h2d -d '3 0'
2602 $ hg ci -Am h2d -d '3 0'
2603 adding head2
2603 adding head2
2604 created new head
2604 created new head
2605
2605
2606 $ echo e >> head2
2606 $ echo e >> head2
2607 $ hg ci -m h2e -d '4 0'
2607 $ hg ci -m h2e -d '4 0'
2608
2608
2609 $ hg merge -q
2609 $ hg merge -q
2610 $ hg ci -m merge -d '5 -3600'
2610 $ hg ci -m merge -d '5 -3600'
2611
2611
2612 No tag set:
2612 No tag set:
2613
2613
2614 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2614 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2615 5: null+5
2615 5: null+5
2616 4: null+4
2616 4: null+4
2617 3: null+3
2617 3: null+3
2618 2: null+3
2618 2: null+3
2619 1: null+2
2619 1: null+2
2620 0: null+1
2620 0: null+1
2621
2621
2622 One common tag: longest path wins:
2622 One common tag: longest path wins:
2623
2623
2624 $ hg tag -r 1 -m t1 -d '6 0' t1
2624 $ hg tag -r 1 -m t1 -d '6 0' t1
2625 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2625 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2626 6: t1+4
2626 6: t1+4
2627 5: t1+3
2627 5: t1+3
2628 4: t1+2
2628 4: t1+2
2629 3: t1+1
2629 3: t1+1
2630 2: t1+1
2630 2: t1+1
2631 1: t1+0
2631 1: t1+0
2632 0: null+1
2632 0: null+1
2633
2633
2634 One ancestor tag: more recent wins:
2634 One ancestor tag: more recent wins:
2635
2635
2636 $ hg tag -r 2 -m t2 -d '7 0' t2
2636 $ hg tag -r 2 -m t2 -d '7 0' t2
2637 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2637 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2638 7: t2+3
2638 7: t2+3
2639 6: t2+2
2639 6: t2+2
2640 5: t2+1
2640 5: t2+1
2641 4: t1+2
2641 4: t1+2
2642 3: t1+1
2642 3: t1+1
2643 2: t2+0
2643 2: t2+0
2644 1: t1+0
2644 1: t1+0
2645 0: null+1
2645 0: null+1
2646
2646
2647 Two branch tags: more recent wins:
2647 Two branch tags: more recent wins:
2648
2648
2649 $ hg tag -r 3 -m t3 -d '8 0' t3
2649 $ hg tag -r 3 -m t3 -d '8 0' t3
2650 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2650 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2651 8: t3+5
2651 8: t3+5
2652 7: t3+4
2652 7: t3+4
2653 6: t3+3
2653 6: t3+3
2654 5: t3+2
2654 5: t3+2
2655 4: t3+1
2655 4: t3+1
2656 3: t3+0
2656 3: t3+0
2657 2: t2+0
2657 2: t2+0
2658 1: t1+0
2658 1: t1+0
2659 0: null+1
2659 0: null+1
2660
2660
2661 Merged tag overrides:
2661 Merged tag overrides:
2662
2662
2663 $ hg tag -r 5 -m t5 -d '9 0' t5
2663 $ hg tag -r 5 -m t5 -d '9 0' t5
2664 $ hg tag -r 3 -m at3 -d '10 0' at3
2664 $ hg tag -r 3 -m at3 -d '10 0' at3
2665 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2665 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2666 10: t5+5
2666 10: t5+5
2667 9: t5+4
2667 9: t5+4
2668 8: t5+3
2668 8: t5+3
2669 7: t5+2
2669 7: t5+2
2670 6: t5+1
2670 6: t5+1
2671 5: t5+0
2671 5: t5+0
2672 4: at3:t3+1
2672 4: at3:t3+1
2673 3: at3:t3+0
2673 3: at3:t3+0
2674 2: t2+0
2674 2: t2+0
2675 1: t1+0
2675 1: t1+0
2676 0: null+1
2676 0: null+1
2677
2677
2678 $ cd ..
2678 $ cd ..
2679
2679
2680
2680
2681 Style path expansion: issue1948 - ui.style option doesn't work on OSX
2681 Style path expansion: issue1948 - ui.style option doesn't work on OSX
2682 if it is a relative path
2682 if it is a relative path
2683
2683
2684 $ mkdir -p home/styles
2684 $ mkdir -p home/styles
2685
2685
2686 $ cat > home/styles/teststyle <<EOF
2686 $ cat > home/styles/teststyle <<EOF
2687 > changeset = 'test {rev}:{node|short}\n'
2687 > changeset = 'test {rev}:{node|short}\n'
2688 > EOF
2688 > EOF
2689
2689
2690 $ HOME=`pwd`/home; export HOME
2690 $ HOME=`pwd`/home; export HOME
2691
2691
2692 $ cat > latesttag/.hg/hgrc <<EOF
2692 $ cat > latesttag/.hg/hgrc <<EOF
2693 > [ui]
2693 > [ui]
2694 > style = ~/styles/teststyle
2694 > style = ~/styles/teststyle
2695 > EOF
2695 > EOF
2696
2696
2697 $ hg -R latesttag tip
2697 $ hg -R latesttag tip
2698 test 10:9b4a630e5f5f
2698 test 10:9b4a630e5f5f
2699
2699
2700 Test recursive showlist template (issue1989):
2700 Test recursive showlist template (issue1989):
2701
2701
2702 $ cat > style1989 <<EOF
2702 $ cat > style1989 <<EOF
2703 > changeset = '{file_mods}{manifest}{extras}'
2703 > changeset = '{file_mods}{manifest}{extras}'
2704 > file_mod = 'M|{author|person}\n'
2704 > file_mod = 'M|{author|person}\n'
2705 > manifest = '{rev},{author}\n'
2705 > manifest = '{rev},{author}\n'
2706 > extra = '{key}: {author}\n'
2706 > extra = '{key}: {author}\n'
2707 > EOF
2707 > EOF
2708
2708
2709 $ hg -R latesttag log -r tip --style=style1989
2709 $ hg -R latesttag log -r tip --style=style1989
2710 M|test
2710 M|test
2711 10,test
2711 10,test
2712 branch: test
2712 branch: test
2713
2713
2714 Test new-style inline templating:
2714 Test new-style inline templating:
2715
2715
2716 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
2716 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
2717 modified files: .hgtags
2717 modified files: .hgtags
2718
2718
2719 Test the sub function of templating for expansion:
2719 Test the sub function of templating for expansion:
2720
2720
2721 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
2721 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
2722 xx
2722 xx
2723
2723
2724 Test the strip function with chars specified:
2724 Test the strip function with chars specified:
2725
2725
2726 $ hg log -R latesttag --template '{desc}\n'
2726 $ hg log -R latesttag --template '{desc}\n'
2727 at3
2727 at3
2728 t5
2728 t5
2729 t3
2729 t3
2730 t2
2730 t2
2731 t1
2731 t1
2732 merge
2732 merge
2733 h2e
2733 h2e
2734 h2d
2734 h2d
2735 h1c
2735 h1c
2736 b
2736 b
2737 a
2737 a
2738
2738
2739 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
2739 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
2740 at3
2740 at3
2741 5
2741 5
2742 3
2742 3
2743 2
2743 2
2744 1
2744 1
2745 merg
2745 merg
2746 h2
2746 h2
2747 h2d
2747 h2d
2748 h1c
2748 h1c
2749 b
2749 b
2750 a
2750 a
2751
2751
2752 Test date format:
2752 Test date format:
2753
2753
2754 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
2754 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
2755 date: 70 01 01 10 +0000
2755 date: 70 01 01 10 +0000
2756 date: 70 01 01 09 +0000
2756 date: 70 01 01 09 +0000
2757 date: 70 01 01 08 +0000
2757 date: 70 01 01 08 +0000
2758 date: 70 01 01 07 +0000
2758 date: 70 01 01 07 +0000
2759 date: 70 01 01 06 +0000
2759 date: 70 01 01 06 +0000
2760 date: 70 01 01 05 +0100
2760 date: 70 01 01 05 +0100
2761 date: 70 01 01 04 +0000
2761 date: 70 01 01 04 +0000
2762 date: 70 01 01 03 +0000
2762 date: 70 01 01 03 +0000
2763 date: 70 01 01 02 +0000
2763 date: 70 01 01 02 +0000
2764 date: 70 01 01 01 +0000
2764 date: 70 01 01 01 +0000
2765 date: 70 01 01 00 +0000
2765 date: 70 01 01 00 +0000
2766
2766
2767 Test invalid date:
2767 Test invalid date:
2768
2768
2769 $ hg log -R latesttag -T '{date(rev)}\n'
2769 $ hg log -R latesttag -T '{date(rev)}\n'
2770 hg: parse error: date expects a date information
2770 hg: parse error: date expects a date information
2771 [255]
2771 [255]
2772
2772
2773 Test integer literal:
2773 Test integer literal:
2774
2774
2775 $ hg log -Ra -r0 -T '{(0)}\n'
2775 $ hg log -Ra -r0 -T '{(0)}\n'
2776 0
2776 0
2777 $ hg log -Ra -r0 -T '{(123)}\n'
2777 $ hg log -Ra -r0 -T '{(123)}\n'
2778 123
2778 123
2779 $ hg log -Ra -r0 -T '{(-4)}\n'
2779 $ hg log -Ra -r0 -T '{(-4)}\n'
2780 -4
2780 -4
2781 $ hg log -Ra -r0 -T '{(-)}\n'
2781 $ hg log -Ra -r0 -T '{(-)}\n'
2782 hg: parse error at 2: integer literal without digits
2782 hg: parse error at 2: integer literal without digits
2783 [255]
2783 [255]
2784 $ hg log -Ra -r0 -T '{(-a)}\n'
2784 $ hg log -Ra -r0 -T '{(-a)}\n'
2785 hg: parse error at 2: integer literal without digits
2785 hg: parse error at 2: integer literal without digits
2786 [255]
2786 [255]
2787
2787
2788 top-level integer literal is interpreted as symbol (i.e. variable name):
2788 top-level integer literal is interpreted as symbol (i.e. variable name):
2789
2789
2790 $ hg log -Ra -r0 -T '{1}\n'
2790 $ hg log -Ra -r0 -T '{1}\n'
2791
2791
2792 $ hg log -Ra -r0 -T '{if("t", "{1}")}\n'
2792 $ hg log -Ra -r0 -T '{if("t", "{1}")}\n'
2793
2793
2794 $ hg log -Ra -r0 -T '{1|stringify}\n'
2794 $ hg log -Ra -r0 -T '{1|stringify}\n'
2795
2795
2796
2796
2797 unless explicit symbol is expected:
2797 unless explicit symbol is expected:
2798
2798
2799 $ hg log -Ra -r0 -T '{desc|1}\n'
2799 $ hg log -Ra -r0 -T '{desc|1}\n'
2800 hg: parse error: expected a symbol, got 'integer'
2800 hg: parse error: expected a symbol, got 'integer'
2801 [255]
2801 [255]
2802 $ hg log -Ra -r0 -T '{1()}\n'
2802 $ hg log -Ra -r0 -T '{1()}\n'
2803 hg: parse error: expected a symbol, got 'integer'
2803 hg: parse error: expected a symbol, got 'integer'
2804 [255]
2804 [255]
2805
2805
2806 Test string literal:
2806 Test string literal:
2807
2807
2808 $ hg log -Ra -r0 -T '{"string with no template fragment"}\n'
2808 $ hg log -Ra -r0 -T '{"string with no template fragment"}\n'
2809 string with no template fragment
2809 string with no template fragment
2810 $ hg log -Ra -r0 -T '{"template: {rev}"}\n'
2810 $ hg log -Ra -r0 -T '{"template: {rev}"}\n'
2811 template: 0
2811 template: 0
2812 $ hg log -Ra -r0 -T '{r"rawstring: {rev}"}\n'
2812 $ hg log -Ra -r0 -T '{r"rawstring: {rev}"}\n'
2813 rawstring: {rev}
2813 rawstring: {rev}
2814
2814
2815 because map operation requires template, raw string can't be used
2816
2817 $ hg log -Ra -r0 -T '{files % r"rawstring"}\n'
2818 hg: parse error: expected template specifier
2819 [255]
2820
2815 Test string escaping:
2821 Test string escaping:
2816
2822
2817 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2823 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2818 >
2824 >
2819 <>\n<[>
2825 <>\n<[>
2820 <>\n<]>
2826 <>\n<]>
2821 <>\n<
2827 <>\n<
2822
2828
2823 $ hg log -R latesttag -r 0 \
2829 $ hg log -R latesttag -r 0 \
2824 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2830 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2825 >
2831 >
2826 <>\n<[>
2832 <>\n<[>
2827 <>\n<]>
2833 <>\n<]>
2828 <>\n<
2834 <>\n<
2829
2835
2830 $ hg log -R latesttag -r 0 -T esc \
2836 $ hg log -R latesttag -r 0 -T esc \
2831 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2837 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2832 >
2838 >
2833 <>\n<[>
2839 <>\n<[>
2834 <>\n<]>
2840 <>\n<]>
2835 <>\n<
2841 <>\n<
2836
2842
2837 $ cat <<'EOF' > esctmpl
2843 $ cat <<'EOF' > esctmpl
2838 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2844 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2839 > EOF
2845 > EOF
2840 $ hg log -R latesttag -r 0 --style ./esctmpl
2846 $ hg log -R latesttag -r 0 --style ./esctmpl
2841 >
2847 >
2842 <>\n<[>
2848 <>\n<[>
2843 <>\n<]>
2849 <>\n<]>
2844 <>\n<
2850 <>\n<
2845
2851
2846 Test exception in quoted template. single backslash before quotation mark is
2852 Test exception in quoted template. single backslash before quotation mark is
2847 stripped before parsing:
2853 stripped before parsing:
2848
2854
2849 $ cat <<'EOF' > escquotetmpl
2855 $ cat <<'EOF' > escquotetmpl
2850 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
2856 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
2851 > EOF
2857 > EOF
2852 $ cd latesttag
2858 $ cd latesttag
2853 $ hg log -r 2 --style ../escquotetmpl
2859 $ hg log -r 2 --style ../escquotetmpl
2854 " \" \" \\" head1
2860 " \" \" \\" head1
2855
2861
2856 $ hg log -r 2 -T esc --config templates.esc='{\"invalid\"}\n'
2862 $ hg log -r 2 -T esc --config templates.esc='{\"invalid\"}\n'
2857 hg: parse error at 1: syntax error
2863 hg: parse error at 1: syntax error
2858 [255]
2864 [255]
2859 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
2865 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
2860 valid
2866 valid
2861 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
2867 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
2862 valid
2868 valid
2863 $ cd ..
2869 $ cd ..
2864
2870
2865 Test leading backslashes:
2871 Test leading backslashes:
2866
2872
2867 $ cd latesttag
2873 $ cd latesttag
2868 $ hg log -r 2 -T '\{rev} {files % "\{file}"} {files % r"\{file}"}\n'
2874 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
2869 {rev} {file} \head1
2875 {rev} {file}
2870 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"} {files % r"\\{file}"}\n'
2876 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
2871 \2 \head1 \\head1
2877 \2 \head1
2872 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"} {files % r"\\\{file}"}\n'
2878 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
2873 \{rev} \{file} \\\head1
2879 \{rev} \{file}
2874 $ cd ..
2880 $ cd ..
2875
2881
2876 Test leading backslashes in "if" expression (issue4714):
2882 Test leading backslashes in "if" expression (issue4714):
2877
2883
2878 $ cd latesttag
2884 $ cd latesttag
2879 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
2885 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
2880 {rev} \2
2886 {rev} \{rev}
2881 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
2887 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
2882 \2 \\2
2888 \2 \\{rev}
2883 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
2889 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
2884 \{rev} \\\2
2890 \{rev} \\\{rev}
2885 $ cd ..
2891 $ cd ..
2886
2892
2887 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
2893 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
2888
2894
2889 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
2895 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
2890 \x6e
2896 \x6e
2891 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
2897 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
2892 \x5c\x786e
2898 \x5c\x786e
2893 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
2899 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
2894 \x6e
2900 \x6e
2895 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
2901 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
2896 \x5c\x786e
2902 \x5c\x786e
2897
2903
2898 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
2904 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
2899 \x6e
2905 \x6e
2900 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
2906 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
2901 \x5c\x786e
2907 \x5c\x786e
2902 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
2908 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
2903 \x6e
2909 \x6e
2904 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
2910 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
2905 \x5c\x786e
2911 \x5c\x786e
2906
2912
2907 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
2913 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
2908 fourth
2914 fourth
2909 second
2915 second
2910 third
2916 third
2911 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
2917 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
2912 fourth\nsecond\nthird
2918 fourth\nsecond\nthird
2913
2919
2914 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
2920 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
2915 <p>
2921 <p>
2916 1st
2922 1st
2917 </p>
2923 </p>
2918 <p>
2924 <p>
2919 2nd
2925 2nd
2920 </p>
2926 </p>
2921 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
2927 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
2922 <p>
2928 <p>
2923 1st\n\n2nd
2929 1st\n\n2nd
2924 </p>
2930 </p>
2925 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
2931 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
2926 1st
2932 1st
2927
2933
2928 2nd
2934 2nd
2929
2935
2930 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
2936 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
2931 o perso
2937 o perso
2932 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
2938 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
2933 no person
2939 no person
2934 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
2940 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
2935 o perso
2941 o perso
2936 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
2942 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
2937 no perso
2943 no perso
2938
2944
2939 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
2945 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
2940 -o perso-
2946 -o perso-
2941 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
2947 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
2942 no person
2948 no person
2943 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
2949 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
2944 \x2do perso\x2d
2950 \x2do perso\x2d
2945 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
2951 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
2946 -o perso-
2952 -o perso-
2947 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
2953 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
2948 \x2do perso\x6e
2954 \x2do perso\x6e
2949
2955
2950 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
2956 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
2951 fourth
2957 fourth
2952 second
2958 second
2953 third
2959 third
2954 $ hg log -R a -r 8 --template '{files % r"{file}\n"}\n'
2955 fourth\nsecond\nthird\n
2956
2960
2957 Test string escaping in nested expression:
2961 Test string escaping in nested expression:
2958
2962
2959 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
2963 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
2960 fourth\x6esecond\x6ethird
2964 fourth\x6esecond\x6ethird
2961 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
2965 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
2962 fourth\x6esecond\x6ethird
2966 fourth\x6esecond\x6ethird
2963
2967
2964 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
2968 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
2965 fourth\x6esecond\x6ethird
2969 fourth\x6esecond\x6ethird
2966 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
2970 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
2967 fourth\x5c\x786esecond\x5c\x786ethird
2971 fourth\x5c\x786esecond\x5c\x786ethird
2968
2972
2969 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
2973 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
2970 3:\x6eo user, \x6eo domai\x6e
2974 3:\x6eo user, \x6eo domai\x6e
2971 4:\x5c\x786eew bra\x5c\x786ech
2975 4:\x5c\x786eew bra\x5c\x786ech
2972
2976
2973 Test recursive evaluation:
2977 Test recursive evaluation:
2974
2978
2975 $ hg init r
2979 $ hg init r
2976 $ cd r
2980 $ cd r
2977 $ echo a > a
2981 $ echo a > a
2978 $ hg ci -Am '{rev}'
2982 $ hg ci -Am '{rev}'
2979 adding a
2983 adding a
2980 $ hg log -r 0 --template '{if(rev, desc)}\n'
2984 $ hg log -r 0 --template '{if(rev, desc)}\n'
2981 {rev}
2985 {rev}
2982 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
2986 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
2983 test 0
2987 test 0
2984
2988
2985 $ hg branch -q 'text.{rev}'
2989 $ hg branch -q 'text.{rev}'
2986 $ echo aa >> aa
2990 $ echo aa >> aa
2987 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
2991 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
2988
2992
2989 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
2993 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
2990 {node|short}desc to
2994 {node|short}desc to
2991 text.{rev}be wrapped
2995 text.{rev}be wrapped
2992 text.{rev}desc to be
2996 text.{rev}desc to be
2993 text.{rev}wrapped (no-eol)
2997 text.{rev}wrapped (no-eol)
2994 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
2998 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
2995 bcc7ff960b8e:desc to
2999 bcc7ff960b8e:desc to
2996 text.1:be wrapped
3000 text.1:be wrapped
2997 text.1:desc to be
3001 text.1:desc to be
2998 text.1:wrapped (no-eol)
3002 text.1:wrapped (no-eol)
2999
3003
3000 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
3004 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
3001 {node|short} (no-eol)
3005 {node|short} (no-eol)
3002 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
3006 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
3003 bcc-ff---b-e (no-eol)
3007 bcc-ff---b-e (no-eol)
3004
3008
3005 $ cat >> .hg/hgrc <<EOF
3009 $ cat >> .hg/hgrc <<EOF
3006 > [extensions]
3010 > [extensions]
3007 > color=
3011 > color=
3008 > [color]
3012 > [color]
3009 > mode=ansi
3013 > mode=ansi
3010 > text.{rev} = red
3014 > text.{rev} = red
3011 > text.1 = green
3015 > text.1 = green
3012 > EOF
3016 > EOF
3013 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
3017 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
3014 \x1b[0;31mtext\x1b[0m (esc)
3018 \x1b[0;31mtext\x1b[0m (esc)
3015 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
3019 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
3016 \x1b[0;32mtext\x1b[0m (esc)
3020 \x1b[0;32mtext\x1b[0m (esc)
3017
3021
3018 Test branches inside if statement:
3022 Test branches inside if statement:
3019
3023
3020 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
3024 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
3021 no
3025 no
3022
3026
3023 Test get function:
3027 Test get function:
3024
3028
3025 $ hg log -r 0 --template '{get(extras, "branch")}\n'
3029 $ hg log -r 0 --template '{get(extras, "branch")}\n'
3026 default
3030 default
3027 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3031 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3028 hg: parse error: get() expects a dict as first argument
3032 hg: parse error: get() expects a dict as first argument
3029 [255]
3033 [255]
3030
3034
3031 Test shortest(node) function:
3035 Test shortest(node) function:
3032
3036
3033 $ echo b > b
3037 $ echo b > b
3034 $ hg ci -qAm b
3038 $ hg ci -qAm b
3035 $ hg log --template '{shortest(node)}\n'
3039 $ hg log --template '{shortest(node)}\n'
3036 e777
3040 e777
3037 bcc7
3041 bcc7
3038 f776
3042 f776
3039 $ hg log --template '{shortest(node, 10)}\n'
3043 $ hg log --template '{shortest(node, 10)}\n'
3040 e777603221
3044 e777603221
3041 bcc7ff960b
3045 bcc7ff960b
3042 f7769ec2ab
3046 f7769ec2ab
3043
3047
3044 Test pad function
3048 Test pad function
3045
3049
3046 $ hg log --template '{pad(rev, 20)} {author|user}\n'
3050 $ hg log --template '{pad(rev, 20)} {author|user}\n'
3047 2 test
3051 2 test
3048 1 {node|short}
3052 1 {node|short}
3049 0 test
3053 0 test
3050
3054
3051 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
3055 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
3052 2 test
3056 2 test
3053 1 {node|short}
3057 1 {node|short}
3054 0 test
3058 0 test
3055
3059
3056 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
3060 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
3057 2------------------- test
3061 2------------------- test
3058 1------------------- {node|short}
3062 1------------------- {node|short}
3059 0------------------- test
3063 0------------------- test
3060
3064
3061 Test template string in pad function
3065 Test template string in pad function
3062
3066
3063 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
3067 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
3064 {0} test
3068 {0} test
3065
3069
3066 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
3070 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
3067 \0 test
3071 \{rev} test
3068
3072
3069 Test ifcontains function
3073 Test ifcontains function
3070
3074
3071 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
3075 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
3072 2 is in the string
3076 2 is in the string
3073 1 is not
3077 1 is not
3074 0 is in the string
3078 0 is in the string
3075
3079
3076 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
3080 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
3077 2 did not add a
3081 2 did not add a
3078 1 did not add a
3082 1 did not add a
3079 0 added a
3083 0 added a
3080
3084
3081 Test revset function
3085 Test revset function
3082
3086
3083 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
3087 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
3084 2 current rev
3088 2 current rev
3085 1 not current rev
3089 1 not current rev
3086 0 not current rev
3090 0 not current rev
3087
3091
3088 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
3092 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
3089 2 match rev
3093 2 match rev
3090 1 match rev
3094 1 match rev
3091 0 not match rev
3095 0 not match rev
3092
3096
3093 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
3097 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
3094 2 Parents: 1
3098 2 Parents: 1
3095 1 Parents: 0
3099 1 Parents: 0
3096 0 Parents:
3100 0 Parents:
3097
3101
3098 $ cat >> .hg/hgrc <<EOF
3102 $ cat >> .hg/hgrc <<EOF
3099 > [revsetalias]
3103 > [revsetalias]
3100 > myparents(\$1) = parents(\$1)
3104 > myparents(\$1) = parents(\$1)
3101 > EOF
3105 > EOF
3102 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
3106 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
3103 2 Parents: 1
3107 2 Parents: 1
3104 1 Parents: 0
3108 1 Parents: 0
3105 0 Parents:
3109 0 Parents:
3106
3110
3107 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
3111 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
3108 Rev: 2
3112 Rev: 2
3109 Ancestor: 0
3113 Ancestor: 0
3110 Ancestor: 1
3114 Ancestor: 1
3111 Ancestor: 2
3115 Ancestor: 2
3112
3116
3113 Rev: 1
3117 Rev: 1
3114 Ancestor: 0
3118 Ancestor: 0
3115 Ancestor: 1
3119 Ancestor: 1
3116
3120
3117 Rev: 0
3121 Rev: 0
3118 Ancestor: 0
3122 Ancestor: 0
3119
3123
3120 Test active bookmark templating
3124 Test active bookmark templating
3121
3125
3122 $ hg book foo
3126 $ hg book foo
3123 $ hg book bar
3127 $ hg book bar
3124 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
3128 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
3125 2 bar* foo
3129 2 bar* foo
3126 1
3130 1
3127 0
3131 0
3128 $ hg log --template "{rev} {activebookmark}\n"
3132 $ hg log --template "{rev} {activebookmark}\n"
3129 2 bar
3133 2 bar
3130 1
3134 1
3131 0
3135 0
3132 $ hg bookmarks --inactive bar
3136 $ hg bookmarks --inactive bar
3133 $ hg log --template "{rev} {activebookmark}\n"
3137 $ hg log --template "{rev} {activebookmark}\n"
3134 2
3138 2
3135 1
3139 1
3136 0
3140 0
3137 $ hg book -r1 baz
3141 $ hg book -r1 baz
3138 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
3142 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
3139 2 bar foo
3143 2 bar foo
3140 1 baz
3144 1 baz
3141 0
3145 0
3142 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
3146 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
3143 2 t
3147 2 t
3144 1 f
3148 1 f
3145 0 f
3149 0 f
3146
3150
3147 Test stringify on sub expressions
3151 Test stringify on sub expressions
3148
3152
3149 $ cd ..
3153 $ cd ..
3150 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
3154 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
3151 fourth, second, third
3155 fourth, second, third
3152 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
3156 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
3153 abc
3157 abc
3154
3158
3155 Test splitlines
3159 Test splitlines
3156
3160
3157 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
3161 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
3158 @ foo Modify, add, remove, rename
3162 @ foo Modify, add, remove, rename
3159 |
3163 |
3160 o foo future
3164 o foo future
3161 |
3165 |
3162 o foo third
3166 o foo third
3163 |
3167 |
3164 o foo second
3168 o foo second
3165
3169
3166 o foo merge
3170 o foo merge
3167 |\
3171 |\
3168 | o foo new head
3172 | o foo new head
3169 | |
3173 | |
3170 o | foo new branch
3174 o | foo new branch
3171 |/
3175 |/
3172 o foo no user, no domain
3176 o foo no user, no domain
3173 |
3177 |
3174 o foo no person
3178 o foo no person
3175 |
3179 |
3176 o foo other 1
3180 o foo other 1
3177 | foo other 2
3181 | foo other 2
3178 | foo
3182 | foo
3179 | foo other 3
3183 | foo other 3
3180 o foo line 1
3184 o foo line 1
3181 foo line 2
3185 foo line 2
3182
3186
3183 Test startswith
3187 Test startswith
3184 $ hg log -Gv -R a --template "{startswith(desc)}"
3188 $ hg log -Gv -R a --template "{startswith(desc)}"
3185 hg: parse error: startswith expects two arguments
3189 hg: parse error: startswith expects two arguments
3186 [255]
3190 [255]
3187
3191
3188 $ hg log -Gv -R a --template "{startswith('line', desc)}"
3192 $ hg log -Gv -R a --template "{startswith('line', desc)}"
3189 @
3193 @
3190 |
3194 |
3191 o
3195 o
3192 |
3196 |
3193 o
3197 o
3194 |
3198 |
3195 o
3199 o
3196
3200
3197 o
3201 o
3198 |\
3202 |\
3199 | o
3203 | o
3200 | |
3204 | |
3201 o |
3205 o |
3202 |/
3206 |/
3203 o
3207 o
3204 |
3208 |
3205 o
3209 o
3206 |
3210 |
3207 o
3211 o
3208 |
3212 |
3209 o line 1
3213 o line 1
3210 line 2
3214 line 2
3211
3215
3212 Test bad template with better error message
3216 Test bad template with better error message
3213
3217
3214 $ hg log -Gv -R a --template '{desc|user()}'
3218 $ hg log -Gv -R a --template '{desc|user()}'
3215 hg: parse error: expected a symbol, got 'func'
3219 hg: parse error: expected a symbol, got 'func'
3216 [255]
3220 [255]
3217
3221
3218 Test word function (including index out of bounds graceful failure)
3222 Test word function (including index out of bounds graceful failure)
3219
3223
3220 $ hg log -Gv -R a --template "{word('1', desc)}"
3224 $ hg log -Gv -R a --template "{word('1', desc)}"
3221 @ add,
3225 @ add,
3222 |
3226 |
3223 o
3227 o
3224 |
3228 |
3225 o
3229 o
3226 |
3230 |
3227 o
3231 o
3228
3232
3229 o
3233 o
3230 |\
3234 |\
3231 | o head
3235 | o head
3232 | |
3236 | |
3233 o | branch
3237 o | branch
3234 |/
3238 |/
3235 o user,
3239 o user,
3236 |
3240 |
3237 o person
3241 o person
3238 |
3242 |
3239 o 1
3243 o 1
3240 |
3244 |
3241 o 1
3245 o 1
3242
3246
3243
3247
3244 Test word third parameter used as splitter
3248 Test word third parameter used as splitter
3245
3249
3246 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
3250 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
3247 @ M
3251 @ M
3248 |
3252 |
3249 o future
3253 o future
3250 |
3254 |
3251 o third
3255 o third
3252 |
3256 |
3253 o sec
3257 o sec
3254
3258
3255 o merge
3259 o merge
3256 |\
3260 |\
3257 | o new head
3261 | o new head
3258 | |
3262 | |
3259 o | new branch
3263 o | new branch
3260 |/
3264 |/
3261 o n
3265 o n
3262 |
3266 |
3263 o n
3267 o n
3264 |
3268 |
3265 o
3269 o
3266 |
3270 |
3267 o line 1
3271 o line 1
3268 line 2
3272 line 2
3269
3273
3270 Test word error messages for not enough and too many arguments
3274 Test word error messages for not enough and too many arguments
3271
3275
3272 $ hg log -Gv -R a --template "{word('0')}"
3276 $ hg log -Gv -R a --template "{word('0')}"
3273 hg: parse error: word expects two or three arguments, got 1
3277 hg: parse error: word expects two or three arguments, got 1
3274 [255]
3278 [255]
3275
3279
3276 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
3280 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
3277 hg: parse error: word expects two or three arguments, got 7
3281 hg: parse error: word expects two or three arguments, got 7
3278 [255]
3282 [255]
3279
3283
3280 Test word for integer literal
3284 Test word for integer literal
3281
3285
3282 $ hg log -R a --template "{word(2, desc)}\n" -r0
3286 $ hg log -R a --template "{word(2, desc)}\n" -r0
3283 line
3287 line
3284
3288
3285 Test word for invalid numbers
3289 Test word for invalid numbers
3286
3290
3287 $ hg log -Gv -R a --template "{word('a', desc)}"
3291 $ hg log -Gv -R a --template "{word('a', desc)}"
3288 hg: parse error: word expects an integer index
3292 hg: parse error: word expects an integer index
3289 [255]
3293 [255]
3290
3294
3291 Test indent and not adding to empty lines
3295 Test indent and not adding to empty lines
3292
3296
3293 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
3297 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
3294 -----
3298 -----
3295 > line 1
3299 > line 1
3296 >> line 2
3300 >> line 2
3297 -----
3301 -----
3298 > other 1
3302 > other 1
3299 >> other 2
3303 >> other 2
3300
3304
3301 >> other 3
3305 >> other 3
3302
3306
3303 Test with non-strings like dates
3307 Test with non-strings like dates
3304
3308
3305 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
3309 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
3306 1200000.00
3310 1200000.00
3307 1300000.00
3311 1300000.00
General Comments 0
You need to be logged in to leave comments. Login now