Merge branch 'jn/maint-fix-pager'
* jn/maint-fix-pager: tests: Fix race condition in t7006-pager t7006-pager: if stdout is not a terminal, make a new one tests: Add tests for automatic use of pager am: Fix launching of pager git svn: Fix launching of pager git.1: Clarify the behavior of the --paginate option Make 'git var GIT_PAGER' always print the configured pager Fix 'git var' usage synopsis
This commit is contained in:
@ -8,7 +8,7 @@ git-var - Show a git logical variable
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git var' [ -l | <variable> ]
|
'git var' ( -l | <variable> )
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
@ -230,7 +230,10 @@ help ...`.
|
|||||||
|
|
||||||
-p::
|
-p::
|
||||||
--paginate::
|
--paginate::
|
||||||
Pipe all output into 'less' (or if set, $PAGER).
|
Pipe all output into 'less' (or if set, $PAGER) if standard
|
||||||
|
output is a terminal. This overrides the `pager.<cmd>`
|
||||||
|
configuration options (see the "Configuration Mechanism" section
|
||||||
|
below).
|
||||||
|
|
||||||
--no-pager::
|
--no-pager::
|
||||||
Do not pipe git output into a pager.
|
Do not pipe git output into a pager.
|
||||||
@ -402,7 +405,8 @@ people. Here is an example:
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
Various commands read from the configuration file and adjust
|
Various commands read from the configuration file and adjust
|
||||||
their operation accordingly.
|
their operation accordingly. See linkgit:git-config[1] for a
|
||||||
|
list.
|
||||||
|
|
||||||
|
|
||||||
Identifier Terminology
|
Identifier Terminology
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "exec_cmd.h"
|
#include "exec_cmd.h"
|
||||||
|
|
||||||
static const char var_usage[] = "git var [-l | <variable>]";
|
static const char var_usage[] = "git var (-l | <variable>)";
|
||||||
|
|
||||||
static const char *editor(int flag)
|
static const char *editor(int flag)
|
||||||
{
|
{
|
||||||
@ -20,7 +20,7 @@ static const char *editor(int flag)
|
|||||||
|
|
||||||
static const char *pager(int flag)
|
static const char *pager(int flag)
|
||||||
{
|
{
|
||||||
const char *pgm = git_pager();
|
const char *pgm = git_pager(1);
|
||||||
|
|
||||||
if (!pgm)
|
if (!pgm)
|
||||||
pgm = "cat";
|
pgm = "cat";
|
||||||
|
2
cache.h
2
cache.h
@ -775,7 +775,7 @@ extern const char *git_committer_info(int);
|
|||||||
extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
|
extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
|
||||||
extern const char *fmt_name(const char *name, const char *email);
|
extern const char *fmt_name(const char *name, const char *email);
|
||||||
extern const char *git_editor(void);
|
extern const char *git_editor(void);
|
||||||
extern const char *git_pager(void);
|
extern const char *git_pager(int stdout_is_tty);
|
||||||
|
|
||||||
struct checkout {
|
struct checkout {
|
||||||
const char *base_dir;
|
const char *base_dir;
|
||||||
|
@ -663,10 +663,7 @@ do
|
|||||||
[eE]*) git_editor "$dotest/final-commit"
|
[eE]*) git_editor "$dotest/final-commit"
|
||||||
action=again ;;
|
action=again ;;
|
||||||
[vV]*) action=again
|
[vV]*) action=again
|
||||||
: ${GIT_PAGER=$(git var GIT_PAGER)}
|
git_pager "$dotest/patch" ;;
|
||||||
: ${LESS=-FRSX}
|
|
||||||
export LESS
|
|
||||||
$GIT_PAGER "$dotest/patch" ;;
|
|
||||||
*) action=again ;;
|
*) action=again ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
@ -107,6 +107,19 @@ git_editor() {
|
|||||||
eval "$GIT_EDITOR" '"$@"'
|
eval "$GIT_EDITOR" '"$@"'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
git_pager() {
|
||||||
|
if test -t 1
|
||||||
|
then
|
||||||
|
GIT_PAGER=$(git var GIT_PAGER)
|
||||||
|
else
|
||||||
|
GIT_PAGER=cat
|
||||||
|
fi
|
||||||
|
: ${LESS=-FRSX}
|
||||||
|
export LESS
|
||||||
|
|
||||||
|
eval "$GIT_PAGER" '"$@"'
|
||||||
|
}
|
||||||
|
|
||||||
sane_grep () {
|
sane_grep () {
|
||||||
GREP_OPTIONS= LC_ALL=C grep "$@"
|
GREP_OPTIONS= LC_ALL=C grep "$@"
|
||||||
}
|
}
|
||||||
|
@ -5465,7 +5465,12 @@ sub git_svn_log_cmd {
|
|||||||
|
|
||||||
# adapted from pager.c
|
# adapted from pager.c
|
||||||
sub config_pager {
|
sub config_pager {
|
||||||
chomp(my $pager = command_oneline(qw(var GIT_PAGER)));
|
if (! -t *STDOUT) {
|
||||||
|
$ENV{GIT_PAGER_IN_USE} = 'false';
|
||||||
|
$pager = undef;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chomp($pager = command_oneline(qw(var GIT_PAGER)));
|
||||||
if ($pager eq 'cat') {
|
if ($pager eq 'cat') {
|
||||||
$pager = undef;
|
$pager = undef;
|
||||||
}
|
}
|
||||||
@ -5473,7 +5478,7 @@ sub config_pager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub run_pager {
|
sub run_pager {
|
||||||
return unless -t *STDOUT && defined $pager;
|
return unless defined $pager;
|
||||||
pipe my ($rfd, $wfd) or return;
|
pipe my ($rfd, $wfd) or return;
|
||||||
defined(my $pid = fork) or ::fatal "Can't fork: $!";
|
defined(my $pid = fork) or ::fatal "Can't fork: $!";
|
||||||
if (!$pid) {
|
if (!$pid) {
|
||||||
|
6
pager.c
6
pager.c
@ -48,11 +48,11 @@ static void wait_for_pager_signal(int signo)
|
|||||||
raise(signo);
|
raise(signo);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *git_pager(void)
|
const char *git_pager(int stdout_is_tty)
|
||||||
{
|
{
|
||||||
const char *pager;
|
const char *pager;
|
||||||
|
|
||||||
if (!isatty(1))
|
if (!stdout_is_tty)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pager = getenv("GIT_PAGER");
|
pager = getenv("GIT_PAGER");
|
||||||
@ -73,7 +73,7 @@ const char *git_pager(void)
|
|||||||
|
|
||||||
void setup_pager(void)
|
void setup_pager(void)
|
||||||
{
|
{
|
||||||
const char *pager = git_pager();
|
const char *pager = git_pager(isatty(1));
|
||||||
|
|
||||||
if (!pager)
|
if (!pager)
|
||||||
return;
|
return;
|
||||||
|
176
t/t7006-pager.sh
Executable file
176
t/t7006-pager.sh
Executable file
@ -0,0 +1,176 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='Test automatic use of a pager.'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
rm -f stdout_is_tty
|
||||||
|
test_expect_success 'set up terminal for tests' '
|
||||||
|
if test -t 1
|
||||||
|
then
|
||||||
|
: > stdout_is_tty
|
||||||
|
elif
|
||||||
|
test_have_prereq PERL &&
|
||||||
|
"$PERL_PATH" "$TEST_DIRECTORY"/t7006/test-terminal.perl \
|
||||||
|
sh -c "test -t 1"
|
||||||
|
then
|
||||||
|
: > test_terminal_works
|
||||||
|
fi
|
||||||
|
'
|
||||||
|
|
||||||
|
if test -e stdout_is_tty
|
||||||
|
then
|
||||||
|
test_terminal() { "$@"; }
|
||||||
|
test_set_prereq TTY
|
||||||
|
elif test -e test_terminal_works
|
||||||
|
then
|
||||||
|
test_terminal() {
|
||||||
|
"$PERL_PATH" "$TEST_DIRECTORY"/t7006/test-terminal.perl "$@"
|
||||||
|
}
|
||||||
|
test_set_prereq TTY
|
||||||
|
else
|
||||||
|
say no usable terminal, so skipping some tests
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset GIT_PAGER GIT_PAGER_IN_USE
|
||||||
|
git config --unset core.pager
|
||||||
|
PAGER='cat > paginated.out'
|
||||||
|
export PAGER
|
||||||
|
|
||||||
|
test_expect_success 'setup' '
|
||||||
|
test_commit initial
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f paginated.out
|
||||||
|
test_expect_success TTY 'some commands use a pager' '
|
||||||
|
test_terminal git log &&
|
||||||
|
test -e paginated.out
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f paginated.out
|
||||||
|
test_expect_success TTY 'some commands do not use a pager' '
|
||||||
|
test_terminal git rev-list HEAD &&
|
||||||
|
! test -e paginated.out
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f paginated.out
|
||||||
|
test_expect_success 'no pager when stdout is a pipe' '
|
||||||
|
git log | cat &&
|
||||||
|
! test -e paginated.out
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f paginated.out
|
||||||
|
test_expect_success 'no pager when stdout is a regular file' '
|
||||||
|
git log > file &&
|
||||||
|
! test -e paginated.out
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f paginated.out
|
||||||
|
test_expect_success TTY 'git --paginate rev-list uses a pager' '
|
||||||
|
test_terminal git --paginate rev-list HEAD &&
|
||||||
|
test -e paginated.out
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f file paginated.out
|
||||||
|
test_expect_success 'no pager even with --paginate when stdout is a pipe' '
|
||||||
|
git --paginate log | cat &&
|
||||||
|
! test -e paginated.out
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f paginated.out
|
||||||
|
test_expect_success TTY 'no pager with --no-pager' '
|
||||||
|
test_terminal git --no-pager log &&
|
||||||
|
! test -e paginated.out
|
||||||
|
'
|
||||||
|
|
||||||
|
# A colored commit log will begin with an appropriate ANSI escape
|
||||||
|
# for the first color; the text "commit" comes later.
|
||||||
|
colorful() {
|
||||||
|
read firstline < $1
|
||||||
|
! expr "$firstline" : "^[a-zA-Z]" >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
rm -f colorful.log colorless.log
|
||||||
|
test_expect_success 'tests can detect color' '
|
||||||
|
git log --no-color > colorless.log &&
|
||||||
|
git log --color > colorful.log &&
|
||||||
|
! colorful colorless.log &&
|
||||||
|
colorful colorful.log
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f colorless.log
|
||||||
|
git config color.ui auto
|
||||||
|
test_expect_success 'no color when stdout is a regular file' '
|
||||||
|
git log > colorless.log &&
|
||||||
|
! colorful colorless.log
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f paginated.out
|
||||||
|
git config color.ui auto
|
||||||
|
test_expect_success TTY 'color when writing to a pager' '
|
||||||
|
TERM=vt100 test_terminal git log &&
|
||||||
|
colorful paginated.out
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f colorful.log
|
||||||
|
git config color.ui auto
|
||||||
|
test_expect_success 'color when writing to a file intended for a pager' '
|
||||||
|
TERM=vt100 GIT_PAGER_IN_USE=true git log > colorful.log &&
|
||||||
|
colorful colorful.log
|
||||||
|
'
|
||||||
|
|
||||||
|
unset PAGER GIT_PAGER
|
||||||
|
git config --unset core.pager
|
||||||
|
test_expect_success 'determine default pager' '
|
||||||
|
less=$(git var GIT_PAGER) &&
|
||||||
|
test -n "$less"
|
||||||
|
'
|
||||||
|
|
||||||
|
if expr "$less" : '^[a-z]*$' > /dev/null && test_have_prereq TTY
|
||||||
|
then
|
||||||
|
test_set_prereq SIMPLEPAGER
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset PAGER GIT_PAGER
|
||||||
|
git config --unset core.pager
|
||||||
|
rm -f default_pager_used
|
||||||
|
test_expect_success SIMPLEPAGER 'default pager is used by default' '
|
||||||
|
cat > $less <<-EOF &&
|
||||||
|
#!$SHELL_PATH
|
||||||
|
wc > default_pager_used
|
||||||
|
EOF
|
||||||
|
chmod +x $less &&
|
||||||
|
PATH=.:$PATH test_terminal git log &&
|
||||||
|
test -e default_pager_used
|
||||||
|
'
|
||||||
|
|
||||||
|
unset GIT_PAGER
|
||||||
|
git config --unset core.pager
|
||||||
|
rm -f PAGER_used
|
||||||
|
test_expect_success TTY 'PAGER overrides default pager' '
|
||||||
|
PAGER="wc > PAGER_used" &&
|
||||||
|
export PAGER &&
|
||||||
|
test_terminal git log &&
|
||||||
|
test -e PAGER_used
|
||||||
|
'
|
||||||
|
|
||||||
|
unset GIT_PAGER
|
||||||
|
rm -f core.pager_used
|
||||||
|
test_expect_success TTY 'core.pager overrides PAGER' '
|
||||||
|
PAGER=wc &&
|
||||||
|
export PAGER &&
|
||||||
|
git config core.pager "wc > core.pager_used" &&
|
||||||
|
test_terminal git log &&
|
||||||
|
test -e core.pager_used
|
||||||
|
'
|
||||||
|
|
||||||
|
rm -f GIT_PAGER_used
|
||||||
|
test_expect_success TTY 'GIT_PAGER overrides core.pager' '
|
||||||
|
git config core.pager wc &&
|
||||||
|
GIT_PAGER="wc > GIT_PAGER_used" &&
|
||||||
|
export GIT_PAGER &&
|
||||||
|
test_terminal git log &&
|
||||||
|
test -e GIT_PAGER_used
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
58
t/t7006/test-terminal.perl
Executable file
58
t/t7006/test-terminal.perl
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use IO::Pty;
|
||||||
|
use File::Copy;
|
||||||
|
|
||||||
|
# Run @$argv in the background with stdout redirected to $out.
|
||||||
|
sub start_child {
|
||||||
|
my ($argv, $out) = @_;
|
||||||
|
my $pid = fork;
|
||||||
|
if (not defined $pid) {
|
||||||
|
die "fork failed: $!"
|
||||||
|
} elsif ($pid == 0) {
|
||||||
|
open STDOUT, ">&", $out;
|
||||||
|
close $out;
|
||||||
|
exec(@$argv) or die "cannot exec '$argv->[0]': $!"
|
||||||
|
}
|
||||||
|
return $pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait for $pid to finish.
|
||||||
|
sub finish_child {
|
||||||
|
# Simplified from wait_or_whine() in run-command.c.
|
||||||
|
my ($pid) = @_;
|
||||||
|
|
||||||
|
my $waiting = waitpid($pid, 0);
|
||||||
|
if ($waiting < 0) {
|
||||||
|
die "waitpid failed: $!";
|
||||||
|
} elsif ($? & 127) {
|
||||||
|
my $code = $? & 127;
|
||||||
|
warn "died of signal $code";
|
||||||
|
return $code - 128;
|
||||||
|
} else {
|
||||||
|
return $? >> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub xsendfile {
|
||||||
|
my ($out, $in) = @_;
|
||||||
|
|
||||||
|
# Note: the real sendfile() cannot read from a terminal.
|
||||||
|
|
||||||
|
# It is unspecified by POSIX whether reads
|
||||||
|
# from a disconnected terminal will return
|
||||||
|
# EIO (as in AIX 4.x, IRIX, and Linux) or
|
||||||
|
# end-of-file. Either is fine.
|
||||||
|
copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($#ARGV < 1) {
|
||||||
|
die "usage: test-terminal program args";
|
||||||
|
}
|
||||||
|
my $master = new IO::Pty;
|
||||||
|
my $slave = $master->slave;
|
||||||
|
my $pid = start_child(\@ARGV, $slave);
|
||||||
|
close $slave;
|
||||||
|
xsendfile(\*STDOUT, $master);
|
||||||
|
exit(finish_child($pid));
|
Reference in New Issue
Block a user