Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/commands.py @ 2573: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
2572:d22d730c96ed | 2573: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: |