99 ui.warn(_('error: %s hook raised an exception: ' |
99 ui.warn(_('error: %s hook raised an exception: ' |
100 '%s\n') % (hname, exc)) |
100 '%s\n') % (hname, exc)) |
101 if throw: |
101 if throw: |
102 raise |
102 raise |
103 ui.traceback() |
103 ui.traceback() |
104 return True |
104 return True, True |
105 finally: |
105 finally: |
106 sys.stdout, sys.stderr, sys.stdin = old |
106 sys.stdout, sys.stderr, sys.stdin = old |
107 duration = time.time() - starttime |
107 duration = time.time() - starttime |
108 ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n', |
108 ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n', |
109 name, funcname, duration) |
109 name, funcname, duration) |
110 if r: |
110 if r: |
111 if throw: |
111 if throw: |
112 raise error.HookAbort(_('%s hook failed') % hname) |
112 raise error.HookAbort(_('%s hook failed') % hname) |
113 ui.warn(_('warning: %s hook failed\n') % hname) |
113 ui.warn(_('warning: %s hook failed\n') % hname) |
114 return r |
114 return r, False |
115 |
115 |
116 def _exthook(ui, repo, name, cmd, args, throw): |
116 def _exthook(ui, repo, name, cmd, args, throw): |
117 ui.note(_("running hook %s: %s\n") % (name, cmd)) |
117 ui.note(_("running hook %s: %s\n") % (name, cmd)) |
118 |
118 |
119 starttime = time.time() |
119 starttime = time.time() |
168 hooks.append((hname, cmd)) |
168 hooks.append((hname, cmd)) |
169 |
169 |
170 res = runhooks(ui, repo, name, hooks, throw=throw, **args) |
170 res = runhooks(ui, repo, name, hooks, throw=throw, **args) |
171 r = False |
171 r = False |
172 for hname, cmd in hooks: |
172 for hname, cmd in hooks: |
173 r = res[hname] or r |
173 r = res[hname][0] or r |
174 return r |
174 return r |
175 |
175 |
176 def runhooks(ui, repo, name, hooks, throw=False, **args): |
176 def runhooks(ui, repo, name, hooks, throw=False, **args): |
177 res = {} |
177 res = {} |
178 oldstdout = -1 |
178 oldstdout = -1 |
191 except (OSError, AttributeError): |
191 except (OSError, AttributeError): |
192 # files seem to be bogus, give up on redirecting (WSGI, etc) |
192 # files seem to be bogus, give up on redirecting (WSGI, etc) |
193 pass |
193 pass |
194 |
194 |
195 if callable(cmd): |
195 if callable(cmd): |
196 r = _pythonhook(ui, repo, name, hname, cmd, args, throw) |
196 r, raised = _pythonhook(ui, repo, name, hname, cmd, args, throw) |
197 elif cmd.startswith('python:'): |
197 elif cmd.startswith('python:'): |
198 if cmd.count(':') >= 2: |
198 if cmd.count(':') >= 2: |
199 path, cmd = cmd[7:].rsplit(':', 1) |
199 path, cmd = cmd[7:].rsplit(':', 1) |
200 path = util.expandpath(path) |
200 path = util.expandpath(path) |
201 if repo: |
201 if repo: |
206 ui.write(_("loading %s hook failed:\n") % hname) |
206 ui.write(_("loading %s hook failed:\n") % hname) |
207 raise |
207 raise |
208 hookfn = getattr(mod, cmd) |
208 hookfn = getattr(mod, cmd) |
209 else: |
209 else: |
210 hookfn = cmd[7:].strip() |
210 hookfn = cmd[7:].strip() |
211 r = _pythonhook(ui, repo, name, hname, hookfn, args, throw) |
211 r, raised = _pythonhook(ui, repo, name, hname, hookfn, args, |
|
212 throw) |
212 else: |
213 else: |
213 r = _exthook(ui, repo, hname, cmd, args, throw) |
214 r = _exthook(ui, repo, hname, cmd, args, throw) |
214 |
215 raised = False |
215 res[hname] = r |
216 |
|
217 res[hname] = r, raised |
216 |
218 |
217 # The stderr is fully buffered on Windows when connected to a pipe. |
219 # The stderr is fully buffered on Windows when connected to a pipe. |
218 # A forcible flush is required to make small stderr data in the |
220 # A forcible flush is required to make small stderr data in the |
219 # remote side available to the client immediately. |
221 # remote side available to the client immediately. |
220 sys.stderr.flush() |
222 sys.stderr.flush() |