Support pager on Windows
Windows does not support pipe|fork, but we can simulate by creating
the pager as a child process, redirecting stdout/in/err appropriately
and then waiting for the child process to terminate after we are
done executing the repo command.
Change-Id: I5dd2bdeb4095e4d93bc678802e53c6d4eda0235b
diff --git a/main.py b/main.py
index 386b4f1..a6538c2 100755
--- a/main.py
+++ b/main.py
@@ -55,7 +55,7 @@
from error import RepoChangedException
import gitc_utils
from manifest_xml import GitcManifest, XmlManifest
-from pager import RunPager
+from pager import RunPager, TerminatePager
from wrapper import WrapperPath, Wrapper
from subcmds import all_commands
@@ -542,6 +542,7 @@
print('fatal: %s' % e, file=sys.stderr)
result = 128
+ TerminatePager()
sys.exit(result)
if __name__ == '__main__':
diff --git a/pager.py b/pager.py
index c621141..0521c0c 100755
--- a/pager.py
+++ b/pager.py
@@ -16,19 +16,53 @@
from __future__ import print_function
import os
import select
+import subprocess
import sys
+import platform_utils
+
active = False
+pager_process = None
+old_stdout = None
+old_stderr = None
def RunPager(globalConfig):
- global active
-
if not os.isatty(0) or not os.isatty(1):
return
pager = _SelectPager(globalConfig)
if pager == '' or pager == 'cat':
return
+ if platform_utils.isWindows():
+ _PipePager(pager);
+ else:
+ _ForkPager(pager)
+
+def TerminatePager():
+ global pager_process, old_stdout, old_stderr
+ if pager_process:
+ sys.stdout.flush()
+ sys.stderr.flush()
+ pager_process.stdin.close()
+ pager_process.wait();
+ pager_process = None
+ # Restore initial stdout/err in case there is more output in this process
+ # after shutting down the pager process
+ sys.stdout = old_stdout
+ sys.stderr = old_stderr
+
+def _PipePager(pager):
+ global pager_process, old_stdout, old_stderr
+ assert pager_process is None, "Only one active pager process at a time"
+ # Create pager process, piping stdout/err into its stdin
+ pager_process = subprocess.Popen([pager], stdin=subprocess.PIPE, stdout=sys.stdout, stderr=sys.stderr)
+ old_stdout = sys.stdout
+ old_stderr = sys.stderr
+ sys.stdout = pager_process.stdin
+ sys.stderr = pager_process.stdin
+
+def _ForkPager(pager):
+ global active
# This process turns into the pager; a child it forks will
# do the real processing and output back to the pager. This
# is necessary to keep the pager in control of the tty.