diff options
author | Junio C Hamano <gitster@pobox.com> | 2010-03-02 12:44:11 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2010-03-02 12:44:11 -0800 |
commit | 52ebb06f1466a235c643acffdea9c9e484cfdec0 (patch) | |
tree | b7bfae26f5719b8447ef176f4df4437d1e3fc4a9 | |
parent | Merge branch 'ml/encode-header-refactor' (diff) | |
parent | tests: Fix race condition in t7006-pager (diff) | |
download | tgif-52ebb06f1466a235c643acffdea9c9e484cfdec0.tar.xz |
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
-rw-r--r-- | Documentation/git-var.txt | 2 | ||||
-rw-r--r-- | Documentation/git.txt | 8 | ||||
-rw-r--r-- | builtin-var.c | 4 | ||||
-rw-r--r-- | cache.h | 2 | ||||
-rwxr-xr-x | git-am.sh | 5 | ||||
-rw-r--r-- | git-sh-setup.sh | 13 | ||||
-rwxr-xr-x | git-svn.perl | 9 | ||||
-rw-r--r-- | pager.c | 6 | ||||
-rwxr-xr-x | t/t7006-pager.sh | 176 | ||||
-rwxr-xr-x | t/t7006/test-terminal.perl | 58 |
10 files changed, 268 insertions, 15 deletions
diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt index bb981822a4..458f3e2755 100644 --- a/Documentation/git-var.txt +++ b/Documentation/git-var.txt @@ -8,7 +8,7 @@ git-var - Show a git logical variable SYNOPSIS -------- -'git var' [ -l | <variable> ] +'git var' ( -l | <variable> ) DESCRIPTION ----------- diff --git a/Documentation/git.txt b/Documentation/git.txt index cc32ce18d2..98b6e16982 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -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. @@ -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 diff --git a/builtin-var.c b/builtin-var.c index 2280518190..70fdb4dec7 100644 --- a/builtin-var.c +++ b/builtin-var.c @@ -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) { @@ -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"; @@ -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; @@ -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 diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 5e22440aec..7a095665d7 100644 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -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 "$@" } diff --git a/git-svn.perl b/git-svn.perl index 49dd649bc5..b7c03b641c 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -5465,7 +5465,12 @@ 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; } @@ -5473,7 +5478,7 @@ sub config_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) { @@ -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"); @@ -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; diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh new file mode 100755 index 0000000000..d9202d5af5 --- /dev/null +++ b/t/t7006-pager.sh @@ -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 diff --git a/t/t7006/test-terminal.perl b/t/t7006/test-terminal.perl new file mode 100755 index 0000000000..73ff809371 --- /dev/null +++ b/t/t7006/test-terminal.perl @@ -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)); |