Merge branch 'jk/execv-dashed-external'
[git] / t / t7006-pager.sh
1 #!/bin/sh
2
3 test_description='Test automatic use of a pager.'
4
5 . ./test-lib.sh
6 . "$TEST_DIRECTORY"/lib-pager.sh
7 . "$TEST_DIRECTORY"/lib-terminal.sh
8
9 test_expect_success 'setup' '
10         sane_unset GIT_PAGER GIT_PAGER_IN_USE &&
11         test_unconfig core.pager &&
12
13         PAGER="cat >paginated.out" &&
14         export PAGER &&
15
16         test_commit initial
17 '
18
19 test_expect_success TTY 'some commands use a pager' '
20         rm -f paginated.out &&
21         test_terminal git log &&
22         test -e paginated.out
23 '
24
25 test_expect_failure TTY 'pager runs from subdir' '
26         echo subdir/paginated.out >expected &&
27         mkdir -p subdir &&
28         rm -f paginated.out subdir/paginated.out &&
29         (
30                 cd subdir &&
31                 test_terminal git log
32         ) &&
33         {
34                 ls paginated.out subdir/paginated.out ||
35                 :
36         } >actual &&
37         test_cmp expected actual
38 '
39
40 test_expect_success TTY 'LESS and LV envvars are set for pagination' '
41         (
42                 sane_unset LESS LV &&
43                 PAGER="env >pager-env.out; wc" &&
44                 export PAGER &&
45
46                 test_terminal git log
47         ) &&
48         grep ^LESS= pager-env.out &&
49         grep ^LV= pager-env.out
50 '
51
52 test_expect_success !MINGW,TTY 'LESS and LV envvars set by git-sh-setup' '
53         (
54                 sane_unset LESS LV &&
55                 PAGER="env >pager-env.out; wc" &&
56                 export PAGER &&
57                 PATH="$(git --exec-path):$PATH" &&
58                 export PATH &&
59                 test_terminal sh -c ". git-sh-setup && git_pager"
60         ) &&
61         grep ^LESS= pager-env.out &&
62         grep ^LV= pager-env.out
63 '
64
65 test_expect_success TTY 'some commands do not use a pager' '
66         rm -f paginated.out &&
67         test_terminal git rev-list HEAD &&
68         ! test -e paginated.out
69 '
70
71 test_expect_success 'no pager when stdout is a pipe' '
72         rm -f paginated.out &&
73         git log | cat &&
74         ! test -e paginated.out
75 '
76
77 test_expect_success 'no pager when stdout is a regular file' '
78         rm -f paginated.out &&
79         git log >file &&
80         ! test -e paginated.out
81 '
82
83 test_expect_success TTY 'git --paginate rev-list uses a pager' '
84         rm -f paginated.out &&
85         test_terminal git --paginate rev-list HEAD &&
86         test -e paginated.out
87 '
88
89 test_expect_success 'no pager even with --paginate when stdout is a pipe' '
90         rm -f file paginated.out &&
91         git --paginate log | cat &&
92         ! test -e paginated.out
93 '
94
95 test_expect_success TTY 'no pager with --no-pager' '
96         rm -f paginated.out &&
97         test_terminal git --no-pager log &&
98         ! test -e paginated.out
99 '
100
101 test_expect_success TTY 'configuration can disable pager' '
102         rm -f paginated.out &&
103         test_unconfig pager.grep &&
104         test_terminal git grep initial &&
105         test -e paginated.out &&
106
107         rm -f paginated.out &&
108         test_config pager.grep false &&
109         test_terminal git grep initial &&
110         ! test -e paginated.out
111 '
112
113 test_expect_success TTY 'git config uses a pager if configured to' '
114         rm -f paginated.out &&
115         test_config pager.config true &&
116         test_terminal git config --list &&
117         test -e paginated.out
118 '
119
120 test_expect_success TTY 'configuration can enable pager (from subdir)' '
121         rm -f paginated.out &&
122         mkdir -p subdir &&
123         test_config pager.bundle true &&
124
125         git bundle create test.bundle --all &&
126         rm -f paginated.out subdir/paginated.out &&
127         (
128                 cd subdir &&
129                 test_terminal git bundle unbundle ../test.bundle
130         ) &&
131         {
132                 test -e paginated.out ||
133                 test -e subdir/paginated.out
134         }
135 '
136
137 # A colored commit log will begin with an appropriate ANSI escape
138 # for the first color; the text "commit" comes later.
139 colorful() {
140         read firstline <$1
141         ! expr "$firstline" : "[a-zA-Z]" >/dev/null
142 }
143
144 test_expect_success 'tests can detect color' '
145         rm -f colorful.log colorless.log &&
146         git log --no-color >colorless.log &&
147         git log --color >colorful.log &&
148         ! colorful colorless.log &&
149         colorful colorful.log
150 '
151
152 test_expect_success 'no color when stdout is a regular file' '
153         rm -f colorless.log &&
154         test_config color.ui auto &&
155         git log >colorless.log &&
156         ! colorful colorless.log
157 '
158
159 test_expect_success TTY 'color when writing to a pager' '
160         rm -f paginated.out &&
161         test_config color.ui auto &&
162         test_terminal env TERM=vt100 git log &&
163         colorful paginated.out
164 '
165
166 test_expect_success TTY 'colors are suppressed by color.pager' '
167         rm -f paginated.out &&
168         test_config color.ui auto &&
169         test_config color.pager false &&
170         test_terminal env TERM=vt100 git log &&
171         ! colorful paginated.out
172 '
173
174 test_expect_success 'color when writing to a file intended for a pager' '
175         rm -f colorful.log &&
176         test_config color.ui auto &&
177         (
178                 TERM=vt100 &&
179                 GIT_PAGER_IN_USE=true &&
180                 export TERM GIT_PAGER_IN_USE &&
181                 git log >colorful.log
182         ) &&
183         colorful colorful.log
184 '
185
186 test_expect_success TTY 'colors are sent to pager for external commands' '
187         test_config alias.externallog "!git log" &&
188         test_config color.ui auto &&
189         test_terminal env TERM=vt100 git -p externallog &&
190         colorful paginated.out
191 '
192
193 # Use this helper to make it easy for the caller of your
194 # terminal-using function to specify whether it should fail.
195 # If you write
196 #
197 #       your_test() {
198 #               parse_args "$@"
199 #
200 #               $test_expectation "$cmd - behaves well" "
201 #                       ...
202 #                       $full_command &&
203 #                       ...
204 #               "
205 #       }
206 #
207 # then your test can be used like this:
208 #
209 #       your_test expect_(success|failure) [test_must_fail] 'git foo'
210 #
211 parse_args() {
212         test_expectation="test_$1"
213         shift
214         if test "$1" = test_must_fail
215         then
216                 full_command="test_must_fail test_terminal "
217                 shift
218         else
219                 full_command="test_terminal "
220         fi
221         cmd=$1
222         full_command="$full_command $1"
223 }
224
225 test_default_pager() {
226         parse_args "$@"
227
228         $test_expectation SIMPLEPAGER,TTY "$cmd - default pager is used by default" "
229                 sane_unset PAGER GIT_PAGER &&
230                 test_unconfig core.pager &&
231                 rm -f default_pager_used &&
232                 cat >\$less <<-\EOF &&
233                 #!/bin/sh
234                 wc >default_pager_used
235                 EOF
236                 chmod +x \$less &&
237                 (
238                         PATH=.:\$PATH &&
239                         export PATH &&
240                         $full_command
241                 ) &&
242                 test -e default_pager_used
243         "
244 }
245
246 test_PAGER_overrides() {
247         parse_args "$@"
248
249         $test_expectation TTY "$cmd - PAGER overrides default pager" "
250                 sane_unset GIT_PAGER &&
251                 test_unconfig core.pager &&
252                 rm -f PAGER_used &&
253                 PAGER='wc >PAGER_used' &&
254                 export PAGER &&
255                 $full_command &&
256                 test -e PAGER_used
257         "
258 }
259
260 test_core_pager_overrides() {
261         if_local_config=
262         used_if_wanted='overrides PAGER'
263         test_core_pager "$@"
264 }
265
266 test_local_config_ignored() {
267         if_local_config='! '
268         used_if_wanted='is not used'
269         test_core_pager "$@"
270 }
271
272 test_core_pager() {
273         parse_args "$@"
274
275         $test_expectation TTY "$cmd - repository-local core.pager setting $used_if_wanted" "
276                 sane_unset GIT_PAGER &&
277                 rm -f core.pager_used &&
278                 PAGER=wc &&
279                 export PAGER &&
280                 test_config core.pager 'wc >core.pager_used' &&
281                 $full_command &&
282                 ${if_local_config}test -e core.pager_used
283         "
284 }
285
286 test_core_pager_subdir() {
287         if_local_config=
288         used_if_wanted='overrides PAGER'
289         test_pager_subdir_helper "$@"
290 }
291
292 test_no_local_config_subdir() {
293         if_local_config='! '
294         used_if_wanted='is not used'
295         test_pager_subdir_helper "$@"
296 }
297
298 test_pager_subdir_helper() {
299         parse_args "$@"
300
301         $test_expectation TTY "$cmd - core.pager $used_if_wanted from subdirectory" "
302                 sane_unset GIT_PAGER &&
303                 rm -f core.pager_used &&
304                 rm -fr sub &&
305                 PAGER=wc &&
306                 stampname=\$(pwd)/core.pager_used &&
307                 export PAGER stampname &&
308                 test_config core.pager 'wc >\"\$stampname\"' &&
309                 mkdir sub &&
310                 (
311                         cd sub &&
312                         $full_command
313                 ) &&
314                 ${if_local_config}test -e core.pager_used
315         "
316 }
317
318 test_GIT_PAGER_overrides() {
319         parse_args "$@"
320
321         $test_expectation TTY "$cmd - GIT_PAGER overrides core.pager" "
322                 rm -f GIT_PAGER_used &&
323                 test_config core.pager wc &&
324                 GIT_PAGER='wc >GIT_PAGER_used' &&
325                 export GIT_PAGER &&
326                 $full_command &&
327                 test -e GIT_PAGER_used
328         "
329 }
330
331 test_doesnt_paginate() {
332         parse_args "$@"
333
334         $test_expectation TTY "no pager for '$cmd'" "
335                 rm -f GIT_PAGER_used &&
336                 GIT_PAGER='wc >GIT_PAGER_used' &&
337                 export GIT_PAGER &&
338                 $full_command &&
339                 ! test -e GIT_PAGER_used
340         "
341 }
342
343 test_pager_choices() {
344         test_default_pager        expect_success "$@"
345         test_PAGER_overrides      expect_success "$@"
346         test_core_pager_overrides expect_success "$@"
347         test_core_pager_subdir    expect_success "$@"
348         test_GIT_PAGER_overrides  expect_success "$@"
349 }
350
351 test_expect_success 'setup: some aliases' '
352         git config alias.aliasedlog log &&
353         git config alias.true "!true"
354 '
355
356 test_pager_choices                       'git log'
357 test_pager_choices                       'git -p log'
358 test_pager_choices                       'git aliasedlog'
359
360 test_default_pager        expect_success 'git -p aliasedlog'
361 test_PAGER_overrides      expect_success 'git -p aliasedlog'
362 test_core_pager_overrides expect_success 'git -p aliasedlog'
363 test_core_pager_subdir    expect_failure 'git -p aliasedlog'
364 test_GIT_PAGER_overrides  expect_success 'git -p aliasedlog'
365
366 test_default_pager        expect_success 'git -p true'
367 test_PAGER_overrides      expect_success 'git -p true'
368 test_core_pager_overrides expect_success 'git -p true'
369 test_core_pager_subdir    expect_failure 'git -p true'
370 test_GIT_PAGER_overrides  expect_success 'git -p true'
371
372 test_default_pager        expect_success test_must_fail 'git -p request-pull'
373 test_PAGER_overrides      expect_success test_must_fail 'git -p request-pull'
374 test_core_pager_overrides expect_success test_must_fail 'git -p request-pull'
375 test_core_pager_subdir    expect_failure test_must_fail 'git -p request-pull'
376 test_GIT_PAGER_overrides  expect_success test_must_fail 'git -p request-pull'
377
378 test_default_pager        expect_success test_must_fail 'git -p'
379 test_PAGER_overrides      expect_success test_must_fail 'git -p'
380 test_local_config_ignored expect_failure test_must_fail 'git -p'
381 test_no_local_config_subdir expect_success test_must_fail 'git -p'
382 test_GIT_PAGER_overrides  expect_success test_must_fail 'git -p'
383
384 test_doesnt_paginate      expect_failure test_must_fail 'git -p nonsense'
385
386 test_pager_choices                       'git shortlog'
387 test_expect_success 'setup: configure shortlog not to paginate' '
388         git config pager.shortlog false
389 '
390 test_doesnt_paginate      expect_success 'git shortlog'
391 test_no_local_config_subdir expect_success 'git shortlog'
392 test_default_pager        expect_success 'git -p shortlog'
393 test_core_pager_subdir    expect_success 'git -p shortlog'
394
395 test_core_pager_subdir    expect_success test_must_fail \
396                                          'git -p apply </dev/null'
397
398 test_expect_success TTY 'command-specific pager' '
399         sane_unset PAGER GIT_PAGER &&
400         echo "foo:initial" >expect &&
401         >actual &&
402         test_unconfig core.pager &&
403         test_config pager.log "sed s/^/foo:/ >actual" &&
404         test_terminal git log --format=%s -1 &&
405         test_cmp expect actual
406 '
407
408 test_expect_success TTY 'command-specific pager overrides core.pager' '
409         sane_unset PAGER GIT_PAGER &&
410         echo "foo:initial" >expect &&
411         >actual &&
412         test_config core.pager "exit 1" &&
413         test_config pager.log "sed s/^/foo:/ >actual" &&
414         test_terminal git log --format=%s -1 &&
415         test_cmp expect actual
416 '
417
418 test_expect_success TTY 'command-specific pager overridden by environment' '
419         GIT_PAGER="sed s/^/foo:/ >actual" && export GIT_PAGER &&
420         >actual &&
421         echo "foo:initial" >expect &&
422         test_config pager.log "exit 1" &&
423         test_terminal git log --format=%s -1 &&
424         test_cmp expect actual
425 '
426
427 test_expect_success 'setup external command' '
428         cat >git-external <<-\EOF &&
429         #!/bin/sh
430         git "$@"
431         EOF
432         chmod +x git-external
433 '
434
435 test_expect_success TTY 'command-specific pager works for external commands' '
436         sane_unset PAGER GIT_PAGER &&
437         echo "foo:initial" >expect &&
438         >actual &&
439         test_config pager.external "sed s/^/foo:/ >actual" &&
440         test_terminal git --exec-path="$(pwd)" external log --format=%s -1 &&
441         test_cmp expect actual
442 '
443
444 test_expect_success TTY 'sub-commands of externals use their own pager' '
445         sane_unset PAGER GIT_PAGER &&
446         echo "foo:initial" >expect &&
447         >actual &&
448         test_config pager.log "sed s/^/foo:/ >actual" &&
449         test_terminal git --exec-path=. external log --format=%s -1 &&
450         test_cmp expect actual
451 '
452
453 test_expect_success TTY 'external command pagers override sub-commands' '
454         sane_unset PAGER GIT_PAGER &&
455         >expect &&
456         >actual &&
457         test_config pager.external false &&
458         test_config pager.log "sed s/^/log:/ >actual" &&
459         test_terminal git --exec-path=. external log --format=%s -1 &&
460         test_cmp expect actual
461 '
462
463 test_expect_success 'command with underscores does not complain' '
464         write_script git-under_score <<-\EOF &&
465         echo ok
466         EOF
467         git --exec-path=. under_score >actual 2>&1 &&
468         echo ok >expect &&
469         test_cmp expect actual
470 '
471
472 test_done