t9300: don't create unused file
[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: only one import-marks feature allowed per stream' '
2147         cat >input <<-EOF &&
2148         feature import-marks=git.marks
2149         feature import-marks=git2.marks
2150         EOF
2151
2152         test_must_fail git fast-import <input
2153 '
2154
2155 test_expect_success 'R: export-marks feature results in a marks file being created' '
2156         cat >input <<-EOF &&
2157         feature export-marks=git.marks
2158         blob
2159         mark :1
2160         data 3
2161         hi
2162
2163         EOF
2164
2165         cat input | git fast-import &&
2166         grep :1 git.marks
2167 '
2168
2169 test_expect_success 'R: export-marks options can be overridden by commandline options' '
2170         cat input | git fast-import --export-marks=other.marks &&
2171         grep :1 other.marks
2172 '
2173
2174 test_expect_success 'R: catch typo in marks file name' '
2175         test_must_fail git fast-import --import-marks=nonexistent.marks </dev/null &&
2176         echo "feature import-marks=nonexistent.marks" |
2177         test_must_fail git fast-import
2178 '
2179
2180 test_expect_success 'R: import and output marks can be the same file' '
2181         rm -f io.marks &&
2182         blob=$(echo hi | git hash-object --stdin) &&
2183         cat >expect <<-EOF &&
2184         :1 $blob
2185         :2 $blob
2186         EOF
2187         git fast-import --export-marks=io.marks <<-\EOF &&
2188         blob
2189         mark :1
2190         data 3
2191         hi
2192
2193         EOF
2194         git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF &&
2195         blob
2196         mark :2
2197         data 3
2198         hi
2199
2200         EOF
2201         test_cmp expect io.marks
2202 '
2203
2204 test_expect_success 'R: --import-marks=foo --output-marks=foo to create foo fails' '
2205         rm -f io.marks &&
2206         test_must_fail git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF
2207         blob
2208         mark :1
2209         data 3
2210         hi
2211
2212         EOF
2213 '
2214
2215 test_expect_success 'R: --import-marks-if-exists' '
2216         rm -f io.marks &&
2217         blob=$(echo hi | git hash-object --stdin) &&
2218         echo ":1 $blob" >expect &&
2219         git fast-import --import-marks-if-exists=io.marks --export-marks=io.marks <<-\EOF &&
2220         blob
2221         mark :1
2222         data 3
2223         hi
2224
2225         EOF
2226         test_cmp expect io.marks
2227 '
2228
2229 test_expect_success 'R: feature import-marks-if-exists' '
2230         rm -f io.marks &&
2231
2232         git fast-import --export-marks=io.marks <<-\EOF &&
2233         feature import-marks-if-exists=not_io.marks
2234         EOF
2235         test_must_be_empty io.marks &&
2236
2237         blob=$(echo hi | git hash-object --stdin) &&
2238
2239         echo ":1 $blob" >io.marks &&
2240         echo ":1 $blob" >expect &&
2241         echo ":2 $blob" >>expect &&
2242
2243         git fast-import --export-marks=io.marks <<-\EOF &&
2244         feature import-marks-if-exists=io.marks
2245         blob
2246         mark :2
2247         data 3
2248         hi
2249
2250         EOF
2251         test_cmp expect io.marks &&
2252
2253         echo ":3 $blob" >>expect &&
2254
2255         git fast-import --import-marks=io.marks \
2256                         --export-marks=io.marks <<-\EOF &&
2257         feature import-marks-if-exists=not_io.marks
2258         blob
2259         mark :3
2260         data 3
2261         hi
2262
2263         EOF
2264         test_cmp expect io.marks &&
2265
2266         git fast-import --import-marks-if-exists=not_io.marks \
2267                         --export-marks=io.marks <<-\EOF &&
2268         feature import-marks-if-exists=io.marks
2269         EOF
2270         test_must_be_empty io.marks
2271 '
2272
2273 test_expect_success 'R: import to output marks works without any content' '
2274         cat >input <<-EOF &&
2275         feature import-marks=marks.out
2276         feature export-marks=marks.new
2277         EOF
2278
2279         cat input | git fast-import &&
2280         test_cmp marks.out marks.new
2281 '
2282
2283 test_expect_success 'R: import marks prefers commandline marks file over the stream' '
2284         cat >input <<-EOF &&
2285         feature import-marks=nonexistent.marks
2286         feature export-marks=marks.new
2287         EOF
2288
2289         cat input | git fast-import --import-marks=marks.out &&
2290         test_cmp marks.out marks.new
2291 '
2292
2293
2294 test_expect_success 'R: multiple --import-marks= should be honoured' '
2295         cat >input <<-EOF &&
2296         feature import-marks=nonexistent.marks
2297         feature export-marks=combined.marks
2298         EOF
2299
2300         head -n2 marks.out > one.marks &&
2301         tail -n +3 marks.out > two.marks &&
2302         git fast-import --import-marks=one.marks --import-marks=two.marks <input &&
2303         test_cmp marks.out combined.marks
2304 '
2305
2306 test_expect_success 'R: feature relative-marks should be honoured' '
2307         cat >input <<-EOF &&
2308         feature relative-marks
2309         feature import-marks=relative.in
2310         feature export-marks=relative.out
2311         EOF
2312
2313         mkdir -p .git/info/fast-import/ &&
2314         cp marks.new .git/info/fast-import/relative.in &&
2315         git fast-import <input &&
2316         test_cmp marks.new .git/info/fast-import/relative.out
2317 '
2318
2319 test_expect_success 'R: feature no-relative-marks should be honoured' '
2320         cat >input <<-EOF &&
2321         feature relative-marks
2322         feature import-marks=relative.in
2323         feature no-relative-marks
2324         feature export-marks=non-relative.out
2325         EOF
2326
2327         git fast-import <input &&
2328         test_cmp marks.new non-relative.out
2329 '
2330
2331 test_expect_success 'R: feature ls supported' '
2332         echo "feature ls" |
2333         git fast-import
2334 '
2335
2336 test_expect_success 'R: feature cat-blob supported' '
2337         echo "feature cat-blob" |
2338         git fast-import
2339 '
2340
2341 test_expect_success 'R: cat-blob-fd must be a nonnegative integer' '
2342         test_must_fail git fast-import --cat-blob-fd=-1 </dev/null
2343 '
2344
2345 test_expect_success !MINGW 'R: print old blob' '
2346         blob=$(echo "yes it can" | git hash-object -w --stdin) &&
2347         cat >expect <<-EOF &&
2348         ${blob} blob 11
2349         yes it can
2350
2351         EOF
2352         echo "cat-blob $blob" |
2353         git fast-import --cat-blob-fd=6 6>actual &&
2354         test_cmp expect actual
2355 '
2356
2357 test_expect_success !MINGW 'R: in-stream cat-blob-fd not respected' '
2358         echo hello >greeting &&
2359         blob=$(git hash-object -w greeting) &&
2360         cat >expect <<-EOF &&
2361         ${blob} blob 6
2362         hello
2363
2364         EOF
2365         git fast-import --cat-blob-fd=3 3>actual.3 >actual.1 <<-EOF &&
2366         cat-blob $blob
2367         EOF
2368         test_cmp expect actual.3 &&
2369         test_must_be_empty actual.1 &&
2370         git fast-import 3>actual.3 >actual.1 <<-EOF &&
2371         option cat-blob-fd=3
2372         cat-blob $blob
2373         EOF
2374         test_must_be_empty actual.3 &&
2375         test_cmp expect actual.1
2376 '
2377
2378 test_expect_success !MINGW 'R: print mark for new blob' '
2379         echo "effluentish" | git hash-object --stdin >expect &&
2380         git fast-import --cat-blob-fd=6 6>actual <<-\EOF &&
2381         blob
2382         mark :1
2383         data <<BLOB_END
2384         effluentish
2385         BLOB_END
2386         get-mark :1
2387         EOF
2388         test_cmp expect actual
2389 '
2390
2391 test_expect_success !MINGW 'R: print new blob' '
2392         blob=$(echo "yep yep yep" | git hash-object --stdin) &&
2393         cat >expect <<-EOF &&
2394         ${blob} blob 12
2395         yep yep yep
2396
2397         EOF
2398         git fast-import --cat-blob-fd=6 6>actual <<-\EOF &&
2399         blob
2400         mark :1
2401         data <<BLOB_END
2402         yep yep yep
2403         BLOB_END
2404         cat-blob :1
2405         EOF
2406         test_cmp expect actual
2407 '
2408
2409 test_expect_success !MINGW 'R: print new blob by sha1' '
2410         blob=$(echo "a new blob named by sha1" | git hash-object --stdin) &&
2411         cat >expect <<-EOF &&
2412         ${blob} blob 25
2413         a new blob named by sha1
2414
2415         EOF
2416         git fast-import --cat-blob-fd=6 6>actual <<-EOF &&
2417         blob
2418         data <<BLOB_END
2419         a new blob named by sha1
2420         BLOB_END
2421         cat-blob $blob
2422         EOF
2423         test_cmp expect actual
2424 '
2425
2426 test_expect_success 'setup: big file' '
2427         (
2428                 echo "the quick brown fox jumps over the lazy dog" >big &&
2429                 for i in 1 2 3
2430                 do
2431                         cat big big big big >bigger &&
2432                         cat bigger bigger bigger bigger >big ||
2433                         exit
2434                 done
2435         )
2436 '
2437
2438 test_expect_success 'R: print two blobs to stdout' '
2439         blob1=$(git hash-object big) &&
2440         blob1_len=$(wc -c <big) &&
2441         blob2=$(echo hello | git hash-object --stdin) &&
2442         {
2443                 echo ${blob1} blob $blob1_len &&
2444                 cat big &&
2445                 cat <<-EOF
2446
2447                 ${blob2} blob 6
2448                 hello
2449
2450                 EOF
2451         } >expect &&
2452         {
2453                 cat <<-\END_PART1 &&
2454                         blob
2455                         mark :1
2456                         data <<data_end
2457                 END_PART1
2458                 cat big &&
2459                 cat <<-\EOF
2460                         data_end
2461                         blob
2462                         mark :2
2463                         data <<data_end
2464                         hello
2465                         data_end
2466                         cat-blob :1
2467                         cat-blob :2
2468                 EOF
2469         } |
2470         git fast-import >actual &&
2471         test_cmp expect actual
2472 '
2473
2474 test_expect_success PIPE 'R: copy using cat-file' '
2475         expect_id=$(git hash-object big) &&
2476         expect_len=$(wc -c <big) &&
2477         echo $expect_id blob $expect_len >expect.response &&
2478
2479         rm -f blobs &&
2480
2481         mkfifo blobs &&
2482         (
2483                 export GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE &&
2484                 cat <<-\EOF &&
2485                 feature cat-blob
2486                 blob
2487                 mark :1
2488                 data <<BLOB
2489                 EOF
2490                 cat big &&
2491                 cat <<-\EOF &&
2492                 BLOB
2493                 cat-blob :1
2494                 EOF
2495
2496                 read blob_id type size <&3 &&
2497                 echo "$blob_id $type $size" >response &&
2498                 test_copy_bytes $size >blob <&3 &&
2499                 read newline <&3 &&
2500
2501                 cat <<-EOF &&
2502                 commit refs/heads/copied
2503                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2504                 data <<COMMIT
2505                 copy big file as file3
2506                 COMMIT
2507                 M 644 inline file3
2508                 data <<BLOB
2509                 EOF
2510                 cat blob &&
2511                 echo BLOB
2512         ) 3<blobs |
2513         git fast-import --cat-blob-fd=3 3>blobs &&
2514         git show copied:file3 >actual &&
2515         test_cmp expect.response response &&
2516         test_cmp big actual
2517 '
2518
2519 test_expect_success PIPE 'R: print blob mid-commit' '
2520         rm -f blobs &&
2521         echo "A blob from _before_ the commit." >expect &&
2522         mkfifo blobs &&
2523         (
2524                 exec 3<blobs &&
2525                 cat <<-EOF &&
2526                 feature cat-blob
2527                 blob
2528                 mark :1
2529                 data <<BLOB
2530                 A blob from _before_ the commit.
2531                 BLOB
2532                 commit refs/heads/temporary
2533                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2534                 data <<COMMIT
2535                 Empty commit
2536                 COMMIT
2537                 cat-blob :1
2538                 EOF
2539
2540                 read blob_id type size <&3 &&
2541                 test_copy_bytes $size >actual <&3 &&
2542                 read newline <&3 &&
2543
2544                 echo
2545         ) |
2546         git fast-import --cat-blob-fd=3 3>blobs &&
2547         test_cmp expect actual
2548 '
2549
2550 test_expect_success PIPE 'R: print staged blob within commit' '
2551         rm -f blobs &&
2552         echo "A blob from _within_ the commit." >expect &&
2553         mkfifo blobs &&
2554         (
2555                 exec 3<blobs &&
2556                 cat <<-EOF &&
2557                 feature cat-blob
2558                 commit refs/heads/within
2559                 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2560                 data <<COMMIT
2561                 Empty commit
2562                 COMMIT
2563                 M 644 inline within
2564                 data <<BLOB
2565                 A blob from _within_ the commit.
2566                 BLOB
2567                 EOF
2568
2569                 to_get=$(
2570                         echo "A blob from _within_ the commit." |
2571                         git hash-object --stdin
2572                 ) &&
2573                 echo "cat-blob $to_get" &&
2574
2575                 read blob_id type size <&3 &&
2576                 test_copy_bytes $size >actual <&3 &&
2577                 read newline <&3 &&
2578
2579                 echo deleteall
2580         ) |
2581         git fast-import --cat-blob-fd=3 3>blobs &&
2582         test_cmp expect actual
2583 '
2584
2585 test_expect_success 'R: quiet option results in no stats being output' '
2586         cat >input <<-EOF &&
2587         option git quiet
2588         blob
2589         data 3
2590         hi
2591
2592         EOF
2593
2594         cat input | git fast-import 2> output &&
2595         test_must_be_empty output
2596 '
2597
2598 test_expect_success 'R: feature done means terminating "done" is mandatory' '
2599         echo feature done | test_must_fail git fast-import &&
2600         test_must_fail git fast-import --done </dev/null
2601 '
2602
2603 test_expect_success 'R: terminating "done" with trailing gibberish is ok' '
2604         git fast-import <<-\EOF &&
2605         feature done
2606         done
2607         trailing gibberish
2608         EOF
2609         git fast-import <<-\EOF
2610         done
2611         more trailing gibberish
2612         EOF
2613 '
2614
2615 test_expect_success 'R: terminating "done" within commit' '
2616         cat >expect <<-\EOF &&
2617         OBJID
2618         :000000 100644 OBJID OBJID A    hello.c
2619         :000000 100644 OBJID OBJID A    hello2.c
2620         EOF
2621         git fast-import <<-EOF &&
2622         commit refs/heads/done-ends
2623         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2624         data <<EOT
2625         Commit terminated by "done" command
2626         EOT
2627         M 100644 inline hello.c
2628         data <<EOT
2629         Hello, world.
2630         EOT
2631         C hello.c hello2.c
2632         done
2633         EOF
2634         git rev-list done-ends |
2635         git diff-tree -r --stdin --root --always |
2636         sed -e "s/$OID_REGEX/OBJID/g" >actual &&
2637         test_cmp expect actual
2638 '
2639
2640 test_expect_success 'R: die on unknown option' '
2641         cat >input <<-EOF &&
2642         option git non-existing-option
2643         EOF
2644
2645         test_must_fail git fast-import <input
2646 '
2647
2648 test_expect_success 'R: unknown commandline options are rejected' '\
2649         test_must_fail git fast-import --non-existing-option < /dev/null
2650 '
2651
2652 test_expect_success 'R: die on invalid option argument' '
2653         echo "option git active-branches=-5" |
2654         test_must_fail git fast-import &&
2655         echo "option git depth=" |
2656         test_must_fail git fast-import &&
2657         test_must_fail git fast-import --depth="5 elephants" </dev/null
2658 '
2659
2660 test_expect_success 'R: ignore non-git options' '
2661         cat >input <<-EOF &&
2662         option non-existing-vcs non-existing-option
2663         EOF
2664
2665         git fast-import <input
2666 '
2667
2668 test_expect_success 'R: corrupt lines do not mess marks file' '
2669         rm -f io.marks &&
2670         blob=$(echo hi | git hash-object --stdin) &&
2671         cat >expect <<-EOF &&
2672         :3 0000000000000000000000000000000000000000
2673         :1 $blob
2674         :2 $blob
2675         EOF
2676         cp expect io.marks &&
2677         test_must_fail git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF &&
2678
2679         EOF
2680         test_cmp expect io.marks
2681 '
2682
2683 ##
2684 ## R: very large blobs
2685 ##
2686 test_expect_success 'R: blob bigger than threshold' '
2687         blobsize=$((2*1024*1024 + 53)) &&
2688         test-tool genrandom bar $blobsize >expect &&
2689         cat >input <<-INPUT_END &&
2690         commit refs/heads/big-file
2691         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2692         data <<COMMIT
2693         R - big file
2694         COMMIT
2695
2696         M 644 inline big1
2697         data $blobsize
2698         INPUT_END
2699         cat expect >>input &&
2700         cat >>input <<-INPUT_END &&
2701         M 644 inline big2
2702         data $blobsize
2703         INPUT_END
2704         cat expect >>input &&
2705         echo >>input &&
2706
2707         test_create_repo R &&
2708         git --git-dir=R/.git config fastimport.unpackLimit 0 &&
2709         git --git-dir=R/.git fast-import --big-file-threshold=1 <input
2710 '
2711
2712 test_expect_success 'R: verify created pack' '
2713         (
2714                 cd R &&
2715                 verify_packs -v > ../verify
2716         )
2717 '
2718
2719 test_expect_success 'R: verify written objects' '
2720         git --git-dir=R/.git cat-file blob big-file:big1 >actual &&
2721         test_cmp_bin expect actual &&
2722         a=$(git --git-dir=R/.git rev-parse big-file:big1) &&
2723         b=$(git --git-dir=R/.git rev-parse big-file:big2) &&
2724         test $a = $b
2725 '
2726
2727 test_expect_success 'R: blob appears only once' '
2728         n=$(grep $a verify | wc -l) &&
2729         test 1 = $n
2730 '
2731
2732 ###
2733 ### series S
2734 ###
2735 #
2736 # Make sure missing spaces and EOLs after mark references
2737 # cause errors.
2738 #
2739 # Setup:
2740 #
2741 #   1--2--4
2742 #    \   /
2743 #     -3-
2744 #
2745 #   commit marks:  301, 302, 303, 304
2746 #   blob marks:              403, 404, resp.
2747 #   note mark:          202
2748 #
2749 # The error message when a space is missing not at the
2750 # end of the line is:
2751 #
2752 #   Missing space after ..
2753 #
2754 # or when extra characters come after the mark at the end
2755 # of the line:
2756 #
2757 #   Garbage after ..
2758 #
2759 # or when the dataref is neither "inline " or a known SHA1,
2760 #
2761 #   Invalid dataref ..
2762 #
2763 test_expect_success 'S: initialize for S tests' '
2764         test_tick &&
2765
2766         cat >input <<-INPUT_END &&
2767         commit refs/heads/S
2768         mark :301
2769         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2770         data <<COMMIT
2771         commit 1
2772         COMMIT
2773         M 100644 inline hello.c
2774         data <<BLOB
2775         blob 1
2776         BLOB
2777
2778         commit refs/heads/S
2779         mark :302
2780         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2781         data <<COMMIT
2782         commit 2
2783         COMMIT
2784         from :301
2785         M 100644 inline hello.c
2786         data <<BLOB
2787         blob 2
2788         BLOB
2789
2790         blob
2791         mark :403
2792         data <<BLOB
2793         blob 3
2794         BLOB
2795
2796         blob
2797         mark :202
2798         data <<BLOB
2799         note 2
2800         BLOB
2801         INPUT_END
2802
2803         git fast-import --export-marks=marks <input
2804 '
2805
2806 #
2807 # filemodify, three datarefs
2808 #
2809 test_expect_success 'S: filemodify with garbage after mark must fail' '
2810         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2811         commit refs/heads/S
2812         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2813         data <<COMMIT
2814         commit N
2815         COMMIT
2816         M 100644 :403x hello.c
2817         EOF
2818         test_i18ngrep "space after mark" err
2819 '
2820
2821 # inline is misspelled; fast-import thinks it is some unknown dataref
2822 test_expect_success 'S: filemodify with garbage after inline must fail' '
2823         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2824         commit refs/heads/S
2825         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2826         data <<COMMIT
2827         commit N
2828         COMMIT
2829         M 100644 inlineX hello.c
2830         data <<BLOB
2831         inline
2832         BLOB
2833         EOF
2834         test_i18ngrep "nvalid dataref" err
2835 '
2836
2837 test_expect_success 'S: filemodify with garbage after sha1 must fail' '
2838         sha1=$(grep :403 marks | cut -d\  -f2) &&
2839         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2840         commit refs/heads/S
2841         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2842         data <<COMMIT
2843         commit N
2844         COMMIT
2845         M 100644 ${sha1}x hello.c
2846         EOF
2847         test_i18ngrep "space after SHA1" err
2848 '
2849
2850 #
2851 # notemodify, three ways to say dataref
2852 #
2853 test_expect_success 'S: notemodify with garbage after mark dataref must fail' '
2854         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2855         commit refs/heads/S
2856         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2857         data <<COMMIT
2858         commit S note dataref markref
2859         COMMIT
2860         N :202x :302
2861         EOF
2862         test_i18ngrep "space after mark" err
2863 '
2864
2865 test_expect_success 'S: notemodify with garbage after inline dataref must fail' '
2866         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2867         commit refs/heads/S
2868         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2869         data <<COMMIT
2870         commit S note dataref inline
2871         COMMIT
2872         N inlineX :302
2873         data <<BLOB
2874         note blob
2875         BLOB
2876         EOF
2877         test_i18ngrep "nvalid dataref" err
2878 '
2879
2880 test_expect_success 'S: notemodify with garbage after sha1 dataref must fail' '
2881         sha1=$(grep :202 marks | cut -d\  -f2) &&
2882         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2883         commit refs/heads/S
2884         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2885         data <<COMMIT
2886         commit S note dataref sha1
2887         COMMIT
2888         N ${sha1}x :302
2889         EOF
2890         test_i18ngrep "space after SHA1" err
2891 '
2892
2893 #
2894 # notemodify, mark in commit-ish
2895 #
2896 test_expect_success 'S: notemodify with garbage after mark commit-ish must fail' '
2897         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2898         commit refs/heads/Snotes
2899         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2900         data <<COMMIT
2901         commit S note commit-ish
2902         COMMIT
2903         N :202 :302x
2904         EOF
2905         test_i18ngrep "after mark" err
2906 '
2907
2908 #
2909 # from
2910 #
2911 test_expect_success 'S: from with garbage after mark must fail' '
2912         test_must_fail \
2913         git fast-import --import-marks=marks --export-marks=marks <<-EOF 2>err &&
2914         commit refs/heads/S2
2915         mark :303
2916         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2917         data <<COMMIT
2918         commit 3
2919         COMMIT
2920         from :301x
2921         M 100644 :403 hello.c
2922         EOF
2923
2924
2925         # go create the commit, need it for merge test
2926         git fast-import --import-marks=marks --export-marks=marks <<-EOF &&
2927         commit refs/heads/S2
2928         mark :303
2929         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2930         data <<COMMIT
2931         commit 3
2932         COMMIT
2933         from :301
2934         M 100644 :403 hello.c
2935         EOF
2936
2937         # now evaluate the error
2938         test_i18ngrep "after mark" err
2939 '
2940
2941
2942 #
2943 # merge
2944 #
2945 test_expect_success 'S: merge with garbage after mark must fail' '
2946         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2947         commit refs/heads/S
2948         mark :304
2949         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2950         data <<COMMIT
2951         merge 4
2952         COMMIT
2953         from :302
2954         merge :303x
2955         M 100644 :403 hello.c
2956         EOF
2957         test_i18ngrep "after mark" err
2958 '
2959
2960 #
2961 # tag, from markref
2962 #
2963 test_expect_success 'S: tag with garbage after mark must fail' '
2964         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2965         tag refs/tags/Stag
2966         from :302x
2967         tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
2968         data <<TAG
2969         tag S
2970         TAG
2971         EOF
2972         test_i18ngrep "after mark" err
2973 '
2974
2975 #
2976 # cat-blob markref
2977 #
2978 test_expect_success 'S: cat-blob with garbage after mark must fail' '
2979         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2980         cat-blob :403x
2981         EOF
2982         test_i18ngrep "after mark" err
2983 '
2984
2985 #
2986 # ls markref
2987 #
2988 test_expect_success 'S: ls with garbage after mark must fail' '
2989         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2990         ls :302x hello.c
2991         EOF
2992         test_i18ngrep "space after mark" err
2993 '
2994
2995 test_expect_success 'S: ls with garbage after sha1 must fail' '
2996         sha1=$(grep :302 marks | cut -d\  -f2) &&
2997         test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
2998         ls ${sha1}x hello.c
2999         EOF
3000         test_i18ngrep "space after tree-ish" err
3001 '
3002
3003 ###
3004 ### series T (ls)
3005 ###
3006 # Setup is carried over from series S.
3007
3008 test_expect_success 'T: ls root tree' '
3009         sed -e "s/Z\$//" >expect <<-EOF &&
3010         040000 tree $(git rev-parse S^{tree})   Z
3011         EOF
3012         sha1=$(git rev-parse --verify S) &&
3013         git fast-import --import-marks=marks <<-EOF >actual &&
3014         ls $sha1 ""
3015         EOF
3016         test_cmp expect actual
3017 '
3018
3019 test_expect_success 'T: delete branch' '
3020         git branch to-delete &&
3021         git fast-import <<-EOF &&
3022         reset refs/heads/to-delete
3023         from 0000000000000000000000000000000000000000
3024         EOF
3025         test_must_fail git rev-parse --verify refs/heads/to-delete
3026 '
3027
3028 test_expect_success 'T: empty reset doesnt delete branch' '
3029         git branch not-to-delete &&
3030         git fast-import <<-EOF &&
3031         reset refs/heads/not-to-delete
3032         EOF
3033         git show-ref &&
3034         git rev-parse --verify refs/heads/not-to-delete
3035 '
3036
3037 ###
3038 ### series U (filedelete)
3039 ###
3040
3041 test_expect_success 'U: initialize for U tests' '
3042         cat >input <<-INPUT_END &&
3043         commit refs/heads/U
3044         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3045         data <<COMMIT
3046         test setup
3047         COMMIT
3048         M 100644 inline hello.c
3049         data <<BLOB
3050         blob 1
3051         BLOB
3052         M 100644 inline good/night.txt
3053         data <<BLOB
3054         sleep well
3055         BLOB
3056         M 100644 inline good/bye.txt
3057         data <<BLOB
3058         au revoir
3059         BLOB
3060
3061         INPUT_END
3062
3063         git fast-import <input
3064 '
3065
3066 test_expect_success 'U: filedelete file succeeds' '
3067         cat >input <<-INPUT_END &&
3068         commit refs/heads/U
3069         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3070         data <<COMMIT
3071         delete good/night.txt
3072         COMMIT
3073         from refs/heads/U^0
3074         D good/night.txt
3075
3076         INPUT_END
3077
3078         git fast-import <input
3079 '
3080
3081 test_expect_success 'U: validate file delete result' '
3082         cat >expect <<-EOF &&
3083         :100644 000000 2907ebb4bf85d91bf0716bb3bd8a68ef48d6da76 0000000000000000000000000000000000000000 D      good/night.txt
3084         EOF
3085
3086         git diff-tree -M -r U^1 U >actual &&
3087
3088         compare_diff_raw expect actual
3089 '
3090
3091 test_expect_success 'U: filedelete directory succeeds' '
3092         cat >input <<-INPUT_END &&
3093         commit refs/heads/U
3094         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3095         data <<COMMIT
3096         delete good dir
3097         COMMIT
3098         from refs/heads/U^0
3099         D good
3100
3101         INPUT_END
3102
3103         git fast-import <input
3104 '
3105
3106 test_expect_success 'U: validate directory delete result' '
3107         cat >expect <<-EOF &&
3108         :100644 000000 69cb75792f55123d8389c156b0b41c2ff00ed507 0000000000000000000000000000000000000000 D      good/bye.txt
3109         EOF
3110
3111         git diff-tree -M -r U^1 U >actual &&
3112
3113         compare_diff_raw expect actual
3114 '
3115
3116 test_expect_success 'U: filedelete root succeeds' '
3117         cat >input <<-INPUT_END &&
3118         commit refs/heads/U
3119         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3120         data <<COMMIT
3121         must succeed
3122         COMMIT
3123         from refs/heads/U^0
3124         D ""
3125
3126         INPUT_END
3127
3128         git fast-import <input
3129 '
3130
3131 test_expect_success 'U: validate root delete result' '
3132         cat >expect <<-EOF &&
3133         :100644 000000 c18147dc648481eeb65dc5e66628429a64843327 0000000000000000000000000000000000000000 D      hello.c
3134         EOF
3135
3136         git diff-tree -M -r U^1 U >actual &&
3137
3138         compare_diff_raw expect actual
3139 '
3140
3141 ###
3142 ### series V (checkpoint)
3143 ###
3144
3145 # The commands in input_file should not produce any output on the file
3146 # descriptor set with --cat-blob-fd (or stdout if unspecified).
3147 #
3148 # To make sure you're observing the side effects of checkpoint *before*
3149 # fast-import terminates (and thus writes out its state), check that the
3150 # fast-import process is still running using background_import_still_running
3151 # *after* evaluating the test conditions.
3152 background_import_then_checkpoint () {
3153         options=$1
3154         input_file=$2
3155
3156         mkfifo V.input
3157         exec 8<>V.input
3158         rm V.input
3159
3160         mkfifo V.output
3161         exec 9<>V.output
3162         rm V.output
3163
3164         git fast-import $options <&8 >&9 &
3165         echo $! >V.pid
3166         # We don't mind if fast-import has already died by the time the test
3167         # ends.
3168         test_when_finished "
3169                 exec 8>&-; exec 9>&-;
3170                 kill $(cat V.pid) && wait $(cat V.pid)
3171                 true"
3172
3173         # Start in the background to ensure we adhere strictly to (blocking)
3174         # pipes writing sequence. We want to assume that the write below could
3175         # block, e.g. if fast-import blocks writing its own output to &9
3176         # because there is no reader on &9 yet.
3177         (
3178                 cat "$input_file"
3179                 echo "checkpoint"
3180                 echo "progress checkpoint"
3181         ) >&8 &
3182
3183         error=1 ;# assume the worst
3184         while read output <&9
3185         do
3186                 if test "$output" = "progress checkpoint"
3187                 then
3188                         error=0
3189                         break
3190                 fi
3191                 # otherwise ignore cruft
3192                 echo >&2 "cruft: $output"
3193         done
3194
3195         if test $error -eq 1
3196         then
3197                 false
3198         fi
3199 }
3200
3201 background_import_still_running () {
3202         if ! kill -0 "$(cat V.pid)"
3203         then
3204                 echo >&2 "background fast-import terminated too early"
3205                 false
3206         fi
3207 }
3208
3209 test_expect_success PIPE 'V: checkpoint helper does not get stuck with extra output' '
3210         cat >input <<-INPUT_END &&
3211         progress foo
3212         progress bar
3213
3214         INPUT_END
3215
3216         background_import_then_checkpoint "" input &&
3217         background_import_still_running
3218 '
3219
3220 test_expect_success PIPE 'V: checkpoint updates refs after reset' '
3221         cat >input <<-\INPUT_END &&
3222         reset refs/heads/V
3223         from refs/heads/U
3224
3225         INPUT_END
3226
3227         background_import_then_checkpoint "" input &&
3228         test "$(git rev-parse --verify V)" = "$(git rev-parse --verify U)" &&
3229         background_import_still_running
3230 '
3231
3232 test_expect_success PIPE 'V: checkpoint updates refs and marks after commit' '
3233         cat >input <<-INPUT_END &&
3234         commit refs/heads/V
3235         mark :1
3236         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3237         data 0
3238         from refs/heads/U
3239
3240         INPUT_END
3241
3242         background_import_then_checkpoint "--export-marks=marks.actual" input &&
3243
3244         echo ":1 $(git rev-parse --verify V)" >marks.expected &&
3245
3246         test "$(git rev-parse --verify V^)" = "$(git rev-parse --verify U)" &&
3247         test_cmp marks.expected marks.actual &&
3248         background_import_still_running
3249 '
3250
3251 # Re-create the exact same commit, but on a different branch: no new object is
3252 # created in the database, but the refs and marks still need to be updated.
3253 test_expect_success PIPE 'V: checkpoint updates refs and marks after commit (no new objects)' '
3254         cat >input <<-INPUT_END &&
3255         commit refs/heads/V2
3256         mark :2
3257         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3258         data 0
3259         from refs/heads/U
3260
3261         INPUT_END
3262
3263         background_import_then_checkpoint "--export-marks=marks.actual" input &&
3264
3265         echo ":2 $(git rev-parse --verify V2)" >marks.expected &&
3266
3267         test "$(git rev-parse --verify V2)" = "$(git rev-parse --verify V)" &&
3268         test_cmp marks.expected marks.actual &&
3269         background_import_still_running
3270 '
3271
3272 test_expect_success PIPE 'V: checkpoint updates tags after tag' '
3273         cat >input <<-INPUT_END &&
3274         tag Vtag
3275         from refs/heads/V
3276         tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3277         data 0
3278
3279         INPUT_END
3280
3281         background_import_then_checkpoint "" input &&
3282         git show-ref -d Vtag &&
3283         background_import_still_running
3284 '
3285
3286 ###
3287 ### series W (get-mark and empty orphan commits)
3288 ###
3289
3290 cat >>W-input <<-W_INPUT_END
3291         commit refs/heads/W-branch
3292         mark :1
3293         author Full Name <user@company.tld> 1000000000 +0100
3294         committer Full Name <user@company.tld> 1000000000 +0100
3295         data 27
3296         Intentionally empty commit
3297         LFsget-mark :1
3298         W_INPUT_END
3299
3300 test_expect_success !MINGW 'W: get-mark & empty orphan commit with no newlines' '
3301         sed -e s/LFs// W-input | tr L "\n" | git fast-import
3302 '
3303
3304 test_expect_success !MINGW 'W: get-mark & empty orphan commit with one newline' '
3305         sed -e s/LFs/L/ W-input | tr L "\n" | git fast-import
3306 '
3307
3308 test_expect_success !MINGW 'W: get-mark & empty orphan commit with ugly second newline' '
3309         # Technically, this should fail as it has too many linefeeds
3310         # according to the grammar in fast-import.txt.  But, for whatever
3311         # reason, it works.  Since using the correct number of newlines
3312         # does not work with older (pre-2.22) versions of git, allow apps
3313         # that used this second-newline workaround to keep working by
3314         # checking it with this test...
3315         sed -e s/LFs/LL/ W-input | tr L "\n" | git fast-import
3316 '
3317
3318 test_expect_success !MINGW 'W: get-mark & empty orphan commit with erroneous third newline' '
3319         # ...but do NOT allow more empty lines than that (see previous test).
3320         sed -e s/LFs/LLL/ W-input | tr L "\n" | test_must_fail git fast-import
3321 '
3322
3323 ###
3324 ### series X (other new features)
3325 ###
3326
3327 test_expect_success 'X: handling encoding' '
3328         test_tick &&
3329         cat >input <<-INPUT_END &&
3330         commit refs/heads/encoding
3331         committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3332         encoding iso-8859-7
3333         data <<COMMIT
3334         INPUT_END
3335
3336         printf "Pi: \360\nCOMMIT\n" >>input &&
3337
3338         git fast-import <input &&
3339         git cat-file -p encoding | grep $(printf "\360") &&
3340         git log -1 --format=%B encoding | grep $(printf "\317\200")
3341 '
3342
3343 test_done