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