Merge branch 'cl/config-regexp-docfix' into maint-2.46
[git/gitster.git] / t / t7006-pager.sh
bloba0296d6ca4019e08e7e8473ee22eabee513f5879
1 #!/bin/sh
3 test_description='Test automatic use of a pager.'
5 TEST_PASSES_SANITIZE_LEAK=true
6 . ./test-lib.sh
7 . "$TEST_DIRECTORY"/lib-pager.sh
8 . "$TEST_DIRECTORY"/lib-terminal.sh
10 test_expect_success 'setup' '
11 sane_unset GIT_PAGER GIT_PAGER_IN_USE &&
12 test_unconfig core.pager &&
14 PAGER="cat >paginated.out" &&
15 export PAGER &&
17 test_commit initial
20 test_expect_success TTY 'some commands use a pager' '
21 rm -f paginated.out &&
22 test_terminal git log &&
23 test_path_is_file paginated.out
26 test_expect_failure TTY 'pager runs from subdir' '
27 echo subdir/paginated.out >expected &&
28 mkdir -p subdir &&
29 rm -f paginated.out subdir/paginated.out &&
31 cd subdir &&
32 test_terminal git log
33 ) &&
35 ls paginated.out subdir/paginated.out ||
37 } >actual &&
38 test_cmp expected actual
41 test_expect_success TTY 'LESS and LV envvars are set for pagination' '
43 sane_unset LESS LV &&
44 PAGER="env >pager-env.out; wc" &&
45 export PAGER &&
47 test_terminal git log
48 ) &&
49 grep ^LESS= pager-env.out &&
50 grep ^LV= pager-env.out
53 test_expect_success !MINGW,TTY 'LESS and LV envvars set by git-sh-setup' '
55 sane_unset LESS LV &&
56 PAGER="env >pager-env.out; wc" &&
57 export PAGER &&
58 PATH="$(git --exec-path):$PATH" &&
59 export PATH &&
60 test_terminal sh -c ". git-sh-setup && git_pager"
61 ) &&
62 grep ^LESS= pager-env.out &&
63 grep ^LV= pager-env.out
66 test_expect_success TTY 'some commands do not use a pager' '
67 rm -f paginated.out &&
68 test_terminal git rev-list HEAD &&
69 test_path_is_missing paginated.out
72 test_expect_success 'no pager when stdout is a pipe' '
73 rm -f paginated.out &&
74 git log | cat &&
75 test_path_is_missing paginated.out
78 test_expect_success 'no pager when stdout is a regular file' '
79 rm -f paginated.out &&
80 git log >file &&
81 test_path_is_missing paginated.out
84 test_expect_success TTY 'git --paginate rev-list uses a pager' '
85 rm -f paginated.out &&
86 test_terminal git --paginate rev-list HEAD &&
87 test_path_is_file paginated.out
90 test_expect_success 'no pager even with --paginate when stdout is a pipe' '
91 rm -f file paginated.out &&
92 git --paginate log | cat &&
93 test_path_is_missing paginated.out
96 test_expect_success TTY 'no pager with --no-pager' '
97 rm -f paginated.out &&
98 test_terminal git --no-pager log &&
99 test_path_is_missing paginated.out
102 test_expect_success TTY 'configuration can disable pager' '
103 rm -f paginated.out &&
104 test_unconfig pager.grep &&
105 test_terminal git grep initial &&
106 test_path_is_file paginated.out &&
108 rm -f paginated.out &&
109 test_config pager.grep false &&
110 test_terminal git grep initial &&
111 test_path_is_missing paginated.out
114 test_expect_success TTY 'configuration can enable pager (from subdir)' '
115 rm -f paginated.out &&
116 mkdir -p subdir &&
117 test_config pager.bundle true &&
119 git bundle create test.bundle --all &&
120 rm -f paginated.out subdir/paginated.out &&
122 cd subdir &&
123 test_terminal git bundle unbundle ../test.bundle
124 ) &&
126 test_path_is_file paginated.out ||
127 test_path_is_file subdir/paginated.out
131 test_expect_success TTY 'git tag -l defaults to paging' '
132 rm -f paginated.out &&
133 test_terminal git tag -l &&
134 test_path_is_file paginated.out
137 test_expect_success TTY 'git tag -l respects pager.tag' '
138 rm -f paginated.out &&
139 test_terminal git -c pager.tag=false tag -l &&
140 test_path_is_missing paginated.out
143 test_expect_success TTY 'git tag -l respects --no-pager' '
144 rm -f paginated.out &&
145 test_terminal git -c pager.tag --no-pager tag -l &&
146 test_path_is_missing paginated.out
149 test_expect_success TTY 'git tag with no args defaults to paging' '
150 # no args implies -l so this should page like -l
151 rm -f paginated.out &&
152 test_terminal git tag &&
153 test_path_is_file paginated.out
156 test_expect_success TTY 'git tag with no args respects pager.tag' '
157 # no args implies -l so this should page like -l
158 rm -f paginated.out &&
159 test_terminal git -c pager.tag=false tag &&
160 test_path_is_missing paginated.out
163 test_expect_success TTY 'git tag --contains defaults to paging' '
164 # --contains implies -l so this should page like -l
165 rm -f paginated.out &&
166 test_terminal git tag --contains &&
167 test_path_is_file paginated.out
170 test_expect_success TTY 'git tag --contains respects pager.tag' '
171 # --contains implies -l so this should page like -l
172 rm -f paginated.out &&
173 test_terminal git -c pager.tag=false tag --contains &&
174 test_path_is_missing paginated.out
177 test_expect_success TTY 'git tag -a defaults to not paging' '
178 test_when_finished "git tag -d newtag" &&
179 rm -f paginated.out &&
180 test_terminal git tag -am message newtag &&
181 test_path_is_missing paginated.out
184 test_expect_success TTY 'git tag -a ignores pager.tag' '
185 test_when_finished "git tag -d newtag" &&
186 rm -f paginated.out &&
187 test_terminal git -c pager.tag tag -am message newtag &&
188 test_path_is_missing paginated.out
191 test_expect_success TTY 'git tag -a respects --paginate' '
192 test_when_finished "git tag -d newtag" &&
193 rm -f paginated.out &&
194 test_terminal git --paginate tag -am message newtag &&
195 test_path_is_file paginated.out
198 test_expect_success TTY 'git tag as alias ignores pager.tag with -a' '
199 test_when_finished "git tag -d newtag" &&
200 rm -f paginated.out &&
201 test_terminal git -c pager.tag -c alias.t=tag t -am message newtag &&
202 test_path_is_missing paginated.out
205 test_expect_success TTY 'git tag as alias respects pager.tag with -l' '
206 rm -f paginated.out &&
207 test_terminal git -c pager.tag=false -c alias.t=tag t -l &&
208 test_path_is_missing paginated.out
211 test_expect_success TTY 'git branch defaults to paging' '
212 rm -f paginated.out &&
213 test_terminal git branch &&
214 test_path_is_file paginated.out
217 test_expect_success TTY 'git branch respects pager.branch' '
218 rm -f paginated.out &&
219 test_terminal git -c pager.branch=false branch &&
220 test_path_is_missing paginated.out
223 test_expect_success TTY 'git branch respects --no-pager' '
224 rm -f paginated.out &&
225 test_terminal git --no-pager branch &&
226 test_path_is_missing paginated.out
229 test_expect_success TTY 'git branch --edit-description ignores pager.branch' '
230 rm -f paginated.out editor.used &&
231 write_script editor <<-\EOF &&
232 echo "New description" >"$1"
233 touch editor.used
235 EDITOR=./editor test_terminal git -c pager.branch branch --edit-description &&
236 test_path_is_missing paginated.out &&
237 test_path_is_file editor.used
240 test_expect_success TTY 'git branch --set-upstream-to ignores pager.branch' '
241 rm -f paginated.out &&
242 git branch other &&
243 test_when_finished "git branch -D other" &&
244 test_terminal git -c pager.branch branch --set-upstream-to=other &&
245 test_when_finished "git branch --unset-upstream" &&
246 test_path_is_missing paginated.out
249 test_expect_success TTY 'git config ignores pager.config when setting' '
250 rm -f paginated.out &&
251 test_terminal git -c pager.config config foo.bar bar &&
252 test_path_is_missing paginated.out
255 test_expect_success TTY 'git config --edit ignores pager.config' '
256 rm -f paginated.out editor.used &&
257 write_script editor <<-\EOF &&
258 touch editor.used
260 EDITOR=./editor test_terminal git -c pager.config config --edit &&
261 test_path_is_missing paginated.out &&
262 test_path_is_file editor.used
265 test_expect_success TTY 'git config --get ignores pager.config' '
266 rm -f paginated.out &&
267 test_terminal git -c pager.config config --get foo.bar &&
268 test_path_is_missing paginated.out
271 test_expect_success TTY 'git config --get-urlmatch defaults to paging' '
272 rm -f paginated.out &&
273 test_terminal git -c http."https://foo.com/".bar=foo \
274 config --get-urlmatch http https://foo.com &&
275 test_path_is_file paginated.out
278 test_expect_success TTY 'git config --get-all respects pager.config' '
279 rm -f paginated.out &&
280 test_terminal git -c pager.config=false config --get-all foo.bar &&
281 test_path_is_missing paginated.out
284 test_expect_success TTY 'git config --list defaults to paging' '
285 rm -f paginated.out &&
286 test_terminal git config --list &&
287 test_path_is_file paginated.out
291 # A colored commit log will begin with an appropriate ANSI escape
292 # for the first color; the text "commit" comes later.
293 colorful() {
294 read firstline <$1
295 ! expr "$firstline" : "[a-zA-Z]" >/dev/null
298 test_expect_success 'tests can detect color' '
299 rm -f colorful.log colorless.log &&
300 git log --no-color >colorless.log &&
301 git log --color >colorful.log &&
302 ! colorful colorless.log &&
303 colorful colorful.log
306 test_expect_success 'no color when stdout is a regular file' '
307 rm -f colorless.log &&
308 test_config color.ui auto &&
309 git log >colorless.log &&
310 ! colorful colorless.log
313 test_expect_success TTY 'color when writing to a pager' '
314 rm -f paginated.out &&
315 test_config color.ui auto &&
316 test_terminal git log &&
317 colorful paginated.out
320 test_expect_success TTY 'colors are suppressed by color.pager' '
321 rm -f paginated.out &&
322 test_config color.ui auto &&
323 test_config color.pager false &&
324 test_terminal git log &&
325 ! colorful paginated.out
328 test_expect_success 'color when writing to a file intended for a pager' '
329 rm -f colorful.log &&
330 test_config color.ui auto &&
332 TERM=vt100 &&
333 GIT_PAGER_IN_USE=true &&
334 export TERM GIT_PAGER_IN_USE &&
335 git log >colorful.log
336 ) &&
337 colorful colorful.log
340 test_expect_success TTY 'colors are sent to pager for external commands' '
341 test_config alias.externallog "!git log" &&
342 test_config color.ui auto &&
343 test_terminal git -p externallog &&
344 colorful paginated.out
347 # Use this helper to make it easy for the caller of your
348 # terminal-using function to specify whether it should fail.
349 # If you write
351 # your_test() {
352 # parse_args "$@"
354 # $test_expectation "$cmd - behaves well" "
355 # ...
356 # $full_command &&
357 # ...
361 # then your test can be used like this:
363 # your_test expect_(success|failure) [test_must_fail] 'git foo'
365 parse_args() {
366 test_expectation="test_$1"
367 shift
368 if test "$1" = test_must_fail
369 then
370 full_command="test_must_fail test_terminal "
371 shift
372 else
373 full_command="test_terminal "
375 cmd=$1
376 full_command="$full_command $1"
379 test_default_pager() {
380 parse_args "$@"
382 $test_expectation SIMPLEPAGER,TTY "$cmd - default pager is used by default" "
383 sane_unset PAGER GIT_PAGER &&
384 test_unconfig core.pager &&
385 rm -f default_pager_used &&
386 cat >\$less <<-\EOF &&
387 #!/bin/sh
388 wc >default_pager_used
390 chmod +x \$less &&
392 PATH=.:\$PATH &&
393 export PATH &&
394 $full_command
395 ) &&
396 test_path_is_file default_pager_used
400 test_PAGER_overrides() {
401 parse_args "$@"
403 $test_expectation TTY "$cmd - PAGER overrides default pager" "
404 sane_unset GIT_PAGER &&
405 test_unconfig core.pager &&
406 rm -f PAGER_used &&
407 PAGER='wc >PAGER_used' &&
408 export PAGER &&
409 $full_command &&
410 test_path_is_file PAGER_used
414 test_core_pager_overrides() {
415 if_local_config=
416 used_if_wanted='overrides PAGER'
417 test_core_pager "$@"
420 test_local_config_ignored() {
421 if_local_config='! '
422 used_if_wanted='is not used'
423 test_core_pager "$@"
426 test_core_pager() {
427 parse_args "$@"
429 $test_expectation TTY "$cmd - repository-local core.pager setting $used_if_wanted" "
430 sane_unset GIT_PAGER &&
431 rm -f core.pager_used &&
432 PAGER=wc &&
433 export PAGER &&
434 test_config core.pager 'wc >core.pager_used' &&
435 $full_command &&
436 ${if_local_config}test_path_is_file core.pager_used
440 test_core_pager_subdir() {
441 if_local_config=
442 used_if_wanted='overrides PAGER'
443 test_pager_subdir_helper "$@"
446 test_no_local_config_subdir() {
447 if_local_config='! '
448 used_if_wanted='is not used'
449 test_pager_subdir_helper "$@"
452 test_pager_subdir_helper() {
453 parse_args "$@"
455 $test_expectation TTY "$cmd - core.pager $used_if_wanted from subdirectory" "
456 sane_unset GIT_PAGER &&
457 rm -f core.pager_used &&
458 rm -fr sub &&
459 PAGER=wc &&
460 stampname=\$(pwd)/core.pager_used &&
461 export PAGER stampname &&
462 test_config core.pager 'wc >\"\$stampname\"' &&
463 mkdir sub &&
465 cd sub &&
466 $full_command
467 ) &&
468 ${if_local_config}test_path_is_file core.pager_used
472 test_GIT_PAGER_overrides() {
473 parse_args "$@"
475 $test_expectation TTY "$cmd - GIT_PAGER overrides core.pager" "
476 rm -f GIT_PAGER_used &&
477 test_config core.pager wc &&
478 GIT_PAGER='wc >GIT_PAGER_used' &&
479 export GIT_PAGER &&
480 $full_command &&
481 test_path_is_file GIT_PAGER_used
485 test_doesnt_paginate() {
486 parse_args "$@"
488 $test_expectation TTY "no pager for '$cmd'" "
489 rm -f GIT_PAGER_used &&
490 GIT_PAGER='wc >GIT_PAGER_used' &&
491 export GIT_PAGER &&
492 $full_command &&
493 test_path_is_missing GIT_PAGER_used
497 test_pager_choices() {
498 test_default_pager expect_success "$@"
499 test_PAGER_overrides expect_success "$@"
500 test_core_pager_overrides expect_success "$@"
501 test_core_pager_subdir expect_success "$@"
502 test_GIT_PAGER_overrides expect_success "$@"
505 test_expect_success 'setup: some aliases' '
506 git config alias.aliasedlog log &&
507 git config alias.true "!true"
510 test_pager_choices 'git log'
511 test_pager_choices 'git -p log'
512 test_pager_choices 'git aliasedlog'
514 test_default_pager expect_success 'git -p aliasedlog'
515 test_PAGER_overrides expect_success 'git -p aliasedlog'
516 test_core_pager_overrides expect_success 'git -p aliasedlog'
517 test_core_pager_subdir expect_success 'git -p aliasedlog'
518 test_GIT_PAGER_overrides expect_success 'git -p aliasedlog'
520 test_default_pager expect_success 'git -p true'
521 test_PAGER_overrides expect_success 'git -p true'
522 test_core_pager_overrides expect_success 'git -p true'
523 test_core_pager_subdir expect_success 'git -p true'
524 test_GIT_PAGER_overrides expect_success 'git -p true'
526 test_default_pager expect_success test_must_fail 'git -p request-pull'
527 test_PAGER_overrides expect_success test_must_fail 'git -p request-pull'
528 test_core_pager_overrides expect_success test_must_fail 'git -p request-pull'
529 test_core_pager_subdir expect_success test_must_fail 'git -p request-pull'
530 test_GIT_PAGER_overrides expect_success test_must_fail 'git -p request-pull'
532 test_default_pager expect_success test_must_fail 'git -p'
533 test_PAGER_overrides expect_success test_must_fail 'git -p'
534 test_local_config_ignored expect_failure test_must_fail 'git -p'
535 test_GIT_PAGER_overrides expect_success test_must_fail 'git -p'
537 test_expect_success TTY 'core.pager in repo config works and retains cwd' '
538 sane_unset GIT_PAGER &&
539 test_config core.pager "cat >cwd-retained" &&
541 cd sub &&
542 rm -f cwd-retained &&
543 test_terminal git -p rev-parse HEAD &&
544 test_path_is_file cwd-retained
548 test_expect_success TTY 'core.pager is found via alias in subdirectory' '
549 sane_unset GIT_PAGER &&
550 test_config core.pager "cat >via-alias" &&
552 cd sub &&
553 rm -f via-alias &&
554 test_terminal git -c alias.r="-p rev-parse" r HEAD &&
555 test_path_is_file via-alias
559 test_doesnt_paginate expect_failure test_must_fail 'git -p nonsense'
561 test_pager_choices 'git shortlog'
562 test_expect_success 'setup: configure shortlog not to paginate' '
563 git config pager.shortlog false
565 test_doesnt_paginate expect_success 'git shortlog'
566 test_no_local_config_subdir expect_success 'git shortlog'
567 test_default_pager expect_success 'git -p shortlog'
568 test_core_pager_subdir expect_success 'git -p shortlog'
570 test_core_pager_subdir expect_success test_must_fail \
571 'git -p apply </dev/null'
573 test_expect_success TTY 'command-specific pager' '
574 sane_unset PAGER GIT_PAGER &&
575 echo "foo:initial" >expect &&
576 >actual &&
577 test_unconfig core.pager &&
578 test_config pager.log "sed s/^/foo:/ >actual" &&
579 test_terminal git log --format=%s -1 &&
580 test_cmp expect actual
583 test_expect_success TTY 'command-specific pager overrides core.pager' '
584 sane_unset PAGER GIT_PAGER &&
585 echo "foo:initial" >expect &&
586 >actual &&
587 test_config core.pager "exit 1" &&
588 test_config pager.log "sed s/^/foo:/ >actual" &&
589 test_terminal git log --format=%s -1 &&
590 test_cmp expect actual
593 test_expect_success TTY 'command-specific pager overridden by environment' '
594 GIT_PAGER="sed s/^/foo:/ >actual" && export GIT_PAGER &&
595 >actual &&
596 echo "foo:initial" >expect &&
597 test_config pager.log "exit 1" &&
598 test_terminal git log --format=%s -1 &&
599 test_cmp expect actual
602 test_expect_success 'setup external command' '
603 cat >git-external <<-\EOF &&
604 #!/bin/sh
605 git "$@"
607 chmod +x git-external
610 test_expect_success TTY 'command-specific pager works for external commands' '
611 sane_unset PAGER GIT_PAGER &&
612 echo "foo:initial" >expect &&
613 >actual &&
614 test_config pager.external "sed s/^/foo:/ >actual" &&
615 test_terminal git --exec-path="$(pwd)" external log --format=%s -1 &&
616 test_cmp expect actual
619 test_expect_success TTY 'sub-commands of externals use their own pager' '
620 sane_unset PAGER GIT_PAGER &&
621 echo "foo:initial" >expect &&
622 >actual &&
623 test_config pager.log "sed s/^/foo:/ >actual" &&
624 test_terminal git --exec-path=. external log --format=%s -1 &&
625 test_cmp expect actual
628 test_expect_success TTY 'external command pagers override sub-commands' '
629 sane_unset PAGER GIT_PAGER &&
630 >actual &&
631 test_config pager.external false &&
632 test_config pager.log "sed s/^/log:/ >actual" &&
633 test_terminal git --exec-path=. external log --format=%s -1 &&
634 test_must_be_empty actual
637 test_expect_success 'command with underscores does not complain' '
638 write_script git-under_score <<-\EOF &&
639 echo ok
641 git --exec-path=. under_score >actual 2>&1 &&
642 echo ok >expect &&
643 test_cmp expect actual
646 test_expect_success TTY 'git tag with auto-columns ' '
647 test_commit one &&
648 test_commit two &&
649 test_commit three &&
650 test_commit four &&
651 test_commit five &&
652 cat >expect <<-\EOF &&
653 initial one two three four five
655 test_terminal env PAGER="cat >actual" COLUMNS=80 \
656 git -c column.ui=auto tag --sort=authordate &&
657 test_cmp expect actual
660 test_expect_success 'setup trace2' '
661 GIT_TRACE2_BRIEF=1 &&
662 export GIT_TRACE2_BRIEF
665 test_expect_success 'setup large log output' '
666 perl -e "
667 print \"this is a long commit message\" x 50000
668 " >commit-msg &&
669 git commit --allow-empty -F commit-msg
672 test_expect_success TTY 'git returns SIGPIPE on early pager exit' '
673 test_when_finished "rm pager-used trace.normal" &&
674 test_config core.pager ">pager-used; head -n 1; exit 0" &&
675 GIT_TRACE2="$(pwd)/trace.normal" &&
676 export GIT_TRACE2 &&
677 test_when_finished "unset GIT_TRACE2" &&
679 if test_have_prereq !MINGW
680 then
681 { test_terminal git log >/dev/null; OUT=$?; } &&
682 test_match_signal 13 "$OUT"
683 else
684 test_terminal git log
685 fi &&
687 grep child_exit trace.normal >child-exits &&
688 test_line_count = 1 child-exits &&
689 grep " code:0 " child-exits &&
690 test_path_is_file pager-used
693 test_expect_success TTY 'git returns SIGPIPE on early pager non-zero exit' '
694 test_when_finished "rm pager-used trace.normal" &&
695 test_config core.pager ">pager-used; head -n 1; exit 1" &&
696 GIT_TRACE2="$(pwd)/trace.normal" &&
697 export GIT_TRACE2 &&
698 test_when_finished "unset GIT_TRACE2" &&
700 if test_have_prereq !MINGW
701 then
702 { test_terminal git log >/dev/null; OUT=$?; } &&
703 test_match_signal 13 "$OUT"
704 else
705 test_terminal git log
706 fi &&
708 grep child_exit trace.normal >child-exits &&
709 test_line_count = 1 child-exits &&
710 grep " code:1 " child-exits &&
711 test_path_is_file pager-used
714 test_expect_success TTY 'git discards pager non-zero exit without SIGPIPE' '
715 test_when_finished "rm pager-used trace.normal" &&
716 test_config core.pager "wc >pager-used; exit 1" &&
717 GIT_TRACE2="$(pwd)/trace.normal" &&
718 export GIT_TRACE2 &&
719 test_when_finished "unset GIT_TRACE2" &&
721 test_terminal git log &&
723 grep child_exit trace.normal >child-exits &&
724 test_line_count = 1 child-exits &&
725 grep " code:1 " child-exits &&
726 test_path_is_file pager-used
729 test_expect_success TTY 'git errors when asked to execute nonexisting pager' '
730 test_when_finished "rm -f err" &&
731 test_config core.pager "does-not-exist" &&
732 test_must_fail test_terminal git log 2>err &&
733 test_grep "unable to execute pager" err
736 test_expect_success TTY 'git returns SIGPIPE on propagated signals from pager' '
737 test_when_finished "rm pager-used trace.normal" &&
738 test_config core.pager ">pager-used; exec test-tool sigchain" &&
739 GIT_TRACE2="$(pwd)/trace.normal" &&
740 export GIT_TRACE2 &&
741 test_when_finished "unset GIT_TRACE2" &&
743 if test_have_prereq !MINGW
744 then
745 { test_terminal git log >/dev/null; OUT=$?; } &&
746 test_match_signal 13 "$OUT"
747 else
748 test_terminal git log
749 fi &&
751 grep child_exit trace.normal >child-exits &&
752 test_line_count = 1 child-exits &&
753 grep " code:143 " child-exits &&
754 test_path_is_file pager-used
757 test_expect_success TTY 'non-existent pager doesnt cause crash' '
758 test_config pager.show invalid-pager &&
759 test_must_fail test_terminal git show
762 test_done