##// END OF EJS Templates
tests: fix up some lax escaping in test-template-basic.t...
Augie Fackler -
r38495:b4cfd803 default
parent child Browse files
Show More
@@ -1,1088 +1,1088 b''
1 Test template syntax and basic functionality
1 Test template syntax and basic functionality
2 ============================================
2 ============================================
3
3
4 $ hg init a
4 $ hg init a
5 $ cd a
5 $ cd a
6 $ echo a > a
6 $ echo a > a
7 $ hg add a
7 $ hg add a
8 $ echo line 1 > b
8 $ echo line 1 > b
9 $ echo line 2 >> b
9 $ echo line 2 >> b
10 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
10 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
11
11
12 $ hg add b
12 $ hg add b
13 $ echo other 1 > c
13 $ echo other 1 > c
14 $ echo other 2 >> c
14 $ echo other 2 >> c
15 $ echo >> c
15 $ echo >> c
16 $ echo other 3 >> c
16 $ echo other 3 >> c
17 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
17 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
18
18
19 $ hg add c
19 $ hg add c
20 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
20 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
21 $ echo c >> c
21 $ echo c >> c
22 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
22 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
23
23
24 $ echo foo > .hg/branch
24 $ echo foo > .hg/branch
25 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
25 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
26
26
27 $ hg co -q 3
27 $ hg co -q 3
28 $ echo other 4 >> d
28 $ echo other 4 >> d
29 $ hg add d
29 $ hg add d
30 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
30 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
31
31
32 $ hg merge -q foo
32 $ hg merge -q foo
33 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
33 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
34
34
35 Test arithmetic operators have the right precedence:
35 Test arithmetic operators have the right precedence:
36
36
37 $ hg log -l 1 -T '{date(date, "%Y") + 5 * 10} {date(date, "%Y") - 2 * 3}\n'
37 $ hg log -l 1 -T '{date(date, "%Y") + 5 * 10} {date(date, "%Y") - 2 * 3}\n'
38 2020 1964
38 2020 1964
39 $ hg log -l 1 -T '{date(date, "%Y") * 5 + 10} {date(date, "%Y") * 3 - 2}\n'
39 $ hg log -l 1 -T '{date(date, "%Y") * 5 + 10} {date(date, "%Y") * 3 - 2}\n'
40 9860 5908
40 9860 5908
41
41
42 Test division:
42 Test division:
43
43
44 $ hg debugtemplate -r0 -v '{5 / 2} {mod(5, 2)}\n'
44 $ hg debugtemplate -r0 -v '{5 / 2} {mod(5, 2)}\n'
45 (template
45 (template
46 (/
46 (/
47 (integer '5')
47 (integer '5')
48 (integer '2'))
48 (integer '2'))
49 (string ' ')
49 (string ' ')
50 (func
50 (func
51 (symbol 'mod')
51 (symbol 'mod')
52 (list
52 (list
53 (integer '5')
53 (integer '5')
54 (integer '2')))
54 (integer '2')))
55 (string '\n'))
55 (string '\n'))
56 * keywords:
56 * keywords:
57 * functions: mod
57 * functions: mod
58 2 1
58 2 1
59 $ hg debugtemplate -r0 -v '{5 / -2} {mod(5, -2)}\n'
59 $ hg debugtemplate -r0 -v '{5 / -2} {mod(5, -2)}\n'
60 (template
60 (template
61 (/
61 (/
62 (integer '5')
62 (integer '5')
63 (negate
63 (negate
64 (integer '2')))
64 (integer '2')))
65 (string ' ')
65 (string ' ')
66 (func
66 (func
67 (symbol 'mod')
67 (symbol 'mod')
68 (list
68 (list
69 (integer '5')
69 (integer '5')
70 (negate
70 (negate
71 (integer '2'))))
71 (integer '2'))))
72 (string '\n'))
72 (string '\n'))
73 * keywords:
73 * keywords:
74 * functions: mod
74 * functions: mod
75 -3 -1
75 -3 -1
76 $ hg debugtemplate -r0 -v '{-5 / 2} {mod(-5, 2)}\n'
76 $ hg debugtemplate -r0 -v '{-5 / 2} {mod(-5, 2)}\n'
77 (template
77 (template
78 (/
78 (/
79 (negate
79 (negate
80 (integer '5'))
80 (integer '5'))
81 (integer '2'))
81 (integer '2'))
82 (string ' ')
82 (string ' ')
83 (func
83 (func
84 (symbol 'mod')
84 (symbol 'mod')
85 (list
85 (list
86 (negate
86 (negate
87 (integer '5'))
87 (integer '5'))
88 (integer '2')))
88 (integer '2')))
89 (string '\n'))
89 (string '\n'))
90 * keywords:
90 * keywords:
91 * functions: mod
91 * functions: mod
92 -3 1
92 -3 1
93 $ hg debugtemplate -r0 -v '{-5 / -2} {mod(-5, -2)}\n'
93 $ hg debugtemplate -r0 -v '{-5 / -2} {mod(-5, -2)}\n'
94 (template
94 (template
95 (/
95 (/
96 (negate
96 (negate
97 (integer '5'))
97 (integer '5'))
98 (negate
98 (negate
99 (integer '2')))
99 (integer '2')))
100 (string ' ')
100 (string ' ')
101 (func
101 (func
102 (symbol 'mod')
102 (symbol 'mod')
103 (list
103 (list
104 (negate
104 (negate
105 (integer '5'))
105 (integer '5'))
106 (negate
106 (negate
107 (integer '2'))))
107 (integer '2'))))
108 (string '\n'))
108 (string '\n'))
109 * keywords:
109 * keywords:
110 * functions: mod
110 * functions: mod
111 2 -1
111 2 -1
112
112
113 Filters bind closer than arithmetic:
113 Filters bind closer than arithmetic:
114
114
115 $ hg debugtemplate -r0 -v '{revset(".")|count - 1}\n'
115 $ hg debugtemplate -r0 -v '{revset(".")|count - 1}\n'
116 (template
116 (template
117 (-
117 (-
118 (|
118 (|
119 (func
119 (func
120 (symbol 'revset')
120 (symbol 'revset')
121 (string '.'))
121 (string '.'))
122 (symbol 'count'))
122 (symbol 'count'))
123 (integer '1'))
123 (integer '1'))
124 (string '\n'))
124 (string '\n'))
125 * keywords:
125 * keywords:
126 * functions: count, revset
126 * functions: count, revset
127 0
127 0
128
128
129 But negate binds closer still:
129 But negate binds closer still:
130
130
131 $ hg debugtemplate -r0 -v '{1-3|stringify}\n'
131 $ hg debugtemplate -r0 -v '{1-3|stringify}\n'
132 (template
132 (template
133 (-
133 (-
134 (integer '1')
134 (integer '1')
135 (|
135 (|
136 (integer '3')
136 (integer '3')
137 (symbol 'stringify')))
137 (symbol 'stringify')))
138 (string '\n'))
138 (string '\n'))
139 * keywords:
139 * keywords:
140 * functions: stringify
140 * functions: stringify
141 hg: parse error: arithmetic only defined on integers
141 hg: parse error: arithmetic only defined on integers
142 [255]
142 [255]
143 $ hg debugtemplate -r0 -v '{-3|stringify}\n'
143 $ hg debugtemplate -r0 -v '{-3|stringify}\n'
144 (template
144 (template
145 (|
145 (|
146 (negate
146 (negate
147 (integer '3'))
147 (integer '3'))
148 (symbol 'stringify'))
148 (symbol 'stringify'))
149 (string '\n'))
149 (string '\n'))
150 * keywords:
150 * keywords:
151 * functions: stringify
151 * functions: stringify
152 -3
152 -3
153
153
154 Filters bind as close as map operator:
154 Filters bind as close as map operator:
155
155
156 $ hg debugtemplate -r0 -v '{desc|splitlines % "{line}\n"}'
156 $ hg debugtemplate -r0 -v '{desc|splitlines % "{line}\n"}'
157 (template
157 (template
158 (%
158 (%
159 (|
159 (|
160 (symbol 'desc')
160 (symbol 'desc')
161 (symbol 'splitlines'))
161 (symbol 'splitlines'))
162 (template
162 (template
163 (symbol 'line')
163 (symbol 'line')
164 (string '\n'))))
164 (string '\n'))))
165 * keywords: desc, line
165 * keywords: desc, line
166 * functions: splitlines
166 * functions: splitlines
167 line 1
167 line 1
168 line 2
168 line 2
169
169
170 Keyword arguments:
170 Keyword arguments:
171
171
172 $ hg debugtemplate -r0 -v '{foo=bar|baz}'
172 $ hg debugtemplate -r0 -v '{foo=bar|baz}'
173 (template
173 (template
174 (keyvalue
174 (keyvalue
175 (symbol 'foo')
175 (symbol 'foo')
176 (|
176 (|
177 (symbol 'bar')
177 (symbol 'bar')
178 (symbol 'baz'))))
178 (symbol 'baz'))))
179 * keywords: bar, foo
179 * keywords: bar, foo
180 * functions: baz
180 * functions: baz
181 hg: parse error: can't use a key-value pair in this context
181 hg: parse error: can't use a key-value pair in this context
182 [255]
182 [255]
183
183
184 $ hg debugtemplate '{pad("foo", width=10, left=true)}\n'
184 $ hg debugtemplate '{pad("foo", width=10, left=true)}\n'
185 foo
185 foo
186
186
187 Call function which takes named arguments by filter syntax:
187 Call function which takes named arguments by filter syntax:
188
188
189 $ hg debugtemplate '{" "|separate}'
189 $ hg debugtemplate '{" "|separate}'
190 $ hg debugtemplate '{("not", "an", "argument", "list")|separate}'
190 $ hg debugtemplate '{("not", "an", "argument", "list")|separate}'
191 hg: parse error: unknown method 'list'
191 hg: parse error: unknown method 'list'
192 [255]
192 [255]
193
193
194 Second branch starting at nullrev:
194 Second branch starting at nullrev:
195
195
196 $ hg update null
196 $ hg update null
197 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
197 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
198 $ echo second > second
198 $ echo second > second
199 $ hg add second
199 $ hg add second
200 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
200 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
201 created new head
201 created new head
202
202
203 $ echo third > third
203 $ echo third > third
204 $ hg add third
204 $ hg add third
205 $ hg mv second fourth
205 $ hg mv second fourth
206 $ hg commit -m third -d "2020-01-01 10:01"
206 $ hg commit -m third -d "2020-01-01 10:01"
207
207
208 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
208 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
209 fourth (second)
209 fourth (second)
210 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
210 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
211 second -> fourth
211 second -> fourth
212 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
212 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
213 8 t
213 8 t
214 7 f
214 7 f
215
215
216 Internal resources shouldn't be exposed (issue5699):
216 Internal resources shouldn't be exposed (issue5699):
217
217
218 $ hg log -r. -T '{cache}{ctx}{repo}{revcache}{templ}{ui}'
218 $ hg log -r. -T '{cache}{ctx}{repo}{revcache}{templ}{ui}'
219
219
220 Never crash on internal resource not available:
220 Never crash on internal resource not available:
221
221
222 $ hg --cwd .. debugtemplate '{"c0bebeef"|shortest}\n'
222 $ hg --cwd .. debugtemplate '{"c0bebeef"|shortest}\n'
223 abort: template resource not available: repo
223 abort: template resource not available: repo
224 [255]
224 [255]
225
225
226 $ hg config -T '{author}'
226 $ hg config -T '{author}'
227
227
228 Quoting for ui.logtemplate
228 Quoting for ui.logtemplate
229
229
230 $ hg tip --config "ui.logtemplate={rev}\n"
230 $ hg tip --config "ui.logtemplate={rev}\n"
231 8
231 8
232 $ hg tip --config "ui.logtemplate='{rev}\n'"
232 $ hg tip --config "ui.logtemplate='{rev}\n'"
233 8
233 8
234 $ hg tip --config 'ui.logtemplate="{rev}\n"'
234 $ hg tip --config 'ui.logtemplate="{rev}\n"'
235 8
235 8
236 $ hg tip --config 'ui.logtemplate=n{rev}\n'
236 $ hg tip --config 'ui.logtemplate=n{rev}\n'
237 n8
237 n8
238
238
239 Check that recursive reference does not fall into RuntimeError (issue4758):
239 Check that recursive reference does not fall into RuntimeError (issue4758):
240
240
241 common mistake:
241 common mistake:
242
242
243 $ cat << EOF > issue4758
243 $ cat << EOF > issue4758
244 > changeset = '{changeset}\n'
244 > changeset = '{changeset}\n'
245 > EOF
245 > EOF
246 $ hg log --style ./issue4758
246 $ hg log --style ./issue4758
247 abort: recursive reference 'changeset' in template
247 abort: recursive reference 'changeset' in template
248 [255]
248 [255]
249
249
250 circular reference:
250 circular reference:
251
251
252 $ cat << EOF > issue4758
252 $ cat << EOF > issue4758
253 > changeset = '{foo}'
253 > changeset = '{foo}'
254 > foo = '{changeset}'
254 > foo = '{changeset}'
255 > EOF
255 > EOF
256 $ hg log --style ./issue4758
256 $ hg log --style ./issue4758
257 abort: recursive reference 'foo' in template
257 abort: recursive reference 'foo' in template
258 [255]
258 [255]
259
259
260 buildmap() -> gettemplate(), where no thunk was made:
260 buildmap() -> gettemplate(), where no thunk was made:
261
261
262 $ cat << EOF > issue4758
262 $ cat << EOF > issue4758
263 > changeset = '{files % changeset}\n'
263 > changeset = '{files % changeset}\n'
264 > EOF
264 > EOF
265 $ hg log --style ./issue4758
265 $ hg log --style ./issue4758
266 abort: recursive reference 'changeset' in template
266 abort: recursive reference 'changeset' in template
267 [255]
267 [255]
268
268
269 not a recursion if a keyword of the same name exists:
269 not a recursion if a keyword of the same name exists:
270
270
271 $ cat << EOF > issue4758
271 $ cat << EOF > issue4758
272 > changeset = '{tags % rev}'
272 > changeset = '{tags % rev}'
273 > rev = '{rev} {tag}\n'
273 > rev = '{rev} {tag}\n'
274 > EOF
274 > EOF
275 $ hg log --style ./issue4758 -r tip
275 $ hg log --style ./issue4758 -r tip
276 8 tip
276 8 tip
277
277
278 Set up phase:
278 Set up phase:
279
279
280 $ hg phase -r 5 --public
280 $ hg phase -r 5 --public
281 $ hg phase -r 7 --secret --force
281 $ hg phase -r 7 --secret --force
282
282
283 Add a dummy commit to make up for the instability of the above:
283 Add a dummy commit to make up for the instability of the above:
284
284
285 $ echo a > a
285 $ echo a > a
286 $ hg add a
286 $ hg add a
287 $ hg ci -m future
287 $ hg ci -m future
288
288
289 Add a commit that does all possible modifications at once
289 Add a commit that does all possible modifications at once
290
290
291 $ echo modify >> third
291 $ echo modify >> third
292 $ touch b
292 $ touch b
293 $ hg add b
293 $ hg add b
294 $ hg mv fourth fifth
294 $ hg mv fourth fifth
295 $ hg rm a
295 $ hg rm a
296 $ hg ci -m "Modify, add, remove, rename"
296 $ hg ci -m "Modify, add, remove, rename"
297
297
298 Error on syntax:
298 Error on syntax:
299
299
300 $ cat <<EOF > t
300 $ cat <<EOF > t
301 > changeset = '{c}'
301 > changeset = '{c}'
302 > c = q
302 > c = q
303 > x = "f
303 > x = "f
304 > EOF
304 > EOF
305 $ echo '[ui]' > .hg/hgrc
305 $ echo '[ui]' > .hg/hgrc
306 $ echo 'style = t' >> .hg/hgrc
306 $ echo 'style = t' >> .hg/hgrc
307 $ hg log
307 $ hg log
308 hg: parse error at t:3: unmatched quotes
308 hg: parse error at t:3: unmatched quotes
309 [255]
309 [255]
310
310
311 $ hg log -T '{date'
311 $ hg log -T '{date'
312 hg: parse error at 1: unterminated template expansion
312 hg: parse error at 1: unterminated template expansion
313 ({date
313 ({date
314 ^ here)
314 ^ here)
315 [255]
315 [255]
316 $ hg log -T '{date(}'
316 $ hg log -T '{date(}'
317 hg: parse error at 6: not a prefix: end
317 hg: parse error at 6: not a prefix: end
318 ({date(}
318 ({date(}
319 ^ here)
319 ^ here)
320 [255]
320 [255]
321 $ hg log -T '{date)}'
321 $ hg log -T '{date)}'
322 hg: parse error at 5: invalid token
322 hg: parse error at 5: invalid token
323 ({date)}
323 ({date)}
324 ^ here)
324 ^ here)
325 [255]
325 [255]
326 $ hg log -T '{date date}'
326 $ hg log -T '{date date}'
327 hg: parse error at 6: invalid token
327 hg: parse error at 6: invalid token
328 ({date date}
328 ({date date}
329 ^ here)
329 ^ here)
330 [255]
330 [255]
331
331
332 $ hg log -T '{}'
332 $ hg log -T '{}'
333 hg: parse error at 1: not a prefix: end
333 hg: parse error at 1: not a prefix: end
334 ({}
334 ({}
335 ^ here)
335 ^ here)
336 [255]
336 [255]
337 $ hg debugtemplate -v '{()}'
337 $ hg debugtemplate -v '{()}'
338 (template
338 (template
339 (group
339 (group
340 None))
340 None))
341 * keywords:
341 * keywords:
342 * functions:
342 * functions:
343 hg: parse error: missing argument
343 hg: parse error: missing argument
344 [255]
344 [255]
345
345
346 Behind the scenes, this would throw TypeError without intype=bytes
346 Behind the scenes, this would throw TypeError without intype=bytes
347
347
348 $ hg log -l 3 --template '{date|obfuscate}\n'
348 $ hg log -l 3 --template '{date|obfuscate}\n'
349 &#48;&#46;&#48;&#48;
349 &#48;&#46;&#48;&#48;
350 &#48;&#46;&#48;&#48;
350 &#48;&#46;&#48;&#48;
351 &#49;&#53;&#55;&#55;&#56;&#55;&#50;&#56;&#54;&#48;&#46;&#48;&#48;
351 &#49;&#53;&#55;&#55;&#56;&#55;&#50;&#56;&#54;&#48;&#46;&#48;&#48;
352
352
353 Behind the scenes, this will throw a ValueError
353 Behind the scenes, this will throw a ValueError
354
354
355 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
355 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
356 hg: parse error: invalid date: 'Modify, add, remove, rename'
356 hg: parse error: invalid date: 'Modify, add, remove, rename'
357 (template filter 'shortdate' is not compatible with keyword 'desc')
357 (template filter 'shortdate' is not compatible with keyword 'desc')
358 [255]
358 [255]
359
359
360 Behind the scenes, this would throw AttributeError without intype=bytes
360 Behind the scenes, this would throw AttributeError without intype=bytes
361
361
362 $ hg log -l 3 --template 'line: {date|escape}\n'
362 $ hg log -l 3 --template 'line: {date|escape}\n'
363 line: 0.00
363 line: 0.00
364 line: 0.00
364 line: 0.00
365 line: 1577872860.00
365 line: 1577872860.00
366
366
367 $ hg log -l 3 --template 'line: {extras|localdate}\n'
367 $ hg log -l 3 --template 'line: {extras|localdate}\n'
368 hg: parse error: localdate expects a date information
368 hg: parse error: localdate expects a date information
369 [255]
369 [255]
370
370
371 Behind the scenes, this will throw ValueError
371 Behind the scenes, this will throw ValueError
372
372
373 $ hg tip --template '{author|email|date}\n'
373 $ hg tip --template '{author|email|date}\n'
374 hg: parse error: date expects a date information
374 hg: parse error: date expects a date information
375 [255]
375 [255]
376
376
377 $ hg tip -T '{author|email|shortdate}\n'
377 $ hg tip -T '{author|email|shortdate}\n'
378 hg: parse error: invalid date: 'test'
378 hg: parse error: invalid date: 'test'
379 (template filter 'shortdate' is not compatible with keyword 'author')
379 (template filter 'shortdate' is not compatible with keyword 'author')
380 [255]
380 [255]
381
381
382 $ hg tip -T '{get(extras, "branch")|shortdate}\n'
382 $ hg tip -T '{get(extras, "branch")|shortdate}\n'
383 hg: parse error: invalid date: 'default'
383 hg: parse error: invalid date: 'default'
384 (incompatible use of template filter 'shortdate')
384 (incompatible use of template filter 'shortdate')
385 [255]
385 [255]
386
386
387 Error in nested template:
387 Error in nested template:
388
388
389 $ hg log -T '{"date'
389 $ hg log -T '{"date'
390 hg: parse error at 2: unterminated string
390 hg: parse error at 2: unterminated string
391 ({"date
391 ({"date
392 ^ here)
392 ^ here)
393 [255]
393 [255]
394
394
395 $ hg log -T '{"foo{date|?}"}'
395 $ hg log -T '{"foo{date|?}"}'
396 hg: parse error at 11: syntax error
396 hg: parse error at 11: syntax error
397 ({"foo{date|?}"}
397 ({"foo{date|?}"}
398 ^ here)
398 ^ here)
399 [255]
399 [255]
400
400
401 Thrown an error if a template function doesn't exist
401 Thrown an error if a template function doesn't exist
402
402
403 $ hg tip --template '{foo()}\n'
403 $ hg tip --template '{foo()}\n'
404 hg: parse error: unknown function 'foo'
404 hg: parse error: unknown function 'foo'
405 [255]
405 [255]
406
406
407 $ cd ..
407 $ cd ..
408
408
409 Set up latesttag repository:
409 Set up latesttag repository:
410
410
411 $ hg init latesttag
411 $ hg init latesttag
412 $ cd latesttag
412 $ cd latesttag
413
413
414 $ echo a > file
414 $ echo a > file
415 $ hg ci -Am a -d '0 0'
415 $ hg ci -Am a -d '0 0'
416 adding file
416 adding file
417
417
418 $ echo b >> file
418 $ echo b >> file
419 $ hg ci -m b -d '1 0'
419 $ hg ci -m b -d '1 0'
420
420
421 $ echo c >> head1
421 $ echo c >> head1
422 $ hg ci -Am h1c -d '2 0'
422 $ hg ci -Am h1c -d '2 0'
423 adding head1
423 adding head1
424
424
425 $ hg update -q 1
425 $ hg update -q 1
426 $ echo d >> head2
426 $ echo d >> head2
427 $ hg ci -Am h2d -d '3 0'
427 $ hg ci -Am h2d -d '3 0'
428 adding head2
428 adding head2
429 created new head
429 created new head
430
430
431 $ echo e >> head2
431 $ echo e >> head2
432 $ hg ci -m h2e -d '4 0'
432 $ hg ci -m h2e -d '4 0'
433
433
434 $ hg merge -q
434 $ hg merge -q
435 $ hg ci -m merge -d '5 -3600'
435 $ hg ci -m merge -d '5 -3600'
436
436
437 $ hg tag -r 1 -m t1 -d '6 0' t1
437 $ hg tag -r 1 -m t1 -d '6 0' t1
438 $ hg tag -r 2 -m t2 -d '7 0' t2
438 $ hg tag -r 2 -m t2 -d '7 0' t2
439 $ hg tag -r 3 -m t3 -d '8 0' t3
439 $ hg tag -r 3 -m t3 -d '8 0' t3
440 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
440 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
441 $ hg tag -r 5 -m t5 -d '9 0' t5
441 $ hg tag -r 5 -m t5 -d '9 0' t5
442 $ hg tag -r 3 -m at3 -d '10 0' at3
442 $ hg tag -r 3 -m at3 -d '10 0' at3
443
443
444 $ cd ..
444 $ cd ..
445
445
446 Test new-style inline templating:
446 Test new-style inline templating:
447
447
448 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
448 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
449 modified files: .hgtags
449 modified files: .hgtags
450
450
451
451
452 $ hg log -R latesttag -r tip -T '{rev % "a"}\n'
452 $ hg log -R latesttag -r tip -T '{rev % "a"}\n'
453 hg: parse error: 11 is not iterable of mappings
453 hg: parse error: 11 is not iterable of mappings
454 (keyword 'rev' does not support map operation)
454 (keyword 'rev' does not support map operation)
455 [255]
455 [255]
456 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "a"}\n'
456 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "a"}\n'
457 hg: parse error: None is not iterable of mappings
457 hg: parse error: None is not iterable of mappings
458 [255]
458 [255]
459 $ hg log -R latesttag -r tip -T '{extras % "{key}\n" % "{key}\n"}'
459 $ hg log -R latesttag -r tip -T '{extras % "{key}\n" % "{key}\n"}'
460 hg: parse error: list of strings is not mappable
460 hg: parse error: list of strings is not mappable
461 [255]
461 [255]
462
462
463 Test new-style inline templating of non-list/dict type:
463 Test new-style inline templating of non-list/dict type:
464
464
465 $ hg log -R latesttag -r tip -T '{manifest}\n'
465 $ hg log -R latesttag -r tip -T '{manifest}\n'
466 11:2bc6e9006ce2
466 11:2bc6e9006ce2
467 $ hg log -R latesttag -r tip -T 'string length: {manifest|count}\n'
467 $ hg log -R latesttag -r tip -T 'string length: {manifest|count}\n'
468 string length: 15
468 string length: 15
469 $ hg log -R latesttag -r tip -T '{manifest % "{rev}:{node}"}\n'
469 $ hg log -R latesttag -r tip -T '{manifest % "{rev}:{node}"}\n'
470 11:2bc6e9006ce29882383a22d39fd1f4e66dd3e2fc
470 11:2bc6e9006ce29882383a22d39fd1f4e66dd3e2fc
471
471
472 $ hg log -R latesttag -r tip -T '{get(extras, "branch") % "{key}: {value}\n"}'
472 $ hg log -R latesttag -r tip -T '{get(extras, "branch") % "{key}: {value}\n"}'
473 branch: default
473 branch: default
474 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "{key}\n"}'
474 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "{key}\n"}'
475 hg: parse error: None is not iterable of mappings
475 hg: parse error: None is not iterable of mappings
476 [255]
476 [255]
477 $ hg log -R latesttag -r tip -T '{min(extras) % "{key}: {value}\n"}'
477 $ hg log -R latesttag -r tip -T '{min(extras) % "{key}: {value}\n"}'
478 branch: default
478 branch: default
479 $ hg log -R latesttag -l1 -T '{min(revset("0:9")) % "{rev}:{node|short}\n"}'
479 $ hg log -R latesttag -l1 -T '{min(revset("0:9")) % "{rev}:{node|short}\n"}'
480 0:ce3cec86e6c2
480 0:ce3cec86e6c2
481 $ hg log -R latesttag -l1 -T '{max(revset("0:9")) % "{rev}:{node|short}\n"}'
481 $ hg log -R latesttag -l1 -T '{max(revset("0:9")) % "{rev}:{node|short}\n"}'
482 9:fbc7cd862e9c
482 9:fbc7cd862e9c
483
483
484 Test dot operator precedence:
484 Test dot operator precedence:
485
485
486 $ hg debugtemplate -R latesttag -r0 -v '{manifest.node|short}\n'
486 $ hg debugtemplate -R latesttag -r0 -v '{manifest.node|short}\n'
487 (template
487 (template
488 (|
488 (|
489 (.
489 (.
490 (symbol 'manifest')
490 (symbol 'manifest')
491 (symbol 'node'))
491 (symbol 'node'))
492 (symbol 'short'))
492 (symbol 'short'))
493 (string '\n'))
493 (string '\n'))
494 * keywords: manifest, node, rev
494 * keywords: manifest, node, rev
495 * functions: formatnode, short
495 * functions: formatnode, short
496 89f4071fec70
496 89f4071fec70
497
497
498 (the following examples are invalid, but seem natural in parsing POV)
498 (the following examples are invalid, but seem natural in parsing POV)
499
499
500 $ hg debugtemplate -R latesttag -r0 -v '{foo|bar.baz}\n' 2> /dev/null
500 $ hg debugtemplate -R latesttag -r0 -v '{foo|bar.baz}\n' 2> /dev/null
501 (template
501 (template
502 (|
502 (|
503 (symbol 'foo')
503 (symbol 'foo')
504 (.
504 (.
505 (symbol 'bar')
505 (symbol 'bar')
506 (symbol 'baz')))
506 (symbol 'baz')))
507 (string '\n'))
507 (string '\n'))
508 [255]
508 [255]
509 $ hg debugtemplate -R latesttag -r0 -v '{foo.bar()}\n' 2> /dev/null
509 $ hg debugtemplate -R latesttag -r0 -v '{foo.bar()}\n' 2> /dev/null
510 (template
510 (template
511 (.
511 (.
512 (symbol 'foo')
512 (symbol 'foo')
513 (func
513 (func
514 (symbol 'bar')
514 (symbol 'bar')
515 None))
515 None))
516 (string '\n'))
516 (string '\n'))
517 * keywords: foo
517 * keywords: foo
518 * functions: bar
518 * functions: bar
519 [255]
519 [255]
520
520
521 Test evaluation of dot operator:
521 Test evaluation of dot operator:
522
522
523 $ hg log -R latesttag -l1 -T '{min(revset("0:9")).node}\n'
523 $ hg log -R latesttag -l1 -T '{min(revset("0:9")).node}\n'
524 ce3cec86e6c26bd9bdfc590a6b92abc9680f1796
524 ce3cec86e6c26bd9bdfc590a6b92abc9680f1796
525 $ hg log -R latesttag -r0 -T '{extras.branch}\n'
525 $ hg log -R latesttag -r0 -T '{extras.branch}\n'
526 default
526 default
527 $ hg log -R latesttag -r0 -T '{date.unixtime} {localdate(date, "+0200").tzoffset}\n'
527 $ hg log -R latesttag -r0 -T '{date.unixtime} {localdate(date, "+0200").tzoffset}\n'
528 0 -7200
528 0 -7200
529
529
530 $ hg log -R latesttag -l1 -T '{author.invalid}\n'
530 $ hg log -R latesttag -l1 -T '{author.invalid}\n'
531 hg: parse error: 'test' is not a dictionary
531 hg: parse error: 'test' is not a dictionary
532 (keyword 'author' does not support member operation)
532 (keyword 'author' does not support member operation)
533 [255]
533 [255]
534 $ hg log -R latesttag -l1 -T '{min("abc").invalid}\n'
534 $ hg log -R latesttag -l1 -T '{min("abc").invalid}\n'
535 hg: parse error: 'a' is not a dictionary
535 hg: parse error: 'a' is not a dictionary
536 [255]
536 [255]
537
537
538 Test integer literal:
538 Test integer literal:
539
539
540 $ hg debugtemplate -v '{(0)}\n'
540 $ hg debugtemplate -v '{(0)}\n'
541 (template
541 (template
542 (group
542 (group
543 (integer '0'))
543 (integer '0'))
544 (string '\n'))
544 (string '\n'))
545 * keywords:
545 * keywords:
546 * functions:
546 * functions:
547 0
547 0
548 $ hg debugtemplate -v '{(123)}\n'
548 $ hg debugtemplate -v '{(123)}\n'
549 (template
549 (template
550 (group
550 (group
551 (integer '123'))
551 (integer '123'))
552 (string '\n'))
552 (string '\n'))
553 * keywords:
553 * keywords:
554 * functions:
554 * functions:
555 123
555 123
556 $ hg debugtemplate -v '{(-4)}\n'
556 $ hg debugtemplate -v '{(-4)}\n'
557 (template
557 (template
558 (group
558 (group
559 (negate
559 (negate
560 (integer '4')))
560 (integer '4')))
561 (string '\n'))
561 (string '\n'))
562 * keywords:
562 * keywords:
563 * functions:
563 * functions:
564 -4
564 -4
565 $ hg debugtemplate '{(-)}\n'
565 $ hg debugtemplate '{(-)}\n'
566 hg: parse error at 3: not a prefix: )
566 hg: parse error at 3: not a prefix: )
567 ({(-)}\n
567 ({(-)}\n
568 ^ here)
568 ^ here)
569 [255]
569 [255]
570 $ hg debugtemplate '{(-a)}\n'
570 $ hg debugtemplate '{(-a)}\n'
571 hg: parse error: negation needs an integer argument
571 hg: parse error: negation needs an integer argument
572 [255]
572 [255]
573
573
574 top-level integer literal is interpreted as symbol (i.e. variable name):
574 top-level integer literal is interpreted as symbol (i.e. variable name):
575
575
576 $ hg debugtemplate -D 1=one -v '{1}\n'
576 $ hg debugtemplate -D 1=one -v '{1}\n'
577 (template
577 (template
578 (integer '1')
578 (integer '1')
579 (string '\n'))
579 (string '\n'))
580 * keywords:
580 * keywords:
581 * functions:
581 * functions:
582 one
582 one
583 $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
583 $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
584 (template
584 (template
585 (func
585 (func
586 (symbol 'if')
586 (symbol 'if')
587 (list
587 (list
588 (string 't')
588 (string 't')
589 (template
589 (template
590 (integer '1'))))
590 (integer '1'))))
591 (string '\n'))
591 (string '\n'))
592 * keywords:
592 * keywords:
593 * functions: if
593 * functions: if
594 one
594 one
595 $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
595 $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
596 (template
596 (template
597 (|
597 (|
598 (integer '1')
598 (integer '1')
599 (symbol 'stringify'))
599 (symbol 'stringify'))
600 (string '\n'))
600 (string '\n'))
601 * keywords:
601 * keywords:
602 * functions: stringify
602 * functions: stringify
603 one
603 one
604
604
605 unless explicit symbol is expected:
605 unless explicit symbol is expected:
606
606
607 $ hg log -Ra -r0 -T '{desc|1}\n'
607 $ hg log -Ra -r0 -T '{desc|1}\n'
608 hg: parse error: expected a symbol, got 'integer'
608 hg: parse error: expected a symbol, got 'integer'
609 [255]
609 [255]
610 $ hg log -Ra -r0 -T '{1()}\n'
610 $ hg log -Ra -r0 -T '{1()}\n'
611 hg: parse error: expected a symbol, got 'integer'
611 hg: parse error: expected a symbol, got 'integer'
612 [255]
612 [255]
613
613
614 Test string literal:
614 Test string literal:
615
615
616 $ hg debugtemplate -Ra -r0 -v '{"string with no template fragment"}\n'
616 $ hg debugtemplate -Ra -r0 -v '{"string with no template fragment"}\n'
617 (template
617 (template
618 (string 'string with no template fragment')
618 (string 'string with no template fragment')
619 (string '\n'))
619 (string '\n'))
620 * keywords:
620 * keywords:
621 * functions:
621 * functions:
622 string with no template fragment
622 string with no template fragment
623 $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
623 $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
624 (template
624 (template
625 (template
625 (template
626 (string 'template: ')
626 (string 'template: ')
627 (symbol 'rev'))
627 (symbol 'rev'))
628 (string '\n'))
628 (string '\n'))
629 * keywords: rev
629 * keywords: rev
630 * functions:
630 * functions:
631 template: 0
631 template: 0
632 $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
632 $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
633 (template
633 (template
634 (string 'rawstring: {rev}')
634 (string 'rawstring: {rev}')
635 (string '\n'))
635 (string '\n'))
636 * keywords:
636 * keywords:
637 * functions:
637 * functions:
638 rawstring: {rev}
638 rawstring: {rev}
639 $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
639 $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
640 (template
640 (template
641 (%
641 (%
642 (symbol 'files')
642 (symbol 'files')
643 (string 'rawstring: {file}'))
643 (string 'rawstring: {file}'))
644 (string '\n'))
644 (string '\n'))
645 * keywords: files
645 * keywords: files
646 * functions:
646 * functions:
647 rawstring: {file}
647 rawstring: {file}
648
648
649 Test string escaping:
649 Test string escaping:
650
650
651 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
651 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
652 >
652 >
653 <>\n<[>
653 <>\n<[>
654 <>\n<]>
654 <>\n<]>
655 <>\n<
655 <>\n<
656
656
657 $ hg log -R latesttag -r 0 \
657 $ hg log -R latesttag -r 0 \
658 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
658 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
659 >
659 >
660 <>\n<[>
660 <>\n<[>
661 <>\n<]>
661 <>\n<]>
662 <>\n<
662 <>\n<
663
663
664 $ hg log -R latesttag -r 0 -T esc \
664 $ hg log -R latesttag -r 0 -T esc \
665 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
665 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
666 >
666 >
667 <>\n<[>
667 <>\n<[>
668 <>\n<]>
668 <>\n<]>
669 <>\n<
669 <>\n<
670
670
671 $ cat <<'EOF' > esctmpl
671 $ cat <<'EOF' > esctmpl
672 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
672 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
673 > EOF
673 > EOF
674 $ hg log -R latesttag -r 0 --style ./esctmpl
674 $ hg log -R latesttag -r 0 --style ./esctmpl
675 >
675 >
676 <>\n<[>
676 <>\n<[>
677 <>\n<]>
677 <>\n<]>
678 <>\n<
678 <>\n<
679
679
680 Test string escaping of quotes:
680 Test string escaping of quotes:
681
681
682 $ hg log -Ra -r0 -T '{"\""}\n'
682 $ hg log -Ra -r0 -T '{"\""}\n'
683 "
683 "
684 $ hg log -Ra -r0 -T '{"\\\""}\n'
684 $ hg log -Ra -r0 -T '{"\\\""}\n'
685 \"
685 \"
686 $ hg log -Ra -r0 -T '{r"\""}\n'
686 $ hg log -Ra -r0 -T '{r"\""}\n'
687 \"
687 \"
688 $ hg log -Ra -r0 -T '{r"\\\""}\n'
688 $ hg log -Ra -r0 -T '{r"\\\""}\n'
689 \\\"
689 \\\"
690
690
691
691
692 $ hg log -Ra -r0 -T '{"\""}\n'
692 $ hg log -Ra -r0 -T '{"\""}\n'
693 "
693 "
694 $ hg log -Ra -r0 -T '{"\\\""}\n'
694 $ hg log -Ra -r0 -T '{"\\\""}\n'
695 \"
695 \"
696 $ hg log -Ra -r0 -T '{r"\""}\n'
696 $ hg log -Ra -r0 -T '{r"\""}\n'
697 \"
697 \"
698 $ hg log -Ra -r0 -T '{r"\\\""}\n'
698 $ hg log -Ra -r0 -T '{r"\\\""}\n'
699 \\\"
699 \\\"
700
700
701 Test exception in quoted template. single backslash before quotation mark is
701 Test exception in quoted template. single backslash before quotation mark is
702 stripped before parsing:
702 stripped before parsing:
703
703
704 $ cat <<'EOF' > escquotetmpl
704 $ cat <<'EOF' > escquotetmpl
705 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
705 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
706 > EOF
706 > EOF
707 $ cd latesttag
707 $ cd latesttag
708 $ hg log -r 2 --style ../escquotetmpl
708 $ hg log -r 2 --style ../escquotetmpl
709 " \" \" \\" head1
709 " \" \" \\" head1
710
710
711 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
711 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
712 valid
712 valid
713 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
713 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
714 valid
714 valid
715
715
716 Test compatibility with 2.9.2-3.4 of escaped quoted strings in nested
716 Test compatibility with 2.9.2-3.4 of escaped quoted strings in nested
717 _evalifliteral() templates (issue4733):
717 _evalifliteral() templates (issue4733):
718
718
719 $ hg log -r 2 -T '{if(rev, "\"{rev}")}\n'
719 $ hg log -r 2 -T '{if(rev, "\"{rev}")}\n'
720 "2
720 "2
721 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\"{rev}\")}")}\n'
721 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\"{rev}\")}")}\n'
722 "2
722 "2
723 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\"{rev}\\\")}\")}")}\n'
723 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\"{rev}\\\")}\")}")}\n'
724 "2
724 "2
725
725
726 $ hg log -r 2 -T '{if(rev, "\\\"")}\n'
726 $ hg log -r 2 -T '{if(rev, "\\\"")}\n'
727 \"
727 \"
728 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\\\\\"\")}")}\n'
728 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\\\\\"\")}")}\n'
729 \"
729 \"
730 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
730 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
731 \"
731 \"
732
732
733 $ hg log -r 2 -T '{if(rev, r"\\\"")}\n'
733 $ hg log -r 2 -T '{if(rev, r"\\\"")}\n'
734 \\\"
734 \\\"
735 $ hg log -r 2 -T '{if(rev, "{if(rev, r\"\\\\\\\"\")}")}\n'
735 $ hg log -r 2 -T '{if(rev, "{if(rev, r\"\\\\\\\"\")}")}\n'
736 \\\"
736 \\\"
737 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, r\\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
737 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, r\\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
738 \\\"
738 \\\"
739
739
740 escaped single quotes and errors:
740 escaped single quotes and errors:
741
741
742 $ hg log -r 2 -T "{if(rev, '{if(rev, \'foo\')}')}"'\n'
742 $ hg log -r 2 -T "{if(rev, '{if(rev, \'foo\')}')}"'\n'
743 foo
743 foo
744 $ hg log -r 2 -T "{if(rev, '{if(rev, r\'foo\')}')}"'\n'
744 $ hg log -r 2 -T "{if(rev, '{if(rev, r\'foo\')}')}"'\n'
745 foo
745 foo
746 $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n'
746 $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n'
747 hg: parse error at 21: unterminated string
747 hg: parse error at 21: unterminated string
748 ({if(rev, "{if(rev, \")}")}\n
748 ({if(rev, "{if(rev, \")}")}\n
749 ^ here)
749 ^ here)
750 [255]
750 [255]
751 $ hg log -r 2 -T '{if(rev, \"\\"")}\n'
751 $ hg log -r 2 -T '{if(rev, \"\\"")}\n'
752 hg: parse error: trailing \ in string
752 hg: parse error: trailing \ in string
753 [255]
753 [255]
754 $ hg log -r 2 -T '{if(rev, r\"\\"")}\n'
754 $ hg log -r 2 -T '{if(rev, r\"\\"")}\n'
755 hg: parse error: trailing \ in string
755 hg: parse error: trailing \ in string
756 [255]
756 [255]
757
757
758 $ cd ..
758 $ cd ..
759
759
760 Test leading backslashes:
760 Test leading backslashes:
761
761
762 $ cd latesttag
762 $ cd latesttag
763 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
763 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
764 {rev} {file}
764 {rev} {file}
765 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
765 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
766 \2 \head1
766 \2 \head1
767 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
767 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
768 \{rev} \{file}
768 \{rev} \{file}
769 $ cd ..
769 $ cd ..
770
770
771 Test leading backslashes in "if" expression (issue4714):
771 Test leading backslashes in "if" expression (issue4714):
772
772
773 $ cd latesttag
773 $ cd latesttag
774 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
774 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
775 {rev} \{rev}
775 {rev} \{rev}
776 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
776 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
777 \2 \\{rev}
777 \2 \\{rev}
778 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
778 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
779 \{rev} \\\{rev}
779 \{rev} \\\{rev}
780 $ cd ..
780 $ cd ..
781
781
782 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
782 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
783
783
784 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
784 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
785 \x6e
785 \x6e
786 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
786 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
787 \x5c\x786e
787 \x5c\x786e
788 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
788 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
789 \x6e
789 \x6e
790 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
790 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
791 \x5c\x786e
791 \x5c\x786e
792
792
793 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
793 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
794 \x6e
794 \x6e
795 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
795 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
796 \x5c\x786e
796 \x5c\x786e
797 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
797 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
798 \x6e
798 \x6e
799 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
799 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
800 \x5c\x786e
800 \x5c\x786e
801
801
802 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
802 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
803 fourth
803 fourth
804 second
804 second
805 third
805 third
806 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
806 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
807 fourth\nsecond\nthird
807 fourth\nsecond\nthird
808
808
809 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
809 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
810 <p>
810 <p>
811 1st
811 1st
812 </p>
812 </p>
813 <p>
813 <p>
814 2nd
814 2nd
815 </p>
815 </p>
816 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
816 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
817 <p>
817 <p>
818 1st\n\n2nd
818 1st\n\n2nd
819 </p>
819 </p>
820 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
820 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
821 1st
821 1st
822
822
823 2nd
823 2nd
824
824
825 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
825 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
826 o perso
826 o perso
827 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
827 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
828 no person
828 no person
829 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
829 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
830 o perso
830 o perso
831 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
831 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
832 no perso
832 no perso
833
833
834 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
834 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
835 -o perso-
835 -o perso-
836 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
836 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
837 no person
837 no person
838 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
838 $ hg log -R a -r 2 --template '{sub("n", r"\\x2d", desc)}\n'
839 \x2do perso\x2d
839 \x2do perso\x2d
840 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
840 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
841 -o perso-
841 -o perso-
842 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
842 $ hg log -R a -r 2 --template '{sub("n", r"\\x2d", r"no perso\x6e")}\n'
843 \x2do perso\x6e
843 \x2do perso\x6e
844
844
845 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
845 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
846 fourth
846 fourth
847 second
847 second
848 third
848 third
849
849
850 Test string escaping in nested expression:
850 Test string escaping in nested expression:
851
851
852 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
852 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
853 fourth\x6esecond\x6ethird
853 fourth\x6esecond\x6ethird
854 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
854 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
855 fourth\x6esecond\x6ethird
855 fourth\x6esecond\x6ethird
856
856
857 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
857 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
858 fourth\x6esecond\x6ethird
858 fourth\x6esecond\x6ethird
859 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
859 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
860 fourth\x5c\x786esecond\x5c\x786ethird
860 fourth\x5c\x786esecond\x5c\x786ethird
861
861
862 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
862 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
863 3:\x6eo user, \x6eo domai\x6e
863 3:\x6eo user, \x6eo domai\x6e
864 4:\x5c\x786eew bra\x5c\x786ech
864 4:\x5c\x786eew bra\x5c\x786ech
865
865
866 Test quotes in nested expression are evaluated just like a $(command)
866 Test quotes in nested expression are evaluated just like a $(command)
867 substitution in POSIX shells:
867 substitution in POSIX shells:
868
868
869 $ hg log -R a -r 8 -T '{"{"{rev}:{node|short}"}"}\n'
869 $ hg log -R a -r 8 -T '{"{"{rev}:{node|short}"}"}\n'
870 8:95c24699272e
870 8:95c24699272e
871 $ hg log -R a -r 8 -T '{"{"\{{rev}} \"{node|short}\""}"}\n'
871 $ hg log -R a -r 8 -T '{"{"\{{rev}} \"{node|short}\""}"}\n'
872 {8} "95c24699272e"
872 {8} "95c24699272e"
873
873
874 Test recursive evaluation:
874 Test recursive evaluation:
875
875
876 $ hg init r
876 $ hg init r
877 $ cd r
877 $ cd r
878 $ echo a > a
878 $ echo a > a
879 $ hg ci -Am '{rev}'
879 $ hg ci -Am '{rev}'
880 adding a
880 adding a
881 $ hg log -r 0 --template '{if(rev, desc)}\n'
881 $ hg log -r 0 --template '{if(rev, desc)}\n'
882 {rev}
882 {rev}
883 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
883 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
884 test 0
884 test 0
885
885
886 $ hg branch -q 'text.{rev}'
886 $ hg branch -q 'text.{rev}'
887 $ echo aa >> aa
887 $ echo aa >> aa
888 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
888 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
889
889
890 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
890 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
891 {node|short}desc to
891 {node|short}desc to
892 text.{rev}be wrapped
892 text.{rev}be wrapped
893 text.{rev}desc to be
893 text.{rev}desc to be
894 text.{rev}wrapped (no-eol)
894 text.{rev}wrapped (no-eol)
895 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
895 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
896 bcc7ff960b8e:desc to
896 bcc7ff960b8e:desc to
897 text.1:be wrapped
897 text.1:be wrapped
898 text.1:desc to be
898 text.1:desc to be
899 text.1:wrapped (no-eol)
899 text.1:wrapped (no-eol)
900 $ hg log -l1 -T '{fill(desc, date, "", "")}\n'
900 $ hg log -l1 -T '{fill(desc, date, "", "")}\n'
901 hg: parse error: fill expects an integer width
901 hg: parse error: fill expects an integer width
902 [255]
902 [255]
903
903
904 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
904 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
905 {node|short} (no-eol)
905 {node|short} (no-eol)
906 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
906 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
907 bcc-ff---b-e (no-eol)
907 bcc-ff---b-e (no-eol)
908
908
909 $ cat >> .hg/hgrc <<EOF
909 $ cat >> .hg/hgrc <<EOF
910 > [extensions]
910 > [extensions]
911 > color=
911 > color=
912 > [color]
912 > [color]
913 > mode=ansi
913 > mode=ansi
914 > text.{rev} = red
914 > text.{rev} = red
915 > text.1 = green
915 > text.1 = green
916 > EOF
916 > EOF
917 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
917 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
918 \x1b[0;31mtext\x1b[0m (esc)
918 \x1b[0;31mtext\x1b[0m (esc)
919 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
919 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
920 \x1b[0;32mtext\x1b[0m (esc)
920 \x1b[0;32mtext\x1b[0m (esc)
921
921
922 $ cd ..
922 $ cd ..
923
923
924 Test bad template with better error message
924 Test bad template with better error message
925
925
926 $ hg log -Gv -R a --template '{desc|user()}'
926 $ hg log -Gv -R a --template '{desc|user()}'
927 hg: parse error: expected a symbol, got 'func'
927 hg: parse error: expected a symbol, got 'func'
928 [255]
928 [255]
929
929
930 Test broken string escapes:
930 Test broken string escapes:
931
931
932 $ hg log -T "bogus\\" -R a
932 $ hg log -T "bogus\\" -R a
933 hg: parse error: trailing \ in string
933 hg: parse error: trailing \ in string
934 [255]
934 [255]
935 $ hg log -T "\\xy" -R a
935 $ hg log -T "\\xy" -R a
936 hg: parse error: invalid \x escape* (glob)
936 hg: parse error: invalid \x escape* (glob)
937 [255]
937 [255]
938
938
939 Templater supports aliases of symbol and func() styles:
939 Templater supports aliases of symbol and func() styles:
940
940
941 $ hg clone -q a aliases
941 $ hg clone -q a aliases
942 $ cd aliases
942 $ cd aliases
943 $ cat <<EOF >> .hg/hgrc
943 $ cat <<EOF >> .hg/hgrc
944 > [templatealias]
944 > [templatealias]
945 > r = rev
945 > r = rev
946 > rn = "{r}:{node|short}"
946 > rn = "{r}:{node|short}"
947 > status(c, files) = files % "{c} {file}\n"
947 > status(c, files) = files % "{c} {file}\n"
948 > utcdate(d) = localdate(d, "UTC")
948 > utcdate(d) = localdate(d, "UTC")
949 > EOF
949 > EOF
950
950
951 $ hg debugtemplate -vr0 '{rn} {utcdate(date)|isodate}\n'
951 $ hg debugtemplate -vr0 '{rn} {utcdate(date)|isodate}\n'
952 (template
952 (template
953 (symbol 'rn')
953 (symbol 'rn')
954 (string ' ')
954 (string ' ')
955 (|
955 (|
956 (func
956 (func
957 (symbol 'utcdate')
957 (symbol 'utcdate')
958 (symbol 'date'))
958 (symbol 'date'))
959 (symbol 'isodate'))
959 (symbol 'isodate'))
960 (string '\n'))
960 (string '\n'))
961 * expanded:
961 * expanded:
962 (template
962 (template
963 (template
963 (template
964 (symbol 'rev')
964 (symbol 'rev')
965 (string ':')
965 (string ':')
966 (|
966 (|
967 (symbol 'node')
967 (symbol 'node')
968 (symbol 'short')))
968 (symbol 'short')))
969 (string ' ')
969 (string ' ')
970 (|
970 (|
971 (func
971 (func
972 (symbol 'localdate')
972 (symbol 'localdate')
973 (list
973 (list
974 (symbol 'date')
974 (symbol 'date')
975 (string 'UTC')))
975 (string 'UTC')))
976 (symbol 'isodate'))
976 (symbol 'isodate'))
977 (string '\n'))
977 (string '\n'))
978 * keywords: date, node, rev
978 * keywords: date, node, rev
979 * functions: isodate, localdate, short
979 * functions: isodate, localdate, short
980 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
980 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
981
981
982 $ hg debugtemplate -vr0 '{status("A", file_adds)}'
982 $ hg debugtemplate -vr0 '{status("A", file_adds)}'
983 (template
983 (template
984 (func
984 (func
985 (symbol 'status')
985 (symbol 'status')
986 (list
986 (list
987 (string 'A')
987 (string 'A')
988 (symbol 'file_adds'))))
988 (symbol 'file_adds'))))
989 * expanded:
989 * expanded:
990 (template
990 (template
991 (%
991 (%
992 (symbol 'file_adds')
992 (symbol 'file_adds')
993 (template
993 (template
994 (string 'A')
994 (string 'A')
995 (string ' ')
995 (string ' ')
996 (symbol 'file')
996 (symbol 'file')
997 (string '\n'))))
997 (string '\n'))))
998 * keywords: file, file_adds
998 * keywords: file, file_adds
999 * functions:
999 * functions:
1000 A a
1000 A a
1001
1001
1002 A unary function alias can be called as a filter:
1002 A unary function alias can be called as a filter:
1003
1003
1004 $ hg debugtemplate -vr0 '{date|utcdate|isodate}\n'
1004 $ hg debugtemplate -vr0 '{date|utcdate|isodate}\n'
1005 (template
1005 (template
1006 (|
1006 (|
1007 (|
1007 (|
1008 (symbol 'date')
1008 (symbol 'date')
1009 (symbol 'utcdate'))
1009 (symbol 'utcdate'))
1010 (symbol 'isodate'))
1010 (symbol 'isodate'))
1011 (string '\n'))
1011 (string '\n'))
1012 * expanded:
1012 * expanded:
1013 (template
1013 (template
1014 (|
1014 (|
1015 (func
1015 (func
1016 (symbol 'localdate')
1016 (symbol 'localdate')
1017 (list
1017 (list
1018 (symbol 'date')
1018 (symbol 'date')
1019 (string 'UTC')))
1019 (string 'UTC')))
1020 (symbol 'isodate'))
1020 (symbol 'isodate'))
1021 (string '\n'))
1021 (string '\n'))
1022 * keywords: date
1022 * keywords: date
1023 * functions: isodate, localdate
1023 * functions: isodate, localdate
1024 1970-01-12 13:46 +0000
1024 1970-01-12 13:46 +0000
1025
1025
1026 Aliases should be applied only to command arguments and templates in hgrc.
1026 Aliases should be applied only to command arguments and templates in hgrc.
1027 Otherwise, our stock styles and web templates could be corrupted:
1027 Otherwise, our stock styles and web templates could be corrupted:
1028
1028
1029 $ hg log -r0 -T '{rn} {utcdate(date)|isodate}\n'
1029 $ hg log -r0 -T '{rn} {utcdate(date)|isodate}\n'
1030 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
1030 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
1031
1031
1032 $ hg log -r0 --config ui.logtemplate='"{rn} {utcdate(date)|isodate}\n"'
1032 $ hg log -r0 --config ui.logtemplate='"{rn} {utcdate(date)|isodate}\n"'
1033 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
1033 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
1034
1034
1035 $ cat <<EOF > tmpl
1035 $ cat <<EOF > tmpl
1036 > changeset = 'nothing expanded:{rn}\n'
1036 > changeset = 'nothing expanded:{rn}\n'
1037 > EOF
1037 > EOF
1038 $ hg log -r0 --style ./tmpl
1038 $ hg log -r0 --style ./tmpl
1039 nothing expanded:
1039 nothing expanded:
1040
1040
1041 Aliases in formatter:
1041 Aliases in formatter:
1042
1042
1043 $ hg branches -T '{pad(branch, 7)} {rn}\n'
1043 $ hg branches -T '{pad(branch, 7)} {rn}\n'
1044 default 6:d41e714fe50d
1044 default 6:d41e714fe50d
1045 foo 4:bbe44766e73d
1045 foo 4:bbe44766e73d
1046
1046
1047 Aliases should honor HGPLAIN:
1047 Aliases should honor HGPLAIN:
1048
1048
1049 $ HGPLAIN= hg log -r0 -T 'nothing expanded:{rn}\n'
1049 $ HGPLAIN= hg log -r0 -T 'nothing expanded:{rn}\n'
1050 nothing expanded:
1050 nothing expanded:
1051 $ HGPLAINEXCEPT=templatealias hg log -r0 -T '{rn}\n'
1051 $ HGPLAINEXCEPT=templatealias hg log -r0 -T '{rn}\n'
1052 0:1e4e1b8f71e0
1052 0:1e4e1b8f71e0
1053
1053
1054 Unparsable alias:
1054 Unparsable alias:
1055
1055
1056 $ hg debugtemplate --config templatealias.bad='x(' -v '{bad}'
1056 $ hg debugtemplate --config templatealias.bad='x(' -v '{bad}'
1057 (template
1057 (template
1058 (symbol 'bad'))
1058 (symbol 'bad'))
1059 abort: bad definition of template alias "bad": at 2: not a prefix: end
1059 abort: bad definition of template alias "bad": at 2: not a prefix: end
1060 [255]
1060 [255]
1061 $ hg log --config templatealias.bad='x(' -T '{bad}'
1061 $ hg log --config templatealias.bad='x(' -T '{bad}'
1062 abort: bad definition of template alias "bad": at 2: not a prefix: end
1062 abort: bad definition of template alias "bad": at 2: not a prefix: end
1063 [255]
1063 [255]
1064
1064
1065 $ cd ..
1065 $ cd ..
1066
1066
1067 Test that template function in extension is registered as expected
1067 Test that template function in extension is registered as expected
1068
1068
1069 $ cd a
1069 $ cd a
1070
1070
1071 $ cat <<EOF > $TESTTMP/customfunc.py
1071 $ cat <<EOF > $TESTTMP/customfunc.py
1072 > from mercurial import registrar
1072 > from mercurial import registrar
1073 >
1073 >
1074 > templatefunc = registrar.templatefunc()
1074 > templatefunc = registrar.templatefunc()
1075 >
1075 >
1076 > @templatefunc(b'custom()')
1076 > @templatefunc(b'custom()')
1077 > def custom(context, mapping, args):
1077 > def custom(context, mapping, args):
1078 > return b'custom'
1078 > return b'custom'
1079 > EOF
1079 > EOF
1080 $ cat <<EOF > .hg/hgrc
1080 $ cat <<EOF > .hg/hgrc
1081 > [extensions]
1081 > [extensions]
1082 > customfunc = $TESTTMP/customfunc.py
1082 > customfunc = $TESTTMP/customfunc.py
1083 > EOF
1083 > EOF
1084
1084
1085 $ hg log -r . -T "{custom()}\n" --config customfunc.enabled=true
1085 $ hg log -r . -T "{custom()}\n" --config customfunc.enabled=true
1086 custom
1086 custom
1087
1087
1088 $ cd ..
1088 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now