##// END OF EJS Templates
tests: document behavior of indent() with empty first line...
Martin von Zweigbergk -
r44092:0fd9e7a1 default
parent child Browse files
Show More
@@ -1,1638 +1,1653 b''
1 1 Test template filters and functions
2 2 ===================================
3 3
4 4 $ hg init a
5 5 $ cd a
6 6 $ echo a > a
7 7 $ hg add a
8 8 $ echo line 1 > b
9 9 $ echo line 2 >> b
10 10 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
11 11
12 12 $ hg add b
13 13 $ echo other 1 > c
14 14 $ echo other 2 >> c
15 15 $ echo >> c
16 16 $ echo other 3 >> c
17 17 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
18 18
19 19 $ hg add c
20 20 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
21 21 $ echo c >> c
22 22 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
23 23
24 24 $ echo foo > .hg/branch
25 25 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
26 26
27 27 $ hg co -q 3
28 28 $ echo other 4 >> d
29 29 $ hg add d
30 30 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
31 31
32 32 $ hg merge -q foo
33 33 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
34 34
35 35 Second branch starting at nullrev:
36 36
37 37 $ hg update null
38 38 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
39 39 $ echo second > second
40 40 $ hg add second
41 41 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
42 42 created new head
43 43
44 44 $ echo third > third
45 45 $ hg add third
46 46 $ hg mv second fourth
47 47 $ hg commit -m third -d "2020-01-01 10:01"
48 48
49 49 $ hg phase -r 5 --public
50 50 $ hg phase -r 7 --secret --force
51 51
52 52 Filters work:
53 53
54 54 $ hg log --template '{author|domain}\n'
55 55
56 56 hostname
57 57
58 58
59 59
60 60
61 61 place
62 62 place
63 63 hostname
64 64
65 65 $ hg log --template '{author|person}\n'
66 66 test
67 67 User Name
68 68 person
69 69 person
70 70 person
71 71 person
72 72 other
73 73 A. N. Other
74 74 User Name
75 75
76 76 $ hg log --template '{author|user}\n'
77 77 test
78 78 user
79 79 person
80 80 person
81 81 person
82 82 person
83 83 other
84 84 other
85 85 user
86 86
87 87 $ hg log --template '{date|date}\n'
88 88 Wed Jan 01 10:01:00 2020 +0000
89 89 Mon Jan 12 13:46:40 1970 +0000
90 90 Sun Jan 18 08:40:01 1970 +0000
91 91 Sun Jan 18 08:40:00 1970 +0000
92 92 Sat Jan 17 04:53:20 1970 +0000
93 93 Fri Jan 16 01:06:40 1970 +0000
94 94 Wed Jan 14 21:20:00 1970 +0000
95 95 Tue Jan 13 17:33:20 1970 +0000
96 96 Mon Jan 12 13:46:40 1970 +0000
97 97
98 98 $ hg log --template '{date|isodate}\n'
99 99 2020-01-01 10:01 +0000
100 100 1970-01-12 13:46 +0000
101 101 1970-01-18 08:40 +0000
102 102 1970-01-18 08:40 +0000
103 103 1970-01-17 04:53 +0000
104 104 1970-01-16 01:06 +0000
105 105 1970-01-14 21:20 +0000
106 106 1970-01-13 17:33 +0000
107 107 1970-01-12 13:46 +0000
108 108
109 109 $ hg log --template '{date|isodatesec}\n'
110 110 2020-01-01 10:01:00 +0000
111 111 1970-01-12 13:46:40 +0000
112 112 1970-01-18 08:40:01 +0000
113 113 1970-01-18 08:40:00 +0000
114 114 1970-01-17 04:53:20 +0000
115 115 1970-01-16 01:06:40 +0000
116 116 1970-01-14 21:20:00 +0000
117 117 1970-01-13 17:33:20 +0000
118 118 1970-01-12 13:46:40 +0000
119 119
120 120 $ hg log --template '{date|rfc822date}\n'
121 121 Wed, 01 Jan 2020 10:01:00 +0000
122 122 Mon, 12 Jan 1970 13:46:40 +0000
123 123 Sun, 18 Jan 1970 08:40:01 +0000
124 124 Sun, 18 Jan 1970 08:40:00 +0000
125 125 Sat, 17 Jan 1970 04:53:20 +0000
126 126 Fri, 16 Jan 1970 01:06:40 +0000
127 127 Wed, 14 Jan 1970 21:20:00 +0000
128 128 Tue, 13 Jan 1970 17:33:20 +0000
129 129 Mon, 12 Jan 1970 13:46:40 +0000
130 130
131 131 $ hg log --template '{desc|firstline}\n'
132 132 third
133 133 second
134 134 merge
135 135 new head
136 136 new branch
137 137 no user, no domain
138 138 no person
139 139 other 1
140 140 line 1
141 141
142 142 $ hg log --template '{node|short}\n'
143 143 95c24699272e
144 144 29114dbae42b
145 145 d41e714fe50d
146 146 13207e5a10d9
147 147 bbe44766e73d
148 148 10e46f2dcbf4
149 149 97054abb4ab8
150 150 b608e9d1a3f0
151 151 1e4e1b8f71e0
152 152
153 153 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
154 154 <changeset author="test"/>
155 155 <changeset author="User Name &lt;user@hostname&gt;"/>
156 156 <changeset author="person"/>
157 157 <changeset author="person"/>
158 158 <changeset author="person"/>
159 159 <changeset author="person"/>
160 160 <changeset author="other@place"/>
161 161 <changeset author="A. N. Other &lt;other@place&gt;"/>
162 162 <changeset author="User Name &lt;user@hostname&gt;"/>
163 163
164 164 $ hg log --template '{rev}: {children}\n'
165 165 8:
166 166 7: 8:95c24699272e
167 167 6:
168 168 5: 6:d41e714fe50d
169 169 4: 6:d41e714fe50d
170 170 3: 4:bbe44766e73d 5:13207e5a10d9
171 171 2: 3:10e46f2dcbf4
172 172 1: 2:97054abb4ab8
173 173 0: 1:b608e9d1a3f0
174 174
175 175 Formatnode filter works:
176 176
177 177 $ hg -q log -r 0 --template '{node|formatnode}\n'
178 178 1e4e1b8f71e0
179 179
180 180 $ hg log -r 0 --template '{node|formatnode}\n'
181 181 1e4e1b8f71e0
182 182
183 183 $ hg -v log -r 0 --template '{node|formatnode}\n'
184 184 1e4e1b8f71e0
185 185
186 186 $ hg --debug log -r 0 --template '{node|formatnode}\n'
187 187 1e4e1b8f71e05681d422154f5421e385fec3454f
188 188
189 189 Age filter:
190 190
191 191 $ hg init unstable-hash
192 192 $ cd unstable-hash
193 193 $ hg log --template '{date|age}\n' > /dev/null || exit 1
194 194
195 195 >>> from __future__ import absolute_import
196 196 >>> import datetime
197 197 >>> fp = open('a', 'wb')
198 198 >>> n = datetime.datetime.now() + datetime.timedelta(366 * 7)
199 199 >>> fp.write(b'%d-%d-%d 00:00' % (n.year, n.month, n.day)) and None
200 200 >>> fp.close()
201 201 $ hg add a
202 202 $ hg commit -m future -d "`cat a`"
203 203
204 204 $ hg log -l1 --template '{date|age}\n'
205 205 7 years from now
206 206
207 207 $ cd ..
208 208 $ rm -rf unstable-hash
209 209
210 210 Filename filters:
211 211
212 212 $ hg debugtemplate '{"foo/bar"|basename}|{"foo/"|basename}|{"foo"|basename}|\n'
213 213 bar||foo|
214 214 $ hg debugtemplate '{"foo/bar"|dirname}|{"foo/"|dirname}|{"foo"|dirname}|\n'
215 215 foo|foo||
216 216 $ hg debugtemplate '{"foo/bar"|stripdir}|{"foo/"|stripdir}|{"foo"|stripdir}|\n'
217 217 foo|foo|foo|
218 218
219 219 commondir() filter:
220 220
221 221 $ hg debugtemplate '{""|splitlines|commondir}\n'
222 222
223 223 $ hg debugtemplate '{"foo/bar\nfoo/baz\nfoo/foobar\n"|splitlines|commondir}\n'
224 224 foo
225 225 $ hg debugtemplate '{"foo/bar\nfoo/bar\n"|splitlines|commondir}\n'
226 226 foo
227 227 $ hg debugtemplate '{"/foo/bar\n/foo/bar\n"|splitlines|commondir}\n'
228 228 foo
229 229 $ hg debugtemplate '{"/foo\n/foo\n"|splitlines|commondir}\n'
230 230
231 231 $ hg debugtemplate '{"foo/bar\nbar/baz"|splitlines|commondir}\n'
232 232
233 233 $ hg debugtemplate '{"foo/bar\nbar/baz\nbar/foo\n"|splitlines|commondir}\n'
234 234
235 235 $ hg debugtemplate '{"foo/../bar\nfoo/bar"|splitlines|commondir}\n'
236 236 foo
237 237 $ hg debugtemplate '{"foo\n/foo"|splitlines|commondir}\n'
238 238
239 239
240 240 $ hg log -r null -T '{rev|commondir}'
241 241 hg: parse error: argument is not a list of text
242 242 (template filter 'commondir' is not compatible with keyword 'rev')
243 243 [255]
244 244
245 245 Add a dummy commit to make up for the instability of the above:
246 246
247 247 $ echo a > a
248 248 $ hg add a
249 249 $ hg ci -m future
250 250
251 251 Count filter:
252 252
253 253 $ hg log -l1 --template '{node|count} {node|short|count}\n'
254 254 40 12
255 255
256 256 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
257 257 0 1 4
258 258
259 259 $ hg log -G --template '{rev}: children: {children|count}, \
260 260 > tags: {tags|count}, file_adds: {file_adds|count}, \
261 261 > ancestors: {revset("ancestors(%s)", rev)|count}'
262 262 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
263 263 |
264 264 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
265 265 |
266 266 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
267 267
268 268 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
269 269 |\
270 270 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
271 271 | |
272 272 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
273 273 |/
274 274 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
275 275 |
276 276 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
277 277 |
278 278 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
279 279 |
280 280 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
281 281
282 282
283 283 $ hg log -l1 -T '{termwidth|count}\n'
284 284 hg: parse error: not countable
285 285 (template filter 'count' is not compatible with keyword 'termwidth')
286 286 [255]
287 287
288 288 Upper/lower filters:
289 289
290 290 $ hg log -r0 --template '{branch|upper}\n'
291 291 DEFAULT
292 292 $ hg log -r0 --template '{author|lower}\n'
293 293 user name <user@hostname>
294 294 $ hg log -r0 --template '{date|upper}\n'
295 295 1000000.00
296 296
297 297 Add a commit that does all possible modifications at once
298 298
299 299 $ echo modify >> third
300 300 $ touch b
301 301 $ hg add b
302 302 $ hg mv fourth fifth
303 303 $ hg rm a
304 304 $ hg ci -m "Modify, add, remove, rename"
305 305
306 306 Pass generator object created by template function to filter
307 307
308 308 $ hg log -l 1 --template '{if(author, author)|user}\n'
309 309 test
310 310
311 311 Test diff function:
312 312
313 313 $ hg diff -c 8
314 314 diff -r 29114dbae42b -r 95c24699272e fourth
315 315 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
316 316 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
317 317 @@ -0,0 +1,1 @@
318 318 +second
319 319 diff -r 29114dbae42b -r 95c24699272e second
320 320 --- a/second Mon Jan 12 13:46:40 1970 +0000
321 321 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
322 322 @@ -1,1 +0,0 @@
323 323 -second
324 324 diff -r 29114dbae42b -r 95c24699272e third
325 325 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
326 326 +++ b/third Wed Jan 01 10:01:00 2020 +0000
327 327 @@ -0,0 +1,1 @@
328 328 +third
329 329
330 330 $ hg log -r 8 -T "{diff()}"
331 331 diff -r 29114dbae42b -r 95c24699272e fourth
332 332 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
333 333 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
334 334 @@ -0,0 +1,1 @@
335 335 +second
336 336 diff -r 29114dbae42b -r 95c24699272e second
337 337 --- a/second Mon Jan 12 13:46:40 1970 +0000
338 338 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
339 339 @@ -1,1 +0,0 @@
340 340 -second
341 341 diff -r 29114dbae42b -r 95c24699272e third
342 342 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
343 343 +++ b/third Wed Jan 01 10:01:00 2020 +0000
344 344 @@ -0,0 +1,1 @@
345 345 +third
346 346
347 347 $ hg log -r 8 -T "{diff('glob:f*')}"
348 348 diff -r 29114dbae42b -r 95c24699272e fourth
349 349 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
350 350 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
351 351 @@ -0,0 +1,1 @@
352 352 +second
353 353
354 354 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
355 355 diff -r 29114dbae42b -r 95c24699272e second
356 356 --- a/second Mon Jan 12 13:46:40 1970 +0000
357 357 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
358 358 @@ -1,1 +0,0 @@
359 359 -second
360 360 diff -r 29114dbae42b -r 95c24699272e third
361 361 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
362 362 +++ b/third Wed Jan 01 10:01:00 2020 +0000
363 363 @@ -0,0 +1,1 @@
364 364 +third
365 365
366 366 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
367 367 diff -r 29114dbae42b -r 95c24699272e fourth
368 368 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
369 369 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
370 370 @@ -0,0 +1,1 @@
371 371 +second
372 372
373 373 $ hg --config diff.git=true log -r 8 -T "{diff()}"
374 374 diff --git a/second b/fourth
375 375 rename from second
376 376 rename to fourth
377 377 diff --git a/third b/third
378 378 new file mode 100644
379 379 --- /dev/null
380 380 +++ b/third
381 381 @@ -0,0 +1,1 @@
382 382 +third
383 383
384 384 $ cd ..
385 385
386 386 latesttag() function:
387 387
388 388 $ hg init latesttag
389 389 $ cd latesttag
390 390
391 391 $ echo a > file
392 392 $ hg ci -Am a -d '0 0'
393 393 adding file
394 394
395 395 $ echo b >> file
396 396 $ hg ci -m b -d '1 0'
397 397
398 398 $ echo c >> head1
399 399 $ hg ci -Am h1c -d '2 0'
400 400 adding head1
401 401
402 402 $ hg update -q 1
403 403 $ echo d >> head2
404 404 $ hg ci -Am h2d -d '3 0'
405 405 adding head2
406 406 created new head
407 407
408 408 $ echo e >> head2
409 409 $ hg ci -m h2e -d '4 0'
410 410
411 411 $ hg merge -q
412 412 $ hg ci -m merge -d '5 -3600'
413 413
414 414 $ hg tag -r 1 -m t1 -d '6 0' t1
415 415 $ hg tag -r 2 -m t2 -d '7 0' t2
416 416 $ hg tag -r 3 -m t3 -d '8 0' t3
417 417 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
418 418 $ hg tag -r 5 -m t5 -d '9 0' t5
419 419 $ hg tag -r 3 -m at3 -d '10 0' at3
420 420
421 421 $ hg log -G --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
422 422 @ 11: t3, C: 9, D: 8
423 423 |
424 424 o 10: t3, C: 8, D: 7
425 425 |
426 426 o 9: t3, C: 7, D: 6
427 427 |
428 428 o 8: t3, C: 6, D: 5
429 429 |
430 430 o 7: t3, C: 5, D: 4
431 431 |
432 432 o 6: t3, C: 4, D: 3
433 433 |
434 434 o 5: t3, C: 3, D: 2
435 435 |\
436 436 | o 4: t3, C: 1, D: 1
437 437 | |
438 438 | o 3: t3, C: 0, D: 0
439 439 | |
440 440 o | 2: t1, C: 1, D: 1
441 441 |/
442 442 o 1: t1, C: 0, D: 0
443 443 |
444 444 o 0: null, C: 1, D: 1
445 445
446 446
447 447 $ cd ..
448 448
449 449 Test filter() empty values:
450 450
451 451 $ hg log -R a -r 1 -T '{filter(desc|splitlines) % "{line}\n"}'
452 452 other 1
453 453 other 2
454 454 other 3
455 455 $ hg log -R a -r 0 -T '{filter(dict(a=0, b=1) % "{ifeq(key, "a", "{value}\n")}")}'
456 456 0
457 457
458 458 0 should not be falsy
459 459
460 460 $ hg log -R a -r 0 -T '{filter(revset("0:2"))}\n'
461 461 0 1 2
462 462
463 463 Test filter() by expression:
464 464
465 465 $ hg log -R a -r 1 -T '{filter(desc|splitlines, ifcontains("1", line, "t"))}\n'
466 466 other 1
467 467 $ hg log -R a -r 0 -T '{filter(dict(a=0, b=1), ifeq(key, "b", "t"))}\n'
468 468 b=1
469 469
470 470 Test filter() shouldn't crash:
471 471
472 472 $ hg log -R a -r 0 -T '{filter(extras)}\n'
473 473 branch=default
474 474 $ hg log -R a -r 0 -T '{filter(files)}\n'
475 475 a
476 476
477 477 Test filter() unsupported arguments:
478 478
479 479 $ hg log -R a -r 0 -T '{filter()}\n'
480 480 hg: parse error: filter expects one or two arguments
481 481 [255]
482 482 $ hg log -R a -r 0 -T '{filter(date)}\n'
483 483 hg: parse error: date is not iterable
484 484 [255]
485 485 $ hg log -R a -r 0 -T '{filter(rev)}\n'
486 486 hg: parse error: 0 is not iterable
487 487 [255]
488 488 $ hg log -R a -r 0 -T '{filter(desc|firstline)}\n'
489 489 hg: parse error: 'line 1' is not filterable
490 490 [255]
491 491 $ hg log -R a -r 0 -T '{filter(manifest)}\n'
492 492 hg: parse error: '0:a0c8bcbbb45c' is not filterable
493 493 [255]
494 494 $ hg log -R a -r 0 -T '{filter(succsandmarkers)}\n'
495 495 hg: parse error: not filterable without template
496 496 [255]
497 497 $ hg log -R a -r 0 -T '{filter(desc|splitlines % "{line}", "")}\n'
498 498 hg: parse error: not filterable by expression
499 499 [255]
500 500
501 501 Test manifest/get() can be join()-ed as string, though it's silly:
502 502
503 503 $ hg log -R latesttag -r tip -T '{join(manifest, ".")}\n'
504 504 1.1.:.2.b.c.6.e.9.0.0.6.c.e.2
505 505 $ hg log -R latesttag -r tip -T '{join(get(extras, "branch"), ".")}\n'
506 506 d.e.f.a.u.l.t
507 507
508 508 Test join() over string
509 509
510 510 $ hg log -R latesttag -r tip -T '{join(rev|stringify, ".")}\n'
511 511 1.1
512 512
513 513 Test join() over uniterable
514 514
515 515 $ hg log -R latesttag -r tip -T '{join(rev, "")}\n'
516 516 hg: parse error: 11 is not iterable
517 517 [255]
518 518
519 519 Test min/max of integers
520 520
521 521 $ hg log -R latesttag -l1 -T '{min(revset("9:10"))}\n'
522 522 9
523 523 $ hg log -R latesttag -l1 -T '{max(revset("9:10"))}\n'
524 524 10
525 525
526 526 Test min/max over map operation:
527 527
528 528 $ hg log -R latesttag -r3 -T '{min(tags % "{tag}")}\n'
529 529 at3
530 530 $ hg log -R latesttag -r3 -T '{max(tags % "{tag}")}\n'
531 531 t3
532 532
533 533 Test min/max of strings:
534 534
535 535 $ hg log -R latesttag -l1 -T '{min(desc)}\n'
536 536 3
537 537 $ hg log -R latesttag -l1 -T '{max(desc)}\n'
538 538 t
539 539
540 540 Test min/max of non-iterable:
541 541
542 542 $ hg debugtemplate '{min(1)}'
543 543 hg: parse error: 1 is not iterable
544 544 (min first argument should be an iterable)
545 545 [255]
546 546 $ hg debugtemplate '{max(2)}'
547 547 hg: parse error: 2 is not iterable
548 548 (max first argument should be an iterable)
549 549 [255]
550 550
551 551 $ hg log -R latesttag -l1 -T '{min(date)}'
552 552 hg: parse error: date is not iterable
553 553 (min first argument should be an iterable)
554 554 [255]
555 555 $ hg log -R latesttag -l1 -T '{max(date)}'
556 556 hg: parse error: date is not iterable
557 557 (max first argument should be an iterable)
558 558 [255]
559 559
560 560 Test min/max of empty sequence:
561 561
562 562 $ hg debugtemplate '{min("")}'
563 563 hg: parse error: empty string
564 564 (min first argument should be an iterable)
565 565 [255]
566 566 $ hg debugtemplate '{max("")}'
567 567 hg: parse error: empty string
568 568 (max first argument should be an iterable)
569 569 [255]
570 570 $ hg debugtemplate '{min(dict())}'
571 571 hg: parse error: empty sequence
572 572 (min first argument should be an iterable)
573 573 [255]
574 574 $ hg debugtemplate '{max(dict())}'
575 575 hg: parse error: empty sequence
576 576 (max first argument should be an iterable)
577 577 [255]
578 578 $ hg debugtemplate '{min(dict() % "")}'
579 579 hg: parse error: empty sequence
580 580 (min first argument should be an iterable)
581 581 [255]
582 582 $ hg debugtemplate '{max(dict() % "")}'
583 583 hg: parse error: empty sequence
584 584 (max first argument should be an iterable)
585 585 [255]
586 586
587 587 Test min/max of if() result
588 588
589 589 $ cd latesttag
590 590 $ hg log -l1 -T '{min(if(true, revset("9:10"), ""))}\n'
591 591 9
592 592 $ hg log -l1 -T '{max(if(false, "", revset("9:10")))}\n'
593 593 10
594 594 $ hg log -l1 -T '{min(ifcontains("a", "aa", revset("9:10"), ""))}\n'
595 595 9
596 596 $ hg log -l1 -T '{max(ifcontains("a", "bb", "", revset("9:10")))}\n'
597 597 10
598 598 $ hg log -l1 -T '{min(ifeq(0, 0, revset("9:10"), ""))}\n'
599 599 9
600 600 $ hg log -l1 -T '{max(ifeq(0, 1, "", revset("9:10")))}\n'
601 601 10
602 602 $ cd ..
603 603
604 604 Test laziness of if() then/else clause
605 605
606 606 $ hg debugtemplate '{count(0)}'
607 607 hg: parse error: not countable
608 608 (incompatible use of template filter 'count')
609 609 [255]
610 610 $ hg debugtemplate '{if(true, "", count(0))}'
611 611 $ hg debugtemplate '{if(false, count(0), "")}'
612 612 $ hg debugtemplate '{ifcontains("a", "aa", "", count(0))}'
613 613 $ hg debugtemplate '{ifcontains("a", "bb", count(0), "")}'
614 614 $ hg debugtemplate '{ifeq(0, 0, "", count(0))}'
615 615 $ hg debugtemplate '{ifeq(0, 1, count(0), "")}'
616 616
617 617 Test search() function:
618 618
619 619 $ hg log -R a -r2 -T '{desc}\n'
620 620 no person
621 621
622 622 $ hg log -R a -r2 -T '{search(r"p.*", desc)}\n'
623 623 person
624 624
625 625 as bool
626 626
627 627 $ hg log -R a -r2 -T '{if(search(r"p.*", desc), "", "not ")}found\n'
628 628 found
629 629 $ hg log -R a -r2 -T '{if(search(r"q", desc), "", "not ")}found\n'
630 630 not found
631 631
632 632 match as json
633 633
634 634 $ hg log -R a -r2 -T '{search(r"(no) p.*", desc)|json}\n'
635 635 {"0": "no person", "1": "no"}
636 636 $ hg log -R a -r2 -T '{search(r"q", desc)|json}\n'
637 637 null
638 638
639 639 group reference
640 640
641 641 $ hg log -R a -r2 -T '{search(r"(no) (p.*)", desc) % "{1|upper} {2|hex}"}\n'
642 642 NO 706572736f6e
643 643 $ hg log -R a -r2 -T '{search(r"(?P<foo>[a-z]*)", desc) % "{foo}"}\n'
644 644 no
645 645 $ hg log -R a -r2 -T '{search(r"(?P<foo>[a-z]*)", desc).foo}\n'
646 646 no
647 647
648 648 group reference with no match
649 649
650 650 $ hg log -R a -r2 -T '{search(r"q", desc) % "match: {0}"}\n'
651 651
652 652
653 653 bad group names
654 654
655 655 $ hg log -R a -r2 -T '{search(r"(?P<0>.)", desc) % "{0}"}\n'
656 656 hg: parse error: search got an invalid pattern: (?P<0>.)
657 657 [255]
658 658 $ hg log -R a -r2 -T '{search(r"(?P<repo>.)", desc) % "{repo}"}\n'
659 659 hg: parse error: invalid group 'repo' in search pattern: (?P<repo>.)
660 660 [255]
661 661
662 662 Test the sub function of templating for expansion:
663 663
664 664 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
665 665 xx
666 666
667 667 $ hg log -R latesttag -r 10 -T '{sub("[", "x", rev)}\n'
668 668 hg: parse error: sub got an invalid pattern: [
669 669 [255]
670 670 $ hg log -R latesttag -r 10 -T '{sub("[0-9]", r"\1", rev)}\n'
671 671 hg: parse error: sub got an invalid replacement: \1
672 672 [255]
673 673
674 674 Test the strip function with chars specified:
675 675
676 676 $ hg log -R latesttag --template '{desc}\n'
677 677 at3
678 678 t5
679 679 t4
680 680 t3
681 681 t2
682 682 t1
683 683 merge
684 684 h2e
685 685 h2d
686 686 h1c
687 687 b
688 688 a
689 689
690 690 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
691 691 at3
692 692 5
693 693 4
694 694 3
695 695 2
696 696 1
697 697 merg
698 698 h2
699 699 h2d
700 700 h1c
701 701 b
702 702 a
703 703
704 704 Test date format:
705 705
706 706 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
707 707 date: 70 01 01 10 +0000
708 708 date: 70 01 01 09 +0000
709 709 date: 70 01 01 04 +0000
710 710 date: 70 01 01 08 +0000
711 711 date: 70 01 01 07 +0000
712 712 date: 70 01 01 06 +0000
713 713 date: 70 01 01 05 +0100
714 714 date: 70 01 01 04 +0000
715 715 date: 70 01 01 03 +0000
716 716 date: 70 01 01 02 +0000
717 717 date: 70 01 01 01 +0000
718 718 date: 70 01 01 00 +0000
719 719
720 720 Test invalid date:
721 721
722 722 $ hg log -R latesttag -T '{date(rev)}\n'
723 723 hg: parse error: date expects a date information
724 724 [255]
725 725
726 726 Set up repository containing template fragments in commit metadata:
727 727
728 728 $ hg init r
729 729 $ cd r
730 730 $ echo a > a
731 731 $ hg ci -Am '{rev}'
732 732 adding a
733 733
734 734 $ hg branch -q 'text.{rev}'
735 735 $ echo aa >> aa
736 736 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
737 737
738 738 color effect can be specified without quoting:
739 739
740 740 $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
741 741 \x1b[0;31mtext\x1b[0m (esc)
742 742
743 743 color effects can be nested (issue5413)
744 744
745 745 $ hg debugtemplate --color=always \
746 746 > '{label(red, "red{label(magenta, "ma{label(cyan, "cyan")}{label(yellow, "yellow")}genta")}")}\n'
747 747 \x1b[0;31mred\x1b[0;35mma\x1b[0;36mcyan\x1b[0m\x1b[0;31m\x1b[0;35m\x1b[0;33myellow\x1b[0m\x1b[0;31m\x1b[0;35mgenta\x1b[0m (esc)
748 748
749 749 pad() should interact well with color codes (issue5416)
750 750
751 751 $ hg debugtemplate --color=always \
752 752 > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n'
753 753 \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc)
754 754
755 755 pad() with truncate has to strip color codes, though
756 756
757 757 $ hg debugtemplate --color=always \
758 758 > '{pad(label(red, "scarlet"), 5, truncate=true)}\n'
759 759 scarl
760 760
761 761 label should be no-op if color is disabled:
762 762
763 763 $ hg log --color=never -l 1 --template '{label(red, "text\n")}'
764 764 text
765 765 $ hg log --config extensions.color=! -l 1 --template '{label(red, "text\n")}'
766 766 text
767 767
768 768 Test branches inside if statement:
769 769
770 770 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
771 771 no
772 772
773 773 Test dict constructor:
774 774
775 775 $ hg log -r 0 -T '{dict(y=node|short, x=rev)}\n'
776 776 y=f7769ec2ab97 x=0
777 777 $ hg log -r 0 -T '{dict(x=rev, y=node|short) % "{key}={value}\n"}'
778 778 x=0
779 779 y=f7769ec2ab97
780 780 $ hg log -r 0 -T '{dict(x=rev, y=node|short)|json}\n'
781 781 {"x": 0, "y": "f7769ec2ab97"}
782 782 $ hg log -r 0 -T '{dict()|json}\n'
783 783 {}
784 784
785 785 $ hg log -r 0 -T '{dict(rev, node=node|short)}\n'
786 786 rev=0 node=f7769ec2ab97
787 787 $ hg log -r 0 -T '{dict(rev, node|short)}\n'
788 788 rev=0 node=f7769ec2ab97
789 789
790 790 $ hg log -r 0 -T '{dict(rev, rev=rev)}\n'
791 791 hg: parse error: duplicated dict key 'rev' inferred
792 792 [255]
793 793 $ hg log -r 0 -T '{dict(node, node|short)}\n'
794 794 hg: parse error: duplicated dict key 'node' inferred
795 795 [255]
796 796 $ hg log -r 0 -T '{dict(1 + 2)}'
797 797 hg: parse error: dict key cannot be inferred
798 798 [255]
799 799
800 800 $ hg log -r 0 -T '{dict(x=rev, x=node)}'
801 801 hg: parse error: dict got multiple values for keyword argument 'x'
802 802 [255]
803 803
804 804 Test get function:
805 805
806 806 $ hg log -r 0 --template '{get(extras, "branch")}\n'
807 807 default
808 808 $ hg log -r 0 --template '{get(extras, "br{"anch"}")}\n'
809 809 default
810 810 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
811 811 hg: parse error: not a dictionary
812 812 (get() expects a dict as first argument)
813 813 [255]
814 814
815 815 Test json filter applied to wrapped object:
816 816
817 817 $ hg log -r0 -T '{files|json}\n'
818 818 ["a"]
819 819 $ hg log -r0 -T '{extras|json}\n'
820 820 {"branch": "default"}
821 821 $ hg log -r0 -T '{date|json}\n'
822 822 [0, 0]
823 823
824 824 Test json filter applied to map result:
825 825
826 826 $ hg log -r0 -T '{json(extras % "{key}")}\n'
827 827 ["branch"]
828 828
829 829 Test localdate(date, tz) function:
830 830
831 831 $ TZ=JST-09 hg log -r0 -T '{date|localdate|isodate}\n'
832 832 1970-01-01 09:00 +0900
833 833 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "UTC")|isodate}\n'
834 834 1970-01-01 00:00 +0000
835 835 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n'
836 836 hg: parse error: localdate expects a timezone
837 837 [255]
838 838 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n'
839 839 1970-01-01 02:00 +0200
840 840 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n'
841 841 1970-01-01 00:00 +0000
842 842 $ TZ=JST-09 hg log -r0 -T '{localdate(date, 0)|isodate}\n'
843 843 1970-01-01 00:00 +0000
844 844 $ hg log -r0 -T '{localdate(date, "invalid")|isodate}\n'
845 845 hg: parse error: localdate expects a timezone
846 846 [255]
847 847 $ hg log -r0 -T '{localdate(date, date)|isodate}\n'
848 848 hg: parse error: localdate expects a timezone
849 849 [255]
850 850
851 851 Test shortest(node) function:
852 852
853 853 $ echo b > b
854 854 $ hg ci -qAm b
855 855 $ hg log --template '{shortest(node)}\n'
856 856 e777
857 857 bcc7
858 858 f776
859 859 $ hg log --template '{shortest(node, 10)}\n'
860 860 e777603221
861 861 bcc7ff960b
862 862 f7769ec2ab
863 863 $ hg log --template '{shortest(node, 1)}\n' -r null
864 864 00
865 865 $ hg log --template '{node|shortest}\n' -l1
866 866 e777
867 867
868 868 $ hg log -r 0 -T '{shortest(node, "1{"0"}")}\n'
869 869 f7769ec2ab
870 870 $ hg log -r 0 -T '{shortest(node, "not an int")}\n'
871 871 hg: parse error: shortest() expects an integer minlength
872 872 [255]
873 873
874 874 $ hg log -r 'wdir()' -T '{node|shortest}\n'
875 875 ffff
876 876
877 877 $ hg log --template '{shortest("f")}\n' -l1
878 878 f
879 879
880 880 $ hg log --template '{shortest("0123456789012345678901234567890123456789")}\n' -l1
881 881 0123456789012345678901234567890123456789
882 882
883 883 $ hg log --template '{shortest("01234567890123456789012345678901234567890123456789")}\n' -l1
884 884 01234567890123456789012345678901234567890123456789
885 885
886 886 $ hg log --template '{shortest("not a hex string")}\n' -l1
887 887 not a hex string
888 888
889 889 $ hg log --template '{shortest("not a hex string, but it'\''s 40 bytes long")}\n' -l1
890 890 not a hex string, but it's 40 bytes long
891 891
892 892 $ hg log --template '{shortest("ffffffffffffffffffffffffffffffffffffffff")}\n' -l1
893 893 ffff
894 894
895 895 $ hg log --template '{shortest("fffffff")}\n' -l1
896 896 ffff
897 897
898 898 $ hg log --template '{shortest("ff")}\n' -l1
899 899 ffff
900 900
901 901 $ cd ..
902 902
903 903 Test shortest(node) with the repo having short hash collision:
904 904
905 905 $ hg init hashcollision
906 906 $ cd hashcollision
907 907 $ cat <<EOF >> .hg/hgrc
908 908 > [experimental]
909 909 > evolution.createmarkers=True
910 910 > EOF
911 911 $ echo 0 > a
912 912 $ hg ci -qAm 0
913 913 $ for i in 17 129 248 242 480 580 617 1057 2857 4025; do
914 914 > hg up -q 0
915 915 > echo $i > a
916 916 > hg ci -qm $i
917 917 > done
918 918 $ hg up -q null
919 919 $ hg log -r0: -T '{rev}:{node}\n'
920 920 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
921 921 1:11424df6dc1dd4ea255eae2b58eaca7831973bbc
922 922 2:11407b3f1b9c3e76a79c1ec5373924df096f0499
923 923 3:11dd92fe0f39dfdaacdaa5f3997edc533875cfc4
924 924 4:10776689e627b465361ad5c296a20a487e153ca4
925 925 5:a00be79088084cb3aff086ab799f8790e01a976b
926 926 6:a0b0acd79b4498d0052993d35a6a748dd51d13e6
927 927 7:a0457b3450b8e1b778f1163b31a435802987fe5d
928 928 8:c56256a09cd28e5764f32e8e2810d0f01e2e357a
929 929 9:c5623987d205cd6d9d8389bfc40fff9dbb670b48
930 930 10:c562ddd9c94164376c20b86b0b4991636a3bf84f
931 931 $ hg debugobsolete a00be79088084cb3aff086ab799f8790e01a976b
932 932 1 new obsolescence markers
933 933 obsoleted 1 changesets
934 934 $ hg debugobsolete c5623987d205cd6d9d8389bfc40fff9dbb670b48
935 935 1 new obsolescence markers
936 936 obsoleted 1 changesets
937 937 $ hg debugobsolete c562ddd9c94164376c20b86b0b4991636a3bf84f
938 938 1 new obsolescence markers
939 939 obsoleted 1 changesets
940 940
941 941 nodes starting with '11' (we don't have the revision number '11' though)
942 942
943 943 $ hg log -r 1:3 -T '{rev}:{shortest(node, 0)}\n'
944 944 1:1142
945 945 2:1140
946 946 3:11d
947 947
948 948 '5:a00' is hidden, but still we have two nodes starting with 'a0'
949 949
950 950 $ hg log -r 6:7 -T '{rev}:{shortest(node, 0)}\n'
951 951 6:a0b
952 952 7:a04
953 953
954 954 node '10' conflicts with the revision number '10' even if it is hidden
955 955 (we could exclude hidden revision numbers, but currently we don't)
956 956
957 957 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n'
958 958 4:107
959 959 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
960 960 4:107
961 961
962 962 $ hg --config experimental.revisions.prefixhexnode=yes log -r 4 -T '{rev}:{shortest(node, 0)}\n'
963 963 4:x10
964 964 $ hg --config experimental.revisions.prefixhexnode=yes log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
965 965 4:x10
966 966
967 967 node 'c562' should be unique if the other 'c562' nodes are hidden
968 968 (but we don't try the slow path to filter out hidden nodes for now)
969 969
970 970 $ hg log -r 8 -T '{rev}:{node|shortest}\n'
971 971 8:c5625
972 972 $ hg log -r 8:10 -T '{rev}:{node|shortest}\n' --hidden
973 973 8:c5625
974 974 9:c5623
975 975 10:c562d
976 976
977 977 $ cd ..
978 978
979 979 Test prefixhexnode when the first character of the hash is 0.
980 980 $ hg init hashcollision2
981 981 $ cd hashcollision2
982 982 $ cat <<EOF >> .hg/hgrc
983 983 > [experimental]
984 984 > evolution.createmarkers=True
985 985 > EOF
986 986 $ echo 0 > a
987 987 $ hg ci -qAm 0
988 988 $ echo 21 > a
989 989 $ hg ci -qm 21
990 990 $ hg up -q null
991 991 $ hg log -r0: -T '{rev}:{node}\n'
992 992 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
993 993 1:0cf177ba2b1dc3862a00fb81715fec90950201be
994 994
995 995 we need the 'x' prefix to ensure we aren't colliding with rev0. We identify
996 996 the collision with nullid if we aren't using disambiguatewithin, so we need to set
997 997 that as well.
998 998 $ hg --config experimental.revisions.disambiguatewithin='descendants(0)' \
999 999 > --config experimental.revisions.prefixhexnode=yes \
1000 1000 > log -r 1 -T '{rev}:{shortest(node, 0)}\n'
1001 1001 1:x0
1002 1002
1003 1003 $ hg debugobsolete 0cf177ba2b1dc3862a00fb81715fec90950201be
1004 1004 1 new obsolescence markers
1005 1005 obsoleted 1 changesets
1006 1006 $ hg up -q 0
1007 1007 $ echo 61 > a
1008 1008 $ hg ci -m 61
1009 1009 $ hg log -r0: -T '{rev}:{node}\n'
1010 1010 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
1011 1011 2:01384dde84b3a511ae0835f35ac40bd806c99bb8
1012 1012
1013 1013 we still have the 'x' prefix because '0' is still the shortest prefix, since
1014 1014 rev1's '0c' is hidden.
1015 1015 $ hg --config experimental.revisions.disambiguatewithin=0:-1-0 \
1016 1016 > --config experimental.revisions.prefixhexnode=yes \
1017 1017 > log -r 0:-1-0 -T '{rev}:{shortest(node, 0)}\n'
1018 1018 2:x0
1019 1019
1020 1020 we don't have the 'x' prefix on 2 because '01' is not a synonym for rev1.
1021 1021 $ hg --config experimental.revisions.disambiguatewithin=0:-1-0 \
1022 1022 > --config experimental.revisions.prefixhexnode=yes \
1023 1023 > log -r 0:-1-0 -T '{rev}:{shortest(node, 0)}\n' --hidden
1024 1024 1:0c
1025 1025 2:01
1026 1026
1027 1027 $ cd ..
1028 1028
1029 1029 Test pad function
1030 1030
1031 1031 $ cd r
1032 1032
1033 1033 $ hg log --template '{pad(rev, 20)} {author|user}\n'
1034 1034 2 test
1035 1035 1 {node|short}
1036 1036 0 test
1037 1037
1038 1038 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
1039 1039 2 test
1040 1040 1 {node|short}
1041 1041 0 test
1042 1042
1043 1043 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
1044 1044 2------------------- test
1045 1045 1------------------- {node|short}
1046 1046 0------------------- test
1047 1047
1048 1048 $ hg log --template '{pad(author, 5, "-", False, True)}\n'
1049 1049 test-
1050 1050 {node
1051 1051 test-
1052 1052 $ hg log --template '{pad(author, 5, "-", True, True)}\n'
1053 1053 -test
1054 1054 hort}
1055 1055 -test
1056 1056
1057 1057 Test template string in pad function
1058 1058
1059 1059 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
1060 1060 {0} test
1061 1061
1062 1062 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
1063 1063 \{rev} test
1064 1064
1065 1065 Test width argument passed to pad function
1066 1066
1067 1067 $ hg log -r 0 -T '{pad(rev, "1{"0"}")} {author|user}\n'
1068 1068 0 test
1069 1069 $ hg log -r 0 -T '{pad(rev, "not an int")}\n'
1070 1070 hg: parse error: pad() expects an integer width
1071 1071 [255]
1072 1072
1073 1073 Test invalid fillchar passed to pad function
1074 1074
1075 1075 $ hg log -r 0 -T '{pad(rev, 10, "")}\n'
1076 1076 hg: parse error: pad() expects a single fill character
1077 1077 [255]
1078 1078 $ hg log -r 0 -T '{pad(rev, 10, "--")}\n'
1079 1079 hg: parse error: pad() expects a single fill character
1080 1080 [255]
1081 1081
1082 1082 Test boolean argument passed to pad function
1083 1083
1084 1084 no crash
1085 1085
1086 1086 $ hg log -r 0 -T '{pad(rev, 10, "-", "f{"oo"}")}\n'
1087 1087 ---------0
1088 1088
1089 1089 string/literal
1090 1090
1091 1091 $ hg log -r 0 -T '{pad(rev, 10, "-", "false")}\n'
1092 1092 ---------0
1093 1093 $ hg log -r 0 -T '{pad(rev, 10, "-", false)}\n'
1094 1094 0---------
1095 1095 $ hg log -r 0 -T '{pad(rev, 10, "-", "")}\n'
1096 1096 0---------
1097 1097
1098 1098 unknown keyword is evaluated to ''
1099 1099
1100 1100 $ hg log -r 0 -T '{pad(rev, 10, "-", unknownkeyword)}\n'
1101 1101 0---------
1102 1102
1103 1103 Test separate function
1104 1104
1105 1105 $ hg log -r 0 -T '{separate("-", "", "a", "b", "", "", "c", "")}\n'
1106 1106 a-b-c
1107 1107 $ hg log -r 0 -T '{separate(" ", "{rev}:{node|short}", author|user, branch)}\n'
1108 1108 0:f7769ec2ab97 test default
1109 1109 $ hg log -r 0 --color=always -T '{separate(" ", "a", label(red, "b"), "c", label(red, ""), "d")}\n'
1110 1110 a \x1b[0;31mb\x1b[0m c d (esc)
1111 1111
1112 1112 Test boolean expression/literal passed to if function
1113 1113
1114 1114 $ hg log -r 0 -T '{if(rev, "rev 0 is True")}\n'
1115 1115 rev 0 is True
1116 1116 $ hg log -r 0 -T '{if(0, "literal 0 is True as well")}\n'
1117 1117 literal 0 is True as well
1118 1118 $ hg log -r 0 -T '{if(min(revset(r"0")), "0 of hybriditem is also True")}\n'
1119 1119 0 of hybriditem is also True
1120 1120 $ hg log -r 0 -T '{if("", "", "empty string is False")}\n'
1121 1121 empty string is False
1122 1122 $ hg log -r 0 -T '{if(revset(r"0 - 0"), "", "empty list is False")}\n'
1123 1123 empty list is False
1124 1124 $ hg log -r 0 -T '{if(revset(r"0"), "non-empty list is True")}\n'
1125 1125 non-empty list is True
1126 1126 $ hg log -r 0 -T '{if(revset(r"0") % "", "list of empty strings is True")}\n'
1127 1127 list of empty strings is True
1128 1128 $ hg log -r 0 -T '{if(true, "true is True")}\n'
1129 1129 true is True
1130 1130 $ hg log -r 0 -T '{if(false, "", "false is False")}\n'
1131 1131 false is False
1132 1132 $ hg log -r 0 -T '{if("false", "non-empty string is True")}\n'
1133 1133 non-empty string is True
1134 1134
1135 1135 Test ifcontains function
1136 1136
1137 1137 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
1138 1138 2 is in the string
1139 1139 1 is not
1140 1140 0 is in the string
1141 1141
1142 1142 $ hg log -T '{rev} {ifcontains(rev, "2 two{" 0"}", "is in the string", "is not")}\n'
1143 1143 2 is in the string
1144 1144 1 is not
1145 1145 0 is in the string
1146 1146
1147 1147 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
1148 1148 2 did not add a
1149 1149 1 did not add a
1150 1150 0 added a
1151 1151
1152 1152 $ hg log --debug -T '{rev}{ifcontains(1, parents, " is parent of 1")}\n'
1153 1153 2 is parent of 1
1154 1154 1
1155 1155 0
1156 1156
1157 1157 $ hg log -l1 -T '{ifcontains("branch", extras, "t", "f")}\n'
1158 1158 t
1159 1159 $ hg log -l1 -T '{ifcontains("branch", extras % "{key}", "t", "f")}\n'
1160 1160 t
1161 1161 $ hg log -l1 -T '{ifcontains("branc", extras % "{key}", "t", "f")}\n'
1162 1162 f
1163 1163 $ hg log -l1 -T '{ifcontains("branc", stringify(extras % "{key}"), "t", "f")}\n'
1164 1164 t
1165 1165
1166 1166 Test revset function
1167 1167
1168 1168 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
1169 1169 2 current rev
1170 1170 1 not current rev
1171 1171 0 not current rev
1172 1172
1173 1173 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
1174 1174 2 match rev
1175 1175 1 match rev
1176 1176 0 not match rev
1177 1177
1178 1178 $ hg log -T '{ifcontains(desc, revset(":"), "", "type not match")}\n' -l1
1179 1179 type not match
1180 1180
1181 1181 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
1182 1182 2 Parents: 1
1183 1183 1 Parents: 0
1184 1184 0 Parents:
1185 1185
1186 1186 $ cat >> .hg/hgrc <<EOF
1187 1187 > [revsetalias]
1188 1188 > myparents(\$1) = parents(\$1)
1189 1189 > EOF
1190 1190 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
1191 1191 2 Parents: 1
1192 1192 1 Parents: 0
1193 1193 0 Parents:
1194 1194
1195 1195 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
1196 1196 Rev: 2
1197 1197 Ancestor: 0
1198 1198 Ancestor: 1
1199 1199 Ancestor: 2
1200 1200
1201 1201 Rev: 1
1202 1202 Ancestor: 0
1203 1203 Ancestor: 1
1204 1204
1205 1205 Rev: 0
1206 1206 Ancestor: 0
1207 1207
1208 1208 $ hg log --template '{revset("TIP"|lower)}\n' -l1
1209 1209 2
1210 1210
1211 1211 $ hg log -T '{revset("%s", "t{"ip"}")}\n' -l1
1212 1212 2
1213 1213
1214 1214 a list template is evaluated for each item of revset/parents
1215 1215
1216 1216 $ hg log -T '{rev} p: {revset("p1(%s)", rev) % "{rev}:{node|short}"}\n'
1217 1217 2 p: 1:bcc7ff960b8e
1218 1218 1 p: 0:f7769ec2ab97
1219 1219 0 p:
1220 1220
1221 1221 $ hg log --debug -T '{rev} p:{parents % " {rev}:{node|short}"}\n'
1222 1222 2 p: 1:bcc7ff960b8e -1:000000000000
1223 1223 1 p: 0:f7769ec2ab97 -1:000000000000
1224 1224 0 p: -1:000000000000 -1:000000000000
1225 1225
1226 1226 therefore, 'revcache' should be recreated for each rev
1227 1227
1228 1228 $ hg log -T '{rev} {file_adds}\np {revset("p1(%s)", rev) % "{file_adds}"}\n'
1229 1229 2 aa b
1230 1230 p
1231 1231 1
1232 1232 p a
1233 1233 0 a
1234 1234 p
1235 1235
1236 1236 $ hg log --debug -T '{rev} {file_adds}\np {parents % "{file_adds}"}\n'
1237 1237 2 aa b
1238 1238 p
1239 1239 1
1240 1240 p a
1241 1241 0 a
1242 1242 p
1243 1243
1244 1244 a revset item must be evaluated as an integer revision, not an offset from tip
1245 1245
1246 1246 $ hg log -l 1 -T '{revset("null") % "{rev}:{node|short}"}\n'
1247 1247 -1:000000000000
1248 1248 $ hg log -l 1 -T '{revset("%s", "null") % "{rev}:{node|short}"}\n'
1249 1249 -1:000000000000
1250 1250
1251 1251 join() should pick '{rev}' from revset items:
1252 1252
1253 1253 $ hg log -R ../a -T '{join(revset("parents(%d)", rev), ", ")}\n' -r6
1254 1254 4, 5
1255 1255
1256 1256 on the other hand, parents are formatted as '{rev}:{node|formatnode}' by
1257 1257 default. join() should agree with the default formatting:
1258 1258
1259 1259 $ hg log -R ../a -T '{join(parents, ", ")}\n' -r6
1260 1260 5:13207e5a10d9, 4:bbe44766e73d
1261 1261
1262 1262 $ hg log -R ../a -T '{join(parents, ",\n")}\n' -r6 --debug
1263 1263 5:13207e5a10d9fd28ec424934298e176197f2c67f,
1264 1264 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1265 1265
1266 1266 Invalid arguments passed to revset()
1267 1267
1268 1268 $ hg log -T '{revset("%whatever", 0)}\n'
1269 1269 hg: parse error: unexpected revspec format character w
1270 1270 [255]
1271 1271 $ hg log -T '{revset("%lwhatever", files)}\n'
1272 1272 hg: parse error: unexpected revspec format character w
1273 1273 [255]
1274 1274 $ hg log -T '{revset("%s %s", 0)}\n'
1275 1275 hg: parse error: missing argument for revspec
1276 1276 [255]
1277 1277 $ hg log -T '{revset("", 0)}\n'
1278 1278 hg: parse error: too many revspec arguments specified
1279 1279 [255]
1280 1280 $ hg log -T '{revset("%s", 0, 1)}\n'
1281 1281 hg: parse error: too many revspec arguments specified
1282 1282 [255]
1283 1283 $ hg log -T '{revset("%", 0)}\n'
1284 1284 hg: parse error: incomplete revspec format character
1285 1285 [255]
1286 1286 $ hg log -T '{revset("%l", 0)}\n'
1287 1287 hg: parse error: incomplete revspec format character
1288 1288 [255]
1289 1289 $ hg log -T '{revset("%d", 'foo')}\n'
1290 1290 hg: parse error: invalid argument for revspec
1291 1291 [255]
1292 1292 $ hg log -T '{revset("%ld", files)}\n'
1293 1293 hg: parse error: invalid argument for revspec
1294 1294 [255]
1295 1295 $ hg log -T '{revset("%ls", 0)}\n'
1296 1296 hg: parse error: invalid argument for revspec
1297 1297 [255]
1298 1298 $ hg log -T '{revset("%b", 'foo')}\n'
1299 1299 hg: parse error: invalid argument for revspec
1300 1300 [255]
1301 1301 $ hg log -T '{revset("%lb", files)}\n'
1302 1302 hg: parse error: invalid argument for revspec
1303 1303 [255]
1304 1304 $ hg log -T '{revset("%r", 0)}\n'
1305 1305 hg: parse error: invalid argument for revspec
1306 1306 [255]
1307 1307
1308 1308 Test files function
1309 1309
1310 1310 $ hg log -T "{rev}\n{join(files('*'), '\n')}\n"
1311 1311 2
1312 1312 a
1313 1313 aa
1314 1314 b
1315 1315 1
1316 1316 a
1317 1317 0
1318 1318 a
1319 1319
1320 1320 $ hg log -T "{rev}\n{join(files('aa'), '\n')}\n"
1321 1321 2
1322 1322 aa
1323 1323 1
1324 1324
1325 1325 0
1326 1326
1327 1327
1328 1328 $ hg log -l1 -T "{files('aa') % '{file}\n'}"
1329 1329 aa
1330 1330 $ hg log -l1 -T "{files('aa') % '{path}\n'}"
1331 1331 aa
1332 1332
1333 1333 $ hg rm a
1334 1334 $ hg log -r "wdir()" -T "{rev}\n{join(files('*'), '\n')}\n"
1335 1335 2147483647
1336 1336 aa
1337 1337 b
1338 1338 $ hg revert a
1339 1339
1340 1340 Test relpath function
1341 1341
1342 1342 $ hg log -r0 -T '{files % "{file|relpath}\n"}'
1343 1343 a
1344 1344 $ cd ..
1345 1345 $ hg log -R r -r0 -T '{files % "{file|relpath}\n"}'
1346 1346 r/a
1347 1347
1348 1348 Test stringify on sub expressions
1349 1349
1350 1350 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
1351 1351 fourth, second, third
1352 1352 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
1353 1353 abc
1354 1354
1355 1355 Test splitlines
1356 1356
1357 1357 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
1358 1358 @ foo Modify, add, remove, rename
1359 1359 |
1360 1360 o foo future
1361 1361 |
1362 1362 o foo third
1363 1363 |
1364 1364 o foo second
1365 1365
1366 1366 o foo merge
1367 1367 |\
1368 1368 | o foo new head
1369 1369 | |
1370 1370 o | foo new branch
1371 1371 |/
1372 1372 o foo no user, no domain
1373 1373 |
1374 1374 o foo no person
1375 1375 |
1376 1376 o foo other 1
1377 1377 | foo other 2
1378 1378 | foo
1379 1379 | foo other 3
1380 1380 o foo line 1
1381 1381 foo line 2
1382 1382
1383 1383 $ hg log -R a -r0 -T '{desc|splitlines}\n'
1384 1384 line 1 line 2
1385 1385 $ hg log -R a -r0 -T '{join(desc|splitlines, "|")}\n'
1386 1386 line 1|line 2
1387 1387
1388 1388 Test startswith
1389 1389 $ hg log -Gv -R a --template "{startswith(desc)}"
1390 1390 hg: parse error: startswith expects two arguments
1391 1391 [255]
1392 1392
1393 1393 $ hg log -Gv -R a --template "{startswith('line', desc)}"
1394 1394 @
1395 1395 |
1396 1396 o
1397 1397 |
1398 1398 o
1399 1399 |
1400 1400 o
1401 1401
1402 1402 o
1403 1403 |\
1404 1404 | o
1405 1405 | |
1406 1406 o |
1407 1407 |/
1408 1408 o
1409 1409 |
1410 1410 o
1411 1411 |
1412 1412 o
1413 1413 |
1414 1414 o line 1
1415 1415 line 2
1416 1416
1417 1417 Test word function (including index out of bounds graceful failure)
1418 1418
1419 1419 $ hg log -Gv -R a --template "{word('1', desc)}"
1420 1420 @ add,
1421 1421 |
1422 1422 o
1423 1423 |
1424 1424 o
1425 1425 |
1426 1426 o
1427 1427
1428 1428 o
1429 1429 |\
1430 1430 | o head
1431 1431 | |
1432 1432 o | branch
1433 1433 |/
1434 1434 o user,
1435 1435 |
1436 1436 o person
1437 1437 |
1438 1438 o 1
1439 1439 |
1440 1440 o 1
1441 1441
1442 1442
1443 1443 Test word third parameter used as splitter
1444 1444
1445 1445 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
1446 1446 @ M
1447 1447 |
1448 1448 o future
1449 1449 |
1450 1450 o third
1451 1451 |
1452 1452 o sec
1453 1453
1454 1454 o merge
1455 1455 |\
1456 1456 | o new head
1457 1457 | |
1458 1458 o | new branch
1459 1459 |/
1460 1460 o n
1461 1461 |
1462 1462 o n
1463 1463 |
1464 1464 o
1465 1465 |
1466 1466 o line 1
1467 1467 line 2
1468 1468
1469 1469 Test word error messages for not enough and too many arguments
1470 1470
1471 1471 $ hg log -Gv -R a --template "{word('0')}"
1472 1472 hg: parse error: word expects two or three arguments, got 1
1473 1473 [255]
1474 1474
1475 1475 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
1476 1476 hg: parse error: word expects two or three arguments, got 7
1477 1477 [255]
1478 1478
1479 1479 Test word for integer literal
1480 1480
1481 1481 $ hg log -R a --template "{word(2, desc)}\n" -r0
1482 1482 line
1483 1483
1484 1484 Test word for invalid numbers
1485 1485
1486 1486 $ hg log -Gv -R a --template "{word('a', desc)}"
1487 1487 hg: parse error: word expects an integer index
1488 1488 [255]
1489 1489
1490 1490 Test word for out of range
1491 1491
1492 1492 $ hg log -R a --template "{word(10000, desc)}"
1493 1493 $ hg log -R a --template "{word(-10000, desc)}"
1494 1494
1495 1495 Test indent and not adding to empty lines
1496 1496
1497 1497 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
1498 1498 -----
1499 1499 > line 1
1500 1500 >> line 2
1501 1501 -----
1502 1502 > other 1
1503 1503 >> other 2
1504 1504
1505 1505 >> other 3
1506 1506
1507 Test indent with empty first line
1508
1509 $ hg version -T "{indent('', '>> ')}\n"
1510 >>
1511
1512 $ hg version -T "{indent('
1513 > second', '>> ')}\n"
1514 >>
1515 >> second
1516
1517 $ hg version -T "{indent('
1518 > second', '>> ', ' > ')}\n"
1519 >
1520 >> second
1521
1507 1522 Test with non-strings like dates
1508 1523
1509 1524 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
1510 1525 1200000.00
1511 1526 1300000.00
1512 1527
1513 1528 Test cbor filter:
1514 1529
1515 1530 $ cat <<'EOF' > "$TESTTMP/decodecbor.py"
1516 1531 > from __future__ import absolute_import
1517 1532 > from mercurial import (
1518 1533 > dispatch,
1519 1534 > pycompat,
1520 1535 > )
1521 1536 > from mercurial.utils import (
1522 1537 > cborutil,
1523 1538 > stringutil,
1524 1539 > )
1525 1540 > dispatch.initstdio()
1526 1541 > items = cborutil.decodeall(pycompat.stdin.read())
1527 1542 > pycompat.stdout.write(stringutil.pprint(items, indent=1) + b'\n')
1528 1543 > EOF
1529 1544
1530 1545 $ hg log -T "{rev|cbor}" -R a -l2 | "$PYTHON" "$TESTTMP/decodecbor.py"
1531 1546 [
1532 1547 10,
1533 1548 9
1534 1549 ]
1535 1550
1536 1551 $ hg log -T "{extras|cbor}" -R a -l1 | "$PYTHON" "$TESTTMP/decodecbor.py"
1537 1552 [
1538 1553 {
1539 1554 'branch': 'default'
1540 1555 }
1541 1556 ]
1542 1557
1543 1558 json filter should escape HTML tags so that the output can be embedded in hgweb:
1544 1559
1545 1560 $ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1
1546 1561 "\u003cfoo@example.org\u003e"
1547 1562
1548 1563 Set up repository for non-ascii encoding tests:
1549 1564
1550 1565 $ hg init nonascii
1551 1566 $ cd nonascii
1552 1567 $ "$PYTHON" <<EOF
1553 1568 > open('latin1', 'wb').write(b'\xe9')
1554 1569 > open('utf-8', 'wb').write(b'\xc3\xa9')
1555 1570 > EOF
1556 1571 $ HGENCODING=utf-8 hg branch -q `cat utf-8`
1557 1572 $ HGENCODING=utf-8 hg ci -qAm "non-ascii branch: `cat utf-8`" utf-8
1558 1573
1559 1574 json filter should try round-trip conversion to utf-8:
1560 1575
1561 1576 $ HGENCODING=ascii hg log -T "{branch|json}\n" -r0
1562 1577 "\u00e9"
1563 1578 $ HGENCODING=ascii hg log -T "{desc|json}\n" -r0
1564 1579 "non-ascii branch: \u00e9"
1565 1580
1566 1581 json filter should take input as utf-8 if it was converted from utf-8:
1567 1582
1568 1583 $ HGENCODING=latin-1 hg log -T "{branch|json}\n" -r0
1569 1584 "\u00e9"
1570 1585 $ HGENCODING=latin-1 hg log -T "{desc|json}\n" -r0
1571 1586 "non-ascii branch: \u00e9"
1572 1587
1573 1588 json filter takes input as utf-8b:
1574 1589
1575 1590 $ HGENCODING=ascii hg log -T "{'`cat utf-8`'|json}\n" -l1
1576 1591 "\u00e9"
1577 1592 $ HGENCODING=ascii hg log -T "{'`cat latin1`'|json}\n" -l1
1578 1593 "\udce9"
1579 1594
1580 1595 cbor filter is bytes transparent, which should handle bytes subtypes
1581 1596 as bytes:
1582 1597
1583 1598 $ HGENCODING=ascii hg log -T "{branch|cbor}" -r0 \
1584 1599 > | "$PYTHON" "$TESTTMP/decodecbor.py"
1585 1600 [
1586 1601 '?'
1587 1602 ]
1588 1603 $ HGENCODING=latin-1 hg log -T "{branch|cbor}" -r0 \
1589 1604 > | "$PYTHON" "$TESTTMP/decodecbor.py"
1590 1605 [
1591 1606 '\xe9'
1592 1607 ]
1593 1608
1594 1609 utf8 filter:
1595 1610
1596 1611 $ HGENCODING=ascii hg log -T "round-trip: {branch|utf8|hex}\n" -r0
1597 1612 round-trip: c3a9
1598 1613 $ HGENCODING=latin1 hg log -T "decoded: {'`cat latin1`'|utf8|hex}\n" -l1
1599 1614 decoded: c3a9
1600 1615 $ HGENCODING=ascii hg log -T "replaced: {'`cat latin1`'|utf8|hex}\n" -l1
1601 1616 abort: decoding near * (glob)
1602 1617 [255]
1603 1618 $ hg log -T "coerced to string: {rev|utf8}\n" -r0
1604 1619 coerced to string: 0
1605 1620
1606 1621 pad width:
1607 1622
1608 1623 $ HGENCODING=utf-8 hg debugtemplate "{pad('`cat utf-8`', 2, '-')}\n"
1609 1624 \xc3\xa9- (esc)
1610 1625
1611 1626 read config options:
1612 1627
1613 1628 $ hg log -T "{config('templateconfig', 'knob', 'foo')}\n"
1614 1629 foo
1615 1630 $ hg log -T "{config('templateconfig', 'knob', 'foo')}\n" \
1616 1631 > --config templateconfig.knob=bar
1617 1632 bar
1618 1633 $ hg log -T "{configbool('templateconfig', 'knob', True)}\n"
1619 1634 True
1620 1635 $ hg log -T "{configbool('templateconfig', 'knob', True)}\n" \
1621 1636 > --config templateconfig.knob=0
1622 1637 False
1623 1638 $ hg log -T "{configint('templateconfig', 'knob', 123)}\n"
1624 1639 123
1625 1640 $ hg log -T "{configint('templateconfig', 'knob', 123)}\n" \
1626 1641 > --config templateconfig.knob=456
1627 1642 456
1628 1643 $ hg log -T "{config('templateconfig', 'knob')}\n"
1629 1644 devel-warn: config item requires an explicit default value: 'templateconfig.knob' at: * (glob)
1630 1645
1631 1646 $ hg log -T "{configbool('ui', 'interactive')}\n"
1632 1647 False
1633 1648 $ hg log -T "{configbool('ui', 'interactive')}\n" --config ui.interactive=1
1634 1649 True
1635 1650 $ hg log -T "{config('templateconfig', 'knob', if(true, 'foo', 'bar'))}\n"
1636 1651 foo
1637 1652
1638 1653 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now