Raw
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Johannes E. Schindelin
4 #
5
6 test_description='git fast-export'
7 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
8 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
9
10 . ./test-lib.sh
11 . "$TEST_DIRECTORY/lib-gpg.sh"
12
13 test_expect_success 'setup' '
14
15 echo break it > file0 &&
16 git add file0 &&
17 test_tick &&
18 echo Wohlauf > file &&
19 git add file &&
20 test_tick &&
21 git commit -m initial &&
22 echo die Luft > file &&
23 echo geht frisch > file2 &&
24 git add file file2 &&
25 test_tick &&
26 git commit -m second &&
27 echo und > file2 &&
28 test_tick &&
29 git commit -m third file2 &&
30 test_tick &&
31 git tag rein &&
32 git checkout -b wer HEAD^ &&
33 echo lange > file2 &&
34 test_tick &&
35 git commit -m sitzt file2 &&
36 test_tick &&
37 git tag -a -m valentin muss &&
38 ANNOTATED_TAG_COUNT=1 &&
39 git merge -s ours main
40
41 '
42
43 test_expect_success 'fast-export | fast-import' '
44
45 MAIN=$(git rev-parse --verify main) &&
46 REIN=$(git rev-parse --verify rein) &&
47 WER=$(git rev-parse --verify wer) &&
48 MUSS=$(git rev-parse --verify muss) &&
49 mkdir new &&
50 git --git-dir=new/.git init &&
51 git fast-export --all >actual &&
52 git -C new fast-import <actual &&
53 test $MAIN = $(git -C new rev-parse --verify refs/heads/main) &&
54 test $REIN = $(git -C new rev-parse --verify refs/tags/rein) &&
55 test $WER = $(git -C new rev-parse --verify refs/heads/wer) &&
56 test $MUSS = $(git -C new rev-parse --verify refs/tags/muss)
57
58 '
59
60 test_expect_success 'fast-export ^muss^{commit} muss' '
61 git fast-export --tag-of-filtered-object=rewrite ^muss^{commit} muss >actual &&
62 cat >expected <<-EOF &&
63 tag muss
64 from $(git rev-parse --verify muss^{commit})
65 $(git cat-file tag muss | grep tagger)
66 data 9
67 valentin
68
69 EOF
70 test_cmp expected actual
71 '
72
73 test_expect_success 'fast-export --mark-tags ^muss^{commit} muss' '
74 git fast-export --mark-tags --tag-of-filtered-object=rewrite ^muss^{commit} muss >actual &&
75 cat >expected <<-EOF &&
76 tag muss
77 mark :1
78 from $(git rev-parse --verify muss^{commit})
79 $(git cat-file tag muss | grep tagger)
80 data 9
81 valentin
82
83 EOF
84 test_cmp expected actual
85 '
86
87 test_expect_success 'fast-export main~2..main' '
88
89 git fast-export main~2..main >actual &&
90 sed "s/main/partial/" actual | git -C new fast-import &&
91 test $MAIN != $(git -C new rev-parse --verify refs/heads/partial) &&
92 git -C new diff --exit-code main partial &&
93 git -C new diff --exit-code main^ partial^ &&
94 test_must_fail git -C new rev-parse partial~2
95
96 '
97
98 test_expect_success 'fast-export --reference-excluded-parents main~2..main' '
99
100 git fast-export --reference-excluded-parents main~2..main >actual &&
101 grep commit.refs/heads/main actual >commit-count &&
102 test_line_count = 2 commit-count &&
103 sed "s/main/rewrite/" actual | git -C new fast-import &&
104 test $MAIN = $(git -C new rev-parse --verify refs/heads/rewrite)
105 '
106
107 test_expect_success 'fast-export --show-original-ids' '
108
109 git fast-export --show-original-ids main >output &&
110 grep ^original-oid output| sed -e s/^original-oid.// | sort >actual &&
111 git rev-list --objects main muss >objects-and-names &&
112 awk "{print \$1}" objects-and-names | sort >commits-trees-blobs &&
113 comm -23 actual commits-trees-blobs >unfound &&
114 test_must_be_empty unfound
115 '
116
117 test_expect_success 'fast-export --show-original-ids | git fast-import' '
118
119 git fast-export --show-original-ids main muss | git fast-import --quiet &&
120 test $MAIN = $(git rev-parse --verify refs/heads/main) &&
121 test $MUSS = $(git rev-parse --verify refs/tags/muss)
122 '
123
124 test_expect_success ICONV 'reencoding iso-8859-7' '
125
126 test_when_finished "git reset --hard HEAD~1" &&
127 test_config i18n.commitencoding iso-8859-7 &&
128 test_tick &&
129 echo rosten >file &&
130 git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file &&
131 git fast-export --reencode=yes wer^..wer >iso-8859-7.fi &&
132 sed "s/wer/i18n/" iso-8859-7.fi | git -C new fast-import &&
133
134 # The commit object, if not re-encoded, would be 200 bytes plus hash.
135 # Removing the "encoding iso-8859-7\n" header drops 20 bytes.
136 # Re-encoding the Pi character from \xF0 (\360) in iso-8859-7
137 # to \xCF\x80 (\317\200) in UTF-8 adds a byte. Check for
138 # the expected size.
139 test $(($(test_oid hexsz) + 181)) -eq "$(git -C new cat-file -s i18n)" &&
140 # ...and for the expected translation of bytes.
141 git -C new cat-file commit i18n >actual &&
142 grep $(printf "\317\200") actual &&
143 # Also make sure the commit does not have the "encoding" header
144 ! grep ^encoding actual
145 '
146
147 test_expect_success 'aborting on iso-8859-7' '
148
149 test_when_finished "git reset --hard HEAD~1" &&
150 test_config i18n.commitencoding iso-8859-7 &&
151 echo rosten >file &&
152 git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file &&
153 test_must_fail git fast-export --reencode=abort wer^..wer >iso-8859-7.fi
154 '
155
156 test_expect_success 'preserving iso-8859-7' '
157
158 test_when_finished "git reset --hard HEAD~1" &&
159 test_config i18n.commitencoding iso-8859-7 &&
160 echo rosten >file &&
161 git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file &&
162 git fast-export --reencode=no wer^..wer >iso-8859-7.fi &&
163 sed "s/wer/i18n-no-recoding/" iso-8859-7.fi | git -C new fast-import &&
164
165 # The commit object, if not re-encoded, is 200 bytes plus hash.
166 # Removing the "encoding iso-8859-7\n" header would drops 20
167 # bytes. Re-encoding the Pi character from \xF0 (\360) in
168 # iso-8859-7 to \xCF\x80 (\317\200) in UTF-8 adds a byte.
169 # Check for the expected size...
170 test $(($(test_oid hexsz) + 200)) -eq "$(git -C new cat-file -s i18n-no-recoding)" &&
171 # ...as well as the expected byte.
172 git -C new cat-file commit i18n-no-recoding >actual &&
173 grep $(printf "\360") actual &&
174 # Also make sure the commit has the "encoding" header
175 grep ^encoding actual
176 '
177
178 test_expect_success 'encoding preserved if reencoding fails' '
179
180 test_when_finished "git reset --hard HEAD~1" &&
181 test_config i18n.commitencoding iso-8859-7 &&
182 echo rosten >file &&
183 git commit -s -F "$TEST_DIRECTORY/t9350/broken-iso-8859-7-commit-message.txt" file &&
184 git fast-export --reencode=yes wer^..wer >iso-8859-7.fi &&
185 sed "s/wer/i18n-invalid/" iso-8859-7.fi | git -C new fast-import &&
186 git -C new cat-file commit i18n-invalid >actual &&
187
188 # Make sure the commit still has the encoding header
189 grep ^encoding actual &&
190 # Verify that the commit has the expected size; i.e.
191 # that no bytes were re-encoded to a different encoding.
192 test $(($(test_oid hexsz) + 212)) -eq "$(git -C new cat-file -s i18n-invalid)" &&
193 # ...and check for the original special bytes
194 grep $(printf "\360") actual &&
195 grep $(printf "\377") actual
196 '
197
198 test_expect_success 'import/export-marks' '
199
200 git checkout -b marks main &&
201 git fast-export --export-marks=tmp-marks HEAD &&
202 test -s tmp-marks &&
203 test_line_count = 3 tmp-marks &&
204 git fast-export --import-marks=tmp-marks \
205 --export-marks=tmp-marks HEAD >actual &&
206 test $(grep ^commit actual | wc -l) -eq 0 &&
207 echo change > file &&
208 git commit -m "last commit" file &&
209 git fast-export --import-marks=tmp-marks \
210 --export-marks=tmp-marks HEAD >actual &&
211 test $(grep ^commit\ actual | wc -l) -eq 1 &&
212 test_line_count = 4 tmp-marks
213
214 '
215
216 cat > signed-tag-import << EOF
217 tag sign-your-name
218 from $(git rev-parse HEAD)
219 tagger C O Mitter <committer@example.com> 1112911993 -0700
220 data 210
221 A message for a sign
222 -----BEGIN PGP SIGNATURE-----
223 Version: GnuPG v1.4.5 (GNU/Linux)
224
225 fakedsignaturefakedsignaturefakedsignaturefakedsignaturfakedsign
226 aturefakedsignaturefake=
227 =/59v
228 -----END PGP SIGNATURE-----
229 EOF
230
231 test_expect_success 'set up faked signed tag' '
232
233 git fast-import <signed-tag-import &&
234 ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1))
235
236 '
237
238 test_expect_success 'signed-tags=abort' '
239
240 test_must_fail git fast-export --signed-tags=abort sign-your-name
241
242 '
243
244 test_expect_success 'signed-tags=verbatim' '
245
246 git fast-export --signed-tags=verbatim sign-your-name > output &&
247 grep PGP output
248
249 '
250
251 test_expect_success 'signed-tags=warn-verbatim' '
252
253 git fast-export --signed-tags=warn-verbatim sign-your-name >output 2>err &&
254 grep PGP output &&
255 test -s err
256
257 '
258
259 # 'warn' is a backward-compatibility alias for 'warn-verbatim'; test
260 # that it keeps working.
261 test_expect_success 'signed-tags=warn' '
262
263 git fast-export --signed-tags=warn sign-your-name >output 2>err &&
264 grep PGP output &&
265 test -s err
266
267 '
268
269 test_expect_success 'signed-tags=strip' '
270
271 git fast-export --signed-tags=strip sign-your-name > output &&
272 ! grep PGP output
273
274 '
275
276 test_expect_success 'signed-tags=warn-strip' '
277 git fast-export --signed-tags=warn-strip sign-your-name >output 2>err &&
278 ! grep PGP output &&
279 test -s err
280 '
281
282 test_expect_success GPGSM 'setup X.509 signed tag' '
283 test_config gpg.format x509 &&
284 test_config user.signingkey $GIT_COMMITTER_EMAIL &&
285
286 git tag -s -m "X.509 signed tag" x509-signed $(git rev-parse HEAD) &&
287 ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1))
288 '
289
290 test_expect_success GPGSM 'signed-tags=verbatim with X.509' '
291 git fast-export --signed-tags=verbatim x509-signed > output &&
292 test_grep "SIGNED MESSAGE" output
293 '
294
295 test_expect_success GPGSM 'signed-tags=strip with X.509' '
296 git fast-export --signed-tags=strip x509-signed > output &&
297 test_grep ! "SIGNED MESSAGE" output
298 '
299
300 test_expect_success GPGSSH 'setup SSH signed tag' '
301 test_config gpg.format ssh &&
302 test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
303
304 git tag -s -m "SSH signed tag" ssh-signed $(git rev-parse HEAD) &&
305 ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1))
306 '
307
308 test_expect_success GPGSSH 'signed-tags=verbatim with SSH' '
309 git fast-export --signed-tags=verbatim ssh-signed > output &&
310 test_grep "SSH SIGNATURE" output
311 '
312
313 test_expect_success GPGSSH 'signed-tags=strip with SSH' '
314 git fast-export --signed-tags=strip ssh-signed > output &&
315 test_grep ! "SSH SIGNATURE" output
316 '
317
318 test_expect_success GPG 'set up signed commit' '
319
320 # Generate a commit with both "gpgsig" and "encoding" set, so
321 # that we can test that fast-import gets the ordering correct
322 # between the two.
323 test_config i18n.commitEncoding ISO-8859-1 &&
324 git checkout -f -b commit-signing main &&
325 echo Sign your name >file-sign &&
326 git add file-sign &&
327 git commit -S -m "signed commit" &&
328 COMMIT_SIGNING=$(git rev-parse --verify commit-signing)
329
330 '
331
332 test_expect_success GPG 'signed-commits default is same as strip' '
333 git fast-export --reencode=no commit-signing >out1 2>err &&
334 git fast-export --reencode=no --signed-commits=strip commit-signing >out2 &&
335 test_cmp out1 out2
336 '
337
338 test_expect_success GPG 'signed-commits=abort' '
339
340 test_must_fail git fast-export --signed-commits=abort commit-signing
341
342 '
343
344 test_expect_success GPG 'signed-commits=verbatim' '
345
346 git fast-export --signed-commits=verbatim --reencode=no commit-signing >output &&
347 test_grep -E "^gpgsig $GIT_DEFAULT_HASH openpgp" output &&
348 grep "encoding ISO-8859-1" output &&
349 git -C new fast-import <output &&
350 STRIPPED=$(git -C new rev-parse --verify refs/heads/commit-signing) &&
351 test $COMMIT_SIGNING = $STRIPPED
352
353 '
354
355 test_expect_success GPG 'signed-commits=warn-verbatim' '
356
357 git fast-export --signed-commits=warn-verbatim --reencode=no commit-signing >output 2>err &&
358 test_grep -E "^gpgsig $GIT_DEFAULT_HASH openpgp" output &&
359 grep "encoding ISO-8859-1" output &&
360 test -s err &&
361 git -C new fast-import <output &&
362 STRIPPED=$(git -C new rev-parse --verify refs/heads/commit-signing) &&
363 test $COMMIT_SIGNING = $STRIPPED
364
365 '
366
367 test_expect_success GPG 'signed-commits=strip' '
368
369 git fast-export --signed-commits=strip --reencode=no commit-signing >output &&
370 ! grep ^gpgsig output &&
371 grep "^encoding ISO-8859-1" output &&
372 sed "s/commit-signing/commit-strip-signing/" output | git -C new fast-import &&
373 STRIPPED=$(git -C new rev-parse --verify refs/heads/commit-strip-signing) &&
374 test $COMMIT_SIGNING != $STRIPPED
375
376 '
377
378 test_expect_success GPG 'signed-commits=warn-strip' '
379
380 git fast-export --signed-commits=warn-strip --reencode=no commit-signing >output 2>err &&
381 ! grep ^gpgsig output &&
382 grep "^encoding ISO-8859-1" output &&
383 test -s err &&
384 sed "s/commit-signing/commit-strip-signing/" output | git -C new fast-import &&
385 STRIPPED=$(git -C new rev-parse --verify refs/heads/commit-strip-signing) &&
386 test $COMMIT_SIGNING != $STRIPPED
387
388 '
389
390 test_expect_success GPGSM 'setup X.509 signed commit' '
391
392 git checkout -b x509-signing main &&
393 test_config gpg.format x509 &&
394 test_config user.signingkey $GIT_COMMITTER_EMAIL &&
395 echo "X.509 content" >file &&
396 git add file &&
397 git commit -S -m "X.509 signed commit" &&
398 X509_COMMIT=$(git rev-parse HEAD) &&
399 git checkout main
400
401 '
402
403 test_expect_success GPGSM 'round-trip X.509 signed commit' '
404
405 git fast-export --signed-commits=verbatim x509-signing >output &&
406 test_grep -E "^gpgsig $GIT_DEFAULT_HASH x509" output &&
407 git -C new fast-import <output &&
408 git -C new cat-file commit refs/heads/x509-signing >actual &&
409 grep "^gpgsig" actual &&
410 IMPORTED=$(git -C new rev-parse refs/heads/x509-signing) &&
411 test $X509_COMMIT = $IMPORTED
412
413 '
414
415 test_expect_success GPGSSH 'setup SSH signed commit' '
416
417 git checkout -b ssh-signing main &&
418 test_config gpg.format ssh &&
419 test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
420 echo "SSH content" >file &&
421 git add file &&
422 git commit -S -m "SSH signed commit" &&
423 SSH_COMMIT=$(git rev-parse HEAD) &&
424 git checkout main
425
426 '
427
428 test_expect_success GPGSSH 'round-trip SSH signed commit' '
429
430 git fast-export --signed-commits=verbatim ssh-signing >output &&
431 test_grep -E "^gpgsig $GIT_DEFAULT_HASH ssh" output &&
432 git -C new fast-import <output &&
433 git -C new cat-file commit refs/heads/ssh-signing >actual &&
434 grep "^gpgsig" actual &&
435 IMPORTED=$(git -C new rev-parse refs/heads/ssh-signing) &&
436 test $SSH_COMMIT = $IMPORTED
437
438 '
439
440 test_expect_success 'setup submodule' '
441
442 test_config_global protocol.file.allow always &&
443 git checkout -f main &&
444 test_might_fail git update-ref -d refs/heads/commit-signing &&
445 mkdir sub &&
446 (
447 cd sub &&
448 git init &&
449 echo test file > file &&
450 git add file &&
451 git commit -m sub_initial
452 ) &&
453 git submodule add "$(pwd)/sub" sub &&
454 git commit -m initial &&
455 test_tick &&
456 (
457 cd sub &&
458 echo more data >> file &&
459 git add file &&
460 git commit -m sub_second
461 ) &&
462 git add sub &&
463 git commit -m second
464
465 '
466
467 test_expect_success 'submodule fast-export | fast-import' '
468
469 test_config_global protocol.file.allow always &&
470 SUBENT1=$(git ls-tree main^ sub) &&
471 SUBENT2=$(git ls-tree main sub) &&
472 rm -rf new &&
473 mkdir new &&
474 git --git-dir=new/.git init &&
475 git fast-export --signed-tags=strip --all >actual &&
476 git -C new fast-import <actual &&
477 test "$SUBENT1" = "$(git -C new ls-tree refs/heads/main^ sub)" &&
478 test "$SUBENT2" = "$(git -C new ls-tree refs/heads/main sub)" &&
479 git -C new checkout main &&
480 git -C new submodule init &&
481 git -C new submodule update &&
482 cmp new/sub/file sub/file
483
484 '
485
486 GIT_AUTHOR_NAME='A U Thor'; export GIT_AUTHOR_NAME
487 GIT_COMMITTER_NAME='C O Mitter'; export GIT_COMMITTER_NAME
488
489 test_expect_success 'setup copies' '
490
491 git checkout -b copy rein &&
492 git mv file file3 &&
493 git commit -m move1 &&
494 test_tick &&
495 cp file2 file4 &&
496 git add file4 &&
497 git mv file2 file5 &&
498 git commit -m copy1 &&
499 test_tick &&
500 cp file3 file6 &&
501 git add file6 &&
502 git commit -m copy2 &&
503 test_tick &&
504 echo more text >> file6 &&
505 echo even more text >> file6 &&
506 git add file6 &&
507 git commit -m modify &&
508 test_tick &&
509 cp file6 file7 &&
510 echo test >> file7 &&
511 git add file7 &&
512 git commit -m copy_modify
513
514 '
515
516 test_expect_success 'fast-export -C -C | fast-import' '
517
518 ENTRY=$(git rev-parse --verify copy) &&
519 rm -rf new &&
520 mkdir new &&
521 git --git-dir=new/.git init &&
522 git fast-export -C -C --signed-tags=strip --all > output &&
523 grep "^C file2 file4\$" output &&
524 git -C new fast-import <output &&
525 test $ENTRY = $(git -C new rev-parse --verify refs/heads/copy)
526
527 '
528
529 test_expect_success 'fast-export | fast-import when main is tagged' '
530
531 git tag -m msg last &&
532 ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1)) &&
533 git fast-export -C -C --signed-tags=strip --all > output &&
534 test $(grep -c "^tag " output) = $ANNOTATED_TAG_COUNT
535
536 '
537
538 cat > tag-content << EOF
539 object $(git rev-parse HEAD)
540 type commit
541 tag rosten
542 EOF
543
544 test_expect_success 'cope with tagger-less tags' '
545
546 TAG=$(git hash-object --literally -t tag -w tag-content) &&
547 git update-ref refs/tags/sonnenschein $TAG &&
548 ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1)) &&
549 git fast-export -C -C --signed-tags=strip --all > output &&
550 test $(grep -c "^tag " output) = $ANNOTATED_TAG_COUNT &&
551 ! grep "Unspecified Tagger" output &&
552 git fast-export -C -C --signed-tags=strip --all \
553 --fake-missing-tagger > output &&
554 test $(grep -c "^tag " output) = $ANNOTATED_TAG_COUNT &&
555 grep "Unspecified Tagger" output
556
557 '
558
559 test_expect_success 'setup for limiting exports by PATH' '
560 mkdir limit-by-paths &&
561 (
562 cd limit-by-paths &&
563 git init &&
564 echo hi > there &&
565 git add there &&
566 git commit -m "First file" &&
567 echo foo > bar &&
568 git add bar &&
569 git commit -m "Second file" &&
570 git tag -a -m msg mytag &&
571 echo morefoo >> bar &&
572 git add bar &&
573 git commit -m "Change to second file"
574 )
575 '
576
577 cat > limit-by-paths/expected << EOF
578 blob
579 mark :1
580 data 3
581 hi
582
583 reset refs/tags/mytag
584 commit refs/tags/mytag
585 mark :2
586 author A U Thor <author@example.com> 1112912713 -0700
587 committer C O Mitter <committer@example.com> 1112912713 -0700
588 data 11
589 First file
590 M 100644 :1 there
591
592 EOF
593
594 test_expect_success ICONV 'dropping tag of filtered out object' '
595 (
596 cd limit-by-paths &&
597 git fast-export --tag-of-filtered-object=drop mytag -- there > output &&
598 test_cmp expected output
599 )
600 '
601
602 cat >> limit-by-paths/expected << EOF
603 tag mytag
604 from :2
605 tagger C O Mitter <committer@example.com> 1112912713 -0700
606 data 4
607 msg
608
609 EOF
610
611 test_expect_success ICONV 'rewriting tag of filtered out object' '
612 (
613 cd limit-by-paths &&
614 git fast-export --tag-of-filtered-object=rewrite mytag -- there > output &&
615 test_cmp expected output
616 )
617 '
618
619 test_expect_success 'rewrite tag predating pathspecs to nothing' '
620 test_create_repo rewrite_tag_predating_pathspecs &&
621 (
622 cd rewrite_tag_predating_pathspecs &&
623
624 test_commit initial &&
625
626 git tag -a -m "Some old tag" v0.0.0.0.0.0.1 &&
627
628 test_commit bar &&
629
630 git fast-export --tag-of-filtered-object=rewrite --all -- bar.t >output &&
631 grep from.$ZERO_OID output
632 )
633 '
634
635 cat > limit-by-paths/expected << EOF
636 blob
637 mark :1
638 data 4
639 foo
640
641 blob
642 mark :2
643 data 3
644 hi
645
646 reset refs/heads/main
647 commit refs/heads/main
648 mark :3
649 author A U Thor <author@example.com> 1112912713 -0700
650 committer C O Mitter <committer@example.com> 1112912713 -0700
651 data 12
652 Second file
653 M 100644 :1 bar
654 M 100644 :2 there
655
656 EOF
657
658 test_expect_failure 'no exact-ref revisions included' '
659 (
660 cd limit-by-paths &&
661 git fast-export main~2..main~1 > output &&
662 test_cmp expected output
663 )
664 '
665
666 test_expect_success 'path limiting with import-marks does not lose unmodified files' '
667 git checkout -b simple marks~2 &&
668 git fast-export --export-marks=marks simple -- file > /dev/null &&
669 echo more content >> file &&
670 test_tick &&
671 git commit -mnext file &&
672 git fast-export --import-marks=marks simple -- file file0 >actual &&
673 grep file0 actual
674 '
675
676 test_expect_success 'path limiting works' '
677 git fast-export simple -- file >actual &&
678 sed -ne "s/^M .* //p" <actual | sort -u >actual.files &&
679 echo file >expect &&
680 test_cmp expect actual.files
681 '
682
683 test_expect_success 'avoid corrupt stream with non-existent mark' '
684 test_create_repo avoid_non_existent_mark &&
685 (
686 cd avoid_non_existent_mark &&
687
688 test_commit important-path &&
689
690 test_commit ignored &&
691
692 git branch A &&
693 git branch B &&
694
695 echo foo >>important-path.t &&
696 git add important-path.t &&
697 test_commit more changes &&
698
699 git fast-export --all -- important-path.t | git fast-import --force
700 )
701 '
702
703 test_expect_success 'full-tree re-shows unmodified files' '
704 git checkout -f simple &&
705 git fast-export --full-tree simple >actual &&
706 test $(grep -c file0 actual) -eq 3
707 '
708
709 test_expect_success 'set-up a few more tags for tag export tests' '
710 git checkout -f main &&
711 HEAD_TREE=$(git show -s --pretty=raw HEAD | sed -n "/tree/s/tree //p") &&
712 git tag tree_tag -m "tagging a tree" $HEAD_TREE &&
713 git tag -a tree_tag-obj -m "tagging a tree" $HEAD_TREE &&
714 git tag tag-obj_tag -m "tagging a tag" tree_tag-obj &&
715 git tag -a tag-obj_tag-obj -m "tagging a tag" tree_tag-obj
716 '
717
718 test_expect_success 'tree_tag' '
719 mkdir result &&
720 (cd result && git init) &&
721 git fast-export tree_tag > fe-stream &&
722 (cd result && git fast-import < ../fe-stream)
723 '
724
725 # NEEDSWORK: not just check return status, but validate the output
726 # Note that these tests DO NOTHING other than print a warning that
727 # they are omitting the one tag we asked them to export (because the
728 # tags resolve to a tree). They exist just to make sure we do not
729 # abort but instead just warn.
730 test_expect_success 'tree_tag-obj' 'git fast-export tree_tag-obj'
731 test_expect_success 'tag-obj_tag' 'git fast-export tag-obj_tag'
732 test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj'
733
734 test_expect_success 'handling tags of blobs' '
735 git tag -a -m "Tag of a blob" blobtag $(git rev-parse main:file) &&
736 git fast-export blobtag >actual &&
737 cat >expect <<-EOF &&
738 blob
739 mark :1
740 data 9
741 die Luft
742
743 tag blobtag
744 from :1
745 tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
746 data 14
747 Tag of a blob
748
749 EOF
750 test_cmp expect actual
751 '
752
753 test_expect_success 'handling nested tags' '
754 git tag -a -m "This is a nested tag" nested muss &&
755 git fast-export --mark-tags nested >output &&
756 grep "^from $ZERO_OID$" output &&
757 grep "^tag nested$" output >tag_lines &&
758 test_line_count = 2 tag_lines
759 '
760
761 test_expect_success 'directory becomes symlink' '
762 git init dirtosymlink &&
763 git init result &&
764 (
765 cd dirtosymlink &&
766 mkdir foo &&
767 mkdir bar &&
768 echo hello > foo/world &&
769 echo hello > bar/world &&
770 git add foo/world bar/world &&
771 git commit -q -mone &&
772 git rm -r foo &&
773 test_ln_s_add bar foo &&
774 git commit -q -mtwo
775 ) &&
776 (
777 cd dirtosymlink &&
778 git fast-export main -- foo |
779 (cd ../result && git fast-import --quiet)
780 ) &&
781 (cd result && git show main:foo)
782 '
783
784 test_expect_success PERL_TEST_HELPERS 'fast-export quotes pathnames' '
785 git init crazy-paths &&
786 test_config -C crazy-paths core.protectNTFS false &&
787 (cd crazy-paths &&
788 blob=$(echo foo | git hash-object -w --stdin) &&
789 git -c core.protectNTFS=false update-index --add \
790 --cacheinfo 100644 $blob "$(printf "path with\\nnewline")" \
791 --cacheinfo 100644 $blob "path with \"quote\"" \
792 --cacheinfo 100644 $blob "path with \\backslash" \
793 --cacheinfo 100644 $blob "path with space" &&
794 git commit -m addition &&
795 git ls-files -z -s | perl -0pe "s{\\t}{$&subdir/}" >index &&
796 git read-tree --empty &&
797 git update-index -z --index-info <index &&
798 git commit -m rename &&
799 git read-tree --empty &&
800 git commit -m deletion &&
801 git fast-export -M HEAD >export.out &&
802 git rev-list HEAD >expect &&
803 git init result &&
804 cd result &&
805 git -c core.protectNTFS=false fast-import <../export.out &&
806 git rev-list HEAD >actual &&
807 test_cmp ../expect actual
808 )
809 '
810
811 test_expect_success 'test bidirectionality' '
812 git init marks-test &&
813 git fast-export --export-marks=marks-cur --import-marks-if-exists=marks-cur --branches | \
814 git --git-dir=marks-test/.git fast-import --export-marks=marks-new --import-marks-if-exists=marks-new &&
815 (cd marks-test &&
816 git reset --hard &&
817 echo Wohlauf > file &&
818 git commit -a -m "back in time") &&
819 git --git-dir=marks-test/.git fast-export --export-marks=marks-new --import-marks-if-exists=marks-new --branches | \
820 git fast-import --export-marks=marks-cur --import-marks-if-exists=marks-cur
821 '
822
823 cat > expected << EOF
824 blob
825 mark :13
826 data 5
827 bump
828
829 commit refs/heads/main
830 mark :14
831 author A U Thor <author@example.com> 1112912773 -0700
832 committer C O Mitter <committer@example.com> 1112912773 -0700
833 data 5
834 bump
835 from :12
836 M 100644 :13 file
837
838 EOF
839
840 test_expect_success ICONV 'avoid uninteresting refs' '
841 > tmp-marks &&
842 git fast-export --import-marks=tmp-marks \
843 --export-marks=tmp-marks main > /dev/null &&
844 git tag v1.0 &&
845 git branch uninteresting &&
846 echo bump > file &&
847 git commit -a -m bump &&
848 git fast-export --import-marks=tmp-marks \
849 --export-marks=tmp-marks ^uninteresting ^v1.0 main > actual &&
850 test_cmp expected actual
851 '
852
853 cat > expected << EOF
854 reset refs/heads/main
855 from :14
856
857 EOF
858
859 test_expect_success ICONV 'refs are updated even if no commits need to be exported' '
860 > tmp-marks &&
861 git fast-export --import-marks=tmp-marks \
862 --export-marks=tmp-marks main > /dev/null &&
863 git fast-export --import-marks=tmp-marks \
864 --export-marks=tmp-marks main > actual &&
865 test_cmp expected actual
866 '
867
868 test_expect_success 'use refspec' '
869 git fast-export --refspec refs/heads/main:refs/heads/foobar main >actual2 &&
870 grep "^commit " actual2 | sort | uniq >actual &&
871 echo "commit refs/heads/foobar" > expected &&
872 test_cmp expected actual
873 '
874
875 test_expect_success 'delete ref because entire history excluded' '
876 git branch to-delete &&
877 git fast-export to-delete ^to-delete >actual &&
878 cat >expected <<-EOF &&
879 reset refs/heads/to-delete
880 from $ZERO_OID
881
882 EOF
883 test_cmp expected actual
884 '
885
886 test_expect_success 'delete refspec' '
887 git fast-export --refspec :refs/heads/to-delete >actual &&
888 cat >expected <<-EOF &&
889 reset refs/heads/to-delete
890 from $ZERO_OID
891
892 EOF
893 test_cmp expected actual
894 '
895
896 test_expect_success 'when using -C, do not declare copy when source of copy is also modified' '
897 test_create_repo src &&
898 echo a_line >src/file.txt &&
899 git -C src add file.txt &&
900 git -C src commit -m 1st_commit &&
901
902 cp src/file.txt src/file2.txt &&
903 echo another_line >>src/file.txt &&
904 git -C src add file.txt file2.txt &&
905 git -C src commit -m 2nd_commit &&
906
907 test_create_repo dst &&
908 git -C src fast-export --all -C >actual &&
909 git -C dst fast-import <actual &&
910 git -C src show >expected &&
911 git -C dst show >actual &&
912 test_cmp expected actual
913 '
914
915 test_expect_success 'merge commit gets exported with --import-marks' '
916 test_create_repo merging &&
917 (
918 cd merging &&
919 test_commit initial &&
920 git checkout -b topic &&
921 test_commit on-topic &&
922 git checkout main &&
923 test_commit on-main &&
924 test_tick &&
925 git merge --no-ff -m Yeah topic &&
926
927 echo ":1 $(git rev-parse HEAD^^)" >marks &&
928 git fast-export --import-marks=marks main >out &&
929 grep Yeah out
930 )
931 '
932
933
934 test_expect_success 'fast-export --first-parent outputs all revisions output by revision walk' '
935 git init first-parent &&
936 (
937 cd first-parent &&
938 test_commit A &&
939 git checkout -b topic1 &&
940 test_commit B &&
941 git checkout main &&
942 git merge --no-ff topic1 &&
943
944 git checkout -b topic2 &&
945 test_commit C &&
946 git checkout main &&
947 git merge --no-ff topic2 &&
948
949 test_commit D &&
950
951 git fast-export main -- --first-parent >first-parent-export &&
952 git fast-export main -- --first-parent --reverse >first-parent-reverse-export &&
953 test_cmp first-parent-export first-parent-reverse-export &&
954
955 git init import &&
956 git -C import fast-import <first-parent-export &&
957
958 git log --format="%ad %s" --first-parent main >expected &&
959 git -C import log --format="%ad %s" --all >actual &&
960 test_cmp expected actual &&
961 test_line_count = 4 actual
962 )
963 '
964
965 test_expect_success 'fast-export handles --end-of-options' '
966 git update-ref refs/heads/nodash HEAD &&
967 git update-ref refs/heads/--dashes HEAD &&
968 git fast-export --end-of-options nodash >expect &&
969 git fast-export --end-of-options --dashes >actual.raw &&
970 # fix up lines which mention the ref for comparison
971 sed s/--dashes/nodash/ <actual.raw >actual &&
972 test_cmp expect actual
973 '
974
975 test_expect_success GPG,RUST 'setup a commit with dual signatures on its SHA-1 and SHA-256 formats' '
976 # Create a signed SHA-256 commit
977 git init --object-format=sha256 explicit-sha256 &&
978 git -C explicit-sha256 config extensions.compatObjectFormat sha1 &&
979 git -C explicit-sha256 checkout -b dual-signed &&
980 test_commit -C explicit-sha256 A &&
981 echo B >explicit-sha256/B &&
982 git -C explicit-sha256 add B &&
983 test_tick &&
984 git -C explicit-sha256 commit -S -m "signed" B &&
985 SHA256_B=$(git -C explicit-sha256 rev-parse dual-signed) &&
986
987 # Create the corresponding SHA-1 commit
988 SHA1_B=$(git -C explicit-sha256 rev-parse --output-object-format=sha1 dual-signed) &&
989
990 # Check that the resulting SHA-1 commit has both signatures
991 echo $SHA1_B | git -C explicit-sha256 cat-file --batch >out &&
992 test_grep -E "^gpgsig " out &&
993 test_grep -E "^gpgsig-sha256 " out
994 '
995
996 test_expect_success GPG,RUST 'export and import of doubly signed commit' '
997 git -C explicit-sha256 fast-export --signed-commits=verbatim dual-signed >output &&
998 test_grep -E "^gpgsig sha1 openpgp" output &&
999 test_grep -E "^gpgsig sha256 openpgp" output &&
1000 git -C new fast-import <output &&
1001 git -C new cat-file commit refs/heads/dual-signed >actual &&
1002 test_grep -E "^gpgsig " actual &&
1003 test_grep -E "^gpgsig-sha256 " actual &&
1004 IMPORTED=$(git -C new rev-parse refs/heads/dual-signed) &&
1005 if test "$GIT_DEFAULT_HASH" = "sha1"
1006 then
1007 test $SHA1_B = $IMPORTED
1008 else
1009 test $SHA256_B = $IMPORTED
1010 fi
1011 '
1012
1013 test_done