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: