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