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