Skip to content

Commit 6914c66

Browse files
committed
Merge branch 'jn/maint-fix-pager' into maint
* 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
2 parents 712d352 + 8c33b4c commit 6914c66

File tree

10 files changed

+268
-15
lines changed

10 files changed

+268
-15
lines changed

Documentation/git-var.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ git-var - Show a git logical variable
88

99
SYNOPSIS
1010
--------
11-
'git var' [ -l | <variable> ]
11+
'git var' ( -l | <variable> )
1212

1313
DESCRIPTION
1414
-----------

Documentation/git.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,10 @@ help ...`.
230230

231231
-p::
232232
--paginate::
233-
Pipe all output into 'less' (or if set, $PAGER).
233+
Pipe all output into 'less' (or if set, $PAGER) if standard
234+
output is a terminal. This overrides the `pager.<cmd>`
235+
configuration options (see the "Configuration Mechanism" section
236+
below).
234237

235238
--no-pager::
236239
Do not pipe git output into a pager.
@@ -402,7 +405,8 @@ people. Here is an example:
402405
------------
403406

404407
Various commands read from the configuration file and adjust
405-
their operation accordingly.
408+
their operation accordingly. See linkgit:git-config[1] for a
409+
list.
406410

407411

408412
Identifier Terminology

builtin-var.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include "cache.h"
77
#include "exec_cmd.h"
88

9-
static const char var_usage[] = "git var [-l | <variable>]";
9+
static const char var_usage[] = "git var (-l | <variable>)";
1010

1111
static const char *editor(int flag)
1212
{
@@ -20,7 +20,7 @@ static const char *editor(int flag)
2020

2121
static const char *pager(int flag)
2222
{
23-
const char *pgm = git_pager();
23+
const char *pgm = git_pager(1);
2424

2525
if (!pgm)
2626
pgm = "cat";

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ extern const char *git_committer_info(int);
775775
extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
776776
extern const char *fmt_name(const char *name, const char *email);
777777
extern const char *git_editor(void);
778-
extern const char *git_pager(void);
778+
extern const char *git_pager(int stdout_is_tty);
779779

780780
struct checkout {
781781
const char *base_dir;

git-am.sh

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -663,10 +663,7 @@ do
663663
[eE]*) git_editor "$dotest/final-commit"
664664
action=again ;;
665665
[vV]*) action=again
666-
: ${GIT_PAGER=$(git var GIT_PAGER)}
667-
: ${LESS=-FRSX}
668-
export LESS
669-
$GIT_PAGER "$dotest/patch" ;;
666+
git_pager "$dotest/patch" ;;
670667
*) action=again ;;
671668
esac
672669
done

git-sh-setup.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,19 @@ git_editor() {
107107
eval "$GIT_EDITOR" '"$@"'
108108
}
109109
110+
git_pager() {
111+
if test -t 1
112+
then
113+
GIT_PAGER=$(git var GIT_PAGER)
114+
else
115+
GIT_PAGER=cat
116+
fi
117+
: ${LESS=-FRSX}
118+
export LESS
119+
120+
eval "$GIT_PAGER" '"$@"'
121+
}
122+
110123
sane_grep () {
111124
GREP_OPTIONS= LC_ALL=C grep "$@"
112125
}

git-svn.perl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5459,15 +5459,20 @@ sub git_svn_log_cmd {
54595459

54605460
# adapted from pager.c
54615461
sub config_pager {
5462-
chomp(my $pager = command_oneline(qw(var GIT_PAGER)));
5462+
if (! -t *STDOUT) {
5463+
$ENV{GIT_PAGER_IN_USE} = 'false';
5464+
$pager = undef;
5465+
return;
5466+
}
5467+
chomp($pager = command_oneline(qw(var GIT_PAGER)));
54635468
if ($pager eq 'cat') {
54645469
$pager = undef;
54655470
}
54665471
$ENV{GIT_PAGER_IN_USE} = defined($pager);
54675472
}
54685473

54695474
sub run_pager {
5470-
return unless -t *STDOUT && defined $pager;
5475+
return unless defined $pager;
54715476
pipe my ($rfd, $wfd) or return;
54725477
defined(my $pid = fork) or ::fatal "Can't fork: $!";
54735478
if (!$pid) {

pager.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ static void wait_for_pager_signal(int signo)
4848
raise(signo);
4949
}
5050

51-
const char *git_pager(void)
51+
const char *git_pager(int stdout_is_tty)
5252
{
5353
const char *pager;
5454

55-
if (!isatty(1))
55+
if (!stdout_is_tty)
5656
return NULL;
5757

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

7474
void setup_pager(void)
7575
{
76-
const char *pager = git_pager();
76+
const char *pager = git_pager(isatty(1));
7777

7878
if (!pager)
7979
return;

t/t7006-pager.sh

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#!/bin/sh
2+
3+
test_description='Test automatic use of a pager.'
4+
5+
. ./test-lib.sh
6+
7+
rm -f stdout_is_tty
8+
test_expect_success 'set up terminal for tests' '
9+
if test -t 1
10+
then
11+
: > stdout_is_tty
12+
elif
13+
test_have_prereq PERL &&
14+
"$PERL_PATH" "$TEST_DIRECTORY"/t7006/test-terminal.perl \
15+
sh -c "test -t 1"
16+
then
17+
: > test_terminal_works
18+
fi
19+
'
20+
21+
if test -e stdout_is_tty
22+
then
23+
test_terminal() { "$@"; }
24+
test_set_prereq TTY
25+
elif test -e test_terminal_works
26+
then
27+
test_terminal() {
28+
"$PERL_PATH" "$TEST_DIRECTORY"/t7006/test-terminal.perl "$@"
29+
}
30+
test_set_prereq TTY
31+
else
32+
say no usable terminal, so skipping some tests
33+
fi
34+
35+
unset GIT_PAGER GIT_PAGER_IN_USE
36+
git config --unset core.pager
37+
PAGER='cat > paginated.out'
38+
export PAGER
39+
40+
test_expect_success 'setup' '
41+
test_commit initial
42+
'
43+
44+
rm -f paginated.out
45+
test_expect_success TTY 'some commands use a pager' '
46+
test_terminal git log &&
47+
test -e paginated.out
48+
'
49+
50+
rm -f paginated.out
51+
test_expect_success TTY 'some commands do not use a pager' '
52+
test_terminal git rev-list HEAD &&
53+
! test -e paginated.out
54+
'
55+
56+
rm -f paginated.out
57+
test_expect_success 'no pager when stdout is a pipe' '
58+
git log | cat &&
59+
! test -e paginated.out
60+
'
61+
62+
rm -f paginated.out
63+
test_expect_success 'no pager when stdout is a regular file' '
64+
git log > file &&
65+
! test -e paginated.out
66+
'
67+
68+
rm -f paginated.out
69+
test_expect_success TTY 'git --paginate rev-list uses a pager' '
70+
test_terminal git --paginate rev-list HEAD &&
71+
test -e paginated.out
72+
'
73+
74+
rm -f file paginated.out
75+
test_expect_success 'no pager even with --paginate when stdout is a pipe' '
76+
git --paginate log | cat &&
77+
! test -e paginated.out
78+
'
79+
80+
rm -f paginated.out
81+
test_expect_success TTY 'no pager with --no-pager' '
82+
test_terminal git --no-pager log &&
83+
! test -e paginated.out
84+
'
85+
86+
# A colored commit log will begin with an appropriate ANSI escape
87+
# for the first color; the text "commit" comes later.
88+
colorful() {
89+
read firstline < $1
90+
! expr "$firstline" : "^[a-zA-Z]" >/dev/null
91+
}
92+
93+
rm -f colorful.log colorless.log
94+
test_expect_success 'tests can detect color' '
95+
git log --no-color > colorless.log &&
96+
git log --color > colorful.log &&
97+
! colorful colorless.log &&
98+
colorful colorful.log
99+
'
100+
101+
rm -f colorless.log
102+
git config color.ui auto
103+
test_expect_success 'no color when stdout is a regular file' '
104+
git log > colorless.log &&
105+
! colorful colorless.log
106+
'
107+
108+
rm -f paginated.out
109+
git config color.ui auto
110+
test_expect_success TTY 'color when writing to a pager' '
111+
TERM=vt100 test_terminal git log &&
112+
colorful paginated.out
113+
'
114+
115+
rm -f colorful.log
116+
git config color.ui auto
117+
test_expect_success 'color when writing to a file intended for a pager' '
118+
TERM=vt100 GIT_PAGER_IN_USE=true git log > colorful.log &&
119+
colorful colorful.log
120+
'
121+
122+
unset PAGER GIT_PAGER
123+
git config --unset core.pager
124+
test_expect_success 'determine default pager' '
125+
less=$(git var GIT_PAGER) &&
126+
test -n "$less"
127+
'
128+
129+
if expr "$less" : '^[a-z]*$' > /dev/null && test_have_prereq TTY
130+
then
131+
test_set_prereq SIMPLEPAGER
132+
fi
133+
134+
unset PAGER GIT_PAGER
135+
git config --unset core.pager
136+
rm -f default_pager_used
137+
test_expect_success SIMPLEPAGER 'default pager is used by default' '
138+
cat > $less <<-EOF &&
139+
#!$SHELL_PATH
140+
wc > default_pager_used
141+
EOF
142+
chmod +x $less &&
143+
PATH=.:$PATH test_terminal git log &&
144+
test -e default_pager_used
145+
'
146+
147+
unset GIT_PAGER
148+
git config --unset core.pager
149+
rm -f PAGER_used
150+
test_expect_success TTY 'PAGER overrides default pager' '
151+
PAGER="wc > PAGER_used" &&
152+
export PAGER &&
153+
test_terminal git log &&
154+
test -e PAGER_used
155+
'
156+
157+
unset GIT_PAGER
158+
rm -f core.pager_used
159+
test_expect_success TTY 'core.pager overrides PAGER' '
160+
PAGER=wc &&
161+
export PAGER &&
162+
git config core.pager "wc > core.pager_used" &&
163+
test_terminal git log &&
164+
test -e core.pager_used
165+
'
166+
167+
rm -f GIT_PAGER_used
168+
test_expect_success TTY 'GIT_PAGER overrides core.pager' '
169+
git config core.pager wc &&
170+
GIT_PAGER="wc > GIT_PAGER_used" &&
171+
export GIT_PAGER &&
172+
test_terminal git log &&
173+
test -e GIT_PAGER_used
174+
'
175+
176+
test_done

t/t7006/test-terminal.perl

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/perl
2+
use strict;
3+
use warnings;
4+
use IO::Pty;
5+
use File::Copy;
6+
7+
# Run @$argv in the background with stdout redirected to $out.
8+
sub start_child {
9+
my ($argv, $out) = @_;
10+
my $pid = fork;
11+
if (not defined $pid) {
12+
die "fork failed: $!"
13+
} elsif ($pid == 0) {
14+
open STDOUT, ">&", $out;
15+
close $out;
16+
exec(@$argv) or die "cannot exec '$argv->[0]': $!"
17+
}
18+
return $pid;
19+
}
20+
21+
# Wait for $pid to finish.
22+
sub finish_child {
23+
# Simplified from wait_or_whine() in run-command.c.
24+
my ($pid) = @_;
25+
26+
my $waiting = waitpid($pid, 0);
27+
if ($waiting < 0) {
28+
die "waitpid failed: $!";
29+
} elsif ($? & 127) {
30+
my $code = $? & 127;
31+
warn "died of signal $code";
32+
return $code - 128;
33+
} else {
34+
return $? >> 8;
35+
}
36+
}
37+
38+
sub xsendfile {
39+
my ($out, $in) = @_;
40+
41+
# Note: the real sendfile() cannot read from a terminal.
42+
43+
# It is unspecified by POSIX whether reads
44+
# from a disconnected terminal will return
45+
# EIO (as in AIX 4.x, IRIX, and Linux) or
46+
# end-of-file. Either is fine.
47+
copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
48+
}
49+
50+
if ($#ARGV < 1) {
51+
die "usage: test-terminal program args";
52+
}
53+
my $master = new IO::Pty;
54+
my $slave = $master->slave;
55+
my $pid = start_child(\@ARGV, $slave);
56+
close $slave;
57+
xsendfile(\*STDOUT, $master);
58+
exit(finish_child($pid));

0 commit comments

Comments
 (0)