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