| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- # Copyright (C) 2008 The Android Open Source Project
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- 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):
- 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.
- #
- try:
- r, w = os.pipe()
- pid = os.fork()
- if not pid:
- os.dup2(w, 1)
- os.dup2(w, 2)
- os.close(r)
- os.close(w)
- active = True
- return
- os.dup2(r, 0)
- os.close(r)
- os.close(w)
- _BecomePager(pager)
- except Exception:
- print("fatal: cannot start pager '%s'" % pager, file=sys.stderr)
- sys.exit(255)
- def _SelectPager(globalConfig):
- try:
- return os.environ['GIT_PAGER']
- except KeyError:
- pass
- pager = globalConfig.GetString('core.pager')
- if pager:
- return pager
- try:
- return os.environ['PAGER']
- except KeyError:
- pass
- return 'less'
- def _BecomePager(pager):
- # Delaying execution of the pager until we have output
- # ready works around a long-standing bug in popularly
- # available versions of 'less', a better 'more'.
- #
- _a, _b, _c = select.select([0], [], [0])
- os.environ['LESS'] = 'FRSX'
- try:
- os.execvp(pager, [pager])
- except OSError:
- os.execv('/bin/sh', ['sh', '-c', pager])
|