Merge branch 'rs/blame-typefix-for-fingerprint'
[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         cat actual &&
1051         compare_diff_raw expect actual
1052 '
1053
1054 ###
1055 ### series N
1056 ###
1057
1058 test_expect_success 'N: copy file in same subdirectory' '
1059         test_tick &&
1060         cat >input <<-INPUT_END &&
1061         commit refs/heads/N1
1062         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1063         data <<COMMIT
1064         file copy
1065         COMMIT
1066
1067         from refs/heads/branch^0
1068         C file2/newf file2/n.e.w.f
1069
1070         INPUT_END
1071
1072         cat >expect <<-EOF &&
1073         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file2/n.e.w.f
1074         EOF
1075         git fast-import <input &&
1076         git diff-tree -C --find-copies-harder -r N1^ N1 >actual &&
1077         compare_diff_raw expect actual
1078 '
1079
1080 test_expect_success 'N: copy then modify subdirectory' '
1081         cat >input <<-INPUT_END &&
1082         commit refs/heads/N2
1083         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1084         data <<COMMIT
1085         clean directory copy
1086         COMMIT
1087
1088         from refs/heads/branch^0
1089         C file2 file3
1090
1091         commit refs/heads/N2
1092         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1093         data <<COMMIT
1094         modify directory copy
1095         COMMIT
1096
1097         M 644 inline file3/file5
1098         data <<EOF
1099         $file5_data
1100         EOF
1101
1102         INPUT_END
1103
1104         cat >expect <<-EOF &&
1105         :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100   newdir/interesting      file3/file5
1106         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
1107         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
1108         EOF
1109         git fast-import <input &&
1110         git diff-tree -C --find-copies-harder -r N2^^ N2 >actual &&
1111         compare_diff_raw expect actual
1112 '
1113
1114 test_expect_success 'N: copy dirty subdirectory' '
1115         cat >input <<-INPUT_END &&
1116         commit refs/heads/N3
1117         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1118         data <<COMMIT
1119         dirty directory copy
1120         COMMIT
1121
1122         from refs/heads/branch^0
1123         M 644 inline file2/file5
1124         data <<EOF
1125         $file5_data
1126         EOF
1127
1128         C file2 file3
1129         D file2/file5
1130
1131         INPUT_END
1132
1133         git fast-import <input &&
1134         test $(git rev-parse N2^{tree}) = $(git rev-parse N3^{tree})
1135 '
1136
1137 test_expect_success 'N: copy directory by id' '
1138         cat >expect <<-\EOF &&
1139         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
1140         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
1141         EOF
1142         subdir=$(git rev-parse refs/heads/branch^0:file2) &&
1143         cat >input <<-INPUT_END &&
1144         commit refs/heads/N4
1145         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1146         data <<COMMIT
1147         copy by tree hash
1148         COMMIT
1149
1150         from refs/heads/branch^0
1151         M 040000 $subdir file3
1152         INPUT_END
1153         git fast-import <input &&
1154         git diff-tree -C --find-copies-harder -r N4^ N4 >actual &&
1155         compare_diff_raw expect actual
1156 '
1157
1158 test_expect_success PIPE 'N: read and copy directory' '
1159         cat >expect <<-\EOF &&
1160         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
1161         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
1162         EOF
1163         git update-ref -d refs/heads/N4 &&
1164         rm -f backflow &&
1165         mkfifo backflow &&
1166         (
1167                 exec <backflow &&
1168                 cat <<-EOF &&
1169                 commit refs/heads/N4
1170                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1171                 data <<COMMIT
1172                 copy by tree hash, part 2
1173                 COMMIT
1174
1175                 from refs/heads/branch^0
1176                 ls "file2"
1177                 EOF
1178                 read mode type tree filename &&
1179                 echo "M 040000 $tree file3"
1180         ) |
1181         git fast-import --cat-blob-fd=3 3>backflow &&
1182         git diff-tree -C --find-copies-harder -r N4^ N4 >actual &&
1183         compare_diff_raw expect actual
1184 '
1185
1186 test_expect_success PIPE 'N: empty directory reads as missing' '
1187         cat <<-\EOF >expect &&
1188         OBJNAME
1189         :000000 100644 OBJNAME OBJNAME A        unrelated
1190         EOF
1191         echo "missing src" >expect.response &&
1192         git update-ref -d refs/heads/read-empty &&
1193         rm -f backflow &&
1194         mkfifo backflow &&
1195         (
1196                 exec <backflow &&
1197                 cat <<-EOF &&
1198                 commit refs/heads/read-empty
1199                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1200                 data <<COMMIT
1201                 read "empty" (missing) directory
1202                 COMMIT
1203
1204                 M 100644 inline src/greeting
1205                 data <<BLOB
1206                 hello
1207                 BLOB
1208                 C src/greeting dst1/non-greeting
1209                 C src/greeting unrelated
1210                 # leave behind "empty" src directory
1211                 D src/greeting
1212                 ls "src"
1213                 EOF
1214                 read -r line &&
1215                 printf "%s\n" "$line" >response &&
1216                 cat <<-\EOF
1217                 D dst1
1218                 D dst2
1219                 EOF
1220         ) |
1221         git fast-import --cat-blob-fd=3 3>backflow &&
1222         test_cmp expect.response response &&
1223         git rev-list read-empty |
1224         git diff-tree -r --root --stdin |
1225         sed "s/$OID_REGEX/OBJNAME/g" >actual &&
1226         test_cmp expect actual
1227 '
1228
1229 test_expect_success 'N: copy root directory by tree hash' '
1230         cat >expect <<-\EOF &&
1231         :100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D      file3/newf
1232         :100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D      file3/oldf
1233         EOF
1234         root=$(git rev-parse refs/heads/branch^0^{tree}) &&
1235         cat >input <<-INPUT_END &&
1236         commit refs/heads/N6
1237         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1238         data <<COMMIT
1239         copy root directory by tree hash
1240         COMMIT
1241
1242         from refs/heads/branch^0
1243         M 040000 $root ""
1244         INPUT_END
1245         git fast-import <input &&
1246         git diff-tree -C --find-copies-harder -r N4 N6 >actual &&
1247         compare_diff_raw expect actual
1248 '
1249
1250 test_expect_success 'N: copy root by path' '
1251         cat >expect <<-\EOF &&
1252         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      oldroot/file2/newf
1253         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      oldroot/file2/oldf
1254         :100755 100755 85df50785d62d3b05ab03d9cbf7e4a0b49449730 85df50785d62d3b05ab03d9cbf7e4a0b49449730 C100   file4   oldroot/file4
1255         :100755 100755 e74b7d465e52746be2b4bae983670711e6e66657 e74b7d465e52746be2b4bae983670711e6e66657 C100   newdir/exec.sh  oldroot/newdir/exec.sh
1256         :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100   newdir/interesting      oldroot/newdir/interesting
1257         EOF
1258         cat >input <<-INPUT_END &&
1259         commit refs/heads/N-copy-root-path
1260         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1261         data <<COMMIT
1262         copy root directory by (empty) path
1263         COMMIT
1264
1265         from refs/heads/branch^0
1266         C "" oldroot
1267         INPUT_END
1268         git fast-import <input &&
1269         git diff-tree -C --find-copies-harder -r branch N-copy-root-path >actual &&
1270         compare_diff_raw expect actual
1271 '
1272
1273 test_expect_success 'N: delete directory by copying' '
1274         cat >expect <<-\EOF &&
1275         OBJID
1276         :100644 000000 OBJID OBJID D    foo/bar/qux
1277         OBJID
1278         :000000 100644 OBJID OBJID A    foo/bar/baz
1279         :000000 100644 OBJID OBJID A    foo/bar/qux
1280         EOF
1281         empty_tree=$(git mktree </dev/null) &&
1282         cat >input <<-INPUT_END &&
1283         commit refs/heads/N-delete
1284         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1285         data <<COMMIT
1286         collect data to be deleted
1287         COMMIT
1288
1289         deleteall
1290         M 100644 inline foo/bar/baz
1291         data <<DATA_END
1292         hello
1293         DATA_END
1294         C "foo/bar/baz" "foo/bar/qux"
1295         C "foo/bar/baz" "foo/bar/quux/1"
1296         C "foo/bar/baz" "foo/bar/quuux"
1297         M 040000 $empty_tree foo/bar/quux
1298         M 040000 $empty_tree foo/bar/quuux
1299
1300         commit refs/heads/N-delete
1301         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1302         data <<COMMIT
1303         delete subdirectory
1304         COMMIT
1305
1306         M 040000 $empty_tree foo/bar/qux
1307         INPUT_END
1308         git fast-import <input &&
1309         git rev-list N-delete |
1310                 git diff-tree -r --stdin --root --always |
1311                 sed -e "s/$OID_REGEX/OBJID/g" >actual &&
1312         test_cmp expect actual
1313 '
1314
1315 test_expect_success 'N: modify copied tree' '
1316         cat >expect <<-\EOF &&
1317         :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100   newdir/interesting      file3/file5
1318         :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
1319         :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
1320         EOF
1321         subdir=$(git rev-parse refs/heads/branch^0:file2) &&
1322         cat >input <<-INPUT_END &&
1323         commit refs/heads/N5
1324         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1325         data <<COMMIT
1326         copy by tree hash
1327         COMMIT
1328
1329         from refs/heads/branch^0
1330         M 040000 $subdir file3
1331
1332         commit refs/heads/N5
1333         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1334         data <<COMMIT
1335         modify directory copy
1336         COMMIT
1337
1338         M 644 inline file3/file5
1339         data <<EOF
1340         $file5_data
1341         EOF
1342         INPUT_END
1343         git fast-import <input &&
1344         git diff-tree -C --find-copies-harder -r N5^^ N5 >actual &&
1345         compare_diff_raw expect actual
1346 '
1347
1348 test_expect_success 'N: reject foo/ syntax' '
1349         subdir=$(git rev-parse refs/heads/branch^0:file2) &&
1350         test_must_fail git fast-import <<-INPUT_END
1351         commit refs/heads/N5B
1352         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1353         data <<COMMIT
1354         copy with invalid syntax
1355         COMMIT
1356
1357         from refs/heads/branch^0
1358         M 040000 $subdir file3/
1359         INPUT_END
1360 '
1361
1362 test_expect_success 'N: reject foo/ syntax in copy source' '
1363         test_must_fail git fast-import <<-INPUT_END
1364         commit refs/heads/N5C
1365         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1366         data <<COMMIT
1367         copy with invalid syntax
1368         COMMIT
1369
1370         from refs/heads/branch^0
1371         C file2/ file3
1372         INPUT_END
1373 '
1374
1375 test_expect_success 'N: reject foo/ syntax in rename source' '
1376         test_must_fail git fast-import <<-INPUT_END
1377         commit refs/heads/N5D
1378         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1379         data <<COMMIT
1380         rename with invalid syntax
1381         COMMIT
1382
1383         from refs/heads/branch^0
1384         R file2/ file3
1385         INPUT_END
1386 '
1387
1388 test_expect_success 'N: reject foo/ syntax in ls argument' '
1389         test_must_fail git fast-import <<-INPUT_END
1390         commit refs/heads/N5E
1391         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1392         data <<COMMIT
1393         copy with invalid syntax
1394         COMMIT
1395
1396         from refs/heads/branch^0
1397         ls "file2/"
1398         INPUT_END
1399 '
1400
1401 test_expect_success 'N: copy to root by id and modify' '
1402         echo "hello, world" >expect.foo &&
1403         echo hello >expect.bar &&
1404         git fast-import <<-SETUP_END &&
1405         commit refs/heads/N7
1406         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1407         data <<COMMIT
1408         hello, tree
1409         COMMIT
1410
1411         deleteall
1412         M 644 inline foo/bar
1413         data <<EOF
1414         hello
1415         EOF
1416         SETUP_END
1417
1418         tree=$(git rev-parse --verify N7:) &&
1419         git fast-import <<-INPUT_END &&
1420         commit refs/heads/N8
1421         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1422         data <<COMMIT
1423         copy to root by id and modify
1424         COMMIT
1425
1426         M 040000 $tree ""
1427         M 644 inline foo/foo
1428         data <<EOF
1429         hello, world
1430         EOF
1431         INPUT_END
1432         git show N8:foo/foo >actual.foo &&
1433         git show N8:foo/bar >actual.bar &&
1434         test_cmp expect.foo actual.foo &&
1435         test_cmp expect.bar actual.bar
1436 '
1437
1438 test_expect_success 'N: extract subtree' '
1439         branch=$(git rev-parse --verify refs/heads/branch^{tree}) &&
1440         cat >input <<-INPUT_END &&
1441         commit refs/heads/N9
1442         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1443         data <<COMMIT
1444         extract subtree branch:newdir
1445         COMMIT
1446
1447         M 040000 $branch ""
1448         C "newdir" ""
1449         INPUT_END
1450         git fast-import <input &&
1451         git diff --exit-code branch:newdir N9
1452 '
1453
1454 test_expect_success 'N: modify subtree, extract it, and modify again' '
1455         echo hello >expect.baz &&
1456         echo hello, world >expect.qux &&
1457         git fast-import <<-SETUP_END &&
1458         commit refs/heads/N10
1459         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1460         data <<COMMIT
1461         hello, tree
1462         COMMIT
1463
1464         deleteall
1465         M 644 inline foo/bar/baz
1466         data <<EOF
1467         hello
1468         EOF
1469         SETUP_END
1470
1471         tree=$(git rev-parse --verify N10:) &&
1472         git fast-import <<-INPUT_END &&
1473         commit refs/heads/N11
1474         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1475         data <<COMMIT
1476         copy to root by id and modify
1477         COMMIT
1478
1479         M 040000 $tree ""
1480         M 100644 inline foo/bar/qux
1481         data <<EOF
1482         hello, world
1483         EOF
1484         R "foo" ""
1485         C "bar/qux" "bar/quux"
1486         INPUT_END
1487         git show N11:bar/baz >actual.baz &&
1488         git show N11:bar/qux >actual.qux &&
1489         git show N11:bar/quux >actual.quux &&
1490         test_cmp expect.baz actual.baz &&
1491         test_cmp expect.qux actual.qux &&
1492         test_cmp expect.qux actual.quux'
1493
1494 ###
1495 ### series O
1496 ###
1497
1498 test_expect_success 'O: comments are all skipped' '
1499         cat >input <<-INPUT_END &&
1500         #we will
1501         commit refs/heads/O1
1502         # -- ignore all of this text
1503         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1504         # $GIT_COMMITTER_NAME has inserted here for his benefit.
1505         data <<COMMIT
1506         dirty directory copy
1507         COMMIT
1508
1509         # do not forget the import blank line!
1510         #
1511         # yes, we started from our usual base of branch^0.
1512         # i like branch^0.
1513         from refs/heads/branch^0
1514         # and we need to reuse file2/file5 from N3 above.
1515         M 644 inline file2/file5
1516         # otherwise the tree will be different
1517         data <<EOF
1518         $file5_data
1519         EOF
1520
1521         # do not forget to copy file2 to file3
1522         C file2 file3
1523         #
1524         # or to delete file5 from file2.
1525         D file2/file5
1526         # are we done yet?
1527
1528         INPUT_END
1529
1530         git fast-import <input &&
1531         test $(git rev-parse N3) = $(git rev-parse O1)
1532 '
1533
1534 test_expect_success 'O: blank lines not necessary after data commands' '
1535         cat >input <<-INPUT_END &&
1536         commit refs/heads/O2
1537         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1538         data <<COMMIT
1539         dirty directory copy
1540         COMMIT
1541         from refs/heads/branch^0
1542         M 644 inline file2/file5
1543         data <<EOF
1544         $file5_data
1545         EOF
1546         C file2 file3
1547         D file2/file5
1548
1549         INPUT_END
1550
1551         git fast-import <input &&
1552         test $(git rev-parse N3) = $(git rev-parse O2)
1553 '
1554
1555 test_expect_success 'O: repack before next test' '
1556         git repack -a -d
1557 '
1558
1559 test_expect_success 'O: blank lines not necessary after other commands' '
1560         cat >input <<-INPUT_END &&
1561         commit refs/heads/O3
1562         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1563         data <<COMMIT
1564         zstring
1565         COMMIT
1566         commit refs/heads/O3
1567         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1568         data <<COMMIT
1569         zof
1570         COMMIT
1571         checkpoint
1572         commit refs/heads/O3
1573         mark :5
1574         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1575         data <<COMMIT
1576         zempty
1577         COMMIT
1578         checkpoint
1579         commit refs/heads/O3
1580         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1581         data <<COMMIT
1582         zcommits
1583         COMMIT
1584         reset refs/tags/O3-2nd
1585         from :5
1586         reset refs/tags/O3-3rd
1587         from :5
1588         INPUT_END
1589
1590         cat >expect <<-INPUT_END &&
1591         string
1592         of
1593         empty
1594         commits
1595         INPUT_END
1596
1597         git fast-import <input &&
1598         test 8 = $(find .git/objects/pack -type f | grep -v multi-pack-index | wc -l) &&
1599         test $(git rev-parse refs/tags/O3-2nd) = $(git rev-parse O3^) &&
1600         git log --reverse --pretty=oneline O3 | sed s/^.*z// >actual &&
1601         test_cmp expect actual
1602 '
1603
1604 test_expect_success 'O: progress outputs as requested by input' '
1605         cat >input <<-INPUT_END &&
1606         commit refs/heads/O4
1607         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1608         data <<COMMIT
1609         zstring
1610         COMMIT
1611         commit refs/heads/O4
1612         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1613         data <<COMMIT
1614         zof
1615         COMMIT
1616         progress Two commits down, 2 to go!
1617         commit refs/heads/O4
1618         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1619         data <<COMMIT
1620         zempty
1621         COMMIT
1622         progress Three commits down, 1 to go!
1623         commit refs/heads/O4
1624         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1625         data <<COMMIT
1626         zcommits
1627         COMMIT
1628         progress done!
1629         INPUT_END
1630         git fast-import <input >actual &&
1631         grep "progress " <input >expect &&
1632         test_cmp expect actual
1633 '
1634
1635 ###
1636 ### series P (gitlinks)
1637 ###
1638
1639 test_expect_success 'P: superproject & submodule mix' '
1640         cat >input <<-INPUT_END &&
1641         blob
1642         mark :1
1643         data 10
1644         test file
1645
1646         reset refs/heads/sub
1647         commit refs/heads/sub
1648         mark :2
1649         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1650         data 12
1651         sub_initial
1652         M 100644 :1 file
1653
1654         blob
1655         mark :3
1656         data <<DATAEND
1657         [submodule "sub"]
1658                 path = sub
1659                 url = "$(pwd)/sub"
1660         DATAEND
1661
1662         commit refs/heads/subuse1
1663         mark :4
1664         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1665         data 8
1666         initial
1667         from refs/heads/master
1668         M 100644 :3 .gitmodules
1669         M 160000 :2 sub
1670
1671         blob
1672         mark :5
1673         data 20
1674         test file
1675         more data
1676
1677         commit refs/heads/sub
1678         mark :6
1679         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1680         data 11
1681         sub_second
1682         from :2
1683         M 100644 :5 file
1684
1685         commit refs/heads/subuse1
1686         mark :7
1687         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1688         data 7
1689         second
1690         from :4
1691         M 160000 :6 sub
1692
1693         INPUT_END
1694
1695         git fast-import <input &&
1696         git checkout subuse1 &&
1697         rm -rf sub &&
1698         mkdir sub &&
1699         (
1700                 cd sub &&
1701                 git init &&
1702                 git fetch --update-head-ok .. refs/heads/sub:refs/heads/master &&
1703                 git checkout master
1704         ) &&
1705         git submodule init &&
1706         git submodule update
1707 '
1708
1709 test_expect_success 'P: verbatim SHA gitlinks' '
1710         SUBLAST=$(git rev-parse --verify sub) &&
1711         SUBPREV=$(git rev-parse --verify sub^) &&
1712
1713         cat >input <<-INPUT_END &&
1714         blob
1715         mark :1
1716         data <<DATAEND
1717         [submodule "sub"]
1718                 path = sub
1719                 url = "$(pwd)/sub"
1720         DATAEND
1721
1722         commit refs/heads/subuse2
1723         mark :2
1724         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1725         data 8
1726         initial
1727         from refs/heads/master
1728         M 100644 :1 .gitmodules
1729         M 160000 $SUBPREV sub
1730
1731         commit refs/heads/subuse2
1732         mark :3
1733         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1734         data 7
1735         second
1736         from :2
1737         M 160000 $SUBLAST sub
1738
1739         INPUT_END
1740
1741         git branch -D sub &&
1742         git gc &&
1743         git prune &&
1744         git fast-import <input &&
1745         test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)
1746 '
1747
1748 test_expect_success 'P: fail on inline gitlink' '
1749         test_tick &&
1750         cat >input <<-INPUT_END &&
1751         commit refs/heads/subuse3
1752         mark :1
1753         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1754         data <<COMMIT
1755         corrupt
1756         COMMIT
1757
1758         from refs/heads/subuse2
1759         M 160000 inline sub
1760         data <<DATA
1761         $SUBPREV
1762         DATA
1763
1764         INPUT_END
1765
1766         test_must_fail git fast-import <input
1767 '
1768
1769 test_expect_success 'P: fail on blob mark in gitlink' '
1770         test_tick &&
1771         cat >input <<-INPUT_END &&
1772         blob
1773         mark :1
1774         data <<DATA
1775         $SUBPREV
1776         DATA
1777
1778         commit refs/heads/subuse3
1779         mark :2
1780         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1781         data <<COMMIT
1782         corrupt
1783         COMMIT
1784
1785         from refs/heads/subuse2
1786         M 160000 :1 sub
1787
1788         INPUT_END
1789
1790         test_must_fail git fast-import <input
1791 '
1792
1793 ###
1794 ### series Q (notes)
1795 ###
1796
1797 test_expect_success 'Q: commit notes' '
1798         note1_data="The first note for the first commit" &&
1799         note2_data="The first note for the second commit" &&
1800         note3_data="The first note for the third commit" &&
1801         note1b_data="The second note for the first commit" &&
1802         note1c_data="The third note for the first commit" &&
1803         note2b_data="The second note for the second commit" &&
1804
1805         test_tick &&
1806         cat >input <<-INPUT_END &&
1807         blob
1808         mark :2
1809         data <<EOF
1810         $file2_data
1811         EOF
1812
1813         commit refs/heads/notes-test
1814         mark :3
1815         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1816         data <<COMMIT
1817         first (:3)
1818         COMMIT
1819
1820         M 644 :2 file2
1821
1822         blob
1823         mark :4
1824         data $file4_len
1825         $file4_data
1826         commit refs/heads/notes-test
1827         mark :5
1828         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1829         data <<COMMIT
1830         second (:5)
1831         COMMIT
1832
1833         M 644 :4 file4
1834
1835         commit refs/heads/notes-test
1836         mark :6
1837         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1838         data <<COMMIT
1839         third (:6)
1840         COMMIT
1841
1842         M 644 inline file5
1843         data <<EOF
1844         $file5_data
1845         EOF
1846
1847         M 755 inline file6
1848         data <<EOF
1849         $file6_data
1850         EOF
1851
1852         blob
1853         mark :7
1854         data <<EOF
1855         $note1_data
1856         EOF
1857
1858         blob
1859         mark :8
1860         data <<EOF
1861         $note2_data
1862         EOF
1863
1864         commit refs/notes/foobar
1865         mark :9
1866         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1867         data <<COMMIT
1868         notes (:9)
1869         COMMIT
1870
1871         N :7 :3
1872         N :8 :5
1873         N inline :6
1874         data <<EOF
1875         $note3_data
1876         EOF
1877
1878         commit refs/notes/foobar
1879         mark :10
1880         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1881         data <<COMMIT
1882         notes (:10)
1883         COMMIT
1884
1885         N inline :3
1886         data <<EOF
1887         $note1b_data
1888         EOF
1889
1890         commit refs/notes/foobar2
1891         mark :11
1892         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1893         data <<COMMIT
1894         notes (:11)
1895         COMMIT
1896
1897         N inline :3
1898         data <<EOF
1899         $note1c_data
1900         EOF
1901
1902         commit refs/notes/foobar
1903         mark :12
1904         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1905         data <<COMMIT
1906         notes (:12)
1907         COMMIT
1908
1909         deleteall
1910         N inline :5
1911         data <<EOF
1912         $note2b_data
1913         EOF
1914
1915         INPUT_END
1916
1917         git fast-import <input &&
1918         git whatchanged notes-test
1919 '
1920
1921 test_expect_success 'Q: verify pack' '
1922         verify_packs
1923 '
1924
1925 test_expect_success 'Q: verify first commit' '
1926         commit1=$(git rev-parse notes-test~2) &&
1927         commit2=$(git rev-parse notes-test^) &&
1928         commit3=$(git rev-parse notes-test) &&
1929
1930         cat >expect <<-EOF &&
1931         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1932         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1933
1934         first (:3)
1935         EOF
1936         git cat-file commit notes-test~2 | sed 1d >actual &&
1937         test_cmp expect actual
1938 '
1939
1940 test_expect_success 'Q: verify second commit' '
1941         cat >expect <<-EOF &&
1942         parent $commit1
1943         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1944         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1945
1946         second (:5)
1947         EOF
1948         git cat-file commit notes-test^ | sed 1d >actual &&
1949         test_cmp expect actual
1950 '
1951
1952 test_expect_success 'Q: verify third commit' '
1953         cat >expect <<-EOF &&
1954         parent $commit2
1955         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1956         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1957
1958         third (:6)
1959         EOF
1960         git cat-file commit notes-test | sed 1d >actual &&
1961         test_cmp expect actual
1962 '
1963
1964 test_expect_success 'Q: verify first notes commit' '
1965         cat >expect <<-EOF &&
1966         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1967         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
1968
1969         notes (:9)
1970         EOF
1971         git cat-file commit refs/notes/foobar~2 | sed 1d >actual &&
1972         test_cmp expect actual
1973 '
1974
1975 test_expect_success 'Q: verify first notes tree' '
1976         cat >expect.unsorted <<-EOF &&
1977         100644 blob $commit1
1978         100644 blob $commit2
1979         100644 blob $commit3
1980         EOF
1981         cat expect.unsorted | sort >expect &&
1982         git cat-file -p refs/notes/foobar~2^{tree} | sed "s/ [0-9a-f]*  / /" >actual &&
1983         test_cmp expect actual
1984 '
1985
1986 test_expect_success 'Q: verify first note for first commit' '
1987         echo "$note1_data" >expect &&
1988         git cat-file blob refs/notes/foobar~2:$commit1 >actual &&
1989         test_cmp expect actual
1990 '
1991
1992 test_expect_success 'Q: verify first note for second commit' '
1993         echo "$note2_data" >expect &&
1994         git cat-file blob refs/notes/foobar~2:$commit2 >actual &&
1995         test_cmp expect actual
1996 '
1997
1998 test_expect_success 'Q: verify first note for third commit' '
1999         echo "$note3_data" >expect &&
2000         git cat-file blob refs/notes/foobar~2:$commit3 >actual &&
2001         test_cmp expect actual
2002 '
2003
2004 test_expect_success 'Q: verify second notes commit' '
2005         cat >expect <<-EOF &&
2006         parent $(git rev-parse --verify refs/notes/foobar~2)
2007         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2008         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2009
2010         notes (:10)
2011         EOF
2012         git cat-file commit refs/notes/foobar^ | sed 1d >actual &&
2013         test_cmp expect actual
2014 '
2015
2016 test_expect_success 'Q: verify second notes tree' '
2017         cat >expect.unsorted <<-EOF &&
2018         100644 blob $commit1
2019         100644 blob $commit2
2020         100644 blob $commit3
2021         EOF
2022         cat expect.unsorted | sort >expect &&
2023         git cat-file -p refs/notes/foobar^^{tree} | sed "s/ [0-9a-f]*   / /" >actual &&
2024         test_cmp expect actual
2025 '
2026
2027 test_expect_success 'Q: verify second note for first commit' '
2028         echo "$note1b_data" >expect &&
2029         git cat-file blob refs/notes/foobar^:$commit1 >actual &&
2030         test_cmp expect actual
2031 '
2032
2033 test_expect_success 'Q: verify first note for second commit' '
2034         echo "$note2_data" >expect &&
2035         git cat-file blob refs/notes/foobar^:$commit2 >actual &&
2036         test_cmp expect actual
2037 '
2038
2039 test_expect_success 'Q: verify first note for third commit' '
2040         echo "$note3_data" >expect &&
2041         git cat-file blob refs/notes/foobar^:$commit3 >actual &&
2042         test_cmp expect actual
2043 '
2044
2045 test_expect_success 'Q: verify third notes commit' '
2046         cat >expect <<-EOF &&
2047         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2048         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2049
2050         notes (:11)
2051         EOF
2052         git cat-file commit refs/notes/foobar2 | sed 1d >actual &&
2053         test_cmp expect actual
2054 '
2055
2056 test_expect_success 'Q: verify third notes tree' '
2057         cat >expect.unsorted <<-EOF &&
2058         100644 blob $commit1
2059         EOF
2060         cat expect.unsorted | sort >expect &&
2061         git cat-file -p refs/notes/foobar2^{tree} | sed "s/ [0-9a-f]*   / /" >actual &&
2062         test_cmp expect actual
2063 '
2064
2065 test_expect_success 'Q: verify third note for first commit' '
2066         echo "$note1c_data" >expect &&
2067         git cat-file blob refs/notes/foobar2:$commit1 >actual &&
2068         test_cmp expect actual
2069 '
2070
2071 test_expect_success 'Q: verify fourth notes commit' '
2072         cat >expect <<-EOF &&
2073         parent $(git rev-parse --verify refs/notes/foobar^)
2074         author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2075         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2076
2077         notes (:12)
2078         EOF
2079         git cat-file commit refs/notes/foobar | sed 1d >actual &&
2080         test_cmp expect actual
2081 '
2082
2083 test_expect_success 'Q: verify fourth notes tree' '
2084         cat >expect.unsorted <<-EOF &&
2085         100644 blob $commit2
2086         EOF
2087         cat expect.unsorted | sort >expect &&
2088         git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]*    / /" >actual &&
2089         test_cmp expect actual
2090 '
2091
2092 test_expect_success 'Q: verify second note for second commit' '
2093         echo "$note2b_data" >expect &&
2094         git cat-file blob refs/notes/foobar:$commit2 >actual &&
2095         test_cmp expect actual
2096 '
2097
2098 test_expect_success 'Q: deny note on empty branch' '
2099         cat >input <<-EOF &&
2100         reset refs/heads/Q0
2101
2102         commit refs/heads/note-Q0
2103         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2104         data <<COMMIT
2105         Note for an empty branch.
2106         COMMIT
2107
2108         N inline refs/heads/Q0
2109         data <<NOTE
2110         some note
2111         NOTE
2112         EOF
2113         test_must_fail git fast-import <input
2114 '
2115 ###
2116 ### series R (feature and option)
2117 ###
2118
2119 test_expect_success 'R: abort on unsupported feature' '
2120         cat >input <<-EOF &&
2121         feature no-such-feature-exists
2122         EOF
2123
2124         test_must_fail git fast-import <input
2125 '
2126
2127 test_expect_success 'R: supported feature is accepted' '
2128         cat >input <<-EOF &&
2129         feature date-format=now
2130         EOF
2131
2132         git fast-import <input
2133 '
2134
2135 test_expect_success 'R: abort on receiving feature after data command' '
2136         cat >input <<-EOF &&
2137         blob
2138         data 3
2139         hi
2140         feature date-format=now
2141         EOF
2142
2143         test_must_fail git fast-import <input
2144 '
2145
2146 test_expect_success 'R: import-marks features forbidden by default' '
2147         >git.marks &&
2148         echo "feature import-marks=git.marks" >input &&
2149         test_must_fail git fast-import <input &&
2150         echo "feature import-marks-if-exists=git.marks" >input &&
2151         test_must_fail git fast-import <input
2152 '
2153
2154 test_expect_success 'R: only one import-marks feature allowed per stream' '
2155         >git.marks &&
2156         >git2.marks &&
2157         cat >input <<-EOF &&
2158         feature import-marks=git.marks
2159         feature import-marks=git2.marks
2160         EOF
2161
2162         test_must_fail git fast-import --allow-unsafe-features <input
2163 '
2164
2165 test_expect_success 'R: export-marks feature forbidden by default' '
2166         echo "feature export-marks=git.marks" >input &&
2167         test_must_fail git fast-import <input
2168 '
2169
2170 test_expect_success 'R: export-marks feature results in a marks file being created' '
2171         cat >input <<-EOF &&
2172         feature export-marks=git.marks
2173         blob
2174         mark :1
2175         data 3
2176         hi
2177
2178         EOF
2179
2180         git fast-import --allow-unsafe-features <input &&
2181         grep :1 git.marks
2182 '
2183
2184 test_expect_success 'R: export-marks options can be overridden by commandline options' '
2185         cat >input <<-\EOF &&
2186         feature export-marks=feature-sub/git.marks
2187         blob
2188         mark :1
2189         data 3
2190         hi
2191
2192         EOF
2193         git fast-import --allow-unsafe-features \
2194                         --export-marks=cmdline-sub/other.marks <input &&
2195         grep :1 cmdline-sub/other.marks &&
2196         test_path_is_missing feature-sub
2197 '
2198
2199 test_expect_success 'R: catch typo in marks file name' '
2200         test_must_fail git fast-import --import-marks=nonexistent.marks </dev/null &&
2201         echo "feature import-marks=nonexistent.marks" |
2202         test_must_fail git fast-import --allow-unsafe-features
2203 '
2204
2205 test_expect_success 'R: import and output marks can be the same file' '
2206         rm -f io.marks &&
2207         blob=$(echo hi | git hash-object --stdin) &&
2208         cat >expect <<-EOF &&
2209         :1 $blob
2210         :2 $blob
2211         EOF
2212         git fast-import --export-marks=io.marks <<-\EOF &&
2213         blob
2214         mark :1
2215         data 3
2216         hi
2217
2218         EOF
2219         git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF &&
2220         blob
2221         mark :2
2222         data 3
2223         hi
2224
2225         EOF
2226         test_cmp expect io.marks
2227 '
2228
2229 test_expect_success 'R: --import-marks=foo --output-marks=foo to create foo fails' '
2230         rm -f io.marks &&
2231         test_must_fail git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF
2232         blob
2233         mark :1
2234         data 3
2235         hi
2236
2237         EOF
2238 '
2239
2240 test_expect_success 'R: --import-marks-if-exists' '
2241         rm -f io.marks &&
2242         blob=$(echo hi | git hash-object --stdin) &&
2243         echo ":1 $blob" >expect &&
2244         git fast-import --import-marks-if-exists=io.marks --export-marks=io.marks <<-\EOF &&
2245         blob
2246         mark :1
2247         data 3
2248         hi
2249
2250         EOF
2251         test_cmp expect io.marks
2252 '
2253
2254 test_expect_success 'R: feature import-marks-if-exists' '
2255         rm -f io.marks &&
2256
2257         git fast-import --export-marks=io.marks \
2258                         --allow-unsafe-features <<-\EOF &&
2259         feature import-marks-if-exists=not_io.marks
2260         EOF
2261         test_must_be_empty io.marks &&
2262
2263         blob=$(echo hi | git hash-object --stdin) &&
2264
2265         echo ":1 $blob" >io.marks &&
2266         echo ":1 $blob" >expect &&
2267         echo ":2 $blob" >>expect &&
2268
2269         git fast-import --export-marks=io.marks \
2270                         --allow-unsafe-features <<-\EOF &&
2271         feature import-marks-if-exists=io.marks
2272         blob
2273         mark :2
2274         data 3
2275         hi
2276
2277         EOF
2278         test_cmp expect io.marks &&
2279
2280         echo ":3 $blob" >>expect &&
2281
2282         git fast-import --import-marks=io.marks \
2283                         --export-marks=io.marks \
2284                         --allow-unsafe-features <<-\EOF &&
2285         feature import-marks-if-exists=not_io.marks
2286         blob
2287         mark :3
2288         data 3
2289         hi
2290
2291         EOF
2292         test_cmp expect io.marks &&
2293
2294         git fast-import --import-marks-if-exists=not_io.marks \
2295                         --export-marks=io.marks \
2296                         --allow-unsafe-features <<-\EOF &&
2297         feature import-marks-if-exists=io.marks
2298         EOF
2299         test_must_be_empty io.marks
2300 '
2301
2302 test_expect_success 'R: import to output marks works without any content' '
2303         cat >input <<-EOF &&
2304         feature import-marks=marks.out
2305         feature export-marks=marks.new
2306         EOF
2307
2308         git fast-import --allow-unsafe-features <input &&
2309         test_cmp marks.out marks.new
2310 '
2311
2312 test_expect_success 'R: import marks prefers commandline marks file over the stream' '
2313         cat >input <<-EOF &&
2314         feature import-marks=nonexistent.marks
2315         feature export-marks=marks.new
2316         EOF
2317
2318         git fast-import --import-marks=marks.out --allow-unsafe-features <input &&
2319         test_cmp marks.out marks.new
2320 '
2321
2322
2323 test_expect_success 'R: multiple --import-marks= should be honoured' '
2324         cat >input <<-EOF &&
2325         feature import-marks=nonexistent.marks
2326         feature export-marks=combined.marks
2327         EOF
2328
2329         head -n2 marks.out > one.marks &&
2330         tail -n +3 marks.out > two.marks &&
2331         git fast-import --import-marks=one.marks --import-marks=two.marks \
2332                 --allow-unsafe-features <input &&
2333         test_cmp marks.out combined.marks
2334 '
2335
2336 test_expect_success 'R: feature relative-marks should be honoured' '
2337         cat >input <<-EOF &&
2338         feature relative-marks
2339         feature import-marks=relative.in
2340         feature export-marks=relative.out
2341         EOF
2342
2343         mkdir -p .git/info/fast-import/ &&
2344         cp marks.new .git/info/fast-import/relative.in &&
2345         git fast-import --allow-unsafe-features <input &&
2346         test_cmp marks.new .git/info/fast-import/relative.out
2347 '
2348
2349 test_expect_success 'R: feature no-relative-marks should be honoured' '
2350         cat >input <<-EOF &&
2351         feature relative-marks
2352         feature import-marks=relative.in
2353         feature no-relative-marks
2354         feature export-marks=non-relative.out
2355         EOF
2356
2357         git fast-import --allow-unsafe-features <input &&
2358         test_cmp marks.new non-relative.out
2359 '
2360
2361 test_expect_success 'R: feature ls supported' '
2362         echo "feature ls" |
2363         git fast-import
2364 '
2365
2366 test_expect_success 'R: feature cat-blob supported' '
2367         echo "feature cat-blob" |
2368         git fast-import
2369 '
2370
2371 test_expect_success 'R: cat-blob-fd must be a nonnegative integer' '
2372         test_must_fail git fast-import --cat-blob-fd=-1 </dev/null
2373 '
2374
2375 test_expect_success !MINGW 'R: print old blob' '
2376         blob=$(echo "yes it can" | git hash-object -w --stdin) &&
2377         cat >expect <<-EOF &&
2378         ${blob} blob 11
2379         yes it can
2380
2381         EOF
2382         echo "cat-blob $blob" |
2383         git fast-import --cat-blob-fd=6 6>actual &&
2384         test_cmp expect actual
2385 '
2386
2387 test_expect_success !MINGW 'R: in-stream cat-blob-fd not respected' '
2388         echo hello >greeting &&
2389         blob=$(git hash-object -w greeting) &&
2390         cat >expect <<-EOF &&
2391         ${blob} blob 6
2392         hello
2393
2394         EOF
2395         git fast-import --cat-blob-fd=3 3>actual.3 >actual.1 <<-EOF &&
2396         cat-blob $blob
2397         EOF
2398         test_cmp expect actual.3 &&
2399         test_must_be_empty actual.1 &&
2400         git fast-import 3>actual.3 >actual.1 <<-EOF &&
2401         option cat-blob-fd=3
2402         cat-blob $blob
2403         EOF
2404         test_must_be_empty actual.3 &&
2405         test_cmp expect actual.1
2406 '
2407
2408 test_expect_success !MINGW 'R: print mark for new blob' '
2409         echo "effluentish" | git hash-object --stdin >expect &&
2410         git fast-import --cat-blob-fd=6 6>actual <<-\EOF &&
2411         blob
2412         mark :1
2413         data <<BLOB_END
2414         effluentish
2415         BLOB_END
2416         get-mark :1
2417         EOF
2418         test_cmp expect actual
2419 '
2420
2421 test_expect_success !MINGW 'R: print new blob' '
2422         blob=$(echo "yep yep yep" | git hash-object --stdin) &&
2423         cat >expect <<-EOF &&
2424         ${blob} blob 12
2425         yep yep yep
2426
2427         EOF
2428         git fast-import --cat-blob-fd=6 6>actual <<-\EOF &&
2429         blob
2430         mark :1
2431         data <<BLOB_END
2432         yep yep yep
2433         BLOB_END
2434         cat-blob :1
2435         EOF
2436         test_cmp expect actual
2437 '
2438
2439 test_expect_success !MINGW 'R: print new blob by sha1' '
2440         blob=$(echo "a new blob named by sha1" | git hash-object --stdin) &&
2441         cat >expect <<-EOF &&
2442         ${blob} blob 25
2443         a new blob named by sha1
2444
2445         EOF
2446         git fast-import --cat-blob-fd=6 6>actual <<-EOF &&
2447         blob
2448         data <<BLOB_END
2449         a new blob named by sha1
2450         BLOB_END
2451         cat-blob $blob
2452         EOF
2453         test_cmp expect actual
2454 '
2455
2456 test_expect_success 'setup: big file' '
2457         (
2458                 echo "the quick brown fox jumps over the lazy dog" >big &&
2459                 for i in 1 2 3
2460                 do
2461                         cat big big big big >bigger &&
2462                         cat bigger bigger bigger bigger >big ||
2463                         exit
2464                 done
2465         )
2466 '
2467
2468 test_expect_success 'R: print two blobs to stdout' '
2469         blob1=$(git hash-object big) &&
2470         blob1_len=$(wc -c <big) &&
2471         blob2=$(echo hello | git hash-object --stdin) &&
2472         {
2473                 echo ${blob1} blob $blob1_len &&
2474                 cat big &&
2475                 cat <<-EOF
2476
2477                 ${blob2} blob 6
2478                 hello
2479
2480                 EOF
2481         } >expect &&
2482         {
2483                 cat <<-\END_PART1 &&
2484                         blob
2485                         mark :1
2486                         data <<data_end
2487                 END_PART1
2488                 cat big &&
2489                 cat <<-\EOF
2490                         data_end
2491                         blob
2492                         mark :2
2493                         data <<data_end
2494                         hello
2495                         data_end
2496                         cat-blob :1
2497                         cat-blob :2
2498                 EOF
2499         } |
2500         git fast-import >actual &&
2501         test_cmp expect actual
2502 '
2503
2504 test_expect_success PIPE 'R: copy using cat-file' '
2505         expect_id=$(git hash-object big) &&
2506         expect_len=$(wc -c <big) &&
2507         echo $expect_id blob $expect_len >expect.response &&
2508
2509         rm -f blobs &&
2510
2511         mkfifo blobs &&
2512         (
2513                 export GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE &&
2514                 cat <<-\EOF &&
2515                 feature cat-blob
2516                 blob
2517                 mark :1
2518                 data <<BLOB
2519                 EOF
2520                 cat big &&
2521                 cat <<-\EOF &&
2522                 BLOB
2523                 cat-blob :1
2524                 EOF
2525
2526                 read blob_id type size <&3 &&
2527                 echo "$blob_id $type $size" >response &&
2528                 test_copy_bytes $size >blob <&3 &&
2529                 read newline <&3 &&
2530
2531                 cat <<-EOF &&
2532                 commit refs/heads/copied
2533                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2534                 data <<COMMIT
2535                 copy big file as file3
2536                 COMMIT
2537                 M 644 inline file3
2538                 data <<BLOB
2539                 EOF
2540                 cat blob &&
2541                 echo BLOB
2542         ) 3<blobs |
2543         git fast-import --cat-blob-fd=3 3>blobs &&
2544         git show copied:file3 >actual &&
2545         test_cmp expect.response response &&
2546         test_cmp big actual
2547 '
2548
2549 test_expect_success PIPE 'R: print blob mid-commit' '
2550         rm -f blobs &&
2551         echo "A blob from _before_ the commit." >expect &&
2552         mkfifo blobs &&
2553         (
2554                 exec 3<blobs &&
2555                 cat <<-EOF &&
2556                 feature cat-blob
2557                 blob
2558                 mark :1
2559                 data <<BLOB
2560                 A blob from _before_ the commit.
2561                 BLOB
2562                 commit refs/heads/temporary
2563                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2564                 data <<COMMIT
2565                 Empty commit
2566                 COMMIT
2567                 cat-blob :1
2568                 EOF
2569
2570                 read blob_id type size <&3 &&
2571                 test_copy_bytes $size >actual <&3 &&
2572                 read newline <&3 &&
2573
2574                 echo
2575         ) |
2576         git fast-import --cat-blob-fd=3 3>blobs &&
2577         test_cmp expect actual
2578 '
2579
2580 test_expect_success PIPE 'R: print staged blob within commit' '
2581         rm -f blobs &&
2582         echo "A blob from _within_ the commit." >expect &&
2583         mkfifo blobs &&
2584         (
2585                 exec 3<blobs &&
2586                 cat <<-EOF &&
2587                 feature cat-blob
2588                 commit refs/heads/within
2589                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2590                 data <<COMMIT
2591                 Empty commit
2592                 COMMIT
2593                 M 644 inline within
2594                 data <<BLOB
2595                 A blob from _within_ the commit.
2596                 BLOB
2597                 EOF
2598
2599                 to_get=$(
2600                         echo "A blob from _within_ the commit." |
2601                         git hash-object --stdin
2602                 ) &&
2603                 echo "cat-blob $to_get" &&
2604
2605                 read blob_id type size <&3 &&
2606                 test_copy_bytes $size >actual <&3 &&
2607                 read newline <&3 &&
2608
2609                 echo deleteall
2610         ) |
2611         git fast-import --cat-blob-fd=3 3>blobs &&
2612         test_cmp expect actual
2613 '
2614
2615 test_expect_success 'R: quiet option results in no stats being output' '
2616         cat >input <<-EOF &&
2617         option git quiet
2618         blob
2619         data 3
2620         hi
2621
2622         EOF
2623
2624         git fast-import 2>output <input &&
2625         test_must_be_empty output
2626 '
2627
2628 test_expect_success 'R: feature done means terminating "done" is mandatory' '
2629         echo feature done | test_must_fail git fast-import &&
2630         test_must_fail git fast-import --done </dev/null
2631 '
2632
2633 test_expect_success 'R: terminating "done" with trailing gibberish is ok' '
2634         git fast-import <<-\EOF &&
2635         feature done
2636         done
2637         trailing gibberish
2638         EOF
2639         git fast-import <<-\EOF
2640         done
2641         more trailing gibberish
2642         EOF
2643 '
2644
2645 test_expect_success 'R: terminating "done" within commit' '
2646         cat >expect <<-\EOF &&
2647         OBJID
2648         :000000 100644 OBJID OBJID A    hello.c
2649         :000000 100644 OBJID OBJID A    hello2.c
2650         EOF
2651         git fast-import <<-EOF &&
2652         commit refs/heads/done-ends
2653         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2654         data <<EOT
2655         Commit terminated by "done" command
2656         EOT
2657         M 100644 inline hello.c
2658         data <<EOT
2659         Hello, world.
2660         EOT
2661         C hello.c hello2.c
2662         done
2663         EOF
2664         git rev-list done-ends |
2665         git diff-tree -r --stdin --root --always |
2666         sed -e "s/$OID_REGEX/OBJID/g" >actual &&
2667         test_cmp expect actual
2668 '
2669
2670 test_expect_success 'R: die on unknown option' '
2671         cat >input <<-EOF &&
2672         option git non-existing-option
2673         EOF
2674
2675         test_must_fail git fast-import <input
2676 '
2677
2678 test_expect_success 'R: unknown commandline options are rejected' '\
2679         test_must_fail git fast-import --non-existing-option < /dev/null
2680 '
2681
2682 test_expect_success 'R: die on invalid option argument' '
2683         echo "option git active-branches=-5" |
2684         test_must_fail git fast-import &&
2685         echo "option git depth=" |
2686         test_must_fail git fast-import &&
2687         test_must_fail git fast-import --depth="5 elephants" </dev/null
2688 '
2689
2690 test_expect_success 'R: ignore non-git options' '
2691         cat >input <<-EOF &&
2692         option non-existing-vcs non-existing-option
2693         EOF
2694
2695         git fast-import <input
2696 '
2697
2698 test_expect_success 'R: corrupt lines do not mess marks file' '
2699         rm -f io.marks &&
2700         blob=$(echo hi | git hash-object --stdin) &&
2701         cat >expect <<-EOF &&
2702         :3 0000000000000000000000000000000000000000
2703         :1 $blob
2704         :2 $blob
2705         EOF
2706         cp expect io.marks &&
2707         test_must_fail git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF &&
2708
2709         EOF
2710         test_cmp expect io.marks
2711 '
2712
2713 ##
2714 ## R: very large blobs
2715 ##
2716 test_expect_success 'R: blob bigger than threshold' '
2717         blobsize=$((2*1024*1024 + 53)) &&
2718         test-tool genrandom bar $blobsize >expect &&
2719         cat >input <<-INPUT_END &&
2720         commit refs/heads/big-file
2721         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2722         data <<COMMIT
2723         R - big file
2724         COMMIT
2725
2726         M 644 inline big1
2727         data $blobsize
2728         INPUT_END
2729         cat expect >>input &&
2730         cat >>input <<-INPUT_END &&
2731         M 644 inline big2
2732         data $blobsize
2733         INPUT_END
2734         cat expect >>input &&
2735         echo >>input &&
2736
2737         test_create_repo R &&
2738         git --git-dir=R/.git config fastimport.unpackLimit 0 &&
2739         git --git-dir=R/.git fast-import --big-file-threshold=1 <input
2740 '
2741
2742 test_expect_success 'R: verify created pack' '
2743         (
2744                 cd R &&
2745                 verify_packs -v > ../verify
2746         )
2747 '
2748
2749 test_expect_success 'R: verify written objects' '
2750         git --git-dir=R/.git cat-file blob big-file:big1 >actual &&
2751         test_cmp_bin expect actual &&
2752         a=$(git --git-dir=R/.git rev-parse big-file:big1) &&
2753         b=$(git --git-dir=R/.git rev-parse big-file:big2) &&
2754         test $a = $b
2755 '
2756
2757 test_expect_success 'R: blob appears only once' '
2758         n=$(grep $a verify | wc -l) &&
2759         test 1 = $n
2760 '
2761
2762 ###
2763 ### series S
2764 ###
2765 #
2766 # Make sure missing spaces and EOLs after mark references
2767 # cause errors.
2768 #
2769 # Setup:
2770 #
2771 #   1--2--4
2772 #    \   /
2773 #     -3-
2774 #
2775 #   commit marks:  301, 302, 303, 304
2776 #   blob marks:              403, 404, resp.
2777 #   note mark:          202
2778 #
2779 # The error message when a space is missing not at the
2780 # end of the line is:
2781 #
2782 #   Missing space after ..
2783 #
2784 # or when extra characters come after the mark at the end
2785 # of the line:
2786 #
2787 #   Garbage after ..
2788 #
2789 # or when the dataref is neither "inline " or a known SHA1,
2790 #
2791 #   Invalid dataref ..
2792 #
2793 test_expect_success 'S: initialize for S tests' '
2794         test_tick &&
2795
2796         cat >input <<-INPUT_END &&
2797         commit refs/heads/S
2798         mark :301
2799         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2800         data <<COMMIT
2801         commit 1
2802         COMMIT
2803         M 100644 inline hello.c
2804         data <<BLOB
2805         blob 1
2806         BLOB
2807
2808         commit refs/heads/S
2809         mark :302
2810         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2811         data <<COMMIT
2812         commit 2
2813         COMMIT
2814         from :301
2815         M 100644 inline hello.c
2816         data <<BLOB
2817         blob 2
2818         BLOB
2819
2820         blob
2821         mark :403
2822         data <<BLOB
2823         blob 3
2824         BLOB
2825
2826         blob
2827         mark :202
2828         data <<BLOB
2829         note 2
2830         BLOB
2831         INPUT_END
2832
2833         git fast-import --export-marks=marks <input
2834 '
2835
2836 #
2837 # filemodify, three datarefs
2838 #
2839 test_expect_success 'S: filemodify with garbage after mark must fail' '
2840         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2841         commit refs/heads/S
2842         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2843         data <<COMMIT
2844         commit N
2845         COMMIT
2846         M 100644 :403x hello.c
2847         EOF
2848         test_i18ngrep "space after mark" err
2849 '
2850
2851 # inline is misspelled; fast-import thinks it is some unknown dataref
2852 test_expect_success 'S: filemodify with garbage after inline must fail' '
2853         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2854         commit refs/heads/S
2855         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2856         data <<COMMIT
2857         commit N
2858         COMMIT
2859         M 100644 inlineX hello.c
2860         data <<BLOB
2861         inline
2862         BLOB
2863         EOF
2864         test_i18ngrep "nvalid dataref" err
2865 '
2866
2867 test_expect_success 'S: filemodify with garbage after sha1 must fail' '
2868         sha1=$(grep :403 marks | cut -d\  -f2) &&
2869         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2870         commit refs/heads/S
2871         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2872         data <<COMMIT
2873         commit N
2874         COMMIT
2875         M 100644 ${sha1}x hello.c
2876         EOF
2877         test_i18ngrep "space after SHA1" err
2878 '
2879
2880 #
2881 # notemodify, three ways to say dataref
2882 #
2883 test_expect_success 'S: notemodify with garbage after mark dataref must fail' '
2884         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2885         commit refs/heads/S
2886         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2887         data <<COMMIT
2888         commit S note dataref markref
2889         COMMIT
2890         N :202x :302
2891         EOF
2892         test_i18ngrep "space after mark" err
2893 '
2894
2895 test_expect_success 'S: notemodify with garbage after inline dataref must fail' '
2896         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2897         commit refs/heads/S
2898         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2899         data <<COMMIT
2900         commit S note dataref inline
2901         COMMIT
2902         N inlineX :302
2903         data <<BLOB
2904         note blob
2905         BLOB
2906         EOF
2907         test_i18ngrep "nvalid dataref" err
2908 '
2909
2910 test_expect_success 'S: notemodify with garbage after sha1 dataref must fail' '
2911         sha1=$(grep :202 marks | cut -d\  -f2) &&
2912         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2913         commit refs/heads/S
2914         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2915         data <<COMMIT
2916         commit S note dataref sha1
2917         COMMIT
2918         N ${sha1}x :302
2919         EOF
2920         test_i18ngrep "space after SHA1" err
2921 '
2922
2923 #
2924 # notemodify, mark in commit-ish
2925 #
2926 test_expect_success 'S: notemodify with garbage after mark commit-ish must fail' '
2927         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2928         commit refs/heads/Snotes
2929         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2930         data <<COMMIT
2931         commit S note commit-ish
2932         COMMIT
2933         N :202 :302x
2934         EOF
2935         test_i18ngrep "after mark" err
2936 '
2937
2938 #
2939 # from
2940 #
2941 test_expect_success 'S: from with garbage after mark must fail' '
2942         test_must_fail \
2943         git fast-import --import-marks=marks --export-marks=marks <<-EOF 2>err &&
2944         commit refs/heads/S2
2945         mark :303
2946         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2947         data <<COMMIT
2948         commit 3
2949         COMMIT
2950         from :301x
2951         M 100644 :403 hello.c
2952         EOF
2953
2954
2955         # go create the commit, need it for merge test
2956         git fast-import --import-marks=marks --export-marks=marks <<-EOF &&
2957         commit refs/heads/S2
2958         mark :303
2959         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2960         data <<COMMIT
2961         commit 3
2962         COMMIT
2963         from :301
2964         M 100644 :403 hello.c
2965         EOF
2966
2967         # now evaluate the error
2968         test_i18ngrep "after mark" err
2969 '
2970
2971
2972 #
2973 # merge
2974 #
2975 test_expect_success 'S: merge with garbage after mark must fail' '
2976         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2977         commit refs/heads/S
2978         mark :304
2979         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2980         data <<COMMIT
2981         merge 4
2982         COMMIT
2983         from :302
2984         merge :303x
2985         M 100644 :403 hello.c
2986         EOF
2987         test_i18ngrep "after mark" err
2988 '
2989
2990 #
2991 # tag, from markref
2992 #
2993 test_expect_success 'S: tag with garbage after mark must fail' '
2994         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2995         tag refs/tags/Stag
2996         from :302x
2997         tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2998         data <<TAG
2999         tag S
3000         TAG
3001         EOF
3002         test_i18ngrep "after mark" err
3003 '
3004
3005 #
3006 # cat-blob markref
3007 #
3008 test_expect_success 'S: cat-blob with garbage after mark must fail' '
3009         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
3010         cat-blob :403x
3011         EOF
3012         test_i18ngrep "after mark" err
3013 '
3014
3015 #
3016 # ls markref
3017 #
3018 test_expect_success 'S: ls with garbage after mark must fail' '
3019         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
3020         ls :302x hello.c
3021         EOF
3022         test_i18ngrep "space after mark" err
3023 '
3024
3025 test_expect_success 'S: ls with garbage after sha1 must fail' '
3026         sha1=$(grep :302 marks | cut -d\  -f2) &&
3027         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
3028         ls ${sha1}x hello.c
3029         EOF
3030         test_i18ngrep "space after tree-ish" err
3031 '
3032
3033 ###
3034 ### series T (ls)
3035 ###
3036 # Setup is carried over from series S.
3037
3038 test_expect_success 'T: ls root tree' '
3039         sed -e "s/Z\$//" >expect <<-EOF &&
3040         040000 tree $(git rev-parse S^{tree})   Z
3041         EOF
3042         sha1=$(git rev-parse --verify S) &&
3043         git fast-import --import-marks=marks <<-EOF >actual &&
3044         ls $sha1 ""
3045         EOF
3046         test_cmp expect actual
3047 '
3048
3049 test_expect_success 'T: delete branch' '
3050         git branch to-delete &&
3051         git fast-import <<-EOF &&
3052         reset refs/heads/to-delete
3053         from 0000000000000000000000000000000000000000
3054         EOF
3055         test_must_fail git rev-parse --verify refs/heads/to-delete
3056 '
3057
3058 test_expect_success 'T: empty reset doesnt delete branch' '
3059         git branch not-to-delete &&
3060         git fast-import <<-EOF &&
3061         reset refs/heads/not-to-delete
3062         EOF
3063         git show-ref &&
3064         git rev-parse --verify refs/heads/not-to-delete
3065 '
3066
3067 ###
3068 ### series U (filedelete)
3069 ###
3070
3071 test_expect_success 'U: initialize for U tests' '
3072         cat >input <<-INPUT_END &&
3073         commit refs/heads/U
3074         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3075         data <<COMMIT
3076         test setup
3077         COMMIT
3078         M 100644 inline hello.c
3079         data <<BLOB
3080         blob 1
3081         BLOB
3082         M 100644 inline good/night.txt
3083         data <<BLOB
3084         sleep well
3085         BLOB
3086         M 100644 inline good/bye.txt
3087         data <<BLOB
3088         au revoir
3089         BLOB
3090
3091         INPUT_END
3092
3093         git fast-import <input
3094 '
3095
3096 test_expect_success 'U: filedelete file succeeds' '
3097         cat >input <<-INPUT_END &&
3098         commit refs/heads/U
3099         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3100         data <<COMMIT
3101         delete good/night.txt
3102         COMMIT
3103         from refs/heads/U^0
3104         D good/night.txt
3105
3106         INPUT_END
3107
3108         git fast-import <input
3109 '
3110
3111 test_expect_success 'U: validate file delete result' '
3112         cat >expect <<-EOF &&
3113         :100644 000000 2907ebb4bf85d91bf0716bb3bd8a68ef48d6da76 0000000000000000000000000000000000000000 D      good/night.txt
3114         EOF
3115
3116         git diff-tree -M -r U^1 U >actual &&
3117
3118         compare_diff_raw expect actual
3119 '
3120
3121 test_expect_success 'U: filedelete directory succeeds' '
3122         cat >input <<-INPUT_END &&
3123         commit refs/heads/U
3124         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3125         data <<COMMIT
3126         delete good dir
3127         COMMIT
3128         from refs/heads/U^0
3129         D good
3130
3131         INPUT_END
3132
3133         git fast-import <input
3134 '
3135
3136 test_expect_success 'U: validate directory delete result' '
3137         cat >expect <<-EOF &&
3138         :100644 000000 69cb75792f55123d8389c156b0b41c2ff00ed507 0000000000000000000000000000000000000000 D      good/bye.txt
3139         EOF
3140
3141         git diff-tree -M -r U^1 U >actual &&
3142
3143         compare_diff_raw expect actual
3144 '
3145
3146 test_expect_success 'U: filedelete root succeeds' '
3147         cat >input <<-INPUT_END &&
3148         commit refs/heads/U
3149         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3150         data <<COMMIT
3151         must succeed
3152         COMMIT
3153         from refs/heads/U^0
3154         D ""
3155
3156         INPUT_END
3157
3158         git fast-import <input
3159 '
3160
3161 test_expect_success 'U: validate root delete result' '
3162         cat >expect <<-EOF &&
3163         :100644 000000 c18147dc648481eeb65dc5e66628429a64843327 0000000000000000000000000000000000000000 D      hello.c
3164         EOF
3165
3166         git diff-tree -M -r U^1 U >actual &&
3167
3168         compare_diff_raw expect actual
3169 '
3170
3171 ###
3172 ### series V (checkpoint)
3173 ###
3174
3175 # The commands in input_file should not produce any output on the file
3176 # descriptor set with --cat-blob-fd (or stdout if unspecified).
3177 #
3178 # To make sure you're observing the side effects of checkpoint *before*
3179 # fast-import terminates (and thus writes out its state), check that the
3180 # fast-import process is still running using background_import_still_running
3181 # *after* evaluating the test conditions.
3182 background_import_then_checkpoint () {
3183         options=$1
3184         input_file=$2
3185
3186         mkfifo V.input
3187         exec 8<>V.input
3188         rm V.input
3189
3190         mkfifo V.output
3191         exec 9<>V.output
3192         rm V.output
3193
3194         (
3195                 git fast-import $options <&8 >&9 &
3196                 echo $! >&9
3197                 wait $!
3198                 echo >&2 "background fast-import terminated too early with exit code $?"
3199                 # Un-block the read loop in the main shell process.
3200                 echo >&9 UNEXPECTED
3201         ) &
3202         sh_pid=$!
3203         read fi_pid <&9
3204         # We don't mind if fast-import has already died by the time the test
3205         # ends.
3206         test_when_finished "
3207                 exec 8>&-; exec 9>&-;
3208                 kill $sh_pid && wait $sh_pid
3209                 kill $fi_pid && wait $fi_pid
3210                 true"
3211
3212         # Start in the background to ensure we adhere strictly to (blocking)
3213         # pipes writing sequence. We want to assume that the write below could
3214         # block, e.g. if fast-import blocks writing its own output to &9
3215         # because there is no reader on &9 yet.
3216         (
3217                 cat "$input_file"
3218                 echo "checkpoint"
3219                 echo "progress checkpoint"
3220         ) >&8 &
3221
3222         error=1 ;# assume the worst
3223         while read output <&9
3224         do
3225                 if test "$output" = "progress checkpoint"
3226                 then
3227                         error=0
3228                         break
3229                 elif test "$output" = "UNEXPECTED"
3230                 then
3231                         break
3232                 fi
3233                 # otherwise ignore cruft
3234                 echo >&2 "cruft: $output"
3235         done
3236
3237         if test $error -eq 1
3238         then
3239                 false
3240         fi
3241 }
3242
3243 background_import_still_running () {
3244         if ! kill -0 "$fi_pid"
3245         then
3246                 echo >&2 "background fast-import terminated too early"
3247                 false
3248         fi
3249 }
3250
3251 test_expect_success PIPE 'V: checkpoint helper does not get stuck with extra output' '
3252         cat >input <<-INPUT_END &&
3253         progress foo
3254         progress bar
3255
3256         INPUT_END
3257
3258         background_import_then_checkpoint "" input &&
3259         background_import_still_running
3260 '
3261
3262 test_expect_success PIPE 'V: checkpoint updates refs after reset' '
3263         cat >input <<-\INPUT_END &&
3264         reset refs/heads/V
3265         from refs/heads/U
3266
3267         INPUT_END
3268
3269         background_import_then_checkpoint "" input &&
3270         test "$(git rev-parse --verify V)" = "$(git rev-parse --verify U)" &&
3271         background_import_still_running
3272 '
3273
3274 test_expect_success PIPE 'V: checkpoint updates refs and marks after commit' '
3275         cat >input <<-INPUT_END &&
3276         commit refs/heads/V
3277         mark :1
3278         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3279         data 0
3280         from refs/heads/U
3281
3282         INPUT_END
3283
3284         background_import_then_checkpoint "--export-marks=marks.actual" input &&
3285
3286         echo ":1 $(git rev-parse --verify V)" >marks.expected &&
3287
3288         test "$(git rev-parse --verify V^)" = "$(git rev-parse --verify U)" &&
3289         test_cmp marks.expected marks.actual &&
3290         background_import_still_running
3291 '
3292
3293 # Re-create the exact same commit, but on a different branch: no new object is
3294 # created in the database, but the refs and marks still need to be updated.
3295 test_expect_success PIPE 'V: checkpoint updates refs and marks after commit (no new objects)' '
3296         cat >input <<-INPUT_END &&
3297         commit refs/heads/V2
3298         mark :2
3299         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3300         data 0
3301         from refs/heads/U
3302
3303         INPUT_END
3304
3305         background_import_then_checkpoint "--export-marks=marks.actual" input &&
3306
3307         echo ":2 $(git rev-parse --verify V2)" >marks.expected &&
3308
3309         test "$(git rev-parse --verify V2)" = "$(git rev-parse --verify V)" &&
3310         test_cmp marks.expected marks.actual &&
3311         background_import_still_running
3312 '
3313
3314 test_expect_success PIPE 'V: checkpoint updates tags after tag' '
3315         cat >input <<-INPUT_END &&
3316         tag Vtag
3317         from refs/heads/V
3318         tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3319         data 0
3320
3321         INPUT_END
3322
3323         background_import_then_checkpoint "" input &&
3324         git show-ref -d Vtag &&
3325         background_import_still_running
3326 '
3327
3328 ###
3329 ### series W (get-mark and empty orphan commits)
3330 ###
3331
3332 cat >>W-input <<-W_INPUT_END
3333         commit refs/heads/W-branch
3334         mark :1
3335         author Full Name <user@company.tld> 1000000000 +0100
3336         committer Full Name <user@company.tld> 1000000000 +0100
3337         data 27
3338         Intentionally empty commit
3339         LFsget-mark :1
3340         W_INPUT_END
3341
3342 test_expect_success !MINGW 'W: get-mark & empty orphan commit with no newlines' '
3343         sed -e s/LFs// W-input | tr L "\n" | git fast-import
3344 '
3345
3346 test_expect_success !MINGW 'W: get-mark & empty orphan commit with one newline' '
3347         sed -e s/LFs/L/ W-input | tr L "\n" | git fast-import
3348 '
3349
3350 test_expect_success !MINGW 'W: get-mark & empty orphan commit with ugly second newline' '
3351         # Technically, this should fail as it has too many linefeeds
3352         # according to the grammar in fast-import.txt.  But, for whatever
3353         # reason, it works.  Since using the correct number of newlines
3354         # does not work with older (pre-2.22) versions of git, allow apps
3355         # that used this second-newline workaround to keep working by
3356         # checking it with this test...
3357         sed -e s/LFs/LL/ W-input | tr L "\n" | git fast-import
3358 '
3359
3360 test_expect_success !MINGW 'W: get-mark & empty orphan commit with erroneous third newline' '
3361         # ...but do NOT allow more empty lines than that (see previous test).
3362         sed -e s/LFs/LLL/ W-input | tr L "\n" | test_must_fail git fast-import
3363 '
3364
3365 ###
3366 ### series X (other new features)
3367 ###
3368
3369 test_expect_success 'X: handling encoding' '
3370         test_tick &&
3371         cat >input <<-INPUT_END &&
3372         commit refs/heads/encoding
3373         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3374         encoding iso-8859-7
3375         data <<COMMIT
3376         INPUT_END
3377
3378         printf "Pi: \360\nCOMMIT\n" >>input &&
3379
3380         git fast-import <input &&
3381         git cat-file -p encoding | grep $(printf "\360") &&
3382         git log -1 --format=%B encoding | grep $(printf "\317\200")
3383 '
3384
3385 test_done