pager: recreate stdout to make it line-buffered
We want to see partial command results as soon as possible. But the buffering
mode of stdout (= pager's stdin) was set to fully-buffered because it isn't
associated with a tty. So, this patch recreates new stdout object to force its
buffering mode.
Because two file objects are associated with the same stdout fd and their
destructors will call close(), one of them must be closed carefully. Python
expects that the stdout fd never be closed even after sys.stdout.close() [1],
but newstdout has no such hack. So this patch calls newstdout.close()
immediately before duplicating the original stdout fd to sys.stdout.
operation sys.stdout newstdout fd
--------------------- ---------- --------- --------
newstdout.close() open closed closed
os.dup2(stdoutfd, ..) open closed open
del sys.stdout closed closed open [1]
[1]: https://hg.python.org/cpython/file/v2.7.10/Python/sysmodule.c#l1391
pager: rename variables of backup fds
The next patch will add backup file objects, so the original variable names
would be confusing.
pager: inline _pagersubprocess() into _runpager()
We don't need _pagersubprocess() because the fork version was removed
at
59d794154e8d.
ui: send traceback of devel warning to appropriate output stream
If ui.ferr is a command-server channel, traceback should be written to it.
util.system: compare fileno to see if it needs stdout redirection
Future patches will reopen stdout to be line-buffered, so sys.stdout may
be different object than sys.__stdout__.
exchange: move stream clone logic into pull code path
Stream clones are a special case of clones. Clones are a special case of
pull. Most of the logic for deciding what to do at pull time is in
exchange.py. It makes sense for the stream clone determination to live
there as well.
This patch moves the calling of the stream clone code into pull(). The
checks in streamclone.canperformstreamclone() ensure that we don't
perform a stream clone unless it is possible.
A future patch will convert maybeperformstreamclone() to accept a
pullop to make it consistent with everything else in pull(). It will
also grow some functionality (in case you doubted the necessity of a 4
line function).