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