2019-06-13 06:30:51 +00:00
|
|
|
# -*- coding:utf-8 -*-
|
2008-10-21 14:00:00 +00:00
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
|
2012-11-02 05:59:27 +00:00
|
|
|
from __future__ import print_function
|
2008-10-21 14:00:00 +00:00
|
|
|
import os
|
|
|
|
import select
|
2016-11-01 22:51:59 +00:00
|
|
|
import subprocess
|
2008-10-21 14:00:00 +00:00
|
|
|
import sys
|
|
|
|
|
2016-11-01 22:51:59 +00:00
|
|
|
import platform_utils
|
|
|
|
|
2008-10-21 14:00:00 +00:00
|
|
|
active = False
|
2016-11-01 22:51:59 +00:00
|
|
|
pager_process = None
|
|
|
|
old_stdout = None
|
|
|
|
old_stderr = None
|
2008-10-21 14:00:00 +00:00
|
|
|
|
2020-02-12 06:20:19 +00:00
|
|
|
|
2008-10-21 14:00:00 +00:00
|
|
|
def RunPager(globalConfig):
|
2009-04-01 14:24:22 +00:00
|
|
|
if not os.isatty(0) or not os.isatty(1):
|
2008-10-21 14:00:00 +00:00
|
|
|
return
|
|
|
|
pager = _SelectPager(globalConfig)
|
|
|
|
if pager == '' or pager == 'cat':
|
|
|
|
return
|
|
|
|
|
2016-11-01 22:51:59 +00:00
|
|
|
if platform_utils.isWindows():
|
2020-02-12 05:14:57 +00:00
|
|
|
_PipePager(pager)
|
2016-11-01 22:51:59 +00:00
|
|
|
else:
|
|
|
|
_ForkPager(pager)
|
|
|
|
|
2020-02-12 06:20:19 +00:00
|
|
|
|
2016-11-01 22:51:59 +00:00
|
|
|
def TerminatePager():
|
|
|
|
global pager_process, old_stdout, old_stderr
|
|
|
|
if pager_process:
|
|
|
|
sys.stdout.flush()
|
|
|
|
sys.stderr.flush()
|
|
|
|
pager_process.stdin.close()
|
2020-02-12 05:14:57 +00:00
|
|
|
pager_process.wait()
|
2016-11-01 22:51:59 +00:00
|
|
|
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
|
|
|
|
|
2020-02-12 06:20:19 +00:00
|
|
|
|
2016-11-01 22:51:59 +00:00
|
|
|
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
|
2020-02-13 04:17:03 +00:00
|
|
|
pager_process = subprocess.Popen([pager], stdin=subprocess.PIPE, stdout=sys.stdout,
|
|
|
|
stderr=sys.stderr)
|
2016-11-01 22:51:59 +00:00
|
|
|
old_stdout = sys.stdout
|
|
|
|
old_stderr = sys.stderr
|
|
|
|
sys.stdout = pager_process.stdin
|
|
|
|
sys.stderr = pager_process.stdin
|
|
|
|
|
2020-02-12 06:20:19 +00:00
|
|
|
|
2016-11-01 22:51:59 +00:00
|
|
|
def _ForkPager(pager):
|
|
|
|
global active
|
2008-10-21 14:00:00 +00:00
|
|
|
# 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:
|
2012-11-02 05:59:27 +00:00
|
|
|
print("fatal: cannot start pager '%s'" % pager, file=sys.stderr)
|
2012-10-03 10:11:28 +00:00
|
|
|
sys.exit(255)
|
2008-10-21 14:00:00 +00:00
|
|
|
|
2020-02-12 06:20:19 +00:00
|
|
|
|
2008-10-21 14:00:00 +00:00
|
|
|
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'
|
|
|
|
|
2020-02-12 06:20:19 +00:00
|
|
|
|
2008-10-21 14:00:00 +00:00
|
|
|
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'.
|
|
|
|
#
|
2012-09-24 03:15:13 +00:00
|
|
|
_a, _b, _c = select.select([0], [], [0])
|
2008-10-21 14:00:00 +00:00
|
|
|
|
|
|
|
os.environ['LESS'] = 'FRSX'
|
|
|
|
|
|
|
|
try:
|
|
|
|
os.execvp(pager, [pager])
|
2012-09-24 03:15:13 +00:00
|
|
|
except OSError:
|
2008-10-21 14:00:00 +00:00
|
|
|
os.execv('/bin/sh', ['sh', '-c', pager])
|