Show More
@@ -124,7 +124,7 b' def _reportimporterror(ui, err, failed, ' | |||
|
124 | 124 | # note: this ui.debug happens before --debug is processed, |
|
125 | 125 | # Use --config ui.debug=1 to see them. |
|
126 | 126 | if ui.configbool('devel', 'debug.extensions'): |
|
127 | ui.debug('could not import %s (%s): trying %s\n' | |
|
127 | ui.debug('debug.extensions: - could not import %s (%s): trying %s\n' | |
|
128 | 128 | % (failed, stringutil.forcebytestr(err), next)) |
|
129 | 129 | if ui.debugflag: |
|
130 | 130 | ui.traceback() |
@@ -166,7 +166,7 b' def _validatetables(ui, mod):' | |||
|
166 | 166 | _rejectunicode(t, o._table) |
|
167 | 167 | _validatecmdtable(ui, getattr(mod, 'cmdtable', {})) |
|
168 | 168 | |
|
169 | def load(ui, name, path): | |
|
169 | def load(ui, name, path, log=lambda *a: None): | |
|
170 | 170 | if name.startswith('hgext.') or name.startswith('hgext/'): |
|
171 | 171 | shortname = name[6:] |
|
172 | 172 | else: |
@@ -175,8 +175,11 b' def load(ui, name, path):' | |||
|
175 | 175 | return None |
|
176 | 176 | if shortname in _extensions: |
|
177 | 177 | return _extensions[shortname] |
|
178 | log(' - loading extension: %r\n', shortname) | |
|
178 | 179 | _extensions[shortname] = None |
|
179 | mod = _importext(name, path, bind(_reportimporterror, ui)) | |
|
180 | with util.timedcm() as stats: | |
|
181 | mod = _importext(name, path, bind(_reportimporterror, ui)) | |
|
182 | log(' > %r extension loaded in %s\n', shortname, stats) | |
|
180 | 183 | |
|
181 | 184 | # Before we do anything with the extension, check against minimum stated |
|
182 | 185 | # compatibility. This gives extension authors a mechanism to have their |
@@ -187,12 +190,16 b' def load(ui, name, path):' | |||
|
187 | 190 | ui.warn(_('(third party extension %s requires version %s or newer ' |
|
188 | 191 | 'of Mercurial; disabling)\n') % (shortname, minver)) |
|
189 | 192 | return |
|
193 | log(' - validating extension tables: %r\n', shortname) | |
|
190 | 194 | _validatetables(ui, mod) |
|
191 | 195 | |
|
192 | 196 | _extensions[shortname] = mod |
|
193 | 197 | _order.append(shortname) |
|
194 | for fn in _aftercallbacks.get(shortname, []): | |
|
195 | fn(loaded=True) | |
|
198 | log(' - invoking registered callbacks: %r\n', shortname) | |
|
199 | with util.timedcm() as stats: | |
|
200 | for fn in _aftercallbacks.get(shortname, []): | |
|
201 | fn(loaded=True) | |
|
202 | log(' > callbacks completed in %s\n', stats) | |
|
196 | 203 | return mod |
|
197 | 204 | |
|
198 | 205 | def _runuisetup(name, ui): |
@@ -225,28 +232,41 b' def _runextsetup(name, ui):' | |||
|
225 | 232 | return True |
|
226 | 233 | |
|
227 | 234 | def loadall(ui, whitelist=None): |
|
235 | if ui.configbool('devel', 'debug.extensions'): | |
|
236 | log = lambda msg, *values: ui.debug('debug.extensions: ', | |
|
237 | msg % values, label='debug.extensions') | |
|
238 | else: | |
|
239 | log = lambda *a, **kw: None | |
|
228 | 240 | result = ui.configitems("extensions") |
|
229 | 241 | if whitelist is not None: |
|
230 | 242 | result = [(k, v) for (k, v) in result if k in whitelist] |
|
231 | 243 | newindex = len(_order) |
|
232 | for (name, path) in result: | |
|
233 | if path: | |
|
234 | if path[0:1] == '!': | |
|
235 | _disabledextensions[name] = path[1:] | |
|
236 | continue | |
|
237 | try: | |
|
238 | load(ui, name, path) | |
|
239 | except Exception as inst: | |
|
240 | msg = stringutil.forcebytestr(inst) | |
|
244 | log('loading %sextensions\n', 'additional ' if newindex else '') | |
|
245 | log('- processing %d entries\n', len(result)) | |
|
246 | with util.timedcm() as stats: | |
|
247 | for (name, path) in result: | |
|
241 | 248 | if path: |
|
242 | ui.warn(_("*** failed to import extension %s from %s: %s\n") | |
|
243 | % (name, path, msg)) | |
|
244 | else: | |
|
245 | ui.warn(_("*** failed to import extension %s: %s\n") | |
|
246 |
|
|
|
247 | if isinstance(inst, error.Hint) and inst.hint: | |
|
248 | ui.warn(_("*** (%s)\n") % inst.hint) | |
|
249 | ui.traceback() | |
|
249 | if path[0:1] == '!': | |
|
250 | if name not in _disabledextensions: | |
|
251 | log(' - skipping disabled extension: %r\n', name) | |
|
252 | _disabledextensions[name] = path[1:] | |
|
253 | continue | |
|
254 | try: | |
|
255 | load(ui, name, path, log) | |
|
256 | except Exception as inst: | |
|
257 | msg = stringutil.forcebytestr(inst) | |
|
258 | if path: | |
|
259 | ui.warn(_("*** failed to import extension %s from %s: %s\n") | |
|
260 | % (name, path, msg)) | |
|
261 | else: | |
|
262 | ui.warn(_("*** failed to import extension %s: %s\n") | |
|
263 | % (name, msg)) | |
|
264 | if isinstance(inst, error.Hint) and inst.hint: | |
|
265 | ui.warn(_("*** (%s)\n") % inst.hint) | |
|
266 | ui.traceback() | |
|
267 | ||
|
268 | log('> loaded %d extensions, total time %s\n', | |
|
269 | len(_order) - newindex, stats) | |
|
250 | 270 | # list of (objname, loadermod, loadername) tuple: |
|
251 | 271 | # - objname is the name of an object in extension module, |
|
252 | 272 | # from which extra information is loaded |
@@ -258,29 +278,47 b' def loadall(ui, whitelist=None):' | |||
|
258 | 278 | earlyextraloaders = [ |
|
259 | 279 | ('configtable', configitems, 'loadconfigtable'), |
|
260 | 280 | ] |
|
281 | ||
|
282 | log('- loading configtable attributes\n') | |
|
261 | 283 | _loadextra(ui, newindex, earlyextraloaders) |
|
262 | 284 | |
|
263 | 285 | broken = set() |
|
286 | log('- executing uisetup hooks\n') | |
|
264 | 287 | for name in _order[newindex:]: |
|
265 | if not _runuisetup(name, ui): | |
|
266 | broken.add(name) | |
|
288 | log(' - running uisetup for %r\n', name) | |
|
289 | with util.timedcm() as stats: | |
|
290 | if not _runuisetup(name, ui): | |
|
291 | log(' - the %r extension uisetup failed\n', name) | |
|
292 | broken.add(name) | |
|
293 | log(' > uisetup for %r took %s\n', name, stats) | |
|
267 | 294 | |
|
295 | log('- executing extsetup hooks\n') | |
|
268 | 296 | for name in _order[newindex:]: |
|
269 | 297 | if name in broken: |
|
270 | 298 | continue |
|
271 | if not _runextsetup(name, ui): | |
|
272 | broken.add(name) | |
|
299 | log(' - running extsetup for %r\n', name) | |
|
300 | with util.timedcm() as stats: | |
|
301 | if not _runextsetup(name, ui): | |
|
302 | log(' - the %r extension extsetup failed\n', name) | |
|
303 | broken.add(name) | |
|
304 | log(' > extsetup for %r took %s\n', name, stats) | |
|
273 | 305 | |
|
274 | 306 | for name in broken: |
|
307 | log(' - disabling broken %r extension\n', name) | |
|
275 | 308 | _extensions[name] = None |
|
276 | 309 | |
|
277 | 310 | # Call aftercallbacks that were never met. |
|
278 | for shortname in _aftercallbacks: | |
|
279 | if shortname in _extensions: | |
|
280 | continue | |
|
311 | log('- executing remaining aftercallbacks\n') | |
|
312 | with util.timedcm() as stats: | |
|
313 | for shortname in _aftercallbacks: | |
|
314 | if shortname in _extensions: | |
|
315 | continue | |
|
281 | 316 | |
|
282 | for fn in _aftercallbacks[shortname]: | |
|
283 | fn(loaded=False) | |
|
317 | for fn in _aftercallbacks[shortname]: | |
|
318 | log(' - extension %r not loaded, notify callbacks\n', | |
|
319 | shortname) | |
|
320 | fn(loaded=False) | |
|
321 | log('> remaining aftercallbacks completed in %s\n', stats) | |
|
284 | 322 | |
|
285 | 323 | # loadall() is called multiple times and lingering _aftercallbacks |
|
286 | 324 | # entries could result in double execution. See issue4646. |
@@ -304,6 +342,7 b' def loadall(ui, whitelist=None):' | |||
|
304 | 342 | # - loadermod is the module where loader is placed |
|
305 | 343 | # - loadername is the name of the function, |
|
306 | 344 | # which takes (ui, extensionname, extraobj) arguments |
|
345 | log('- loading extension registration objects\n') | |
|
307 | 346 | extraloaders = [ |
|
308 | 347 | ('cmdtable', commands, 'loadcmdtable'), |
|
309 | 348 | ('colortable', color, 'loadcolortable'), |
@@ -314,7 +353,10 b' def loadall(ui, whitelist=None):' | |||
|
314 | 353 | ('templatefunc', templatefuncs, 'loadfunction'), |
|
315 | 354 | ('templatekeyword', templatekw, 'loadkeyword'), |
|
316 | 355 | ] |
|
317 | _loadextra(ui, newindex, extraloaders) | |
|
356 | with util.timedcm() as stats: | |
|
357 | _loadextra(ui, newindex, extraloaders) | |
|
358 | log('> extension registration object loading took %s\n', stats) | |
|
359 | log('extension loading complete\n') | |
|
318 | 360 | |
|
319 | 361 | def _loadextra(ui, newindex, extraloaders): |
|
320 | 362 | for name in _order[newindex:]: |
@@ -9,6 +9,7 b'' | |||
|
9 | 9 | from __future__ import absolute_import |
|
10 | 10 | |
|
11 | 11 | import errno |
|
12 | import functools | |
|
12 | 13 | import hashlib |
|
13 | 14 | import os |
|
14 | 15 | import shutil |
@@ -162,9 +163,16 b' def _peerorrepo(ui, path, create=False, ' | |||
|
162 | 163 | """return a repository object for the specified path""" |
|
163 | 164 | obj = _peerlookup(path).instance(ui, path, create, intents=intents) |
|
164 | 165 | ui = getattr(obj, "ui", ui) |
|
166 | if ui.configbool('devel', 'debug.extensions'): | |
|
167 | log = functools.partial( | |
|
168 | ui.debug, 'debug.extensions: ', label='debug.extensions') | |
|
169 | else: | |
|
170 | log = lambda *a, **kw: None | |
|
165 | 171 | for f in presetupfuncs or []: |
|
166 | 172 | f(ui, obj) |
|
173 | log('- executing reposetup hooks\n') | |
|
167 | 174 | for name, module in extensions.extensions(ui): |
|
175 | log(' - running reposetup for %s\n' % (name,)) | |
|
168 | 176 | hook = getattr(module, 'reposetup', None) |
|
169 | 177 | if hook: |
|
170 | 178 | hook(ui, obj) |
@@ -77,18 +77,49 b' show traceback for ImportError of hgext.' | |||
|
77 | 77 | $ (hg help help --traceback --debug --config devel.debug.extensions=yes 2>&1) \ |
|
78 | 78 | > | grep -v '^ ' \ |
|
79 | 79 | > | egrep 'extension..[^p]|^Exception|Traceback|ImportError|not import' |
|
80 | debug.extensions: loading extensions | |
|
81 | debug.extensions: - processing 5 entries | |
|
82 | debug.extensions: - loading extension: 'gpg' | |
|
83 | debug.extensions: > 'gpg' extension loaded in * (glob) | |
|
84 | debug.extensions: - validating extension tables: 'gpg' | |
|
85 | debug.extensions: - invoking registered callbacks: 'gpg' | |
|
86 | debug.extensions: > callbacks completed in * (glob) | |
|
87 | debug.extensions: - loading extension: 'badext' | |
|
80 | 88 | *** failed to import extension badext from $TESTTMP/badext.py: bit bucket overflow |
|
81 | 89 | Traceback (most recent call last): |
|
82 | 90 | Exception: bit bucket overflow |
|
83 | could not import hgext.badext2 (No module named *badext2): trying hgext3rd.badext2 (glob) | |
|
91 | debug.extensions: - loading extension: 'baddocext' | |
|
92 | debug.extensions: > 'baddocext' extension loaded in * (glob) | |
|
93 | debug.extensions: - validating extension tables: 'baddocext' | |
|
94 | debug.extensions: - invoking registered callbacks: 'baddocext' | |
|
95 | debug.extensions: > callbacks completed in * (glob) | |
|
96 | debug.extensions: - loading extension: 'badext2' | |
|
97 | debug.extensions: - could not import hgext.badext2 (No module named badext2): trying hgext3rd.badext2 | |
|
84 | 98 | Traceback (most recent call last): |
|
85 | 99 | ImportError: No module named *badext2 (glob) |
|
86 |
could not import hgext3rd.badext2 (No module named |
|
|
100 | debug.extensions: - could not import hgext3rd.badext2 (No module named badext2): trying badext2 | |
|
87 | 101 | Traceback (most recent call last): |
|
88 | 102 | ImportError: No module named *badext2 (glob) |
|
89 | 103 | *** failed to import extension badext2: No module named badext2 |
|
90 | 104 | Traceback (most recent call last): |
|
91 | 105 | ImportError: No module named badext2 |
|
106 | debug.extensions: > loaded 2 extensions, total time * (glob) | |
|
107 | debug.extensions: - loading configtable attributes | |
|
108 | debug.extensions: - executing uisetup hooks | |
|
109 | debug.extensions: - running uisetup for 'gpg' | |
|
110 | debug.extensions: > uisetup for 'gpg' took * (glob) | |
|
111 | debug.extensions: - running uisetup for 'baddocext' | |
|
112 | debug.extensions: > uisetup for 'baddocext' took * (glob) | |
|
113 | debug.extensions: - executing extsetup hooks | |
|
114 | debug.extensions: - running extsetup for 'gpg' | |
|
115 | debug.extensions: > extsetup for 'gpg' took * (glob) | |
|
116 | debug.extensions: - running extsetup for 'baddocext' | |
|
117 | debug.extensions: > extsetup for 'baddocext' took * (glob) | |
|
118 | debug.extensions: - executing remaining aftercallbacks | |
|
119 | debug.extensions: > remaining aftercallbacks completed in * (glob) | |
|
120 | debug.extensions: - loading extension registration objects | |
|
121 | debug.extensions: > extension registration object loading took * (glob) | |
|
122 | debug.extensions: extension loading complete | |
|
92 | 123 | |
|
93 | 124 | confirm that there's no crash when an extension's documentation is bad |
|
94 | 125 |
General Comments 0
You need to be logged in to leave comments.
Login now