##// END OF EJS Templates
Merge with stable
Merge with stable

File last commit:

r9851:9e7b2c49 default
r9937:5c990169 merge default
Show More
hook.py
147 lines | 5.2 KiB | text/x-python | PythonLexer
Matt Mackall
hooks: separate hook code into a separate module
r4622 # hook.py - hook support for mercurial
#
# Copyright 2007 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
Matt Mackall
hooks: separate hook code into a separate module
r4622
from i18n import _
Simon Heimberg
separate import lines from mercurial and general python modules
r8312 import os, sys
import extensions, util
Matt Mackall
hooks: separate hook code into a separate module
r4622
def _pythonhook(ui, repo, name, hname, funcname, args, throw):
'''call python hook. hook is callable object, looked up as
name in python module. if callable returns "true", hook
fails, else passes. if hook raises exception, treated as
hook failure. exception propagates if throw is "true".
reason for "true" meaning "hook failed" is so that
unmodified commands (e.g. mercurial.commands.update) can
be run as hooks without wrappers to convert return values.'''
ui.note(_("calling hook %s: %s\n") % (hname, funcname))
obj = funcname
Dirkjan Ochtman
some modernization cleanups, forward compatibility
r8366 if not hasattr(obj, '__call__'):
Matt Mackall
hooks: separate hook code into a separate module
r4622 d = funcname.rfind('.')
if d == -1:
raise util.Abort(_('%s hook is invalid ("%s" not in '
'a module)') % (hname, funcname))
modname = funcname[:d]
Steve Borho
hook: fix full path imports on Windows (issue1779)...
r9332 oldpaths = sys.path[:]
if hasattr(sys, "frozen"):
# binary installs require sys.path manipulation
path, name = os.path.split(modname)
if path and name:
sys.path.append(path)
modname = name
Matt Mackall
hooks: separate hook code into a separate module
r4622 try:
obj = __import__(modname)
except ImportError:
Bryan O'Sullivan
Make it possible to debug failed hook imports via use of --traceback...
r9851 e1 = sys.exc_type, sys.exc_value, sys.exc_traceback
Matt Mackall
hooks: separate hook code into a separate module
r4622 try:
# extensions are loaded with hgext_ prefix
obj = __import__("hgext_%s" % modname)
except ImportError:
Bryan O'Sullivan
Make it possible to debug failed hook imports via use of --traceback...
r9851 e2 = sys.exc_type, sys.exc_value, sys.exc_traceback
if ui.tracebackflag:
ui.warn(_('exception from first failed import attempt:\n'))
ui.traceback(e1)
if ui.tracebackflag:
ui.warn(_('exception from second failed import attempt:\n'))
ui.traceback(e2)
Matt Mackall
hooks: separate hook code into a separate module
r4622 raise util.Abort(_('%s hook is invalid '
'(import of "%s" failed)') %
(hname, modname))
Steve Borho
hook: fix full path imports on Windows (issue1779)...
r9332 sys.path = oldpaths
Matt Mackall
hooks: separate hook code into a separate module
r4622 try:
for p in funcname.split('.')[1:]:
obj = getattr(obj, p)
Benoit Boissinot
remove unused variables
r7280 except AttributeError:
Matt Mackall
hooks: separate hook code into a separate module
r4622 raise util.Abort(_('%s hook is invalid '
'("%s" is not defined)') %
(hname, funcname))
Dirkjan Ochtman
some modernization cleanups, forward compatibility
r8366 if not hasattr(obj, '__call__'):
Matt Mackall
hooks: separate hook code into a separate module
r4622 raise util.Abort(_('%s hook is invalid '
'("%s" is not callable)') %
(hname, funcname))
try:
r = obj(ui=ui, repo=repo, hooktype=name, **args)
Matt Mackall
error: move SignalInterrupt...
r7644 except KeyboardInterrupt:
Matt Mackall
hooks: separate hook code into a separate module
r4622 raise
except Exception, exc:
if isinstance(exc, util.Abort):
ui.warn(_('error: %s hook failed: %s\n') %
(hname, exc.args[0]))
else:
ui.warn(_('error: %s hook raised an exception: '
'%s\n') % (hname, exc))
if throw:
raise
Matt Mackall
ui: print_exc() -> traceback()
r8206 ui.traceback()
Matt Mackall
hooks: separate hook code into a separate module
r4622 return True
if r:
if throw:
raise util.Abort(_('%s hook failed') % hname)
ui.warn(_('warning: %s hook failed\n') % hname)
return r
def _exthook(ui, repo, name, cmd, args, throw):
ui.note(_("running hook %s: %s\n") % (name, cmd))
Matt Mackall
Introduce HG_PREPEND to solve pretxn races...
r7787
env = {}
for k, v in args.iteritems():
Dirkjan Ochtman
some modernization cleanups, forward compatibility
r8366 if hasattr(v, '__call__'):
Matt Mackall
Introduce HG_PREPEND to solve pretxn races...
r7787 v = v()
env['HG_' + k.upper()] = v
Matt Mackall
hooks: fix pre- and post- hooks specified in .hg/hgrc...
r5869 if repo:
cwd = repo.root
else:
cwd = os.getcwd()
r = util.system(cmd, environ=env, cwd=cwd)
Matt Mackall
hooks: separate hook code into a separate module
r4622 if r:
desc, r = util.explain_exit(r)
if throw:
raise util.Abort(_('%s hook %s') % (name, desc))
ui.warn(_('warning: %s hook %s\n') % (name, desc))
return r
Matt Mackall
hook: redirect stdout to stderr for ssh and http servers
r5833 _redirect = False
def redirect(state):
Alexis S. L. Carvalho
hook.py: fix redirections introduced by 323b9c55b328...
r6266 global _redirect
Matt Mackall
hook: redirect stdout to stderr for ssh and http servers
r5833 _redirect = state
Matt Mackall
hooks: separate hook code into a separate module
r4622 def hook(ui, repo, name, throw=False, **args):
r = False
Matt Mackall
hook: redirect stdout to stderr for ssh and http servers
r5833
Sune Foldager
hook: only redirect stdout if it and stderr are valid files...
r9658 oldstdout = -1
Matt Mackall
hook: redirect stdout to stderr for ssh and http servers
r5833 if _redirect:
Sune Foldager
hook: only redirect stdout if it and stderr are valid files...
r9658 stdoutno = sys.__stdout__.fileno()
stderrno = sys.__stderr__.fileno()
# temporarily redirect stdout to stderr, if possible
if stdoutno >= 0 and stderrno >= 0:
oldstdout = os.dup(stdoutno)
os.dup2(stderrno, stdoutno)
Matt Mackall
hook: redirect stdout to stderr for ssh and http servers
r5833
Jesse Long
hooks: restore io correctly on exception
r7416 try:
Matt Mackall
replace util.sort with sorted built-in...
r8209 for hname, cmd in ui.configitems('hooks'):
Jesse Long
hooks: restore io correctly on exception
r7416 if hname.split('.')[0] != name or not cmd:
continue
Dirkjan Ochtman
some modernization cleanups, forward compatibility
r8366 if hasattr(cmd, '__call__'):
Jesse Long
hooks: restore io correctly on exception
r7416 r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r
elif cmd.startswith('python:'):
Steve Borho
hook: fix full path imports on Windows (issue1779)...
r9332 if cmd.count(':') >= 2:
path, cmd = cmd[7:].rsplit(':', 1)
mod = extensions.loadpath(path, 'hghook.%s' % hname)
Alexander Solovyov
ability to load hooks from arbitrary python module
r7916 hookfn = getattr(mod, cmd)
else:
hookfn = cmd[7:].strip()
r = _pythonhook(ui, repo, name, hname, hookfn, args, throw) or r
Jesse Long
hooks: restore io correctly on exception
r7416 else:
r = _exthook(ui, repo, hname, cmd, args, throw) or r
finally:
Sune Foldager
hook: only redirect stdout if it and stderr are valid files...
r9658 if _redirect and oldstdout >= 0:
os.dup2(oldstdout, stdoutno)
Jesse Long
hooks: restore io correctly on exception
r7416 os.close(oldstdout)
Alexis S. L. Carvalho
hook.py: fix redirections introduced by 323b9c55b328...
r6266
return r