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