annotate mercurial/hook.py @ 31144:5564fcd031df

hook: lower inflated use of sys.__stdout__ and __stderr__ They were introduced at 9f76df0edb7d, where sys.stdout could be replaced by sys.stderr. After that, we've changed the way of stdout redirection by afccc64eea73, so we no longer need to reference the original __stdout__ and __stderr__ objects. Let's move away from using __std*__ objects so we can simply wrap sys.std* objects for Python 3 porting.
author Yuya Nishihara <yuya@tcha.org>
date Tue, 08 Nov 2016 22:41:45 +0900
parents ad56204f733e
children 39d13b8c101d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1 # hook.py - hook support for mercurial
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
2 #
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
3 # Copyright 2007 Matt Mackall <mpm@selenic.com>
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
4 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8209
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10103
diff changeset
6 # GNU General Public License version 2 or any later version.
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
7
26537
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
8 from __future__ import absolute_import
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
9
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
10 import os
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
11 import sys
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
12 import time
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
13
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
14 from .i18n import _
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
15 from . import (
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
16 demandimport,
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
17 error,
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
18 extensions,
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
19 util,
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26214
diff changeset
20 )
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
21
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
22 def _pythonhook(ui, repo, name, hname, funcname, args, throw):
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
23 '''call python hook. hook is callable object, looked up as
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
24 name in python module. if callable returns "true", hook
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
25 fails, else passes. if hook raises exception, treated as
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
26 hook failure. exception propagates if throw is "true".
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
27
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
28 reason for "true" meaning "hook failed" is so that
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
29 unmodified commands (e.g. mercurial.commands.update) can
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
30 be run as hooks without wrappers to convert return values.'''
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
31
21797
b009dd135aa0 hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 20548
diff changeset
32 if callable(funcname):
20548
5bd6a9fec103 hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents: 20547
diff changeset
33 obj = funcname
5bd6a9fec103 hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents: 20547
diff changeset
34 funcname = obj.__module__ + "." + obj.__name__
5bd6a9fec103 hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents: 20547
diff changeset
35 else:
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
36 d = funcname.rfind('.')
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
37 if d == -1:
27332
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 27227
diff changeset
38 raise error.HookLoadError(
28777
cedbe8723d99 hook: even fewer parentheses for load errors
Siddharth Agarwal <sid0@fb.com>
parents: 28751
diff changeset
39 _('%s hook is invalid: "%s" not in a module')
27332
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 27227
diff changeset
40 % (hname, funcname))
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
41 modname = funcname[:d]
10103
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
42 oldpaths = sys.path
14942
4a28cb4df1f8 windows: check util.mainfrozen() instead of ad-hoc checks everywhere
Augie Fackler <durin42@gmail.com>
parents: 14916
diff changeset
43 if util.mainfrozen():
9332
872d49dd577a hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents: 8366
diff changeset
44 # binary installs require sys.path manipulation
10103
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
45 modpath, modfile = os.path.split(modname)
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
46 if modpath and modfile:
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
47 sys.path = sys.path[:] + [modpath]
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
48 modname = modfile
25812
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
49 with demandimport.deactivated():
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
50 try:
25812
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
51 obj = __import__(modname)
28780
b892e424f88c hook: don't crash on syntax errors in python hooks
Siddharth Agarwal <sid0@fb.com>
parents: 28779
diff changeset
52 except (ImportError, SyntaxError):
28749
2058e1a894f2 hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents: 27868
diff changeset
53 e1 = sys.exc_info()
25812
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
54 try:
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
55 # extensions are loaded with hgext_ prefix
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
56 obj = __import__("hgext_%s" % modname)
28780
b892e424f88c hook: don't crash on syntax errors in python hooks
Siddharth Agarwal <sid0@fb.com>
parents: 28779
diff changeset
57 except (ImportError, SyntaxError):
28749
2058e1a894f2 hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents: 27868
diff changeset
58 e2 = sys.exc_info()
25812
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
59 if ui.tracebackflag:
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
60 ui.warn(_('exception from first failed import '
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
61 'attempt:\n'))
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
62 ui.traceback(e1)
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
63 if ui.tracebackflag:
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
64 ui.warn(_('exception from second failed import '
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
65 'attempt:\n'))
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25619
diff changeset
66 ui.traceback(e2)
28751
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28750
diff changeset
67
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28750
diff changeset
68 if not ui.tracebackflag:
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28750
diff changeset
69 tracebackhint = _(
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28750
diff changeset
70 'run with --traceback for stack trace')
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28750
diff changeset
71 else:
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28750
diff changeset
72 tracebackhint = None
27332
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 27227
diff changeset
73 raise error.HookLoadError(
28750
0c9e914029be hook: fewer parentheses for hook load errors
Siddharth Agarwal <sid0@fb.com>
parents: 28749
diff changeset
74 _('%s hook is invalid: import of "%s" failed') %
28751
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28750
diff changeset
75 (hname, modname), hint=tracebackhint)
9332
872d49dd577a hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents: 8366
diff changeset
76 sys.path = oldpaths
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
77 try:
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
78 for p in funcname.split('.')[1:]:
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
79 obj = getattr(obj, p)
7278
810ca383da9c remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6764
diff changeset
80 except AttributeError:
27332
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 27227
diff changeset
81 raise error.HookLoadError(
28750
0c9e914029be hook: fewer parentheses for hook load errors
Siddharth Agarwal <sid0@fb.com>
parents: 28749
diff changeset
82 _('%s hook is invalid: "%s" is not defined')
27332
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 27227
diff changeset
83 % (hname, funcname))
21797
b009dd135aa0 hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 20548
diff changeset
84 if not callable(obj):
27332
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 27227
diff changeset
85 raise error.HookLoadError(
28750
0c9e914029be hook: fewer parentheses for hook load errors
Siddharth Agarwal <sid0@fb.com>
parents: 28749
diff changeset
86 _('%s hook is invalid: "%s" is not callable')
27332
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 27227
diff changeset
87 % (hname, funcname))
20547
9d9f8ccffead hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents: 20422
diff changeset
88
9d9f8ccffead hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents: 20422
diff changeset
89 ui.note(_("calling hook %s: %s\n") % (hname, funcname))
9d9f8ccffead hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents: 20422
diff changeset
90 starttime = time.time()
9d9f8ccffead hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents: 20422
diff changeset
91
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
92 try:
25495
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24860
diff changeset
93 r = obj(ui=ui, repo=repo, hooktype=name, **args)
26214
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25812
diff changeset
94 except Exception as exc:
27227
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26537
diff changeset
95 if isinstance(exc, error.Abort):
25495
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24860
diff changeset
96 ui.warn(_('error: %s hook failed: %s\n') %
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24860
diff changeset
97 (hname, exc.args[0]))
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24860
diff changeset
98 else:
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24860
diff changeset
99 ui.warn(_('error: %s hook raised an exception: '
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24860
diff changeset
100 '%s\n') % (hname, exc))
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24860
diff changeset
101 if throw:
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
102 raise
28779
2a71d9483199 hook: for python hook exceptions, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28777
diff changeset
103 if not ui.tracebackflag:
2a71d9483199 hook: for python hook exceptions, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28777
diff changeset
104 ui.warn(_('(run with --traceback for stack trace)\n'))
25495
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24860
diff changeset
105 ui.traceback()
27379
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 27378
diff changeset
106 return True, True
14889
a59058fd074a hooks: redirect stdout/err/in to the ui descriptors when calling python hooks
Idan Kamara <idankk86@gmail.com>
parents: 14711
diff changeset
107 finally:
18671
1c305128e5b9 blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents: 18111
diff changeset
108 duration = time.time() - starttime
18691
4f485bd68f1d blackbox: do not translate the log messages
Durham Goode <durham@fb.com>
parents: 18671
diff changeset
109 ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n',
20548
5bd6a9fec103 hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents: 20547
diff changeset
110 name, funcname, duration)
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
111 if r:
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
112 if throw:
23415
cdbb85489c41 hook: raise a more specialized HookAbort exception when a hook fails
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21797
diff changeset
113 raise error.HookAbort(_('%s hook failed') % hname)
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
114 ui.warn(_('warning: %s hook failed\n') % hname)
27379
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 27378
diff changeset
115 return r, False
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
116
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
117 def _exthook(ui, repo, name, cmd, args, throw):
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
118 ui.note(_("running hook %s: %s\n") % (name, cmd))
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
119
18671
1c305128e5b9 blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents: 18111
diff changeset
120 starttime = time.time()
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
121 env = {}
27391
520defbc0335 hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27379
diff changeset
122
520defbc0335 hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27379
diff changeset
123 # make in-memory changes visible to external process
27868
10695f8f3323 dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents: 27501
diff changeset
124 if repo is not None:
10695f8f3323 dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents: 27501
diff changeset
125 tr = repo.currenttransaction()
10695f8f3323 dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents: 27501
diff changeset
126 repo.dirstate.write(tr)
10695f8f3323 dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents: 27501
diff changeset
127 if tr and tr.writepending():
10695f8f3323 dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents: 27501
diff changeset
128 env['HG_PENDING'] = repo.root
27391
520defbc0335 hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27379
diff changeset
129
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
130 for k, v in args.iteritems():
21797
b009dd135aa0 hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 20548
diff changeset
131 if callable(v):
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
132 v = v()
13207
1775382ff833 hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13121
diff changeset
133 if isinstance(v, dict):
1775382ff833 hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13121
diff changeset
134 # make the dictionary element order stable across Python
1775382ff833 hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13121
diff changeset
135 # implementations
1775382ff833 hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13121
diff changeset
136 v = ('{' +
1775382ff833 hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13121
diff changeset
137 ', '.join('%r: %r' % i for i in sorted(v.iteritems())) +
1775382ff833 hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13121
diff changeset
138 '}')
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
139 env['HG_' + k.upper()] = v
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
140
5876
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5834
diff changeset
141 if repo:
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5834
diff changeset
142 cwd = repo.root
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5834
diff changeset
143 else:
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5834
diff changeset
144 cwd = os.getcwd()
23270
41c03b7592ed util.system: use ui.system() in place of optional ui.fout parameter
Yuya Nishihara <yuya@tcha.org>
parents: 23268
diff changeset
145 r = ui.system(cmd, environ=env, cwd=cwd)
18671
1c305128e5b9 blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents: 18111
diff changeset
146
1c305128e5b9 blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents: 18111
diff changeset
147 duration = time.time() - starttime
18691
4f485bd68f1d blackbox: do not translate the log messages
Durham Goode <durham@fb.com>
parents: 18671
diff changeset
148 ui.log('exthook', 'exthook-%s: %s finished in %0.2f seconds\n',
18671
1c305128e5b9 blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents: 18111
diff changeset
149 name, cmd, duration)
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
150 if r:
14234
600e64004eb5 rename explain_exit to explainexit
Adrian Buehlmann <adrian@cadifra.com>
parents: 13207
diff changeset
151 desc, r = util.explainexit(r)
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
152 if throw:
23415
cdbb85489c41 hook: raise a more specialized HookAbort exception when a hook fails
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21797
diff changeset
153 raise error.HookAbort(_('%s hook %s') % (name, desc))
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
154 ui.warn(_('warning: %s hook %s\n') % (name, desc))
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
155 return r
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
156
29688
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
157 # represent an untrusted hook command
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
158 _fromuntrusted = object()
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
159
15896
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15521
diff changeset
160 def _allhooks(ui):
29687
3112c5e18835 hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29686
diff changeset
161 """return a list of (hook-id, cmd) pairs sorted by priority"""
3112c5e18835 hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29686
diff changeset
162 hooks = _hookitems(ui)
29688
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
163 # Be careful in this section, propagating the real commands from untrusted
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
164 # sources would create a security vulnerability, make sure anything altered
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
165 # in that section uses "_fromuntrusted" as its command.
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
166 untrustedhooks = _hookitems(ui, _untrusted=True)
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
167 for name, value in untrustedhooks.items():
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
168 trustedvalue = hooks.get(name, (None, None, name, _fromuntrusted))
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
169 if value != trustedvalue:
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
170 (lp, lo, lk, lv) = trustedvalue
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
171 hooks[name] = (lp, lo, lk, _fromuntrusted)
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
172 # (end of the security sensitive section)
29687
3112c5e18835 hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29686
diff changeset
173 return [(k, v) for p, o, k, v in sorted(hooks.values())]
3112c5e18835 hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29686
diff changeset
174
29688
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
175 def _hookitems(ui, _untrusted=False):
29687
3112c5e18835 hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29686
diff changeset
176 """return all hooks items ready to be sorted"""
29686
44bd37af54e5 hook: small refactor to store hooks as dict instead of list
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28780
diff changeset
177 hooks = {}
29688
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
178 for name, cmd in ui.configitems('hooks', untrusted=_untrusted):
15896
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15521
diff changeset
179 if not name.startswith('priority'):
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15521
diff changeset
180 priority = ui.configint('hooks', 'priority.%s' % name, 0)
29686
44bd37af54e5 hook: small refactor to store hooks as dict instead of list
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28780
diff changeset
181 hooks[name] = (-priority, len(hooks), name, cmd)
29687
3112c5e18835 hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29686
diff changeset
182 return hooks
15896
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15521
diff changeset
183
5834
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4623
diff changeset
184 _redirect = False
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4623
diff changeset
185 def redirect(state):
6266
9f76df0edb7d hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5876
diff changeset
186 global _redirect
5834
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4623
diff changeset
187 _redirect = state
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4623
diff changeset
188
4623
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
189 def hook(ui, repo, name, throw=False, **args):
17052
15d4d475de9e ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents: 15896
diff changeset
190 if not ui.callhooks:
15d4d475de9e ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents: 15896
diff changeset
191 return False
15d4d475de9e ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents: 15896
diff changeset
192
27377
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 27332
diff changeset
193 hooks = []
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 27332
diff changeset
194 for hname, cmd in _allhooks(ui):
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 27332
diff changeset
195 if hname.split('.')[0] == name and cmd:
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 27332
diff changeset
196 hooks.append((hname, cmd))
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 27332
diff changeset
197
27378
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 27377
diff changeset
198 res = runhooks(ui, repo, name, hooks, throw=throw, **args)
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 27377
diff changeset
199 r = False
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 27377
diff changeset
200 for hname, cmd in hooks:
27379
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 27378
diff changeset
201 r = res[hname][0] or r
27378
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 27377
diff changeset
202 return r
27377
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 27332
diff changeset
203
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 27332
diff changeset
204 def runhooks(ui, repo, name, hooks, throw=False, **args):
27378
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 27377
diff changeset
205 res = {}
9658
852b1f3032d2 hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents: 9332
diff changeset
206 oldstdout = -1
5834
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4623
diff changeset
207
7427
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7278
diff changeset
208 try:
27377
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 27332
diff changeset
209 for hname, cmd in hooks:
17975
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17411
diff changeset
210 if oldstdout == -1 and _redirect:
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17411
diff changeset
211 try:
31144
5564fcd031df hook: lower inflated use of sys.__stdout__ and __stderr__
Yuya Nishihara <yuya@tcha.org>
parents: 31143
diff changeset
212 stdoutno = sys.stdout.fileno()
5564fcd031df hook: lower inflated use of sys.__stdout__ and __stderr__
Yuya Nishihara <yuya@tcha.org>
parents: 31143
diff changeset
213 stderrno = sys.stderr.fileno()
17975
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17411
diff changeset
214 # temporarily redirect stdout to stderr, if possible
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17411
diff changeset
215 if stdoutno >= 0 and stderrno >= 0:
31144
5564fcd031df hook: lower inflated use of sys.__stdout__ and __stderr__
Yuya Nishihara <yuya@tcha.org>
parents: 31143
diff changeset
216 sys.stdout.flush()
17975
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17411
diff changeset
217 oldstdout = os.dup(stdoutno)
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17411
diff changeset
218 os.dup2(stderrno, stdoutno)
17976
2c63896783e3 hooks: be even more forgiven of non-fd descriptors (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17975
diff changeset
219 except (OSError, AttributeError):
2c63896783e3 hooks: be even more forgiven of non-fd descriptors (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17975
diff changeset
220 # files seem to be bogus, give up on redirecting (WSGI, etc)
17975
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17411
diff changeset
221 pass
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17411
diff changeset
222
29688
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
223 if cmd is _fromuntrusted:
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
224 if throw:
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
225 raise error.HookAbort(
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
226 _('untrusted hook %s not executed') % name,
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
227 hint = _("see 'hg help config.trusted'"))
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
228 ui.warn(_('warning: untrusted hook %s not executed\n') % name)
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
229 r = 1
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
230 raised = False
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29687
diff changeset
231 elif callable(cmd):
27379
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 27378
diff changeset
232 r, raised = _pythonhook(ui, repo, name, hname, cmd, args, throw)
7427
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7278
diff changeset
233 elif cmd.startswith('python:'):
9332
872d49dd577a hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents: 8366
diff changeset
234 if cmd.count(':') >= 2:
872d49dd577a hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents: 8366
diff changeset
235 path, cmd = cmd[7:].rsplit(':', 1)
13120
789e0fa2fcea hook: assume relative path to hook is given from repo root
Alexander Solovyov <alexander@solovyov.net>
parents: 11469
diff changeset
236 path = util.expandpath(path)
13121
ecf7d6e0eef0 hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents: 13120
diff changeset
237 if repo:
ecf7d6e0eef0 hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents: 13120
diff changeset
238 path = os.path.join(repo.root, path)
17219
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 17052
diff changeset
239 try:
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 17052
diff changeset
240 mod = extensions.loadpath(path, 'hghook.%s' % hname)
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 17052
diff changeset
241 except Exception:
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 17052
diff changeset
242 ui.write(_("loading %s hook failed:\n") % hname)
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 17052
diff changeset
243 raise
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
244 hookfn = getattr(mod, cmd)
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
245 else:
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
246 hookfn = cmd[7:].strip()
27379
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 27378
diff changeset
247 r, raised = _pythonhook(ui, repo, name, hname, hookfn, args,
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 27378
diff changeset
248 throw)
7427
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7278
diff changeset
249 else:
27378
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 27377
diff changeset
250 r = _exthook(ui, repo, hname, cmd, args, throw)
27379
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 27378
diff changeset
251 raised = False
27378
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 27377
diff changeset
252
27379
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 27378
diff changeset
253 res[hname] = r, raised
24860
2abbf4750915 hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 23426
diff changeset
254
2abbf4750915 hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 23426
diff changeset
255 # The stderr is fully buffered on Windows when connected to a pipe.
2abbf4750915 hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 23426
diff changeset
256 # A forcible flush is required to make small stderr data in the
2abbf4750915 hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 23426
diff changeset
257 # remote side available to the client immediately.
2abbf4750915 hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 23426
diff changeset
258 sys.stderr.flush()
7427
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7278
diff changeset
259 finally:
9658
852b1f3032d2 hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents: 9332
diff changeset
260 if _redirect and oldstdout >= 0:
31144
5564fcd031df hook: lower inflated use of sys.__stdout__ and __stderr__
Yuya Nishihara <yuya@tcha.org>
parents: 31143
diff changeset
261 sys.stdout.flush() # write hook output to stderr fd
9658
852b1f3032d2 hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents: 9332
diff changeset
262 os.dup2(oldstdout, stdoutno)
7427
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7278
diff changeset
263 os.close(oldstdout)
6266
9f76df0edb7d hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5876
diff changeset
264
27378
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 27377
diff changeset
265 return res