##// END OF EJS Templates
pyoxidizer: disable the test for disabled & broken extensions help...
marmoute -
r48659:d88f4231 stable
parent child Browse files
Show More
@@ -1,1910 +1,1926 b''
1 Test basic extension support
1 Test basic extension support
2 $ cat > unflush.py <<EOF
2 $ cat > unflush.py <<EOF
3 > import sys
3 > import sys
4 > from mercurial import pycompat
4 > from mercurial import pycompat
5 > if pycompat.ispy3:
5 > if pycompat.ispy3:
6 > # no changes required
6 > # no changes required
7 > sys.exit(0)
7 > sys.exit(0)
8 > with open(sys.argv[1], 'rb') as f:
8 > with open(sys.argv[1], 'rb') as f:
9 > data = f.read()
9 > data = f.read()
10 > with open(sys.argv[1], 'wb') as f:
10 > with open(sys.argv[1], 'wb') as f:
11 > f.write(data.replace(b', flush=True', b''))
11 > f.write(data.replace(b', flush=True', b''))
12 > EOF
12 > EOF
13
13
14 $ cat > foobar.py <<EOF
14 $ cat > foobar.py <<EOF
15 > import os
15 > import os
16 > from mercurial import commands, 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) (no-pyoxidizer !)
671 File "*/mercurial/extensions.py", line *, in _runuisetup (glob) (no-pyoxidizer !)
672 File "mercurial.extensions", line *, in _runuisetup (glob) (pyoxidizer !)
672 File "mercurial.extensions", line *, in _runuisetup (glob) (pyoxidizer !)
673 uisetup(ui)
673 uisetup(ui)
674 File "$TESTTMP/baduisetup.py", line 2, in uisetup
674 File "$TESTTMP/baduisetup.py", line 2, in uisetup
675 1 / 0
675 1 / 0
676 ZeroDivisionError: * by zero (glob)
676 ZeroDivisionError: * by zero (glob)
677 *** failed to set up extension baduisetup: * by zero (glob)
677 *** failed to set up extension baduisetup: * by zero (glob)
678 Mercurial Distributed SCM (version *) (glob)
678 Mercurial Distributed SCM (version *) (glob)
679 (see https://mercurial-scm.org for more information)
679 (see https://mercurial-scm.org for more information)
680
680
681 Copyright (C) 2005-* Olivia Mackall and others (glob)
681 Copyright (C) 2005-* Olivia Mackall and others (glob)
682 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
683 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
683 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
684
684
685 $ cd ..
685 $ cd ..
686
686
687 hide outer repo
687 hide outer repo
688 $ hg init
688 $ hg init
689
689
690 $ cat > empty.py <<EOF
690 $ cat > empty.py <<EOF
691 > '''empty cmdtable
691 > '''empty cmdtable
692 > '''
692 > '''
693 > cmdtable = {}
693 > cmdtable = {}
694 > EOF
694 > EOF
695 $ emptypath=`pwd`/empty.py
695 $ emptypath=`pwd`/empty.py
696 $ echo "empty = $emptypath" >> $HGRCPATH
696 $ echo "empty = $emptypath" >> $HGRCPATH
697 $ hg help empty
697 $ hg help empty
698 empty extension - empty cmdtable
698 empty extension - empty cmdtable
699
699
700 no commands defined
700 no commands defined
701
701
702
702
703 $ echo 'empty = !' >> $HGRCPATH
703 $ echo 'empty = !' >> $HGRCPATH
704
704
705 $ cat > debugextension.py <<EOF
705 $ cat > debugextension.py <<EOF
706 > '''only debugcommands
706 > '''only debugcommands
707 > '''
707 > '''
708 > from mercurial import registrar
708 > from mercurial import registrar
709 > cmdtable = {}
709 > cmdtable = {}
710 > command = registrar.command(cmdtable)
710 > command = registrar.command(cmdtable)
711 > @command(b'debugfoobar', [], b'hg debugfoobar')
711 > @command(b'debugfoobar', [], b'hg debugfoobar')
712 > def debugfoobar(ui, repo, *args, **opts):
712 > def debugfoobar(ui, repo, *args, **opts):
713 > "yet another debug command"
713 > "yet another debug command"
714 > @command(b'foo', [], b'hg foo')
714 > @command(b'foo', [], b'hg foo')
715 > def foo(ui, repo, *args, **opts):
715 > def foo(ui, repo, *args, **opts):
716 > """yet another foo command
716 > """yet another foo command
717 > This command has been DEPRECATED since forever.
717 > This command has been DEPRECATED since forever.
718 > """
718 > """
719 > EOF
719 > EOF
720 $ debugpath=`pwd`/debugextension.py
720 $ debugpath=`pwd`/debugextension.py
721 $ echo "debugextension = $debugpath" >> $HGRCPATH
721 $ echo "debugextension = $debugpath" >> $HGRCPATH
722
722
723 $ hg help debugextension
723 $ hg help debugextension
724 hg debugextensions
724 hg debugextensions
725
725
726 show information about active extensions
726 show information about active extensions
727
727
728 options:
728 options:
729
729
730 -T --template TEMPLATE display with template
730 -T --template TEMPLATE display with template
731
731
732 (some details hidden, use --verbose to show complete help)
732 (some details hidden, use --verbose to show complete help)
733
733
734
734
735 $ hg --verbose help debugextension
735 $ hg --verbose help debugextension
736 hg debugextensions
736 hg debugextensions
737
737
738 show information about active extensions
738 show information about active extensions
739
739
740 options:
740 options:
741
741
742 -T --template TEMPLATE display with template
742 -T --template TEMPLATE display with template
743
743
744 global options ([+] can be repeated):
744 global options ([+] can be repeated):
745
745
746 -R --repository REPO repository root directory or name of overlay bundle
746 -R --repository REPO repository root directory or name of overlay bundle
747 file
747 file
748 --cwd DIR change working directory
748 --cwd DIR change working directory
749 -y --noninteractive do not prompt, automatically pick the first choice for
749 -y --noninteractive do not prompt, automatically pick the first choice for
750 all prompts
750 all prompts
751 -q --quiet suppress output
751 -q --quiet suppress output
752 -v --verbose enable additional output
752 -v --verbose enable additional output
753 --color TYPE when to colorize (boolean, always, auto, never, or
753 --color TYPE when to colorize (boolean, always, auto, never, or
754 debug)
754 debug)
755 --config CONFIG [+] set/override config option (use 'section.name=value')
755 --config CONFIG [+] set/override config option (use 'section.name=value')
756 --debug enable debugging output
756 --debug enable debugging output
757 --debugger start debugger
757 --debugger start debugger
758 --encoding ENCODE set the charset encoding (default: ascii)
758 --encoding ENCODE set the charset encoding (default: ascii)
759 --encodingmode MODE set the charset encoding mode (default: strict)
759 --encodingmode MODE set the charset encoding mode (default: strict)
760 --traceback always print a traceback on exception
760 --traceback always print a traceback on exception
761 --time time how long the command takes
761 --time time how long the command takes
762 --profile print command execution profile
762 --profile print command execution profile
763 --version output version information and exit
763 --version output version information and exit
764 -h --help display help and exit
764 -h --help display help and exit
765 --hidden consider hidden changesets
765 --hidden consider hidden changesets
766 --pager TYPE when to paginate (boolean, always, auto, or never)
766 --pager TYPE when to paginate (boolean, always, auto, or never)
767 (default: auto)
767 (default: auto)
768
768
769
769
770
770
771
771
772
772
773
773
774 $ hg --debug help debugextension
774 $ hg --debug help debugextension
775 hg debugextensions
775 hg debugextensions
776
776
777 show information about active extensions
777 show information about active extensions
778
778
779 options:
779 options:
780
780
781 -T --template TEMPLATE display with template
781 -T --template TEMPLATE display with template
782
782
783 global options ([+] can be repeated):
783 global options ([+] can be repeated):
784
784
785 -R --repository REPO repository root directory or name of overlay bundle
785 -R --repository REPO repository root directory or name of overlay bundle
786 file
786 file
787 --cwd DIR change working directory
787 --cwd DIR change working directory
788 -y --noninteractive do not prompt, automatically pick the first choice for
788 -y --noninteractive do not prompt, automatically pick the first choice for
789 all prompts
789 all prompts
790 -q --quiet suppress output
790 -q --quiet suppress output
791 -v --verbose enable additional output
791 -v --verbose enable additional output
792 --color TYPE when to colorize (boolean, always, auto, never, or
792 --color TYPE when to colorize (boolean, always, auto, never, or
793 debug)
793 debug)
794 --config CONFIG [+] set/override config option (use 'section.name=value')
794 --config CONFIG [+] set/override config option (use 'section.name=value')
795 --debug enable debugging output
795 --debug enable debugging output
796 --debugger start debugger
796 --debugger start debugger
797 --encoding ENCODE set the charset encoding (default: ascii)
797 --encoding ENCODE set the charset encoding (default: ascii)
798 --encodingmode MODE set the charset encoding mode (default: strict)
798 --encodingmode MODE set the charset encoding mode (default: strict)
799 --traceback always print a traceback on exception
799 --traceback always print a traceback on exception
800 --time time how long the command takes
800 --time time how long the command takes
801 --profile print command execution profile
801 --profile print command execution profile
802 --version output version information and exit
802 --version output version information and exit
803 -h --help display help and exit
803 -h --help display help and exit
804 --hidden consider hidden changesets
804 --hidden consider hidden changesets
805 --pager TYPE when to paginate (boolean, always, auto, or never)
805 --pager TYPE when to paginate (boolean, always, auto, or never)
806 (default: auto)
806 (default: auto)
807
807
808
808
809
809
810
810
811
811
812 $ echo 'debugextension = !' >> $HGRCPATH
812 $ echo 'debugextension = !' >> $HGRCPATH
813
813
814 Asking for help about a deprecated extension should do something useful:
814 Asking for help about a deprecated extension should do something useful:
815
815
816 $ hg help glog
816 $ hg help glog
817 'glog' is provided by the following extension:
817 'glog' is provided by the following extension:
818
818
819 graphlog command to view revision graphs from a shell (DEPRECATED)
819 graphlog command to view revision graphs from a shell (DEPRECATED)
820
820
821 (use 'hg help extensions' for information on enabling extensions)
821 (use 'hg help extensions' for information on enabling extensions)
822
822
823 Extension module help vs command help:
823 Extension module help vs command help:
824
824
825 $ echo 'extdiff =' >> $HGRCPATH
825 $ echo 'extdiff =' >> $HGRCPATH
826 $ hg help extdiff
826 $ hg help extdiff
827 hg extdiff [OPT]... [FILE]...
827 hg extdiff [OPT]... [FILE]...
828
828
829 use external program to diff repository (or selected files)
829 use external program to diff repository (or selected files)
830
830
831 Show differences between revisions for the specified files, using an
831 Show differences between revisions for the specified files, using an
832 external program. The default program used is diff, with default options
832 external program. The default program used is diff, with default options
833 "-Npru".
833 "-Npru".
834
834
835 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
836 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-
837 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
838 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
839 directories or files to compare.
839 directories or files to compare.
840
840
841 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
842 diff'.
842 diff'.
843
843
844 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
845 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
846 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
847 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
848 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
849 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
850 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
851 graphical interface.
851 graphical interface.
852
852
853 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
854 external program. It is ignored if --per-file isn't specified.
854 external program. It is ignored if --per-file isn't specified.
855
855
856 (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)
857
857
858 options ([+] can be repeated):
858 options ([+] can be repeated):
859
859
860 -p --program CMD comparison program to run
860 -p --program CMD comparison program to run
861 -o --option OPT [+] pass option to comparison program
861 -o --option OPT [+] pass option to comparison program
862 --from REV1 revision to diff from
862 --from REV1 revision to diff from
863 --to REV2 revision to diff to
863 --to REV2 revision to diff to
864 -c --change REV change made by revision
864 -c --change REV change made by revision
865 --per-file compare each file instead of revision snapshots
865 --per-file compare each file instead of revision snapshots
866 --confirm prompt user before each external program invocation
866 --confirm prompt user before each external program invocation
867 --patch compare patches for two revisions
867 --patch compare patches for two revisions
868 -I --include PATTERN [+] include names matching the given patterns
868 -I --include PATTERN [+] include names matching the given patterns
869 -X --exclude PATTERN [+] exclude names matching the given patterns
869 -X --exclude PATTERN [+] exclude names matching the given patterns
870 -S --subrepos recurse into subrepositories
870 -S --subrepos recurse into subrepositories
871
871
872 (some details hidden, use --verbose to show complete help)
872 (some details hidden, use --verbose to show complete help)
873
873
874
874
875
875
876
876
877
877
878
878
879
879
880
880
881
881
882
882
883 $ hg help --extension extdiff
883 $ hg help --extension extdiff
884 extdiff extension - command to allow external programs to compare revisions
884 extdiff extension - command to allow external programs to compare revisions
885
885
886 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
887 revisions, or revision with working directory. The external diff programs are
887 revisions, or revision with working directory. The external diff programs are
888 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
889 to directories containing snapshots of files to compare.
889 to directories containing snapshots of files to compare.
890
890
891 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
892 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
893 copied back to the working directory from the temporary directory.
893 copied back to the working directory from the temporary directory.
894
894
895 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
896 do not need to type 'hg extdiff -p kdiff3' always.
896 do not need to type 'hg extdiff -p kdiff3' always.
897
897
898 [extdiff]
898 [extdiff]
899 # 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
900 cdiff = gdiff -Nprc5
900 cdiff = gdiff -Nprc5
901 ## or the old way:
901 ## or the old way:
902 #cmd.cdiff = gdiff
902 #cmd.cdiff = gdiff
903 #opts.cdiff = -Nprc5
903 #opts.cdiff = -Nprc5
904
904
905 # 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
906 # 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]
907 # will be used, if available
907 # will be used, if available
908 meld =
908 meld =
909
909
910 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
910 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
911 # (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
912 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
912 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
913 # your .vimrc
913 # your .vimrc
914 vimdiff = gvim -f "+next" \
914 vimdiff = gvim -f "+next" \
915 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
915 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
916
916
917 Tool arguments can include variables that are expanded at runtime:
917 Tool arguments can include variables that are expanded at runtime:
918
918
919 $parent1, $plabel1 - filename, descriptive label of first parent
919 $parent1, $plabel1 - filename, descriptive label of first parent
920 $child, $clabel - filename, descriptive label of child revision
920 $child, $clabel - filename, descriptive label of child revision
921 $parent2, $plabel2 - filename, descriptive label of second parent
921 $parent2, $plabel2 - filename, descriptive label of second parent
922 $root - repository root
922 $root - repository root
923 $parent is an alias for $parent1.
923 $parent is an alias for $parent1.
924
924
925 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]
926 sections for diff tool arguments, when none are specified in [extdiff].
926 sections for diff tool arguments, when none are specified in [extdiff].
927
927
928 [extdiff]
928 [extdiff]
929 kdiff3 =
929 kdiff3 =
930
930
931 [diff-tools]
931 [diff-tools]
932 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
932 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
933
933
934 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
935 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
936 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
937 '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
938 (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
939 option).
939 option).
940
940
941 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"
942 flag next to where "diffargs" are specified:
942 flag next to where "diffargs" are specified:
943
943
944 [diff-tools]
944 [diff-tools]
945 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
945 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
946 kdiff3.gui = true
946 kdiff3.gui = true
947
947
948 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'
949 command. The extdiff extension makes snapshots of only needed files, so
949 command. The extdiff extension makes snapshots of only needed files, so
950 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
951 faster than having to compare the entire tree).
951 faster than having to compare the entire tree).
952
952
953 list of commands:
953 list of commands:
954
954
955 extdiff use external program to diff repository (or selected files)
955 extdiff use external program to diff repository (or selected files)
956
956
957 (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)
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
974 $ echo 'extdiff = !' >> $HGRCPATH
974 $ echo 'extdiff = !' >> $HGRCPATH
975
975
976 Test help topic with same name as extension
976 Test help topic with same name as extension
977
977
978 $ cat > multirevs.py <<EOF
978 $ cat > multirevs.py <<EOF
979 > from mercurial import commands, registrar
979 > from mercurial import commands, registrar
980 > cmdtable = {}
980 > cmdtable = {}
981 > command = registrar.command(cmdtable)
981 > command = registrar.command(cmdtable)
982 > """multirevs extension
982 > """multirevs extension
983 > Big multi-line module docstring."""
983 > Big multi-line module docstring."""
984 > @command(b'multirevs', [], b'ARG', norepo=True)
984 > @command(b'multirevs', [], b'ARG', norepo=True)
985 > def multirevs(ui, repo, arg, *args, **opts):
985 > def multirevs(ui, repo, arg, *args, **opts):
986 > """multirevs command"""
986 > """multirevs command"""
987 > EOF
987 > EOF
988 $ echo "multirevs = multirevs.py" >> $HGRCPATH
988 $ echo "multirevs = multirevs.py" >> $HGRCPATH
989
989
990 $ hg help multirevs | tail
990 $ hg help multirevs | tail
991 used):
991 used):
992
992
993 hg update :@
993 hg update :@
994
994
995 - 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
996 last revisions of the revset are used):
996 last revisions of the revset are used):
997
997
998 hg diff -r 1.3::1.5
998 hg diff -r 1.3::1.5
999
999
1000 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
1001
1001
1002
1002
1003
1003
1004
1004
1005
1005
1006
1006
1007 $ hg help -c multirevs
1007 $ hg help -c multirevs
1008 hg multirevs ARG
1008 hg multirevs ARG
1009
1009
1010 multirevs command
1010 multirevs command
1011
1011
1012 (some details hidden, use --verbose to show complete help)
1012 (some details hidden, use --verbose to show complete help)
1013
1013
1014
1014
1015
1015
1016 $ hg multirevs
1016 $ hg multirevs
1017 hg multirevs: invalid arguments
1017 hg multirevs: invalid arguments
1018 hg multirevs ARG
1018 hg multirevs ARG
1019
1019
1020 multirevs command
1020 multirevs command
1021
1021
1022 (use 'hg multirevs -h' to show more help)
1022 (use 'hg multirevs -h' to show more help)
1023 [10]
1023 [10]
1024
1024
1025
1025
1026
1026
1027 $ echo "multirevs = !" >> $HGRCPATH
1027 $ echo "multirevs = !" >> $HGRCPATH
1028
1028
1029 Issue811: Problem loading extensions twice (by site and by user)
1029 Issue811: Problem loading extensions twice (by site and by user)
1030
1030
1031 $ cat <<EOF >> $HGRCPATH
1031 $ cat <<EOF >> $HGRCPATH
1032 > mq =
1032 > mq =
1033 > strip =
1033 > strip =
1034 > hgext.mq =
1034 > hgext.mq =
1035 > hgext/mq =
1035 > hgext/mq =
1036 > EOF
1036 > EOF
1037
1037
1038 Show extensions:
1038 Show extensions:
1039 (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)
1040
1040
1041 #if no-extraextensions
1041 #if no-extraextensions
1042 $ hg debugextensions
1042 $ hg debugextensions
1043 mq
1043 mq
1044 strip
1044 strip
1045 #endif
1045 #endif
1046
1046
1047 For extensions, which name matches one of its commands, help
1047 For extensions, which name matches one of its commands, help
1048 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
1049 along with extension help itself
1049 along with extension help itself
1050
1050
1051 $ mkdir $TESTTMP/d
1051 $ mkdir $TESTTMP/d
1052 $ cat > $TESTTMP/d/dodo.py <<EOF
1052 $ cat > $TESTTMP/d/dodo.py <<EOF
1053 > """
1053 > """
1054 > This is an awesome 'dodo' extension. It does nothing and
1054 > This is an awesome 'dodo' extension. It does nothing and
1055 > writes 'Foo foo'
1055 > writes 'Foo foo'
1056 > """
1056 > """
1057 > from mercurial import commands, registrar
1057 > from mercurial import commands, registrar
1058 > cmdtable = {}
1058 > cmdtable = {}
1059 > command = registrar.command(cmdtable)
1059 > command = registrar.command(cmdtable)
1060 > @command(b'dodo', [], b'hg dodo')
1060 > @command(b'dodo', [], b'hg dodo')
1061 > def dodo(ui, *args, **kwargs):
1061 > def dodo(ui, *args, **kwargs):
1062 > """Does nothing"""
1062 > """Does nothing"""
1063 > ui.write(b"I do nothing. Yay\\n")
1063 > ui.write(b"I do nothing. Yay\\n")
1064 > @command(b'foofoo', [], b'hg foofoo')
1064 > @command(b'foofoo', [], b'hg foofoo')
1065 > def foofoo(ui, *args, **kwargs):
1065 > def foofoo(ui, *args, **kwargs):
1066 > """Writes 'Foo foo'"""
1066 > """Writes 'Foo foo'"""
1067 > ui.write(b"Foo foo\\n")
1067 > ui.write(b"Foo foo\\n")
1068 > EOF
1068 > EOF
1069 $ dodopath=$TESTTMP/d/dodo.py
1069 $ dodopath=$TESTTMP/d/dodo.py
1070
1070
1071 $ echo "dodo = $dodopath" >> $HGRCPATH
1071 $ echo "dodo = $dodopath" >> $HGRCPATH
1072
1072
1073 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
1074 $ hg help -e dodo
1074 $ hg help -e dodo
1075 dodo extension -
1075 dodo extension -
1076
1076
1077 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'
1078
1078
1079 list of commands:
1079 list of commands:
1080
1080
1081 dodo Does nothing
1081 dodo Does nothing
1082 foofoo Writes 'Foo foo'
1082 foofoo Writes 'Foo foo'
1083
1083
1084 (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)
1085
1085
1086 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
1087 extension help itself
1087 extension help itself
1088 $ hg help -v -e dodo
1088 $ hg help -v -e dodo
1089 dodo extension -
1089 dodo extension -
1090
1090
1091 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'
1092
1092
1093 list of commands:
1093 list of commands:
1094
1094
1095 dodo Does nothing
1095 dodo Does nothing
1096 foofoo Writes 'Foo foo'
1096 foofoo Writes 'Foo foo'
1097
1097
1098 global options ([+] can be repeated):
1098 global options ([+] can be repeated):
1099
1099
1100 -R --repository REPO repository root directory or name of overlay bundle
1100 -R --repository REPO repository root directory or name of overlay bundle
1101 file
1101 file
1102 --cwd DIR change working directory
1102 --cwd DIR change working directory
1103 -y --noninteractive do not prompt, automatically pick the first choice for
1103 -y --noninteractive do not prompt, automatically pick the first choice for
1104 all prompts
1104 all prompts
1105 -q --quiet suppress output
1105 -q --quiet suppress output
1106 -v --verbose enable additional output
1106 -v --verbose enable additional output
1107 --color TYPE when to colorize (boolean, always, auto, never, or
1107 --color TYPE when to colorize (boolean, always, auto, never, or
1108 debug)
1108 debug)
1109 --config CONFIG [+] set/override config option (use 'section.name=value')
1109 --config CONFIG [+] set/override config option (use 'section.name=value')
1110 --debug enable debugging output
1110 --debug enable debugging output
1111 --debugger start debugger
1111 --debugger start debugger
1112 --encoding ENCODE set the charset encoding (default: ascii)
1112 --encoding ENCODE set the charset encoding (default: ascii)
1113 --encodingmode MODE set the charset encoding mode (default: strict)
1113 --encodingmode MODE set the charset encoding mode (default: strict)
1114 --traceback always print a traceback on exception
1114 --traceback always print a traceback on exception
1115 --time time how long the command takes
1115 --time time how long the command takes
1116 --profile print command execution profile
1116 --profile print command execution profile
1117 --version output version information and exit
1117 --version output version information and exit
1118 -h --help display help and exit
1118 -h --help display help and exit
1119 --hidden consider hidden changesets
1119 --hidden consider hidden changesets
1120 --pager TYPE when to paginate (boolean, always, auto, or never)
1120 --pager TYPE when to paginate (boolean, always, auto, or never)
1121 (default: auto)
1121 (default: auto)
1122
1122
1123 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
1124 $ hg help -v dodo
1124 $ hg help -v dodo
1125 hg dodo
1125 hg dodo
1126
1126
1127 Does nothing
1127 Does nothing
1128
1128
1129 (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)
1130
1130
1131 options:
1131 options:
1132
1132
1133 --mq operate on patch repository
1133 --mq operate on patch repository
1134
1134
1135 global options ([+] can be repeated):
1135 global options ([+] can be repeated):
1136
1136
1137 -R --repository REPO repository root directory or name of overlay bundle
1137 -R --repository REPO repository root directory or name of overlay bundle
1138 file
1138 file
1139 --cwd DIR change working directory
1139 --cwd DIR change working directory
1140 -y --noninteractive do not prompt, automatically pick the first choice for
1140 -y --noninteractive do not prompt, automatically pick the first choice for
1141 all prompts
1141 all prompts
1142 -q --quiet suppress output
1142 -q --quiet suppress output
1143 -v --verbose enable additional output
1143 -v --verbose enable additional output
1144 --color TYPE when to colorize (boolean, always, auto, never, or
1144 --color TYPE when to colorize (boolean, always, auto, never, or
1145 debug)
1145 debug)
1146 --config CONFIG [+] set/override config option (use 'section.name=value')
1146 --config CONFIG [+] set/override config option (use 'section.name=value')
1147 --debug enable debugging output
1147 --debug enable debugging output
1148 --debugger start debugger
1148 --debugger start debugger
1149 --encoding ENCODE set the charset encoding (default: ascii)
1149 --encoding ENCODE set the charset encoding (default: ascii)
1150 --encodingmode MODE set the charset encoding mode (default: strict)
1150 --encodingmode MODE set the charset encoding mode (default: strict)
1151 --traceback always print a traceback on exception
1151 --traceback always print a traceback on exception
1152 --time time how long the command takes
1152 --time time how long the command takes
1153 --profile print command execution profile
1153 --profile print command execution profile
1154 --version output version information and exit
1154 --version output version information and exit
1155 -h --help display help and exit
1155 -h --help display help and exit
1156 --hidden consider hidden changesets
1156 --hidden consider hidden changesets
1157 --pager TYPE when to paginate (boolean, always, auto, or never)
1157 --pager TYPE when to paginate (boolean, always, auto, or never)
1158 (default: auto)
1158 (default: auto)
1159
1159
1160 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,
1161 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
1162 along with extension help
1162 along with extension help
1163 $ cat > $TESTTMP/d/dudu.py <<EOF
1163 $ cat > $TESTTMP/d/dudu.py <<EOF
1164 > """
1164 > """
1165 > This is an awesome 'dudu' extension. It does something and
1165 > This is an awesome 'dudu' extension. It does something and
1166 > also writes 'Beep beep'
1166 > also writes 'Beep beep'
1167 > """
1167 > """
1168 > from mercurial import commands, registrar
1168 > from mercurial import commands, registrar
1169 > cmdtable = {}
1169 > cmdtable = {}
1170 > command = registrar.command(cmdtable)
1170 > command = registrar.command(cmdtable)
1171 > @command(b'something', [], b'hg something')
1171 > @command(b'something', [], b'hg something')
1172 > def something(ui, *args, **kwargs):
1172 > def something(ui, *args, **kwargs):
1173 > """Does something"""
1173 > """Does something"""
1174 > ui.write(b"I do something. Yaaay\\n")
1174 > ui.write(b"I do something. Yaaay\\n")
1175 > @command(b'beep', [], b'hg beep')
1175 > @command(b'beep', [], b'hg beep')
1176 > def beep(ui, *args, **kwargs):
1176 > def beep(ui, *args, **kwargs):
1177 > """Writes 'Beep beep'"""
1177 > """Writes 'Beep beep'"""
1178 > ui.write(b"Beep beep\\n")
1178 > ui.write(b"Beep beep\\n")
1179 > EOF
1179 > EOF
1180 $ dudupath=$TESTTMP/d/dudu.py
1180 $ dudupath=$TESTTMP/d/dudu.py
1181
1181
1182 $ echo "dudu = $dudupath" >> $HGRCPATH
1182 $ echo "dudu = $dudupath" >> $HGRCPATH
1183
1183
1184 $ hg help -e dudu
1184 $ hg help -e dudu
1185 dudu extension -
1185 dudu extension -
1186
1186
1187 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
1188 beep'
1188 beep'
1189
1189
1190 list of commands:
1190 list of commands:
1191
1191
1192 beep Writes 'Beep beep'
1192 beep Writes 'Beep beep'
1193 something Does something
1193 something Does something
1194
1194
1195 (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)
1196
1196
1197 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,
1198 help options '-v' and '-v -e' should be equivalent
1198 help options '-v' and '-v -e' should be equivalent
1199 $ hg help -v dudu
1199 $ hg help -v dudu
1200 dudu extension -
1200 dudu extension -
1201
1201
1202 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
1203 beep'
1203 beep'
1204
1204
1205 list of commands:
1205 list of commands:
1206
1206
1207 beep Writes 'Beep beep'
1207 beep Writes 'Beep beep'
1208 something Does something
1208 something Does something
1209
1209
1210 global options ([+] can be repeated):
1210 global options ([+] can be repeated):
1211
1211
1212 -R --repository REPO repository root directory or name of overlay bundle
1212 -R --repository REPO repository root directory or name of overlay bundle
1213 file
1213 file
1214 --cwd DIR change working directory
1214 --cwd DIR change working directory
1215 -y --noninteractive do not prompt, automatically pick the first choice for
1215 -y --noninteractive do not prompt, automatically pick the first choice for
1216 all prompts
1216 all prompts
1217 -q --quiet suppress output
1217 -q --quiet suppress output
1218 -v --verbose enable additional output
1218 -v --verbose enable additional output
1219 --color TYPE when to colorize (boolean, always, auto, never, or
1219 --color TYPE when to colorize (boolean, always, auto, never, or
1220 debug)
1220 debug)
1221 --config CONFIG [+] set/override config option (use 'section.name=value')
1221 --config CONFIG [+] set/override config option (use 'section.name=value')
1222 --debug enable debugging output
1222 --debug enable debugging output
1223 --debugger start debugger
1223 --debugger start debugger
1224 --encoding ENCODE set the charset encoding (default: ascii)
1224 --encoding ENCODE set the charset encoding (default: ascii)
1225 --encodingmode MODE set the charset encoding mode (default: strict)
1225 --encodingmode MODE set the charset encoding mode (default: strict)
1226 --traceback always print a traceback on exception
1226 --traceback always print a traceback on exception
1227 --time time how long the command takes
1227 --time time how long the command takes
1228 --profile print command execution profile
1228 --profile print command execution profile
1229 --version output version information and exit
1229 --version output version information and exit
1230 -h --help display help and exit
1230 -h --help display help and exit
1231 --hidden consider hidden changesets
1231 --hidden consider hidden changesets
1232 --pager TYPE when to paginate (boolean, always, auto, or never)
1232 --pager TYPE when to paginate (boolean, always, auto, or never)
1233 (default: auto)
1233 (default: auto)
1234
1234
1235 $ hg help -v -e dudu
1235 $ hg help -v -e dudu
1236 dudu extension -
1236 dudu extension -
1237
1237
1238 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
1239 beep'
1239 beep'
1240
1240
1241 list of commands:
1241 list of commands:
1242
1242
1243 beep Writes 'Beep beep'
1243 beep Writes 'Beep beep'
1244 something Does something
1244 something Does something
1245
1245
1246 global options ([+] can be repeated):
1246 global options ([+] can be repeated):
1247
1247
1248 -R --repository REPO repository root directory or name of overlay bundle
1248 -R --repository REPO repository root directory or name of overlay bundle
1249 file
1249 file
1250 --cwd DIR change working directory
1250 --cwd DIR change working directory
1251 -y --noninteractive do not prompt, automatically pick the first choice for
1251 -y --noninteractive do not prompt, automatically pick the first choice for
1252 all prompts
1252 all prompts
1253 -q --quiet suppress output
1253 -q --quiet suppress output
1254 -v --verbose enable additional output
1254 -v --verbose enable additional output
1255 --color TYPE when to colorize (boolean, always, auto, never, or
1255 --color TYPE when to colorize (boolean, always, auto, never, or
1256 debug)
1256 debug)
1257 --config CONFIG [+] set/override config option (use 'section.name=value')
1257 --config CONFIG [+] set/override config option (use 'section.name=value')
1258 --debug enable debugging output
1258 --debug enable debugging output
1259 --debugger start debugger
1259 --debugger start debugger
1260 --encoding ENCODE set the charset encoding (default: ascii)
1260 --encoding ENCODE set the charset encoding (default: ascii)
1261 --encodingmode MODE set the charset encoding mode (default: strict)
1261 --encodingmode MODE set the charset encoding mode (default: strict)
1262 --traceback always print a traceback on exception
1262 --traceback always print a traceback on exception
1263 --time time how long the command takes
1263 --time time how long the command takes
1264 --profile print command execution profile
1264 --profile print command execution profile
1265 --version output version information and exit
1265 --version output version information and exit
1266 -h --help display help and exit
1266 -h --help display help and exit
1267 --hidden consider hidden changesets
1267 --hidden consider hidden changesets
1268 --pager TYPE when to paginate (boolean, always, auto, or never)
1268 --pager TYPE when to paginate (boolean, always, auto, or never)
1269 (default: auto)
1269 (default: auto)
1270
1270
1271 Disabled extension commands:
1271 Disabled extension commands:
1272
1272
1273 $ ORGHGRCPATH=$HGRCPATH
1273 $ ORGHGRCPATH=$HGRCPATH
1274 $ HGRCPATH=
1274 $ HGRCPATH=
1275 $ export HGRCPATH
1275 $ export HGRCPATH
1276 $ hg help email
1276 $ hg help email
1277 'email' is provided by the following extension:
1277 'email' is provided by the following extension:
1278
1278
1279 patchbomb command to send changesets as (a series of) patch emails
1279 patchbomb command to send changesets as (a series of) patch emails
1280
1280
1281 (use 'hg help extensions' for information on enabling extensions)
1281 (use 'hg help extensions' for information on enabling extensions)
1282
1282
1283
1283
1284 $ hg qdel
1284 $ hg qdel
1285 hg: unknown command 'qdel'
1285 hg: unknown command 'qdel'
1286 'qdelete' is provided by the following extension:
1286 'qdelete' is provided by the following extension:
1287
1287
1288 mq manage a stack of patches
1288 mq manage a stack of patches
1289
1289
1290 (use 'hg help extensions' for information on enabling extensions)
1290 (use 'hg help extensions' for information on enabling extensions)
1291 [255]
1291 [255]
1292
1292
1293
1293
1294 $ hg churn
1294 $ hg churn
1295 hg: unknown command 'churn'
1295 hg: unknown command 'churn'
1296 'churn' is provided by the following extension:
1296 'churn' is provided by the following extension:
1297
1297
1298 churn command to display statistics about repository history
1298 churn command to display statistics about repository history
1299
1299
1300 (use 'hg help extensions' for information on enabling extensions)
1300 (use 'hg help extensions' for information on enabling extensions)
1301 [255]
1301 [255]
1302
1302
1303
1303
1304
1304
1305 Disabled extensions:
1305 Disabled extensions:
1306
1306
1307 $ hg help churn
1307 $ hg help churn
1308 churn extension - command to display statistics about repository history
1308 churn extension - command to display statistics about repository history
1309
1309
1310 (use 'hg help extensions' for information on enabling extensions)
1310 (use 'hg help extensions' for information on enabling extensions)
1311
1311
1312 $ hg help patchbomb
1312 $ hg help patchbomb
1313 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
1314
1314
1315 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
1316 describes the series as a whole.
1316 describes the series as a whole.
1317
1317
1318 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
1319 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
1320 two or three body parts:
1320 two or three body parts:
1321
1321
1322 - The changeset description.
1322 - The changeset description.
1323 - [Optional] The result of running diffstat on the patch.
1323 - [Optional] The result of running diffstat on the patch.
1324 - The patch itself, as generated by 'hg export'.
1324 - The patch itself, as generated by 'hg export'.
1325
1325
1326 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
1327 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
1328 news readers, and in mail archives.
1328 news readers, and in mail archives.
1329
1329
1330 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
1331 file:
1331 file:
1332
1332
1333 [email]
1333 [email]
1334 from = My Name <my@email>
1334 from = My Name <my@email>
1335 to = recipient1, recipient2, ...
1335 to = recipient1, recipient2, ...
1336 cc = cc1, cc2, ...
1336 cc = cc1, cc2, ...
1337 bcc = bcc1, bcc2, ...
1337 bcc = bcc1, bcc2, ...
1338 reply-to = address1, address2, ...
1338 reply-to = address1, address2, ...
1339
1339
1340 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
1341 "[email]" address settings.
1341 "[email]" address settings.
1342
1342
1343 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
1344 patchbomb.
1344 patchbomb.
1345
1345
1346 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
1347 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
1348 patchbomb extension can automatically send patchbombs directly from the
1348 patchbomb extension can automatically send patchbombs directly from the
1349 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.
1350
1350
1351 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
1352 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
1353 never prompt by configuring an empty value:
1353 never prompt by configuring an empty value:
1354
1354
1355 [email]
1355 [email]
1356 cc =
1356 cc =
1357
1357
1358 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
1359 "patchbomb.intro" configuration option. The configuration is always
1359 "patchbomb.intro" configuration option. The configuration is always
1360 overwritten by command line flags like --intro and --desc:
1360 overwritten by command line flags like --intro and --desc:
1361
1361
1362 [patchbomb]
1362 [patchbomb]
1363 intro=auto # include introduction message if more than 1 patch (default)
1363 intro=auto # include introduction message if more than 1 patch (default)
1364 intro=never # never include an introduction message
1364 intro=never # never include an introduction message
1365 intro=always # always include an introduction message
1365 intro=always # always include an introduction message
1366
1366
1367 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
1368 specified by --flag option are exported as "{flags}" keyword:
1368 specified by --flag option are exported as "{flags}" keyword:
1369
1369
1370 [patchbomb]
1370 [patchbomb]
1371 flagtemplate = "{separate(' ',
1371 flagtemplate = "{separate(' ',
1372 ifeq(branch, 'default', '', branch|upper),
1372 ifeq(branch, 'default', '', branch|upper),
1373 flags)}"
1373 flags)}"
1374
1374
1375 You can set patchbomb to always ask for confirmation by setting
1375 You can set patchbomb to always ask for confirmation by setting
1376 "patchbomb.confirm" to true.
1376 "patchbomb.confirm" to true.
1377
1377
1378 (use 'hg help extensions' for information on enabling extensions)
1378 (use 'hg help extensions' for information on enabling extensions)
1379
1379
1380
1380
1381 Help can find unimported extensions
1382 -----------------------------------
1383
1384 XXX-PYOXIDIZER since the frozen binary does not have source directory tree,
1385 this make the checking for actual file under `hgext` a bit complicated. In
1386 addition these tests do some strange dance to ensure some other module are the
1387 first in `sys.path` (since the current install path is always in front
1388 otherwise) that are fragile and that does not match reality in the field. So
1389 for now we disable this test untill a deeper rework of that logic is done.
1390
1391 #if no-pyoxidizer
1392
1381 Broken disabled extension and command:
1393 Broken disabled extension and command:
1382
1394
1383 $ mkdir hgext
1395 $ mkdir hgext
1384 $ echo > hgext/__init__.py
1396 $ echo > hgext/__init__.py
1385 $ cat > hgext/broken.py <<NO_CHECK_EOF
1397 $ cat > hgext/broken.py <<NO_CHECK_EOF
1386 > "broken extension'
1398 > "broken extension'
1387 > NO_CHECK_EOF
1399 > NO_CHECK_EOF
1388 $ cat > path.py <<EOF
1400 $ cat > path.py <<EOF
1389 > import os
1401 > import os
1390 > import sys
1402 > import sys
1391 > sys.path.insert(0, os.environ['HGEXTPATH'])
1403 > sys.path.insert(0, os.environ['HGEXTPATH'])
1392 > EOF
1404 > EOF
1393 $ HGEXTPATH=`pwd`
1405 $ HGEXTPATH=`pwd`
1394 $ export HGEXTPATH
1406 $ export HGEXTPATH
1395
1407
1396 $ hg --config extensions.path=./path.py help broken
1408 $ hg --config extensions.path=./path.py help broken
1397 broken extension - (no help text available)
1409 broken extension - (no help text available)
1398
1410
1399 (use 'hg help extensions' for information on enabling extensions)
1411 (use 'hg help extensions' for information on enabling extensions)
1400
1412
1401
1413
1402 $ cat > hgext/forest.py <<EOF
1414 $ cat > hgext/forest.py <<EOF
1403 > cmdtable = None
1415 > cmdtable = None
1404 > @command()
1416 > @command()
1405 > def f():
1417 > def f():
1406 > pass
1418 > pass
1407 > @command(123)
1419 > @command(123)
1408 > def g():
1420 > def g():
1409 > pass
1421 > pass
1410 > EOF
1422 > EOF
1411 $ hg --config extensions.path=./path.py help foo
1423 $ hg --config extensions.path=./path.py help foo
1412 abort: no such help topic: foo
1424 abort: no such help topic: foo
1413 (try 'hg help --keyword foo')
1425 (try 'hg help --keyword foo')
1414 [255]
1426 [255]
1415
1427
1428 #endif
1429
1430 ---
1431
1416 $ cat > throw.py <<EOF
1432 $ cat > throw.py <<EOF
1417 > from mercurial import commands, registrar, util
1433 > from mercurial import commands, registrar, util
1418 > cmdtable = {}
1434 > cmdtable = {}
1419 > command = registrar.command(cmdtable)
1435 > command = registrar.command(cmdtable)
1420 > class Bogon(Exception): pass
1436 > class Bogon(Exception): pass
1421 > # NB: version should be bytes; simulating extension not ported to py3
1437 > # NB: version should be bytes; simulating extension not ported to py3
1422 > __version__ = '1.0.0'
1438 > __version__ = '1.0.0'
1423 > @command(b'throw', [], b'hg throw', norepo=True)
1439 > @command(b'throw', [], b'hg throw', norepo=True)
1424 > def throw(ui, **opts):
1440 > def throw(ui, **opts):
1425 > """throws an exception"""
1441 > """throws an exception"""
1426 > raise Bogon()
1442 > raise Bogon()
1427 > EOF
1443 > EOF
1428
1444
1429 Test extension without proper byteification of key attributes doesn't crash when
1445 Test extension without proper byteification of key attributes doesn't crash when
1430 accessed.
1446 accessed.
1431
1447
1432 $ hg version -v --config extensions.throw=throw.py | grep '^ '
1448 $ hg version -v --config extensions.throw=throw.py | grep '^ '
1433 throw external 1.0.0
1449 throw external 1.0.0
1434
1450
1435 No declared supported version, extension complains:
1451 No declared supported version, extension complains:
1436 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1452 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1437 ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0
1453 ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0
1438 ** which supports versions unknown of Mercurial.
1454 ** which supports versions unknown of Mercurial.
1439 ** Please disable "throw" and try your action again.
1455 ** Please disable "throw" and try your action again.
1440 ** If that fixes the bug please report it to the extension author.
1456 ** If that fixes the bug please report it to the extension author.
1441 ** Python * (glob)
1457 ** Python * (glob)
1442 ** Mercurial Distributed SCM * (glob)
1458 ** Mercurial Distributed SCM * (glob)
1443 ** Extensions loaded: throw 1.0.0
1459 ** Extensions loaded: throw 1.0.0
1444
1460
1445 empty declaration of supported version, extension complains (but doesn't choke if
1461 empty declaration of supported version, extension complains (but doesn't choke if
1446 the value is improperly a str instead of bytes):
1462 the value is improperly a str instead of bytes):
1447 $ echo "testedwith = ''" >> throw.py
1463 $ echo "testedwith = ''" >> throw.py
1448 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1464 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1449 ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0
1465 ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0
1450 ** which supports versions unknown of Mercurial.
1466 ** which supports versions unknown of Mercurial.
1451 ** Please disable "throw" and try your action again.
1467 ** Please disable "throw" and try your action again.
1452 ** If that fixes the bug please report it to the extension author.
1468 ** If that fixes the bug please report it to the extension author.
1453 ** Python * (glob)
1469 ** Python * (glob)
1454 ** Mercurial Distributed SCM (*) (glob)
1470 ** Mercurial Distributed SCM (*) (glob)
1455 ** Extensions loaded: throw 1.0.0
1471 ** Extensions loaded: throw 1.0.0
1456
1472
1457 If the extension specifies a buglink, show that (but don't choke if the value is
1473 If the extension specifies a buglink, show that (but don't choke if the value is
1458 improperly a str instead of bytes):
1474 improperly a str instead of bytes):
1459 $ echo 'buglink = "http://example.com/bts"' >> throw.py
1475 $ echo 'buglink = "http://example.com/bts"' >> throw.py
1460 $ rm -f throw.pyc throw.pyo
1476 $ rm -f throw.pyc throw.pyo
1461 $ rm -Rf __pycache__
1477 $ rm -Rf __pycache__
1462 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1478 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1463 ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0
1479 ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0
1464 ** which supports versions unknown of Mercurial.
1480 ** which supports versions unknown of Mercurial.
1465 ** Please disable "throw" and try your action again.
1481 ** Please disable "throw" and try your action again.
1466 ** If that fixes the bug please report it to http://example.com/bts
1482 ** If that fixes the bug please report it to http://example.com/bts
1467 ** Python * (glob)
1483 ** Python * (glob)
1468 ** Mercurial Distributed SCM (*) (glob)
1484 ** Mercurial Distributed SCM (*) (glob)
1469 ** Extensions loaded: throw 1.0.0
1485 ** Extensions loaded: throw 1.0.0
1470
1486
1471 If the extensions declare outdated versions, accuse the older extension first:
1487 If the extensions declare outdated versions, accuse the older extension first:
1472 $ echo "from mercurial import util" >> older.py
1488 $ echo "from mercurial import util" >> older.py
1473 $ echo "util.version = lambda:b'2.2'" >> older.py
1489 $ echo "util.version = lambda:b'2.2'" >> older.py
1474 $ echo "testedwith = b'1.9.3'" >> older.py
1490 $ echo "testedwith = b'1.9.3'" >> older.py
1475 $ echo "testedwith = b'2.1.1'" >> throw.py
1491 $ echo "testedwith = b'2.1.1'" >> throw.py
1476 $ rm -f throw.pyc throw.pyo
1492 $ rm -f throw.pyc throw.pyo
1477 $ rm -Rf __pycache__
1493 $ rm -Rf __pycache__
1478 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1494 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1479 > throw 2>&1 | egrep '^\*\*'
1495 > throw 2>&1 | egrep '^\*\*'
1480 ** Unknown exception encountered with possibly-broken third-party extension "older" (version N/A)
1496 ** Unknown exception encountered with possibly-broken third-party extension "older" (version N/A)
1481 ** which supports versions 1.9 of Mercurial.
1497 ** which supports versions 1.9 of Mercurial.
1482 ** Please disable "older" and try your action again.
1498 ** Please disable "older" and try your action again.
1483 ** If that fixes the bug please report it to the extension author.
1499 ** If that fixes the bug please report it to the extension author.
1484 ** Python * (glob)
1500 ** Python * (glob)
1485 ** Mercurial Distributed SCM (version 2.2)
1501 ** Mercurial Distributed SCM (version 2.2)
1486 ** Extensions loaded: older, throw 1.0.0
1502 ** Extensions loaded: older, throw 1.0.0
1487
1503
1488 One extension only tested with older, one only with newer versions:
1504 One extension only tested with older, one only with newer versions:
1489 $ echo "util.version = lambda:b'2.1'" >> older.py
1505 $ echo "util.version = lambda:b'2.1'" >> older.py
1490 $ rm -f older.pyc older.pyo
1506 $ rm -f older.pyc older.pyo
1491 $ rm -Rf __pycache__
1507 $ rm -Rf __pycache__
1492 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1508 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1493 > throw 2>&1 | egrep '^\*\*'
1509 > throw 2>&1 | egrep '^\*\*'
1494 ** Unknown exception encountered with possibly-broken third-party extension "older" (version N/A)
1510 ** Unknown exception encountered with possibly-broken third-party extension "older" (version N/A)
1495 ** which supports versions 1.9 of Mercurial.
1511 ** which supports versions 1.9 of Mercurial.
1496 ** Please disable "older" and try your action again.
1512 ** Please disable "older" and try your action again.
1497 ** If that fixes the bug please report it to the extension author.
1513 ** If that fixes the bug please report it to the extension author.
1498 ** Python * (glob)
1514 ** Python * (glob)
1499 ** Mercurial Distributed SCM (version 2.1)
1515 ** Mercurial Distributed SCM (version 2.1)
1500 ** Extensions loaded: older, throw 1.0.0
1516 ** Extensions loaded: older, throw 1.0.0
1501
1517
1502 Older extension is tested with current version, the other only with newer:
1518 Older extension is tested with current version, the other only with newer:
1503 $ echo "util.version = lambda:b'1.9.3'" >> older.py
1519 $ echo "util.version = lambda:b'1.9.3'" >> older.py
1504 $ rm -f older.pyc older.pyo
1520 $ rm -f older.pyc older.pyo
1505 $ rm -Rf __pycache__
1521 $ rm -Rf __pycache__
1506 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1522 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1507 > throw 2>&1 | egrep '^\*\*'
1523 > throw 2>&1 | egrep '^\*\*'
1508 ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0
1524 ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0
1509 ** which supports versions 2.1 of Mercurial.
1525 ** which supports versions 2.1 of Mercurial.
1510 ** Please disable "throw" and try your action again.
1526 ** Please disable "throw" and try your action again.
1511 ** If that fixes the bug please report it to http://example.com/bts
1527 ** If that fixes the bug please report it to http://example.com/bts
1512 ** Python * (glob)
1528 ** Python * (glob)
1513 ** Mercurial Distributed SCM (version 1.9.3)
1529 ** Mercurial Distributed SCM (version 1.9.3)
1514 ** Extensions loaded: older, throw 1.0.0
1530 ** Extensions loaded: older, throw 1.0.0
1515
1531
1516 Ability to point to a different point
1532 Ability to point to a different point
1517 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1533 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1518 > --config ui.supportcontact='Your Local Goat Lenders' throw 2>&1 | egrep '^\*\*'
1534 > --config ui.supportcontact='Your Local Goat Lenders' throw 2>&1 | egrep '^\*\*'
1519 ** unknown exception encountered, please report by visiting
1535 ** unknown exception encountered, please report by visiting
1520 ** Your Local Goat Lenders
1536 ** Your Local Goat Lenders
1521 ** Python * (glob)
1537 ** Python * (glob)
1522 ** Mercurial Distributed SCM (*) (glob)
1538 ** Mercurial Distributed SCM (*) (glob)
1523 ** Extensions loaded: older, throw 1.0.0
1539 ** Extensions loaded: older, throw 1.0.0
1524
1540
1525 Declare the version as supporting this hg version, show regular bts link:
1541 Declare the version as supporting this hg version, show regular bts link:
1526 $ hgver=`hg debuginstall -T '{hgver}'`
1542 $ hgver=`hg debuginstall -T '{hgver}'`
1527 $ echo 'testedwith = """'"$hgver"'"""' >> throw.py
1543 $ echo 'testedwith = """'"$hgver"'"""' >> throw.py
1528 $ if [ -z "$hgver" ]; then
1544 $ if [ -z "$hgver" ]; then
1529 > echo "unable to fetch a mercurial version. Make sure __version__ is correct";
1545 > echo "unable to fetch a mercurial version. Make sure __version__ is correct";
1530 > fi
1546 > fi
1531 $ rm -f throw.pyc throw.pyo
1547 $ rm -f throw.pyc throw.pyo
1532 $ rm -Rf __pycache__
1548 $ rm -Rf __pycache__
1533 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1549 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1534 ** unknown exception encountered, please report by visiting
1550 ** unknown exception encountered, please report by visiting
1535 ** https://mercurial-scm.org/wiki/BugTracker
1551 ** https://mercurial-scm.org/wiki/BugTracker
1536 ** Python * (glob)
1552 ** Python * (glob)
1537 ** Mercurial Distributed SCM (*) (glob)
1553 ** Mercurial Distributed SCM (*) (glob)
1538 ** Extensions loaded: throw 1.0.0
1554 ** Extensions loaded: throw 1.0.0
1539
1555
1540 Patch version is ignored during compatibility check
1556 Patch version is ignored during compatibility check
1541 $ echo "testedwith = b'3.2'" >> throw.py
1557 $ echo "testedwith = b'3.2'" >> throw.py
1542 $ echo "util.version = lambda:b'3.2.2'" >> throw.py
1558 $ echo "util.version = lambda:b'3.2.2'" >> throw.py
1543 $ rm -f throw.pyc throw.pyo
1559 $ rm -f throw.pyc throw.pyo
1544 $ rm -Rf __pycache__
1560 $ rm -Rf __pycache__
1545 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1561 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1546 ** unknown exception encountered, please report by visiting
1562 ** unknown exception encountered, please report by visiting
1547 ** https://mercurial-scm.org/wiki/BugTracker
1563 ** https://mercurial-scm.org/wiki/BugTracker
1548 ** Python * (glob)
1564 ** Python * (glob)
1549 ** Mercurial Distributed SCM (*) (glob)
1565 ** Mercurial Distributed SCM (*) (glob)
1550 ** Extensions loaded: throw 1.0.0
1566 ** Extensions loaded: throw 1.0.0
1551
1567
1552 Test version number support in 'hg version':
1568 Test version number support in 'hg version':
1553 $ echo '__version__ = (1, 2, 3)' >> throw.py
1569 $ echo '__version__ = (1, 2, 3)' >> throw.py
1554 $ rm -f throw.pyc throw.pyo
1570 $ rm -f throw.pyc throw.pyo
1555 $ rm -Rf __pycache__
1571 $ rm -Rf __pycache__
1556 $ hg version -v
1572 $ hg version -v
1557 Mercurial Distributed SCM (version *) (glob)
1573 Mercurial Distributed SCM (version *) (glob)
1558 (see https://mercurial-scm.org for more information)
1574 (see https://mercurial-scm.org for more information)
1559
1575
1560 Copyright (C) 2005-* Olivia Mackall and others (glob)
1576 Copyright (C) 2005-* Olivia Mackall and others (glob)
1561 This is free software; see the source for copying conditions. There is NO
1577 This is free software; see the source for copying conditions. There is NO
1562 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1578 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1563
1579
1564 Enabled extensions:
1580 Enabled extensions:
1565
1581
1566
1582
1567 $ hg version -v --config extensions.throw=throw.py
1583 $ hg version -v --config extensions.throw=throw.py
1568 Mercurial Distributed SCM (version *) (glob)
1584 Mercurial Distributed SCM (version *) (glob)
1569 (see https://mercurial-scm.org for more information)
1585 (see https://mercurial-scm.org for more information)
1570
1586
1571 Copyright (C) 2005-* Olivia Mackall and others (glob)
1587 Copyright (C) 2005-* Olivia Mackall and others (glob)
1572 This is free software; see the source for copying conditions. There is NO
1588 This is free software; see the source for copying conditions. There is NO
1573 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1589 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1574
1590
1575 Enabled extensions:
1591 Enabled extensions:
1576
1592
1577 throw external 1.2.3
1593 throw external 1.2.3
1578 $ echo 'getversion = lambda: b"1.twentythree"' >> throw.py
1594 $ echo 'getversion = lambda: b"1.twentythree"' >> throw.py
1579 $ rm -f throw.pyc throw.pyo
1595 $ rm -f throw.pyc throw.pyo
1580 $ rm -Rf __pycache__
1596 $ rm -Rf __pycache__
1581 $ hg version -v --config extensions.throw=throw.py --config extensions.strip=
1597 $ hg version -v --config extensions.throw=throw.py --config extensions.strip=
1582 Mercurial Distributed SCM (version *) (glob)
1598 Mercurial Distributed SCM (version *) (glob)
1583 (see https://mercurial-scm.org for more information)
1599 (see https://mercurial-scm.org for more information)
1584
1600
1585 Copyright (C) 2005-* Olivia Mackall and others (glob)
1601 Copyright (C) 2005-* Olivia Mackall and others (glob)
1586 This is free software; see the source for copying conditions. There is NO
1602 This is free software; see the source for copying conditions. There is NO
1587 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1603 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1588
1604
1589 Enabled extensions:
1605 Enabled extensions:
1590
1606
1591 strip internal
1607 strip internal
1592 throw external 1.twentythree
1608 throw external 1.twentythree
1593
1609
1594 $ hg version -q --config extensions.throw=throw.py
1610 $ hg version -q --config extensions.throw=throw.py
1595 Mercurial Distributed SCM (version *) (glob)
1611 Mercurial Distributed SCM (version *) (glob)
1596
1612
1597 Test template output:
1613 Test template output:
1598
1614
1599 $ hg version --config extensions.strip= -T'{extensions}'
1615 $ hg version --config extensions.strip= -T'{extensions}'
1600 strip
1616 strip
1601
1617
1602 Test JSON output of version:
1618 Test JSON output of version:
1603
1619
1604 $ hg version -Tjson
1620 $ hg version -Tjson
1605 [
1621 [
1606 {
1622 {
1607 "extensions": [],
1623 "extensions": [],
1608 "ver": "*" (glob)
1624 "ver": "*" (glob)
1609 }
1625 }
1610 ]
1626 ]
1611
1627
1612 $ hg version --config extensions.throw=throw.py -Tjson
1628 $ hg version --config extensions.throw=throw.py -Tjson
1613 [
1629 [
1614 {
1630 {
1615 "extensions": [{"bundled": false, "name": "throw", "ver": "1.twentythree"}],
1631 "extensions": [{"bundled": false, "name": "throw", "ver": "1.twentythree"}],
1616 "ver": "3.2.2"
1632 "ver": "3.2.2"
1617 }
1633 }
1618 ]
1634 ]
1619
1635
1620 $ hg version --config extensions.strip= -Tjson
1636 $ hg version --config extensions.strip= -Tjson
1621 [
1637 [
1622 {
1638 {
1623 "extensions": [{"bundled": true, "name": "strip", "ver": null}],
1639 "extensions": [{"bundled": true, "name": "strip", "ver": null}],
1624 "ver": "*" (glob)
1640 "ver": "*" (glob)
1625 }
1641 }
1626 ]
1642 ]
1627
1643
1628 Test template output of version:
1644 Test template output of version:
1629
1645
1630 $ hg version --config extensions.throw=throw.py --config extensions.strip= \
1646 $ hg version --config extensions.throw=throw.py --config extensions.strip= \
1631 > -T'{extensions % "{name} {pad(ver, 16)} ({if(bundled, "internal", "external")})\n"}'
1647 > -T'{extensions % "{name} {pad(ver, 16)} ({if(bundled, "internal", "external")})\n"}'
1632 strip (internal)
1648 strip (internal)
1633 throw 1.twentythree (external)
1649 throw 1.twentythree (external)
1634
1650
1635 Refuse to load extensions with minimum version requirements
1651 Refuse to load extensions with minimum version requirements
1636
1652
1637 $ cat > minversion1.py << EOF
1653 $ cat > minversion1.py << EOF
1638 > from mercurial import util
1654 > from mercurial import util
1639 > util.version = lambda: b'3.5.2'
1655 > util.version = lambda: b'3.5.2'
1640 > minimumhgversion = b'3.6'
1656 > minimumhgversion = b'3.6'
1641 > EOF
1657 > EOF
1642 $ hg --config extensions.minversion=minversion1.py version
1658 $ hg --config extensions.minversion=minversion1.py version
1643 (third party extension minversion requires version 3.6 or newer of Mercurial (current: 3.5.2); disabling)
1659 (third party extension minversion requires version 3.6 or newer of Mercurial (current: 3.5.2); disabling)
1644 Mercurial Distributed SCM (version 3.5.2)
1660 Mercurial Distributed SCM (version 3.5.2)
1645 (see https://mercurial-scm.org for more information)
1661 (see https://mercurial-scm.org for more information)
1646
1662
1647 Copyright (C) 2005-* Olivia Mackall and others (glob)
1663 Copyright (C) 2005-* Olivia Mackall and others (glob)
1648 This is free software; see the source for copying conditions. There is NO
1664 This is free software; see the source for copying conditions. There is NO
1649 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1665 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1650
1666
1651 $ cat > minversion2.py << EOF
1667 $ cat > minversion2.py << EOF
1652 > from mercurial import util
1668 > from mercurial import util
1653 > util.version = lambda: b'3.6'
1669 > util.version = lambda: b'3.6'
1654 > minimumhgversion = b'3.7'
1670 > minimumhgversion = b'3.7'
1655 > EOF
1671 > EOF
1656 $ hg --config extensions.minversion=minversion2.py version 2>&1 | egrep '\(third'
1672 $ hg --config extensions.minversion=minversion2.py version 2>&1 | egrep '\(third'
1657 (third party extension minversion requires version 3.7 or newer of Mercurial (current: 3.6); disabling)
1673 (third party extension minversion requires version 3.7 or newer of Mercurial (current: 3.6); disabling)
1658
1674
1659 Can load version that is only off by point release
1675 Can load version that is only off by point release
1660
1676
1661 $ cat > minversion2.py << EOF
1677 $ cat > minversion2.py << EOF
1662 > from mercurial import util
1678 > from mercurial import util
1663 > util.version = lambda: b'3.6.1'
1679 > util.version = lambda: b'3.6.1'
1664 > minimumhgversion = b'3.6'
1680 > minimumhgversion = b'3.6'
1665 > EOF
1681 > EOF
1666 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1682 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1667 [1]
1683 [1]
1668
1684
1669 Can load minimum version identical to current
1685 Can load minimum version identical to current
1670
1686
1671 $ cat > minversion3.py << EOF
1687 $ cat > minversion3.py << EOF
1672 > from mercurial import util
1688 > from mercurial import util
1673 > util.version = lambda: b'3.5'
1689 > util.version = lambda: b'3.5'
1674 > minimumhgversion = b'3.5'
1690 > minimumhgversion = b'3.5'
1675 > EOF
1691 > EOF
1676 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1692 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1677 [1]
1693 [1]
1678
1694
1679 Restore HGRCPATH
1695 Restore HGRCPATH
1680
1696
1681 $ HGRCPATH=$ORGHGRCPATH
1697 $ HGRCPATH=$ORGHGRCPATH
1682 $ export HGRCPATH
1698 $ export HGRCPATH
1683
1699
1684 Commands handling multiple repositories at a time should invoke only
1700 Commands handling multiple repositories at a time should invoke only
1685 "reposetup()" of extensions enabling in the target repository.
1701 "reposetup()" of extensions enabling in the target repository.
1686
1702
1687 $ mkdir reposetup-test
1703 $ mkdir reposetup-test
1688 $ cd reposetup-test
1704 $ cd reposetup-test
1689
1705
1690 $ cat > $TESTTMP/reposetuptest.py <<EOF
1706 $ cat > $TESTTMP/reposetuptest.py <<EOF
1691 > from mercurial import extensions
1707 > from mercurial import extensions
1692 > def reposetup(ui, repo):
1708 > def reposetup(ui, repo):
1693 > ui.write(b'reposetup() for %s\n' % (repo.root))
1709 > ui.write(b'reposetup() for %s\n' % (repo.root))
1694 > ui.flush()
1710 > ui.flush()
1695 > EOF
1711 > EOF
1696 $ hg init src
1712 $ hg init src
1697 $ echo a > src/a
1713 $ echo a > src/a
1698 $ hg -R src commit -Am '#0 at src/a'
1714 $ hg -R src commit -Am '#0 at src/a'
1699 adding a
1715 adding a
1700 $ echo '[extensions]' >> src/.hg/hgrc
1716 $ echo '[extensions]' >> src/.hg/hgrc
1701 $ echo '# enable extension locally' >> src/.hg/hgrc
1717 $ echo '# enable extension locally' >> src/.hg/hgrc
1702 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
1718 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
1703 $ hg -R src status
1719 $ hg -R src status
1704 reposetup() for $TESTTMP/reposetup-test/src
1720 reposetup() for $TESTTMP/reposetup-test/src
1705 reposetup() for $TESTTMP/reposetup-test/src (chg !)
1721 reposetup() for $TESTTMP/reposetup-test/src (chg !)
1706
1722
1707 #if no-extraextensions
1723 #if no-extraextensions
1708 $ hg --cwd src debugextensions
1724 $ hg --cwd src debugextensions
1709 reposetup() for $TESTTMP/reposetup-test/src
1725 reposetup() for $TESTTMP/reposetup-test/src
1710 dodo (untested!)
1726 dodo (untested!)
1711 dudu (untested!)
1727 dudu (untested!)
1712 mq
1728 mq
1713 reposetuptest (untested!)
1729 reposetuptest (untested!)
1714 strip
1730 strip
1715 #endif
1731 #endif
1716
1732
1717 $ hg clone -U src clone-dst1
1733 $ hg clone -U src clone-dst1
1718 reposetup() for $TESTTMP/reposetup-test/src
1734 reposetup() for $TESTTMP/reposetup-test/src
1719 $ hg init push-dst1
1735 $ hg init push-dst1
1720 $ hg -q -R src push push-dst1
1736 $ hg -q -R src push push-dst1
1721 reposetup() for $TESTTMP/reposetup-test/src
1737 reposetup() for $TESTTMP/reposetup-test/src
1722 $ hg init pull-src1
1738 $ hg init pull-src1
1723 $ hg -q -R pull-src1 pull src
1739 $ hg -q -R pull-src1 pull src
1724 reposetup() for $TESTTMP/reposetup-test/src
1740 reposetup() for $TESTTMP/reposetup-test/src
1725
1741
1726 $ cat <<EOF >> $HGRCPATH
1742 $ cat <<EOF >> $HGRCPATH
1727 > [extensions]
1743 > [extensions]
1728 > # disable extension globally and explicitly
1744 > # disable extension globally and explicitly
1729 > reposetuptest = !
1745 > reposetuptest = !
1730 > EOF
1746 > EOF
1731 $ hg clone -U src clone-dst2
1747 $ hg clone -U src clone-dst2
1732 reposetup() for $TESTTMP/reposetup-test/src
1748 reposetup() for $TESTTMP/reposetup-test/src
1733 $ hg init push-dst2
1749 $ hg init push-dst2
1734 $ hg -q -R src push push-dst2
1750 $ hg -q -R src push push-dst2
1735 reposetup() for $TESTTMP/reposetup-test/src
1751 reposetup() for $TESTTMP/reposetup-test/src
1736 $ hg init pull-src2
1752 $ hg init pull-src2
1737 $ hg -q -R pull-src2 pull src
1753 $ hg -q -R pull-src2 pull src
1738 reposetup() for $TESTTMP/reposetup-test/src
1754 reposetup() for $TESTTMP/reposetup-test/src
1739
1755
1740 $ cat <<EOF >> $HGRCPATH
1756 $ cat <<EOF >> $HGRCPATH
1741 > [extensions]
1757 > [extensions]
1742 > # enable extension globally
1758 > # enable extension globally
1743 > reposetuptest = $TESTTMP/reposetuptest.py
1759 > reposetuptest = $TESTTMP/reposetuptest.py
1744 > EOF
1760 > EOF
1745 $ hg clone -U src clone-dst3
1761 $ hg clone -U src clone-dst3
1746 reposetup() for $TESTTMP/reposetup-test/src
1762 reposetup() for $TESTTMP/reposetup-test/src
1747 reposetup() for $TESTTMP/reposetup-test/clone-dst3
1763 reposetup() for $TESTTMP/reposetup-test/clone-dst3
1748 $ hg init push-dst3
1764 $ hg init push-dst3
1749 reposetup() for $TESTTMP/reposetup-test/push-dst3
1765 reposetup() for $TESTTMP/reposetup-test/push-dst3
1750 $ hg -q -R src push push-dst3
1766 $ hg -q -R src push push-dst3
1751 reposetup() for $TESTTMP/reposetup-test/src
1767 reposetup() for $TESTTMP/reposetup-test/src
1752 reposetup() for $TESTTMP/reposetup-test/push-dst3
1768 reposetup() for $TESTTMP/reposetup-test/push-dst3
1753 $ hg init pull-src3
1769 $ hg init pull-src3
1754 reposetup() for $TESTTMP/reposetup-test/pull-src3
1770 reposetup() for $TESTTMP/reposetup-test/pull-src3
1755 $ hg -q -R pull-src3 pull src
1771 $ hg -q -R pull-src3 pull src
1756 reposetup() for $TESTTMP/reposetup-test/pull-src3
1772 reposetup() for $TESTTMP/reposetup-test/pull-src3
1757 reposetup() for $TESTTMP/reposetup-test/src
1773 reposetup() for $TESTTMP/reposetup-test/src
1758
1774
1759 $ echo '[extensions]' >> src/.hg/hgrc
1775 $ echo '[extensions]' >> src/.hg/hgrc
1760 $ echo '# disable extension locally' >> src/.hg/hgrc
1776 $ echo '# disable extension locally' >> src/.hg/hgrc
1761 $ echo 'reposetuptest = !' >> src/.hg/hgrc
1777 $ echo 'reposetuptest = !' >> src/.hg/hgrc
1762 $ hg clone -U src clone-dst4
1778 $ hg clone -U src clone-dst4
1763 reposetup() for $TESTTMP/reposetup-test/clone-dst4
1779 reposetup() for $TESTTMP/reposetup-test/clone-dst4
1764 $ hg init push-dst4
1780 $ hg init push-dst4
1765 reposetup() for $TESTTMP/reposetup-test/push-dst4
1781 reposetup() for $TESTTMP/reposetup-test/push-dst4
1766 $ hg -q -R src push push-dst4
1782 $ hg -q -R src push push-dst4
1767 reposetup() for $TESTTMP/reposetup-test/push-dst4
1783 reposetup() for $TESTTMP/reposetup-test/push-dst4
1768 $ hg init pull-src4
1784 $ hg init pull-src4
1769 reposetup() for $TESTTMP/reposetup-test/pull-src4
1785 reposetup() for $TESTTMP/reposetup-test/pull-src4
1770 $ hg -q -R pull-src4 pull src
1786 $ hg -q -R pull-src4 pull src
1771 reposetup() for $TESTTMP/reposetup-test/pull-src4
1787 reposetup() for $TESTTMP/reposetup-test/pull-src4
1772
1788
1773 disabling in command line overlays with all configuration
1789 disabling in command line overlays with all configuration
1774 $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
1790 $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
1775 $ hg --config extensions.reposetuptest=! init push-dst5
1791 $ hg --config extensions.reposetuptest=! init push-dst5
1776 $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
1792 $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
1777 $ hg --config extensions.reposetuptest=! init pull-src5
1793 $ hg --config extensions.reposetuptest=! init pull-src5
1778 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
1794 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
1779
1795
1780 $ cat <<EOF >> $HGRCPATH
1796 $ cat <<EOF >> $HGRCPATH
1781 > [extensions]
1797 > [extensions]
1782 > # disable extension globally and explicitly
1798 > # disable extension globally and explicitly
1783 > reposetuptest = !
1799 > reposetuptest = !
1784 > EOF
1800 > EOF
1785 $ hg init parent
1801 $ hg init parent
1786 $ hg init parent/sub1
1802 $ hg init parent/sub1
1787 $ echo 1 > parent/sub1/1
1803 $ echo 1 > parent/sub1/1
1788 $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
1804 $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
1789 adding 1
1805 adding 1
1790 $ hg init parent/sub2
1806 $ hg init parent/sub2
1791 $ hg init parent/sub2/sub21
1807 $ hg init parent/sub2/sub21
1792 $ echo 21 > parent/sub2/sub21/21
1808 $ echo 21 > parent/sub2/sub21/21
1793 $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
1809 $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
1794 adding 21
1810 adding 21
1795 $ cat > parent/sub2/.hgsub <<EOF
1811 $ cat > parent/sub2/.hgsub <<EOF
1796 > sub21 = sub21
1812 > sub21 = sub21
1797 > EOF
1813 > EOF
1798 $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
1814 $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
1799 adding .hgsub
1815 adding .hgsub
1800 $ hg init parent/sub3
1816 $ hg init parent/sub3
1801 $ echo 3 > parent/sub3/3
1817 $ echo 3 > parent/sub3/3
1802 $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
1818 $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
1803 adding 3
1819 adding 3
1804 $ cat > parent/.hgsub <<EOF
1820 $ cat > parent/.hgsub <<EOF
1805 > sub1 = sub1
1821 > sub1 = sub1
1806 > sub2 = sub2
1822 > sub2 = sub2
1807 > sub3 = sub3
1823 > sub3 = sub3
1808 > EOF
1824 > EOF
1809 $ hg -R parent commit -Am '#0 at parent'
1825 $ hg -R parent commit -Am '#0 at parent'
1810 adding .hgsub
1826 adding .hgsub
1811 $ echo '[extensions]' >> parent/.hg/hgrc
1827 $ echo '[extensions]' >> parent/.hg/hgrc
1812 $ echo '# enable extension locally' >> parent/.hg/hgrc
1828 $ echo '# enable extension locally' >> parent/.hg/hgrc
1813 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
1829 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
1814 $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
1830 $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
1815 $ hg -R parent status -S -A
1831 $ hg -R parent status -S -A
1816 reposetup() for $TESTTMP/reposetup-test/parent
1832 reposetup() for $TESTTMP/reposetup-test/parent
1817 reposetup() for $TESTTMP/reposetup-test/parent/sub2
1833 reposetup() for $TESTTMP/reposetup-test/parent/sub2
1818 C .hgsub
1834 C .hgsub
1819 C .hgsubstate
1835 C .hgsubstate
1820 C sub1/1
1836 C sub1/1
1821 C sub2/.hgsub
1837 C sub2/.hgsub
1822 C sub2/.hgsubstate
1838 C sub2/.hgsubstate
1823 C sub2/sub21/21
1839 C sub2/sub21/21
1824 C sub3/3
1840 C sub3/3
1825
1841
1826 $ cd ..
1842 $ cd ..
1827
1843
1828 Prohibit registration of commands that don't use @command (issue5137)
1844 Prohibit registration of commands that don't use @command (issue5137)
1829
1845
1830 $ hg init deprecated
1846 $ hg init deprecated
1831 $ cd deprecated
1847 $ cd deprecated
1832
1848
1833 $ cat <<EOF > deprecatedcmd.py
1849 $ cat <<EOF > deprecatedcmd.py
1834 > def deprecatedcmd(repo, ui):
1850 > def deprecatedcmd(repo, ui):
1835 > pass
1851 > pass
1836 > cmdtable = {
1852 > cmdtable = {
1837 > b'deprecatedcmd': (deprecatedcmd, [], b''),
1853 > b'deprecatedcmd': (deprecatedcmd, [], b''),
1838 > }
1854 > }
1839 > EOF
1855 > EOF
1840 $ cat <<EOF > .hg/hgrc
1856 $ cat <<EOF > .hg/hgrc
1841 > [extensions]
1857 > [extensions]
1842 > deprecatedcmd = `pwd`/deprecatedcmd.py
1858 > deprecatedcmd = `pwd`/deprecatedcmd.py
1843 > mq = !
1859 > mq = !
1844 > hgext.mq = !
1860 > hgext.mq = !
1845 > hgext/mq = !
1861 > hgext/mq = !
1846 > EOF
1862 > EOF
1847
1863
1848 $ hg deprecatedcmd > /dev/null
1864 $ hg deprecatedcmd > /dev/null
1849 *** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo
1865 *** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo
1850 *** (use @command decorator to register 'deprecatedcmd')
1866 *** (use @command decorator to register 'deprecatedcmd')
1851 hg: unknown command 'deprecatedcmd'
1867 hg: unknown command 'deprecatedcmd'
1852 (use 'hg help' for a list of commands)
1868 (use 'hg help' for a list of commands)
1853 [10]
1869 [10]
1854
1870
1855 the extension shouldn't be loaded at all so the mq works:
1871 the extension shouldn't be loaded at all so the mq works:
1856
1872
1857 $ hg qseries --config extensions.mq= > /dev/null
1873 $ hg qseries --config extensions.mq= > /dev/null
1858 *** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo
1874 *** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo
1859 *** (use @command decorator to register 'deprecatedcmd')
1875 *** (use @command decorator to register 'deprecatedcmd')
1860
1876
1861 $ cd ..
1877 $ cd ..
1862
1878
1863 Test synopsis and docstring extending
1879 Test synopsis and docstring extending
1864
1880
1865 $ hg init exthelp
1881 $ hg init exthelp
1866 $ cat > exthelp.py <<EOF
1882 $ cat > exthelp.py <<EOF
1867 > from mercurial import commands, extensions
1883 > from mercurial import commands, extensions
1868 > def exbookmarks(orig, *args, **opts):
1884 > def exbookmarks(orig, *args, **opts):
1869 > return orig(*args, **opts)
1885 > return orig(*args, **opts)
1870 > def uisetup(ui):
1886 > def uisetup(ui):
1871 > synopsis = b' GREPME [--foo] [-x]'
1887 > synopsis = b' GREPME [--foo] [-x]'
1872 > docstring = '''
1888 > docstring = '''
1873 > GREPME make sure that this is in the help!
1889 > GREPME make sure that this is in the help!
1874 > '''
1890 > '''
1875 > extensions.wrapcommand(commands.table, b'bookmarks', exbookmarks,
1891 > extensions.wrapcommand(commands.table, b'bookmarks', exbookmarks,
1876 > synopsis, docstring)
1892 > synopsis, docstring)
1877 > EOF
1893 > EOF
1878 $ abspath=`pwd`/exthelp.py
1894 $ abspath=`pwd`/exthelp.py
1879 $ echo '[extensions]' >> $HGRCPATH
1895 $ echo '[extensions]' >> $HGRCPATH
1880 $ echo "exthelp = $abspath" >> $HGRCPATH
1896 $ echo "exthelp = $abspath" >> $HGRCPATH
1881 $ cd exthelp
1897 $ cd exthelp
1882 $ hg help bookmarks | grep GREPME
1898 $ hg help bookmarks | grep GREPME
1883 hg bookmarks [OPTIONS]... [NAME]... GREPME [--foo] [-x]
1899 hg bookmarks [OPTIONS]... [NAME]... GREPME [--foo] [-x]
1884 GREPME make sure that this is in the help!
1900 GREPME make sure that this is in the help!
1885 $ cd ..
1901 $ cd ..
1886
1902
1887 Prohibit the use of unicode strings as the default value of options
1903 Prohibit the use of unicode strings as the default value of options
1888
1904
1889 $ hg init $TESTTMP/opt-unicode-default
1905 $ hg init $TESTTMP/opt-unicode-default
1890
1906
1891 $ cat > $TESTTMP/test_unicode_default_value.py << EOF
1907 $ cat > $TESTTMP/test_unicode_default_value.py << EOF
1892 > from __future__ import print_function
1908 > from __future__ import print_function
1893 > from mercurial import registrar
1909 > from mercurial import registrar
1894 > cmdtable = {}
1910 > cmdtable = {}
1895 > command = registrar.command(cmdtable)
1911 > command = registrar.command(cmdtable)
1896 > @command(b'dummy', [(b'', b'opt', u'value', u'help')], 'ext [OPTIONS]')
1912 > @command(b'dummy', [(b'', b'opt', u'value', u'help')], 'ext [OPTIONS]')
1897 > def ext(*args, **opts):
1913 > def ext(*args, **opts):
1898 > print(opts[b'opt'], flush=True)
1914 > print(opts[b'opt'], flush=True)
1899 > EOF
1915 > EOF
1900 $ "$PYTHON" $TESTTMP/unflush.py $TESTTMP/test_unicode_default_value.py
1916 $ "$PYTHON" $TESTTMP/unflush.py $TESTTMP/test_unicode_default_value.py
1901 $ cat > $TESTTMP/opt-unicode-default/.hg/hgrc << EOF
1917 $ cat > $TESTTMP/opt-unicode-default/.hg/hgrc << EOF
1902 > [extensions]
1918 > [extensions]
1903 > test_unicode_default_value = $TESTTMP/test_unicode_default_value.py
1919 > test_unicode_default_value = $TESTTMP/test_unicode_default_value.py
1904 > EOF
1920 > EOF
1905 $ hg -R $TESTTMP/opt-unicode-default dummy
1921 $ hg -R $TESTTMP/opt-unicode-default dummy
1906 *** failed to import extension test_unicode_default_value from $TESTTMP/test_unicode_default_value.py: unicode *'value' found in cmdtable.dummy (glob)
1922 *** failed to import extension test_unicode_default_value from $TESTTMP/test_unicode_default_value.py: unicode *'value' found in cmdtable.dummy (glob)
1907 *** (use b'' to make it byte string)
1923 *** (use b'' to make it byte string)
1908 hg: unknown command 'dummy'
1924 hg: unknown command 'dummy'
1909 (did you mean summary?)
1925 (did you mean summary?)
1910 [10]
1926 [10]
General Comments 0
You need to be logged in to leave comments. Login now