##// END OF EJS Templates
demandimport: support "absolute_import" for external libraries (issue4029)...
FUJIWARA Katsunori -
r19932:e3a5922e default
parent child Browse files
Show More
@@ -1,155 +1,156 b''
1 # demandimport.py - global demand-loading of modules for Mercurial
1 # demandimport.py - global demand-loading of modules for Mercurial
2 #
2 #
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 '''
8 '''
9 demandimport - automatic demandloading of modules
9 demandimport - automatic demandloading of modules
10
10
11 To enable this module, do:
11 To enable this module, do:
12
12
13 import demandimport; demandimport.enable()
13 import demandimport; demandimport.enable()
14
14
15 Imports of the following forms will be demand-loaded:
15 Imports of the following forms will be demand-loaded:
16
16
17 import a, b.c
17 import a, b.c
18 import a.b as c
18 import a.b as c
19 from a import b,c # a will be loaded immediately
19 from a import b,c # a will be loaded immediately
20
20
21 These imports will not be delayed:
21 These imports will not be delayed:
22
22
23 from a import *
23 from a import *
24 b = __import__(a)
24 b = __import__(a)
25 '''
25 '''
26
26
27 import __builtin__
27 import __builtin__
28 _origimport = __import__
28 _origimport = __import__
29
29
30 nothing = object()
30 nothing = object()
31
31
32 try:
32 try:
33 _origimport(__builtin__.__name__, {}, {}, None, -1)
33 _origimport(__builtin__.__name__, {}, {}, None, -1)
34 except TypeError: # no level argument
34 except TypeError: # no level argument
35 def _import(name, globals, locals, fromlist, level):
35 def _import(name, globals, locals, fromlist, level):
36 "call _origimport with no level argument"
36 "call _origimport with no level argument"
37 return _origimport(name, globals, locals, fromlist)
37 return _origimport(name, globals, locals, fromlist)
38 else:
38 else:
39 _import = _origimport
39 _import = _origimport
40
40
41 class _demandmod(object):
41 class _demandmod(object):
42 """module demand-loader and proxy"""
42 """module demand-loader and proxy"""
43 def __init__(self, name, globals, locals):
43 def __init__(self, name, globals, locals, level=-1):
44 if '.' in name:
44 if '.' in name:
45 head, rest = name.split('.', 1)
45 head, rest = name.split('.', 1)
46 after = [rest]
46 after = [rest]
47 else:
47 else:
48 head = name
48 head = name
49 after = []
49 after = []
50 object.__setattr__(self, "_data", (head, globals, locals, after))
50 object.__setattr__(self, "_data",
51 (head, globals, locals, after, level))
51 object.__setattr__(self, "_module", None)
52 object.__setattr__(self, "_module", None)
52 def _extend(self, name):
53 def _extend(self, name):
53 """add to the list of submodules to load"""
54 """add to the list of submodules to load"""
54 self._data[3].append(name)
55 self._data[3].append(name)
55 def _load(self):
56 def _load(self):
56 if not self._module:
57 if not self._module:
57 head, globals, locals, after = self._data
58 head, globals, locals, after, level = self._data
58 mod = _origimport(head, globals, locals)
59 mod = _import(head, globals, locals, None, level)
59 # load submodules
60 # load submodules
60 def subload(mod, p):
61 def subload(mod, p):
61 h, t = p, None
62 h, t = p, None
62 if '.' in p:
63 if '.' in p:
63 h, t = p.split('.', 1)
64 h, t = p.split('.', 1)
64 if getattr(mod, h, nothing) is nothing:
65 if getattr(mod, h, nothing) is nothing:
65 setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__))
66 setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__))
66 elif t:
67 elif t:
67 subload(getattr(mod, h), t)
68 subload(getattr(mod, h), t)
68
69
69 for x in after:
70 for x in after:
70 subload(mod, x)
71 subload(mod, x)
71
72
72 # are we in the locals dictionary still?
73 # are we in the locals dictionary still?
73 if locals and locals.get(head) == self:
74 if locals and locals.get(head) == self:
74 locals[head] = mod
75 locals[head] = mod
75 object.__setattr__(self, "_module", mod)
76 object.__setattr__(self, "_module", mod)
76
77
77 def __repr__(self):
78 def __repr__(self):
78 if self._module:
79 if self._module:
79 return "<proxied module '%s'>" % self._data[0]
80 return "<proxied module '%s'>" % self._data[0]
80 return "<unloaded module '%s'>" % self._data[0]
81 return "<unloaded module '%s'>" % self._data[0]
81 def __call__(self, *args, **kwargs):
82 def __call__(self, *args, **kwargs):
82 raise TypeError("%s object is not callable" % repr(self))
83 raise TypeError("%s object is not callable" % repr(self))
83 def __getattribute__(self, attr):
84 def __getattribute__(self, attr):
84 if attr in ('_data', '_extend', '_load', '_module'):
85 if attr in ('_data', '_extend', '_load', '_module'):
85 return object.__getattribute__(self, attr)
86 return object.__getattribute__(self, attr)
86 self._load()
87 self._load()
87 return getattr(self._module, attr)
88 return getattr(self._module, attr)
88 def __setattr__(self, attr, val):
89 def __setattr__(self, attr, val):
89 self._load()
90 self._load()
90 setattr(self._module, attr, val)
91 setattr(self._module, attr, val)
91
92
92 def _demandimport(name, globals=None, locals=None, fromlist=None, level=-1):
93 def _demandimport(name, globals=None, locals=None, fromlist=None, level=-1):
93 if not locals or name in ignore or fromlist == ('*',):
94 if not locals or name in ignore or fromlist == ('*',):
94 # these cases we can't really delay
95 # these cases we can't really delay
95 return _import(name, globals, locals, fromlist, level)
96 return _import(name, globals, locals, fromlist, level)
96 elif not fromlist:
97 elif not fromlist:
97 # import a [as b]
98 # import a [as b]
98 if '.' in name: # a.b
99 if '.' in name: # a.b
99 base, rest = name.split('.', 1)
100 base, rest = name.split('.', 1)
100 # email.__init__ loading email.mime
101 # email.__init__ loading email.mime
101 if globals and globals.get('__name__', None) == base:
102 if globals and globals.get('__name__', None) == base:
102 return _import(name, globals, locals, fromlist, level)
103 return _import(name, globals, locals, fromlist, level)
103 # if a is already demand-loaded, add b to its submodule list
104 # if a is already demand-loaded, add b to its submodule list
104 if base in locals:
105 if base in locals:
105 if isinstance(locals[base], _demandmod):
106 if isinstance(locals[base], _demandmod):
106 locals[base]._extend(rest)
107 locals[base]._extend(rest)
107 return locals[base]
108 return locals[base]
108 return _demandmod(name, globals, locals)
109 return _demandmod(name, globals, locals, level)
109 else:
110 else:
110 if level != -1:
111 if level != -1:
111 # from . import b,c,d or from .a import b,c,d
112 # from . import b,c,d or from .a import b,c,d
112 return _origimport(name, globals, locals, fromlist, level)
113 return _origimport(name, globals, locals, fromlist, level)
113 # from a import b,c,d
114 # from a import b,c,d
114 mod = _origimport(name, globals, locals)
115 mod = _origimport(name, globals, locals)
115 # recurse down the module chain
116 # recurse down the module chain
116 for comp in name.split('.')[1:]:
117 for comp in name.split('.')[1:]:
117 if getattr(mod, comp, nothing) is nothing:
118 if getattr(mod, comp, nothing) is nothing:
118 setattr(mod, comp, _demandmod(comp, mod.__dict__, mod.__dict__))
119 setattr(mod, comp, _demandmod(comp, mod.__dict__, mod.__dict__))
119 mod = getattr(mod, comp)
120 mod = getattr(mod, comp)
120 for x in fromlist:
121 for x in fromlist:
121 # set requested submodules for demand load
122 # set requested submodules for demand load
122 if getattr(mod, x, nothing) is nothing:
123 if getattr(mod, x, nothing) is nothing:
123 setattr(mod, x, _demandmod(x, mod.__dict__, locals))
124 setattr(mod, x, _demandmod(x, mod.__dict__, locals))
124 return mod
125 return mod
125
126
126 ignore = [
127 ignore = [
127 '_hashlib',
128 '_hashlib',
128 '_xmlplus',
129 '_xmlplus',
129 'fcntl',
130 'fcntl',
130 'win32com.gen_py',
131 'win32com.gen_py',
131 '_winreg', # 2.7 mimetypes needs immediate ImportError
132 '_winreg', # 2.7 mimetypes needs immediate ImportError
132 'pythoncom',
133 'pythoncom',
133 # imported by tarfile, not available under Windows
134 # imported by tarfile, not available under Windows
134 'pwd',
135 'pwd',
135 'grp',
136 'grp',
136 # imported by profile, itself imported by hotshot.stats,
137 # imported by profile, itself imported by hotshot.stats,
137 # not available under Windows
138 # not available under Windows
138 'resource',
139 'resource',
139 # this trips up many extension authors
140 # this trips up many extension authors
140 'gtk',
141 'gtk',
141 # setuptools' pkg_resources.py expects "from __main__ import x" to
142 # setuptools' pkg_resources.py expects "from __main__ import x" to
142 # raise ImportError if x not defined
143 # raise ImportError if x not defined
143 '__main__',
144 '__main__',
144 '_ssl', # conditional imports in the stdlib, issue1964
145 '_ssl', # conditional imports in the stdlib, issue1964
145 'rfc822',
146 'rfc822',
146 'mimetools',
147 'mimetools',
147 ]
148 ]
148
149
149 def enable():
150 def enable():
150 "enable global demand-loading of modules"
151 "enable global demand-loading of modules"
151 __builtin__.__import__ = _demandimport
152 __builtin__.__import__ = _demandimport
152
153
153 def disable():
154 def disable():
154 "disable global demand-loading of modules"
155 "disable global demand-loading of modules"
155 __builtin__.__import__ = _origimport
156 __builtin__.__import__ = _origimport
@@ -1,710 +1,749 b''
1 Test basic extension support
1 Test basic extension support
2
2
3 $ cat > foobar.py <<EOF
3 $ cat > foobar.py <<EOF
4 > import os
4 > import os
5 > from mercurial import commands
5 > from mercurial import commands
6 >
6 >
7 > def uisetup(ui):
7 > def uisetup(ui):
8 > ui.write("uisetup called\\n")
8 > ui.write("uisetup called\\n")
9 >
9 >
10 > def reposetup(ui, repo):
10 > def reposetup(ui, repo):
11 > ui.write("reposetup called for %s\\n" % os.path.basename(repo.root))
11 > ui.write("reposetup called for %s\\n" % os.path.basename(repo.root))
12 > ui.write("ui %s= repo.ui\\n" % (ui == repo.ui and "=" or "!"))
12 > ui.write("ui %s= repo.ui\\n" % (ui == repo.ui and "=" or "!"))
13 >
13 >
14 > def foo(ui, *args, **kwargs):
14 > def foo(ui, *args, **kwargs):
15 > ui.write("Foo\\n")
15 > ui.write("Foo\\n")
16 >
16 >
17 > def bar(ui, *args, **kwargs):
17 > def bar(ui, *args, **kwargs):
18 > ui.write("Bar\\n")
18 > ui.write("Bar\\n")
19 >
19 >
20 > cmdtable = {
20 > cmdtable = {
21 > "foo": (foo, [], "hg foo"),
21 > "foo": (foo, [], "hg foo"),
22 > "bar": (bar, [], "hg bar"),
22 > "bar": (bar, [], "hg bar"),
23 > }
23 > }
24 >
24 >
25 > commands.norepo += ' bar'
25 > commands.norepo += ' bar'
26 > EOF
26 > EOF
27 $ abspath=`pwd`/foobar.py
27 $ abspath=`pwd`/foobar.py
28
28
29 $ mkdir barfoo
29 $ mkdir barfoo
30 $ cp foobar.py barfoo/__init__.py
30 $ cp foobar.py barfoo/__init__.py
31 $ barfoopath=`pwd`/barfoo
31 $ barfoopath=`pwd`/barfoo
32
32
33 $ hg init a
33 $ hg init a
34 $ cd a
34 $ cd a
35 $ echo foo > file
35 $ echo foo > file
36 $ hg add file
36 $ hg add file
37 $ hg commit -m 'add file'
37 $ hg commit -m 'add file'
38
38
39 $ echo '[extensions]' >> $HGRCPATH
39 $ echo '[extensions]' >> $HGRCPATH
40 $ echo "foobar = $abspath" >> $HGRCPATH
40 $ echo "foobar = $abspath" >> $HGRCPATH
41 $ hg foo
41 $ hg foo
42 uisetup called
42 uisetup called
43 reposetup called for a
43 reposetup called for a
44 ui == repo.ui
44 ui == repo.ui
45 Foo
45 Foo
46
46
47 $ cd ..
47 $ cd ..
48 $ hg clone a b
48 $ hg clone a b
49 uisetup called
49 uisetup called
50 reposetup called for a
50 reposetup called for a
51 ui == repo.ui
51 ui == repo.ui
52 reposetup called for b
52 reposetup called for b
53 ui == repo.ui
53 ui == repo.ui
54 updating to branch default
54 updating to branch default
55 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
55 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
56
56
57 $ hg bar
57 $ hg bar
58 uisetup called
58 uisetup called
59 Bar
59 Bar
60 $ echo 'foobar = !' >> $HGRCPATH
60 $ echo 'foobar = !' >> $HGRCPATH
61
61
62 module/__init__.py-style
62 module/__init__.py-style
63
63
64 $ echo "barfoo = $barfoopath" >> $HGRCPATH
64 $ echo "barfoo = $barfoopath" >> $HGRCPATH
65 $ cd a
65 $ cd a
66 $ hg foo
66 $ hg foo
67 uisetup called
67 uisetup called
68 reposetup called for a
68 reposetup called for a
69 ui == repo.ui
69 ui == repo.ui
70 Foo
70 Foo
71 $ echo 'barfoo = !' >> $HGRCPATH
71 $ echo 'barfoo = !' >> $HGRCPATH
72
72
73 Check that extensions are loaded in phases:
73 Check that extensions are loaded in phases:
74
74
75 $ cat > foo.py <<EOF
75 $ cat > foo.py <<EOF
76 > import os
76 > import os
77 > name = os.path.basename(__file__).rsplit('.', 1)[0]
77 > name = os.path.basename(__file__).rsplit('.', 1)[0]
78 > print "1) %s imported" % name
78 > print "1) %s imported" % name
79 > def uisetup(ui):
79 > def uisetup(ui):
80 > print "2) %s uisetup" % name
80 > print "2) %s uisetup" % name
81 > def extsetup():
81 > def extsetup():
82 > print "3) %s extsetup" % name
82 > print "3) %s extsetup" % name
83 > def reposetup(ui, repo):
83 > def reposetup(ui, repo):
84 > print "4) %s reposetup" % name
84 > print "4) %s reposetup" % name
85 > EOF
85 > EOF
86
86
87 $ cp foo.py bar.py
87 $ cp foo.py bar.py
88 $ echo 'foo = foo.py' >> $HGRCPATH
88 $ echo 'foo = foo.py' >> $HGRCPATH
89 $ echo 'bar = bar.py' >> $HGRCPATH
89 $ echo 'bar = bar.py' >> $HGRCPATH
90
90
91 Command with no output, we just want to see the extensions loaded:
91 Command with no output, we just want to see the extensions loaded:
92
92
93 $ hg paths
93 $ hg paths
94 1) foo imported
94 1) foo imported
95 1) bar imported
95 1) bar imported
96 2) foo uisetup
96 2) foo uisetup
97 2) bar uisetup
97 2) bar uisetup
98 3) foo extsetup
98 3) foo extsetup
99 3) bar extsetup
99 3) bar extsetup
100 4) foo reposetup
100 4) foo reposetup
101 4) bar reposetup
101 4) bar reposetup
102
102
103 Check hgweb's load order:
103 Check hgweb's load order:
104
104
105 $ cat > hgweb.cgi <<EOF
105 $ cat > hgweb.cgi <<EOF
106 > #!/usr/bin/env python
106 > #!/usr/bin/env python
107 > from mercurial import demandimport; demandimport.enable()
107 > from mercurial import demandimport; demandimport.enable()
108 > from mercurial.hgweb import hgweb
108 > from mercurial.hgweb import hgweb
109 > from mercurial.hgweb import wsgicgi
109 > from mercurial.hgweb import wsgicgi
110 >
110 >
111 > application = hgweb('.', 'test repo')
111 > application = hgweb('.', 'test repo')
112 > wsgicgi.launch(application)
112 > wsgicgi.launch(application)
113 > EOF
113 > EOF
114
114
115 $ REQUEST_METHOD='GET' PATH_INFO='/' SCRIPT_NAME='' QUERY_STRING='' \
115 $ REQUEST_METHOD='GET' PATH_INFO='/' SCRIPT_NAME='' QUERY_STRING='' \
116 > SERVER_PORT='80' SERVER_NAME='localhost' python hgweb.cgi \
116 > SERVER_PORT='80' SERVER_NAME='localhost' python hgweb.cgi \
117 > | grep '^[0-9]) ' # ignores HTML output
117 > | grep '^[0-9]) ' # ignores HTML output
118 1) foo imported
118 1) foo imported
119 1) bar imported
119 1) bar imported
120 2) foo uisetup
120 2) foo uisetup
121 2) bar uisetup
121 2) bar uisetup
122 3) foo extsetup
122 3) foo extsetup
123 3) bar extsetup
123 3) bar extsetup
124 4) foo reposetup
124 4) foo reposetup
125 4) bar reposetup
125 4) bar reposetup
126 4) foo reposetup
126 4) foo reposetup
127 4) bar reposetup
127 4) bar reposetup
128
128
129 $ echo 'foo = !' >> $HGRCPATH
129 $ echo 'foo = !' >> $HGRCPATH
130 $ echo 'bar = !' >> $HGRCPATH
130 $ echo 'bar = !' >> $HGRCPATH
131
131
132 Check "from __future__ import absolute_import" support for external libraries
133
134 $ mkdir $TESTTMP/libroot
135 $ echo "s = 'libroot/ambig.py'" > $TESTTMP/libroot/ambig.py
136 $ mkdir $TESTTMP/libroot/mod
137 $ touch $TESTTMP/libroot/mod/__init__.py
138 $ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py
139
140 #if absimport
141 $ cat > $TESTTMP/libroot/mod/ambigabs.py <<EOF
142 > from __future__ import absolute_import
143 > import ambig # should load "libroot/ambig.py"
144 > s = ambig.s
145 > EOF
146 $ cat > loadabs.py <<EOF
147 > import mod.ambigabs as ambigabs
148 > def extsetup():
149 > print 'ambigabs.s=%s' % ambigabs.s
150 > EOF
151 $ (PYTHONPATH=$PYTHONPATH:$TESTTMP/libroot; hg --config extensions.loadabs=loadabs.py root)
152 ambigabs.s=libroot/ambig.py
153 $TESTTMP/a
154 #endif
155
156 #if no-py3k
157 $ cat > $TESTTMP/libroot/mod/ambigrel.py <<EOF
158 > import ambig # should load "libroot/mod/ambig.py"
159 > s = ambig.s
160 > EOF
161 $ cat > loadrel.py <<EOF
162 > import mod.ambigrel as ambigrel
163 > def extsetup():
164 > print 'ambigrel.s=%s' % ambigrel.s
165 > EOF
166 $ (PYTHONPATH=$PYTHONPATH:$TESTTMP/libroot; hg --config extensions.loadrel=loadrel.py root)
167 ambigrel.s=libroot/mod/ambig.py
168 $TESTTMP/a
169 #endif
170
132 $ cd ..
171 $ cd ..
133
172
134 hide outer repo
173 hide outer repo
135 $ hg init
174 $ hg init
136
175
137 $ cat > empty.py <<EOF
176 $ cat > empty.py <<EOF
138 > '''empty cmdtable
177 > '''empty cmdtable
139 > '''
178 > '''
140 > cmdtable = {}
179 > cmdtable = {}
141 > EOF
180 > EOF
142 $ emptypath=`pwd`/empty.py
181 $ emptypath=`pwd`/empty.py
143 $ echo "empty = $emptypath" >> $HGRCPATH
182 $ echo "empty = $emptypath" >> $HGRCPATH
144 $ hg help empty
183 $ hg help empty
145 empty extension - empty cmdtable
184 empty extension - empty cmdtable
146
185
147 no commands defined
186 no commands defined
148
187
149 $ echo 'empty = !' >> $HGRCPATH
188 $ echo 'empty = !' >> $HGRCPATH
150
189
151 $ cat > debugextension.py <<EOF
190 $ cat > debugextension.py <<EOF
152 > '''only debugcommands
191 > '''only debugcommands
153 > '''
192 > '''
154 > def debugfoobar(ui, repo, *args, **opts):
193 > def debugfoobar(ui, repo, *args, **opts):
155 > "yet another debug command"
194 > "yet another debug command"
156 > pass
195 > pass
157 >
196 >
158 > def foo(ui, repo, *args, **opts):
197 > def foo(ui, repo, *args, **opts):
159 > """yet another foo command
198 > """yet another foo command
160 >
199 >
161 > This command has been DEPRECATED since forever.
200 > This command has been DEPRECATED since forever.
162 > """
201 > """
163 > pass
202 > pass
164 >
203 >
165 > cmdtable = {
204 > cmdtable = {
166 > "debugfoobar": (debugfoobar, (), "hg debugfoobar"),
205 > "debugfoobar": (debugfoobar, (), "hg debugfoobar"),
167 > "foo": (foo, (), "hg foo")
206 > "foo": (foo, (), "hg foo")
168 > }
207 > }
169 > EOF
208 > EOF
170 $ debugpath=`pwd`/debugextension.py
209 $ debugpath=`pwd`/debugextension.py
171 $ echo "debugextension = $debugpath" >> $HGRCPATH
210 $ echo "debugextension = $debugpath" >> $HGRCPATH
172
211
173 $ hg help debugextension
212 $ hg help debugextension
174 debugextension extension - only debugcommands
213 debugextension extension - only debugcommands
175
214
176 no commands defined
215 no commands defined
177
216
178 $ hg --verbose help debugextension
217 $ hg --verbose help debugextension
179 debugextension extension - only debugcommands
218 debugextension extension - only debugcommands
180
219
181 list of commands:
220 list of commands:
182
221
183 foo yet another foo command
222 foo yet another foo command
184
223
185 global options:
224 global options:
186
225
187 -R --repository REPO repository root directory or name of overlay bundle
226 -R --repository REPO repository root directory or name of overlay bundle
188 file
227 file
189 --cwd DIR change working directory
228 --cwd DIR change working directory
190 -y --noninteractive do not prompt, automatically pick the first choice for
229 -y --noninteractive do not prompt, automatically pick the first choice for
191 all prompts
230 all prompts
192 -q --quiet suppress output
231 -q --quiet suppress output
193 -v --verbose enable additional output
232 -v --verbose enable additional output
194 --config CONFIG [+] set/override config option (use 'section.name=value')
233 --config CONFIG [+] set/override config option (use 'section.name=value')
195 --debug enable debugging output
234 --debug enable debugging output
196 --debugger start debugger
235 --debugger start debugger
197 --encoding ENCODE set the charset encoding (default: ascii)
236 --encoding ENCODE set the charset encoding (default: ascii)
198 --encodingmode MODE set the charset encoding mode (default: strict)
237 --encodingmode MODE set the charset encoding mode (default: strict)
199 --traceback always print a traceback on exception
238 --traceback always print a traceback on exception
200 --time time how long the command takes
239 --time time how long the command takes
201 --profile print command execution profile
240 --profile print command execution profile
202 --version output version information and exit
241 --version output version information and exit
203 -h --help display help and exit
242 -h --help display help and exit
204 --hidden consider hidden changesets
243 --hidden consider hidden changesets
205
244
206 [+] marked option can be specified multiple times
245 [+] marked option can be specified multiple times
207
246
208 $ hg --debug help debugextension
247 $ hg --debug help debugextension
209 debugextension extension - only debugcommands
248 debugextension extension - only debugcommands
210
249
211 list of commands:
250 list of commands:
212
251
213 debugfoobar yet another debug command
252 debugfoobar yet another debug command
214 foo yet another foo command
253 foo yet another foo command
215
254
216 global options:
255 global options:
217
256
218 -R --repository REPO repository root directory or name of overlay bundle
257 -R --repository REPO repository root directory or name of overlay bundle
219 file
258 file
220 --cwd DIR change working directory
259 --cwd DIR change working directory
221 -y --noninteractive do not prompt, automatically pick the first choice for
260 -y --noninteractive do not prompt, automatically pick the first choice for
222 all prompts
261 all prompts
223 -q --quiet suppress output
262 -q --quiet suppress output
224 -v --verbose enable additional output
263 -v --verbose enable additional output
225 --config CONFIG [+] set/override config option (use 'section.name=value')
264 --config CONFIG [+] set/override config option (use 'section.name=value')
226 --debug enable debugging output
265 --debug enable debugging output
227 --debugger start debugger
266 --debugger start debugger
228 --encoding ENCODE set the charset encoding (default: ascii)
267 --encoding ENCODE set the charset encoding (default: ascii)
229 --encodingmode MODE set the charset encoding mode (default: strict)
268 --encodingmode MODE set the charset encoding mode (default: strict)
230 --traceback always print a traceback on exception
269 --traceback always print a traceback on exception
231 --time time how long the command takes
270 --time time how long the command takes
232 --profile print command execution profile
271 --profile print command execution profile
233 --version output version information and exit
272 --version output version information and exit
234 -h --help display help and exit
273 -h --help display help and exit
235 --hidden consider hidden changesets
274 --hidden consider hidden changesets
236
275
237 [+] marked option can be specified multiple times
276 [+] marked option can be specified multiple times
238 $ echo 'debugextension = !' >> $HGRCPATH
277 $ echo 'debugextension = !' >> $HGRCPATH
239
278
240 Extension module help vs command help:
279 Extension module help vs command help:
241
280
242 $ echo 'extdiff =' >> $HGRCPATH
281 $ echo 'extdiff =' >> $HGRCPATH
243 $ hg help extdiff
282 $ hg help extdiff
244 hg extdiff [OPT]... [FILE]...
283 hg extdiff [OPT]... [FILE]...
245
284
246 use external program to diff repository (or selected files)
285 use external program to diff repository (or selected files)
247
286
248 Show differences between revisions for the specified files, using an
287 Show differences between revisions for the specified files, using an
249 external program. The default program used is diff, with default options
288 external program. The default program used is diff, with default options
250 "-Npru".
289 "-Npru".
251
290
252 To select a different program, use the -p/--program option. The program
291 To select a different program, use the -p/--program option. The program
253 will be passed the names of two directories to compare. To pass additional
292 will be passed the names of two directories to compare. To pass additional
254 options to the program, use -o/--option. These will be passed before the
293 options to the program, use -o/--option. These will be passed before the
255 names of the directories to compare.
294 names of the directories to compare.
256
295
257 When two revision arguments are given, then changes are shown between
296 When two revision arguments are given, then changes are shown between
258 those revisions. If only one revision is specified then that revision is
297 those revisions. If only one revision is specified then that revision is
259 compared to the working directory, and, when no revisions are specified,
298 compared to the working directory, and, when no revisions are specified,
260 the working directory files are compared to its parent.
299 the working directory files are compared to its parent.
261
300
262 use "hg help -e extdiff" to show help for the extdiff extension
301 use "hg help -e extdiff" to show help for the extdiff extension
263
302
264 options:
303 options:
265
304
266 -p --program CMD comparison program to run
305 -p --program CMD comparison program to run
267 -o --option OPT [+] pass option to comparison program
306 -o --option OPT [+] pass option to comparison program
268 -r --rev REV [+] revision
307 -r --rev REV [+] revision
269 -c --change REV change made by revision
308 -c --change REV change made by revision
270 -I --include PATTERN [+] include names matching the given patterns
309 -I --include PATTERN [+] include names matching the given patterns
271 -X --exclude PATTERN [+] exclude names matching the given patterns
310 -X --exclude PATTERN [+] exclude names matching the given patterns
272
311
273 [+] marked option can be specified multiple times
312 [+] marked option can be specified multiple times
274
313
275 use "hg -v help extdiff" to show the global options
314 use "hg -v help extdiff" to show the global options
276
315
277 $ hg help --extension extdiff
316 $ hg help --extension extdiff
278 extdiff extension - command to allow external programs to compare revisions
317 extdiff extension - command to allow external programs to compare revisions
279
318
280 The extdiff Mercurial extension allows you to use external programs to compare
319 The extdiff Mercurial extension allows you to use external programs to compare
281 revisions, or revision with working directory. The external diff programs are
320 revisions, or revision with working directory. The external diff programs are
282 called with a configurable set of options and two non-option arguments: paths
321 called with a configurable set of options and two non-option arguments: paths
283 to directories containing snapshots of files to compare.
322 to directories containing snapshots of files to compare.
284
323
285 The extdiff extension also allows you to configure new diff commands, so you
324 The extdiff extension also allows you to configure new diff commands, so you
286 do not need to type "hg extdiff -p kdiff3" always.
325 do not need to type "hg extdiff -p kdiff3" always.
287
326
288 [extdiff]
327 [extdiff]
289 # add new command that runs GNU diff(1) in 'context diff' mode
328 # add new command that runs GNU diff(1) in 'context diff' mode
290 cdiff = gdiff -Nprc5
329 cdiff = gdiff -Nprc5
291 ## or the old way:
330 ## or the old way:
292 #cmd.cdiff = gdiff
331 #cmd.cdiff = gdiff
293 #opts.cdiff = -Nprc5
332 #opts.cdiff = -Nprc5
294
333
295 # add new command called vdiff, runs kdiff3
334 # add new command called vdiff, runs kdiff3
296 vdiff = kdiff3
335 vdiff = kdiff3
297
336
298 # add new command called meld, runs meld (no need to name twice)
337 # add new command called meld, runs meld (no need to name twice)
299 meld =
338 meld =
300
339
301 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
340 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
302 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
341 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
303 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
342 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
304 # your .vimrc
343 # your .vimrc
305 vimdiff = gvim -f "+next" \
344 vimdiff = gvim -f "+next" \
306 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
345 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
307
346
308 Tool arguments can include variables that are expanded at runtime:
347 Tool arguments can include variables that are expanded at runtime:
309
348
310 $parent1, $plabel1 - filename, descriptive label of first parent
349 $parent1, $plabel1 - filename, descriptive label of first parent
311 $child, $clabel - filename, descriptive label of child revision
350 $child, $clabel - filename, descriptive label of child revision
312 $parent2, $plabel2 - filename, descriptive label of second parent
351 $parent2, $plabel2 - filename, descriptive label of second parent
313 $root - repository root
352 $root - repository root
314 $parent is an alias for $parent1.
353 $parent is an alias for $parent1.
315
354
316 The extdiff extension will look in your [diff-tools] and [merge-tools]
355 The extdiff extension will look in your [diff-tools] and [merge-tools]
317 sections for diff tool arguments, when none are specified in [extdiff].
356 sections for diff tool arguments, when none are specified in [extdiff].
318
357
319 [extdiff]
358 [extdiff]
320 kdiff3 =
359 kdiff3 =
321
360
322 [diff-tools]
361 [diff-tools]
323 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
362 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
324
363
325 You can use -I/-X and list of file or directory names like normal "hg diff"
364 You can use -I/-X and list of file or directory names like normal "hg diff"
326 command. The extdiff extension makes snapshots of only needed files, so
365 command. The extdiff extension makes snapshots of only needed files, so
327 running the external diff program will actually be pretty fast (at least
366 running the external diff program will actually be pretty fast (at least
328 faster than having to compare the entire tree).
367 faster than having to compare the entire tree).
329
368
330 list of commands:
369 list of commands:
331
370
332 extdiff use external program to diff repository (or selected files)
371 extdiff use external program to diff repository (or selected files)
333
372
334 use "hg -v help extdiff" to show builtin aliases and global options
373 use "hg -v help extdiff" to show builtin aliases and global options
335
374
336 $ echo 'extdiff = !' >> $HGRCPATH
375 $ echo 'extdiff = !' >> $HGRCPATH
337
376
338 Test help topic with same name as extension
377 Test help topic with same name as extension
339
378
340 $ cat > multirevs.py <<EOF
379 $ cat > multirevs.py <<EOF
341 > from mercurial import commands
380 > from mercurial import commands
342 > """multirevs extension
381 > """multirevs extension
343 > Big multi-line module docstring."""
382 > Big multi-line module docstring."""
344 > def multirevs(ui, repo, arg, *args, **opts):
383 > def multirevs(ui, repo, arg, *args, **opts):
345 > """multirevs command"""
384 > """multirevs command"""
346 > pass
385 > pass
347 > cmdtable = {
386 > cmdtable = {
348 > "multirevs": (multirevs, [], 'ARG')
387 > "multirevs": (multirevs, [], 'ARG')
349 > }
388 > }
350 > commands.norepo += ' multirevs'
389 > commands.norepo += ' multirevs'
351 > EOF
390 > EOF
352 $ echo "multirevs = multirevs.py" >> $HGRCPATH
391 $ echo "multirevs = multirevs.py" >> $HGRCPATH
353
392
354 $ hg help multirevs
393 $ hg help multirevs
355 Specifying Multiple Revisions
394 Specifying Multiple Revisions
356 """""""""""""""""""""""""""""
395 """""""""""""""""""""""""""""
357
396
358 When Mercurial accepts more than one revision, they may be specified
397 When Mercurial accepts more than one revision, they may be specified
359 individually, or provided as a topologically continuous range, separated
398 individually, or provided as a topologically continuous range, separated
360 by the ":" character.
399 by the ":" character.
361
400
362 The syntax of range notation is [BEGIN]:[END], where BEGIN and END are
401 The syntax of range notation is [BEGIN]:[END], where BEGIN and END are
363 revision identifiers. Both BEGIN and END are optional. If BEGIN is not
402 revision identifiers. Both BEGIN and END are optional. If BEGIN is not
364 specified, it defaults to revision number 0. If END is not specified, it
403 specified, it defaults to revision number 0. If END is not specified, it
365 defaults to the tip. The range ":" thus means "all revisions".
404 defaults to the tip. The range ":" thus means "all revisions".
366
405
367 If BEGIN is greater than END, revisions are treated in reverse order.
406 If BEGIN is greater than END, revisions are treated in reverse order.
368
407
369 A range acts as a closed interval. This means that a range of 3:5 gives 3,
408 A range acts as a closed interval. This means that a range of 3:5 gives 3,
370 4 and 5. Similarly, a range of 9:6 gives 9, 8, 7, and 6.
409 4 and 5. Similarly, a range of 9:6 gives 9, 8, 7, and 6.
371
410
372 use "hg help -c multirevs" to see help for the multirevs command
411 use "hg help -c multirevs" to see help for the multirevs command
373
412
374 $ hg help -c multirevs
413 $ hg help -c multirevs
375 hg multirevs ARG
414 hg multirevs ARG
376
415
377 multirevs command
416 multirevs command
378
417
379 use "hg -v help multirevs" to show the global options
418 use "hg -v help multirevs" to show the global options
380
419
381 $ hg multirevs
420 $ hg multirevs
382 hg multirevs: invalid arguments
421 hg multirevs: invalid arguments
383 hg multirevs ARG
422 hg multirevs ARG
384
423
385 multirevs command
424 multirevs command
386
425
387 use "hg help multirevs" to show the full help text
426 use "hg help multirevs" to show the full help text
388 [255]
427 [255]
389
428
390 $ echo "multirevs = !" >> $HGRCPATH
429 $ echo "multirevs = !" >> $HGRCPATH
391
430
392 Issue811: Problem loading extensions twice (by site and by user)
431 Issue811: Problem loading extensions twice (by site and by user)
393
432
394 $ debugpath=`pwd`/debugissue811.py
433 $ debugpath=`pwd`/debugissue811.py
395 $ cat > debugissue811.py <<EOF
434 $ cat > debugissue811.py <<EOF
396 > '''show all loaded extensions
435 > '''show all loaded extensions
397 > '''
436 > '''
398 > from mercurial import extensions, commands
437 > from mercurial import extensions, commands
399 >
438 >
400 > def debugextensions(ui):
439 > def debugextensions(ui):
401 > "yet another debug command"
440 > "yet another debug command"
402 > ui.write("%s\n" % '\n'.join([x for x, y in extensions.extensions()]))
441 > ui.write("%s\n" % '\n'.join([x for x, y in extensions.extensions()]))
403 >
442 >
404 > cmdtable = {"debugextensions": (debugextensions, (), "hg debugextensions")}
443 > cmdtable = {"debugextensions": (debugextensions, (), "hg debugextensions")}
405 > commands.norepo += " debugextensions"
444 > commands.norepo += " debugextensions"
406 > EOF
445 > EOF
407 $ echo "debugissue811 = $debugpath" >> $HGRCPATH
446 $ echo "debugissue811 = $debugpath" >> $HGRCPATH
408 $ echo "mq=" >> $HGRCPATH
447 $ echo "mq=" >> $HGRCPATH
409 $ echo "strip=" >> $HGRCPATH
448 $ echo "strip=" >> $HGRCPATH
410 $ echo "hgext.mq=" >> $HGRCPATH
449 $ echo "hgext.mq=" >> $HGRCPATH
411 $ echo "hgext/mq=" >> $HGRCPATH
450 $ echo "hgext/mq=" >> $HGRCPATH
412
451
413 Show extensions:
452 Show extensions:
414 (note that mq force load strip, also checking it's not loaded twice)
453 (note that mq force load strip, also checking it's not loaded twice)
415
454
416 $ hg debugextensions
455 $ hg debugextensions
417 debugissue811
456 debugissue811
418 strip
457 strip
419 mq
458 mq
420
459
421 Disabled extension commands:
460 Disabled extension commands:
422
461
423 $ ORGHGRCPATH=$HGRCPATH
462 $ ORGHGRCPATH=$HGRCPATH
424 $ HGRCPATH=
463 $ HGRCPATH=
425 $ export HGRCPATH
464 $ export HGRCPATH
426 $ hg help email
465 $ hg help email
427 'email' is provided by the following extension:
466 'email' is provided by the following extension:
428
467
429 patchbomb command to send changesets as (a series of) patch emails
468 patchbomb command to send changesets as (a series of) patch emails
430
469
431 use "hg help extensions" for information on enabling extensions
470 use "hg help extensions" for information on enabling extensions
432 $ hg qdel
471 $ hg qdel
433 hg: unknown command 'qdel'
472 hg: unknown command 'qdel'
434 'qdelete' is provided by the following extension:
473 'qdelete' is provided by the following extension:
435
474
436 mq manage a stack of patches
475 mq manage a stack of patches
437
476
438 use "hg help extensions" for information on enabling extensions
477 use "hg help extensions" for information on enabling extensions
439 [255]
478 [255]
440 $ hg churn
479 $ hg churn
441 hg: unknown command 'churn'
480 hg: unknown command 'churn'
442 'churn' is provided by the following extension:
481 'churn' is provided by the following extension:
443
482
444 churn command to display statistics about repository history
483 churn command to display statistics about repository history
445
484
446 use "hg help extensions" for information on enabling extensions
485 use "hg help extensions" for information on enabling extensions
447 [255]
486 [255]
448
487
449 Disabled extensions:
488 Disabled extensions:
450
489
451 $ hg help churn
490 $ hg help churn
452 churn extension - command to display statistics about repository history
491 churn extension - command to display statistics about repository history
453
492
454 use "hg help extensions" for information on enabling extensions
493 use "hg help extensions" for information on enabling extensions
455 $ hg help patchbomb
494 $ hg help patchbomb
456 patchbomb extension - command to send changesets as (a series of) patch emails
495 patchbomb extension - command to send changesets as (a series of) patch emails
457
496
458 use "hg help extensions" for information on enabling extensions
497 use "hg help extensions" for information on enabling extensions
459
498
460 Broken disabled extension and command:
499 Broken disabled extension and command:
461
500
462 $ mkdir hgext
501 $ mkdir hgext
463 $ echo > hgext/__init__.py
502 $ echo > hgext/__init__.py
464 $ cat > hgext/broken.py <<EOF
503 $ cat > hgext/broken.py <<EOF
465 > "broken extension'
504 > "broken extension'
466 > EOF
505 > EOF
467 $ cat > path.py <<EOF
506 $ cat > path.py <<EOF
468 > import os, sys
507 > import os, sys
469 > sys.path.insert(0, os.environ['HGEXTPATH'])
508 > sys.path.insert(0, os.environ['HGEXTPATH'])
470 > EOF
509 > EOF
471 $ HGEXTPATH=`pwd`
510 $ HGEXTPATH=`pwd`
472 $ export HGEXTPATH
511 $ export HGEXTPATH
473
512
474 $ hg --config extensions.path=./path.py help broken
513 $ hg --config extensions.path=./path.py help broken
475 broken extension - (no help text available)
514 broken extension - (no help text available)
476
515
477 use "hg help extensions" for information on enabling extensions
516 use "hg help extensions" for information on enabling extensions
478
517
479 $ cat > hgext/forest.py <<EOF
518 $ cat > hgext/forest.py <<EOF
480 > cmdtable = None
519 > cmdtable = None
481 > EOF
520 > EOF
482 $ hg --config extensions.path=./path.py help foo > /dev/null
521 $ hg --config extensions.path=./path.py help foo > /dev/null
483 warning: error finding commands in $TESTTMP/hgext/forest.py (glob)
522 warning: error finding commands in $TESTTMP/hgext/forest.py (glob)
484 hg: unknown command 'foo'
523 hg: unknown command 'foo'
485 warning: error finding commands in $TESTTMP/hgext/forest.py (glob)
524 warning: error finding commands in $TESTTMP/hgext/forest.py (glob)
486 [255]
525 [255]
487
526
488 $ cat > throw.py <<EOF
527 $ cat > throw.py <<EOF
489 > from mercurial import cmdutil, commands
528 > from mercurial import cmdutil, commands
490 > cmdtable = {}
529 > cmdtable = {}
491 > command = cmdutil.command(cmdtable)
530 > command = cmdutil.command(cmdtable)
492 > class Bogon(Exception): pass
531 > class Bogon(Exception): pass
493 >
532 >
494 > @command('throw', [], 'hg throw')
533 > @command('throw', [], 'hg throw')
495 > def throw(ui, **opts):
534 > def throw(ui, **opts):
496 > """throws an exception"""
535 > """throws an exception"""
497 > raise Bogon()
536 > raise Bogon()
498 > commands.norepo += " throw"
537 > commands.norepo += " throw"
499 > EOF
538 > EOF
500 No declared supported version, extension complains:
539 No declared supported version, extension complains:
501 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
540 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
502 ** Unknown exception encountered with possibly-broken third-party extension throw
541 ** Unknown exception encountered with possibly-broken third-party extension throw
503 ** which supports versions unknown of Mercurial.
542 ** which supports versions unknown of Mercurial.
504 ** Please disable throw and try your action again.
543 ** Please disable throw and try your action again.
505 ** If that fixes the bug please report it to the extension author.
544 ** If that fixes the bug please report it to the extension author.
506 ** Python * (glob)
545 ** Python * (glob)
507 ** Mercurial Distributed SCM * (glob)
546 ** Mercurial Distributed SCM * (glob)
508 ** Extensions loaded: throw
547 ** Extensions loaded: throw
509 empty declaration of supported version, extension complains:
548 empty declaration of supported version, extension complains:
510 $ echo "testedwith = ''" >> throw.py
549 $ echo "testedwith = ''" >> throw.py
511 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
550 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
512 ** Unknown exception encountered with possibly-broken third-party extension throw
551 ** Unknown exception encountered with possibly-broken third-party extension throw
513 ** which supports versions unknown of Mercurial.
552 ** which supports versions unknown of Mercurial.
514 ** Please disable throw and try your action again.
553 ** Please disable throw and try your action again.
515 ** If that fixes the bug please report it to the extension author.
554 ** If that fixes the bug please report it to the extension author.
516 ** Python * (glob)
555 ** Python * (glob)
517 ** Mercurial Distributed SCM (*) (glob)
556 ** Mercurial Distributed SCM (*) (glob)
518 ** Extensions loaded: throw
557 ** Extensions loaded: throw
519 If the extension specifies a buglink, show that:
558 If the extension specifies a buglink, show that:
520 $ echo 'buglink = "http://example.com/bts"' >> throw.py
559 $ echo 'buglink = "http://example.com/bts"' >> throw.py
521 $ rm -f throw.pyc throw.pyo
560 $ rm -f throw.pyc throw.pyo
522 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
561 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
523 ** Unknown exception encountered with possibly-broken third-party extension throw
562 ** Unknown exception encountered with possibly-broken third-party extension throw
524 ** which supports versions unknown of Mercurial.
563 ** which supports versions unknown of Mercurial.
525 ** Please disable throw and try your action again.
564 ** Please disable throw and try your action again.
526 ** If that fixes the bug please report it to http://example.com/bts
565 ** If that fixes the bug please report it to http://example.com/bts
527 ** Python * (glob)
566 ** Python * (glob)
528 ** Mercurial Distributed SCM (*) (glob)
567 ** Mercurial Distributed SCM (*) (glob)
529 ** Extensions loaded: throw
568 ** Extensions loaded: throw
530 If the extensions declare outdated versions, accuse the older extension first:
569 If the extensions declare outdated versions, accuse the older extension first:
531 $ echo "from mercurial import util" >> older.py
570 $ echo "from mercurial import util" >> older.py
532 $ echo "util.version = lambda:'2.2'" >> older.py
571 $ echo "util.version = lambda:'2.2'" >> older.py
533 $ echo "testedwith = '1.9.3'" >> older.py
572 $ echo "testedwith = '1.9.3'" >> older.py
534 $ echo "testedwith = '2.1.1'" >> throw.py
573 $ echo "testedwith = '2.1.1'" >> throw.py
535 $ rm -f throw.pyc throw.pyo
574 $ rm -f throw.pyc throw.pyo
536 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
575 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
537 > throw 2>&1 | egrep '^\*\*'
576 > throw 2>&1 | egrep '^\*\*'
538 ** Unknown exception encountered with possibly-broken third-party extension older
577 ** Unknown exception encountered with possibly-broken third-party extension older
539 ** which supports versions 1.9.3 of Mercurial.
578 ** which supports versions 1.9.3 of Mercurial.
540 ** Please disable older and try your action again.
579 ** Please disable older and try your action again.
541 ** If that fixes the bug please report it to the extension author.
580 ** If that fixes the bug please report it to the extension author.
542 ** Python * (glob)
581 ** Python * (glob)
543 ** Mercurial Distributed SCM (version 2.2)
582 ** Mercurial Distributed SCM (version 2.2)
544 ** Extensions loaded: throw, older
583 ** Extensions loaded: throw, older
545 One extension only tested with older, one only with newer versions:
584 One extension only tested with older, one only with newer versions:
546 $ echo "util.version = lambda:'2.1.0'" >> older.py
585 $ echo "util.version = lambda:'2.1.0'" >> older.py
547 $ rm -f older.pyc older.pyo
586 $ rm -f older.pyc older.pyo
548 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
587 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
549 > throw 2>&1 | egrep '^\*\*'
588 > throw 2>&1 | egrep '^\*\*'
550 ** Unknown exception encountered with possibly-broken third-party extension older
589 ** Unknown exception encountered with possibly-broken third-party extension older
551 ** which supports versions 1.9.3 of Mercurial.
590 ** which supports versions 1.9.3 of Mercurial.
552 ** Please disable older and try your action again.
591 ** Please disable older and try your action again.
553 ** If that fixes the bug please report it to the extension author.
592 ** If that fixes the bug please report it to the extension author.
554 ** Python * (glob)
593 ** Python * (glob)
555 ** Mercurial Distributed SCM (version 2.1.0)
594 ** Mercurial Distributed SCM (version 2.1.0)
556 ** Extensions loaded: throw, older
595 ** Extensions loaded: throw, older
557 Older extension is tested with current version, the other only with newer:
596 Older extension is tested with current version, the other only with newer:
558 $ echo "util.version = lambda:'1.9.3'" >> older.py
597 $ echo "util.version = lambda:'1.9.3'" >> older.py
559 $ rm -f older.pyc older.pyo
598 $ rm -f older.pyc older.pyo
560 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
599 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
561 > throw 2>&1 | egrep '^\*\*'
600 > throw 2>&1 | egrep '^\*\*'
562 ** Unknown exception encountered with possibly-broken third-party extension throw
601 ** Unknown exception encountered with possibly-broken third-party extension throw
563 ** which supports versions 2.1.1 of Mercurial.
602 ** which supports versions 2.1.1 of Mercurial.
564 ** Please disable throw and try your action again.
603 ** Please disable throw and try your action again.
565 ** If that fixes the bug please report it to http://example.com/bts
604 ** If that fixes the bug please report it to http://example.com/bts
566 ** Python * (glob)
605 ** Python * (glob)
567 ** Mercurial Distributed SCM (version 1.9.3)
606 ** Mercurial Distributed SCM (version 1.9.3)
568 ** Extensions loaded: throw, older
607 ** Extensions loaded: throw, older
569
608
570 Declare the version as supporting this hg version, show regular bts link:
609 Declare the version as supporting this hg version, show regular bts link:
571 $ hgver=`python -c 'from mercurial import util; print util.version().split("+")[0]'`
610 $ hgver=`python -c 'from mercurial import util; print util.version().split("+")[0]'`
572 $ echo 'testedwith = """'"$hgver"'"""' >> throw.py
611 $ echo 'testedwith = """'"$hgver"'"""' >> throw.py
573 $ rm -f throw.pyc throw.pyo
612 $ rm -f throw.pyc throw.pyo
574 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
613 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
575 ** unknown exception encountered, please report by visiting
614 ** unknown exception encountered, please report by visiting
576 ** http://mercurial.selenic.com/wiki/BugTracker
615 ** http://mercurial.selenic.com/wiki/BugTracker
577 ** Python * (glob)
616 ** Python * (glob)
578 ** Mercurial Distributed SCM (*) (glob)
617 ** Mercurial Distributed SCM (*) (glob)
579 ** Extensions loaded: throw
618 ** Extensions loaded: throw
580
619
581 Restore HGRCPATH
620 Restore HGRCPATH
582
621
583 $ HGRCPATH=$ORGHGRCPATH
622 $ HGRCPATH=$ORGHGRCPATH
584 $ export HGRCPATH
623 $ export HGRCPATH
585
624
586 Commands handling multiple repositories at a time should invoke only
625 Commands handling multiple repositories at a time should invoke only
587 "reposetup()" of extensions enabling in the target repository.
626 "reposetup()" of extensions enabling in the target repository.
588
627
589 $ mkdir reposetup-test
628 $ mkdir reposetup-test
590 $ cd reposetup-test
629 $ cd reposetup-test
591
630
592 $ cat > $TESTTMP/reposetuptest.py <<EOF
631 $ cat > $TESTTMP/reposetuptest.py <<EOF
593 > from mercurial import extensions
632 > from mercurial import extensions
594 > def reposetup(ui, repo):
633 > def reposetup(ui, repo):
595 > ui.write('reposetup() for %s\n' % (repo.root))
634 > ui.write('reposetup() for %s\n' % (repo.root))
596 > EOF
635 > EOF
597 $ hg init src
636 $ hg init src
598 $ echo a > src/a
637 $ echo a > src/a
599 $ hg -R src commit -Am '#0 at src/a'
638 $ hg -R src commit -Am '#0 at src/a'
600 adding a
639 adding a
601 $ echo '[extensions]' >> src/.hg/hgrc
640 $ echo '[extensions]' >> src/.hg/hgrc
602 $ echo '# enable extension locally' >> src/.hg/hgrc
641 $ echo '# enable extension locally' >> src/.hg/hgrc
603 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
642 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
604 $ hg -R src status
643 $ hg -R src status
605 reposetup() for $TESTTMP/reposetup-test/src
644 reposetup() for $TESTTMP/reposetup-test/src
606
645
607 $ hg clone -U src clone-dst1
646 $ hg clone -U src clone-dst1
608 reposetup() for $TESTTMP/reposetup-test/src
647 reposetup() for $TESTTMP/reposetup-test/src
609 $ hg init push-dst1
648 $ hg init push-dst1
610 $ hg -q -R src push push-dst1
649 $ hg -q -R src push push-dst1
611 reposetup() for $TESTTMP/reposetup-test/src
650 reposetup() for $TESTTMP/reposetup-test/src
612 $ hg init pull-src1
651 $ hg init pull-src1
613 $ hg -q -R pull-src1 pull src
652 $ hg -q -R pull-src1 pull src
614 reposetup() for $TESTTMP/reposetup-test/src
653 reposetup() for $TESTTMP/reposetup-test/src
615
654
616 $ echo '[extensions]' >> $HGRCPATH
655 $ echo '[extensions]' >> $HGRCPATH
617 $ echo '# disable extension globally and explicitly' >> $HGRCPATH
656 $ echo '# disable extension globally and explicitly' >> $HGRCPATH
618 $ echo 'reposetuptest = !' >> $HGRCPATH
657 $ echo 'reposetuptest = !' >> $HGRCPATH
619 $ hg clone -U src clone-dst2
658 $ hg clone -U src clone-dst2
620 reposetup() for $TESTTMP/reposetup-test/src
659 reposetup() for $TESTTMP/reposetup-test/src
621 $ hg init push-dst2
660 $ hg init push-dst2
622 $ hg -q -R src push push-dst2
661 $ hg -q -R src push push-dst2
623 reposetup() for $TESTTMP/reposetup-test/src
662 reposetup() for $TESTTMP/reposetup-test/src
624 $ hg init pull-src2
663 $ hg init pull-src2
625 $ hg -q -R pull-src2 pull src
664 $ hg -q -R pull-src2 pull src
626 reposetup() for $TESTTMP/reposetup-test/src
665 reposetup() for $TESTTMP/reposetup-test/src
627
666
628 $ echo '[extensions]' >> $HGRCPATH
667 $ echo '[extensions]' >> $HGRCPATH
629 $ echo '# enable extension globally' >> $HGRCPATH
668 $ echo '# enable extension globally' >> $HGRCPATH
630 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> $HGRCPATH
669 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> $HGRCPATH
631 $ hg clone -U src clone-dst3
670 $ hg clone -U src clone-dst3
632 reposetup() for $TESTTMP/reposetup-test/src
671 reposetup() for $TESTTMP/reposetup-test/src
633 reposetup() for $TESTTMP/reposetup-test/clone-dst3
672 reposetup() for $TESTTMP/reposetup-test/clone-dst3
634 $ hg init push-dst3
673 $ hg init push-dst3
635 reposetup() for $TESTTMP/reposetup-test/push-dst3
674 reposetup() for $TESTTMP/reposetup-test/push-dst3
636 $ hg -q -R src push push-dst3
675 $ hg -q -R src push push-dst3
637 reposetup() for $TESTTMP/reposetup-test/src
676 reposetup() for $TESTTMP/reposetup-test/src
638 reposetup() for $TESTTMP/reposetup-test/push-dst3
677 reposetup() for $TESTTMP/reposetup-test/push-dst3
639 $ hg init pull-src3
678 $ hg init pull-src3
640 reposetup() for $TESTTMP/reposetup-test/pull-src3
679 reposetup() for $TESTTMP/reposetup-test/pull-src3
641 $ hg -q -R pull-src3 pull src
680 $ hg -q -R pull-src3 pull src
642 reposetup() for $TESTTMP/reposetup-test/pull-src3
681 reposetup() for $TESTTMP/reposetup-test/pull-src3
643 reposetup() for $TESTTMP/reposetup-test/src
682 reposetup() for $TESTTMP/reposetup-test/src
644
683
645 $ echo '[extensions]' >> src/.hg/hgrc
684 $ echo '[extensions]' >> src/.hg/hgrc
646 $ echo '# disable extension locally' >> src/.hg/hgrc
685 $ echo '# disable extension locally' >> src/.hg/hgrc
647 $ echo 'reposetuptest = !' >> src/.hg/hgrc
686 $ echo 'reposetuptest = !' >> src/.hg/hgrc
648 $ hg clone -U src clone-dst4
687 $ hg clone -U src clone-dst4
649 reposetup() for $TESTTMP/reposetup-test/clone-dst4
688 reposetup() for $TESTTMP/reposetup-test/clone-dst4
650 $ hg init push-dst4
689 $ hg init push-dst4
651 reposetup() for $TESTTMP/reposetup-test/push-dst4
690 reposetup() for $TESTTMP/reposetup-test/push-dst4
652 $ hg -q -R src push push-dst4
691 $ hg -q -R src push push-dst4
653 reposetup() for $TESTTMP/reposetup-test/push-dst4
692 reposetup() for $TESTTMP/reposetup-test/push-dst4
654 $ hg init pull-src4
693 $ hg init pull-src4
655 reposetup() for $TESTTMP/reposetup-test/pull-src4
694 reposetup() for $TESTTMP/reposetup-test/pull-src4
656 $ hg -q -R pull-src4 pull src
695 $ hg -q -R pull-src4 pull src
657 reposetup() for $TESTTMP/reposetup-test/pull-src4
696 reposetup() for $TESTTMP/reposetup-test/pull-src4
658
697
659 disabling in command line overlays with all configuration
698 disabling in command line overlays with all configuration
660 $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
699 $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
661 $ hg --config extensions.reposetuptest=! init push-dst5
700 $ hg --config extensions.reposetuptest=! init push-dst5
662 $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
701 $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
663 $ hg --config extensions.reposetuptest=! init pull-src5
702 $ hg --config extensions.reposetuptest=! init pull-src5
664 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
703 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
665
704
666 $ echo '[extensions]' >> $HGRCPATH
705 $ echo '[extensions]' >> $HGRCPATH
667 $ echo '# disable extension globally and explicitly' >> $HGRCPATH
706 $ echo '# disable extension globally and explicitly' >> $HGRCPATH
668 $ echo 'reposetuptest = !' >> $HGRCPATH
707 $ echo 'reposetuptest = !' >> $HGRCPATH
669 $ hg init parent
708 $ hg init parent
670 $ hg init parent/sub1
709 $ hg init parent/sub1
671 $ echo 1 > parent/sub1/1
710 $ echo 1 > parent/sub1/1
672 $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
711 $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
673 adding 1
712 adding 1
674 $ hg init parent/sub2
713 $ hg init parent/sub2
675 $ hg init parent/sub2/sub21
714 $ hg init parent/sub2/sub21
676 $ echo 21 > parent/sub2/sub21/21
715 $ echo 21 > parent/sub2/sub21/21
677 $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
716 $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
678 adding 21
717 adding 21
679 $ cat > parent/sub2/.hgsub <<EOF
718 $ cat > parent/sub2/.hgsub <<EOF
680 > sub21 = sub21
719 > sub21 = sub21
681 > EOF
720 > EOF
682 $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
721 $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
683 adding .hgsub
722 adding .hgsub
684 $ hg init parent/sub3
723 $ hg init parent/sub3
685 $ echo 3 > parent/sub3/3
724 $ echo 3 > parent/sub3/3
686 $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
725 $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
687 adding 3
726 adding 3
688 $ cat > parent/.hgsub <<EOF
727 $ cat > parent/.hgsub <<EOF
689 > sub1 = sub1
728 > sub1 = sub1
690 > sub2 = sub2
729 > sub2 = sub2
691 > sub3 = sub3
730 > sub3 = sub3
692 > EOF
731 > EOF
693 $ hg -R parent commit -Am '#0 at parent'
732 $ hg -R parent commit -Am '#0 at parent'
694 adding .hgsub
733 adding .hgsub
695 $ echo '[extensions]' >> parent/.hg/hgrc
734 $ echo '[extensions]' >> parent/.hg/hgrc
696 $ echo '# enable extension locally' >> parent/.hg/hgrc
735 $ echo '# enable extension locally' >> parent/.hg/hgrc
697 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
736 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
698 $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
737 $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
699 $ hg -R parent status -S -A
738 $ hg -R parent status -S -A
700 reposetup() for $TESTTMP/reposetup-test/parent
739 reposetup() for $TESTTMP/reposetup-test/parent
701 reposetup() for $TESTTMP/reposetup-test/parent/sub2
740 reposetup() for $TESTTMP/reposetup-test/parent/sub2
702 C .hgsub
741 C .hgsub
703 C .hgsubstate
742 C .hgsubstate
704 C sub1/1
743 C sub1/1
705 C sub2/.hgsub
744 C sub2/.hgsub
706 C sub2/.hgsubstate
745 C sub2/.hgsubstate
707 C sub2/sub21/21
746 C sub2/sub21/21
708 C sub3/3
747 C sub3/3
709
748
710 $ cd ..
749 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now