Mercurial > public > mercurial-scm > hg-stable
comparison 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 |
comparison
equal
deleted
inserted
replaced
2153:635653cd73ab | 2155:ff255b41b4aa |
---|---|
9 import filelog, manifest, changelog, dirstate, repo | 9 import filelog, manifest, changelog, dirstate, repo |
10 from node import * | 10 from node import * |
11 from i18n import gettext as _ | 11 from i18n import gettext as _ |
12 from demandload import * | 12 from demandload import * |
13 demandload(globals(), "appendfile changegroup") | 13 demandload(globals(), "appendfile changegroup") |
14 demandload(globals(), "re lock transaction tempfile stat mdiff errno ui revlog") | 14 demandload(globals(), "re lock transaction tempfile stat mdiff errno ui") |
15 demandload(globals(), "revlog sys traceback") | |
15 | 16 |
16 class localrepository(object): | 17 class localrepository(object): |
17 def __del__(self): | 18 def __del__(self): |
18 self.transhandle = None | 19 self.transhandle = None |
19 def __init__(self, parentui, path=None, create=0): | 20 def __init__(self, parentui, path=None, create=0): |
69 if create: | 70 if create: |
70 os.mkdir(self.path) | 71 os.mkdir(self.path) |
71 os.mkdir(self.join("data")) | 72 os.mkdir(self.join("data")) |
72 | 73 |
73 self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root) | 74 self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root) |
75 | |
74 def hook(self, name, throw=False, **args): | 76 def hook(self, name, throw=False, **args): |
77 def callhook(hname, funcname): | |
78 '''call python hook. hook is callable object, looked up as | |
79 name in python module. if callable returns "true", hook | |
80 passes, else fails. if hook raises exception, treated as | |
81 hook failure. exception propagates if throw is "true".''' | |
82 | |
83 self.ui.note(_("calling hook %s: %s\n") % (hname, funcname)) | |
84 d = funcname.rfind('.') | |
85 if d == -1: | |
86 raise util.Abort(_('%s hook is invalid ("%s" not in a module)') | |
87 % (hname, funcname)) | |
88 modname = funcname[:d] | |
89 try: | |
90 obj = __import__(modname) | |
91 except ImportError: | |
92 raise util.Abort(_('%s hook is invalid ' | |
93 '(import of "%s" failed)') % | |
94 (hname, modname)) | |
95 try: | |
96 for p in funcname.split('.')[1:]: | |
97 obj = getattr(obj, p) | |
98 except AttributeError, err: | |
99 raise util.Abort(_('%s hook is invalid ' | |
100 '("%s" is not defined)') % | |
101 (hname, funcname)) | |
102 if not callable(obj): | |
103 raise util.Abort(_('%s hook is invalid ' | |
104 '("%s" is not callable)') % | |
105 (hname, funcname)) | |
106 try: | |
107 r = obj(ui=ui, repo=repo, hooktype=name, **args) | |
108 except (KeyboardInterrupt, util.SignalInterrupt): | |
109 raise | |
110 except Exception, exc: | |
111 if isinstance(exc, util.Abort): | |
112 self.ui.warn(_('error: %s hook failed: %s\n') % | |
113 (hname, exc.args[0] % exc.args[1:])) | |
114 else: | |
115 self.ui.warn(_('error: %s hook raised an exception: ' | |
116 '%s\n') % (hname, exc)) | |
117 if throw: | |
118 raise | |
119 if "--traceback" in sys.argv[1:]: | |
120 traceback.print_exc() | |
121 return False | |
122 if not r: | |
123 if throw: | |
124 raise util.Abort(_('%s hook failed') % hname) | |
125 self.ui.warn(_('error: %s hook failed\n') % hname) | |
126 return r | |
127 | |
75 def runhook(name, cmd): | 128 def runhook(name, cmd): |
76 self.ui.note(_("running hook %s: %s\n") % (name, cmd)) | 129 self.ui.note(_("running hook %s: %s\n") % (name, cmd)) |
77 env = dict([('HG_' + k.upper(), v) for k, v in args.iteritems()] + | 130 env = dict([('HG_' + k.upper(), v) for k, v in args.iteritems()] + |
78 [(k.upper(), v) for k, v in args.iteritems()]) | 131 [(k.upper(), v) for k, v in args.iteritems()]) |
79 r = util.system(cmd, environ=env, cwd=self.root) | 132 r = util.system(cmd, environ=env, cwd=self.root) |
88 r = True | 141 r = True |
89 hooks = [(hname, cmd) for hname, cmd in self.ui.configitems("hooks") | 142 hooks = [(hname, cmd) for hname, cmd in self.ui.configitems("hooks") |
90 if hname.split(".", 1)[0] == name and cmd] | 143 if hname.split(".", 1)[0] == name and cmd] |
91 hooks.sort() | 144 hooks.sort() |
92 for hname, cmd in hooks: | 145 for hname, cmd in hooks: |
93 r = runhook(hname, cmd) and r | 146 if cmd.startswith('python:'): |
147 r = callhook(hname, cmd[7:].strip()) and r | |
148 else: | |
149 r = runhook(hname, cmd) and r | |
94 return r | 150 return r |
95 | 151 |
96 def tags(self): | 152 def tags(self): |
97 '''return a mapping of tag to node''' | 153 '''return a mapping of tag to node''' |
98 if not self.tagscache: | 154 if not self.tagscache: |