Skip to content
/ git Public
forked from git/git

Commit

Permalink
Merge branch 'jn/maint-fix-pager'
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
gitster committed Mar 2, 2010
2 parents 77b30bc + 8c33b4c commit 52ebb06
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Documentation/git-var.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ git-var - Show a git logical variable

SYNOPSIS
--------
'git var' [ -l | <variable> ]
'git var' ( -l | <variable> )

DESCRIPTION
-----------
Expand Down
8 changes: 6 additions & 2 deletions Documentation/git.txt
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,10 @@ help ...`.

-p::
--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::
Do not pipe git output into a pager.
Expand Down Expand Up @@ -402,7 +405,8 @@ people. Here is an example:
------------

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
Expand Down
4 changes: 2 additions & 2 deletions builtin-var.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "cache.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)
{
Expand All @@ -20,7 +20,7 @@ static const char *editor(int flag)

static const char *pager(int flag)
{
const char *pgm = git_pager();
const char *pgm = git_pager(1);

if (!pgm)
pgm = "cat";
Expand Down
2 changes: 1 addition & 1 deletion cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_name(const char *name, const char *email);
extern const char *git_editor(void);
extern const char *git_pager(void);
extern const char *git_pager(int stdout_is_tty);

struct checkout {
const char *base_dir;
Expand Down
5 changes: 1 addition & 4 deletions git-am.sh
Original file line number Diff line number Diff line change
Expand Up @@ -663,10 +663,7 @@ do
[eE]*) git_editor "$dotest/final-commit"
action=again ;;
[vV]*) action=again
: ${GIT_PAGER=$(git var GIT_PAGER)}
: ${LESS=-FRSX}
export LESS
$GIT_PAGER "$dotest/patch" ;;
git_pager "$dotest/patch" ;;
*) action=again ;;
esac
done
Expand Down
13 changes: 13 additions & 0 deletions git-sh-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,19 @@ 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 () {
GREP_OPTIONS= LC_ALL=C grep "$@"
}
Expand Down
9 changes: 7 additions & 2 deletions git-svn.perl
Original file line number Diff line number Diff line change
Expand Up @@ -5465,15 +5465,20 @@ sub git_svn_log_cmd {

# adapted from pager.c
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') {
$pager = undef;
}
$ENV{GIT_PAGER_IN_USE} = defined($pager);
}

sub run_pager {
return unless -t *STDOUT && defined $pager;
return unless defined $pager;
pipe my ($rfd, $wfd) or return;
defined(my $pid = fork) or ::fatal "Can't fork: $!";
if (!$pid) {
Expand Down
6 changes: 3 additions & 3 deletions pager.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ static void wait_for_pager_signal(int signo)
raise(signo);
}

const char *git_pager(void)
const char *git_pager(int stdout_is_tty)
{
const char *pager;

if (!isatty(1))
if (!stdout_is_tty)
return NULL;

pager = getenv("GIT_PAGER");
Expand All @@ -73,7 +73,7 @@ const char *git_pager(void)

void setup_pager(void)
{
const char *pager = git_pager();
const char *pager = git_pager(isatty(1));

if (!pager)
return;
Expand Down
176 changes: 176 additions & 0 deletions t/t7006-pager.sh
Original file line number Diff line number Diff line change
@@ -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 changes: 58 additions & 0 deletions t/t7006/test-terminal.perl
Original file line number Diff line number Diff line change
@@ -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));

0 comments on commit 52ebb06

Please sign in to comment.