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