diff: correct interaction between --exit-code and -I<pattern>
[git] / t / t9300-fast-import.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Shawn Pearce
4 #
5
6 test_description='test git fast-import utility'
7 . ./test-lib.sh
8 . "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
9
10 verify_packs () {
11         for p in .git/objects/pack/*.pack
12         do
13                 git verify-pack "$@" "$p" || return
14         done
15 }
16
17 file2_data='file2
18 second line of EOF'
19
20 file3_data='EOF
21 in 3rd file
22  END'
23
24 file4_data=abcd
25 file4_len=4
26
27 file5_data='an inline file.
28   we should see it later.'
29
30 file6_data='#!/bin/sh
31 echo "$@"'
32
33 ###
34 ### series A
35 ###
36
37 test_expect_success 'empty stream succeeds' '
38         git config fastimport.unpackLimit 0 &&
39         git fast-import </dev/null
40 '
41
42 test_expect_success 'truncated stream complains' '
43         echo "tag foo" | test_must_fail git fast-import
44 '
45
46 test_expect_success 'A: create pack from stdin' '
47         test_tick &&
48         cat >input <<-INPUT_END &&
49         blob
50         mark :2
51         data <<EOF
52         $file2_data
53         EOF
54
55         blob
56         mark :3
57         data <<END
58         $file3_data
59         END
60
61         blob
62         mark :4
63         data $file4_len
64         $file4_data
65         commit refs/heads/master
66         mark :5
67         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
68         data <<COMMIT
69         initial
70         COMMIT
71
72         M 644 :2 file2
73         M 644 :3 file3
74         M 755 :4 file4
75
76         tag series-A
77         from :5
78         data <<EOF
79         An annotated tag without a tagger
80         EOF
81
82         tag series-A-blob
83         from :3
84         data <<EOF
85         An annotated tag that annotates a blob.
86         EOF
87
88         tag to-be-deleted
89         from :3
90         data <<EOF
91         Another annotated tag that annotates a blob.
92         EOF
93
94         reset refs/tags/to-be-deleted
95         from 0000000000000000000000000000000000000000
96
97         tag nested
98         mark :6
99         from :4
100         data <<EOF
101         Tag of our lovely commit
102         EOF
103
104         reset refs/tags/nested
105         from 0000000000000000000000000000000000000000
106
107         tag nested
108         mark :7
109         from :6
110         data <<EOF
111         Tag of tag of our lovely commit
112         EOF
113
114         alias
115         mark :8
116         to :5
117
118         INPUT_END
119         git fast-import --export-marks=marks.out <input &&
120         git whatchanged master
121 '
122
123 test_expect_success 'A: verify pack' '
124         verify_packs
125 '
126
127 test_expect_success 'A: verify commit' '
128         cat >expect <<-EOF &&
129         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
130         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
131
132         initial
133         EOF
134         git cat-file commit master | sed 1d >actual &&
135         test_cmp expect actual
136 '
137
138 test_expect_success 'A: verify tree' '
139         cat >expect <<-EOF &&
140         100644 blob file2
141         100644 blob file3
142         100755 blob file4
143         EOF
144         git cat-file -p master^{tree} | sed "s/ [0-9a-f]*       / /" >actual &&
145         test_cmp expect actual
146 '
147
148 test_expect_success 'A: verify file2' '
149         echo "$file2_data" >expect &&
150         git cat-file blob master:file2 >actual &&
151         test_cmp expect actual
152 '
153
154 test_expect_success 'A: verify file3' '
155         echo "$file3_data" >expect &&
156         git cat-file blob master:file3 >actual &&
157         test_cmp expect actual
158 '
159
160 test_expect_success 'A: verify file4' '
161         printf "$file4_data" >expect &&
162         git cat-file blob master:file4 >actual &&
163         test_cmp expect actual
164 '
165
166 test_expect_success 'A: verify tag/series-A' '
167         cat >expect <<-EOF &&
168         object $(git rev-parse refs/heads/master)
169         type commit
170         tag series-A
171
172         An annotated tag without a tagger
173         EOF
174         git cat-file tag tags/series-A >actual &&
175         test_cmp expect actual
176 '
177
178 test_expect_success 'A: verify tag/series-A-blob' '
179         cat >expect <<-EOF &&
180         object $(git rev-parse refs/heads/master:file3)
181         type blob
182         tag series-A-blob
183
184         An annotated tag that annotates a blob.
185         EOF
186         git cat-file tag tags/series-A-blob >actual &&
187         test_cmp expect actual
188 '
189
190 test_expect_success 'A: verify tag deletion is successful' '
191         test_must_fail git rev-parse --verify refs/tags/to-be-deleted
192 '
193
194 test_expect_success 'A: verify marks output' '
195         cat >expect <<-EOF &&
196         :2 $(git rev-parse --verify master:file2)
197         :3 $(git rev-parse --verify master:file3)
198         :4 $(git rev-parse --verify master:file4)
199         :5 $(git rev-parse --verify master^0)
200         :6 $(git cat-file tag nested | grep object | cut -d" " -f 2)
201         :7 $(git rev-parse --verify nested)
202         :8 $(git rev-parse --verify master^0)
203         EOF
204         test_cmp expect marks.out
205 '
206
207 test_expect_success 'A: verify marks import' '
208         git fast-import \
209                 --import-marks=marks.out \
210                 --export-marks=marks.new \
211                 </dev/null &&
212         test_cmp expect marks.new
213 '
214
215 test_expect_success 'A: tag blob by sha1' '
216         test_tick &&
217         new_blob=$(echo testing | git hash-object --stdin) &&
218         cat >input <<-INPUT_END &&
219         tag series-A-blob-2
220         from $(git rev-parse refs/heads/master:file3)
221         data <<EOF
222         Tag blob by sha1.
223         EOF
224
225         blob
226         mark :6
227         data <<EOF
228         testing
229         EOF
230
231         commit refs/heads/new_blob
232         committer  <> 0 +0000
233         data 0
234         M 644 :6 new_blob
235         #pretend we got sha1 from fast-import
236         ls "new_blob"
237
238         tag series-A-blob-3
239         from $new_blob
240         data <<EOF
241         Tag new_blob.
242         EOF
243         INPUT_END
244
245         cat >expect <<-EOF &&
246         object $(git rev-parse refs/heads/master:file3)
247         type blob
248         tag series-A-blob-2
249
250         Tag blob by sha1.
251         object $new_blob
252         type blob
253         tag series-A-blob-3
254
255         Tag new_blob.
256         EOF
257
258         git fast-import <input &&
259         git cat-file tag tags/series-A-blob-2 >actual &&
260         git cat-file tag tags/series-A-blob-3 >>actual &&
261         test_cmp expect actual
262 '
263
264 test_expect_success 'A: verify marks import does not crash' '
265         test_tick &&
266         cat >input <<-INPUT_END &&
267         commit refs/heads/verify--import-marks
268         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
269         data <<COMMIT
270         recreate from :5
271         COMMIT
272
273         from :5
274         M 755 :2 copy-of-file2
275
276         INPUT_END
277
278         git fast-import --import-marks=marks.out <input &&
279         git whatchanged verify--import-marks
280 '
281
282 test_expect_success 'A: verify pack' '
283         verify_packs
284 '
285
286 test_expect_success 'A: verify diff' '
287         cat >expect <<-EOF &&
288         :000000 100755 0000000000000000000000000000000000000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 A      copy-of-file2
289         EOF
290         git diff-tree -M -r master verify--import-marks >actual &&
291         compare_diff_raw expect actual &&
292         test $(git rev-parse --verify master:file2) \
293             = $(git rev-parse --verify verify--import-marks:copy-of-file2)
294 '
295
296 test_expect_success 'A: export marks with large values' '
297         test_tick &&
298         mt=$(git hash-object --stdin < /dev/null) &&
299         >input.blob &&
300         >marks.exp &&
301         >tree.exp &&
302
303         cat >input.commit <<-EOF &&
304         commit refs/heads/verify--dump-marks
305         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
306         data <<COMMIT
307         test the sparse array dumping routines with exponentially growing marks
308         COMMIT
309         EOF
310
311         i=0 l=4 m=6 n=7 &&
312         while test "$i" -lt 27
313         do
314                 cat >>input.blob <<-EOF &&
315                 blob
316                 mark :$l
317                 data 0
318                 blob
319                 mark :$m
320                 data 0
321                 blob
322                 mark :$n
323                 data 0
324                 EOF
325                 echo "M 100644 :$l l$i" >>input.commit &&
326                 echo "M 100644 :$m m$i" >>input.commit &&
327                 echo "M 100644 :$n n$i" >>input.commit &&
328
329                 echo ":$l $mt" >>marks.exp &&
330                 echo ":$m $mt" >>marks.exp &&
331                 echo ":$n $mt" >>marks.exp &&
332
333                 printf "100644 blob $mt\tl$i\n" >>tree.exp &&
334                 printf "100644 blob $mt\tm$i\n" >>tree.exp &&
335                 printf "100644 blob $mt\tn$i\n" >>tree.exp &&
336
337                 l=$(($l + $l)) &&
338                 m=$(($m + $m)) &&
339                 n=$(($l + $n)) &&
340
341                 i=$((1 + $i)) || return 1
342         done &&
343
344         sort tree.exp > tree.exp_s &&
345
346         cat input.blob input.commit | git fast-import --export-marks=marks.large &&
347         git ls-tree refs/heads/verify--dump-marks >tree.out &&
348         test_cmp tree.exp_s tree.out &&
349         test_cmp marks.exp marks.large
350 '
351
352 ###
353 ### series B
354 ###
355
356 test_expect_success 'B: fail on invalid blob sha1' '
357         test_tick &&
358         cat >input <<-INPUT_END &&
359         commit refs/heads/branch
360         mark :1
361         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
362         data <<COMMIT
363         corrupt
364         COMMIT
365
366         from refs/heads/master
367         M 755 0000000000000000000000000000000000000001 zero1
368
369         INPUT_END
370
371         test_when_finished "rm -f .git/objects/pack_* .git/objects/index_*" &&
372         test_must_fail git fast-import <input
373 '
374
375 test_expect_success 'B: accept branch name "TEMP_TAG"' '
376         cat >input <<-INPUT_END &&
377         commit TEMP_TAG
378         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
379         data <<COMMIT
380         tag base
381         COMMIT
382
383         from refs/heads/master
384
385         INPUT_END
386
387         test_when_finished "rm -f .git/TEMP_TAG
388                 git gc
389                 git prune" &&
390         git fast-import <input &&
391         test -f .git/TEMP_TAG &&
392         test $(git rev-parse master) = $(git rev-parse TEMP_TAG^)
393 '
394
395 test_expect_success 'B: accept empty committer' '
396         cat >input <<-INPUT_END &&
397         commit refs/heads/empty-committer-1
398         committer  <> $GIT_COMMITTER_DATE
399         data <<COMMIT
400         empty commit
401         COMMIT
402         INPUT_END
403
404         test_when_finished "git update-ref -d refs/heads/empty-committer-1
405                 git gc
406                 git prune" &&
407         git fast-import <input &&
408         out=$(git fsck) &&
409         echo "$out" &&
410         test -z "$out"
411 '
412
413 test_expect_success 'B: reject invalid timezone' '
414         cat >input <<-INPUT_END &&
415         commit refs/heads/invalid-timezone
416         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1234567890 +051800
417         data <<COMMIT
418         empty commit
419         COMMIT
420         INPUT_END
421
422         test_when_finished "git update-ref -d refs/heads/invalid-timezone" &&
423         test_must_fail git fast-import <input
424 '
425
426 test_expect_success 'B: accept invalid timezone with raw-permissive' '
427         cat >input <<-INPUT_END &&
428         commit refs/heads/invalid-timezone
429         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1234567890 +051800
430         data <<COMMIT
431         empty commit
432         COMMIT
433         INPUT_END
434
435         git init invalid-timezone &&
436         git -C invalid-timezone fast-import --date-format=raw-permissive <input &&
437         git -C invalid-timezone cat-file -p invalid-timezone >out &&
438         grep "1234567890 [+]051800" out
439 '
440
441 test_expect_success 'B: accept and fixup committer with no name' '
442         cat >input <<-INPUT_END &&
443         commit refs/heads/empty-committer-2
444         committer <a@b.com> $GIT_COMMITTER_DATE
445         data <<COMMIT
446         empty commit
447         COMMIT
448         INPUT_END
449
450         test_when_finished "git update-ref -d refs/heads/empty-committer-2
451                 git gc
452                 git prune" &&
453         git fast-import <input &&
454         out=$(git fsck) &&
455         echo "$out" &&
456         test -z "$out"
457 '
458
459 test_expect_success 'B: fail on invalid committer (1)' '
460         cat >input <<-INPUT_END &&
461         commit refs/heads/invalid-committer
462         committer Name email> $GIT_COMMITTER_DATE
463         data <<COMMIT
464         empty commit
465         COMMIT
466         INPUT_END
467
468         test_when_finished "git update-ref -d refs/heads/invalid-committer" &&
469         test_must_fail git fast-import <input
470 '
471
472 test_expect_success 'B: fail on invalid committer (2)' '
473         cat >input <<-INPUT_END &&
474         commit refs/heads/invalid-committer
475         committer Name <e<mail> $GIT_COMMITTER_DATE
476         data <<COMMIT
477         empty commit
478         COMMIT
479         INPUT_END
480
481         test_when_finished "git update-ref -d refs/heads/invalid-committer" &&
482         test_must_fail git fast-import <input
483 '
484
485 test_expect_success 'B: fail on invalid committer (3)' '
486         cat >input <<-INPUT_END &&
487         commit refs/heads/invalid-committer
488         committer Name <email>> $GIT_COMMITTER_DATE
489         data <<COMMIT
490         empty commit
491         COMMIT
492         INPUT_END
493
494         test_when_finished "git update-ref -d refs/heads/invalid-committer" &&
495         test_must_fail git fast-import <input
496 '
497
498 test_expect_success 'B: fail on invalid committer (4)' '
499         cat >input <<-INPUT_END &&
500         commit refs/heads/invalid-committer
501         committer Name <email $GIT_COMMITTER_DATE
502         data <<COMMIT
503         empty commit
504         COMMIT
505         INPUT_END
506
507         test_when_finished "git update-ref -d refs/heads/invalid-committer" &&
508         test_must_fail git fast-import <input
509 '
510
511 test_expect_success 'B: fail on invalid committer (5)' '
512         cat >input <<-INPUT_END &&
513         commit refs/heads/invalid-committer
514         committer Name<email> $GIT_COMMITTER_DATE
515         data <<COMMIT
516         empty commit
517         COMMIT
518         INPUT_END
519
520         test_when_finished "git update-ref -d refs/heads/invalid-committer" &&
521         test_must_fail git fast-import <input
522 '
523
524 ###
525 ### series C
526 ###
527
528 test_expect_success 'C: incremental import create pack from stdin' '
529         newf=$(echo hi newf | git hash-object -w --stdin) &&
530         oldf=$(git rev-parse --verify master:file2) &&
531         test_tick &&
532         cat >input <<-INPUT_END &&
533         commit refs/heads/branch
534         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
535         data <<COMMIT
536         second
537         COMMIT
538
539         from refs/heads/master
540         M 644 $oldf file2/oldf
541         M 755 $newf file2/newf
542         D file3
543
544         INPUT_END
545
546         git fast-import <input &&
547         git whatchanged branch
548 '
549
550 test_expect_success 'C: verify pack' '
551         verify_packs
552 '
553
554 test_expect_success 'C: validate reuse existing blob' '
555         test $newf = $(git rev-parse --verify branch:file2/newf) &&
556         test $oldf = $(git rev-parse --verify branch:file2/oldf)
557 '
558
559 test_expect_success 'C: verify commit' '
560         cat >expect <<-EOF &&
561         parent $(git rev-parse --verify master^0)
562         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
563         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
564
565         second
566         EOF
567
568         git cat-file commit branch | sed 1d >actual &&
569         test_cmp expect actual
570 '
571
572 test_expect_success 'C: validate rename result' '
573         cat >expect <<-EOF &&
574         :000000 100755 0000000000000000000000000000000000000000 f1fb5da718392694d0076d677d6d0e364c79b0bc A      file2/newf
575         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 R100   file2   file2/oldf
576         :100644 000000 0d92e9f3374ae2947c23aa477cbc68ce598135f1 0000000000000000000000000000000000000000 D      file3
577         EOF
578         git diff-tree -M -r master branch >actual &&
579         compare_diff_raw expect actual
580 '
581
582 ###
583 ### series D
584 ###
585
586 test_expect_success 'D: inline data in commit' '
587         test_tick &&
588         cat >input <<-INPUT_END &&
589         commit refs/heads/branch
590         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
591         data <<COMMIT
592         third
593         COMMIT
594
595         from refs/heads/branch^0
596         M 644 inline newdir/interesting
597         data <<EOF
598         $file5_data
599         EOF
600
601         M 755 inline newdir/exec.sh
602         data <<EOF
603         $file6_data
604         EOF
605
606         INPUT_END
607
608         git fast-import <input &&
609         git whatchanged branch
610 '
611
612 test_expect_success 'D: verify pack' '
613         verify_packs
614 '
615
616 test_expect_success 'D: validate new files added' '
617         cat >expect <<-EOF &&
618         :000000 100755 0000000000000000000000000000000000000000 e74b7d465e52746be2b4bae983670711e6e66657 A      newdir/exec.sh
619         :000000 100644 0000000000000000000000000000000000000000 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 A      newdir/interesting
620         EOF
621         git diff-tree -M -r branch^ branch >actual &&
622         compare_diff_raw expect actual
623 '
624
625 test_expect_success 'D: verify file5' '
626         echo "$file5_data" >expect &&
627         git cat-file blob branch:newdir/interesting >actual &&
628         test_cmp expect actual
629 '
630
631 test_expect_success 'D: verify file6' '
632         echo "$file6_data" >expect &&
633         git cat-file blob branch:newdir/exec.sh >actual &&
634         test_cmp expect actual
635 '
636
637 ###
638 ### series E
639 ###
640
641 test_expect_success 'E: rfc2822 date, --date-format=raw' '
642         cat >input <<-INPUT_END &&
643         commit refs/heads/branch
644         author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> Tue Feb 6 11:22:18 2007 -0500
645         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> Tue Feb 6 12:35:02 2007 -0500
646         data <<COMMIT
647         RFC 2822 type date
648         COMMIT
649
650         from refs/heads/branch^0
651
652         INPUT_END
653
654         test_must_fail git fast-import --date-format=raw <input
655 '
656 test_expect_success 'E: rfc2822 date, --date-format=rfc2822' '
657         git fast-import --date-format=rfc2822 <input
658 '
659
660 test_expect_success 'E: verify pack' '
661         verify_packs
662 '
663
664 test_expect_success 'E: verify commit' '
665         cat >expect <<-EOF &&
666         author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 1170778938 -0500
667         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1170783302 -0500
668
669         RFC 2822 type date
670         EOF
671         git cat-file commit branch | sed 1,2d >actual &&
672         test_cmp expect actual
673 '
674
675 ###
676 ### series F
677 ###
678
679 test_expect_success 'F: non-fast-forward update skips' '
680         old_branch=$(git rev-parse --verify branch^0) &&
681         test_tick &&
682         cat >input <<-INPUT_END &&
683         commit refs/heads/branch
684         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
685         data <<COMMIT
686         losing things already?
687         COMMIT
688
689         from refs/heads/branch~1
690
691         reset refs/heads/other
692         from refs/heads/branch
693
694         INPUT_END
695
696         test_must_fail git fast-import <input &&
697         # branch must remain unaffected
698         test $old_branch = $(git rev-parse --verify branch^0)
699 '
700
701 test_expect_success 'F: verify pack' '
702         verify_packs
703 '
704
705 test_expect_success 'F: verify other commit' '
706         cat >expect <<-EOF &&
707         tree $(git rev-parse branch~1^{tree})
708         parent $(git rev-parse branch~1)
709         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
710         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
711
712         losing things already?
713         EOF
714         git cat-file commit other >actual &&
715         test_cmp expect actual
716 '
717
718 ###
719 ### series G
720 ###
721
722 test_expect_success 'G: non-fast-forward update forced' '
723         old_branch=$(git rev-parse --verify branch^0) &&
724         test_tick &&
725         cat >input <<-INPUT_END &&
726         commit refs/heads/branch
727         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
728         data <<COMMIT
729         losing things already?
730         COMMIT
731
732         from refs/heads/branch~1
733
734         INPUT_END
735         git fast-import --force <input
736 '
737
738 test_expect_success 'G: verify pack' '
739         verify_packs
740 '
741
742 test_expect_success 'G: branch changed, but logged' '
743         test $old_branch != $(git rev-parse --verify branch^0) &&
744         test $old_branch = $(git rev-parse --verify branch@{1})
745 '
746
747 ###
748 ### series H
749 ###
750
751 test_expect_success 'H: deletall, add 1' '
752         test_tick &&
753         cat >input <<-INPUT_END &&
754         commit refs/heads/H
755         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
756         data <<COMMIT
757         third
758         COMMIT
759
760         from refs/heads/branch^0
761         M 644 inline i-will-die
762         data <<EOF
763         this file will never exist.
764         EOF
765
766         deleteall
767         M 644 inline h/e/l/lo
768         data <<EOF
769         $file5_data
770         EOF
771
772         INPUT_END
773         git fast-import <input &&
774         git whatchanged H
775 '
776
777 test_expect_success 'H: verify pack' '
778         verify_packs
779 '
780
781 test_expect_success 'H: validate old files removed, new files added' '
782         cat >expect <<-EOF &&
783         :100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D      file2/newf
784         :100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D      file2/oldf
785         :100755 000000 85df50785d62d3b05ab03d9cbf7e4a0b49449730 0000000000000000000000000000000000000000 D      file4
786         :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100   newdir/interesting      h/e/l/lo
787         :100755 000000 e74b7d465e52746be2b4bae983670711e6e66657 0000000000000000000000000000000000000000 D      newdir/exec.sh
788         EOF
789         git diff-tree -M -r H^ H >actual &&
790         compare_diff_raw expect actual
791 '
792
793 test_expect_success 'H: verify file' '
794         echo "$file5_data" >expect &&
795         git cat-file blob H:h/e/l/lo >actual &&
796         test_cmp expect actual
797 '
798
799 ###
800 ### series I
801 ###
802
803 test_expect_success 'I: export-pack-edges' '
804         cat >input <<-INPUT_END &&
805         commit refs/heads/export-boundary
806         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
807         data <<COMMIT
808         we have a border.  its only 40 characters wide.
809         COMMIT
810
811         from refs/heads/branch
812
813         INPUT_END
814         git fast-import --export-pack-edges=edges.list <input
815 '
816
817 test_expect_success 'I: verify edge list' '
818         cat >expect <<-EOF &&
819         .git/objects/pack/pack-.pack: $(git rev-parse --verify export-boundary)
820         EOF
821         sed -e s/pack-.*pack/pack-.pack/ edges.list >actual &&
822         test_cmp expect actual
823 '
824
825 ###
826 ### series J
827 ###
828
829 test_expect_success 'J: reset existing branch creates empty commit' '
830         cat >input <<-INPUT_END &&
831         commit refs/heads/J
832         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
833         data <<COMMIT
834         create J
835         COMMIT
836
837         from refs/heads/branch
838
839         reset refs/heads/J
840
841         commit refs/heads/J
842         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
843         data <<COMMIT
844         initialize J
845         COMMIT
846
847         INPUT_END
848         git fast-import <input
849 '
850 test_expect_success 'J: branch has 1 commit, empty tree' '
851         test 1 = $(git rev-list J | wc -l) &&
852         test 0 = $(git ls-tree J | wc -l)
853 '
854
855 test_expect_success 'J: tag must fail on empty branch' '
856         cat >input <<-INPUT_END &&
857         reset refs/heads/J2
858
859         tag wrong_tag
860         from refs/heads/J2
861         data <<EOF
862         Tag branch that was reset.
863         EOF
864         INPUT_END
865         test_must_fail git fast-import <input
866 '
867
868 ###
869 ### series K
870 ###
871
872 test_expect_success 'K: reinit branch with from' '
873         cat >input <<-INPUT_END &&
874         commit refs/heads/K
875         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
876         data <<COMMIT
877         create K
878         COMMIT
879
880         from refs/heads/branch
881
882         commit refs/heads/K
883         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
884         data <<COMMIT
885         redo K
886         COMMIT
887
888         from refs/heads/branch^1
889
890         INPUT_END
891         git fast-import <input
892 '
893 test_expect_success 'K: verify K^1 = branch^1' '
894         test $(git rev-parse --verify branch^1) \
895                 = $(git rev-parse --verify K^1)
896 '
897
898 ###
899 ### series L
900 ###
901
902 test_expect_success 'L: verify internal tree sorting' '
903         cat >input <<-INPUT_END &&
904         blob
905         mark :1
906         data <<EOF
907         some data
908         EOF
909
910         blob
911         mark :2
912         data <<EOF
913         other data
914         EOF
915
916         commit refs/heads/L
917         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
918         data <<COMMIT
919         create L
920         COMMIT
921
922         M 644 :1 b.
923         M 644 :1 b/other
924         M 644 :1 ba
925
926         commit refs/heads/L
927         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
928         data <<COMMIT
929         update L
930         COMMIT
931
932         M 644 :2 b.
933         M 644 :2 b/other
934         M 644 :2 ba
935         INPUT_END
936
937         cat >expect <<-EXPECT_END &&
938         :100644 100644 4268632... 55d3a52... M  b.
939         :040000 040000 0ae5cac... 443c768... M  b
940         :100644 100644 4268632... 55d3a52... M  ba
941         EXPECT_END
942
943         git fast-import <input &&
944         GIT_PRINT_SHA1_ELLIPSIS="yes" git diff-tree --abbrev --raw L^ L >output &&
945         test_cmp expect output
946 '
947
948 test_expect_success 'L: nested tree copy does not corrupt deltas' '
949         cat >input <<-INPUT_END &&
950         blob
951         mark :1
952         data <<EOF
953         the data
954         EOF
955
956         commit refs/heads/L2
957         committer C O Mitter <committer@example.com> 1112912473 -0700
958         data <<COMMIT
959         init L2
960         COMMIT
961         M 644 :1 a/b/c
962         M 644 :1 a/b/d
963         M 644 :1 a/e/f
964
965         commit refs/heads/L2
966         committer C O Mitter <committer@example.com> 1112912473 -0700
967         data <<COMMIT
968         update L2
969         COMMIT
970         C a g
971         C a/e g/b
972         M 644 :1 g/b/h
973         INPUT_END
974
975         cat >expect <<-\EOF &&
976         g/b/f
977         g/b/h
978         EOF
979
980         test_when_finished "git update-ref -d refs/heads/L2" &&
981         git fast-import <input &&
982         git ls-tree L2 g/b/ >tmp &&
983         cat tmp | cut -f 2 >actual &&
984         test_cmp expect actual &&
985         git fsck $(git rev-parse L2)
986 '
987
988 ###
989 ### series M
990 ###
991
992 test_expect_success 'M: rename file in same subdirectory' '
993         test_tick &&
994         cat >input <<-INPUT_END &&
995         commit refs/heads/M1
996         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
997         data <<COMMIT
998         file rename
999         COMMIT
1000
1001         from refs/heads/branch^0
1002         R file2/newf file2/n.e.w.f
1003
1004         INPUT_END
1005
1006         cat >expect <<-EOF &&
1007         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100   file2/newf      file2/n.e.w.f
1008         EOF
1009         git fast-import <input &&
1010         git diff-tree -M -r M1^ M1 >actual &&
1011         compare_diff_raw expect actual
1012 '
1013
1014 test_expect_success 'M: rename file to new subdirectory' '
1015         cat >input <<-INPUT_END &&
1016         commit refs/heads/M2
1017         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1018         data <<COMMIT
1019         file rename
1020         COMMIT
1021
1022         from refs/heads/branch^0
1023         R file2/newf i/am/new/to/you
1024
1025         INPUT_END
1026
1027         cat >expect <<-EOF &&
1028         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100   file2/newf      i/am/new/to/you
1029         EOF
1030         git fast-import <input &&
1031         git diff-tree -M -r M2^ M2 >actual &&
1032         compare_diff_raw expect actual
1033 '
1034
1035 test_expect_success 'M: rename subdirectory to new subdirectory' '
1036         cat >input <<-INPUT_END &&
1037         commit refs/heads/M3
1038         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1039         data <<COMMIT
1040         file rename
1041         COMMIT
1042
1043         from refs/heads/M2^0
1044         R i other/sub
1045
1046         INPUT_END
1047
1048         cat >expect <<-EOF &&
1049         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100   i/am/new/to/you other/sub/am/new/to/you
1050         EOF
1051         git fast-import <input &&
1052         git diff-tree -M -r M3^ M3 >actual &&
1053         compare_diff_raw expect actual
1054 '
1055
1056 test_expect_success 'M: rename root to subdirectory' '
1057         cat >input <<-INPUT_END &&
1058         commit refs/heads/M4
1059         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1060         data <<COMMIT
1061         rename root
1062         COMMIT
1063
1064         from refs/heads/M2^0
1065         R "" sub
1066
1067         INPUT_END
1068
1069         cat >expect <<-EOF &&
1070         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 R100   file2/oldf      sub/file2/oldf
1071         :100755 100755 85df50785d62d3b05ab03d9cbf7e4a0b49449730 85df50785d62d3b05ab03d9cbf7e4a0b49449730 R100   file4   sub/file4
1072         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100   i/am/new/to/you sub/i/am/new/to/you
1073         :100755 100755 e74b7d465e52746be2b4bae983670711e6e66657 e74b7d465e52746be2b4bae983670711e6e66657 R100   newdir/exec.sh  sub/newdir/exec.sh
1074         :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100   newdir/interesting      sub/newdir/interesting
1075         EOF
1076         git fast-import <input &&
1077         git diff-tree -M -r M4^ M4 >actual &&
1078         compare_diff_raw expect actual
1079 '
1080
1081 ###
1082 ### series N
1083 ###
1084
1085 test_expect_success 'N: copy file in same subdirectory' '
1086         test_tick &&
1087         cat >input <<-INPUT_END &&
1088         commit refs/heads/N1
1089         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1090         data <<COMMIT
1091         file copy
1092         COMMIT
1093
1094         from refs/heads/branch^0
1095         C file2/newf file2/n.e.w.f
1096
1097         INPUT_END
1098
1099         cat >expect <<-EOF &&
1100         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file2/n.e.w.f
1101         EOF
1102         git fast-import <input &&
1103         git diff-tree -C --find-copies-harder -r N1^ N1 >actual &&
1104         compare_diff_raw expect actual
1105 '
1106
1107 test_expect_success 'N: copy then modify subdirectory' '
1108         cat >input <<-INPUT_END &&
1109         commit refs/heads/N2
1110         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1111         data <<COMMIT
1112         clean directory copy
1113         COMMIT
1114
1115         from refs/heads/branch^0
1116         C file2 file3
1117
1118         commit refs/heads/N2
1119         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1120         data <<COMMIT
1121         modify directory copy
1122         COMMIT
1123
1124         M 644 inline file3/file5
1125         data <<EOF
1126         $file5_data
1127         EOF
1128
1129         INPUT_END
1130
1131         cat >expect <<-EOF &&
1132         :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100   newdir/interesting      file3/file5
1133         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
1134         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
1135         EOF
1136         git fast-import <input &&
1137         git diff-tree -C --find-copies-harder -r N2^^ N2 >actual &&
1138         compare_diff_raw expect actual
1139 '
1140
1141 test_expect_success 'N: copy dirty subdirectory' '
1142         cat >input <<-INPUT_END &&
1143         commit refs/heads/N3
1144         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1145         data <<COMMIT
1146         dirty directory copy
1147         COMMIT
1148
1149         from refs/heads/branch^0
1150         M 644 inline file2/file5
1151         data <<EOF
1152         $file5_data
1153         EOF
1154
1155         C file2 file3
1156         D file2/file5
1157
1158         INPUT_END
1159
1160         git fast-import <input &&
1161         test $(git rev-parse N2^{tree}) = $(git rev-parse N3^{tree})
1162 '
1163
1164 test_expect_success 'N: copy directory by id' '
1165         cat >expect <<-\EOF &&
1166         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
1167         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
1168         EOF
1169         subdir=$(git rev-parse refs/heads/branch^0:file2) &&
1170         cat >input <<-INPUT_END &&
1171         commit refs/heads/N4
1172         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1173         data <<COMMIT
1174         copy by tree hash
1175         COMMIT
1176
1177         from refs/heads/branch^0
1178         M 040000 $subdir file3
1179         INPUT_END
1180         git fast-import <input &&
1181         git diff-tree -C --find-copies-harder -r N4^ N4 >actual &&
1182         compare_diff_raw expect actual
1183 '
1184
1185 test_expect_success PIPE 'N: read and copy directory' '
1186         cat >expect <<-\EOF &&
1187         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
1188         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
1189         EOF
1190         git update-ref -d refs/heads/N4 &&
1191         rm -f backflow &&
1192         mkfifo backflow &&
1193         (
1194                 exec <backflow &&
1195                 cat <<-EOF &&
1196                 commit refs/heads/N4
1197                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1198                 data <<COMMIT
1199                 copy by tree hash, part 2
1200                 COMMIT
1201
1202                 from refs/heads/branch^0
1203                 ls "file2"
1204                 EOF
1205                 read mode type tree filename &&
1206                 echo "M 040000 $tree file3"
1207         ) |
1208         git fast-import --cat-blob-fd=3 3>backflow &&
1209         git diff-tree -C --find-copies-harder -r N4^ N4 >actual &&
1210         compare_diff_raw expect actual
1211 '
1212
1213 test_expect_success PIPE 'N: empty directory reads as missing' '
1214         cat <<-\EOF >expect &&
1215         OBJNAME
1216         :000000 100644 OBJNAME OBJNAME A        unrelated
1217         EOF
1218         echo "missing src" >expect.response &&
1219         git update-ref -d refs/heads/read-empty &&
1220         rm -f backflow &&
1221         mkfifo backflow &&
1222         (
1223                 exec <backflow &&
1224                 cat <<-EOF &&
1225                 commit refs/heads/read-empty
1226                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1227                 data <<COMMIT
1228                 read "empty" (missing) directory
1229                 COMMIT
1230
1231                 M 100644 inline src/greeting
1232                 data <<BLOB
1233                 hello
1234                 BLOB
1235                 C src/greeting dst1/non-greeting
1236                 C src/greeting unrelated
1237                 # leave behind "empty" src directory
1238                 D src/greeting
1239                 ls "src"
1240                 EOF
1241                 read -r line &&
1242                 printf "%s\n" "$line" >response &&
1243                 cat <<-\EOF
1244                 D dst1
1245                 D dst2
1246                 EOF
1247         ) |
1248         git fast-import --cat-blob-fd=3 3>backflow &&
1249         test_cmp expect.response response &&
1250         git rev-list read-empty |
1251         git diff-tree -r --root --stdin |
1252         sed "s/$OID_REGEX/OBJNAME/g" >actual &&
1253         test_cmp expect actual
1254 '
1255
1256 test_expect_success 'N: copy root directory by tree hash' '
1257         cat >expect <<-\EOF &&
1258         :100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D      file3/newf
1259         :100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D      file3/oldf
1260         EOF
1261         root=$(git rev-parse refs/heads/branch^0^{tree}) &&
1262         cat >input <<-INPUT_END &&
1263         commit refs/heads/N6
1264         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1265         data <<COMMIT
1266         copy root directory by tree hash
1267         COMMIT
1268
1269         from refs/heads/branch^0
1270         M 040000 $root ""
1271         INPUT_END
1272         git fast-import <input &&
1273         git diff-tree -C --find-copies-harder -r N4 N6 >actual &&
1274         compare_diff_raw expect actual
1275 '
1276
1277 test_expect_success 'N: copy root by path' '
1278         cat >expect <<-\EOF &&
1279         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      oldroot/file2/newf
1280         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      oldroot/file2/oldf
1281         :100755 100755 85df50785d62d3b05ab03d9cbf7e4a0b49449730 85df50785d62d3b05ab03d9cbf7e4a0b49449730 C100   file4   oldroot/file4
1282         :100755 100755 e74b7d465e52746be2b4bae983670711e6e66657 e74b7d465e52746be2b4bae983670711e6e66657 C100   newdir/exec.sh  oldroot/newdir/exec.sh
1283         :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100   newdir/interesting      oldroot/newdir/interesting
1284         EOF
1285         cat >input <<-INPUT_END &&
1286         commit refs/heads/N-copy-root-path
1287         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1288         data <<COMMIT
1289         copy root directory by (empty) path
1290         COMMIT
1291
1292         from refs/heads/branch^0
1293         C "" oldroot
1294         INPUT_END
1295         git fast-import <input &&
1296         git diff-tree -C --find-copies-harder -r branch N-copy-root-path >actual &&
1297         compare_diff_raw expect actual
1298 '
1299
1300 test_expect_success 'N: delete directory by copying' '
1301         cat >expect <<-\EOF &&
1302         OBJID
1303         :100644 000000 OBJID OBJID D    foo/bar/qux
1304         OBJID
1305         :000000 100644 OBJID OBJID A    foo/bar/baz
1306         :000000 100644 OBJID OBJID A    foo/bar/qux
1307         EOF
1308         empty_tree=$(git mktree </dev/null) &&
1309         cat >input <<-INPUT_END &&
1310         commit refs/heads/N-delete
1311         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1312         data <<COMMIT
1313         collect data to be deleted
1314         COMMIT
1315
1316         deleteall
1317         M 100644 inline foo/bar/baz
1318         data <<DATA_END
1319         hello
1320         DATA_END
1321         C "foo/bar/baz" "foo/bar/qux"
1322         C "foo/bar/baz" "foo/bar/quux/1"
1323         C "foo/bar/baz" "foo/bar/quuux"
1324         M 040000 $empty_tree foo/bar/quux
1325         M 040000 $empty_tree foo/bar/quuux
1326
1327         commit refs/heads/N-delete
1328         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1329         data <<COMMIT
1330         delete subdirectory
1331         COMMIT
1332
1333         M 040000 $empty_tree foo/bar/qux
1334         INPUT_END
1335         git fast-import <input &&
1336         git rev-list N-delete |
1337                 git diff-tree -r --stdin --root --always |
1338                 sed -e "s/$OID_REGEX/OBJID/g" >actual &&
1339         test_cmp expect actual
1340 '
1341
1342 test_expect_success 'N: modify copied tree' '
1343         cat >expect <<-\EOF &&
1344         :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100   newdir/interesting      file3/file5
1345         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
1346         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
1347         EOF
1348         subdir=$(git rev-parse refs/heads/branch^0:file2) &&
1349         cat >input <<-INPUT_END &&
1350         commit refs/heads/N5
1351         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1352         data <<COMMIT
1353         copy by tree hash
1354         COMMIT
1355
1356         from refs/heads/branch^0
1357         M 040000 $subdir file3
1358
1359         commit refs/heads/N5
1360         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1361         data <<COMMIT
1362         modify directory copy
1363         COMMIT
1364
1365         M 644 inline file3/file5
1366         data <<EOF
1367         $file5_data
1368         EOF
1369         INPUT_END
1370         git fast-import <input &&
1371         git diff-tree -C --find-copies-harder -r N5^^ N5 >actual &&
1372         compare_diff_raw expect actual
1373 '
1374
1375 test_expect_success 'N: reject foo/ syntax' '
1376         subdir=$(git rev-parse refs/heads/branch^0:file2) &&
1377         test_must_fail git fast-import <<-INPUT_END
1378         commit refs/heads/N5B
1379         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1380         data <<COMMIT
1381         copy with invalid syntax
1382         COMMIT
1383
1384         from refs/heads/branch^0
1385         M 040000 $subdir file3/
1386         INPUT_END
1387 '
1388
1389 test_expect_success 'N: reject foo/ syntax in copy source' '
1390         test_must_fail git fast-import <<-INPUT_END
1391         commit refs/heads/N5C
1392         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1393         data <<COMMIT
1394         copy with invalid syntax
1395         COMMIT
1396
1397         from refs/heads/branch^0
1398         C file2/ file3
1399         INPUT_END
1400 '
1401
1402 test_expect_success 'N: reject foo/ syntax in rename source' '
1403         test_must_fail git fast-import <<-INPUT_END
1404         commit refs/heads/N5D
1405         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1406         data <<COMMIT
1407         rename with invalid syntax
1408         COMMIT
1409
1410         from refs/heads/branch^0
1411         R file2/ file3
1412         INPUT_END
1413 '
1414
1415 test_expect_success 'N: reject foo/ syntax in ls argument' '
1416         test_must_fail git fast-import <<-INPUT_END
1417         commit refs/heads/N5E
1418         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1419         data <<COMMIT
1420         copy with invalid syntax
1421         COMMIT
1422
1423         from refs/heads/branch^0
1424         ls "file2/"
1425         INPUT_END
1426 '
1427
1428 test_expect_success 'N: copy to root by id and modify' '
1429         echo "hello, world" >expect.foo &&
1430         echo hello >expect.bar &&
1431         git fast-import <<-SETUP_END &&
1432         commit refs/heads/N7
1433         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1434         data <<COMMIT
1435         hello, tree
1436         COMMIT
1437
1438         deleteall
1439         M 644 inline foo/bar
1440         data <<EOF
1441         hello
1442         EOF
1443         SETUP_END
1444
1445         tree=$(git rev-parse --verify N7:) &&
1446         git fast-import <<-INPUT_END &&
1447         commit refs/heads/N8
1448         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1449         data <<COMMIT
1450         copy to root by id and modify
1451         COMMIT
1452
1453         M 040000 $tree ""
1454         M 644 inline foo/foo
1455         data <<EOF
1456         hello, world
1457         EOF
1458         INPUT_END
1459         git show N8:foo/foo >actual.foo &&
1460         git show N8:foo/bar >actual.bar &&
1461         test_cmp expect.foo actual.foo &&
1462         test_cmp expect.bar actual.bar
1463 '
1464
1465 test_expect_success 'N: extract subtree' '
1466         branch=$(git rev-parse --verify refs/heads/branch^{tree}) &&
1467         cat >input <<-INPUT_END &&
1468         commit refs/heads/N9
1469         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1470         data <<COMMIT
1471         extract subtree branch:newdir
1472         COMMIT
1473
1474         M 040000 $branch ""
1475         C "newdir" ""
1476         INPUT_END
1477         git fast-import <input &&
1478         git diff --exit-code branch:newdir N9
1479 '
1480
1481 test_expect_success 'N: modify subtree, extract it, and modify again' '
1482         echo hello >expect.baz &&
1483         echo hello, world >expect.qux &&
1484         git fast-import <<-SETUP_END &&
1485         commit refs/heads/N10
1486         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1487         data <<COMMIT
1488         hello, tree
1489         COMMIT
1490
1491         deleteall
1492         M 644 inline foo/bar/baz
1493         data <<EOF
1494         hello
1495         EOF
1496         SETUP_END
1497
1498         tree=$(git rev-parse --verify N10:) &&
1499         git fast-import <<-INPUT_END &&
1500         commit refs/heads/N11
1501         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1502         data <<COMMIT
1503         copy to root by id and modify
1504         COMMIT
1505
1506         M 040000 $tree ""
1507         M 100644 inline foo/bar/qux
1508         data <<EOF
1509         hello, world
1510         EOF
1511         R "foo" ""
1512         C "bar/qux" "bar/quux"
1513         INPUT_END
1514         git show N11:bar/baz >actual.baz &&
1515         git show N11:bar/qux >actual.qux &&
1516         git show N11:bar/quux >actual.quux &&
1517         test_cmp expect.baz actual.baz &&
1518         test_cmp expect.qux actual.qux &&
1519         test_cmp expect.qux actual.quux'
1520
1521 ###
1522 ### series O
1523 ###
1524
1525 test_expect_success 'O: comments are all skipped' '
1526         cat >input <<-INPUT_END &&
1527         #we will
1528         commit refs/heads/O1
1529         # -- ignore all of this text
1530         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1531         # $GIT_COMMITTER_NAME has inserted here for his benefit.
1532         data <<COMMIT
1533         dirty directory copy
1534         COMMIT
1535
1536         # do not forget the import blank line!
1537         #
1538         # yes, we started from our usual base of branch^0.
1539         # i like branch^0.
1540         from refs/heads/branch^0
1541         # and we need to reuse file2/file5 from N3 above.
1542         M 644 inline file2/file5
1543         # otherwise the tree will be different
1544         data <<EOF
1545         $file5_data
1546         EOF
1547
1548         # do not forget to copy file2 to file3
1549         C file2 file3
1550         #
1551         # or to delete file5 from file2.
1552         D file2/file5
1553         # are we done yet?
1554
1555         INPUT_END
1556
1557         git fast-import <input &&
1558         test $(git rev-parse N3) = $(git rev-parse O1)
1559 '
1560
1561 test_expect_success 'O: blank lines not necessary after data commands' '
1562         cat >input <<-INPUT_END &&
1563         commit refs/heads/O2
1564         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1565         data <<COMMIT
1566         dirty directory copy
1567         COMMIT
1568         from refs/heads/branch^0
1569         M 644 inline file2/file5
1570         data <<EOF
1571         $file5_data
1572         EOF
1573         C file2 file3
1574         D file2/file5
1575
1576         INPUT_END
1577
1578         git fast-import <input &&
1579         test $(git rev-parse N3) = $(git rev-parse O2)
1580 '
1581
1582 test_expect_success 'O: repack before next test' '
1583         git repack -a -d
1584 '
1585
1586 test_expect_success 'O: blank lines not necessary after other commands' '
1587         cat >input <<-INPUT_END &&
1588         commit refs/heads/O3
1589         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1590         data <<COMMIT
1591         zstring
1592         COMMIT
1593         commit refs/heads/O3
1594         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1595         data <<COMMIT
1596         zof
1597         COMMIT
1598         checkpoint
1599         commit refs/heads/O3
1600         mark :5
1601         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1602         data <<COMMIT
1603         zempty
1604         COMMIT
1605         checkpoint
1606         commit refs/heads/O3
1607         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1608         data <<COMMIT
1609         zcommits
1610         COMMIT
1611         reset refs/tags/O3-2nd
1612         from :5
1613         reset refs/tags/O3-3rd
1614         from :5
1615         INPUT_END
1616
1617         cat >expect <<-INPUT_END &&
1618         string
1619         of
1620         empty
1621         commits
1622         INPUT_END
1623
1624         git fast-import <input &&
1625         test 8 = $(find .git/objects/pack -type f | grep -v multi-pack-index | wc -l) &&
1626         test $(git rev-parse refs/tags/O3-2nd) = $(git rev-parse O3^) &&
1627         git log --reverse --pretty=oneline O3 | sed s/^.*z// >actual &&
1628         test_cmp expect actual
1629 '
1630
1631 test_expect_success 'O: progress outputs as requested by input' '
1632         cat >input <<-INPUT_END &&
1633         commit refs/heads/O4
1634         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1635         data <<COMMIT
1636         zstring
1637         COMMIT
1638         commit refs/heads/O4
1639         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1640         data <<COMMIT
1641         zof
1642         COMMIT
1643         progress Two commits down, 2 to go!
1644         commit refs/heads/O4
1645         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1646         data <<COMMIT
1647         zempty
1648         COMMIT
1649         progress Three commits down, 1 to go!
1650         commit refs/heads/O4
1651         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1652         data <<COMMIT
1653         zcommits
1654         COMMIT
1655         progress done!
1656         INPUT_END
1657         git fast-import <input >actual &&
1658         grep "progress " <input >expect &&
1659         test_cmp expect actual
1660 '
1661
1662 ###
1663 ### series P (gitlinks)
1664 ###
1665
1666 test_expect_success 'P: superproject & submodule mix' '
1667         cat >input <<-INPUT_END &&
1668         blob
1669         mark :1
1670         data 10
1671         test file
1672
1673         reset refs/heads/sub
1674         commit refs/heads/sub
1675         mark :2
1676         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1677         data 12
1678         sub_initial
1679         M 100644 :1 file
1680
1681         blob
1682         mark :3
1683         data <<DATAEND
1684         [submodule "sub"]
1685                 path = sub
1686                 url = "$(pwd)/sub"
1687         DATAEND
1688
1689         commit refs/heads/subuse1
1690         mark :4
1691         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1692         data 8
1693         initial
1694         from refs/heads/master
1695         M 100644 :3 .gitmodules
1696         M 160000 :2 sub
1697
1698         blob
1699         mark :5
1700         data 20
1701         test file
1702         more data
1703
1704         commit refs/heads/sub
1705         mark :6
1706         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1707         data 11
1708         sub_second
1709         from :2
1710         M 100644 :5 file
1711
1712         commit refs/heads/subuse1
1713         mark :7
1714         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1715         data 7
1716         second
1717         from :4
1718         M 160000 :6 sub
1719
1720         INPUT_END
1721
1722         git fast-import <input &&
1723         git checkout subuse1 &&
1724         rm -rf sub &&
1725         mkdir sub &&
1726         (
1727                 cd sub &&
1728                 git init &&
1729                 git fetch --update-head-ok .. refs/heads/sub:refs/heads/master &&
1730                 git checkout master
1731         ) &&
1732         git submodule init &&
1733         git submodule update
1734 '
1735
1736 test_expect_success 'P: verbatim SHA gitlinks' '
1737         SUBLAST=$(git rev-parse --verify sub) &&
1738         SUBPREV=$(git rev-parse --verify sub^) &&
1739
1740         cat >input <<-INPUT_END &&
1741         blob
1742         mark :1
1743         data <<DATAEND
1744         [submodule "sub"]
1745                 path = sub
1746                 url = "$(pwd)/sub"
1747         DATAEND
1748
1749         commit refs/heads/subuse2
1750         mark :2
1751         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1752         data 8
1753         initial
1754         from refs/heads/master
1755         M 100644 :1 .gitmodules
1756         M 160000 $SUBPREV sub
1757
1758         commit refs/heads/subuse2
1759         mark :3
1760         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1761         data 7
1762         second
1763         from :2
1764         M 160000 $SUBLAST sub
1765
1766         INPUT_END
1767
1768         git branch -D sub &&
1769         git gc &&
1770         git prune &&
1771         git fast-import <input &&
1772         test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)
1773 '
1774
1775 test_expect_success 'P: fail on inline gitlink' '
1776         test_tick &&
1777         cat >input <<-INPUT_END &&
1778         commit refs/heads/subuse3
1779         mark :1
1780         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1781         data <<COMMIT
1782         corrupt
1783         COMMIT
1784
1785         from refs/heads/subuse2
1786         M 160000 inline sub
1787         data <<DATA
1788         $SUBPREV
1789         DATA
1790
1791         INPUT_END
1792
1793         test_must_fail git fast-import <input
1794 '
1795
1796 test_expect_success 'P: fail on blob mark in gitlink' '
1797         test_tick &&
1798         cat >input <<-INPUT_END &&
1799         blob
1800         mark :1
1801         data <<DATA
1802         $SUBPREV
1803         DATA
1804
1805         commit refs/heads/subuse3
1806         mark :2
1807         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1808         data <<COMMIT
1809         corrupt
1810         COMMIT
1811
1812         from refs/heads/subuse2
1813         M 160000 :1 sub
1814
1815         INPUT_END
1816
1817         test_must_fail git fast-import <input
1818 '
1819
1820 ###
1821 ### series Q (notes)
1822 ###
1823
1824 test_expect_success 'Q: commit notes' '
1825         note1_data="The first note for the first commit" &&
1826         note2_data="The first note for the second commit" &&
1827         note3_data="The first note for the third commit" &&
1828         note1b_data="The second note for the first commit" &&
1829         note1c_data="The third note for the first commit" &&
1830         note2b_data="The second note for the second commit" &&
1831
1832         test_tick &&
1833         cat >input <<-INPUT_END &&
1834         blob
1835         mark :2
1836         data <<EOF
1837         $file2_data
1838         EOF
1839
1840         commit refs/heads/notes-test
1841         mark :3
1842         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1843         data <<COMMIT
1844         first (:3)
1845         COMMIT
1846
1847         M 644 :2 file2
1848
1849         blob
1850         mark :4
1851         data $file4_len
1852         $file4_data
1853         commit refs/heads/notes-test
1854         mark :5
1855         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1856         data <<COMMIT
1857         second (:5)
1858         COMMIT
1859
1860         M 644 :4 file4
1861
1862         commit refs/heads/notes-test
1863         mark :6
1864         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1865         data <<COMMIT
1866         third (:6)
1867         COMMIT
1868
1869         M 644 inline file5
1870         data <<EOF
1871         $file5_data
1872         EOF
1873
1874         M 755 inline file6
1875         data <<EOF
1876         $file6_data
1877         EOF
1878
1879         blob
1880         mark :7
1881         data <<EOF
1882         $note1_data
1883         EOF
1884
1885         blob
1886         mark :8
1887         data <<EOF
1888         $note2_data
1889         EOF
1890
1891         commit refs/notes/foobar
1892         mark :9
1893         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1894         data <<COMMIT
1895         notes (:9)
1896         COMMIT
1897
1898         N :7 :3
1899         N :8 :5
1900         N inline :6
1901         data <<EOF
1902         $note3_data
1903         EOF
1904
1905         commit refs/notes/foobar
1906         mark :10
1907         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1908         data <<COMMIT
1909         notes (:10)
1910         COMMIT
1911
1912         N inline :3
1913         data <<EOF
1914         $note1b_data
1915         EOF
1916
1917         commit refs/notes/foobar2
1918         mark :11
1919         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1920         data <<COMMIT
1921         notes (:11)
1922         COMMIT
1923
1924         N inline :3
1925         data <<EOF
1926         $note1c_data
1927         EOF
1928
1929         commit refs/notes/foobar
1930         mark :12
1931         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1932         data <<COMMIT
1933         notes (:12)
1934         COMMIT
1935
1936         deleteall
1937         N inline :5
1938         data <<EOF
1939         $note2b_data
1940         EOF
1941
1942         INPUT_END
1943
1944         git fast-import <input &&
1945         git whatchanged notes-test
1946 '
1947
1948 test_expect_success 'Q: verify pack' '
1949         verify_packs
1950 '
1951
1952 test_expect_success 'Q: verify first commit' '
1953         commit1=$(git rev-parse notes-test~2) &&
1954         commit2=$(git rev-parse notes-test^) &&
1955         commit3=$(git rev-parse notes-test) &&
1956
1957         cat >expect <<-EOF &&
1958         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1959         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1960
1961         first (:3)
1962         EOF
1963         git cat-file commit notes-test~2 | sed 1d >actual &&
1964         test_cmp expect actual
1965 '
1966
1967 test_expect_success 'Q: verify second commit' '
1968         cat >expect <<-EOF &&
1969         parent $commit1
1970         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1971         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1972
1973         second (:5)
1974         EOF
1975         git cat-file commit notes-test^ | sed 1d >actual &&
1976         test_cmp expect actual
1977 '
1978
1979 test_expect_success 'Q: verify third commit' '
1980         cat >expect <<-EOF &&
1981         parent $commit2
1982         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1983         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1984
1985         third (:6)
1986         EOF
1987         git cat-file commit notes-test | sed 1d >actual &&
1988         test_cmp expect actual
1989 '
1990
1991 test_expect_success 'Q: verify first notes commit' '
1992         cat >expect <<-EOF &&
1993         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1994         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1995
1996         notes (:9)
1997         EOF
1998         git cat-file commit refs/notes/foobar~2 | sed 1d >actual &&
1999         test_cmp expect actual
2000 '
2001
2002 test_expect_success 'Q: verify first notes tree' '
2003         cat >expect.unsorted <<-EOF &&
2004         100644 blob $commit1
2005         100644 blob $commit2
2006         100644 blob $commit3
2007         EOF
2008         cat expect.unsorted | sort >expect &&
2009         git cat-file -p refs/notes/foobar~2^{tree} | sed "s/ [0-9a-f]*  / /" >actual &&
2010         test_cmp expect actual
2011 '
2012
2013 test_expect_success 'Q: verify first note for first commit' '
2014         echo "$note1_data" >expect &&
2015         git cat-file blob refs/notes/foobar~2:$commit1 >actual &&
2016         test_cmp expect actual
2017 '
2018
2019 test_expect_success 'Q: verify first note for second commit' '
2020         echo "$note2_data" >expect &&
2021         git cat-file blob refs/notes/foobar~2:$commit2 >actual &&
2022         test_cmp expect actual
2023 '
2024
2025 test_expect_success 'Q: verify first note for third commit' '
2026         echo "$note3_data" >expect &&
2027         git cat-file blob refs/notes/foobar~2:$commit3 >actual &&
2028         test_cmp expect actual
2029 '
2030
2031 test_expect_success 'Q: verify second notes commit' '
2032         cat >expect <<-EOF &&
2033         parent $(git rev-parse --verify refs/notes/foobar~2)
2034         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2035         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2036
2037         notes (:10)
2038         EOF
2039         git cat-file commit refs/notes/foobar^ | sed 1d >actual &&
2040         test_cmp expect actual
2041 '
2042
2043 test_expect_success 'Q: verify second notes tree' '
2044         cat >expect.unsorted <<-EOF &&
2045         100644 blob $commit1
2046         100644 blob $commit2
2047         100644 blob $commit3
2048         EOF
2049         cat expect.unsorted | sort >expect &&
2050         git cat-file -p refs/notes/foobar^^{tree} | sed "s/ [0-9a-f]*   / /" >actual &&
2051         test_cmp expect actual
2052 '
2053
2054 test_expect_success 'Q: verify second note for first commit' '
2055         echo "$note1b_data" >expect &&
2056         git cat-file blob refs/notes/foobar^:$commit1 >actual &&
2057         test_cmp expect actual
2058 '
2059
2060 test_expect_success 'Q: verify first note for second commit' '
2061         echo "$note2_data" >expect &&
2062         git cat-file blob refs/notes/foobar^:$commit2 >actual &&
2063         test_cmp expect actual
2064 '
2065
2066 test_expect_success 'Q: verify first note for third commit' '
2067         echo "$note3_data" >expect &&
2068         git cat-file blob refs/notes/foobar^:$commit3 >actual &&
2069         test_cmp expect actual
2070 '
2071
2072 test_expect_success 'Q: verify third notes commit' '
2073         cat >expect <<-EOF &&
2074         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2075         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2076
2077         notes (:11)
2078         EOF
2079         git cat-file commit refs/notes/foobar2 | sed 1d >actual &&
2080         test_cmp expect actual
2081 '
2082
2083 test_expect_success 'Q: verify third notes tree' '
2084         cat >expect.unsorted <<-EOF &&
2085         100644 blob $commit1
2086         EOF
2087         cat expect.unsorted | sort >expect &&
2088         git cat-file -p refs/notes/foobar2^{tree} | sed "s/ [0-9a-f]*   / /" >actual &&
2089         test_cmp expect actual
2090 '
2091
2092 test_expect_success 'Q: verify third note for first commit' '
2093         echo "$note1c_data" >expect &&
2094         git cat-file blob refs/notes/foobar2:$commit1 >actual &&
2095         test_cmp expect actual
2096 '
2097
2098 test_expect_success 'Q: verify fourth notes commit' '
2099         cat >expect <<-EOF &&
2100         parent $(git rev-parse --verify refs/notes/foobar^)
2101         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2102         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2103
2104         notes (:12)
2105         EOF
2106         git cat-file commit refs/notes/foobar | sed 1d >actual &&
2107         test_cmp expect actual
2108 '
2109
2110 test_expect_success 'Q: verify fourth notes tree' '
2111         cat >expect.unsorted <<-EOF &&
2112         100644 blob $commit2
2113         EOF
2114         cat expect.unsorted | sort >expect &&
2115         git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]*    / /" >actual &&
2116         test_cmp expect actual
2117 '
2118
2119 test_expect_success 'Q: verify second note for second commit' '
2120         echo "$note2b_data" >expect &&
2121         git cat-file blob refs/notes/foobar:$commit2 >actual &&
2122         test_cmp expect actual
2123 '
2124
2125 test_expect_success 'Q: deny note on empty branch' '
2126         cat >input <<-EOF &&
2127         reset refs/heads/Q0
2128
2129         commit refs/heads/note-Q0
2130         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2131         data <<COMMIT
2132         Note for an empty branch.
2133         COMMIT
2134
2135         N inline refs/heads/Q0
2136         data <<NOTE
2137         some note
2138         NOTE
2139         EOF
2140         test_must_fail git fast-import <input
2141 '
2142 ###
2143 ### series R (feature and option)
2144 ###
2145
2146 test_expect_success 'R: abort on unsupported feature' '
2147         cat >input <<-EOF &&
2148         feature no-such-feature-exists
2149         EOF
2150
2151         test_must_fail git fast-import <input
2152 '
2153
2154 test_expect_success 'R: supported feature is accepted' '
2155         cat >input <<-EOF &&
2156         feature date-format=now
2157         EOF
2158
2159         git fast-import <input
2160 '
2161
2162 test_expect_success 'R: abort on receiving feature after data command' '
2163         cat >input <<-EOF &&
2164         blob
2165         data 3
2166         hi
2167         feature date-format=now
2168         EOF
2169
2170         test_must_fail git fast-import <input
2171 '
2172
2173 test_expect_success 'R: import-marks features forbidden by default' '
2174         >git.marks &&
2175         echo "feature import-marks=git.marks" >input &&
2176         test_must_fail git fast-import <input &&
2177         echo "feature import-marks-if-exists=git.marks" >input &&
2178         test_must_fail git fast-import <input
2179 '
2180
2181 test_expect_success 'R: only one import-marks feature allowed per stream' '
2182         >git.marks &&
2183         >git2.marks &&
2184         cat >input <<-EOF &&
2185         feature import-marks=git.marks
2186         feature import-marks=git2.marks
2187         EOF
2188
2189         test_must_fail git fast-import --allow-unsafe-features <input
2190 '
2191
2192 test_expect_success 'R: export-marks feature forbidden by default' '
2193         echo "feature export-marks=git.marks" >input &&
2194         test_must_fail git fast-import <input
2195 '
2196
2197 test_expect_success 'R: export-marks feature results in a marks file being created' '
2198         cat >input <<-EOF &&
2199         feature export-marks=git.marks
2200         blob
2201         mark :1
2202         data 3
2203         hi
2204
2205         EOF
2206
2207         git fast-import --allow-unsafe-features <input &&
2208         grep :1 git.marks
2209 '
2210
2211 test_expect_success 'R: export-marks options can be overridden by commandline options' '
2212         cat >input <<-\EOF &&
2213         feature export-marks=feature-sub/git.marks
2214         blob
2215         mark :1
2216         data 3
2217         hi
2218
2219         EOF
2220         git fast-import --allow-unsafe-features \
2221                         --export-marks=cmdline-sub/other.marks <input &&
2222         grep :1 cmdline-sub/other.marks &&
2223         test_path_is_missing feature-sub
2224 '
2225
2226 test_expect_success 'R: catch typo in marks file name' '
2227         test_must_fail git fast-import --import-marks=nonexistent.marks </dev/null &&
2228         echo "feature import-marks=nonexistent.marks" |
2229         test_must_fail git fast-import --allow-unsafe-features
2230 '
2231
2232 test_expect_success 'R: import and output marks can be the same file' '
2233         rm -f io.marks &&
2234         blob=$(echo hi | git hash-object --stdin) &&
2235         cat >expect <<-EOF &&
2236         :1 $blob
2237         :2 $blob
2238         EOF
2239         git fast-import --export-marks=io.marks <<-\EOF &&
2240         blob
2241         mark :1
2242         data 3
2243         hi
2244
2245         EOF
2246         git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF &&
2247         blob
2248         mark :2
2249         data 3
2250         hi
2251
2252         EOF
2253         test_cmp expect io.marks
2254 '
2255
2256 test_expect_success 'R: --import-marks=foo --output-marks=foo to create foo fails' '
2257         rm -f io.marks &&
2258         test_must_fail git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF
2259         blob
2260         mark :1
2261         data 3
2262         hi
2263
2264         EOF
2265 '
2266
2267 test_expect_success 'R: --import-marks-if-exists' '
2268         rm -f io.marks &&
2269         blob=$(echo hi | git hash-object --stdin) &&
2270         echo ":1 $blob" >expect &&
2271         git fast-import --import-marks-if-exists=io.marks --export-marks=io.marks <<-\EOF &&
2272         blob
2273         mark :1
2274         data 3
2275         hi
2276
2277         EOF
2278         test_cmp expect io.marks
2279 '
2280
2281 test_expect_success 'R: feature import-marks-if-exists' '
2282         rm -f io.marks &&
2283
2284         git fast-import --export-marks=io.marks \
2285                         --allow-unsafe-features <<-\EOF &&
2286         feature import-marks-if-exists=not_io.marks
2287         EOF
2288         test_must_be_empty io.marks &&
2289
2290         blob=$(echo hi | git hash-object --stdin) &&
2291
2292         echo ":1 $blob" >io.marks &&
2293         echo ":1 $blob" >expect &&
2294         echo ":2 $blob" >>expect &&
2295
2296         git fast-import --export-marks=io.marks \
2297                         --allow-unsafe-features <<-\EOF &&
2298         feature import-marks-if-exists=io.marks
2299         blob
2300         mark :2
2301         data 3
2302         hi
2303
2304         EOF
2305         test_cmp expect io.marks &&
2306
2307         echo ":3 $blob" >>expect &&
2308
2309         git fast-import --import-marks=io.marks \
2310                         --export-marks=io.marks \
2311                         --allow-unsafe-features <<-\EOF &&
2312         feature import-marks-if-exists=not_io.marks
2313         blob
2314         mark :3
2315         data 3
2316         hi
2317
2318         EOF
2319         test_cmp expect io.marks &&
2320
2321         git fast-import --import-marks-if-exists=not_io.marks \
2322                         --export-marks=io.marks \
2323                         --allow-unsafe-features <<-\EOF &&
2324         feature import-marks-if-exists=io.marks
2325         EOF
2326         test_must_be_empty io.marks
2327 '
2328
2329 test_expect_success 'R: import to output marks works without any content' '
2330         cat >input <<-EOF &&
2331         feature import-marks=marks.out
2332         feature export-marks=marks.new
2333         EOF
2334
2335         git fast-import --allow-unsafe-features <input &&
2336         test_cmp marks.out marks.new
2337 '
2338
2339 test_expect_success 'R: import marks prefers commandline marks file over the stream' '
2340         cat >input <<-EOF &&
2341         feature import-marks=nonexistent.marks
2342         feature export-marks=marks.new
2343         EOF
2344
2345         git fast-import --import-marks=marks.out --allow-unsafe-features <input &&
2346         test_cmp marks.out marks.new
2347 '
2348
2349
2350 test_expect_success 'R: multiple --import-marks= should be honoured' '
2351         cat >input <<-EOF &&
2352         feature import-marks=nonexistent.marks
2353         feature export-marks=combined.marks
2354         EOF
2355
2356         head -n2 marks.out > one.marks &&
2357         tail -n +3 marks.out > two.marks &&
2358         git fast-import --import-marks=one.marks --import-marks=two.marks \
2359                 --allow-unsafe-features <input &&
2360         test_cmp marks.out combined.marks
2361 '
2362
2363 test_expect_success 'R: feature relative-marks should be honoured' '
2364         cat >input <<-EOF &&
2365         feature relative-marks
2366         feature import-marks=relative.in
2367         feature export-marks=relative.out
2368         EOF
2369
2370         mkdir -p .git/info/fast-import/ &&
2371         cp marks.new .git/info/fast-import/relative.in &&
2372         git fast-import --allow-unsafe-features <input &&
2373         test_cmp marks.new .git/info/fast-import/relative.out
2374 '
2375
2376 test_expect_success 'R: feature no-relative-marks should be honoured' '
2377         cat >input <<-EOF &&
2378         feature relative-marks
2379         feature import-marks=relative.in
2380         feature no-relative-marks
2381         feature export-marks=non-relative.out
2382         EOF
2383
2384         git fast-import --allow-unsafe-features <input &&
2385         test_cmp marks.new non-relative.out
2386 '
2387
2388 test_expect_success 'R: feature ls supported' '
2389         echo "feature ls" |
2390         git fast-import
2391 '
2392
2393 test_expect_success 'R: feature cat-blob supported' '
2394         echo "feature cat-blob" |
2395         git fast-import
2396 '
2397
2398 test_expect_success 'R: cat-blob-fd must be a nonnegative integer' '
2399         test_must_fail git fast-import --cat-blob-fd=-1 </dev/null
2400 '
2401
2402 test_expect_success !MINGW 'R: print old blob' '
2403         blob=$(echo "yes it can" | git hash-object -w --stdin) &&
2404         cat >expect <<-EOF &&
2405         ${blob} blob 11
2406         yes it can
2407
2408         EOF
2409         echo "cat-blob $blob" |
2410         git fast-import --cat-blob-fd=6 6>actual &&
2411         test_cmp expect actual
2412 '
2413
2414 test_expect_success !MINGW 'R: in-stream cat-blob-fd not respected' '
2415         echo hello >greeting &&
2416         blob=$(git hash-object -w greeting) &&
2417         cat >expect <<-EOF &&
2418         ${blob} blob 6
2419         hello
2420
2421         EOF
2422         git fast-import --cat-blob-fd=3 3>actual.3 >actual.1 <<-EOF &&
2423         cat-blob $blob
2424         EOF
2425         test_cmp expect actual.3 &&
2426         test_must_be_empty actual.1 &&
2427         git fast-import 3>actual.3 >actual.1 <<-EOF &&
2428         option cat-blob-fd=3
2429         cat-blob $blob
2430         EOF
2431         test_must_be_empty actual.3 &&
2432         test_cmp expect actual.1
2433 '
2434
2435 test_expect_success !MINGW 'R: print mark for new blob' '
2436         echo "effluentish" | git hash-object --stdin >expect &&
2437         git fast-import --cat-blob-fd=6 6>actual <<-\EOF &&
2438         blob
2439         mark :1
2440         data <<BLOB_END
2441         effluentish
2442         BLOB_END
2443         get-mark :1
2444         EOF
2445         test_cmp expect actual
2446 '
2447
2448 test_expect_success !MINGW 'R: print new blob' '
2449         blob=$(echo "yep yep yep" | git hash-object --stdin) &&
2450         cat >expect <<-EOF &&
2451         ${blob} blob 12
2452         yep yep yep
2453
2454         EOF
2455         git fast-import --cat-blob-fd=6 6>actual <<-\EOF &&
2456         blob
2457         mark :1
2458         data <<BLOB_END
2459         yep yep yep
2460         BLOB_END
2461         cat-blob :1
2462         EOF
2463         test_cmp expect actual
2464 '
2465
2466 test_expect_success !MINGW 'R: print new blob by sha1' '
2467         blob=$(echo "a new blob named by sha1" | git hash-object --stdin) &&
2468         cat >expect <<-EOF &&
2469         ${blob} blob 25
2470         a new blob named by sha1
2471
2472         EOF
2473         git fast-import --cat-blob-fd=6 6>actual <<-EOF &&
2474         blob
2475         data <<BLOB_END
2476         a new blob named by sha1
2477         BLOB_END
2478         cat-blob $blob
2479         EOF
2480         test_cmp expect actual
2481 '
2482
2483 test_expect_success 'setup: big file' '
2484         (
2485                 echo "the quick brown fox jumps over the lazy dog" >big &&
2486                 for i in 1 2 3
2487                 do
2488                         cat big big big big >bigger &&
2489                         cat bigger bigger bigger bigger >big ||
2490                         exit
2491                 done
2492         )
2493 '
2494
2495 test_expect_success 'R: print two blobs to stdout' '
2496         blob1=$(git hash-object big) &&
2497         blob1_len=$(wc -c <big) &&
2498         blob2=$(echo hello | git hash-object --stdin) &&
2499         {
2500                 echo ${blob1} blob $blob1_len &&
2501                 cat big &&
2502                 cat <<-EOF
2503
2504                 ${blob2} blob 6
2505                 hello
2506
2507                 EOF
2508         } >expect &&
2509         {
2510                 cat <<-\END_PART1 &&
2511                         blob
2512                         mark :1
2513                         data <<data_end
2514                 END_PART1
2515                 cat big &&
2516                 cat <<-\EOF
2517                         data_end
2518                         blob
2519                         mark :2
2520                         data <<data_end
2521                         hello
2522                         data_end
2523                         cat-blob :1
2524                         cat-blob :2
2525                 EOF
2526         } |
2527         git fast-import >actual &&
2528         test_cmp expect actual
2529 '
2530
2531 test_expect_success PIPE 'R: copy using cat-file' '
2532         expect_id=$(git hash-object big) &&
2533         expect_len=$(wc -c <big) &&
2534         echo $expect_id blob $expect_len >expect.response &&
2535
2536         rm -f blobs &&
2537
2538         mkfifo blobs &&
2539         (
2540                 export GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE &&
2541                 cat <<-\EOF &&
2542                 feature cat-blob
2543                 blob
2544                 mark :1
2545                 data <<BLOB
2546                 EOF
2547                 cat big &&
2548                 cat <<-\EOF &&
2549                 BLOB
2550                 cat-blob :1
2551                 EOF
2552
2553                 read blob_id type size <&3 &&
2554                 echo "$blob_id $type $size" >response &&
2555                 test_copy_bytes $size >blob <&3 &&
2556                 read newline <&3 &&
2557
2558                 cat <<-EOF &&
2559                 commit refs/heads/copied
2560                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2561                 data <<COMMIT
2562                 copy big file as file3
2563                 COMMIT
2564                 M 644 inline file3
2565                 data <<BLOB
2566                 EOF
2567                 cat blob &&
2568                 echo BLOB
2569         ) 3<blobs |
2570         git fast-import --cat-blob-fd=3 3>blobs &&
2571         git show copied:file3 >actual &&
2572         test_cmp expect.response response &&
2573         test_cmp big actual
2574 '
2575
2576 test_expect_success PIPE 'R: print blob mid-commit' '
2577         rm -f blobs &&
2578         echo "A blob from _before_ the commit." >expect &&
2579         mkfifo blobs &&
2580         (
2581                 exec 3<blobs &&
2582                 cat <<-EOF &&
2583                 feature cat-blob
2584                 blob
2585                 mark :1
2586                 data <<BLOB
2587                 A blob from _before_ the commit.
2588                 BLOB
2589                 commit refs/heads/temporary
2590                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2591                 data <<COMMIT
2592                 Empty commit
2593                 COMMIT
2594                 cat-blob :1
2595                 EOF
2596
2597                 read blob_id type size <&3 &&
2598                 test_copy_bytes $size >actual <&3 &&
2599                 read newline <&3 &&
2600
2601                 echo
2602         ) |
2603         git fast-import --cat-blob-fd=3 3>blobs &&
2604         test_cmp expect actual
2605 '
2606
2607 test_expect_success PIPE 'R: print staged blob within commit' '
2608         rm -f blobs &&
2609         echo "A blob from _within_ the commit." >expect &&
2610         mkfifo blobs &&
2611         (
2612                 exec 3<blobs &&
2613                 cat <<-EOF &&
2614                 feature cat-blob
2615                 commit refs/heads/within
2616                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2617                 data <<COMMIT
2618                 Empty commit
2619                 COMMIT
2620                 M 644 inline within
2621                 data <<BLOB
2622                 A blob from _within_ the commit.
2623                 BLOB
2624                 EOF
2625
2626                 to_get=$(
2627                         echo "A blob from _within_ the commit." |
2628                         git hash-object --stdin
2629                 ) &&
2630                 echo "cat-blob $to_get" &&
2631
2632                 read blob_id type size <&3 &&
2633                 test_copy_bytes $size >actual <&3 &&
2634                 read newline <&3 &&
2635
2636                 echo deleteall
2637         ) |
2638         git fast-import --cat-blob-fd=3 3>blobs &&
2639         test_cmp expect actual
2640 '
2641
2642 test_expect_success 'R: quiet option results in no stats being output' '
2643         cat >input <<-EOF &&
2644         option git quiet
2645         blob
2646         data 3
2647         hi
2648
2649         EOF
2650
2651         git fast-import 2>output <input &&
2652         test_must_be_empty output
2653 '
2654
2655 test_expect_success 'R: feature done means terminating "done" is mandatory' '
2656         echo feature done | test_must_fail git fast-import &&
2657         test_must_fail git fast-import --done </dev/null
2658 '
2659
2660 test_expect_success 'R: terminating "done" with trailing gibberish is ok' '
2661         git fast-import <<-\EOF &&
2662         feature done
2663         done
2664         trailing gibberish
2665         EOF
2666         git fast-import <<-\EOF
2667         done
2668         more trailing gibberish
2669         EOF
2670 '
2671
2672 test_expect_success 'R: terminating "done" within commit' '
2673         cat >expect <<-\EOF &&
2674         OBJID
2675         :000000 100644 OBJID OBJID A    hello.c
2676         :000000 100644 OBJID OBJID A    hello2.c
2677         EOF
2678         git fast-import <<-EOF &&
2679         commit refs/heads/done-ends
2680         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2681         data <<EOT
2682         Commit terminated by "done" command
2683         EOT
2684         M 100644 inline hello.c
2685         data <<EOT
2686         Hello, world.
2687         EOT
2688         C hello.c hello2.c
2689         done
2690         EOF
2691         git rev-list done-ends |
2692         git diff-tree -r --stdin --root --always |
2693         sed -e "s/$OID_REGEX/OBJID/g" >actual &&
2694         test_cmp expect actual
2695 '
2696
2697 test_expect_success 'R: die on unknown option' '
2698         cat >input <<-EOF &&
2699         option git non-existing-option
2700         EOF
2701
2702         test_must_fail git fast-import <input
2703 '
2704
2705 test_expect_success 'R: unknown commandline options are rejected' '\
2706         test_must_fail git fast-import --non-existing-option < /dev/null
2707 '
2708
2709 test_expect_success 'R: die on invalid option argument' '
2710         echo "option git active-branches=-5" |
2711         test_must_fail git fast-import &&
2712         echo "option git depth=" |
2713         test_must_fail git fast-import &&
2714         test_must_fail git fast-import --depth="5 elephants" </dev/null
2715 '
2716
2717 test_expect_success 'R: ignore non-git options' '
2718         cat >input <<-EOF &&
2719         option non-existing-vcs non-existing-option
2720         EOF
2721
2722         git fast-import <input
2723 '
2724
2725 test_expect_success 'R: corrupt lines do not mess marks file' '
2726         rm -f io.marks &&
2727         blob=$(echo hi | git hash-object --stdin) &&
2728         cat >expect <<-EOF &&
2729         :3 0000000000000000000000000000000000000000
2730         :1 $blob
2731         :2 $blob
2732         EOF
2733         cp expect io.marks &&
2734         test_must_fail git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF &&
2735
2736         EOF
2737         test_cmp expect io.marks
2738 '
2739
2740 ##
2741 ## R: very large blobs
2742 ##
2743 test_expect_success 'R: blob bigger than threshold' '
2744         blobsize=$((2*1024*1024 + 53)) &&
2745         test-tool genrandom bar $blobsize >expect &&
2746         cat >input <<-INPUT_END &&
2747         commit refs/heads/big-file
2748         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2749         data <<COMMIT
2750         R - big file
2751         COMMIT
2752
2753         M 644 inline big1
2754         data $blobsize
2755         INPUT_END
2756         cat expect >>input &&
2757         cat >>input <<-INPUT_END &&
2758         M 644 inline big2
2759         data $blobsize
2760         INPUT_END
2761         cat expect >>input &&
2762         echo >>input &&
2763
2764         test_create_repo R &&
2765         git --git-dir=R/.git config fastimport.unpackLimit 0 &&
2766         git --git-dir=R/.git fast-import --big-file-threshold=1 <input
2767 '
2768
2769 test_expect_success 'R: verify created pack' '
2770         (
2771                 cd R &&
2772                 verify_packs -v > ../verify
2773         )
2774 '
2775
2776 test_expect_success 'R: verify written objects' '
2777         git --git-dir=R/.git cat-file blob big-file:big1 >actual &&
2778         test_cmp_bin expect actual &&
2779         a=$(git --git-dir=R/.git rev-parse big-file:big1) &&
2780         b=$(git --git-dir=R/.git rev-parse big-file:big2) &&
2781         test $a = $b
2782 '
2783
2784 test_expect_success 'R: blob appears only once' '
2785         n=$(grep $a verify | wc -l) &&
2786         test 1 = $n
2787 '
2788
2789 ###
2790 ### series S
2791 ###
2792 #
2793 # Make sure missing spaces and EOLs after mark references
2794 # cause errors.
2795 #
2796 # Setup:
2797 #
2798 #   1--2--4
2799 #    \   /
2800 #     -3-
2801 #
2802 #   commit marks:  301, 302, 303, 304
2803 #   blob marks:              403, 404, resp.
2804 #   note mark:          202
2805 #
2806 # The error message when a space is missing not at the
2807 # end of the line is:
2808 #
2809 #   Missing space after ..
2810 #
2811 # or when extra characters come after the mark at the end
2812 # of the line:
2813 #
2814 #   Garbage after ..
2815 #
2816 # or when the dataref is neither "inline " or a known SHA1,
2817 #
2818 #   Invalid dataref ..
2819 #
2820 test_expect_success 'S: initialize for S tests' '
2821         test_tick &&
2822
2823         cat >input <<-INPUT_END &&
2824         commit refs/heads/S
2825         mark :301
2826         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2827         data <<COMMIT
2828         commit 1
2829         COMMIT
2830         M 100644 inline hello.c
2831         data <<BLOB
2832         blob 1
2833         BLOB
2834
2835         commit refs/heads/S
2836         mark :302
2837         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2838         data <<COMMIT
2839         commit 2
2840         COMMIT
2841         from :301
2842         M 100644 inline hello.c
2843         data <<BLOB
2844         blob 2
2845         BLOB
2846
2847         blob
2848         mark :403
2849         data <<BLOB
2850         blob 3
2851         BLOB
2852
2853         blob
2854         mark :202
2855         data <<BLOB
2856         note 2
2857         BLOB
2858         INPUT_END
2859
2860         git fast-import --export-marks=marks <input
2861 '
2862
2863 #
2864 # filemodify, three datarefs
2865 #
2866 test_expect_success 'S: filemodify with garbage after mark must fail' '
2867         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2868         commit refs/heads/S
2869         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2870         data <<COMMIT
2871         commit N
2872         COMMIT
2873         M 100644 :403x hello.c
2874         EOF
2875         test_i18ngrep "space after mark" err
2876 '
2877
2878 # inline is misspelled; fast-import thinks it is some unknown dataref
2879 test_expect_success 'S: filemodify with garbage after inline must fail' '
2880         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2881         commit refs/heads/S
2882         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2883         data <<COMMIT
2884         commit N
2885         COMMIT
2886         M 100644 inlineX hello.c
2887         data <<BLOB
2888         inline
2889         BLOB
2890         EOF
2891         test_i18ngrep "nvalid dataref" err
2892 '
2893
2894 test_expect_success 'S: filemodify with garbage after sha1 must fail' '
2895         sha1=$(grep :403 marks | cut -d\  -f2) &&
2896         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2897         commit refs/heads/S
2898         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2899         data <<COMMIT
2900         commit N
2901         COMMIT
2902         M 100644 ${sha1}x hello.c
2903         EOF
2904         test_i18ngrep "space after SHA1" err
2905 '
2906
2907 #
2908 # notemodify, three ways to say dataref
2909 #
2910 test_expect_success 'S: notemodify with garbage after mark dataref must fail' '
2911         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2912         commit refs/heads/S
2913         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2914         data <<COMMIT
2915         commit S note dataref markref
2916         COMMIT
2917         N :202x :302
2918         EOF
2919         test_i18ngrep "space after mark" err
2920 '
2921
2922 test_expect_success 'S: notemodify with garbage after inline dataref must fail' '
2923         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2924         commit refs/heads/S
2925         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2926         data <<COMMIT
2927         commit S note dataref inline
2928         COMMIT
2929         N inlineX :302
2930         data <<BLOB
2931         note blob
2932         BLOB
2933         EOF
2934         test_i18ngrep "nvalid dataref" err
2935 '
2936
2937 test_expect_success 'S: notemodify with garbage after sha1 dataref must fail' '
2938         sha1=$(grep :202 marks | cut -d\  -f2) &&
2939         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2940         commit refs/heads/S
2941         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2942         data <<COMMIT
2943         commit S note dataref sha1
2944         COMMIT
2945         N ${sha1}x :302
2946         EOF
2947         test_i18ngrep "space after SHA1" err
2948 '
2949
2950 #
2951 # notemodify, mark in commit-ish
2952 #
2953 test_expect_success 'S: notemodify with garbage after mark commit-ish must fail' '
2954         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2955         commit refs/heads/Snotes
2956         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2957         data <<COMMIT
2958         commit S note commit-ish
2959         COMMIT
2960         N :202 :302x
2961         EOF
2962         test_i18ngrep "after mark" err
2963 '
2964
2965 #
2966 # from
2967 #
2968 test_expect_success 'S: from with garbage after mark must fail' '
2969         test_must_fail \
2970         git fast-import --import-marks=marks --export-marks=marks <<-EOF 2>err &&
2971         commit refs/heads/S2
2972         mark :303
2973         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2974         data <<COMMIT
2975         commit 3
2976         COMMIT
2977         from :301x
2978         M 100644 :403 hello.c
2979         EOF
2980
2981
2982         # go create the commit, need it for merge test
2983         git fast-import --import-marks=marks --export-marks=marks <<-EOF &&
2984         commit refs/heads/S2
2985         mark :303
2986         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2987         data <<COMMIT
2988         commit 3
2989         COMMIT
2990         from :301
2991         M 100644 :403 hello.c
2992         EOF
2993
2994         # now evaluate the error
2995         test_i18ngrep "after mark" err
2996 '
2997
2998
2999 #
3000 # merge
3001 #
3002 test_expect_success 'S: merge with garbage after mark must fail' '
3003         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
3004         commit refs/heads/S
3005         mark :304
3006         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3007         data <<COMMIT
3008         merge 4
3009         COMMIT
3010         from :302
3011         merge :303x
3012         M 100644 :403 hello.c
3013         EOF
3014         test_i18ngrep "after mark" err
3015 '
3016
3017 #
3018 # tag, from markref
3019 #
3020 test_expect_success 'S: tag with garbage after mark must fail' '
3021         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
3022         tag refs/tags/Stag
3023         from :302x
3024         tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3025         data <<TAG
3026         tag S
3027         TAG
3028         EOF
3029         test_i18ngrep "after mark" err
3030 '
3031
3032 #
3033 # cat-blob markref
3034 #
3035 test_expect_success 'S: cat-blob with garbage after mark must fail' '
3036         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
3037         cat-blob :403x
3038         EOF
3039         test_i18ngrep "after mark" err
3040 '
3041
3042 #
3043 # ls markref
3044 #
3045 test_expect_success 'S: ls with garbage after mark must fail' '
3046         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
3047         ls :302x hello.c
3048         EOF
3049         test_i18ngrep "space after mark" err
3050 '
3051
3052 test_expect_success 'S: ls with garbage after sha1 must fail' '
3053         sha1=$(grep :302 marks | cut -d\  -f2) &&
3054         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
3055         ls ${sha1}x hello.c
3056         EOF
3057         test_i18ngrep "space after tree-ish" err
3058 '
3059
3060 ###
3061 ### series T (ls)
3062 ###
3063 # Setup is carried over from series S.
3064
3065 test_expect_success 'T: ls root tree' '
3066         sed -e "s/Z\$//" >expect <<-EOF &&
3067         040000 tree $(git rev-parse S^{tree})   Z
3068         EOF
3069         sha1=$(git rev-parse --verify S) &&
3070         git fast-import --import-marks=marks <<-EOF >actual &&
3071         ls $sha1 ""
3072         EOF
3073         test_cmp expect actual
3074 '
3075
3076 test_expect_success 'T: delete branch' '
3077         git branch to-delete &&
3078         git fast-import <<-EOF &&
3079         reset refs/heads/to-delete
3080         from 0000000000000000000000000000000000000000
3081         EOF
3082         test_must_fail git rev-parse --verify refs/heads/to-delete
3083 '
3084
3085 test_expect_success 'T: empty reset doesnt delete branch' '
3086         git branch not-to-delete &&
3087         git fast-import <<-EOF &&
3088         reset refs/heads/not-to-delete
3089         EOF
3090         git show-ref &&
3091         git rev-parse --verify refs/heads/not-to-delete
3092 '
3093
3094 ###
3095 ### series U (filedelete)
3096 ###
3097
3098 test_expect_success 'U: initialize for U tests' '
3099         cat >input <<-INPUT_END &&
3100         commit refs/heads/U
3101         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3102         data <<COMMIT
3103         test setup
3104         COMMIT
3105         M 100644 inline hello.c
3106         data <<BLOB
3107         blob 1
3108         BLOB
3109         M 100644 inline good/night.txt
3110         data <<BLOB
3111         sleep well
3112         BLOB
3113         M 100644 inline good/bye.txt
3114         data <<BLOB
3115         au revoir
3116         BLOB
3117
3118         INPUT_END
3119
3120         git fast-import <input
3121 '
3122
3123 test_expect_success 'U: filedelete file succeeds' '
3124         cat >input <<-INPUT_END &&
3125         commit refs/heads/U
3126         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3127         data <<COMMIT
3128         delete good/night.txt
3129         COMMIT
3130         from refs/heads/U^0
3131         D good/night.txt
3132
3133         INPUT_END
3134
3135         git fast-import <input
3136 '
3137
3138 test_expect_success 'U: validate file delete result' '
3139         cat >expect <<-EOF &&
3140         :100644 000000 2907ebb4bf85d91bf0716bb3bd8a68ef48d6da76 0000000000000000000000000000000000000000 D      good/night.txt
3141         EOF
3142
3143         git diff-tree -M -r U^1 U >actual &&
3144
3145         compare_diff_raw expect actual
3146 '
3147
3148 test_expect_success 'U: filedelete directory succeeds' '
3149         cat >input <<-INPUT_END &&
3150         commit refs/heads/U
3151         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3152         data <<COMMIT
3153         delete good dir
3154         COMMIT
3155         from refs/heads/U^0
3156         D good
3157
3158         INPUT_END
3159
3160         git fast-import <input
3161 '
3162
3163 test_expect_success 'U: validate directory delete result' '
3164         cat >expect <<-EOF &&
3165         :100644 000000 69cb75792f55123d8389c156b0b41c2ff00ed507 0000000000000000000000000000000000000000 D      good/bye.txt
3166         EOF
3167
3168         git diff-tree -M -r U^1 U >actual &&
3169
3170         compare_diff_raw expect actual
3171 '
3172
3173 test_expect_success 'U: filedelete root succeeds' '
3174         cat >input <<-INPUT_END &&
3175         commit refs/heads/U
3176         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3177         data <<COMMIT
3178         must succeed
3179         COMMIT
3180         from refs/heads/U^0
3181         D ""
3182
3183         INPUT_END
3184
3185         git fast-import <input
3186 '
3187
3188 test_expect_success 'U: validate root delete result' '
3189         cat >expect <<-EOF &&
3190         :100644 000000 c18147dc648481eeb65dc5e66628429a64843327 0000000000000000000000000000000000000000 D      hello.c
3191         EOF
3192
3193         git diff-tree -M -r U^1 U >actual &&
3194
3195         compare_diff_raw expect actual
3196 '
3197
3198 ###
3199 ### series V (checkpoint)
3200 ###
3201
3202 # The commands in input_file should not produce any output on the file
3203 # descriptor set with --cat-blob-fd (or stdout if unspecified).
3204 #
3205 # To make sure you're observing the side effects of checkpoint *before*
3206 # fast-import terminates (and thus writes out its state), check that the
3207 # fast-import process is still running using background_import_still_running
3208 # *after* evaluating the test conditions.
3209 background_import_then_checkpoint () {
3210         options=$1
3211         input_file=$2
3212
3213         mkfifo V.input
3214         exec 8<>V.input
3215         rm V.input
3216
3217         mkfifo V.output
3218         exec 9<>V.output
3219         rm V.output
3220
3221         (
3222                 git fast-import $options <&8 >&9 &
3223                 echo $! >&9
3224                 wait $!
3225                 echo >&2 "background fast-import terminated too early with exit code $?"
3226                 # Un-block the read loop in the main shell process.
3227                 echo >&9 UNEXPECTED
3228         ) &
3229         sh_pid=$!
3230         read fi_pid <&9
3231         # We don't mind if fast-import has already died by the time the test
3232         # ends.
3233         test_when_finished "
3234                 exec 8>&-; exec 9>&-;
3235                 kill $sh_pid && wait $sh_pid
3236                 kill $fi_pid && wait $fi_pid
3237                 true"
3238
3239         # Start in the background to ensure we adhere strictly to (blocking)
3240         # pipes writing sequence. We want to assume that the write below could
3241         # block, e.g. if fast-import blocks writing its own output to &9
3242         # because there is no reader on &9 yet.
3243         (
3244                 cat "$input_file"
3245                 echo "checkpoint"
3246                 echo "progress checkpoint"
3247         ) >&8 &
3248
3249         error=1 ;# assume the worst
3250         while read output <&9
3251         do
3252                 if test "$output" = "progress checkpoint"
3253                 then
3254                         error=0
3255                         break
3256                 elif test "$output" = "UNEXPECTED"
3257                 then
3258                         break
3259                 fi
3260                 # otherwise ignore cruft
3261                 echo >&2 "cruft: $output"
3262         done
3263
3264         if test $error -eq 1
3265         then
3266                 false
3267         fi
3268 }
3269
3270 background_import_still_running () {
3271         if ! kill -0 "$fi_pid"
3272         then
3273                 echo >&2 "background fast-import terminated too early"
3274                 false
3275         fi
3276 }
3277
3278 test_expect_success PIPE 'V: checkpoint helper does not get stuck with extra output' '
3279         cat >input <<-INPUT_END &&
3280         progress foo
3281         progress bar
3282
3283         INPUT_END
3284
3285         background_import_then_checkpoint "" input &&
3286         background_import_still_running
3287 '
3288
3289 test_expect_success PIPE 'V: checkpoint updates refs after reset' '
3290         cat >input <<-\INPUT_END &&
3291         reset refs/heads/V
3292         from refs/heads/U
3293
3294         INPUT_END
3295
3296         background_import_then_checkpoint "" input &&
3297         test "$(git rev-parse --verify V)" = "$(git rev-parse --verify U)" &&
3298         background_import_still_running
3299 '
3300
3301 test_expect_success PIPE 'V: checkpoint updates refs and marks after commit' '
3302         cat >input <<-INPUT_END &&
3303         commit refs/heads/V
3304         mark :1
3305         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3306         data 0
3307         from refs/heads/U
3308
3309         INPUT_END
3310
3311         background_import_then_checkpoint "--export-marks=marks.actual" input &&
3312
3313         echo ":1 $(git rev-parse --verify V)" >marks.expected &&
3314
3315         test "$(git rev-parse --verify V^)" = "$(git rev-parse --verify U)" &&
3316         test_cmp marks.expected marks.actual &&
3317         background_import_still_running
3318 '
3319
3320 # Re-create the exact same commit, but on a different branch: no new object is
3321 # created in the database, but the refs and marks still need to be updated.
3322 test_expect_success PIPE 'V: checkpoint updates refs and marks after commit (no new objects)' '
3323         cat >input <<-INPUT_END &&
3324         commit refs/heads/V2
3325         mark :2
3326         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3327         data 0
3328         from refs/heads/U
3329
3330         INPUT_END
3331
3332         background_import_then_checkpoint "--export-marks=marks.actual" input &&
3333
3334         echo ":2 $(git rev-parse --verify V2)" >marks.expected &&
3335
3336         test "$(git rev-parse --verify V2)" = "$(git rev-parse --verify V)" &&
3337         test_cmp marks.expected marks.actual &&
3338         background_import_still_running
3339 '
3340
3341 test_expect_success PIPE 'V: checkpoint updates tags after tag' '
3342         cat >input <<-INPUT_END &&
3343         tag Vtag
3344         from refs/heads/V
3345         tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3346         data 0
3347
3348         INPUT_END
3349
3350         background_import_then_checkpoint "" input &&
3351         git show-ref -d Vtag &&
3352         background_import_still_running
3353 '
3354
3355 ###
3356 ### series W (get-mark and empty orphan commits)
3357 ###
3358
3359 cat >>W-input <<-W_INPUT_END
3360         commit refs/heads/W-branch
3361         mark :1
3362         author Full Name <user@company.tld> 1000000000 +0100
3363         committer Full Name <user@company.tld> 1000000000 +0100
3364         data 27
3365         Intentionally empty commit
3366         LFsget-mark :1
3367         W_INPUT_END
3368
3369 test_expect_success !MINGW 'W: get-mark & empty orphan commit with no newlines' '
3370         sed -e s/LFs// W-input | tr L "\n" | git fast-import
3371 '
3372
3373 test_expect_success !MINGW 'W: get-mark & empty orphan commit with one newline' '
3374         sed -e s/LFs/L/ W-input | tr L "\n" | git fast-import
3375 '
3376
3377 test_expect_success !MINGW 'W: get-mark & empty orphan commit with ugly second newline' '
3378         # Technically, this should fail as it has too many linefeeds
3379         # according to the grammar in fast-import.txt.  But, for whatever
3380         # reason, it works.  Since using the correct number of newlines
3381         # does not work with older (pre-2.22) versions of git, allow apps
3382         # that used this second-newline workaround to keep working by
3383         # checking it with this test...
3384         sed -e s/LFs/LL/ W-input | tr L "\n" | git fast-import
3385 '
3386
3387 test_expect_success !MINGW 'W: get-mark & empty orphan commit with erroneous third newline' '
3388         # ...but do NOT allow more empty lines than that (see previous test).
3389         sed -e s/LFs/LLL/ W-input | tr L "\n" | test_must_fail git fast-import
3390 '
3391
3392 ###
3393 ### series X (other new features)
3394 ###
3395
3396 test_expect_success 'X: handling encoding' '
3397         test_tick &&
3398         cat >input <<-INPUT_END &&
3399         commit refs/heads/encoding
3400         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3401         encoding iso-8859-7
3402         data <<COMMIT
3403         INPUT_END
3404
3405         printf "Pi: \360\nCOMMIT\n" >>input &&
3406
3407         git fast-import <input &&
3408         git cat-file -p encoding | grep $(printf "\360") &&
3409         git log -1 --format=%B encoding | grep $(printf "\317\200")
3410 '
3411
3412 ###
3413 ### series Y (submodules and hash algorithms)
3414 ###
3415
3416 cat >Y-sub-input <<\Y_INPUT_END
3417 blob
3418 mark :1
3419 data 4
3420 foo
3421
3422 reset refs/heads/master
3423 commit refs/heads/master
3424 mark :2
3425 author Full Name <user@company.tld> 1000000000 +0100
3426 committer Full Name <user@company.tld> 1000000000 +0100
3427 data 24
3428 Test submodule commit 1
3429 M 100644 :1 file
3430
3431 blob
3432 mark :3
3433 data 8
3434 foo
3435 bar
3436
3437 commit refs/heads/master
3438 mark :4
3439 author Full Name <user@company.tld> 1000000001 +0100
3440 committer Full Name <user@company.tld> 1000000001 +0100
3441 data 24
3442 Test submodule commit 2
3443 from :2
3444 M 100644 :3 file
3445 Y_INPUT_END
3446
3447 # Note that the submodule object IDs are intentionally not translated.
3448 cat >Y-main-input <<\Y_INPUT_END
3449 blob
3450 mark :1
3451 data 4
3452 foo
3453
3454 reset refs/heads/master
3455 commit refs/heads/master
3456 mark :2
3457 author Full Name <user@company.tld> 2000000000 +0100
3458 committer Full Name <user@company.tld> 2000000000 +0100
3459 data 14
3460 Test commit 1
3461 M 100644 :1 file
3462
3463 blob
3464 mark :3
3465 data 73
3466 [submodule "sub1"]
3467         path = sub1
3468         url = https://void.example.com/main.git
3469
3470 commit refs/heads/master
3471 mark :4
3472 author Full Name <user@company.tld> 2000000001 +0100
3473 committer Full Name <user@company.tld> 2000000001 +0100
3474 data 14
3475 Test commit 2
3476 from :2
3477 M 100644 :3 .gitmodules
3478 M 160000 0712c5be7cf681388e355ef47525aaf23aee1a6d sub1
3479
3480 blob
3481 mark :5
3482 data 8
3483 foo
3484 bar
3485
3486 commit refs/heads/master
3487 mark :6
3488 author Full Name <user@company.tld> 2000000002 +0100
3489 committer Full Name <user@company.tld> 2000000002 +0100
3490 data 14
3491 Test commit 3
3492 from :4
3493 M 100644 :5 file
3494 M 160000 ff729f5e62f72c0c3978207d9a80e5f3a65f14d7 sub1
3495 Y_INPUT_END
3496
3497 cat >Y-marks <<\Y_INPUT_END
3498 :2 0712c5be7cf681388e355ef47525aaf23aee1a6d
3499 :4 ff729f5e62f72c0c3978207d9a80e5f3a65f14d7
3500 Y_INPUT_END
3501
3502 test_expect_success 'Y: setup' '
3503         test_oid_cache <<-EOF
3504         Ymaster sha1:9afed2f9161ddf416c0a1863b8b0725b00070504
3505         Ymaster sha256:c0a1010da1df187b2e287654793df01b464bd6f8e3f17fc1481a7dadf84caee3
3506         EOF
3507 '
3508
3509 test_expect_success 'Y: rewrite submodules' '
3510         git init main1 &&
3511         (
3512                 cd main1 &&
3513                 git init sub2 &&
3514                 git -C sub2 fast-import --export-marks=../sub2-marks <../Y-sub-input &&
3515                 git fast-import --rewrite-submodules-from=sub:../Y-marks \
3516                         --rewrite-submodules-to=sub:sub2-marks <../Y-main-input &&
3517                 test "$(git rev-parse master)" = "$(test_oid Ymaster)"
3518         )
3519 '
3520
3521 test_done