##// END OF EJS Templates
hook: move stdio redirection to context manager...
Gregory Szorc -
r45140:3cbbfd0b default
parent child Browse files
Show More
@@ -7,6 +7,7 b''
7 7
8 8 from __future__ import absolute_import
9 9
10 import contextlib
10 11 import os
11 12 import sys
12 13
@@ -259,26 +260,45 b' def hook(ui, repo, htype, throw=False, *'
259 260 return r
260 261
261 262
263 @contextlib.contextmanager
264 def redirect_stdio():
265 """Redirects stdout to stderr, if possible."""
266
267 oldstdout = -1
268 try:
269 if _redirect:
270 try:
271 stdoutno = procutil.stdout.fileno()
272 stderrno = procutil.stderr.fileno()
273 # temporarily redirect stdout to stderr, if possible
274 if stdoutno >= 0 and stderrno >= 0:
275 procutil.stdout.flush()
276 oldstdout = os.dup(stdoutno)
277 os.dup2(stderrno, stdoutno)
278 except (OSError, AttributeError):
279 # files seem to be bogus, give up on redirecting (WSGI, etc)
280 pass
281
282 yield
283
284 finally:
285 # The stderr is fully buffered on Windows when connected to a pipe.
286 # A forcible flush is required to make small stderr data in the
287 # remote side available to the client immediately.
288 procutil.stderr.flush()
289
290 if _redirect and oldstdout >= 0:
291 procutil.stdout.flush() # write hook output to stderr fd
292 os.dup2(oldstdout, stdoutno)
293 os.close(oldstdout)
294
295
262 296 def runhooks(ui, repo, htype, hooks, throw=False, **args):
263 297 args = pycompat.byteskwargs(args)
264 298 res = {}
265 oldstdout = -1
266 299
267 try:
300 with redirect_stdio():
268 301 for hname, cmd in hooks:
269 if oldstdout == -1 and _redirect:
270 try:
271 stdoutno = procutil.stdout.fileno()
272 stderrno = procutil.stderr.fileno()
273 # temporarily redirect stdout to stderr, if possible
274 if stdoutno >= 0 and stderrno >= 0:
275 procutil.stdout.flush()
276 oldstdout = os.dup(stdoutno)
277 os.dup2(stderrno, stdoutno)
278 except (OSError, AttributeError):
279 # files seem to be bogus, give up on redirecting (WSGI, etc)
280 pass
281
282 302 if cmd is _fromuntrusted:
283 303 if throw:
284 304 raise error.HookAbort(
@@ -312,15 +332,5 b' def runhooks(ui, repo, htype, hooks, thr'
312 332 raised = False
313 333
314 334 res[hname] = r, raised
315 finally:
316 # The stderr is fully buffered on Windows when connected to a pipe.
317 # A forcible flush is required to make small stderr data in the
318 # remote side available to the client immediately.
319 procutil.stderr.flush()
320
321 if _redirect and oldstdout >= 0:
322 procutil.stdout.flush() # write hook output to stderr fd
323 os.dup2(oldstdout, stdoutno)
324 os.close(oldstdout)
325 335
326 336 return res
General Comments 0
You need to be logged in to leave comments. Login now