##// END OF EJS Templates
extensions: changed to call extsetup() from extensions.loadall()...
Yuya Nishihara -
r9660:e0eae93e default
parent child Browse files
Show More
@@ -1,511 +1,501 b''
1 1 # dispatch.py - command dispatching for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2, incorporated herein by reference.
7 7
8 8 from i18n import _
9 9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time
10 10 import util, commands, hg, fancyopts, extensions, hook, error
11 11 import cmdutil, encoding
12 12 import ui as _ui
13 13
14 14 def run():
15 15 "run the command in sys.argv"
16 16 sys.exit(dispatch(sys.argv[1:]))
17 17
18 18 def dispatch(args):
19 19 "run the command specified in args"
20 20 try:
21 21 u = _ui.ui()
22 22 if '--traceback' in args:
23 23 u.setconfig('ui', 'traceback', 'on')
24 24 except util.Abort, inst:
25 25 sys.stderr.write(_("abort: %s\n") % inst)
26 26 return -1
27 27 except error.ConfigError, inst:
28 28 sys.stderr.write(_("hg: %s\n") % inst)
29 29 return -1
30 30 return _runcatch(u, args)
31 31
32 32 def _runcatch(ui, args):
33 33 def catchterm(*args):
34 34 raise error.SignalInterrupt
35 35
36 36 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
37 37 num = getattr(signal, name, None)
38 38 if num: signal.signal(num, catchterm)
39 39
40 40 try:
41 41 try:
42 42 # enter the debugger before command execution
43 43 if '--debugger' in args:
44 44 pdb.set_trace()
45 45 try:
46 46 return _dispatch(ui, args)
47 47 finally:
48 48 ui.flush()
49 49 except:
50 50 # enter the debugger when we hit an exception
51 51 if '--debugger' in args:
52 52 pdb.post_mortem(sys.exc_info()[2])
53 53 ui.traceback()
54 54 raise
55 55
56 56 # Global exception handling, alphabetically
57 57 # Mercurial-specific first, followed by built-in and library exceptions
58 58 except error.AmbiguousCommand, inst:
59 59 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
60 60 (inst.args[0], " ".join(inst.args[1])))
61 61 except error.ConfigError, inst:
62 62 ui.warn(_("hg: %s\n") % inst.args[0])
63 63 except error.LockHeld, inst:
64 64 if inst.errno == errno.ETIMEDOUT:
65 65 reason = _('timed out waiting for lock held by %s') % inst.locker
66 66 else:
67 67 reason = _('lock held by %s') % inst.locker
68 68 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
69 69 except error.LockUnavailable, inst:
70 70 ui.warn(_("abort: could not lock %s: %s\n") %
71 71 (inst.desc or inst.filename, inst.strerror))
72 72 except error.ParseError, inst:
73 73 if inst.args[0]:
74 74 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
75 75 commands.help_(ui, inst.args[0])
76 76 else:
77 77 ui.warn(_("hg: %s\n") % inst.args[1])
78 78 commands.help_(ui, 'shortlist')
79 79 except error.RepoError, inst:
80 80 ui.warn(_("abort: %s!\n") % inst)
81 81 except error.ResponseError, inst:
82 82 ui.warn(_("abort: %s") % inst.args[0])
83 83 if not isinstance(inst.args[1], basestring):
84 84 ui.warn(" %r\n" % (inst.args[1],))
85 85 elif not inst.args[1]:
86 86 ui.warn(_(" empty string\n"))
87 87 else:
88 88 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
89 89 except error.RevlogError, inst:
90 90 ui.warn(_("abort: %s!\n") % inst)
91 91 except error.SignalInterrupt:
92 92 ui.warn(_("killed!\n"))
93 93 except error.UnknownCommand, inst:
94 94 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
95 95 commands.help_(ui, 'shortlist')
96 96 except util.Abort, inst:
97 97 ui.warn(_("abort: %s\n") % inst)
98 98 except ImportError, inst:
99 99 m = str(inst).split()[-1]
100 100 ui.warn(_("abort: could not import module %s!\n") % m)
101 101 if m in "mpatch bdiff".split():
102 102 ui.warn(_("(did you forget to compile extensions?)\n"))
103 103 elif m in "zlib".split():
104 104 ui.warn(_("(is your Python install correct?)\n"))
105 105 except IOError, inst:
106 106 if hasattr(inst, "code"):
107 107 ui.warn(_("abort: %s\n") % inst)
108 108 elif hasattr(inst, "reason"):
109 109 try: # usually it is in the form (errno, strerror)
110 110 reason = inst.reason.args[1]
111 111 except: # it might be anything, for example a string
112 112 reason = inst.reason
113 113 ui.warn(_("abort: error: %s\n") % reason)
114 114 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
115 115 if ui.debugflag:
116 116 ui.warn(_("broken pipe\n"))
117 117 elif getattr(inst, "strerror", None):
118 118 if getattr(inst, "filename", None):
119 119 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
120 120 else:
121 121 ui.warn(_("abort: %s\n") % inst.strerror)
122 122 else:
123 123 raise
124 124 except OSError, inst:
125 125 if getattr(inst, "filename", None):
126 126 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
127 127 else:
128 128 ui.warn(_("abort: %s\n") % inst.strerror)
129 129 except KeyboardInterrupt:
130 130 try:
131 131 ui.warn(_("interrupted!\n"))
132 132 except IOError, inst:
133 133 if inst.errno == errno.EPIPE:
134 134 if ui.debugflag:
135 135 ui.warn(_("\nbroken pipe\n"))
136 136 else:
137 137 raise
138 138 except MemoryError:
139 139 ui.warn(_("abort: out of memory\n"))
140 140 except SystemExit, inst:
141 141 # Commands shouldn't sys.exit directly, but give a return code.
142 142 # Just in case catch this and and pass exit code to caller.
143 143 return inst.code
144 144 except socket.error, inst:
145 145 ui.warn(_("abort: %s\n") % inst.args[-1])
146 146 except:
147 147 ui.warn(_("** unknown exception encountered, details follow\n"))
148 148 ui.warn(_("** report bug details to "
149 149 "http://mercurial.selenic.com/bts/\n"))
150 150 ui.warn(_("** or mercurial@selenic.com\n"))
151 151 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
152 152 % util.version())
153 153 ui.warn(_("** Extensions loaded: %s\n")
154 154 % ", ".join([x[0] for x in extensions.extensions()]))
155 155 raise
156 156
157 157 return -1
158 158
159 159 def _findrepo(p):
160 160 while not os.path.isdir(os.path.join(p, ".hg")):
161 161 oldp, p = p, os.path.dirname(p)
162 162 if p == oldp:
163 163 return None
164 164
165 165 return p
166 166
167 167 def aliasargs(fn):
168 168 if hasattr(fn, 'args'):
169 169 return fn.args
170 170 return []
171 171
172 172 class cmdalias(object):
173 173 def __init__(self, name, definition, cmdtable):
174 174 self.name = name
175 175 self.definition = definition
176 176 self.args = []
177 177 self.opts = []
178 178 self.help = ''
179 179 self.norepo = True
180 180
181 181 try:
182 182 cmdutil.findcmd(self.name, cmdtable, True)
183 183 self.shadows = True
184 184 except error.UnknownCommand:
185 185 self.shadows = False
186 186
187 187 if not self.definition:
188 188 def fn(ui, *args):
189 189 ui.warn(_("no definition for alias '%s'\n") % self.name)
190 190 return 1
191 191 self.fn = fn
192 192
193 193 return
194 194
195 195 args = shlex.split(self.definition)
196 196 cmd = args.pop(0)
197 197 opts = []
198 198 help = ''
199 199
200 200 try:
201 201 self.fn, self.opts, self.help = cmdutil.findcmd(cmd, cmdtable, False)[1]
202 202 self.args = aliasargs(self.fn) + args
203 203 if cmd not in commands.norepo.split(' '):
204 204 self.norepo = False
205 205 except error.UnknownCommand:
206 206 def fn(ui, *args):
207 207 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
208 208 % (self.name, cmd))
209 209 return 1
210 210 self.fn = fn
211 211 except error.AmbiguousCommand:
212 212 def fn(ui, *args):
213 213 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
214 214 % (self.name, cmd))
215 215 return 1
216 216 self.fn = fn
217 217
218 218 def __call__(self, ui, *args, **opts):
219 219 if self.shadows:
220 220 ui.debug("alias '%s' shadows command\n" % self.name)
221 221
222 222 return self.fn(ui, *args, **opts)
223 223
224 224 def addaliases(ui, cmdtable):
225 225 # aliases are processed after extensions have been loaded, so they
226 226 # may use extension commands. Aliases can also use other alias definitions,
227 227 # but only if they have been defined prior to the current definition.
228 228 for alias, definition in ui.configitems('alias'):
229 229 aliasdef = cmdalias(alias, definition, cmdtable)
230 230 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
231 231 if aliasdef.norepo:
232 232 commands.norepo += ' %s' % alias
233 233
234 234 def _parse(ui, args):
235 235 options = {}
236 236 cmdoptions = {}
237 237
238 238 try:
239 239 args = fancyopts.fancyopts(args, commands.globalopts, options)
240 240 except fancyopts.getopt.GetoptError, inst:
241 241 raise error.ParseError(None, inst)
242 242
243 243 if args:
244 244 cmd, args = args[0], args[1:]
245 245 aliases, i = cmdutil.findcmd(cmd, commands.table,
246 246 ui.config("ui", "strict"))
247 247 cmd = aliases[0]
248 248 args = aliasargs(i[0]) + args
249 249 defaults = ui.config("defaults", cmd)
250 250 if defaults:
251 251 args = map(util.expandpath, shlex.split(defaults)) + args
252 252 c = list(i[1])
253 253 else:
254 254 cmd = None
255 255 c = []
256 256
257 257 # combine global options into local
258 258 for o in commands.globalopts:
259 259 c.append((o[0], o[1], options[o[1]], o[3]))
260 260
261 261 try:
262 262 args = fancyopts.fancyopts(args, c, cmdoptions, True)
263 263 except fancyopts.getopt.GetoptError, inst:
264 264 raise error.ParseError(cmd, inst)
265 265
266 266 # separate global options back out
267 267 for o in commands.globalopts:
268 268 n = o[1]
269 269 options[n] = cmdoptions[n]
270 270 del cmdoptions[n]
271 271
272 272 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
273 273
274 274 def _parseconfig(ui, config):
275 275 """parse the --config options from the command line"""
276 276 for cfg in config:
277 277 try:
278 278 name, value = cfg.split('=', 1)
279 279 section, name = name.split('.', 1)
280 280 if not section or not name:
281 281 raise IndexError
282 282 ui.setconfig(section, name, value)
283 283 except (IndexError, ValueError):
284 284 raise util.Abort(_('malformed --config option: %s') % cfg)
285 285
286 286 def _earlygetopt(aliases, args):
287 287 """Return list of values for an option (or aliases).
288 288
289 289 The values are listed in the order they appear in args.
290 290 The options and values are removed from args.
291 291 """
292 292 try:
293 293 argcount = args.index("--")
294 294 except ValueError:
295 295 argcount = len(args)
296 296 shortopts = [opt for opt in aliases if len(opt) == 2]
297 297 values = []
298 298 pos = 0
299 299 while pos < argcount:
300 300 if args[pos] in aliases:
301 301 if pos + 1 >= argcount:
302 302 # ignore and let getopt report an error if there is no value
303 303 break
304 304 del args[pos]
305 305 values.append(args.pop(pos))
306 306 argcount -= 2
307 307 elif args[pos][:2] in shortopts:
308 308 # short option can have no following space, e.g. hg log -Rfoo
309 309 values.append(args.pop(pos)[2:])
310 310 argcount -= 1
311 311 else:
312 312 pos += 1
313 313 return values
314 314
315 315 def runcommand(lui, repo, cmd, fullargs, ui, options, d):
316 316 # run pre-hook, and abort if it fails
317 317 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs))
318 318 if ret:
319 319 return ret
320 320 ret = _runcommand(ui, options, cmd, d)
321 321 # run post-hook, passing command result
322 322 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
323 323 result = ret)
324 324 return ret
325 325
326 326 _loaded = set()
327 327 def _dispatch(ui, args):
328 328 # read --config before doing anything else
329 329 # (e.g. to change trust settings for reading .hg/hgrc)
330 330 _parseconfig(ui, _earlygetopt(['--config'], args))
331 331
332 332 # check for cwd
333 333 cwd = _earlygetopt(['--cwd'], args)
334 334 if cwd:
335 335 os.chdir(cwd[-1])
336 336
337 337 # read the local repository .hgrc into a local ui object
338 338 path = _findrepo(os.getcwd()) or ""
339 339 if not path:
340 340 lui = ui
341 341 else:
342 342 try:
343 343 lui = ui.copy()
344 344 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
345 345 except IOError:
346 346 pass
347 347
348 348 # now we can expand paths, even ones in .hg/hgrc
349 349 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
350 350 if rpath:
351 351 path = lui.expandpath(rpath[-1])
352 352 lui = ui.copy()
353 353 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
354 354
355 355 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
356 356 # reposetup. Programs like TortoiseHg will call _dispatch several
357 357 # times so we keep track of configured extensions in _loaded.
358 358 extensions.loadall(lui)
359 359 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
360 360
361 # (uisetup is handled in extensions.loadall)
362
363 for name, module in exts:
364 extsetup = getattr(module, 'extsetup', None)
365 if extsetup:
366 try:
367 extsetup(ui)
368 except TypeError:
369 if extsetup.func_code.co_argcount != 0:
370 raise
371 extsetup() # old extsetup with no ui argument
361 # (uisetup and extsetup are handled in extensions.loadall)
372 362
373 363 for name, module in exts:
374 364 cmdtable = getattr(module, 'cmdtable', {})
375 365 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
376 366 if overrides:
377 367 ui.warn(_("extension '%s' overrides commands: %s\n")
378 368 % (name, " ".join(overrides)))
379 369 commands.table.update(cmdtable)
380 370 _loaded.add(name)
381 371
382 372 # (reposetup is handled in hg.repository)
383 373
384 374 addaliases(lui, commands.table)
385 375
386 376 # check for fallback encoding
387 377 fallback = lui.config('ui', 'fallbackencoding')
388 378 if fallback:
389 379 encoding.fallbackencoding = fallback
390 380
391 381 fullargs = args
392 382 cmd, func, args, options, cmdoptions = _parse(lui, args)
393 383
394 384 if options["config"]:
395 385 raise util.Abort(_("Option --config may not be abbreviated!"))
396 386 if options["cwd"]:
397 387 raise util.Abort(_("Option --cwd may not be abbreviated!"))
398 388 if options["repository"]:
399 389 raise util.Abort(_(
400 390 "Option -R has to be separated from other options (e.g. not -qR) "
401 391 "and --repository may only be abbreviated as --repo!"))
402 392
403 393 if options["encoding"]:
404 394 encoding.encoding = options["encoding"]
405 395 if options["encodingmode"]:
406 396 encoding.encodingmode = options["encodingmode"]
407 397 if options["time"]:
408 398 def get_times():
409 399 t = os.times()
410 400 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
411 401 t = (t[0], t[1], t[2], t[3], time.clock())
412 402 return t
413 403 s = get_times()
414 404 def print_time():
415 405 t = get_times()
416 406 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
417 407 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
418 408 atexit.register(print_time)
419 409
420 410 if options['verbose'] or options['debug'] or options['quiet']:
421 411 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
422 412 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
423 413 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
424 414 if options['traceback']:
425 415 ui.setconfig('ui', 'traceback', 'on')
426 416 if options['noninteractive']:
427 417 ui.setconfig('ui', 'interactive', 'off')
428 418
429 419 if options['help']:
430 420 return commands.help_(ui, cmd, options['version'])
431 421 elif options['version']:
432 422 return commands.version_(ui)
433 423 elif not cmd:
434 424 return commands.help_(ui, 'shortlist')
435 425
436 426 repo = None
437 427 if cmd not in commands.norepo.split():
438 428 try:
439 429 repo = hg.repository(ui, path=path)
440 430 ui = repo.ui
441 431 if not repo.local():
442 432 raise util.Abort(_("repository '%s' is not local") % path)
443 433 ui.setconfig("bundle", "mainreporoot", repo.root)
444 434 except error.RepoError:
445 435 if cmd not in commands.optionalrepo.split():
446 436 if args and not path: # try to infer -R from command args
447 437 repos = map(_findrepo, args)
448 438 guess = repos[0]
449 439 if guess and repos.count(guess) == len(repos):
450 440 return _dispatch(ui, ['--repository', guess] + fullargs)
451 441 if not path:
452 442 raise error.RepoError(_("There is no Mercurial repository"
453 443 " here (.hg not found)"))
454 444 raise
455 445 args.insert(0, repo)
456 446 elif rpath:
457 447 ui.warn("warning: --repository ignored\n")
458 448
459 449 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
460 450 return runcommand(lui, repo, cmd, fullargs, ui, options, d)
461 451
462 452 def _runcommand(ui, options, cmd, cmdfunc):
463 453 def checkargs():
464 454 try:
465 455 return cmdfunc()
466 456 except error.SignatureError:
467 457 raise error.ParseError(cmd, _("invalid arguments"))
468 458
469 459 if options['profile']:
470 460 format = ui.config('profiling', 'format', default='text')
471 461
472 462 if not format in ['text', 'kcachegrind']:
473 463 ui.warn(_("unrecognized profiling format '%s'"
474 464 " - Ignored\n") % format)
475 465 format = 'text'
476 466
477 467 output = ui.config('profiling', 'output')
478 468
479 469 if output:
480 470 path = ui.expandpath(output)
481 471 ostream = open(path, 'wb')
482 472 else:
483 473 ostream = sys.stderr
484 474
485 475 try:
486 476 from mercurial import lsprof
487 477 except ImportError:
488 478 raise util.Abort(_(
489 479 'lsprof not available - install from '
490 480 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
491 481 p = lsprof.Profiler()
492 482 p.enable(subcalls=True)
493 483 try:
494 484 return checkargs()
495 485 finally:
496 486 p.disable()
497 487
498 488 if format == 'kcachegrind':
499 489 import lsprofcalltree
500 490 calltree = lsprofcalltree.KCacheGrind(p)
501 491 calltree.output(ostream)
502 492 else:
503 493 # format == 'text'
504 494 stats = lsprof.Stats(p.getstats())
505 495 stats.sort()
506 496 stats.pprint(top=10, file=ostream, climit=5)
507 497
508 498 if output:
509 499 ostream.close()
510 500 else:
511 501 return checkargs()
@@ -1,181 +1,191 b''
1 1 # extensions.py - extension handling for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2, incorporated herein by reference.
7 7
8 8 import imp, os
9 9 import util, cmdutil, help
10 10 from i18n import _, gettext
11 11
12 12 _extensions = {}
13 13 _order = []
14 14
15 15 def extensions():
16 16 for name in _order:
17 17 module = _extensions[name]
18 18 if module:
19 19 yield name, module
20 20
21 21 def find(name):
22 22 '''return module with given extension name'''
23 23 try:
24 24 return _extensions[name]
25 25 except KeyError:
26 26 for k, v in _extensions.iteritems():
27 27 if k.endswith('.' + name) or k.endswith('/' + name):
28 28 return v
29 29 raise KeyError(name)
30 30
31 31 def loadpath(path, module_name):
32 32 module_name = module_name.replace('.', '_')
33 33 path = util.expandpath(path)
34 34 if os.path.isdir(path):
35 35 # module/__init__.py style
36 36 d, f = os.path.split(path.rstrip('/'))
37 37 fd, fpath, desc = imp.find_module(f, [d])
38 38 return imp.load_module(module_name, fd, fpath, desc)
39 39 else:
40 40 return imp.load_source(module_name, path)
41 41
42 42 def load(ui, name, path):
43 43 # unused ui argument kept for backwards compatibility
44 44 if name.startswith('hgext.') or name.startswith('hgext/'):
45 45 shortname = name[6:]
46 46 else:
47 47 shortname = name
48 48 if shortname in _extensions:
49 49 return
50 50 _extensions[shortname] = None
51 51 if path:
52 52 # the module will be loaded in sys.modules
53 53 # choose an unique name so that it doesn't
54 54 # conflicts with other modules
55 55 mod = loadpath(path, 'hgext.%s' % name)
56 56 else:
57 57 def importh(name):
58 58 mod = __import__(name)
59 59 components = name.split('.')
60 60 for comp in components[1:]:
61 61 mod = getattr(mod, comp)
62 62 return mod
63 63 try:
64 64 mod = importh("hgext.%s" % name)
65 65 except ImportError:
66 66 mod = importh(name)
67 67 _extensions[shortname] = mod
68 68 _order.append(shortname)
69 69
70 70 def loadall(ui):
71 71 result = ui.configitems("extensions")
72 72 newindex = len(_order)
73 73 for (name, path) in result:
74 74 if path:
75 75 if path[0] == '!':
76 76 continue
77 77 try:
78 78 load(ui, name, path)
79 79 except KeyboardInterrupt:
80 80 raise
81 81 except Exception, inst:
82 82 if path:
83 83 ui.warn(_("*** failed to import extension %s from %s: %s\n")
84 84 % (name, path, inst))
85 85 else:
86 86 ui.warn(_("*** failed to import extension %s: %s\n")
87 87 % (name, inst))
88 88 if ui.traceback():
89 89 return 1
90 90
91 91 for name in _order[newindex:]:
92 92 uisetup = getattr(_extensions[name], 'uisetup', None)
93 93 if uisetup:
94 94 uisetup(ui)
95 95
96 for name in _order[newindex:]:
97 extsetup = getattr(_extensions[name], 'extsetup', None)
98 if extsetup:
99 try:
100 extsetup(ui)
101 except TypeError:
102 if extsetup.func_code.co_argcount != 0:
103 raise
104 extsetup() # old extsetup with no ui argument
105
96 106 def wrapcommand(table, command, wrapper):
97 107 aliases, entry = cmdutil.findcmd(command, table)
98 108 for alias, e in table.iteritems():
99 109 if e is entry:
100 110 key = alias
101 111 break
102 112
103 113 origfn = entry[0]
104 114 def wrap(*args, **kwargs):
105 115 return util.checksignature(wrapper)(
106 116 util.checksignature(origfn), *args, **kwargs)
107 117
108 118 wrap.__doc__ = getattr(origfn, '__doc__')
109 119 wrap.__module__ = getattr(origfn, '__module__')
110 120
111 121 newentry = list(entry)
112 122 newentry[0] = wrap
113 123 table[key] = tuple(newentry)
114 124 return entry
115 125
116 126 def wrapfunction(container, funcname, wrapper):
117 127 def wrap(*args, **kwargs):
118 128 return wrapper(origfn, *args, **kwargs)
119 129
120 130 origfn = getattr(container, funcname)
121 131 setattr(container, funcname, wrap)
122 132 return origfn
123 133
124 134 def disabled():
125 135 '''find disabled extensions from hgext
126 136 returns a dict of {name: desc}, and the max name length'''
127 137
128 138 import hgext
129 139 extpath = os.path.dirname(os.path.abspath(hgext.__file__))
130 140
131 141 try: # might not be a filesystem path
132 142 files = os.listdir(extpath)
133 143 except OSError:
134 144 return None, 0
135 145
136 146 exts = {}
137 147 maxlength = 0
138 148 for e in files:
139 149
140 150 if e.endswith('.py'):
141 151 name = e.rsplit('.', 1)[0]
142 152 path = os.path.join(extpath, e)
143 153 else:
144 154 name = e
145 155 path = os.path.join(extpath, e, '__init__.py')
146 156 if not os.path.exists(path):
147 157 continue
148 158
149 159 if name in exts or name in _order or name == '__init__':
150 160 continue
151 161
152 162 try:
153 163 file = open(path)
154 164 except IOError:
155 165 continue
156 166 else:
157 167 doc = help.moduledoc(file)
158 168 file.close()
159 169
160 170 if doc: # extracting localized synopsis
161 171 exts[name] = gettext(doc).splitlines()[0]
162 172 else:
163 173 exts[name] = _('(no help text available)')
164 174
165 175 if len(name) > maxlength:
166 176 maxlength = len(name)
167 177
168 178 return exts, maxlength
169 179
170 180 def enabled():
171 181 '''return a dict of {name: desc} of extensions, and the max name length'''
172 182 exts = {}
173 183 maxlength = 0
174 184 exthelps = []
175 185 for ename, ext in extensions():
176 186 doc = (gettext(ext.__doc__) or _('(no help text available)'))
177 187 ename = ename.split('.')[-1]
178 188 maxlength = max(len(ename), maxlength)
179 189 exts[ename] = doc.splitlines()[0].strip()
180 190
181 191 return exts, maxlength
General Comments 0
You need to be logged in to leave comments. Login now