Mercurial > public > mercurial-scm > hg-stable
diff mercurial/localrepo.py @ 2155:ff255b41b4aa
support hooks written in python.
to write hook in python, create module with hook function inside.
make sure mercurial can import module (put it in $PYTHONPATH or load it
as extension). hook function should look like this:
def myhook(ui, repo, hooktype, **kwargs):
if hook_passes:
return True
elif hook_explicitly_fails:
return False
elif some_other_failure:
import util
raise util.Abort('helpful failure message')
else:
return
# implicit return of None makes hook fail!
then in .hgrc, add hook with "python:" prefix:
[hooks]
commit = python:mymodule.myhook
author | Vadim Gelfer <vadim.gelfer@gmail.com> |
---|---|
date | Fri, 28 Apr 2006 15:50:22 -0700 |
parents | f15c6394d90d |
children | 628bf85f07ee |
line wrap: on
line diff
--- a/mercurial/localrepo.py Fri Apr 28 14:50:23 2006 -0700 +++ b/mercurial/localrepo.py Fri Apr 28 15:50:22 2006 -0700 @@ -11,7 +11,8 @@ from i18n import gettext as _ from demandload import * demandload(globals(), "appendfile changegroup") -demandload(globals(), "re lock transaction tempfile stat mdiff errno ui revlog") +demandload(globals(), "re lock transaction tempfile stat mdiff errno ui") +demandload(globals(), "revlog sys traceback") class localrepository(object): def __del__(self): @@ -71,7 +72,59 @@ os.mkdir(self.join("data")) self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root) + def hook(self, name, throw=False, **args): + def callhook(hname, funcname): + '''call python hook. hook is callable object, looked up as + name in python module. if callable returns "true", hook + passes, else fails. if hook raises exception, treated as + hook failure. exception propagates if throw is "true".''' + + self.ui.note(_("calling hook %s: %s\n") % (hname, funcname)) + d = funcname.rfind('.') + if d == -1: + raise util.Abort(_('%s hook is invalid ("%s" not in a module)') + % (hname, funcname)) + modname = funcname[:d] + try: + obj = __import__(modname) + except ImportError: + raise util.Abort(_('%s hook is invalid ' + '(import of "%s" failed)') % + (hname, modname)) + try: + for p in funcname.split('.')[1:]: + obj = getattr(obj, p) + except AttributeError, err: + raise util.Abort(_('%s hook is invalid ' + '("%s" is not defined)') % + (hname, funcname)) + if not callable(obj): + raise util.Abort(_('%s hook is invalid ' + '("%s" is not callable)') % + (hname, funcname)) + try: + r = obj(ui=ui, repo=repo, hooktype=name, **args) + except (KeyboardInterrupt, util.SignalInterrupt): + raise + except Exception, exc: + if isinstance(exc, util.Abort): + self.ui.warn(_('error: %s hook failed: %s\n') % + (hname, exc.args[0] % exc.args[1:])) + else: + self.ui.warn(_('error: %s hook raised an exception: ' + '%s\n') % (hname, exc)) + if throw: + raise + if "--traceback" in sys.argv[1:]: + traceback.print_exc() + return False + if not r: + if throw: + raise util.Abort(_('%s hook failed') % hname) + self.ui.warn(_('error: %s hook failed\n') % hname) + return r + def runhook(name, cmd): self.ui.note(_("running hook %s: %s\n") % (name, cmd)) env = dict([('HG_' + k.upper(), v) for k, v in args.iteritems()] + @@ -90,7 +143,10 @@ if hname.split(".", 1)[0] == name and cmd] hooks.sort() for hname, cmd in hooks: - r = runhook(hname, cmd) and r + if cmd.startswith('python:'): + r = callhook(hname, cmd[7:].strip()) and r + else: + r = runhook(hname, cmd) and r return r def tags(self):