##// END OF EJS Templates
extensions: add detailed loading information...
Martijn Pieters -
r38834:d5895867 default
parent child Browse files
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 % (name, msg))
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 *badext2): trying badext2 (glob)
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