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