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