Merge branch 'jk/verify-packfile-gently'
[git] / t / t7810-grep.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Junio C Hamano
4 #
5
6 test_description='git grep various.
7 '
8
9 . ./test-lib.sh
10
11 cat >hello.c <<EOF
12 #include <assert.h>
13 #include <stdio.h>
14
15 int main(int argc, const char **argv)
16 {
17         printf("Hello world.\n");
18         return 0;
19         /* char ?? */
20 }
21 EOF
22
23 test_expect_success setup '
24         {
25                 echo foo mmap bar
26                 echo foo_mmap bar
27                 echo foo_mmap bar mmap
28                 echo foo mmap bar_mmap
29                 echo foo_mmap bar mmap baz
30         } >file &&
31         {
32                 echo Hello world
33                 echo HeLLo world
34                 echo Hello_world
35                 echo HeLLo_world
36         } >hello_world &&
37         {
38                 echo "a+b*c"
39                 echo "a+bc"
40                 echo "abc"
41         } >ab &&
42         echo vvv >v &&
43         echo ww w >w &&
44         echo x x xx x >x &&
45         echo y yy >y &&
46         echo zzz > z &&
47         mkdir t &&
48         echo test >t/t &&
49         echo vvv >t/v &&
50         mkdir t/a &&
51         echo vvv >t/a/v &&
52         {
53                 echo "line without leading space1"
54                 echo " line with leading space1"
55                 echo " line with leading space2"
56                 echo " line with leading space3"
57                 echo "line without leading space2"
58         } >space &&
59         git add . &&
60         test_tick &&
61         git commit -m initial
62 '
63
64 test_expect_success 'grep should not segfault with a bad input' '
65         test_must_fail git grep "("
66 '
67
68 for H in HEAD ''
69 do
70         case "$H" in
71         HEAD)   HC='HEAD:' L='HEAD' ;;
72         '')     HC= L='in working tree' ;;
73         esac
74
75         test_expect_success "grep -w $L" '
76                 {
77                         echo ${HC}file:1:foo mmap bar
78                         echo ${HC}file:3:foo_mmap bar mmap
79                         echo ${HC}file:4:foo mmap bar_mmap
80                         echo ${HC}file:5:foo_mmap bar mmap baz
81                 } >expected &&
82                 git -c grep.linenumber=false grep -n -w -e mmap $H >actual &&
83                 test_cmp expected actual
84         '
85
86         test_expect_success "grep -w $L" '
87                 {
88                         echo ${HC}file:1:foo mmap bar
89                         echo ${HC}file:3:foo_mmap bar mmap
90                         echo ${HC}file:4:foo mmap bar_mmap
91                         echo ${HC}file:5:foo_mmap bar mmap baz
92                 } >expected &&
93                 git -c grep.linenumber=true grep -w -e mmap $H >actual &&
94                 test_cmp expected actual
95         '
96
97         test_expect_success "grep -w $L" '
98                 {
99                         echo ${HC}file:foo mmap bar
100                         echo ${HC}file:foo_mmap bar mmap
101                         echo ${HC}file:foo mmap bar_mmap
102                         echo ${HC}file:foo_mmap bar mmap baz
103                 } >expected &&
104                 git -c grep.linenumber=true grep --no-line-number -w -e mmap $H >actual &&
105                 test_cmp expected actual
106         '
107
108         test_expect_success "grep -w $L (w)" '
109                 : >expected &&
110                 test_must_fail git grep -n -w -e "^w" $H >actual &&
111                 test_cmp expected actual
112         '
113
114         test_expect_success "grep -w $L (x)" '
115                 {
116                         echo ${HC}x:1:x x xx x
117                 } >expected &&
118                 git grep -n -w -e "x xx* x" $H >actual &&
119                 test_cmp expected actual
120         '
121
122         test_expect_success "grep -w $L (y-1)" '
123                 {
124                         echo ${HC}y:1:y yy
125                 } >expected &&
126                 git grep -n -w -e "^y" $H >actual &&
127                 test_cmp expected actual
128         '
129
130         test_expect_success "grep -w $L (y-2)" '
131                 : >expected &&
132                 if git grep -n -w -e "^y y" $H >actual
133                 then
134                         echo should not have matched
135                         cat actual
136                         false
137                 else
138                         test_cmp expected actual
139                 fi
140         '
141
142         test_expect_success "grep -w $L (z)" '
143                 : >expected &&
144                 if git grep -n -w -e "^z" $H >actual
145                 then
146                         echo should not have matched
147                         cat actual
148                         false
149                 else
150                         test_cmp expected actual
151                 fi
152         '
153
154         test_expect_success "grep $L (t-1)" '
155                 echo "${HC}t/t:1:test" >expected &&
156                 git grep -n -e test $H >actual &&
157                 test_cmp expected actual
158         '
159
160         test_expect_success "grep $L (t-2)" '
161                 echo "${HC}t:1:test" >expected &&
162                 (
163                         cd t &&
164                         git grep -n -e test $H
165                 ) >actual &&
166                 test_cmp expected actual
167         '
168
169         test_expect_success "grep $L (t-3)" '
170                 echo "${HC}t/t:1:test" >expected &&
171                 (
172                         cd t &&
173                         git grep --full-name -n -e test $H
174                 ) >actual &&
175                 test_cmp expected actual
176         '
177
178         test_expect_success "grep -c $L (no /dev/null)" '
179                 ! git grep -c test $H | grep /dev/null
180         '
181
182         test_expect_success "grep --max-depth -1 $L" '
183                 {
184                         echo ${HC}t/a/v:1:vvv
185                         echo ${HC}t/v:1:vvv
186                         echo ${HC}v:1:vvv
187                 } >expected &&
188                 git grep --max-depth -1 -n -e vvv $H >actual &&
189                 test_cmp expected actual
190         '
191
192         test_expect_success "grep --max-depth 0 $L" '
193                 {
194                         echo ${HC}v:1:vvv
195                 } >expected &&
196                 git grep --max-depth 0 -n -e vvv $H >actual &&
197                 test_cmp expected actual
198         '
199
200         test_expect_success "grep --max-depth 0 -- '*' $L" '
201                 {
202                         echo ${HC}t/a/v:1:vvv
203                         echo ${HC}t/v:1:vvv
204                         echo ${HC}v:1:vvv
205                 } >expected &&
206                 git grep --max-depth 0 -n -e vvv $H -- "*" >actual &&
207                 test_cmp expected actual
208         '
209
210         test_expect_success "grep --max-depth 1 $L" '
211                 {
212                         echo ${HC}t/v:1:vvv
213                         echo ${HC}v:1:vvv
214                 } >expected &&
215                 git grep --max-depth 1 -n -e vvv $H >actual &&
216                 test_cmp expected actual
217         '
218
219         test_expect_success "grep --max-depth 0 -- t $L" '
220                 {
221                         echo ${HC}t/v:1:vvv
222                 } >expected &&
223                 git grep --max-depth 0 -n -e vvv $H -- t >actual &&
224                 test_cmp expected actual
225         '
226
227         test_expect_success "grep --max-depth 0 -- . t $L" '
228                 {
229                         echo ${HC}t/v:1:vvv
230                         echo ${HC}v:1:vvv
231                 } >expected &&
232                 git grep --max-depth 0 -n -e vvv $H -- . t >actual &&
233                 test_cmp expected actual
234         '
235
236         test_expect_success "grep --max-depth 0 -- t . $L" '
237                 {
238                         echo ${HC}t/v:1:vvv
239                         echo ${HC}v:1:vvv
240                 } >expected &&
241                 git grep --max-depth 0 -n -e vvv $H -- t . >actual &&
242                 test_cmp expected actual
243         '
244         test_expect_success "grep $L with grep.extendedRegexp=false" '
245                 echo "${HC}ab:a+bc" >expected &&
246                 git -c grep.extendedRegexp=false grep "a+b*c" $H ab >actual &&
247                 test_cmp expected actual
248         '
249
250         test_expect_success "grep $L with grep.extendedRegexp=true" '
251                 echo "${HC}ab:abc" >expected &&
252                 git -c grep.extendedRegexp=true grep "a+b*c" $H ab >actual &&
253                 test_cmp expected actual
254         '
255
256         test_expect_success "grep $L with grep.patterntype=basic" '
257                 echo "${HC}ab:a+bc" >expected &&
258                 git -c grep.patterntype=basic grep "a+b*c" $H ab >actual &&
259                 test_cmp expected actual
260         '
261
262         test_expect_success "grep $L with grep.patterntype=extended" '
263                 echo "${HC}ab:abc" >expected &&
264                 git -c grep.patterntype=extended grep "a+b*c" $H ab >actual &&
265                 test_cmp expected actual
266         '
267
268         test_expect_success "grep $L with grep.patterntype=fixed" '
269                 echo "${HC}ab:a+b*c" >expected &&
270                 git -c grep.patterntype=fixed grep "a+b*c" $H ab >actual &&
271                 test_cmp expected actual
272         '
273
274         test_expect_success LIBPCRE "grep $L with grep.patterntype=perl" '
275                 echo "${HC}ab:a+b*c" >expected &&
276                 git -c grep.patterntype=perl grep "a\x{2b}b\x{2a}c" $H ab >actual &&
277                 test_cmp expected actual
278         '
279
280         test_expect_success "grep $L with grep.patternType=default and grep.extendedRegexp=true" '
281                 echo "${HC}ab:abc" >expected &&
282                 git \
283                         -c grep.patternType=default \
284                         -c grep.extendedRegexp=true \
285                         grep "a+b*c" $H ab >actual &&
286                 test_cmp expected actual
287         '
288
289         test_expect_success "grep $L with grep.extendedRegexp=true and grep.patternType=default" '
290                 echo "${HC}ab:abc" >expected &&
291                 git \
292                         -c grep.extendedRegexp=true \
293                         -c grep.patternType=default \
294                         grep "a+b*c" $H ab >actual &&
295                 test_cmp expected actual
296         '
297
298         test_expect_success "grep $L with grep.patternType=extended and grep.extendedRegexp=false" '
299                 echo "${HC}ab:abc" >expected &&
300                 git \
301                         -c grep.patternType=extended \
302                         -c grep.extendedRegexp=false \
303                         grep "a+b*c" $H ab >actual &&
304                 test_cmp expected actual
305         '
306
307         test_expect_success "grep $L with grep.patternType=basic and grep.extendedRegexp=true" '
308                 echo "${HC}ab:a+bc" >expected &&
309                 git \
310                         -c grep.patternType=basic \
311                         -c grep.extendedRegexp=true \
312                         grep "a+b*c" $H ab >actual &&
313                 test_cmp expected actual
314         '
315
316         test_expect_success "grep $L with grep.extendedRegexp=false and grep.patternType=extended" '
317                 echo "${HC}ab:abc" >expected &&
318                 git \
319                         -c grep.extendedRegexp=false \
320                         -c grep.patternType=extended \
321                         grep "a+b*c" $H ab >actual &&
322                 test_cmp expected actual
323         '
324
325         test_expect_success "grep $L with grep.extendedRegexp=true and grep.patternType=basic" '
326                 echo "${HC}ab:a+bc" >expected &&
327                 git \
328                         -c grep.extendedRegexp=true \
329                         -c grep.patternType=basic \
330                         grep "a+b*c" $H ab >actual &&
331                 test_cmp expected actual
332         '
333
334         test_expect_success "grep --count $L" '
335                 echo ${HC}ab:3 >expected &&
336                 git grep --count -e b $H -- ab >actual &&
337                 test_cmp expected actual
338         '
339
340         test_expect_success "grep --count -h $L" '
341                 echo 3 >expected &&
342                 git grep --count -h -e b $H -- ab >actual &&
343                 test_cmp expected actual
344         '
345 done
346
347 cat >expected <<EOF
348 file
349 EOF
350 test_expect_success 'grep -l -C' '
351         git grep -l -C1 foo >actual &&
352         test_cmp expected actual
353 '
354
355 cat >expected <<EOF
356 file:5
357 EOF
358 test_expect_success 'grep -c -C' '
359         git grep -c -C1 foo >actual &&
360         test_cmp expected actual
361 '
362
363 test_expect_success 'grep -L -C' '
364         git ls-files >expected &&
365         git grep -L -C1 nonexistent_string >actual &&
366         test_cmp expected actual
367 '
368
369 cat >expected <<EOF
370 file:foo mmap bar_mmap
371 EOF
372
373 test_expect_success 'grep -e A --and -e B' '
374         git grep -e "foo mmap" --and -e bar_mmap >actual &&
375         test_cmp expected actual
376 '
377
378 cat >expected <<EOF
379 file:foo_mmap bar mmap
380 file:foo_mmap bar mmap baz
381 EOF
382
383
384 test_expect_success 'grep ( -e A --or -e B ) --and -e B' '
385         git grep \( -e foo_ --or -e baz \) \
386                 --and -e " mmap" >actual &&
387         test_cmp expected actual
388 '
389
390 cat >expected <<EOF
391 file:foo mmap bar
392 EOF
393
394 test_expect_success 'grep -e A --and --not -e B' '
395         git grep -e "foo mmap" --and --not -e bar_mmap >actual &&
396         test_cmp expected actual
397 '
398
399 test_expect_success 'grep should ignore GREP_OPTIONS' '
400         GREP_OPTIONS=-v git grep " mmap bar\$" >actual &&
401         test_cmp expected actual
402 '
403
404 test_expect_success 'grep -f, non-existent file' '
405         test_must_fail git grep -f patterns
406 '
407
408 cat >expected <<EOF
409 file:foo mmap bar
410 file:foo_mmap bar
411 file:foo_mmap bar mmap
412 file:foo mmap bar_mmap
413 file:foo_mmap bar mmap baz
414 EOF
415
416 cat >pattern <<EOF
417 mmap
418 EOF
419
420 test_expect_success 'grep -f, one pattern' '
421         git grep -f pattern >actual &&
422         test_cmp expected actual
423 '
424
425 cat >expected <<EOF
426 file:foo mmap bar
427 file:foo_mmap bar
428 file:foo_mmap bar mmap
429 file:foo mmap bar_mmap
430 file:foo_mmap bar mmap baz
431 t/a/v:vvv
432 t/v:vvv
433 v:vvv
434 EOF
435
436 cat >patterns <<EOF
437 mmap
438 vvv
439 EOF
440
441 test_expect_success 'grep -f, multiple patterns' '
442         git grep -f patterns >actual &&
443         test_cmp expected actual
444 '
445
446 test_expect_success 'grep, multiple patterns' '
447         git grep "$(cat patterns)" >actual &&
448         test_cmp expected actual
449 '
450
451 cat >expected <<EOF
452 file:foo mmap bar
453 file:foo_mmap bar
454 file:foo_mmap bar mmap
455 file:foo mmap bar_mmap
456 file:foo_mmap bar mmap baz
457 t/a/v:vvv
458 t/v:vvv
459 v:vvv
460 EOF
461
462 cat >patterns <<EOF
463
464 mmap
465
466 vvv
467
468 EOF
469
470 test_expect_success 'grep -f, ignore empty lines' '
471         git grep -f patterns >actual &&
472         test_cmp expected actual
473 '
474
475 test_expect_success 'grep -f, ignore empty lines, read patterns from stdin' '
476         git grep -f - <patterns >actual &&
477         test_cmp expected actual
478 '
479
480 cat >expected <<EOF
481 y:y yy
482 --
483 z:zzz
484 EOF
485
486 test_expect_success 'grep -q, silently report matches' '
487         >empty &&
488         git grep -q mmap >actual &&
489         test_cmp empty actual &&
490         test_must_fail git grep -q qfwfq >actual &&
491         test_cmp empty actual
492 '
493
494 test_expect_success 'grep -C1 hunk mark between files' '
495         git grep -C1 "^[yz]" >actual &&
496         test_cmp expected actual
497 '
498
499 test_expect_success 'log grep setup' '
500         echo a >>file &&
501         test_tick &&
502         GIT_AUTHOR_NAME="With * Asterisk" \
503         GIT_AUTHOR_EMAIL="xyzzy@frotz.com" \
504         git commit -a -m "second" &&
505
506         echo a >>file &&
507         test_tick &&
508         git commit -a -m "third" &&
509
510         echo a >>file &&
511         test_tick &&
512         GIT_AUTHOR_NAME="Night Fall" \
513         GIT_AUTHOR_EMAIL="nitfol@frobozz.com" \
514         git commit -a -m "fourth"
515 '
516
517 test_expect_success 'log grep (1)' '
518         git log --author=author --pretty=tformat:%s >actual &&
519         {
520                 echo third && echo initial
521         } >expect &&
522         test_cmp expect actual
523 '
524
525 test_expect_success 'log grep (2)' '
526         git log --author=" * " -F --pretty=tformat:%s >actual &&
527         {
528                 echo second
529         } >expect &&
530         test_cmp expect actual
531 '
532
533 test_expect_success 'log grep (3)' '
534         git log --author="^A U" --pretty=tformat:%s >actual &&
535         {
536                 echo third && echo initial
537         } >expect &&
538         test_cmp expect actual
539 '
540
541 test_expect_success 'log grep (4)' '
542         git log --author="frotz\.com>$" --pretty=tformat:%s >actual &&
543         {
544                 echo second
545         } >expect &&
546         test_cmp expect actual
547 '
548
549 test_expect_success 'log grep (5)' '
550         git log --author=Thor -F --pretty=tformat:%s >actual &&
551         {
552                 echo third && echo initial
553         } >expect &&
554         test_cmp expect actual
555 '
556
557 test_expect_success 'log grep (6)' '
558         git log --author=-0700  --pretty=tformat:%s >actual &&
559         >expect &&
560         test_cmp expect actual
561 '
562
563 test_expect_success 'log grep (7)' '
564         git log -g --grep-reflog="commit: third" --pretty=tformat:%s >actual &&
565         echo third >expect &&
566         test_cmp expect actual
567 '
568
569 test_expect_success 'log grep (8)' '
570         git log -g --grep-reflog="commit: third" --grep-reflog="commit: second" --pretty=tformat:%s >actual &&
571         {
572                 echo third && echo second
573         } >expect &&
574         test_cmp expect actual
575 '
576
577 test_expect_success 'log grep (9)' '
578         git log -g --grep-reflog="commit: third" --author="Thor" --pretty=tformat:%s >actual &&
579         echo third >expect &&
580         test_cmp expect actual
581 '
582
583 test_expect_success 'log grep (9)' '
584         git log -g --grep-reflog="commit: third" --author="non-existent" --pretty=tformat:%s >actual &&
585         : >expect &&
586         test_cmp expect actual
587 '
588
589 test_expect_success 'log --grep-reflog can only be used under -g' '
590         test_must_fail git log --grep-reflog="commit: third"
591 '
592
593 test_expect_success 'log with multiple --grep uses union' '
594         git log --grep=i --grep=r --format=%s >actual &&
595         {
596                 echo fourth && echo third && echo initial
597         } >expect &&
598         test_cmp expect actual
599 '
600
601 test_expect_success 'log --all-match with multiple --grep uses intersection' '
602         git log --all-match --grep=i --grep=r --format=%s >actual &&
603         {
604                 echo third
605         } >expect &&
606         test_cmp expect actual
607 '
608
609 test_expect_success 'log with multiple --author uses union' '
610         git log --author="Thor" --author="Aster" --format=%s >actual &&
611         {
612             echo third && echo second && echo initial
613         } >expect &&
614         test_cmp expect actual
615 '
616
617 test_expect_success 'log --all-match with multiple --author still uses union' '
618         git log --all-match --author="Thor" --author="Aster" --format=%s >actual &&
619         {
620             echo third && echo second && echo initial
621         } >expect &&
622         test_cmp expect actual
623 '
624
625 test_expect_success 'log --grep --author uses intersection' '
626         # grep matches only third and fourth
627         # author matches only initial and third
628         git log --author="A U Thor" --grep=r --format=%s >actual &&
629         {
630                 echo third
631         } >expect &&
632         test_cmp expect actual
633 '
634
635 test_expect_success 'log --grep --grep --author takes union of greps and intersects with author' '
636         # grep matches initial and second but not third
637         # author matches only initial and third
638         git log --author="A U Thor" --grep=s --grep=l --format=%s >actual &&
639         {
640                 echo initial
641         } >expect &&
642         test_cmp expect actual
643 '
644
645 test_expect_success 'log ---all-match -grep --author --author still takes union of authors and intersects with grep' '
646         # grep matches only initial and third
647         # author matches all but second
648         git log --all-match --author="Thor" --author="Night" --grep=i --format=%s >actual &&
649         {
650             echo third && echo initial
651         } >expect &&
652         test_cmp expect actual
653 '
654
655 test_expect_success 'log --grep --author --author takes union of authors and intersects with grep' '
656         # grep matches only initial and third
657         # author matches all but second
658         git log --author="Thor" --author="Night" --grep=i --format=%s >actual &&
659         {
660             echo third && echo initial
661         } >expect &&
662         test_cmp expect actual
663 '
664
665 test_expect_success 'log --all-match --grep --grep --author takes intersection' '
666         # grep matches only third
667         # author matches only initial and third
668         git log --all-match --author="A U Thor" --grep=i --grep=r --format=%s >actual &&
669         {
670                 echo third
671         } >expect &&
672         test_cmp expect actual
673 '
674
675 test_expect_success 'log --author does not search in timestamp' '
676         : >expect &&
677         git log --author="$GIT_AUTHOR_DATE" >actual &&
678         test_cmp expect actual
679 '
680
681 test_expect_success 'log --committer does not search in timestamp' '
682         : >expect &&
683         git log --committer="$GIT_COMMITTER_DATE" >actual &&
684         test_cmp expect actual
685 '
686
687 test_expect_success 'grep with CE_VALID file' '
688         git update-index --assume-unchanged t/t &&
689         rm t/t &&
690         test "$(git grep test)" = "t/t:test" &&
691         git update-index --no-assume-unchanged t/t &&
692         git checkout t/t
693 '
694
695 cat >expected <<EOF
696 hello.c=#include <stdio.h>
697 hello.c:        return 0;
698 EOF
699
700 test_expect_success 'grep -p with userdiff' '
701         git config diff.custom.funcname "^#" &&
702         echo "hello.c diff=custom" >.gitattributes &&
703         git grep -p return >actual &&
704         test_cmp expected actual
705 '
706
707 cat >expected <<EOF
708 hello.c=int main(int argc, const char **argv)
709 hello.c:        return 0;
710 EOF
711
712 test_expect_success 'grep -p' '
713         rm -f .gitattributes &&
714         git grep -p return >actual &&
715         test_cmp expected actual
716 '
717
718 cat >expected <<EOF
719 hello.c-#include <stdio.h>
720 hello.c-
721 hello.c=int main(int argc, const char **argv)
722 hello.c-{
723 hello.c-        printf("Hello world.\n");
724 hello.c:        return 0;
725 EOF
726
727 test_expect_success 'grep -p -B5' '
728         git grep -p -B5 return >actual &&
729         test_cmp expected actual
730 '
731
732 cat >expected <<EOF
733 hello.c=int main(int argc, const char **argv)
734 hello.c-{
735 hello.c-        printf("Hello world.\n");
736 hello.c:        return 0;
737 hello.c-        /* char ?? */
738 hello.c-}
739 EOF
740
741 test_expect_success 'grep -W' '
742         git grep -W return >actual &&
743         test_cmp expected actual
744 '
745
746 cat >expected <<EOF
747 hello.c-#include <assert.h>
748 hello.c:#include <stdio.h>
749 EOF
750
751 test_expect_success 'grep -W shows no trailing empty lines' '
752         git grep -W stdio >actual &&
753         test_cmp expected actual
754 '
755
756 cat >expected <<EOF
757 hello.c=        printf("Hello world.\n");
758 hello.c:        return 0;
759 hello.c-        /* char ?? */
760 EOF
761
762 test_expect_success 'grep -W with userdiff' '
763         test_when_finished "rm -f .gitattributes" &&
764         git config diff.custom.xfuncname "(printf.*|})$" &&
765         echo "hello.c diff=custom" >.gitattributes &&
766         git grep -W return >actual &&
767         test_cmp expected actual
768 '
769
770 test_expect_success 'grep from a subdirectory to search wider area (1)' '
771         mkdir -p s &&
772         (
773                 cd s && git grep "x x x" ..
774         )
775 '
776
777 test_expect_success 'grep from a subdirectory to search wider area (2)' '
778         mkdir -p s &&
779         (
780                 cd s || exit 1
781                 ( git grep xxyyzz .. >out ; echo $? >status )
782                 ! test -s out &&
783                 test 1 = $(cat status)
784         )
785 '
786
787 cat >expected <<EOF
788 hello.c:int main(int argc, const char **argv)
789 EOF
790
791 test_expect_success 'grep -Fi' '
792         git grep -Fi "CHAR *" >actual &&
793         test_cmp expected actual
794 '
795
796 test_expect_success 'outside of git repository' '
797         rm -fr non &&
798         mkdir -p non/git/sub &&
799         echo hello >non/git/file1 &&
800         echo world >non/git/sub/file2 &&
801         {
802                 echo file1:hello &&
803                 echo sub/file2:world
804         } >non/expect.full &&
805         echo file2:world >non/expect.sub &&
806         (
807                 GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
808                 export GIT_CEILING_DIRECTORIES &&
809                 cd non/git &&
810                 test_must_fail git grep o &&
811                 git grep --no-index o >../actual.full &&
812                 test_cmp ../expect.full ../actual.full &&
813                 cd sub &&
814                 test_must_fail git grep o &&
815                 git grep --no-index o >../../actual.sub &&
816                 test_cmp ../../expect.sub ../../actual.sub
817         ) &&
818
819         echo ".*o*" >non/git/.gitignore &&
820         (
821                 GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
822                 export GIT_CEILING_DIRECTORIES &&
823                 cd non/git &&
824                 test_must_fail git grep o &&
825                 git grep --no-index --exclude-standard o >../actual.full &&
826                 test_cmp ../expect.full ../actual.full &&
827
828                 {
829                         echo ".gitignore:.*o*" &&
830                         cat ../expect.full
831                 } >../expect.with.ignored &&
832                 git grep --no-index --no-exclude o >../actual.full &&
833                 test_cmp ../expect.with.ignored ../actual.full
834         )
835 '
836
837 test_expect_success 'outside of git repository with fallbackToNoIndex' '
838         rm -fr non &&
839         mkdir -p non/git/sub &&
840         echo hello >non/git/file1 &&
841         echo world >non/git/sub/file2 &&
842         cat <<-\EOF >non/expect.full &&
843         file1:hello
844         sub/file2:world
845         EOF
846         echo file2:world >non/expect.sub &&
847         (
848                 GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
849                 export GIT_CEILING_DIRECTORIES &&
850                 cd non/git &&
851                 test_must_fail git -c grep.fallbackToNoIndex=false grep o &&
852                 git -c grep.fallbackToNoIndex=true grep o >../actual.full &&
853                 test_cmp ../expect.full ../actual.full &&
854                 cd sub &&
855                 test_must_fail git -c grep.fallbackToNoIndex=false grep o &&
856                 git -c grep.fallbackToNoIndex=true grep o >../../actual.sub &&
857                 test_cmp ../../expect.sub ../../actual.sub
858         ) &&
859
860         echo ".*o*" >non/git/.gitignore &&
861         (
862                 GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
863                 export GIT_CEILING_DIRECTORIES &&
864                 cd non/git &&
865                 test_must_fail git -c grep.fallbackToNoIndex=false grep o &&
866                 git -c grep.fallbackToNoIndex=true grep --exclude-standard o >../actual.full &&
867                 test_cmp ../expect.full ../actual.full &&
868
869                 {
870                         echo ".gitignore:.*o*" &&
871                         cat ../expect.full
872                 } >../expect.with.ignored &&
873                 git -c grep.fallbackToNoIndex grep --no-exclude o >../actual.full &&
874                 test_cmp ../expect.with.ignored ../actual.full
875         )
876 '
877
878 test_expect_success 'inside git repository but with --no-index' '
879         rm -fr is &&
880         mkdir -p is/git/sub &&
881         echo hello >is/git/file1 &&
882         echo world >is/git/sub/file2 &&
883         echo ".*o*" >is/git/.gitignore &&
884         {
885                 echo file1:hello &&
886                 echo sub/file2:world
887         } >is/expect.unignored &&
888         {
889                 echo ".gitignore:.*o*" &&
890                 cat is/expect.unignored
891         } >is/expect.full &&
892         : >is/expect.empty &&
893         echo file2:world >is/expect.sub &&
894         (
895                 cd is/git &&
896                 git init &&
897                 test_must_fail git grep o >../actual.full &&
898                 test_cmp ../expect.empty ../actual.full &&
899
900                 git grep --untracked o >../actual.unignored &&
901                 test_cmp ../expect.unignored ../actual.unignored &&
902
903                 git grep --no-index o >../actual.full &&
904                 test_cmp ../expect.full ../actual.full &&
905
906                 git grep --no-index --exclude-standard o >../actual.unignored &&
907                 test_cmp ../expect.unignored ../actual.unignored &&
908
909                 cd sub &&
910                 test_must_fail git grep o >../../actual.sub &&
911                 test_cmp ../../expect.empty ../../actual.sub &&
912
913                 git grep --no-index o >../../actual.sub &&
914                 test_cmp ../../expect.sub ../../actual.sub &&
915
916                 git grep --untracked o >../../actual.sub &&
917                 test_cmp ../../expect.sub ../../actual.sub
918         )
919 '
920
921 test_expect_success 'grep --no-index descends into repos, but not .git' '
922         rm -fr non &&
923         mkdir -p non/git &&
924         (
925                 GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
926                 export GIT_CEILING_DIRECTORIES &&
927                 cd non/git &&
928
929                 echo magic >file &&
930                 git init repo &&
931                 (
932                         cd repo &&
933                         echo magic >file &&
934                         git add file &&
935                         git commit -m foo &&
936                         echo magic >.git/file
937                 ) &&
938
939                 cat >expect <<-\EOF &&
940                 file
941                 repo/file
942                 EOF
943                 git grep -l --no-index magic >actual &&
944                 test_cmp expect actual
945         )
946 '
947
948 test_expect_success 'setup double-dash tests' '
949 cat >double-dash <<EOF &&
950 --
951 ->
952 other
953 EOF
954 git add double-dash
955 '
956
957 cat >expected <<EOF
958 double-dash:->
959 EOF
960 test_expect_success 'grep -- pattern' '
961         git grep -- "->" >actual &&
962         test_cmp expected actual
963 '
964 test_expect_success 'grep -- pattern -- pathspec' '
965         git grep -- "->" -- double-dash >actual &&
966         test_cmp expected actual
967 '
968 test_expect_success 'grep -e pattern -- path' '
969         git grep -e "->" -- double-dash >actual &&
970         test_cmp expected actual
971 '
972
973 cat >expected <<EOF
974 double-dash:--
975 EOF
976 test_expect_success 'grep -e -- -- path' '
977         git grep -e -- -- double-dash >actual &&
978         test_cmp expected actual
979 '
980
981 cat >expected <<EOF
982 hello.c:int main(int argc, const char **argv)
983 hello.c:        printf("Hello world.\n");
984 EOF
985
986 test_expect_success LIBPCRE 'grep --perl-regexp pattern' '
987         git grep --perl-regexp "\p{Ps}.*?\p{Pe}" hello.c >actual &&
988         test_cmp expected actual
989 '
990
991 test_expect_success LIBPCRE 'grep -P pattern' '
992         git grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual &&
993         test_cmp expected actual
994 '
995
996 test_expect_success 'grep pattern with grep.extendedRegexp=true' '
997         >empty &&
998         test_must_fail git -c grep.extendedregexp=true \
999                 grep "\p{Ps}.*?\p{Pe}" hello.c >actual &&
1000         test_cmp empty actual
1001 '
1002
1003 test_expect_success LIBPCRE 'grep -P pattern with grep.extendedRegexp=true' '
1004         git -c grep.extendedregexp=true \
1005                 grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual &&
1006         test_cmp expected actual
1007 '
1008
1009 test_expect_success LIBPCRE 'grep -P -v pattern' '
1010         {
1011                 echo "ab:a+b*c"
1012                 echo "ab:a+bc"
1013         } >expected &&
1014         git grep -P -v "abc" ab >actual &&
1015         test_cmp expected actual
1016 '
1017
1018 test_expect_success LIBPCRE 'grep -P -i pattern' '
1019         cat >expected <<-EOF &&
1020         hello.c:        printf("Hello world.\n");
1021         EOF
1022         git grep -P -i "PRINTF\([^\d]+\)" hello.c >actual &&
1023         test_cmp expected actual
1024 '
1025
1026 test_expect_success LIBPCRE 'grep -P -w pattern' '
1027         {
1028                 echo "hello_world:Hello world"
1029                 echo "hello_world:HeLLo world"
1030         } >expected &&
1031         git grep -P -w "He((?i)ll)o" hello_world >actual &&
1032         test_cmp expected actual
1033 '
1034
1035 test_expect_success 'grep -G invalidpattern properly dies ' '
1036         test_must_fail git grep -G "a["
1037 '
1038
1039 test_expect_success 'grep invalidpattern properly dies with grep.patternType=basic' '
1040         test_must_fail git -c grep.patterntype=basic grep "a["
1041 '
1042
1043 test_expect_success 'grep -E invalidpattern properly dies ' '
1044         test_must_fail git grep -E "a["
1045 '
1046
1047 test_expect_success 'grep invalidpattern properly dies with grep.patternType=extended' '
1048         test_must_fail git -c grep.patterntype=extended grep "a["
1049 '
1050
1051 test_expect_success LIBPCRE 'grep -P invalidpattern properly dies ' '
1052         test_must_fail git grep -P "a["
1053 '
1054
1055 test_expect_success LIBPCRE 'grep invalidpattern properly dies with grep.patternType=perl' '
1056         test_must_fail git -c grep.patterntype=perl grep "a["
1057 '
1058
1059 test_expect_success 'grep -G -E -F pattern' '
1060         echo "ab:a+b*c" >expected &&
1061         git grep -G -E -F "a+b*c" ab >actual &&
1062         test_cmp expected actual
1063 '
1064
1065 test_expect_success 'grep pattern with grep.patternType=basic, =extended, =fixed' '
1066         echo "ab:a+b*c" >expected &&
1067         git \
1068                 -c grep.patterntype=basic \
1069                 -c grep.patterntype=extended \
1070                 -c grep.patterntype=fixed \
1071                 grep "a+b*c" ab >actual &&
1072         test_cmp expected actual
1073 '
1074
1075 test_expect_success 'grep -E -F -G pattern' '
1076         echo "ab:a+bc" >expected &&
1077         git grep -E -F -G "a+b*c" ab >actual &&
1078         test_cmp expected actual
1079 '
1080
1081 test_expect_success 'grep pattern with grep.patternType=extended, =fixed, =basic' '
1082         echo "ab:a+bc" >expected &&
1083         git \
1084                 -c grep.patterntype=extended \
1085                 -c grep.patterntype=fixed \
1086                 -c grep.patterntype=basic \
1087                 grep "a+b*c" ab >actual &&
1088         test_cmp expected actual
1089 '
1090
1091 test_expect_success 'grep -F -G -E pattern' '
1092         echo "ab:abc" >expected &&
1093         git grep -F -G -E "a+b*c" ab >actual &&
1094         test_cmp expected actual
1095 '
1096
1097 test_expect_success 'grep pattern with grep.patternType=fixed, =basic, =extended' '
1098         echo "ab:abc" >expected &&
1099         git \
1100                 -c grep.patterntype=fixed \
1101                 -c grep.patterntype=basic \
1102                 -c grep.patterntype=extended \
1103                 grep "a+b*c" ab >actual &&
1104         test_cmp expected actual
1105 '
1106
1107 test_expect_success 'grep -G -F -P -E pattern' '
1108         >empty &&
1109         test_must_fail git grep -G -F -P -E "a\x{2b}b\x{2a}c" ab >actual &&
1110         test_cmp empty actual
1111 '
1112
1113 test_expect_success 'grep pattern with grep.patternType=fixed, =basic, =perl, =extended' '
1114         >empty &&
1115         test_must_fail git \
1116                 -c grep.patterntype=fixed \
1117                 -c grep.patterntype=basic \
1118                 -c grep.patterntype=perl \
1119                 -c grep.patterntype=extended \
1120                 grep "a\x{2b}b\x{2a}c" ab >actual &&
1121         test_cmp empty actual
1122 '
1123
1124 test_expect_success LIBPCRE 'grep -G -F -E -P pattern' '
1125         echo "ab:a+b*c" >expected &&
1126         git grep -G -F -E -P "a\x{2b}b\x{2a}c" ab >actual &&
1127         test_cmp expected actual
1128 '
1129
1130 test_expect_success LIBPCRE 'grep pattern with grep.patternType=fixed, =basic, =extended, =perl' '
1131         echo "ab:a+b*c" >expected &&
1132         git \
1133                 -c grep.patterntype=fixed \
1134                 -c grep.patterntype=basic \
1135                 -c grep.patterntype=extended \
1136                 -c grep.patterntype=perl \
1137                 grep "a\x{2b}b\x{2a}c" ab >actual &&
1138         test_cmp expected actual
1139 '
1140
1141 test_expect_success LIBPCRE 'grep -P pattern with grep.patternType=fixed' '
1142         echo "ab:a+b*c" >expected &&
1143         git \
1144                 -c grep.patterntype=fixed \
1145                 grep -P "a\x{2b}b\x{2a}c" ab >actual &&
1146         test_cmp expected actual
1147 '
1148
1149 test_expect_success 'grep -F pattern with grep.patternType=basic' '
1150         echo "ab:a+b*c" >expected &&
1151         git \
1152                 -c grep.patterntype=basic \
1153                 grep -F "*c" ab >actual &&
1154         test_cmp expected actual
1155 '
1156
1157 test_expect_success 'grep -G pattern with grep.patternType=fixed' '
1158         {
1159                 echo "ab:a+b*c"
1160                 echo "ab:a+bc"
1161         } >expected &&
1162         git \
1163                 -c grep.patterntype=fixed \
1164                 grep -G "a+b" ab >actual &&
1165         test_cmp expected actual
1166 '
1167
1168 test_expect_success 'grep -E pattern with grep.patternType=fixed' '
1169         {
1170                 echo "ab:a+b*c"
1171                 echo "ab:a+bc"
1172                 echo "ab:abc"
1173         } >expected &&
1174         git \
1175                 -c grep.patterntype=fixed \
1176                 grep -E "a+" ab >actual &&
1177         test_cmp expected actual
1178 '
1179
1180 cat >expected <<EOF
1181 hello.c<RED>:<RESET>int main(int argc, const char **argv)
1182 hello.c<RED>-<RESET>{
1183 <RED>--<RESET>
1184 hello.c<RED>:<RESET>    /* char ?? */
1185 hello.c<RED>-<RESET>}
1186 <RED>--<RESET>
1187 hello_world<RED>:<RESET>Hello_world
1188 hello_world<RED>-<RESET>HeLLo_world
1189 EOF
1190
1191 test_expect_success 'grep --color, separator' '
1192         test_config color.grep.context          normal &&
1193         test_config color.grep.filename         normal &&
1194         test_config color.grep.function         normal &&
1195         test_config color.grep.linenumber       normal &&
1196         test_config color.grep.match            normal &&
1197         test_config color.grep.selected         normal &&
1198         test_config color.grep.separator        red &&
1199
1200         git grep --color=always -A1 -e char -e lo_w hello.c hello_world |
1201         test_decode_color >actual &&
1202         test_cmp expected actual
1203 '
1204
1205 cat >expected <<EOF
1206 hello.c:int main(int argc, const char **argv)
1207 hello.c:        /* char ?? */
1208
1209 hello_world:Hello_world
1210 EOF
1211
1212 test_expect_success 'grep --break' '
1213         git grep --break -e char -e lo_w hello.c hello_world >actual &&
1214         test_cmp expected actual
1215 '
1216
1217 cat >expected <<EOF
1218 hello.c:int main(int argc, const char **argv)
1219 hello.c-{
1220 --
1221 hello.c:        /* char ?? */
1222 hello.c-}
1223
1224 hello_world:Hello_world
1225 hello_world-HeLLo_world
1226 EOF
1227
1228 test_expect_success 'grep --break with context' '
1229         git grep --break -A1 -e char -e lo_w hello.c hello_world >actual &&
1230         test_cmp expected actual
1231 '
1232
1233 cat >expected <<EOF
1234 hello.c
1235 int main(int argc, const char **argv)
1236         /* char ?? */
1237 hello_world
1238 Hello_world
1239 EOF
1240
1241 test_expect_success 'grep --heading' '
1242         git grep --heading -e char -e lo_w hello.c hello_world >actual &&
1243         test_cmp expected actual
1244 '
1245
1246 cat >expected <<EOF
1247 <BOLD;GREEN>hello.c<RESET>
1248 4:int main(int argc, const <BLACK;BYELLOW>char<RESET> **argv)
1249 8:      /* <BLACK;BYELLOW>char<RESET> ?? */
1250
1251 <BOLD;GREEN>hello_world<RESET>
1252 3:Hel<BLACK;BYELLOW>lo_w<RESET>orld
1253 EOF
1254
1255 test_expect_success 'mimic ack-grep --group' '
1256         test_config color.grep.context          normal &&
1257         test_config color.grep.filename         "bold green" &&
1258         test_config color.grep.function         normal &&
1259         test_config color.grep.linenumber       normal &&
1260         test_config color.grep.match            "black yellow" &&
1261         test_config color.grep.selected         normal &&
1262         test_config color.grep.separator        normal &&
1263
1264         git grep --break --heading -n --color \
1265                 -e char -e lo_w hello.c hello_world |
1266         test_decode_color >actual &&
1267         test_cmp expected actual
1268 '
1269
1270 cat >expected <<EOF
1271 space: line with leading space1
1272 space: line with leading space2
1273 space: line with leading space3
1274 EOF
1275
1276 test_expect_success LIBPCRE 'grep -E "^ "' '
1277         git grep -E "^ " space >actual &&
1278         test_cmp expected actual
1279 '
1280
1281 test_expect_success LIBPCRE 'grep -P "^ "' '
1282         git grep -P "^ " space >actual &&
1283         test_cmp expected actual
1284 '
1285
1286 cat >expected <<EOF
1287 space-line without leading space1
1288 space: line <RED>with <RESET>leading space1
1289 space: line <RED>with <RESET>leading <RED>space2<RESET>
1290 space: line <RED>with <RESET>leading space3
1291 space:line without leading <RED>space2<RESET>
1292 EOF
1293
1294 test_expect_success 'grep --color -e A -e B with context' '
1295         test_config color.grep.context          normal &&
1296         test_config color.grep.filename         normal &&
1297         test_config color.grep.function         normal &&
1298         test_config color.grep.linenumber       normal &&
1299         test_config color.grep.matchContext     normal &&
1300         test_config color.grep.matchSelected    red &&
1301         test_config color.grep.selected         normal &&
1302         test_config color.grep.separator        normal &&
1303
1304         git grep --color=always -C2 -e "with " -e space2  space |
1305         test_decode_color >actual &&
1306         test_cmp expected actual
1307 '
1308
1309 cat >expected <<EOF
1310 space-line without leading space1
1311 space- line with leading space1
1312 space: line <RED>with <RESET>leading <RED>space2<RESET>
1313 space- line with leading space3
1314 space-line without leading space2
1315 EOF
1316
1317 test_expect_success 'grep --color -e A --and -e B with context' '
1318         test_config color.grep.context          normal &&
1319         test_config color.grep.filename         normal &&
1320         test_config color.grep.function         normal &&
1321         test_config color.grep.linenumber       normal &&
1322         test_config color.grep.matchContext     normal &&
1323         test_config color.grep.matchSelected    red &&
1324         test_config color.grep.selected         normal &&
1325         test_config color.grep.separator        normal &&
1326
1327         git grep --color=always -C2 -e "with " --and -e space2  space |
1328         test_decode_color >actual &&
1329         test_cmp expected actual
1330 '
1331
1332 cat >expected <<EOF
1333 space-line without leading space1
1334 space: line <RED>with <RESET>leading space1
1335 space- line with leading space2
1336 space: line <RED>with <RESET>leading space3
1337 space-line without leading space2
1338 EOF
1339
1340 test_expect_success 'grep --color -e A --and --not -e B with context' '
1341         test_config color.grep.context          normal &&
1342         test_config color.grep.filename         normal &&
1343         test_config color.grep.function         normal &&
1344         test_config color.grep.linenumber       normal &&
1345         test_config color.grep.matchContext     normal &&
1346         test_config color.grep.matchSelected    red &&
1347         test_config color.grep.selected         normal &&
1348         test_config color.grep.separator        normal &&
1349
1350         git grep --color=always -C2 -e "with " --and --not -e space2  space |
1351         test_decode_color >actual &&
1352         test_cmp expected actual
1353 '
1354
1355 cat >expected <<EOF
1356 hello.c-
1357 hello.c=int main(int argc, const char **argv)
1358 hello.c-{
1359 hello.c:        pr<RED>int<RESET>f("<RED>Hello<RESET> world.\n");
1360 hello.c-        return 0;
1361 hello.c-        /* char ?? */
1362 hello.c-}
1363 EOF
1364
1365 test_expect_success 'grep --color -e A --and -e B -p with context' '
1366         test_config color.grep.context          normal &&
1367         test_config color.grep.filename         normal &&
1368         test_config color.grep.function         normal &&
1369         test_config color.grep.linenumber       normal &&
1370         test_config color.grep.matchContext     normal &&
1371         test_config color.grep.matchSelected    red &&
1372         test_config color.grep.selected         normal &&
1373         test_config color.grep.separator        normal &&
1374
1375         git grep --color=always -p -C3 -e int --and -e Hello --no-index hello.c |
1376         test_decode_color >actual &&
1377         test_cmp expected actual
1378 '
1379
1380 test_expect_success 'grep can find things only in the work tree' '
1381         : >work-tree-only &&
1382         git add work-tree-only &&
1383         test_when_finished "git rm -f work-tree-only" &&
1384         echo "find in work tree" >work-tree-only &&
1385         git grep --quiet "find in work tree" &&
1386         test_must_fail git grep --quiet --cached "find in work tree" &&
1387         test_must_fail git grep --quiet "find in work tree" HEAD
1388 '
1389
1390 test_expect_success 'grep can find things only in the work tree (i-t-a)' '
1391         echo "intend to add this" >intend-to-add &&
1392         git add -N intend-to-add &&
1393         test_when_finished "git rm -f intend-to-add" &&
1394         git grep --quiet "intend to add this" &&
1395         test_must_fail git grep --quiet --cached "intend to add this" &&
1396         test_must_fail git grep --quiet "intend to add this" HEAD
1397 '
1398
1399 test_expect_success 'grep does not search work tree with assume unchanged' '
1400         echo "intend to add this" >intend-to-add &&
1401         git add -N intend-to-add &&
1402         git update-index --assume-unchanged intend-to-add &&
1403         test_when_finished "git rm -f intend-to-add" &&
1404         test_must_fail git grep --quiet "intend to add this" &&
1405         test_must_fail git grep --quiet --cached "intend to add this" &&
1406         test_must_fail git grep --quiet "intend to add this" HEAD
1407 '
1408
1409 test_expect_success 'grep can find things only in the index' '
1410         echo "only in the index" >cache-this &&
1411         git add cache-this &&
1412         rm cache-this &&
1413         test_when_finished "git rm --cached cache-this" &&
1414         test_must_fail git grep --quiet "only in the index" &&
1415         git grep --quiet --cached "only in the index" &&
1416         test_must_fail git grep --quiet "only in the index" HEAD
1417 '
1418
1419 test_expect_success 'grep does not report i-t-a with -L --cached' '
1420         echo "intend to add this" >intend-to-add &&
1421         git add -N intend-to-add &&
1422         test_when_finished "git rm -f intend-to-add" &&
1423         git ls-files | grep -v "^intend-to-add\$" >expected &&
1424         git grep -L --cached "nonexistent_string" >actual &&
1425         test_cmp expected actual
1426 '
1427
1428 test_expect_success 'grep does not report i-t-a and assume unchanged with -L' '
1429         echo "intend to add this" >intend-to-add-assume-unchanged &&
1430         git add -N intend-to-add-assume-unchanged &&
1431         test_when_finished "git rm -f intend-to-add-assume-unchanged" &&
1432         git update-index --assume-unchanged intend-to-add-assume-unchanged &&
1433         git ls-files | grep -v "^intend-to-add-assume-unchanged\$" >expected &&
1434         git grep -L "nonexistent_string" >actual &&
1435         test_cmp expected actual
1436 '
1437
1438 test_done