Merge branch 'sb/histogram-less-memory'
[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 'configuration can enable pager (from subdir)' '
114         rm -f paginated.out &&
115         mkdir -p subdir &&
116         test_config pager.bundle true &&
117
118         git bundle create test.bundle --all &&
119         rm -f paginated.out subdir/paginated.out &&
120         (
121                 cd subdir &&
122                 test_terminal git bundle unbundle ../test.bundle
123         ) &&
124         {
125                 test -e paginated.out ||
126                 test -e subdir/paginated.out
127         }
128 '
129
130 test_expect_success TTY 'git tag -l defaults to paging' '
131         rm -f paginated.out &&
132         test_terminal git tag -l &&
133         test -e paginated.out
134 '
135
136 test_expect_success TTY 'git tag -l respects pager.tag' '
137         rm -f paginated.out &&
138         test_terminal git -c pager.tag=false tag -l &&
139         ! test -e paginated.out
140 '
141
142 test_expect_success TTY 'git tag -l respects --no-pager' '
143         rm -f paginated.out &&
144         test_terminal git -c pager.tag --no-pager tag -l &&
145         ! test -e paginated.out
146 '
147
148 test_expect_success TTY 'git tag with no args defaults to paging' '
149         # no args implies -l so this should page like -l
150         rm -f paginated.out &&
151         test_terminal git tag &&
152         test -e paginated.out
153 '
154
155 test_expect_success TTY 'git tag with no args respects pager.tag' '
156         # no args implies -l so this should page like -l
157         rm -f paginated.out &&
158         test_terminal git -c pager.tag=false tag &&
159         ! test -e paginated.out
160 '
161
162 test_expect_success TTY 'git tag --contains defaults to paging' '
163         # --contains implies -l so this should page like -l
164         rm -f paginated.out &&
165         test_terminal git tag --contains &&
166         test -e paginated.out
167 '
168
169 test_expect_success TTY 'git tag --contains respects pager.tag' '
170         # --contains implies -l so this should page like -l
171         rm -f paginated.out &&
172         test_terminal git -c pager.tag=false tag --contains &&
173         ! test -e paginated.out
174 '
175
176 test_expect_success TTY 'git tag -a defaults to not paging' '
177         test_when_finished "git tag -d newtag" &&
178         rm -f paginated.out &&
179         test_terminal git tag -am message newtag &&
180         ! test -e paginated.out
181 '
182
183 test_expect_success TTY 'git tag -a ignores pager.tag' '
184         test_when_finished "git tag -d newtag" &&
185         rm -f paginated.out &&
186         test_terminal git -c pager.tag tag -am message newtag &&
187         ! test -e paginated.out
188 '
189
190 test_expect_success TTY 'git tag -a respects --paginate' '
191         test_when_finished "git tag -d newtag" &&
192         rm -f paginated.out &&
193         test_terminal git --paginate tag -am message newtag &&
194         test -e paginated.out
195 '
196
197 test_expect_success TTY 'git tag as alias ignores pager.tag with -a' '
198         test_when_finished "git tag -d newtag" &&
199         rm -f paginated.out &&
200         test_terminal git -c pager.tag -c alias.t=tag t -am message newtag &&
201         ! test -e paginated.out
202 '
203
204 test_expect_success TTY 'git tag as alias respects pager.tag with -l' '
205         rm -f paginated.out &&
206         test_terminal git -c pager.tag=false -c alias.t=tag t -l &&
207         ! test -e paginated.out
208 '
209
210 test_expect_success TTY 'git branch defaults to paging' '
211         rm -f paginated.out &&
212         test_terminal git branch &&
213         test -e paginated.out
214 '
215
216 test_expect_success TTY 'git branch respects pager.branch' '
217         rm -f paginated.out &&
218         test_terminal git -c pager.branch=false branch &&
219         ! test -e paginated.out
220 '
221
222 test_expect_success TTY 'git branch respects --no-pager' '
223         rm -f paginated.out &&
224         test_terminal git --no-pager branch &&
225         ! test -e paginated.out
226 '
227
228 test_expect_success TTY 'git branch --edit-description ignores pager.branch' '
229         rm -f paginated.out editor.used &&
230         write_script editor <<-\EOF &&
231                 echo "New description" >"$1"
232                 touch editor.used
233         EOF
234         EDITOR=./editor test_terminal git -c pager.branch branch --edit-description &&
235         ! test -e paginated.out &&
236         test -e editor.used
237 '
238
239 test_expect_success TTY 'git branch --set-upstream-to ignores pager.branch' '
240         rm -f paginated.out &&
241         git branch other &&
242         test_when_finished "git branch -D other" &&
243         test_terminal git -c pager.branch branch --set-upstream-to=other &&
244         test_when_finished "git branch --unset-upstream" &&
245         ! test -e paginated.out
246 '
247
248 test_expect_success TTY 'git config ignores pager.config when setting' '
249         rm -f paginated.out &&
250         test_terminal git -c pager.config config foo.bar bar &&
251         ! test -e paginated.out
252 '
253
254 test_expect_success TTY 'git config --edit ignores pager.config' '
255         rm -f paginated.out editor.used &&
256         write_script editor <<-\EOF &&
257                 touch editor.used
258         EOF
259         EDITOR=./editor test_terminal git -c pager.config config --edit &&
260         ! test -e paginated.out &&
261         test -e editor.used
262 '
263
264 test_expect_success TTY 'git config --get ignores pager.config' '
265         rm -f paginated.out &&
266         test_terminal git -c pager.config config --get foo.bar &&
267         ! test -e paginated.out
268 '
269
270 test_expect_success TTY 'git config --get-urlmatch defaults to paging' '
271         rm -f paginated.out &&
272         test_terminal git -c http."https://foo.com/".bar=foo \
273                           config --get-urlmatch http https://foo.com &&
274         test -e paginated.out
275 '
276
277 test_expect_success TTY 'git config --get-all respects pager.config' '
278         rm -f paginated.out &&
279         test_terminal git -c pager.config=false config --get-all foo.bar &&
280         ! test -e paginated.out
281 '
282
283 test_expect_success TTY 'git config --list defaults to paging' '
284         rm -f paginated.out &&
285         test_terminal git config --list &&
286         test -e paginated.out
287 '
288
289
290 # A colored commit log will begin with an appropriate ANSI escape
291 # for the first color; the text "commit" comes later.
292 colorful() {
293         read firstline <$1
294         ! expr "$firstline" : "[a-zA-Z]" >/dev/null
295 }
296
297 test_expect_success 'tests can detect color' '
298         rm -f colorful.log colorless.log &&
299         git log --no-color >colorless.log &&
300         git log --color >colorful.log &&
301         ! colorful colorless.log &&
302         colorful colorful.log
303 '
304
305 test_expect_success 'no color when stdout is a regular file' '
306         rm -f colorless.log &&
307         test_config color.ui auto &&
308         git log >colorless.log &&
309         ! colorful colorless.log
310 '
311
312 test_expect_success TTY 'color when writing to a pager' '
313         rm -f paginated.out &&
314         test_config color.ui auto &&
315         test_terminal git log &&
316         colorful paginated.out
317 '
318
319 test_expect_success TTY 'colors are suppressed by color.pager' '
320         rm -f paginated.out &&
321         test_config color.ui auto &&
322         test_config color.pager false &&
323         test_terminal git log &&
324         ! colorful paginated.out
325 '
326
327 test_expect_success 'color when writing to a file intended for a pager' '
328         rm -f colorful.log &&
329         test_config color.ui auto &&
330         (
331                 TERM=vt100 &&
332                 GIT_PAGER_IN_USE=true &&
333                 export TERM GIT_PAGER_IN_USE &&
334                 git log >colorful.log
335         ) &&
336         colorful colorful.log
337 '
338
339 test_expect_success TTY 'colors are sent to pager for external commands' '
340         test_config alias.externallog "!git log" &&
341         test_config color.ui auto &&
342         test_terminal git -p externallog &&
343         colorful paginated.out
344 '
345
346 # Use this helper to make it easy for the caller of your
347 # terminal-using function to specify whether it should fail.
348 # If you write
349 #
350 #       your_test() {
351 #               parse_args "$@"
352 #
353 #               $test_expectation "$cmd - behaves well" "
354 #                       ...
355 #                       $full_command &&
356 #                       ...
357 #               "
358 #       }
359 #
360 # then your test can be used like this:
361 #
362 #       your_test expect_(success|failure) [test_must_fail] 'git foo'
363 #
364 parse_args() {
365         test_expectation="test_$1"
366         shift
367         if test "$1" = test_must_fail
368         then
369                 full_command="test_must_fail test_terminal "
370                 shift
371         else
372                 full_command="test_terminal "
373         fi
374         cmd=$1
375         full_command="$full_command $1"
376 }
377
378 test_default_pager() {
379         parse_args "$@"
380
381         $test_expectation SIMPLEPAGER,TTY "$cmd - default pager is used by default" "
382                 sane_unset PAGER GIT_PAGER &&
383                 test_unconfig core.pager &&
384                 rm -f default_pager_used &&
385                 cat >\$less <<-\EOF &&
386                 #!/bin/sh
387                 wc >default_pager_used
388                 EOF
389                 chmod +x \$less &&
390                 (
391                         PATH=.:\$PATH &&
392                         export PATH &&
393                         $full_command
394                 ) &&
395                 test -e default_pager_used
396         "
397 }
398
399 test_PAGER_overrides() {
400         parse_args "$@"
401
402         $test_expectation TTY "$cmd - PAGER overrides default pager" "
403                 sane_unset GIT_PAGER &&
404                 test_unconfig core.pager &&
405                 rm -f PAGER_used &&
406                 PAGER='wc >PAGER_used' &&
407                 export PAGER &&
408                 $full_command &&
409                 test -e PAGER_used
410         "
411 }
412
413 test_core_pager_overrides() {
414         if_local_config=
415         used_if_wanted='overrides PAGER'
416         test_core_pager "$@"
417 }
418
419 test_local_config_ignored() {
420         if_local_config='! '
421         used_if_wanted='is not used'
422         test_core_pager "$@"
423 }
424
425 test_core_pager() {
426         parse_args "$@"
427
428         $test_expectation TTY "$cmd - repository-local core.pager setting $used_if_wanted" "
429                 sane_unset GIT_PAGER &&
430                 rm -f core.pager_used &&
431                 PAGER=wc &&
432                 export PAGER &&
433                 test_config core.pager 'wc >core.pager_used' &&
434                 $full_command &&
435                 ${if_local_config}test -e core.pager_used
436         "
437 }
438
439 test_core_pager_subdir() {
440         if_local_config=
441         used_if_wanted='overrides PAGER'
442         test_pager_subdir_helper "$@"
443 }
444
445 test_no_local_config_subdir() {
446         if_local_config='! '
447         used_if_wanted='is not used'
448         test_pager_subdir_helper "$@"
449 }
450
451 test_pager_subdir_helper() {
452         parse_args "$@"
453
454         $test_expectation TTY "$cmd - core.pager $used_if_wanted from subdirectory" "
455                 sane_unset GIT_PAGER &&
456                 rm -f core.pager_used &&
457                 rm -fr sub &&
458                 PAGER=wc &&
459                 stampname=\$(pwd)/core.pager_used &&
460                 export PAGER stampname &&
461                 test_config core.pager 'wc >\"\$stampname\"' &&
462                 mkdir sub &&
463                 (
464                         cd sub &&
465                         $full_command
466                 ) &&
467                 ${if_local_config}test -e core.pager_used
468         "
469 }
470
471 test_GIT_PAGER_overrides() {
472         parse_args "$@"
473
474         $test_expectation TTY "$cmd - GIT_PAGER overrides core.pager" "
475                 rm -f GIT_PAGER_used &&
476                 test_config core.pager wc &&
477                 GIT_PAGER='wc >GIT_PAGER_used' &&
478                 export GIT_PAGER &&
479                 $full_command &&
480                 test -e GIT_PAGER_used
481         "
482 }
483
484 test_doesnt_paginate() {
485         parse_args "$@"
486
487         $test_expectation TTY "no pager for '$cmd'" "
488                 rm -f GIT_PAGER_used &&
489                 GIT_PAGER='wc >GIT_PAGER_used' &&
490                 export GIT_PAGER &&
491                 $full_command &&
492                 ! test -e GIT_PAGER_used
493         "
494 }
495
496 test_pager_choices() {
497         test_default_pager        expect_success "$@"
498         test_PAGER_overrides      expect_success "$@"
499         test_core_pager_overrides expect_success "$@"
500         test_core_pager_subdir    expect_success "$@"
501         test_GIT_PAGER_overrides  expect_success "$@"
502 }
503
504 test_expect_success 'setup: some aliases' '
505         git config alias.aliasedlog log &&
506         git config alias.true "!true"
507 '
508
509 test_pager_choices                       'git log'
510 test_pager_choices                       'git -p log'
511 test_pager_choices                       'git aliasedlog'
512
513 test_default_pager        expect_success 'git -p aliasedlog'
514 test_PAGER_overrides      expect_success 'git -p aliasedlog'
515 test_core_pager_overrides expect_success 'git -p aliasedlog'
516 test_core_pager_subdir    expect_success 'git -p aliasedlog'
517 test_GIT_PAGER_overrides  expect_success 'git -p aliasedlog'
518
519 test_default_pager        expect_success 'git -p true'
520 test_PAGER_overrides      expect_success 'git -p true'
521 test_core_pager_overrides expect_success 'git -p true'
522 test_core_pager_subdir    expect_success 'git -p true'
523 test_GIT_PAGER_overrides  expect_success 'git -p true'
524
525 test_default_pager        expect_success test_must_fail 'git -p request-pull'
526 test_PAGER_overrides      expect_success test_must_fail 'git -p request-pull'
527 test_core_pager_overrides expect_success test_must_fail 'git -p request-pull'
528 test_core_pager_subdir    expect_success test_must_fail 'git -p request-pull'
529 test_GIT_PAGER_overrides  expect_success test_must_fail 'git -p request-pull'
530
531 test_default_pager        expect_success test_must_fail 'git -p'
532 test_PAGER_overrides      expect_success test_must_fail 'git -p'
533 test_local_config_ignored expect_failure test_must_fail 'git -p'
534 test_GIT_PAGER_overrides  expect_success test_must_fail 'git -p'
535
536 test_expect_success TTY 'core.pager in repo config works and retains cwd' '
537         sane_unset GIT_PAGER &&
538         test_config core.pager "cat >cwd-retained" &&
539         (
540                 cd sub &&
541                 rm -f cwd-retained &&
542                 test_terminal git -p rev-parse HEAD &&
543                 test_path_is_file cwd-retained
544         )
545 '
546
547 test_expect_success TTY 'core.pager is found via alias in subdirectory' '
548         sane_unset GIT_PAGER &&
549         test_config core.pager "cat >via-alias" &&
550         (
551                 cd sub &&
552                 rm -f via-alias &&
553                 test_terminal git -c alias.r="-p rev-parse" r HEAD &&
554                 test_path_is_file via-alias
555         )
556 '
557
558 test_doesnt_paginate      expect_failure test_must_fail 'git -p nonsense'
559
560 test_pager_choices                       'git shortlog'
561 test_expect_success 'setup: configure shortlog not to paginate' '
562         git config pager.shortlog false
563 '
564 test_doesnt_paginate      expect_success 'git shortlog'
565 test_no_local_config_subdir expect_success 'git shortlog'
566 test_default_pager        expect_success 'git -p shortlog'
567 test_core_pager_subdir    expect_success 'git -p shortlog'
568
569 test_core_pager_subdir    expect_success test_must_fail \
570                                          'git -p apply </dev/null'
571
572 test_expect_success TTY 'command-specific pager' '
573         sane_unset PAGER GIT_PAGER &&
574         echo "foo:initial" >expect &&
575         >actual &&
576         test_unconfig core.pager &&
577         test_config pager.log "sed s/^/foo:/ >actual" &&
578         test_terminal git log --format=%s -1 &&
579         test_cmp expect actual
580 '
581
582 test_expect_success TTY 'command-specific pager overrides core.pager' '
583         sane_unset PAGER GIT_PAGER &&
584         echo "foo:initial" >expect &&
585         >actual &&
586         test_config core.pager "exit 1" &&
587         test_config pager.log "sed s/^/foo:/ >actual" &&
588         test_terminal git log --format=%s -1 &&
589         test_cmp expect actual
590 '
591
592 test_expect_success TTY 'command-specific pager overridden by environment' '
593         GIT_PAGER="sed s/^/foo:/ >actual" && export GIT_PAGER &&
594         >actual &&
595         echo "foo:initial" >expect &&
596         test_config pager.log "exit 1" &&
597         test_terminal git log --format=%s -1 &&
598         test_cmp expect actual
599 '
600
601 test_expect_success 'setup external command' '
602         cat >git-external <<-\EOF &&
603         #!/bin/sh
604         git "$@"
605         EOF
606         chmod +x git-external
607 '
608
609 test_expect_success TTY 'command-specific pager works for external commands' '
610         sane_unset PAGER GIT_PAGER &&
611         echo "foo:initial" >expect &&
612         >actual &&
613         test_config pager.external "sed s/^/foo:/ >actual" &&
614         test_terminal git --exec-path="$(pwd)" external log --format=%s -1 &&
615         test_cmp expect actual
616 '
617
618 test_expect_success TTY 'sub-commands of externals use their own pager' '
619         sane_unset PAGER GIT_PAGER &&
620         echo "foo:initial" >expect &&
621         >actual &&
622         test_config pager.log "sed s/^/foo:/ >actual" &&
623         test_terminal git --exec-path=. external log --format=%s -1 &&
624         test_cmp expect actual
625 '
626
627 test_expect_success TTY 'external command pagers override sub-commands' '
628         sane_unset PAGER GIT_PAGER &&
629         >expect &&
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_cmp expect actual
635 '
636
637 test_expect_success 'command with underscores does not complain' '
638         write_script git-under_score <<-\EOF &&
639         echo ok
640         EOF
641         git --exec-path=. under_score >actual 2>&1 &&
642         echo ok >expect &&
643         test_cmp expect actual
644 '
645
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
654         EOF
655         test_terminal env PAGER="cat >actual" COLUMNS=80 \
656                 git -c column.ui=auto tag --sort=authordate &&
657         test_cmp expect actual
658 '
659
660 test_done