pager: work around bug in python 2.4's subprocess module (issue3533) stable
authorMichael Bacarella <mbacarella@janestreet.com>
Fri, 06 Jul 2012 18:06:52 -0400
branchstable
changeset 17250 18f935b4c05a
parent 17249 7d4747c711a9
child 17251 98166640b356
pager: work around bug in python 2.4's subprocess module (issue3533) hg v2.2.2 fixed the pager on Windows, but broke it on Python 2.4. This patch only uses the new behavior if Python >= 2.5 is detected.
hgext/pager.py
--- a/hgext/pager.py	Wed Jul 25 19:02:35 2012 +0200
+++ b/hgext/pager.py	Fri Jul 06 18:06:52 2012 -0400
@@ -53,7 +53,35 @@
 
 testedwith = 'internal'
 
-def _runpager(ui, p):
+def _pagerfork(ui, p):
+    if not util.safehasattr(os, 'fork'):
+        sys.stdout = util.popen(p, 'wb')
+        if ui._isatty(sys.stderr):
+            sys.stderr = sys.stdout
+        return
+    fdin, fdout = os.pipe()
+    pid = os.fork()
+    if pid == 0:
+        os.close(fdin)
+        os.dup2(fdout, sys.stdout.fileno())
+        if ui._isatty(sys.stderr):
+            os.dup2(fdout, sys.stderr.fileno())
+        os.close(fdout)
+        return
+    os.dup2(fdin, sys.stdin.fileno())
+    os.close(fdin)
+    os.close(fdout)
+    try:
+        os.execvp('/bin/sh', ['/bin/sh', '-c', p])
+    except OSError, e:
+        if e.errno == errno.ENOENT:
+            # no /bin/sh, try executing the pager directly
+            args = shlex.split(p)
+            os.execvp(args[0], args)
+        else:
+            raise
+
+def _pagersubprocess(ui, p):
     pager = subprocess.Popen(p, shell=True, bufsize=-1,
                              close_fds=util.closefds, stdin=subprocess.PIPE,
                              stdout=sys.stdout, stderr=sys.stderr)
@@ -71,6 +99,15 @@
         os.dup2(stderr, sys.stderr.fileno())
         pager.wait()
 
+def _runpager(ui, p):
+    # The subprocess module shipped with Python <= 2.4 is buggy (issue3533).
+    # The compat version is buggy on Windows (issue3225), but has been shipping
+    # with hg for a long time.  Preserve existing functionality.
+    if sys.version_info >= (2, 5):
+        _pagersubprocess(ui, p)
+    else:
+        _pagerfork(ui, p)
+
 def uisetup(ui):
     if '--debugger' in sys.argv or not ui.formatted():
         return