##// END OF EJS Templates
hook: fix bug (reuse of variable) introduced in 872d49dd577a...
Sune Foldager -
r10103:37679dbf stable
parent child Browse files
Show More
@@ -1,147 +1,147 b''
1 1 # hook.py - hook support for mercurial
2 2 #
3 3 # Copyright 2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2, incorporated herein by reference.
7 7
8 8 from i18n import _
9 9 import os, sys
10 10 import extensions, util
11 11
12 12 def _pythonhook(ui, repo, name, hname, funcname, args, throw):
13 13 '''call python hook. hook is callable object, looked up as
14 14 name in python module. if callable returns "true", hook
15 15 fails, else passes. if hook raises exception, treated as
16 16 hook failure. exception propagates if throw is "true".
17 17
18 18 reason for "true" meaning "hook failed" is so that
19 19 unmodified commands (e.g. mercurial.commands.update) can
20 20 be run as hooks without wrappers to convert return values.'''
21 21
22 22 ui.note(_("calling hook %s: %s\n") % (hname, funcname))
23 23 obj = funcname
24 24 if not hasattr(obj, '__call__'):
25 25 d = funcname.rfind('.')
26 26 if d == -1:
27 27 raise util.Abort(_('%s hook is invalid ("%s" not in '
28 28 'a module)') % (hname, funcname))
29 29 modname = funcname[:d]
30 oldpaths = sys.path[:]
30 oldpaths = sys.path
31 31 if hasattr(sys, "frozen"):
32 32 # binary installs require sys.path manipulation
33 path, name = os.path.split(modname)
34 if path and name:
35 sys.path.append(path)
36 modname = name
33 modpath, modfile = os.path.split(modname)
34 if modpath and modfile:
35 sys.path = sys.path[:] + [modpath]
36 modname = modfile
37 37 try:
38 38 obj = __import__(modname)
39 39 except ImportError:
40 40 e1 = sys.exc_type, sys.exc_value, sys.exc_traceback
41 41 try:
42 42 # extensions are loaded with hgext_ prefix
43 43 obj = __import__("hgext_%s" % modname)
44 44 except ImportError:
45 45 e2 = sys.exc_type, sys.exc_value, sys.exc_traceback
46 46 if ui.tracebackflag:
47 47 ui.warn(_('exception from first failed import attempt:\n'))
48 48 ui.traceback(e1)
49 49 if ui.tracebackflag:
50 50 ui.warn(_('exception from second failed import attempt:\n'))
51 51 ui.traceback(e2)
52 52 raise util.Abort(_('%s hook is invalid '
53 53 '(import of "%s" failed)') %
54 54 (hname, modname))
55 55 sys.path = oldpaths
56 56 try:
57 57 for p in funcname.split('.')[1:]:
58 58 obj = getattr(obj, p)
59 59 except AttributeError:
60 60 raise util.Abort(_('%s hook is invalid '
61 61 '("%s" is not defined)') %
62 62 (hname, funcname))
63 63 if not hasattr(obj, '__call__'):
64 64 raise util.Abort(_('%s hook is invalid '
65 65 '("%s" is not callable)') %
66 66 (hname, funcname))
67 67 try:
68 68 r = obj(ui=ui, repo=repo, hooktype=name, **args)
69 69 except KeyboardInterrupt:
70 70 raise
71 71 except Exception, exc:
72 72 if isinstance(exc, util.Abort):
73 73 ui.warn(_('error: %s hook failed: %s\n') %
74 74 (hname, exc.args[0]))
75 75 else:
76 76 ui.warn(_('error: %s hook raised an exception: '
77 77 '%s\n') % (hname, exc))
78 78 if throw:
79 79 raise
80 80 ui.traceback()
81 81 return True
82 82 if r:
83 83 if throw:
84 84 raise util.Abort(_('%s hook failed') % hname)
85 85 ui.warn(_('warning: %s hook failed\n') % hname)
86 86 return r
87 87
88 88 def _exthook(ui, repo, name, cmd, args, throw):
89 89 ui.note(_("running hook %s: %s\n") % (name, cmd))
90 90
91 91 env = {}
92 92 for k, v in args.iteritems():
93 93 if hasattr(v, '__call__'):
94 94 v = v()
95 95 env['HG_' + k.upper()] = v
96 96
97 97 if repo:
98 98 cwd = repo.root
99 99 else:
100 100 cwd = os.getcwd()
101 101 r = util.system(cmd, environ=env, cwd=cwd)
102 102 if r:
103 103 desc, r = util.explain_exit(r)
104 104 if throw:
105 105 raise util.Abort(_('%s hook %s') % (name, desc))
106 106 ui.warn(_('warning: %s hook %s\n') % (name, desc))
107 107 return r
108 108
109 109 _redirect = False
110 110 def redirect(state):
111 111 global _redirect
112 112 _redirect = state
113 113
114 114 def hook(ui, repo, name, throw=False, **args):
115 115 r = False
116 116
117 117 oldstdout = -1
118 118 if _redirect:
119 119 stdoutno = sys.__stdout__.fileno()
120 120 stderrno = sys.__stderr__.fileno()
121 121 # temporarily redirect stdout to stderr, if possible
122 122 if stdoutno >= 0 and stderrno >= 0:
123 123 oldstdout = os.dup(stdoutno)
124 124 os.dup2(stderrno, stdoutno)
125 125
126 126 try:
127 127 for hname, cmd in ui.configitems('hooks'):
128 128 if hname.split('.')[0] != name or not cmd:
129 129 continue
130 130 if hasattr(cmd, '__call__'):
131 131 r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r
132 132 elif cmd.startswith('python:'):
133 133 if cmd.count(':') >= 2:
134 134 path, cmd = cmd[7:].rsplit(':', 1)
135 135 mod = extensions.loadpath(path, 'hghook.%s' % hname)
136 136 hookfn = getattr(mod, cmd)
137 137 else:
138 138 hookfn = cmd[7:].strip()
139 139 r = _pythonhook(ui, repo, name, hname, hookfn, args, throw) or r
140 140 else:
141 141 r = _exthook(ui, repo, hname, cmd, args, throw) or r
142 142 finally:
143 143 if _redirect and oldstdout >= 0:
144 144 os.dup2(oldstdout, stdoutno)
145 145 os.close(oldstdout)
146 146
147 147 return r
General Comments 0
You need to be logged in to leave comments. Login now