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