##// END OF EJS Templates
py3: add b'' prefixes in tests/test-extension.t...
Pulkit Goyal -
r38038:a9ffb4a5 default
parent child Browse files
Show More
@@ -1,1729 +1,1729 b''
1 1 Test basic extension support
2 2
3 3 $ cat > foobar.py <<EOF
4 4 > import os
5 5 > from mercurial import commands, registrar
6 6 > cmdtable = {}
7 7 > command = registrar.command(cmdtable)
8 8 > configtable = {}
9 9 > configitem = registrar.configitem(configtable)
10 10 > configitem(b'tests', b'foo', default=b"Foo")
11 11 > def uisetup(ui):
12 12 > ui.write(b"uisetup called\\n")
13 13 > ui.flush()
14 14 > def reposetup(ui, repo):
15 15 > ui.write(b"reposetup called for %s\\n" % os.path.basename(repo.root))
16 16 > ui.write(b"ui %s= repo.ui\\n" % (ui == repo.ui and b"=" or b"!"))
17 17 > ui.flush()
18 18 > @command(b'foo', [], b'hg foo')
19 19 > def foo(ui, *args, **kwargs):
20 20 > foo = ui.config(b'tests', b'foo')
21 21 > ui.write(foo)
22 22 > ui.write(b"\\n")
23 23 > @command(b'bar', [], b'hg bar', norepo=True)
24 24 > def bar(ui, *args, **kwargs):
25 25 > ui.write(b"Bar\\n")
26 26 > EOF
27 27 $ abspath=`pwd`/foobar.py
28 28
29 29 $ mkdir barfoo
30 30 $ cp foobar.py barfoo/__init__.py
31 31 $ barfoopath=`pwd`/barfoo
32 32
33 33 $ hg init a
34 34 $ cd a
35 35 $ echo foo > file
36 36 $ hg add file
37 37 $ hg commit -m 'add file'
38 38
39 39 $ echo '[extensions]' >> $HGRCPATH
40 40 $ echo "foobar = $abspath" >> $HGRCPATH
41 41 $ hg foo
42 42 uisetup called
43 43 reposetup called for a
44 44 ui == repo.ui
45 45 reposetup called for a (chg !)
46 46 ui == repo.ui (chg !)
47 47 Foo
48 48
49 49 $ cd ..
50 50 $ hg clone a b
51 51 uisetup called (no-chg !)
52 52 reposetup called for a
53 53 ui == repo.ui
54 54 reposetup called for b
55 55 ui == repo.ui
56 56 updating to branch default
57 57 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 58
59 59 $ hg bar
60 60 uisetup called (no-chg !)
61 61 Bar
62 62 $ echo 'foobar = !' >> $HGRCPATH
63 63
64 64 module/__init__.py-style
65 65
66 66 $ echo "barfoo = $barfoopath" >> $HGRCPATH
67 67 $ cd a
68 68 $ hg foo
69 69 uisetup called
70 70 reposetup called for a
71 71 ui == repo.ui
72 72 reposetup called for a (chg !)
73 73 ui == repo.ui (chg !)
74 74 Foo
75 75 $ echo 'barfoo = !' >> $HGRCPATH
76 76
77 77 Check that extensions are loaded in phases:
78 78
79 79 $ cat > foo.py <<EOF
80 80 > import os
81 81 > name = os.path.basename(__file__).rsplit('.', 1)[0]
82 82 > print("1) %s imported" % name)
83 83 > def uisetup(ui):
84 84 > print("2) %s uisetup" % name)
85 85 > def extsetup():
86 86 > print("3) %s extsetup" % name)
87 87 > def reposetup(ui, repo):
88 88 > print("4) %s reposetup" % name)
89 89 >
90 90 > # custom predicate to check registration of functions at loading
91 91 > from mercurial import (
92 92 > registrar,
93 93 > smartset,
94 94 > )
95 95 > revsetpredicate = registrar.revsetpredicate()
96 96 > @revsetpredicate(name, safe=True) # safe=True for query via hgweb
97 97 > def custompredicate(repo, subset, x):
98 98 > return smartset.baseset([r for r in subset if r in {0}])
99 99 > EOF
100 100
101 101 $ cp foo.py bar.py
102 102 $ echo 'foo = foo.py' >> $HGRCPATH
103 103 $ echo 'bar = bar.py' >> $HGRCPATH
104 104
105 105 Check normal command's load order of extensions and registration of functions
106 106
107 107 $ hg log -r "foo() and bar()" -q
108 108 1) foo imported
109 109 1) bar imported
110 110 2) foo uisetup
111 111 2) bar uisetup
112 112 3) foo extsetup
113 113 3) bar extsetup
114 114 4) foo reposetup
115 115 4) bar reposetup
116 116 0:c24b9ac61126
117 117
118 118 Check hgweb's load order of extensions and registration of functions
119 119
120 120 $ cat > hgweb.cgi <<EOF
121 121 > #!$PYTHON
122 122 > from mercurial import demandimport; demandimport.enable()
123 123 > from mercurial.hgweb import hgweb
124 124 > from mercurial.hgweb import wsgicgi
125 125 > application = hgweb('.', 'test repo')
126 126 > wsgicgi.launch(application)
127 127 > EOF
128 128 $ . "$TESTDIR/cgienv"
129 129
130 130 $ PATH_INFO='/' SCRIPT_NAME='' $PYTHON hgweb.cgi \
131 131 > | grep '^[0-9]) ' # ignores HTML output
132 132 1) foo imported
133 133 1) bar imported
134 134 2) foo uisetup
135 135 2) bar uisetup
136 136 3) foo extsetup
137 137 3) bar extsetup
138 138 4) foo reposetup
139 139 4) bar reposetup
140 140
141 141 (check that revset predicate foo() and bar() are available)
142 142
143 143 #if msys
144 144 $ PATH_INFO='//shortlog'
145 145 #else
146 146 $ PATH_INFO='/shortlog'
147 147 #endif
148 148 $ export PATH_INFO
149 149 $ SCRIPT_NAME='' QUERY_STRING='rev=foo() and bar()' $PYTHON hgweb.cgi \
150 150 > | grep '<a href="/rev/[0-9a-z]*">'
151 151 <a href="/rev/c24b9ac61126">add file</a>
152 152
153 153 $ echo 'foo = !' >> $HGRCPATH
154 154 $ echo 'bar = !' >> $HGRCPATH
155 155
156 156 Check "from __future__ import absolute_import" support for external libraries
157 157
158 158 #if windows
159 159 $ PATHSEP=";"
160 160 #else
161 161 $ PATHSEP=":"
162 162 #endif
163 163 $ export PATHSEP
164 164
165 165 $ mkdir $TESTTMP/libroot
166 166 $ echo "s = 'libroot/ambig.py'" > $TESTTMP/libroot/ambig.py
167 167 $ mkdir $TESTTMP/libroot/mod
168 168 $ touch $TESTTMP/libroot/mod/__init__.py
169 169 $ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py
170 170
171 171 $ cat > $TESTTMP/libroot/mod/ambigabs.py <<EOF
172 172 > from __future__ import absolute_import
173 173 > import ambig # should load "libroot/ambig.py"
174 174 > s = ambig.s
175 175 > EOF
176 176 $ cat > loadabs.py <<EOF
177 177 > import mod.ambigabs as ambigabs
178 178 > def extsetup():
179 179 > print('ambigabs.s=%s' % ambigabs.s)
180 180 > EOF
181 181 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadabs=loadabs.py root)
182 182 ambigabs.s=libroot/ambig.py
183 183 $TESTTMP/a
184 184
185 185 #if no-py3k
186 186 $ cat > $TESTTMP/libroot/mod/ambigrel.py <<EOF
187 187 > import ambig # should load "libroot/mod/ambig.py"
188 188 > s = ambig.s
189 189 > EOF
190 190 $ cat > loadrel.py <<EOF
191 191 > import mod.ambigrel as ambigrel
192 192 > def extsetup():
193 193 > print('ambigrel.s=%s' % ambigrel.s)
194 194 > EOF
195 195 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadrel=loadrel.py root)
196 196 ambigrel.s=libroot/mod/ambig.py
197 197 $TESTTMP/a
198 198 #endif
199 199
200 200 Check absolute/relative import of extension specific modules
201 201
202 202 $ mkdir $TESTTMP/extroot
203 203 $ cat > $TESTTMP/extroot/bar.py <<EOF
204 204 > s = 'this is extroot.bar'
205 205 > EOF
206 206 $ mkdir $TESTTMP/extroot/sub1
207 207 $ cat > $TESTTMP/extroot/sub1/__init__.py <<EOF
208 208 > s = 'this is extroot.sub1.__init__'
209 209 > EOF
210 210 $ cat > $TESTTMP/extroot/sub1/baz.py <<EOF
211 211 > s = 'this is extroot.sub1.baz'
212 212 > EOF
213 213 $ cat > $TESTTMP/extroot/__init__.py <<EOF
214 214 > s = 'this is extroot.__init__'
215 215 > import foo
216 216 > def extsetup(ui):
217 217 > ui.write('(extroot) ', foo.func(), '\n')
218 218 > ui.flush()
219 219 > EOF
220 220
221 221 $ cat > $TESTTMP/extroot/foo.py <<EOF
222 222 > # test absolute import
223 223 > buf = []
224 224 > def func():
225 225 > # "not locals" case
226 226 > import extroot.bar
227 227 > buf.append('import extroot.bar in func(): %s' % extroot.bar.s)
228 228 > return '\n(extroot) '.join(buf)
229 229 > # "fromlist == ('*',)" case
230 230 > from extroot.bar import *
231 231 > buf.append('from extroot.bar import *: %s' % s)
232 232 > # "not fromlist" and "if '.' in name" case
233 233 > import extroot.sub1.baz
234 234 > buf.append('import extroot.sub1.baz: %s' % extroot.sub1.baz.s)
235 235 > # "not fromlist" and NOT "if '.' in name" case
236 236 > import extroot
237 237 > buf.append('import extroot: %s' % extroot.s)
238 238 > # NOT "not fromlist" and NOT "level != -1" case
239 239 > from extroot.bar import s
240 240 > buf.append('from extroot.bar import s: %s' % s)
241 241 > EOF
242 242 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.extroot=$TESTTMP/extroot root)
243 243 (extroot) from extroot.bar import *: this is extroot.bar
244 244 (extroot) import extroot.sub1.baz: this is extroot.sub1.baz
245 245 (extroot) import extroot: this is extroot.__init__
246 246 (extroot) from extroot.bar import s: this is extroot.bar
247 247 (extroot) import extroot.bar in func(): this is extroot.bar
248 248 $TESTTMP/a
249 249
250 250 #if no-py3k
251 251 $ rm "$TESTTMP"/extroot/foo.*
252 252 $ rm -Rf "$TESTTMP/extroot/__pycache__"
253 253 $ cat > $TESTTMP/extroot/foo.py <<EOF
254 254 > # test relative import
255 255 > buf = []
256 256 > def func():
257 257 > # "not locals" case
258 258 > import bar
259 259 > buf.append('import bar in func(): %s' % bar.s)
260 260 > return '\n(extroot) '.join(buf)
261 261 > # "fromlist == ('*',)" case
262 262 > from bar import *
263 263 > buf.append('from bar import *: %s' % s)
264 264 > # "not fromlist" and "if '.' in name" case
265 265 > import sub1.baz
266 266 > buf.append('import sub1.baz: %s' % sub1.baz.s)
267 267 > # "not fromlist" and NOT "if '.' in name" case
268 268 > import sub1
269 269 > buf.append('import sub1: %s' % sub1.s)
270 270 > # NOT "not fromlist" and NOT "level != -1" case
271 271 > from bar import s
272 272 > buf.append('from bar import s: %s' % s)
273 273 > EOF
274 274 $ hg --config extensions.extroot=$TESTTMP/extroot root
275 275 (extroot) from bar import *: this is extroot.bar
276 276 (extroot) import sub1.baz: this is extroot.sub1.baz
277 277 (extroot) import sub1: this is extroot.sub1.__init__
278 278 (extroot) from bar import s: this is extroot.bar
279 279 (extroot) import bar in func(): this is extroot.bar
280 280 $TESTTMP/a
281 281 #endif
282 282
283 283 #if demandimport
284 284
285 285 Examine whether module loading is delayed until actual referring, even
286 286 though module is imported with "absolute_import" feature.
287 287
288 288 Files below in each packages are used for described purpose:
289 289
290 290 - "called": examine whether "from MODULE import ATTR" works correctly
291 291 - "unused": examine whether loading is delayed correctly
292 292 - "used": examine whether "from PACKAGE import MODULE" works correctly
293 293
294 294 Package hierarchy is needed to examine whether demand importing works
295 295 as expected for "from SUB.PACK.AGE import MODULE".
296 296
297 297 Setup "external library" to be imported with "absolute_import"
298 298 feature.
299 299
300 300 $ mkdir -p $TESTTMP/extlibroot/lsub1/lsub2
301 301 $ touch $TESTTMP/extlibroot/__init__.py
302 302 $ touch $TESTTMP/extlibroot/lsub1/__init__.py
303 303 $ touch $TESTTMP/extlibroot/lsub1/lsub2/__init__.py
304 304
305 305 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/called.py <<EOF
306 306 > def func():
307 307 > return "this is extlibroot.lsub1.lsub2.called.func()"
308 308 > EOF
309 309 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/unused.py <<EOF
310 310 > raise Exception("extlibroot.lsub1.lsub2.unused is loaded unintentionally")
311 311 > EOF
312 312 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/used.py <<EOF
313 313 > detail = "this is extlibroot.lsub1.lsub2.used"
314 314 > EOF
315 315
316 316 Setup sub-package of "external library", which causes instantiation of
317 317 demandmod in "recurse down the module chain" code path. Relative
318 318 importing with "absolute_import" feature isn't tested, because "level
319 319 >=1 " doesn't cause instantiation of demandmod.
320 320
321 321 $ mkdir -p $TESTTMP/extlibroot/recursedown/abs
322 322 $ cat > $TESTTMP/extlibroot/recursedown/abs/used.py <<EOF
323 323 > detail = "this is extlibroot.recursedown.abs.used"
324 324 > EOF
325 325 $ cat > $TESTTMP/extlibroot/recursedown/abs/__init__.py <<EOF
326 326 > from __future__ import absolute_import
327 327 > from extlibroot.recursedown.abs.used import detail
328 328 > EOF
329 329
330 330 $ mkdir -p $TESTTMP/extlibroot/recursedown/legacy
331 331 $ cat > $TESTTMP/extlibroot/recursedown/legacy/used.py <<EOF
332 332 > detail = "this is extlibroot.recursedown.legacy.used"
333 333 > EOF
334 334 $ cat > $TESTTMP/extlibroot/recursedown/legacy/__init__.py <<EOF
335 335 > # legacy style (level == -1) import
336 336 > from extlibroot.recursedown.legacy.used import detail
337 337 > EOF
338 338
339 339 $ cat > $TESTTMP/extlibroot/recursedown/__init__.py <<EOF
340 340 > from __future__ import absolute_import
341 341 > from extlibroot.recursedown.abs import detail as absdetail
342 342 > from .legacy import detail as legacydetail
343 343 > EOF
344 344
345 345 Setup package that re-exports an attribute of its submodule as the same
346 346 name. This leaves 'shadowing.used' pointing to 'used.detail', but still
347 347 the submodule 'used' should be somehow accessible. (issue5617)
348 348
349 349 $ mkdir -p $TESTTMP/extlibroot/shadowing
350 350 $ cat > $TESTTMP/extlibroot/shadowing/used.py <<EOF
351 351 > detail = "this is extlibroot.shadowing.used"
352 352 > EOF
353 353 $ cat > $TESTTMP/extlibroot/shadowing/proxied.py <<EOF
354 354 > from __future__ import absolute_import
355 355 > from extlibroot.shadowing.used import detail
356 356 > EOF
357 357 $ cat > $TESTTMP/extlibroot/shadowing/__init__.py <<EOF
358 358 > from __future__ import absolute_import
359 359 > from .used import detail as used
360 360 > EOF
361 361
362 362 Setup extension local modules to be imported with "absolute_import"
363 363 feature.
364 364
365 365 $ mkdir -p $TESTTMP/absextroot/xsub1/xsub2
366 366 $ touch $TESTTMP/absextroot/xsub1/__init__.py
367 367 $ touch $TESTTMP/absextroot/xsub1/xsub2/__init__.py
368 368
369 369 $ cat > $TESTTMP/absextroot/xsub1/xsub2/called.py <<EOF
370 370 > def func():
371 371 > return "this is absextroot.xsub1.xsub2.called.func()"
372 372 > EOF
373 373 $ cat > $TESTTMP/absextroot/xsub1/xsub2/unused.py <<EOF
374 374 > raise Exception("absextroot.xsub1.xsub2.unused is loaded unintentionally")
375 375 > EOF
376 376 $ cat > $TESTTMP/absextroot/xsub1/xsub2/used.py <<EOF
377 377 > detail = "this is absextroot.xsub1.xsub2.used"
378 378 > EOF
379 379
380 380 Setup extension local modules to examine whether demand importing
381 381 works as expected in "level > 1" case.
382 382
383 383 $ cat > $TESTTMP/absextroot/relimportee.py <<EOF
384 384 > detail = "this is absextroot.relimportee"
385 385 > EOF
386 386 $ cat > $TESTTMP/absextroot/xsub1/xsub2/relimporter.py <<EOF
387 387 > from __future__ import absolute_import
388 388 > from ... import relimportee
389 389 > detail = "this relimporter imports %r" % (relimportee.detail)
390 390 > EOF
391 391
392 392 Setup modules, which actually import extension local modules at
393 393 runtime.
394 394
395 395 $ cat > $TESTTMP/absextroot/absolute.py << EOF
396 396 > from __future__ import absolute_import
397 397 >
398 398 > # import extension local modules absolutely (level = 0)
399 399 > from absextroot.xsub1.xsub2 import used, unused
400 400 > from absextroot.xsub1.xsub2.called import func
401 401 >
402 402 > def getresult():
403 403 > result = []
404 404 > result.append(used.detail)
405 405 > result.append(func())
406 406 > return result
407 407 > EOF
408 408
409 409 $ cat > $TESTTMP/absextroot/relative.py << EOF
410 410 > from __future__ import absolute_import
411 411 >
412 412 > # import extension local modules relatively (level == 1)
413 413 > from .xsub1.xsub2 import used, unused
414 414 > from .xsub1.xsub2.called import func
415 415 >
416 416 > # import a module, which implies "importing with level > 1"
417 417 > from .xsub1.xsub2 import relimporter
418 418 >
419 419 > def getresult():
420 420 > result = []
421 421 > result.append(used.detail)
422 422 > result.append(func())
423 423 > result.append(relimporter.detail)
424 424 > return result
425 425 > EOF
426 426
427 427 Setup main procedure of extension.
428 428
429 429 $ cat > $TESTTMP/absextroot/__init__.py <<EOF
430 430 > from __future__ import absolute_import
431 431 > from mercurial import registrar
432 432 > cmdtable = {}
433 433 > command = registrar.command(cmdtable)
434 434 >
435 435 > # "absolute" and "relative" shouldn't be imported before actual
436 436 > # command execution, because (1) they import same modules, and (2)
437 437 > # preceding import (= instantiate "demandmod" object instead of
438 438 > # real "module" object) might hide problem of succeeding import.
439 439 >
440 440 > @command(b'showabsolute', [], norepo=True)
441 441 > def showabsolute(ui, *args, **opts):
442 442 > from absextroot import absolute
443 443 > ui.write(b'ABS: %s\n' % '\nABS: '.join(absolute.getresult()))
444 444 >
445 445 > @command(b'showrelative', [], norepo=True)
446 446 > def showrelative(ui, *args, **opts):
447 447 > from . import relative
448 448 > ui.write(b'REL: %s\n' % '\nREL: '.join(relative.getresult()))
449 449 >
450 450 > # import modules from external library
451 451 > from extlibroot.lsub1.lsub2 import used as lused, unused as lunused
452 452 > from extlibroot.lsub1.lsub2.called import func as lfunc
453 453 > from extlibroot.recursedown import absdetail, legacydetail
454 454 > from extlibroot.shadowing import proxied
455 455 >
456 456 > def uisetup(ui):
457 457 > result = []
458 458 > result.append(lused.detail)
459 459 > result.append(lfunc())
460 460 > result.append(absdetail)
461 461 > result.append(legacydetail)
462 462 > result.append(proxied.detail)
463 > ui.write('LIB: %s\n' % '\nLIB: '.join(result))
463 > ui.write(b'LIB: %s\n' % '\nLIB: '.join(result))
464 464 > EOF
465 465
466 466 Examine module importing.
467 467
468 468 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.absextroot=$TESTTMP/absextroot showabsolute)
469 469 LIB: this is extlibroot.lsub1.lsub2.used
470 470 LIB: this is extlibroot.lsub1.lsub2.called.func()
471 471 LIB: this is extlibroot.recursedown.abs.used
472 472 LIB: this is extlibroot.recursedown.legacy.used
473 473 LIB: this is extlibroot.shadowing.used
474 474 ABS: this is absextroot.xsub1.xsub2.used
475 475 ABS: this is absextroot.xsub1.xsub2.called.func()
476 476
477 477 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.absextroot=$TESTTMP/absextroot showrelative)
478 478 LIB: this is extlibroot.lsub1.lsub2.used
479 479 LIB: this is extlibroot.lsub1.lsub2.called.func()
480 480 LIB: this is extlibroot.recursedown.abs.used
481 481 LIB: this is extlibroot.recursedown.legacy.used
482 482 LIB: this is extlibroot.shadowing.used
483 483 REL: this is absextroot.xsub1.xsub2.used
484 484 REL: this is absextroot.xsub1.xsub2.called.func()
485 485 REL: this relimporter imports 'this is absextroot.relimportee'
486 486
487 487 Examine whether sub-module is imported relatively as expected.
488 488
489 489 See also issue5208 for detail about example case on Python 3.x.
490 490
491 491 $ f -q $TESTTMP/extlibroot/lsub1/lsub2/notexist.py
492 492 $TESTTMP/extlibroot/lsub1/lsub2/notexist.py: file not found
493 493
494 494 $ cat > $TESTTMP/notexist.py <<EOF
495 495 > text = 'notexist.py at root is loaded unintentionally\n'
496 496 > EOF
497 497
498 498 $ cat > $TESTTMP/checkrelativity.py <<EOF
499 499 > from mercurial import registrar
500 500 > cmdtable = {}
501 501 > command = registrar.command(cmdtable)
502 502 >
503 503 > # demand import avoids failure of importing notexist here
504 504 > import extlibroot.lsub1.lsub2.notexist
505 505 >
506 506 > @command(b'checkrelativity', [], norepo=True)
507 507 > def checkrelativity(ui, *args, **opts):
508 508 > try:
509 509 > ui.write(extlibroot.lsub1.lsub2.notexist.text)
510 510 > return 1 # unintentional success
511 511 > except ImportError:
512 512 > pass # intentional failure
513 513 > EOF
514 514
515 515 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.checkrelativity=$TESTTMP/checkrelativity.py checkrelativity)
516 516
517 517 #endif
518 518
519 519 Make sure a broken uisetup doesn't globally break hg:
520 520 $ cat > $TESTTMP/baduisetup.py <<EOF
521 521 > def uisetup(ui):
522 522 > 1/0
523 523 > EOF
524 524
525 525 Even though the extension fails during uisetup, hg is still basically usable:
526 526 $ hg --config extensions.baduisetup=$TESTTMP/baduisetup.py version
527 527 Traceback (most recent call last):
528 528 File "*/mercurial/extensions.py", line *, in _runuisetup (glob)
529 529 uisetup(ui)
530 530 File "$TESTTMP/baduisetup.py", line 2, in uisetup
531 531 1/0
532 532 ZeroDivisionError: integer division or modulo by zero
533 533 *** failed to set up extension baduisetup: integer division or modulo by zero
534 534 Mercurial Distributed SCM (version *) (glob)
535 535 (see https://mercurial-scm.org for more information)
536 536
537 537 Copyright (C) 2005-* Matt Mackall and others (glob)
538 538 This is free software; see the source for copying conditions. There is NO
539 539 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
540 540
541 541 $ cd ..
542 542
543 543 hide outer repo
544 544 $ hg init
545 545
546 546 $ cat > empty.py <<EOF
547 547 > '''empty cmdtable
548 548 > '''
549 549 > cmdtable = {}
550 550 > EOF
551 551 $ emptypath=`pwd`/empty.py
552 552 $ echo "empty = $emptypath" >> $HGRCPATH
553 553 $ hg help empty
554 554 empty extension - empty cmdtable
555 555
556 556 no commands defined
557 557
558 558
559 559 $ echo 'empty = !' >> $HGRCPATH
560 560
561 561 $ cat > debugextension.py <<EOF
562 562 > '''only debugcommands
563 563 > '''
564 564 > from mercurial import registrar
565 565 > cmdtable = {}
566 566 > command = registrar.command(cmdtable)
567 567 > @command(b'debugfoobar', [], b'hg debugfoobar')
568 568 > def debugfoobar(ui, repo, *args, **opts):
569 569 > "yet another debug command"
570 570 > pass
571 571 > @command(b'foo', [], b'hg foo')
572 572 > def foo(ui, repo, *args, **opts):
573 573 > """yet another foo command
574 574 > This command has been DEPRECATED since forever.
575 575 > """
576 576 > pass
577 577 > EOF
578 578 $ debugpath=`pwd`/debugextension.py
579 579 $ echo "debugextension = $debugpath" >> $HGRCPATH
580 580
581 581 $ hg help debugextension
582 582 hg debugextensions
583 583
584 584 show information about active extensions
585 585
586 586 options:
587 587
588 588 (some details hidden, use --verbose to show complete help)
589 589
590 590
591 591 $ hg --verbose help debugextension
592 592 hg debugextensions
593 593
594 594 show information about active extensions
595 595
596 596 options:
597 597
598 598 -T --template TEMPLATE display with template (EXPERIMENTAL)
599 599
600 600 global options ([+] can be repeated):
601 601
602 602 -R --repository REPO repository root directory or name of overlay bundle
603 603 file
604 604 --cwd DIR change working directory
605 605 -y --noninteractive do not prompt, automatically pick the first choice for
606 606 all prompts
607 607 -q --quiet suppress output
608 608 -v --verbose enable additional output
609 609 --color TYPE when to colorize (boolean, always, auto, never, or
610 610 debug)
611 611 --config CONFIG [+] set/override config option (use 'section.name=value')
612 612 --debug enable debugging output
613 613 --debugger start debugger
614 614 --encoding ENCODE set the charset encoding (default: ascii)
615 615 --encodingmode MODE set the charset encoding mode (default: strict)
616 616 --traceback always print a traceback on exception
617 617 --time time how long the command takes
618 618 --profile print command execution profile
619 619 --version output version information and exit
620 620 -h --help display help and exit
621 621 --hidden consider hidden changesets
622 622 --pager TYPE when to paginate (boolean, always, auto, or never)
623 623 (default: auto)
624 624
625 625
626 626
627 627
628 628
629 629
630 630 $ hg --debug help debugextension
631 631 hg debugextensions
632 632
633 633 show information about active extensions
634 634
635 635 options:
636 636
637 637 -T --template TEMPLATE display with template (EXPERIMENTAL)
638 638
639 639 global options ([+] can be repeated):
640 640
641 641 -R --repository REPO repository root directory or name of overlay bundle
642 642 file
643 643 --cwd DIR change working directory
644 644 -y --noninteractive do not prompt, automatically pick the first choice for
645 645 all prompts
646 646 -q --quiet suppress output
647 647 -v --verbose enable additional output
648 648 --color TYPE when to colorize (boolean, always, auto, never, or
649 649 debug)
650 650 --config CONFIG [+] set/override config option (use 'section.name=value')
651 651 --debug enable debugging output
652 652 --debugger start debugger
653 653 --encoding ENCODE set the charset encoding (default: ascii)
654 654 --encodingmode MODE set the charset encoding mode (default: strict)
655 655 --traceback always print a traceback on exception
656 656 --time time how long the command takes
657 657 --profile print command execution profile
658 658 --version output version information and exit
659 659 -h --help display help and exit
660 660 --hidden consider hidden changesets
661 661 --pager TYPE when to paginate (boolean, always, auto, or never)
662 662 (default: auto)
663 663
664 664
665 665
666 666
667 667
668 668 $ echo 'debugextension = !' >> $HGRCPATH
669 669
670 670 Asking for help about a deprecated extension should do something useful:
671 671
672 672 $ hg help glog
673 673 'glog' is provided by the following extension:
674 674
675 675 graphlog command to view revision graphs from a shell (DEPRECATED)
676 676
677 677 (use 'hg help extensions' for information on enabling extensions)
678 678
679 679 Extension module help vs command help:
680 680
681 681 $ echo 'extdiff =' >> $HGRCPATH
682 682 $ hg help extdiff
683 683 hg extdiff [OPT]... [FILE]...
684 684
685 685 use external program to diff repository (or selected files)
686 686
687 687 Show differences between revisions for the specified files, using an
688 688 external program. The default program used is diff, with default options
689 689 "-Npru".
690 690
691 691 To select a different program, use the -p/--program option. The program
692 692 will be passed the names of two directories to compare. To pass additional
693 693 options to the program, use -o/--option. These will be passed before the
694 694 names of the directories to compare.
695 695
696 696 When two revision arguments are given, then changes are shown between
697 697 those revisions. If only one revision is specified then that revision is
698 698 compared to the working directory, and, when no revisions are specified,
699 699 the working directory files are compared to its parent.
700 700
701 701 (use 'hg help -e extdiff' to show help for the extdiff extension)
702 702
703 703 options ([+] can be repeated):
704 704
705 705 -p --program CMD comparison program to run
706 706 -o --option OPT [+] pass option to comparison program
707 707 -r --rev REV [+] revision
708 708 -c --change REV change made by revision
709 709 --patch compare patches for two revisions
710 710 -I --include PATTERN [+] include names matching the given patterns
711 711 -X --exclude PATTERN [+] exclude names matching the given patterns
712 712 -S --subrepos recurse into subrepositories
713 713
714 714 (some details hidden, use --verbose to show complete help)
715 715
716 716
717 717
718 718
719 719
720 720
721 721
722 722
723 723
724 724
725 725 $ hg help --extension extdiff
726 726 extdiff extension - command to allow external programs to compare revisions
727 727
728 728 The extdiff Mercurial extension allows you to use external programs to compare
729 729 revisions, or revision with working directory. The external diff programs are
730 730 called with a configurable set of options and two non-option arguments: paths
731 731 to directories containing snapshots of files to compare.
732 732
733 733 If there is more than one file being compared and the "child" revision is the
734 734 working directory, any modifications made in the external diff program will be
735 735 copied back to the working directory from the temporary directory.
736 736
737 737 The extdiff extension also allows you to configure new diff commands, so you
738 738 do not need to type 'hg extdiff -p kdiff3' always.
739 739
740 740 [extdiff]
741 741 # add new command that runs GNU diff(1) in 'context diff' mode
742 742 cdiff = gdiff -Nprc5
743 743 ## or the old way:
744 744 #cmd.cdiff = gdiff
745 745 #opts.cdiff = -Nprc5
746 746
747 747 # add new command called meld, runs meld (no need to name twice). If
748 748 # the meld executable is not available, the meld tool in [merge-tools]
749 749 # will be used, if available
750 750 meld =
751 751
752 752 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
753 753 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
754 754 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
755 755 # your .vimrc
756 756 vimdiff = gvim -f "+next" \
757 757 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
758 758
759 759 Tool arguments can include variables that are expanded at runtime:
760 760
761 761 $parent1, $plabel1 - filename, descriptive label of first parent
762 762 $child, $clabel - filename, descriptive label of child revision
763 763 $parent2, $plabel2 - filename, descriptive label of second parent
764 764 $root - repository root
765 765 $parent is an alias for $parent1.
766 766
767 767 The extdiff extension will look in your [diff-tools] and [merge-tools]
768 768 sections for diff tool arguments, when none are specified in [extdiff].
769 769
770 770 [extdiff]
771 771 kdiff3 =
772 772
773 773 [diff-tools]
774 774 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
775 775
776 776 You can use -I/-X and list of file or directory names like normal 'hg diff'
777 777 command. The extdiff extension makes snapshots of only needed files, so
778 778 running the external diff program will actually be pretty fast (at least
779 779 faster than having to compare the entire tree).
780 780
781 781 list of commands:
782 782
783 783 extdiff use external program to diff repository (or selected files)
784 784
785 785 (use 'hg help -v -e extdiff' to show built-in aliases and global options)
786 786
787 787
788 788
789 789
790 790
791 791
792 792
793 793
794 794
795 795
796 796
797 797
798 798
799 799
800 800
801 801
802 802 $ echo 'extdiff = !' >> $HGRCPATH
803 803
804 804 Test help topic with same name as extension
805 805
806 806 $ cat > multirevs.py <<EOF
807 807 > from mercurial import commands, registrar
808 808 > cmdtable = {}
809 809 > command = registrar.command(cmdtable)
810 810 > """multirevs extension
811 811 > Big multi-line module docstring."""
812 812 > @command(b'multirevs', [], b'ARG', norepo=True)
813 813 > def multirevs(ui, repo, arg, *args, **opts):
814 814 > """multirevs command"""
815 815 > pass
816 816 > EOF
817 817 $ echo "multirevs = multirevs.py" >> $HGRCPATH
818 818
819 819 $ hg help multirevs | tail
820 820 used):
821 821
822 822 hg update :@
823 823
824 824 - Show diff between tags 1.3 and 1.5 (this works because the first and the
825 825 last revisions of the revset are used):
826 826
827 827 hg diff -r 1.3::1.5
828 828
829 829 use 'hg help -c multirevs' to see help for the multirevs command
830 830
831 831
832 832
833 833
834 834
835 835
836 836 $ hg help -c multirevs
837 837 hg multirevs ARG
838 838
839 839 multirevs command
840 840
841 841 (some details hidden, use --verbose to show complete help)
842 842
843 843
844 844
845 845 $ hg multirevs
846 846 hg multirevs: invalid arguments
847 847 hg multirevs ARG
848 848
849 849 multirevs command
850 850
851 851 (use 'hg multirevs -h' to show more help)
852 852 [255]
853 853
854 854
855 855
856 856 $ echo "multirevs = !" >> $HGRCPATH
857 857
858 858 Issue811: Problem loading extensions twice (by site and by user)
859 859
860 860 $ cat <<EOF >> $HGRCPATH
861 861 > mq =
862 862 > strip =
863 863 > hgext.mq =
864 864 > hgext/mq =
865 865 > EOF
866 866
867 867 Show extensions:
868 868 (note that mq force load strip, also checking it's not loaded twice)
869 869
870 870 #if no-extraextensions
871 871 $ hg debugextensions
872 872 mq
873 873 strip
874 874 #endif
875 875
876 876 For extensions, which name matches one of its commands, help
877 877 message should ask '-v -e' to get list of built-in aliases
878 878 along with extension help itself
879 879
880 880 $ mkdir $TESTTMP/d
881 881 $ cat > $TESTTMP/d/dodo.py <<EOF
882 882 > """
883 883 > This is an awesome 'dodo' extension. It does nothing and
884 884 > writes 'Foo foo'
885 885 > """
886 886 > from mercurial import commands, registrar
887 887 > cmdtable = {}
888 888 > command = registrar.command(cmdtable)
889 889 > @command(b'dodo', [], b'hg dodo')
890 890 > def dodo(ui, *args, **kwargs):
891 891 > """Does nothing"""
892 892 > ui.write(b"I do nothing. Yay\\n")
893 893 > @command(b'foofoo', [], b'hg foofoo')
894 894 > def foofoo(ui, *args, **kwargs):
895 895 > """Writes 'Foo foo'"""
896 896 > ui.write(b"Foo foo\\n")
897 897 > EOF
898 898 $ dodopath=$TESTTMP/d/dodo.py
899 899
900 900 $ echo "dodo = $dodopath" >> $HGRCPATH
901 901
902 902 Make sure that user is asked to enter '-v -e' to get list of built-in aliases
903 903 $ hg help -e dodo
904 904 dodo extension -
905 905
906 906 This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo'
907 907
908 908 list of commands:
909 909
910 910 dodo Does nothing
911 911 foofoo Writes 'Foo foo'
912 912
913 913 (use 'hg help -v -e dodo' to show built-in aliases and global options)
914 914
915 915 Make sure that '-v -e' prints list of built-in aliases along with
916 916 extension help itself
917 917 $ hg help -v -e dodo
918 918 dodo extension -
919 919
920 920 This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo'
921 921
922 922 list of commands:
923 923
924 924 dodo Does nothing
925 925 foofoo Writes 'Foo foo'
926 926
927 927 global options ([+] can be repeated):
928 928
929 929 -R --repository REPO repository root directory or name of overlay bundle
930 930 file
931 931 --cwd DIR change working directory
932 932 -y --noninteractive do not prompt, automatically pick the first choice for
933 933 all prompts
934 934 -q --quiet suppress output
935 935 -v --verbose enable additional output
936 936 --color TYPE when to colorize (boolean, always, auto, never, or
937 937 debug)
938 938 --config CONFIG [+] set/override config option (use 'section.name=value')
939 939 --debug enable debugging output
940 940 --debugger start debugger
941 941 --encoding ENCODE set the charset encoding (default: ascii)
942 942 --encodingmode MODE set the charset encoding mode (default: strict)
943 943 --traceback always print a traceback on exception
944 944 --time time how long the command takes
945 945 --profile print command execution profile
946 946 --version output version information and exit
947 947 -h --help display help and exit
948 948 --hidden consider hidden changesets
949 949 --pager TYPE when to paginate (boolean, always, auto, or never)
950 950 (default: auto)
951 951
952 952 Make sure that single '-v' option shows help and built-ins only for 'dodo' command
953 953 $ hg help -v dodo
954 954 hg dodo
955 955
956 956 Does nothing
957 957
958 958 (use 'hg help -e dodo' to show help for the dodo extension)
959 959
960 960 options:
961 961
962 962 --mq operate on patch repository
963 963
964 964 global options ([+] can be repeated):
965 965
966 966 -R --repository REPO repository root directory or name of overlay bundle
967 967 file
968 968 --cwd DIR change working directory
969 969 -y --noninteractive do not prompt, automatically pick the first choice for
970 970 all prompts
971 971 -q --quiet suppress output
972 972 -v --verbose enable additional output
973 973 --color TYPE when to colorize (boolean, always, auto, never, or
974 974 debug)
975 975 --config CONFIG [+] set/override config option (use 'section.name=value')
976 976 --debug enable debugging output
977 977 --debugger start debugger
978 978 --encoding ENCODE set the charset encoding (default: ascii)
979 979 --encodingmode MODE set the charset encoding mode (default: strict)
980 980 --traceback always print a traceback on exception
981 981 --time time how long the command takes
982 982 --profile print command execution profile
983 983 --version output version information and exit
984 984 -h --help display help and exit
985 985 --hidden consider hidden changesets
986 986 --pager TYPE when to paginate (boolean, always, auto, or never)
987 987 (default: auto)
988 988
989 989 In case when extension name doesn't match any of its commands,
990 990 help message should ask for '-v' to get list of built-in aliases
991 991 along with extension help
992 992 $ cat > $TESTTMP/d/dudu.py <<EOF
993 993 > """
994 994 > This is an awesome 'dudu' extension. It does something and
995 995 > also writes 'Beep beep'
996 996 > """
997 997 > from mercurial import commands, registrar
998 998 > cmdtable = {}
999 999 > command = registrar.command(cmdtable)
1000 1000 > @command(b'something', [], b'hg something')
1001 1001 > def something(ui, *args, **kwargs):
1002 1002 > """Does something"""
1003 1003 > ui.write(b"I do something. Yaaay\\n")
1004 1004 > @command(b'beep', [], b'hg beep')
1005 1005 > def beep(ui, *args, **kwargs):
1006 1006 > """Writes 'Beep beep'"""
1007 1007 > ui.write(b"Beep beep\\n")
1008 1008 > EOF
1009 1009 $ dudupath=$TESTTMP/d/dudu.py
1010 1010
1011 1011 $ echo "dudu = $dudupath" >> $HGRCPATH
1012 1012
1013 1013 $ hg help -e dudu
1014 1014 dudu extension -
1015 1015
1016 1016 This is an awesome 'dudu' extension. It does something and also writes 'Beep
1017 1017 beep'
1018 1018
1019 1019 list of commands:
1020 1020
1021 1021 beep Writes 'Beep beep'
1022 1022 something Does something
1023 1023
1024 1024 (use 'hg help -v dudu' to show built-in aliases and global options)
1025 1025
1026 1026 In case when extension name doesn't match any of its commands,
1027 1027 help options '-v' and '-v -e' should be equivalent
1028 1028 $ hg help -v dudu
1029 1029 dudu extension -
1030 1030
1031 1031 This is an awesome 'dudu' extension. It does something and also writes 'Beep
1032 1032 beep'
1033 1033
1034 1034 list of commands:
1035 1035
1036 1036 beep Writes 'Beep beep'
1037 1037 something Does something
1038 1038
1039 1039 global options ([+] can be repeated):
1040 1040
1041 1041 -R --repository REPO repository root directory or name of overlay bundle
1042 1042 file
1043 1043 --cwd DIR change working directory
1044 1044 -y --noninteractive do not prompt, automatically pick the first choice for
1045 1045 all prompts
1046 1046 -q --quiet suppress output
1047 1047 -v --verbose enable additional output
1048 1048 --color TYPE when to colorize (boolean, always, auto, never, or
1049 1049 debug)
1050 1050 --config CONFIG [+] set/override config option (use 'section.name=value')
1051 1051 --debug enable debugging output
1052 1052 --debugger start debugger
1053 1053 --encoding ENCODE set the charset encoding (default: ascii)
1054 1054 --encodingmode MODE set the charset encoding mode (default: strict)
1055 1055 --traceback always print a traceback on exception
1056 1056 --time time how long the command takes
1057 1057 --profile print command execution profile
1058 1058 --version output version information and exit
1059 1059 -h --help display help and exit
1060 1060 --hidden consider hidden changesets
1061 1061 --pager TYPE when to paginate (boolean, always, auto, or never)
1062 1062 (default: auto)
1063 1063
1064 1064 $ hg help -v -e dudu
1065 1065 dudu extension -
1066 1066
1067 1067 This is an awesome 'dudu' extension. It does something and also writes 'Beep
1068 1068 beep'
1069 1069
1070 1070 list of commands:
1071 1071
1072 1072 beep Writes 'Beep beep'
1073 1073 something Does something
1074 1074
1075 1075 global options ([+] can be repeated):
1076 1076
1077 1077 -R --repository REPO repository root directory or name of overlay bundle
1078 1078 file
1079 1079 --cwd DIR change working directory
1080 1080 -y --noninteractive do not prompt, automatically pick the first choice for
1081 1081 all prompts
1082 1082 -q --quiet suppress output
1083 1083 -v --verbose enable additional output
1084 1084 --color TYPE when to colorize (boolean, always, auto, never, or
1085 1085 debug)
1086 1086 --config CONFIG [+] set/override config option (use 'section.name=value')
1087 1087 --debug enable debugging output
1088 1088 --debugger start debugger
1089 1089 --encoding ENCODE set the charset encoding (default: ascii)
1090 1090 --encodingmode MODE set the charset encoding mode (default: strict)
1091 1091 --traceback always print a traceback on exception
1092 1092 --time time how long the command takes
1093 1093 --profile print command execution profile
1094 1094 --version output version information and exit
1095 1095 -h --help display help and exit
1096 1096 --hidden consider hidden changesets
1097 1097 --pager TYPE when to paginate (boolean, always, auto, or never)
1098 1098 (default: auto)
1099 1099
1100 1100 Disabled extension commands:
1101 1101
1102 1102 $ ORGHGRCPATH=$HGRCPATH
1103 1103 $ HGRCPATH=
1104 1104 $ export HGRCPATH
1105 1105 $ hg help email
1106 1106 'email' is provided by the following extension:
1107 1107
1108 1108 patchbomb command to send changesets as (a series of) patch emails
1109 1109
1110 1110 (use 'hg help extensions' for information on enabling extensions)
1111 1111
1112 1112
1113 1113 $ hg qdel
1114 1114 hg: unknown command 'qdel'
1115 1115 'qdelete' is provided by the following extension:
1116 1116
1117 1117 mq manage a stack of patches
1118 1118
1119 1119 (use 'hg help extensions' for information on enabling extensions)
1120 1120 [255]
1121 1121
1122 1122
1123 1123 $ hg churn
1124 1124 hg: unknown command 'churn'
1125 1125 'churn' is provided by the following extension:
1126 1126
1127 1127 churn command to display statistics about repository history
1128 1128
1129 1129 (use 'hg help extensions' for information on enabling extensions)
1130 1130 [255]
1131 1131
1132 1132
1133 1133
1134 1134 Disabled extensions:
1135 1135
1136 1136 $ hg help churn
1137 1137 churn extension - command to display statistics about repository history
1138 1138
1139 1139 (use 'hg help extensions' for information on enabling extensions)
1140 1140
1141 1141 $ hg help patchbomb
1142 1142 patchbomb extension - command to send changesets as (a series of) patch emails
1143 1143
1144 1144 The series is started off with a "[PATCH 0 of N]" introduction, which
1145 1145 describes the series as a whole.
1146 1146
1147 1147 Each patch email has a Subject line of "[PATCH M of N] ...", using the first
1148 1148 line of the changeset description as the subject text. The message contains
1149 1149 two or three body parts:
1150 1150
1151 1151 - The changeset description.
1152 1152 - [Optional] The result of running diffstat on the patch.
1153 1153 - The patch itself, as generated by 'hg export'.
1154 1154
1155 1155 Each message refers to the first in the series using the In-Reply-To and
1156 1156 References headers, so they will show up as a sequence in threaded mail and
1157 1157 news readers, and in mail archives.
1158 1158
1159 1159 To configure other defaults, add a section like this to your configuration
1160 1160 file:
1161 1161
1162 1162 [email]
1163 1163 from = My Name <my@email>
1164 1164 to = recipient1, recipient2, ...
1165 1165 cc = cc1, cc2, ...
1166 1166 bcc = bcc1, bcc2, ...
1167 1167 reply-to = address1, address2, ...
1168 1168
1169 1169 Use "[patchbomb]" as configuration section name if you need to override global
1170 1170 "[email]" address settings.
1171 1171
1172 1172 Then you can use the 'hg email' command to mail a series of changesets as a
1173 1173 patchbomb.
1174 1174
1175 1175 You can also either configure the method option in the email section to be a
1176 1176 sendmail compatible mailer or fill out the [smtp] section so that the
1177 1177 patchbomb extension can automatically send patchbombs directly from the
1178 1178 commandline. See the [email] and [smtp] sections in hgrc(5) for details.
1179 1179
1180 1180 By default, 'hg email' will prompt for a "To" or "CC" header if you do not
1181 1181 supply one via configuration or the command line. You can override this to
1182 1182 never prompt by configuring an empty value:
1183 1183
1184 1184 [email]
1185 1185 cc =
1186 1186
1187 1187 You can control the default inclusion of an introduction message with the
1188 1188 "patchbomb.intro" configuration option. The configuration is always
1189 1189 overwritten by command line flags like --intro and --desc:
1190 1190
1191 1191 [patchbomb]
1192 1192 intro=auto # include introduction message if more than 1 patch (default)
1193 1193 intro=never # never include an introduction message
1194 1194 intro=always # always include an introduction message
1195 1195
1196 1196 You can specify a template for flags to be added in subject prefixes. Flags
1197 1197 specified by --flag option are exported as "{flags}" keyword:
1198 1198
1199 1199 [patchbomb]
1200 1200 flagtemplate = "{separate(' ',
1201 1201 ifeq(branch, 'default', '', branch|upper),
1202 1202 flags)}"
1203 1203
1204 1204 You can set patchbomb to always ask for confirmation by setting
1205 1205 "patchbomb.confirm" to true.
1206 1206
1207 1207 (use 'hg help extensions' for information on enabling extensions)
1208 1208
1209 1209
1210 1210 Broken disabled extension and command:
1211 1211
1212 1212 $ mkdir hgext
1213 1213 $ echo > hgext/__init__.py
1214 1214 $ cat > hgext/broken.py <<EOF
1215 1215 > "broken extension'
1216 1216 > EOF
1217 1217 $ cat > path.py <<EOF
1218 1218 > import os, sys
1219 1219 > sys.path.insert(0, os.environ['HGEXTPATH'])
1220 1220 > EOF
1221 1221 $ HGEXTPATH=`pwd`
1222 1222 $ export HGEXTPATH
1223 1223
1224 1224 $ hg --config extensions.path=./path.py help broken
1225 1225 broken extension - (no help text available)
1226 1226
1227 1227 (use 'hg help extensions' for information on enabling extensions)
1228 1228
1229 1229
1230 1230 $ cat > hgext/forest.py <<EOF
1231 1231 > cmdtable = None
1232 1232 > EOF
1233 1233 $ hg --config extensions.path=./path.py help foo > /dev/null
1234 1234 warning: error finding commands in $TESTTMP/hgext/forest.py
1235 1235 abort: no such help topic: foo
1236 1236 (try 'hg help --keyword foo')
1237 1237 [255]
1238 1238
1239 1239 $ cat > throw.py <<EOF
1240 1240 > from mercurial import commands, registrar, util
1241 1241 > cmdtable = {}
1242 1242 > command = registrar.command(cmdtable)
1243 1243 > class Bogon(Exception): pass
1244 1244 > @command(b'throw', [], b'hg throw', norepo=True)
1245 1245 > def throw(ui, **opts):
1246 1246 > """throws an exception"""
1247 1247 > raise Bogon()
1248 1248 > EOF
1249 1249
1250 1250 No declared supported version, extension complains:
1251 1251 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1252 1252 ** Unknown exception encountered with possibly-broken third-party extension throw
1253 1253 ** which supports versions unknown of Mercurial.
1254 1254 ** Please disable throw and try your action again.
1255 1255 ** If that fixes the bug please report it to the extension author.
1256 1256 ** Python * (glob)
1257 1257 ** Mercurial Distributed SCM * (glob)
1258 1258 ** Extensions loaded: throw
1259 1259
1260 1260 empty declaration of supported version, extension complains:
1261 1261 $ echo "testedwith = ''" >> throw.py
1262 1262 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1263 1263 ** Unknown exception encountered with possibly-broken third-party extension throw
1264 1264 ** which supports versions unknown of Mercurial.
1265 1265 ** Please disable throw and try your action again.
1266 1266 ** If that fixes the bug please report it to the extension author.
1267 1267 ** Python * (glob)
1268 1268 ** Mercurial Distributed SCM (*) (glob)
1269 1269 ** Extensions loaded: throw
1270 1270
1271 1271 If the extension specifies a buglink, show that:
1272 1272 $ echo 'buglink = "http://example.com/bts"' >> throw.py
1273 1273 $ rm -f throw.pyc throw.pyo
1274 1274 $ rm -Rf __pycache__
1275 1275 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1276 1276 ** Unknown exception encountered with possibly-broken third-party extension throw
1277 1277 ** which supports versions unknown of Mercurial.
1278 1278 ** Please disable throw and try your action again.
1279 1279 ** If that fixes the bug please report it to http://example.com/bts
1280 1280 ** Python * (glob)
1281 1281 ** Mercurial Distributed SCM (*) (glob)
1282 1282 ** Extensions loaded: throw
1283 1283
1284 1284 If the extensions declare outdated versions, accuse the older extension first:
1285 1285 $ echo "from mercurial import util" >> older.py
1286 $ echo "util.version = lambda:'2.2'" >> older.py
1286 $ echo "util.version = lambda:b'2.2'" >> older.py
1287 1287 $ echo "testedwith = b'1.9.3'" >> older.py
1288 1288 $ echo "testedwith = b'2.1.1'" >> throw.py
1289 1289 $ rm -f throw.pyc throw.pyo
1290 1290 $ rm -Rf __pycache__
1291 1291 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1292 1292 > throw 2>&1 | egrep '^\*\*'
1293 1293 ** Unknown exception encountered with possibly-broken third-party extension older
1294 1294 ** which supports versions 1.9 of Mercurial.
1295 1295 ** Please disable older and try your action again.
1296 1296 ** If that fixes the bug please report it to the extension author.
1297 1297 ** Python * (glob)
1298 1298 ** Mercurial Distributed SCM (version 2.2)
1299 1299 ** Extensions loaded: throw, older
1300 1300
1301 1301 One extension only tested with older, one only with newer versions:
1302 1302 $ echo "util.version = lambda:b'2.1'" >> older.py
1303 1303 $ rm -f older.pyc older.pyo
1304 1304 $ rm -Rf __pycache__
1305 1305 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1306 1306 > throw 2>&1 | egrep '^\*\*'
1307 1307 ** Unknown exception encountered with possibly-broken third-party extension older
1308 1308 ** which supports versions 1.9 of Mercurial.
1309 1309 ** Please disable older and try your action again.
1310 1310 ** If that fixes the bug please report it to the extension author.
1311 1311 ** Python * (glob)
1312 1312 ** Mercurial Distributed SCM (version 2.1)
1313 1313 ** Extensions loaded: throw, older
1314 1314
1315 1315 Older extension is tested with current version, the other only with newer:
1316 1316 $ echo "util.version = lambda:b'1.9.3'" >> older.py
1317 1317 $ rm -f older.pyc older.pyo
1318 1318 $ rm -Rf __pycache__
1319 1319 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1320 1320 > throw 2>&1 | egrep '^\*\*'
1321 1321 ** Unknown exception encountered with possibly-broken third-party extension throw
1322 1322 ** which supports versions 2.1 of Mercurial.
1323 1323 ** Please disable throw and try your action again.
1324 1324 ** If that fixes the bug please report it to http://example.com/bts
1325 1325 ** Python * (glob)
1326 1326 ** Mercurial Distributed SCM (version 1.9.3)
1327 1327 ** Extensions loaded: throw, older
1328 1328
1329 1329 Ability to point to a different point
1330 1330 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1331 1331 > --config ui.supportcontact='Your Local Goat Lenders' throw 2>&1 | egrep '^\*\*'
1332 1332 ** unknown exception encountered, please report by visiting
1333 1333 ** Your Local Goat Lenders
1334 1334 ** Python * (glob)
1335 1335 ** Mercurial Distributed SCM (*) (glob)
1336 1336 ** Extensions loaded: throw, older
1337 1337
1338 1338 Declare the version as supporting this hg version, show regular bts link:
1339 1339 $ hgver=`hg debuginstall -T '{hgver}'`
1340 1340 $ echo 'testedwith = """'"$hgver"'"""' >> throw.py
1341 1341 $ if [ -z "$hgver" ]; then
1342 1342 > echo "unable to fetch a mercurial version. Make sure __version__ is correct";
1343 1343 > fi
1344 1344 $ rm -f throw.pyc throw.pyo
1345 1345 $ rm -Rf __pycache__
1346 1346 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1347 1347 ** unknown exception encountered, please report by visiting
1348 1348 ** https://mercurial-scm.org/wiki/BugTracker
1349 1349 ** Python * (glob)
1350 1350 ** Mercurial Distributed SCM (*) (glob)
1351 1351 ** Extensions loaded: throw
1352 1352
1353 1353 Patch version is ignored during compatibility check
1354 1354 $ echo "testedwith = b'3.2'" >> throw.py
1355 1355 $ echo "util.version = lambda:b'3.2.2'" >> throw.py
1356 1356 $ rm -f throw.pyc throw.pyo
1357 1357 $ rm -Rf __pycache__
1358 1358 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1359 1359 ** unknown exception encountered, please report by visiting
1360 1360 ** https://mercurial-scm.org/wiki/BugTracker
1361 1361 ** Python * (glob)
1362 1362 ** Mercurial Distributed SCM (*) (glob)
1363 1363 ** Extensions loaded: throw
1364 1364
1365 1365 Test version number support in 'hg version':
1366 1366 $ echo '__version__ = (1, 2, 3)' >> throw.py
1367 1367 $ rm -f throw.pyc throw.pyo
1368 1368 $ rm -Rf __pycache__
1369 1369 $ hg version -v
1370 1370 Mercurial Distributed SCM (version *) (glob)
1371 1371 (see https://mercurial-scm.org for more information)
1372 1372
1373 1373 Copyright (C) 2005-* Matt Mackall and others (glob)
1374 1374 This is free software; see the source for copying conditions. There is NO
1375 1375 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1376 1376
1377 1377 Enabled extensions:
1378 1378
1379 1379
1380 1380 $ hg version -v --config extensions.throw=throw.py
1381 1381 Mercurial Distributed SCM (version *) (glob)
1382 1382 (see https://mercurial-scm.org for more information)
1383 1383
1384 1384 Copyright (C) 2005-* Matt Mackall and others (glob)
1385 1385 This is free software; see the source for copying conditions. There is NO
1386 1386 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1387 1387
1388 1388 Enabled extensions:
1389 1389
1390 1390 throw external 1.2.3
1391 $ echo 'getversion = lambda: "1.twentythree"' >> throw.py
1391 $ echo 'getversion = lambda: b"1.twentythree"' >> throw.py
1392 1392 $ rm -f throw.pyc throw.pyo
1393 1393 $ rm -Rf __pycache__
1394 1394 $ hg version -v --config extensions.throw=throw.py --config extensions.strip=
1395 1395 Mercurial Distributed SCM (version *) (glob)
1396 1396 (see https://mercurial-scm.org for more information)
1397 1397
1398 1398 Copyright (C) 2005-* Matt Mackall and others (glob)
1399 1399 This is free software; see the source for copying conditions. There is NO
1400 1400 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1401 1401
1402 1402 Enabled extensions:
1403 1403
1404 1404 throw external 1.twentythree
1405 1405 strip internal
1406 1406
1407 1407 $ hg version -q --config extensions.throw=throw.py
1408 1408 Mercurial Distributed SCM (version *) (glob)
1409 1409
1410 1410 Test template output:
1411 1411
1412 1412 $ hg version --config extensions.strip= -T'{extensions}'
1413 1413 strip
1414 1414
1415 1415 Test JSON output of version:
1416 1416
1417 1417 $ hg version -Tjson
1418 1418 [
1419 1419 {
1420 1420 "extensions": [],
1421 1421 "ver": "*" (glob)
1422 1422 }
1423 1423 ]
1424 1424
1425 1425 $ hg version --config extensions.throw=throw.py -Tjson
1426 1426 [
1427 1427 {
1428 1428 "extensions": [{"bundled": false, "name": "throw", "ver": "1.twentythree"}],
1429 1429 "ver": "3.2.2"
1430 1430 }
1431 1431 ]
1432 1432
1433 1433 $ hg version --config extensions.strip= -Tjson
1434 1434 [
1435 1435 {
1436 1436 "extensions": [{"bundled": true, "name": "strip", "ver": null}],
1437 1437 "ver": "*" (glob)
1438 1438 }
1439 1439 ]
1440 1440
1441 1441 Test template output of version:
1442 1442
1443 1443 $ hg version --config extensions.throw=throw.py --config extensions.strip= \
1444 1444 > -T'{extensions % "{name} {pad(ver, 16)} ({if(bundled, "internal", "external")})\n"}'
1445 1445 throw 1.twentythree (external)
1446 1446 strip (internal)
1447 1447
1448 1448 Refuse to load extensions with minimum version requirements
1449 1449
1450 1450 $ cat > minversion1.py << EOF
1451 1451 > from mercurial import util
1452 1452 > util.version = lambda: b'3.5.2'
1453 1453 > minimumhgversion = b'3.6'
1454 1454 > EOF
1455 1455 $ hg --config extensions.minversion=minversion1.py version
1456 1456 (third party extension minversion requires version 3.6 or newer of Mercurial; disabling)
1457 1457 Mercurial Distributed SCM (version 3.5.2)
1458 1458 (see https://mercurial-scm.org for more information)
1459 1459
1460 1460 Copyright (C) 2005-* Matt Mackall and others (glob)
1461 1461 This is free software; see the source for copying conditions. There is NO
1462 1462 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1463 1463
1464 1464 $ cat > minversion2.py << EOF
1465 1465 > from mercurial import util
1466 1466 > util.version = lambda: b'3.6'
1467 1467 > minimumhgversion = b'3.7'
1468 1468 > EOF
1469 1469 $ hg --config extensions.minversion=minversion2.py version 2>&1 | egrep '\(third'
1470 1470 (third party extension minversion requires version 3.7 or newer of Mercurial; disabling)
1471 1471
1472 1472 Can load version that is only off by point release
1473 1473
1474 1474 $ cat > minversion2.py << EOF
1475 1475 > from mercurial import util
1476 1476 > util.version = lambda: b'3.6.1'
1477 1477 > minimumhgversion = b'3.6'
1478 1478 > EOF
1479 1479 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1480 1480 [1]
1481 1481
1482 1482 Can load minimum version identical to current
1483 1483
1484 1484 $ cat > minversion3.py << EOF
1485 1485 > from mercurial import util
1486 1486 > util.version = lambda: b'3.5'
1487 1487 > minimumhgversion = b'3.5'
1488 1488 > EOF
1489 1489 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1490 1490 [1]
1491 1491
1492 1492 Restore HGRCPATH
1493 1493
1494 1494 $ HGRCPATH=$ORGHGRCPATH
1495 1495 $ export HGRCPATH
1496 1496
1497 1497 Commands handling multiple repositories at a time should invoke only
1498 1498 "reposetup()" of extensions enabling in the target repository.
1499 1499
1500 1500 $ mkdir reposetup-test
1501 1501 $ cd reposetup-test
1502 1502
1503 1503 $ cat > $TESTTMP/reposetuptest.py <<EOF
1504 1504 > from mercurial import extensions
1505 1505 > def reposetup(ui, repo):
1506 1506 > ui.write(b'reposetup() for %s\n' % (repo.root))
1507 1507 > ui.flush()
1508 1508 > EOF
1509 1509 $ hg init src
1510 1510 $ echo a > src/a
1511 1511 $ hg -R src commit -Am '#0 at src/a'
1512 1512 adding a
1513 1513 $ echo '[extensions]' >> src/.hg/hgrc
1514 1514 $ echo '# enable extension locally' >> src/.hg/hgrc
1515 1515 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
1516 1516 $ hg -R src status
1517 1517 reposetup() for $TESTTMP/reposetup-test/src
1518 1518 reposetup() for $TESTTMP/reposetup-test/src (chg !)
1519 1519
1520 1520 $ hg --cwd src debugextensions
1521 1521 reposetup() for $TESTTMP/reposetup-test/src
1522 1522 dodo (untested!)
1523 1523 dudu (untested!)
1524 1524 mq
1525 1525 reposetuptest (untested!)
1526 1526 strip
1527 1527
1528 1528 $ hg clone -U src clone-dst1
1529 1529 reposetup() for $TESTTMP/reposetup-test/src
1530 1530 $ hg init push-dst1
1531 1531 $ hg -q -R src push push-dst1
1532 1532 reposetup() for $TESTTMP/reposetup-test/src
1533 1533 $ hg init pull-src1
1534 1534 $ hg -q -R pull-src1 pull src
1535 1535 reposetup() for $TESTTMP/reposetup-test/src
1536 1536
1537 1537 $ cat <<EOF >> $HGRCPATH
1538 1538 > [extensions]
1539 1539 > # disable extension globally and explicitly
1540 1540 > reposetuptest = !
1541 1541 > EOF
1542 1542 $ hg clone -U src clone-dst2
1543 1543 reposetup() for $TESTTMP/reposetup-test/src
1544 1544 $ hg init push-dst2
1545 1545 $ hg -q -R src push push-dst2
1546 1546 reposetup() for $TESTTMP/reposetup-test/src
1547 1547 $ hg init pull-src2
1548 1548 $ hg -q -R pull-src2 pull src
1549 1549 reposetup() for $TESTTMP/reposetup-test/src
1550 1550
1551 1551 $ cat <<EOF >> $HGRCPATH
1552 1552 > [extensions]
1553 1553 > # enable extension globally
1554 1554 > reposetuptest = $TESTTMP/reposetuptest.py
1555 1555 > EOF
1556 1556 $ hg clone -U src clone-dst3
1557 1557 reposetup() for $TESTTMP/reposetup-test/src
1558 1558 reposetup() for $TESTTMP/reposetup-test/clone-dst3
1559 1559 $ hg init push-dst3
1560 1560 reposetup() for $TESTTMP/reposetup-test/push-dst3
1561 1561 $ hg -q -R src push push-dst3
1562 1562 reposetup() for $TESTTMP/reposetup-test/src
1563 1563 reposetup() for $TESTTMP/reposetup-test/push-dst3
1564 1564 $ hg init pull-src3
1565 1565 reposetup() for $TESTTMP/reposetup-test/pull-src3
1566 1566 $ hg -q -R pull-src3 pull src
1567 1567 reposetup() for $TESTTMP/reposetup-test/pull-src3
1568 1568 reposetup() for $TESTTMP/reposetup-test/src
1569 1569
1570 1570 $ echo '[extensions]' >> src/.hg/hgrc
1571 1571 $ echo '# disable extension locally' >> src/.hg/hgrc
1572 1572 $ echo 'reposetuptest = !' >> src/.hg/hgrc
1573 1573 $ hg clone -U src clone-dst4
1574 1574 reposetup() for $TESTTMP/reposetup-test/clone-dst4
1575 1575 $ hg init push-dst4
1576 1576 reposetup() for $TESTTMP/reposetup-test/push-dst4
1577 1577 $ hg -q -R src push push-dst4
1578 1578 reposetup() for $TESTTMP/reposetup-test/push-dst4
1579 1579 $ hg init pull-src4
1580 1580 reposetup() for $TESTTMP/reposetup-test/pull-src4
1581 1581 $ hg -q -R pull-src4 pull src
1582 1582 reposetup() for $TESTTMP/reposetup-test/pull-src4
1583 1583
1584 1584 disabling in command line overlays with all configuration
1585 1585 $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
1586 1586 $ hg --config extensions.reposetuptest=! init push-dst5
1587 1587 $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
1588 1588 $ hg --config extensions.reposetuptest=! init pull-src5
1589 1589 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
1590 1590
1591 1591 $ cat <<EOF >> $HGRCPATH
1592 1592 > [extensions]
1593 1593 > # disable extension globally and explicitly
1594 1594 > reposetuptest = !
1595 1595 > EOF
1596 1596 $ hg init parent
1597 1597 $ hg init parent/sub1
1598 1598 $ echo 1 > parent/sub1/1
1599 1599 $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
1600 1600 adding 1
1601 1601 $ hg init parent/sub2
1602 1602 $ hg init parent/sub2/sub21
1603 1603 $ echo 21 > parent/sub2/sub21/21
1604 1604 $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
1605 1605 adding 21
1606 1606 $ cat > parent/sub2/.hgsub <<EOF
1607 1607 > sub21 = sub21
1608 1608 > EOF
1609 1609 $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
1610 1610 adding .hgsub
1611 1611 $ hg init parent/sub3
1612 1612 $ echo 3 > parent/sub3/3
1613 1613 $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
1614 1614 adding 3
1615 1615 $ cat > parent/.hgsub <<EOF
1616 1616 > sub1 = sub1
1617 1617 > sub2 = sub2
1618 1618 > sub3 = sub3
1619 1619 > EOF
1620 1620 $ hg -R parent commit -Am '#0 at parent'
1621 1621 adding .hgsub
1622 1622 $ echo '[extensions]' >> parent/.hg/hgrc
1623 1623 $ echo '# enable extension locally' >> parent/.hg/hgrc
1624 1624 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
1625 1625 $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
1626 1626 $ hg -R parent status -S -A
1627 1627 reposetup() for $TESTTMP/reposetup-test/parent
1628 1628 reposetup() for $TESTTMP/reposetup-test/parent/sub2
1629 1629 C .hgsub
1630 1630 C .hgsubstate
1631 1631 C sub1/1
1632 1632 C sub2/.hgsub
1633 1633 C sub2/.hgsubstate
1634 1634 C sub2/sub21/21
1635 1635 C sub3/3
1636 1636
1637 1637 $ cd ..
1638 1638
1639 1639 Prohibit registration of commands that don't use @command (issue5137)
1640 1640
1641 1641 $ hg init deprecated
1642 1642 $ cd deprecated
1643 1643
1644 1644 $ cat <<EOF > deprecatedcmd.py
1645 1645 > def deprecatedcmd(repo, ui):
1646 1646 > pass
1647 1647 > cmdtable = {
1648 1648 > b'deprecatedcmd': (deprecatedcmd, [], b''),
1649 1649 > }
1650 1650 > EOF
1651 1651 $ cat <<EOF > .hg/hgrc
1652 1652 > [extensions]
1653 1653 > deprecatedcmd = `pwd`/deprecatedcmd.py
1654 1654 > mq = !
1655 1655 > hgext.mq = !
1656 1656 > hgext/mq = !
1657 1657 > EOF
1658 1658
1659 1659 $ hg deprecatedcmd > /dev/null
1660 1660 *** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo
1661 1661 *** (use @command decorator to register 'deprecatedcmd')
1662 1662 hg: unknown command 'deprecatedcmd'
1663 1663 [255]
1664 1664
1665 1665 the extension shouldn't be loaded at all so the mq works:
1666 1666
1667 1667 $ hg qseries --config extensions.mq= > /dev/null
1668 1668 *** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo
1669 1669 *** (use @command decorator to register 'deprecatedcmd')
1670 1670
1671 1671 $ cd ..
1672 1672
1673 1673 Test synopsis and docstring extending
1674 1674
1675 1675 $ hg init exthelp
1676 1676 $ cat > exthelp.py <<EOF
1677 1677 > from mercurial import commands, extensions
1678 1678 > def exbookmarks(orig, *args, **opts):
1679 1679 > return orig(*args, **opts)
1680 1680 > def uisetup(ui):
1681 > synopsis = ' GREPME [--foo] [-x]'
1681 > synopsis = b' GREPME [--foo] [-x]'
1682 1682 > docstring = '''
1683 1683 > GREPME make sure that this is in the help!
1684 1684 > '''
1685 1685 > extensions.wrapcommand(commands.table, b'bookmarks', exbookmarks,
1686 1686 > synopsis, docstring)
1687 1687 > EOF
1688 1688 $ abspath=`pwd`/exthelp.py
1689 1689 $ echo '[extensions]' >> $HGRCPATH
1690 1690 $ echo "exthelp = $abspath" >> $HGRCPATH
1691 1691 $ cd exthelp
1692 1692 $ hg help bookmarks | grep GREPME
1693 1693 hg bookmarks [OPTIONS]... [NAME]... GREPME [--foo] [-x]
1694 1694 GREPME make sure that this is in the help!
1695 1695 $ cd ..
1696 1696
1697 1697 Show deprecation warning for the use of cmdutil.command
1698 1698
1699 1699 $ cat > nonregistrar.py <<EOF
1700 1700 > from mercurial import cmdutil
1701 1701 > cmdtable = {}
1702 1702 > command = cmdutil.command(cmdtable)
1703 1703 > @command(b'foo', [], norepo=True)
1704 1704 > def foo(ui):
1705 1705 > pass
1706 1706 > EOF
1707 1707
1708 1708 Prohibit the use of unicode strings as the default value of options
1709 1709
1710 1710 $ hg init $TESTTMP/opt-unicode-default
1711 1711
1712 1712 $ cat > $TESTTMP/test_unicode_default_value.py << EOF
1713 1713 > from mercurial import registrar
1714 1714 > cmdtable = {}
1715 1715 > command = registrar.command(cmdtable)
1716 > @command(b'dummy', [('', 'opt', u'value', u'help')], 'ext [OPTIONS]')
1716 > @command(b'dummy', [(b'', b'opt', u'value', u'help')], 'ext [OPTIONS]')
1717 1717 > def ext(*args, **opts):
1718 > print(opts['opt'])
1718 > print(opts[b'opt'])
1719 1719 > EOF
1720 1720 $ cat > $TESTTMP/opt-unicode-default/.hg/hgrc << EOF
1721 1721 > [extensions]
1722 1722 > test_unicode_default_value = $TESTTMP/test_unicode_default_value.py
1723 1723 > EOF
1724 1724 $ hg -R $TESTTMP/opt-unicode-default dummy
1725 1725 *** failed to import extension test_unicode_default_value from $TESTTMP/test_unicode_default_value.py: unicode u'value' found in cmdtable.dummy
1726 1726 *** (use b'' to make it byte string)
1727 1727 hg: unknown command 'dummy'
1728 1728 (did you mean summary?)
1729 1729 [255]
General Comments 0
You need to be logged in to leave comments. Login now