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