comparison mercurial/commands.py @ 2572:b13a98bd078e

fix problems with external module handling. found by benoit boissinot. first fix is to not store module objects in commands.external dict, instead use module names for key into sys.modules. this prevents circular reference during cleanup of aborted transaction. second is to get name right during import of external module.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Thu, 06 Jul 2006 15:03:34 -0700
parents 83cfd95eafb5
children 78c2903fcabe
comparison
equal deleted inserted replaced
2571:d22d730c96ed 2572:b13a98bd078e
3369 external = {} 3369 external = {}
3370 3370
3371 def findext(name): 3371 def findext(name):
3372 '''return module with given extension name''' 3372 '''return module with given extension name'''
3373 try: 3373 try:
3374 return external[name] 3374 return sys.modules[external[name]]
3375 except KeyError: 3375 except KeyError:
3376 dotname = '.' + name 3376 dotname = '.' + name
3377 for k, v in external.iteritems(): 3377 for k, v in external.iteritems():
3378 if k.endswith('.' + name) or v.__name__ == name: 3378 if k.endswith('.' + name) or v == name:
3379 return v 3379 return sys.modules[v]
3380 raise KeyError(name) 3380 raise KeyError(name)
3381 3381
3382 def dispatch(args): 3382 def dispatch(args):
3383 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM': 3383 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
3384 num = getattr(signal, name, None) 3384 num = getattr(signal, name, None)
3388 u = ui.ui(traceback='--traceback' in sys.argv[1:]) 3388 u = ui.ui(traceback='--traceback' in sys.argv[1:])
3389 except util.Abort, inst: 3389 except util.Abort, inst:
3390 sys.stderr.write(_("abort: %s\n") % inst) 3390 sys.stderr.write(_("abort: %s\n") % inst)
3391 return -1 3391 return -1
3392 3392
3393 for x in u.extensions(): 3393 for ext_name, load_from_name in u.extensions():
3394 try: 3394 try:
3395 if x[1]: 3395 if load_from_name:
3396 # the module will be loaded in sys.modules 3396 # the module will be loaded in sys.modules
3397 # choose an unique name so that it doesn't 3397 # choose an unique name so that it doesn't
3398 # conflicts with other modules 3398 # conflicts with other modules
3399 module_name = "hgext_%s" % x[0].replace('.', '_') 3399 module_name = "hgext_%s" % ext_name.replace('.', '_')
3400 mod = imp.load_source(module_name, x[1]) 3400 mod = imp.load_source(module_name, load_from_name)
3401 else: 3401 else:
3402 def importh(name): 3402 def importh(name):
3403 mod = __import__(name) 3403 mod = __import__(name)
3404 components = name.split('.') 3404 components = name.split('.')
3405 for comp in components[1:]: 3405 for comp in components[1:]:
3406 mod = getattr(mod, comp) 3406 mod = getattr(mod, comp)
3407 return mod 3407 return mod
3408 try: 3408 try:
3409 name = 'hgext.' + x[0] 3409 mod = importh("hgext.%s" % ext_name)
3410 mod = importh(name)
3411 except ImportError: 3410 except ImportError:
3412 name = x[0] 3411 mod = importh(ext_name)
3413 mod = importh(name) 3412 external[ext_name] = mod.__name__
3414 external[name] = mod
3415 except (util.SignalInterrupt, KeyboardInterrupt): 3413 except (util.SignalInterrupt, KeyboardInterrupt):
3416 raise 3414 raise
3417 except Exception, inst: 3415 except Exception, inst:
3418 u.warn(_("*** failed to import extension %s: %s\n") % (x[0], inst)) 3416 u.warn(_("*** failed to import extension %s: %s\n") % (x[0], inst))
3419 if u.print_exc(): 3417 if u.print_exc():
3420 return 1 3418 return 1
3421 3419
3422 for x in external.itervalues(): 3420 for name in external.itervalues():
3423 uisetup = getattr(x, 'uisetup', None) 3421 mod = sys.modules[name]
3422 uisetup = getattr(mod, 'uisetup', None)
3424 if uisetup: 3423 if uisetup:
3425 uisetup(u) 3424 uisetup(u)
3426 cmdtable = getattr(x, 'cmdtable', {}) 3425 cmdtable = getattr(mod, 'cmdtable', {})
3427 for t in cmdtable: 3426 for t in cmdtable:
3428 if t in table: 3427 if t in table:
3429 u.warn(_("module %s overrides %s\n") % (x.__name__, t)) 3428 u.warn(_("module %s overrides %s\n") % (name, t))
3430 table.update(cmdtable) 3429 table.update(cmdtable)
3431 3430
3432 try: 3431 try:
3433 cmd, func, args, options, cmdoptions = parse(u, args) 3432 cmd, func, args, options, cmdoptions = parse(u, args)
3434 if options["time"]: 3433 if options["time"]:
3473 if cmd not in norepo.split(): 3472 if cmd not in norepo.split():
3474 try: 3473 try:
3475 if not repo: 3474 if not repo:
3476 repo = hg.repository(u, path=path) 3475 repo = hg.repository(u, path=path)
3477 u = repo.ui 3476 u = repo.ui
3478 for x in external.itervalues(): 3477 for name in external.itervalues():
3479 if hasattr(x, 'reposetup'): 3478 mod = sys.modules[name]
3480 x.reposetup(u, repo) 3479 if hasattr(mod, 'reposetup'):
3480 mod.reposetup(u, repo)
3481 except hg.RepoError: 3481 except hg.RepoError:
3482 if cmd not in optionalrepo.split(): 3482 if cmd not in optionalrepo.split():
3483 raise 3483 raise
3484 d = lambda: func(u, repo, *args, **cmdoptions) 3484 d = lambda: func(u, repo, *args, **cmdoptions)
3485 else: 3485 else: