4
5
. ./test-lib.sh
6
7
-cat <<EOF >rot13.sh
7
+TEST_ROOT="$(pwd)"
8
+
9
+cat <<EOF >"$TEST_ROOT/rot13.sh"
10
#!$SHELL_PATH
11
tr \
12
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \
13
'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
14
EOF
13
-chmod +x rot13.sh
15
+chmod +x "$TEST_ROOT/rot13.sh"
16
+
17
+generate_random_characters () {
18
+ LEN=$1
19
+ NAME=$2
20
+ test-genrandom some-seed $LEN |
21
+ perl -pe "s/./chr((ord($&) % 26) + ord('a'))/sge" >"$TEST_ROOT/$NAME"
22
+}
23
+
24
+file_size () {
25
+ cat "$1" | wc -c | sed "s/^[ ]*//"
26
+}
27
+
28
+filter_git () {
29
+ rm -f rot13-filter.log &&
30
+ git "$@" 2>git-stderr.log &&
31
+ rm -f git-stderr.log
32
+}
33
+
34
+# Compare two files and ensure that `clean` and `smudge` respectively are
35
+# called at least once if specified in the `expect` file. The actual
36
+# invocation count is not relevant because their number can vary.
37
+# c.f. http://public-inbox.org/git/xmqqshv18i8i.fsf@gitster.mtv.corp.google.com/
38
+test_cmp_count () {
39
+ expect=$1
40
+ actual=$2
41
+ for FILE in "$expect" "$actual"
42
+ do
43
+ sort "$FILE" | uniq -c | sed "s/^[ ]*//" |
44
+ sed "s/^\([0-9]\) IN: clean/x IN: clean/" |
45
+ sed "s/^\([0-9]\) IN: smudge/x IN: smudge/" >"$FILE.tmp" &&
46
+ mv "$FILE.tmp" "$FILE"
47
+ done &&
48
+ test_cmp "$expect" "$actual"
49
+}
50
+
51
+# Compare two files but exclude all `clean` invocations because Git can
52
+# call `clean` zero or more times.
53
+# c.f. http://public-inbox.org/git/xmqqshv18i8i.fsf@gitster.mtv.corp.google.com/
54
+test_cmp_exclude_clean () {
55
+ expect=$1
56
+ actual=$2
57
+ for FILE in "$expect" "$actual"
58
+ do
59
+ grep -v "IN: clean" "$FILE" >"$FILE.tmp" &&
60
+ mv "$FILE.tmp" "$FILE"
61
+ done &&
62
+ test_cmp "$expect" "$actual"
63
+}
64
+
65
+# Check that the contents of two files are equal and that their rot13 version
66
+# is equal to the committed content.
67
+test_cmp_committed_rot13 () {
68
+ test_cmp "$1" "$2" &&
69
+ "$TEST_ROOT/rot13.sh" <"$1" >expected &&
70
+ git cat-file blob :"$2" >actual &&
71
+ test_cmp expected actual
72
+}
73
74
test_expect_success setup '
75
git config filter.rot13.smudge ./rot13.sh &&
90
cat test >test.i &&
91
git add test test.t test.i &&
92
rm -f test test.t test.i &&
34
- git checkout -- test test.t test.i
93
+ git checkout -- test test.t test.i &&
94
+
95
+ echo "content-test2" >test2.o &&
96
+ echo "content-test3 - filename with special characters" >"test3 '\''sq'\'',\$x.o"
97
'
98
99
script='s/^\$Id: \([0-9a-f]*\) \$/\1/p'
341
test_line_count = 0 count
342
'
343
344
+test_expect_success PERL 'required process filter should filter data' '
345
+ test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
346
+ test_config_global filter.protocol.required true &&
347
+ rm -rf repo &&
348
+ mkdir repo &&
349
+ (
350
+ cd repo &&
351
+ git init &&
352
+
353
+ echo "git-stderr.log" >.gitignore &&
354
+ echo "*.r filter=protocol" >.gitattributes &&
355
+ git add . &&
356
+ git commit . -m "test commit 1" &&
357
+ git branch empty-branch &&
358
+
359
+ cp "$TEST_ROOT/test.o" test.r &&
360
+ cp "$TEST_ROOT/test2.o" test2.r &&
361
+ mkdir testsubdir &&
362
+ cp "$TEST_ROOT/test3 '\''sq'\'',\$x.o" "testsubdir/test3 '\''sq'\'',\$x.r" &&
363
+ >test4-empty.r &&
364
+
365
+ S=$(file_size test.r) &&
366
+ S2=$(file_size test2.r) &&
367
+ S3=$(file_size "testsubdir/test3 '\''sq'\'',\$x.r") &&
368
+
369
+ filter_git add . &&
370
+ cat >expected.log <<-EOF &&
371
+ START
372
+ init handshake complete
373
+ IN: clean test.r $S [OK] -- OUT: $S . [OK]
374
+ IN: clean test2.r $S2 [OK] -- OUT: $S2 . [OK]
375
+ IN: clean test4-empty.r 0 [OK] -- OUT: 0 [OK]
376
+ IN: clean testsubdir/test3 '\''sq'\'',\$x.r $S3 [OK] -- OUT: $S3 . [OK]
377
+ STOP
378
+ EOF
379
+ test_cmp_count expected.log rot13-filter.log &&
380
+
381
+ filter_git commit . -m "test commit 2" &&
382
+ cat >expected.log <<-EOF &&
383
+ START
384
+ init handshake complete
385
+ IN: clean test.r $S [OK] -- OUT: $S . [OK]
386
+ IN: clean test2.r $S2 [OK] -- OUT: $S2 . [OK]
387
+ IN: clean test4-empty.r 0 [OK] -- OUT: 0 [OK]
388
+ IN: clean testsubdir/test3 '\''sq'\'',\$x.r $S3 [OK] -- OUT: $S3 . [OK]
389
+ IN: clean test.r $S [OK] -- OUT: $S . [OK]
390
+ IN: clean test2.r $S2 [OK] -- OUT: $S2 . [OK]
391
+ IN: clean test4-empty.r 0 [OK] -- OUT: 0 [OK]
392
+ IN: clean testsubdir/test3 '\''sq'\'',\$x.r $S3 [OK] -- OUT: $S3 . [OK]
393
+ STOP
394
+ EOF
395
+ test_cmp_count expected.log rot13-filter.log &&
396
+
397
+ rm -f test2.r "testsubdir/test3 '\''sq'\'',\$x.r" &&
398
+
399
+ filter_git checkout --quiet --no-progress . &&
400
+ cat >expected.log <<-EOF &&
401
+ START
402
+ init handshake complete
403
+ IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
404
+ IN: smudge testsubdir/test3 '\''sq'\'',\$x.r $S3 [OK] -- OUT: $S3 . [OK]
405
+ STOP
406
+ EOF
407
+ test_cmp_exclude_clean expected.log rot13-filter.log &&
408
+
409
+ filter_git checkout --quiet --no-progress empty-branch &&
410
+ cat >expected.log <<-EOF &&
411
+ START
412
+ init handshake complete
413
+ IN: clean test.r $S [OK] -- OUT: $S . [OK]
414
+ STOP
415
+ EOF
416
+ test_cmp_exclude_clean expected.log rot13-filter.log &&
417
+
418
+ filter_git checkout --quiet --no-progress master &&
419
+ cat >expected.log <<-EOF &&
420
+ START
421
+ init handshake complete
422
+ IN: smudge test.r $S [OK] -- OUT: $S . [OK]
423
+ IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
424
+ IN: smudge test4-empty.r 0 [OK] -- OUT: 0 [OK]
425
+ IN: smudge testsubdir/test3 '\''sq'\'',\$x.r $S3 [OK] -- OUT: $S3 . [OK]
426
+ STOP
427
+ EOF
428
+ test_cmp_exclude_clean expected.log rot13-filter.log &&
429
+
430
+ test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r &&
431
+ test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r &&
432
+ test_cmp_committed_rot13 "$TEST_ROOT/test3 '\''sq'\'',\$x.o" "testsubdir/test3 '\''sq'\'',\$x.r"
433
+ )
434
+'
435
+
436
+test_expect_success PERL 'required process filter takes precedence' '
437
+ test_config_global filter.protocol.clean false &&
438
+ test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean" &&
439
+ test_config_global filter.protocol.required true &&
440
+ rm -rf repo &&
441
+ mkdir repo &&
442
+ (
443
+ cd repo &&
444
+ git init &&
445
+
446
+ echo "*.r filter=protocol" >.gitattributes &&
447
+ cp "$TEST_ROOT/test.o" test.r &&
448
+ S=$(file_size test.r) &&
449
+
450
+ # Check that the process filter is invoked here
451
+ filter_git add . &&
452
+ cat >expected.log <<-EOF &&
453
+ START
454
+ init handshake complete
455
+ IN: clean test.r $S [OK] -- OUT: $S . [OK]
456
+ STOP
457
+ EOF
458
+ test_cmp_count expected.log rot13-filter.log
459
+ )
460
+'
461
+
462
+test_expect_success PERL 'required process filter should be used only for "clean" operation only' '
463
+ test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean" &&
464
+ rm -rf repo &&
465
+ mkdir repo &&
466
+ (
467
+ cd repo &&
468
+ git init &&
469
+
470
+ echo "*.r filter=protocol" >.gitattributes &&
471
+ cp "$TEST_ROOT/test.o" test.r &&
472
+ S=$(file_size test.r) &&
473
+
474
+ filter_git add . &&
475
+ cat >expected.log <<-EOF &&
476
+ START
477
+ init handshake complete
478
+ IN: clean test.r $S [OK] -- OUT: $S . [OK]
479
+ STOP
480
+ EOF
481
+ test_cmp_count expected.log rot13-filter.log &&
482
+
483
+ rm test.r &&
484
+
485
+ filter_git checkout --quiet --no-progress . &&
486
+ # If the filter would be used for "smudge", too, we would see
487
+ # "IN: smudge test.r 57 [OK] -- OUT: 57 . [OK]" here
488
+ cat >expected.log <<-EOF &&
489
+ START
490
+ init handshake complete
491
+ STOP
492
+ EOF
493
+ test_cmp_exclude_clean expected.log rot13-filter.log
494
+ )
495
+'
496
+
497
+test_expect_success PERL 'required process filter should process multiple packets' '
498
+ test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
499
+ test_config_global filter.protocol.required true &&
500
+
501
+ rm -rf repo &&
502
+ mkdir repo &&
503
+ (
504
+ cd repo &&
505
+ git init &&
506
+
507
+ # Generate data requiring 1, 2, 3 packets
508
+ S=65516 && # PKTLINE_DATA_MAXLEN -> Maximal size of a packet
509
+ generate_random_characters $(($S )) 1pkt_1__.file &&
510
+ generate_random_characters $(($S +1)) 2pkt_1+1.file &&
511
+ generate_random_characters $(($S*2-1)) 2pkt_2-1.file &&
512
+ generate_random_characters $(($S*2 )) 2pkt_2__.file &&
513
+ generate_random_characters $(($S*2+1)) 3pkt_2+1.file &&
514
+
515
+ for FILE in "$TEST_ROOT"/*.file
516
+ do
517
+ cp "$FILE" . &&
518
+ "$TEST_ROOT/rot13.sh" <"$FILE" >"$FILE.rot13"
519
+ done &&
520
+
521
+ echo "*.file filter=protocol" >.gitattributes &&
522
+ filter_git add *.file .gitattributes &&
523
+ cat >expected.log <<-EOF &&
524
+ START
525
+ init handshake complete
526
+ IN: clean 1pkt_1__.file $(($S )) [OK] -- OUT: $(($S )) . [OK]
527
+ IN: clean 2pkt_1+1.file $(($S +1)) [OK] -- OUT: $(($S +1)) .. [OK]
528
+ IN: clean 2pkt_2-1.file $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK]
529
+ IN: clean 2pkt_2__.file $(($S*2 )) [OK] -- OUT: $(($S*2 )) .. [OK]
530
+ IN: clean 3pkt_2+1.file $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK]
531
+ STOP
532
+ EOF
533
+ test_cmp_count expected.log rot13-filter.log &&
534
+
535
+ rm -f *.file &&
536
+
537
+ filter_git checkout --quiet --no-progress -- *.file &&
538
+ cat >expected.log <<-EOF &&
539
+ START
540
+ init handshake complete
541
+ IN: smudge 1pkt_1__.file $(($S )) [OK] -- OUT: $(($S )) . [OK]
542
+ IN: smudge 2pkt_1+1.file $(($S +1)) [OK] -- OUT: $(($S +1)) .. [OK]
543
+ IN: smudge 2pkt_2-1.file $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK]
544
+ IN: smudge 2pkt_2__.file $(($S*2 )) [OK] -- OUT: $(($S*2 )) .. [OK]
545
+ IN: smudge 3pkt_2+1.file $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK]
546
+ STOP
547
+ EOF
548
+ test_cmp_exclude_clean expected.log rot13-filter.log &&
549
+
550
+ for FILE in *.file
551
+ do
552
+ test_cmp_committed_rot13 "$TEST_ROOT/$FILE" $FILE
553
+ done
554
+ )
555
+'
556
+
557
+test_expect_success PERL 'required process filter with clean error should fail' '
558
+ test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
559
+ test_config_global filter.protocol.required true &&
560
+ rm -rf repo &&
561
+ mkdir repo &&
562
+ (
563
+ cd repo &&
564
+ git init &&
565
+
566
+ echo "*.r filter=protocol" >.gitattributes &&
567
+
568
+ cp "$TEST_ROOT/test.o" test.r &&
569
+ echo "this is going to fail" >clean-write-fail.r &&
570
+ echo "content-test3-subdir" >test3.r &&
571
+
572
+ test_must_fail git add .
573
+ )
574
+'
575
+
576
+test_expect_success PERL 'process filter should restart after unexpected write failure' '
577
+ test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
578
+ rm -rf repo &&
579
+ mkdir repo &&
580
+ (
581
+ cd repo &&
582
+ git init &&
583
+
584
+ echo "*.r filter=protocol" >.gitattributes &&
585
+
586
+ cp "$TEST_ROOT/test.o" test.r &&
587
+ cp "$TEST_ROOT/test2.o" test2.r &&
588
+ echo "this is going to fail" >smudge-write-fail.o &&
589
+ cp smudge-write-fail.o smudge-write-fail.r &&
590
+
591
+ S=$(file_size test.r) &&
592
+ S2=$(file_size test2.r) &&
593
+ SF=$(file_size smudge-write-fail.r) &&
594
+
595
+ git add . &&
596
+ rm -f *.r &&
597
+
598
+ rm -f rot13-filter.log &&
599
+ git checkout --quiet --no-progress . 2>git-stderr.log &&
600
+
601
+ grep "smudge write error at" git-stderr.log &&
602
+ grep "error: external filter" git-stderr.log &&
603
+
604
+ cat >expected.log <<-EOF &&
605
+ START
606
+ init handshake complete
607
+ IN: smudge smudge-write-fail.r $SF [OK] -- OUT: $SF [WRITE FAIL]
608
+ START
609
+ init handshake complete
610
+ IN: smudge test.r $S [OK] -- OUT: $S . [OK]
611
+ IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
612
+ STOP
613
+ EOF
614
+ test_cmp_exclude_clean expected.log rot13-filter.log &&
615
+
616
+ test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r &&
617
+ test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r &&
618
+
619
+ # Smudge failed
620
+ ! test_cmp smudge-write-fail.o smudge-write-fail.r &&
621
+ "$TEST_ROOT/rot13.sh" <smudge-write-fail.o >expected &&
622
+ git cat-file blob :smudge-write-fail.r >actual &&
623
+ test_cmp expected actual
624
+ )
625
+'
626
+
627
+test_expect_success PERL 'process filter should not be restarted if it signals an error' '
628
+ test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
629
+ rm -rf repo &&
630
+ mkdir repo &&
631
+ (
632
+ cd repo &&
633
+ git init &&
634
+
635
+ echo "*.r filter=protocol" >.gitattributes &&
636
+
637
+ cp "$TEST_ROOT/test.o" test.r &&
638
+ cp "$TEST_ROOT/test2.o" test2.r &&
639
+ echo "this will cause an error" >error.o &&
640
+ cp error.o error.r &&
641
+
642
+ S=$(file_size test.r) &&
643
+ S2=$(file_size test2.r) &&
644
+ SE=$(file_size error.r) &&
645
+
646
+ git add . &&
647
+ rm -f *.r &&
648
+
649
+ filter_git checkout --quiet --no-progress . &&
650
+ cat >expected.log <<-EOF &&
651
+ START
652
+ init handshake complete
653
+ IN: smudge error.r $SE [OK] -- OUT: 0 [ERROR]
654
+ IN: smudge test.r $S [OK] -- OUT: $S . [OK]
655
+ IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
656
+ STOP
657
+ EOF
658
+ test_cmp_exclude_clean expected.log rot13-filter.log &&
659
+
660
+ test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r &&
661
+ test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r &&
662
+ test_cmp error.o error.r
663
+ )
664
+'
665
+
666
+test_expect_success PERL 'process filter abort stops processing of all further files' '
667
+ test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
668
+ rm -rf repo &&
669
+ mkdir repo &&
670
+ (
671
+ cd repo &&
672
+ git init &&
673
+
674
+ echo "*.r filter=protocol" >.gitattributes &&
675
+
676
+ cp "$TEST_ROOT/test.o" test.r &&
677
+ cp "$TEST_ROOT/test2.o" test2.r &&
678
+ echo "error this blob and all future blobs" >abort.o &&
679
+ cp abort.o abort.r &&
680
+
681
+ SA=$(file_size abort.r) &&
682
+
683
+ git add . &&
684
+ rm -f *.r &&
685
+
686
+ # Note: This test assumes that Git filters files in alphabetical
687
+ # order ("abort.r" before "test.r").
688
+ filter_git checkout --quiet --no-progress . &&
689
+ cat >expected.log <<-EOF &&
690
+ START
691
+ init handshake complete
692
+ IN: smudge abort.r $SA [OK] -- OUT: 0 [ABORT]
693
+ STOP
694
+ EOF
695
+ test_cmp_exclude_clean expected.log rot13-filter.log &&
696
+
697
+ test_cmp "$TEST_ROOT/test.o" test.r &&
698
+ test_cmp "$TEST_ROOT/test2.o" test2.r &&
699
+ test_cmp abort.o abort.r
700
+ )
701
+'
702
+
703
+test_expect_success PERL 'invalid process filter must fail (and not hang!)' '
704
+ test_config_global filter.protocol.process cat &&
705
+ test_config_global filter.protocol.required true &&
706
+ rm -rf repo &&
707
+ mkdir repo &&
708
+ (
709
+ cd repo &&
710
+ git init &&
711
+
712
+ echo "*.r filter=protocol" >.gitattributes &&
713
+
714
+ cp "$TEST_ROOT/test.o" test.r &&
715
+ test_must_fail git add . 2>git-stderr.log &&
716
+ grep "does not support filter protocol version" git-stderr.log
717
+ )
718
+'
719
+
720
test_done