Mercurial > hg
changeset 11182:3c368a1c962d stable
pager: fork and exec pager as parent process
With the pager as the child process instead of the parent process, the
termination of the parent Mercurial process can cause the terminal to return
before the pager exits. Inverting the relationship prevents that issue.
Platforms without fork() will continue to use util.popen().
author | Brodie Rao <brodie@bitheap.org> |
---|---|
date | Mon, 03 May 2010 14:00:34 -0500 |
parents | 3b3261f6d9ba |
children | a890cc501501 db2897926d14 |
files | hgext/color.py hgext/pager.py |
diffstat | 2 files changed, 24 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/color.py Thu May 13 11:30:50 2010 -0500 +++ b/hgext/color.py Mon May 03 14:00:34 2010 -0500 @@ -333,11 +333,14 @@ def _setupcmd(ui, cmd, table, func, effectsmap): '''patch in command to command table and load effect map''' + # check isatty() before anything else changes it (like pager) + isatty = sys.__stdout__.isatty() + def nocolor(orig, *args, **opts): if (opts['no_color'] or opts['color'] == 'never' or (opts['color'] == 'auto' and (os.environ.get('TERM') == 'dumb' - or not sys.__stdout__.isatty()))): + or not isatty))): del opts['no_color'] del opts['color'] return orig(*args, **opts)
--- a/hgext/pager.py Thu May 13 11:30:50 2010 -0500 +++ b/hgext/pager.py Mon May 03 14:00:34 2010 -0500 @@ -49,9 +49,27 @@ specify them in the global .hgrc ''' -import sys, os, signal +import sys, os, signal, shlex from mercurial import dispatch, util, extensions +def _runpager(p): + if not hasattr(os, 'fork'): + sys.stderr = sys.stdout = util.popen(p, 'wb') + return + fdin, fdout = os.pipe() + pid = os.fork() + if pid == 0: + os.close(fdin) + os.dup2(fdout, sys.stdout.fileno()) + os.dup2(fdout, sys.stderr.fileno()) + os.close(fdout) + return + os.dup2(fdin, sys.stdin.fileno()) + os.close(fdin) + os.close(fdout) + args = shlex.split(p) + os.execvp(args[0], args) + def uisetup(ui): def pagecmd(orig, ui, options, cmd, cmdfunc): p = ui.config("pager", "pager", os.environ.get("PAGER")) @@ -60,7 +78,7 @@ if (cmd in attend or (cmd not in ui.configlist('pager', 'ignore') and not attend)): ui.setconfig('ui', 'interactive', False) - sys.stderr = sys.stdout = util.popen(p, "wb") + _runpager(p) if ui.configbool('pager', 'quiet'): signal.signal(signal.SIGPIPE, signal.SIG_DFL) return orig(ui, options, cmd, cmdfunc)