50c2fceef403c6d047632cea4b31486984ad470d
   1#!/bin/sh
   2#
   3# Copyright (c) 2007 Johannes E. Schindelin
   4#
   5
   6test_description='git fast-export'
   7. ./test-lib.sh
   8
   9test_expect_success 'setup' '
  10
  11        echo break it > file0 &&
  12        git add file0 &&
  13        test_tick &&
  14        echo Wohlauf > file &&
  15        git add file &&
  16        test_tick &&
  17        git commit -m initial &&
  18        echo die Luft > file &&
  19        echo geht frisch > file2 &&
  20        git add file file2 &&
  21        test_tick &&
  22        git commit -m second &&
  23        echo und > file2 &&
  24        test_tick &&
  25        git commit -m third file2 &&
  26        test_tick &&
  27        git tag rein &&
  28        git checkout -b wer HEAD^ &&
  29        echo lange > file2 &&
  30        test_tick &&
  31        git commit -m sitzt file2 &&
  32        test_tick &&
  33        git tag -a -m valentin muss &&
  34        git merge -s ours master
  35
  36'
  37
  38test_expect_success 'fast-export | fast-import' '
  39
  40        MASTER=$(git rev-parse --verify master) &&
  41        REIN=$(git rev-parse --verify rein) &&
  42        WER=$(git rev-parse --verify wer) &&
  43        MUSS=$(git rev-parse --verify muss) &&
  44        mkdir new &&
  45        git --git-dir=new/.git init &&
  46        git fast-export --all >actual &&
  47        (cd new &&
  48         git fast-import &&
  49         test $MASTER = $(git rev-parse --verify refs/heads/master) &&
  50         test $REIN = $(git rev-parse --verify refs/tags/rein) &&
  51         test $WER = $(git rev-parse --verify refs/heads/wer) &&
  52         test $MUSS = $(git rev-parse --verify refs/tags/muss)) <actual
  53
  54'
  55
  56test_expect_success 'fast-export master~2..master' '
  57
  58        git fast-export master~2..master >actual &&
  59        sed "s/master/partial/" actual |
  60                (cd new &&
  61                 git fast-import &&
  62                 test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
  63                 git diff --exit-code master partial &&
  64                 git diff --exit-code master^ partial^ &&
  65                 test_must_fail git rev-parse partial~2)
  66
  67'
  68
  69test_expect_success 'iso-8859-1' '
  70
  71        git config i18n.commitencoding ISO8859-1 &&
  72        # use author and committer name in ISO-8859-1 to match it.
  73        . "$TEST_DIRECTORY"/t3901/8859-1.txt &&
  74        test_tick &&
  75        echo rosten >file &&
  76        git commit -s -m den file &&
  77        git fast-export wer^..wer >iso8859-1.fi &&
  78        sed "s/wer/i18n/" iso8859-1.fi |
  79                (cd new &&
  80                 git fast-import &&
  81                 git cat-file commit i18n >actual &&
  82                 grep "Áéí óú" actual)
  83
  84'
  85test_expect_success 'import/export-marks' '
  86
  87        git checkout -b marks master &&
  88        git fast-export --export-marks=tmp-marks HEAD &&
  89        test -s tmp-marks &&
  90        test_line_count = 3 tmp-marks &&
  91        git fast-export --import-marks=tmp-marks \
  92                --export-marks=tmp-marks HEAD >actual &&
  93        test $(grep ^commit actual | wc -l) -eq 0 &&
  94        echo change > file &&
  95        git commit -m "last commit" file &&
  96        git fast-export --import-marks=tmp-marks \
  97                --export-marks=tmp-marks HEAD >actual &&
  98        test $(grep ^commit\  actual | wc -l) -eq 1 &&
  99        test_line_count = 4 tmp-marks
 100
 101'
 102
 103cat > signed-tag-import << EOF
 104tag sign-your-name
 105from $(git rev-parse HEAD)
 106tagger C O Mitter <committer@example.com> 1112911993 -0700
 107data 210
 108A message for a sign
 109-----BEGIN PGP SIGNATURE-----
 110Version: GnuPG v1.4.5 (GNU/Linux)
 111
 112fakedsignaturefakedsignaturefakedsignaturefakedsignaturfakedsign
 113aturefakedsignaturefake=
 114=/59v
 115-----END PGP SIGNATURE-----
 116EOF
 117
 118test_expect_success 'set up faked signed tag' '
 119
 120        cat signed-tag-import | git fast-import
 121
 122'
 123
 124test_expect_success 'signed-tags=abort' '
 125
 126        test_must_fail git fast-export --signed-tags=abort sign-your-name
 127
 128'
 129
 130test_expect_success 'signed-tags=verbatim' '
 131
 132        git fast-export --signed-tags=verbatim sign-your-name > output &&
 133        grep PGP output
 134
 135'
 136
 137test_expect_success 'signed-tags=strip' '
 138
 139        git fast-export --signed-tags=strip sign-your-name > output &&
 140        ! grep PGP output
 141
 142'
 143
 144test_expect_success 'signed-tags=warn-strip' '
 145        git fast-export --signed-tags=warn-strip sign-your-name >output 2>err &&
 146        ! grep PGP output &&
 147        test -s err
 148'
 149
 150test_expect_success 'setup submodule' '
 151
 152        git checkout -f master &&
 153        mkdir sub &&
 154        (
 155                cd sub &&
 156                git init  &&
 157                echo test file > file &&
 158                git add file &&
 159                git commit -m sub_initial
 160        ) &&
 161        git submodule add "$(pwd)/sub" sub &&
 162        git commit -m initial &&
 163        test_tick &&
 164        (
 165                cd sub &&
 166                echo more data >> file &&
 167                git add file &&
 168                git commit -m sub_second
 169        ) &&
 170        git add sub &&
 171        git commit -m second
 172
 173'
 174
 175test_expect_success 'submodule fast-export | fast-import' '
 176
 177        SUBENT1=$(git ls-tree master^ sub) &&
 178        SUBENT2=$(git ls-tree master sub) &&
 179        rm -rf new &&
 180        mkdir new &&
 181        git --git-dir=new/.git init &&
 182        git fast-export --signed-tags=strip --all >actual &&
 183        (cd new &&
 184         git fast-import &&
 185         test "$SUBENT1" = "$(git ls-tree refs/heads/master^ sub)" &&
 186         test "$SUBENT2" = "$(git ls-tree refs/heads/master sub)" &&
 187         git checkout master &&
 188         git submodule init &&
 189         git submodule update &&
 190         cmp sub/file ../sub/file) <actual
 191
 192'
 193
 194GIT_AUTHOR_NAME='A U Thor'; export GIT_AUTHOR_NAME
 195GIT_COMMITTER_NAME='C O Mitter'; export GIT_COMMITTER_NAME
 196
 197test_expect_success 'setup copies' '
 198
 199        git config --unset i18n.commitencoding &&
 200        git checkout -b copy rein &&
 201        git mv file file3 &&
 202        git commit -m move1 &&
 203        test_tick &&
 204        cp file2 file4 &&
 205        git add file4 &&
 206        git mv file2 file5 &&
 207        git commit -m copy1 &&
 208        test_tick &&
 209        cp file3 file6 &&
 210        git add file6 &&
 211        git commit -m copy2 &&
 212        test_tick &&
 213        echo more text >> file6 &&
 214        echo even more text >> file6 &&
 215        git add file6 &&
 216        git commit -m modify &&
 217        test_tick &&
 218        cp file6 file7 &&
 219        echo test >> file7 &&
 220        git add file7 &&
 221        git commit -m copy_modify
 222
 223'
 224
 225test_expect_success 'fast-export -C -C | fast-import' '
 226
 227        ENTRY=$(git rev-parse --verify copy) &&
 228        rm -rf new &&
 229        mkdir new &&
 230        git --git-dir=new/.git init &&
 231        git fast-export -C -C --signed-tags=strip --all > output &&
 232        grep "^C file2 file4\$" output &&
 233        cat output |
 234        (cd new &&
 235         git fast-import &&
 236         test $ENTRY = $(git rev-parse --verify refs/heads/copy))
 237
 238'
 239
 240test_expect_success 'fast-export | fast-import when master is tagged' '
 241
 242        git tag -m msg last &&
 243        git fast-export -C -C --signed-tags=strip --all > output &&
 244        test $(grep -c "^tag " output) = 3
 245
 246'
 247
 248cat > tag-content << EOF
 249object $(git rev-parse HEAD)
 250type commit
 251tag rosten
 252EOF
 253
 254test_expect_success 'cope with tagger-less tags' '
 255
 256        TAG=$(git hash-object -t tag -w tag-content) &&
 257        git update-ref refs/tags/sonnenschein $TAG &&
 258        git fast-export -C -C --signed-tags=strip --all > output &&
 259        test $(grep -c "^tag " output) = 4 &&
 260        ! grep "Unspecified Tagger" output &&
 261        git fast-export -C -C --signed-tags=strip --all \
 262                --fake-missing-tagger > output &&
 263        test $(grep -c "^tag " output) = 4 &&
 264        grep "Unspecified Tagger" output
 265
 266'
 267
 268test_expect_success 'setup for limiting exports by PATH' '
 269        mkdir limit-by-paths &&
 270        (
 271                cd limit-by-paths &&
 272                git init &&
 273                echo hi > there &&
 274                git add there &&
 275                git commit -m "First file" &&
 276                echo foo > bar &&
 277                git add bar &&
 278                git commit -m "Second file" &&
 279                git tag -a -m msg mytag &&
 280                echo morefoo >> bar &&
 281                git add bar &&
 282                git commit -m "Change to second file"
 283        )
 284'
 285
 286cat > limit-by-paths/expected << EOF
 287blob
 288mark :1
 289data 3
 290hi
 291
 292reset refs/tags/mytag
 293commit refs/tags/mytag
 294mark :2
 295author A U Thor <author@example.com> 1112912713 -0700
 296committer C O Mitter <committer@example.com> 1112912713 -0700
 297data 11
 298First file
 299M 100644 :1 there
 300
 301EOF
 302
 303test_expect_success 'dropping tag of filtered out object' '
 304(
 305        cd limit-by-paths &&
 306        git fast-export --tag-of-filtered-object=drop mytag -- there > output &&
 307        test_cmp expected output
 308)
 309'
 310
 311cat >> limit-by-paths/expected << EOF
 312tag mytag
 313from :2
 314tagger C O Mitter <committer@example.com> 1112912713 -0700
 315data 4
 316msg
 317
 318EOF
 319
 320test_expect_success 'rewriting tag of filtered out object' '
 321(
 322        cd limit-by-paths &&
 323        git fast-export --tag-of-filtered-object=rewrite mytag -- there > output &&
 324        test_cmp expected output
 325)
 326'
 327
 328test_expect_success 'rewrite tag predating pathspecs to nothing' '
 329        test_create_repo rewrite_tag_predating_pathspecs &&
 330        (
 331                cd rewrite_tag_predating_pathspecs &&
 332
 333                test_commit initial &&
 334
 335                git tag -a -m "Some old tag" v0.0.0.0.0.0.1 &&
 336
 337                test_commit bar &&
 338
 339                git fast-export --tag-of-filtered-object=rewrite --all -- bar.t >output &&
 340                grep from.$ZERO_OID output
 341        )
 342'
 343
 344cat > limit-by-paths/expected << EOF
 345blob
 346mark :1
 347data 4
 348foo
 349
 350blob
 351mark :2
 352data 3
 353hi
 354
 355reset refs/heads/master
 356commit refs/heads/master
 357mark :3
 358author A U Thor <author@example.com> 1112912713 -0700
 359committer C O Mitter <committer@example.com> 1112912713 -0700
 360data 12
 361Second file
 362M 100644 :1 bar
 363M 100644 :2 there
 364
 365EOF
 366
 367test_expect_failure 'no exact-ref revisions included' '
 368        (
 369                cd limit-by-paths &&
 370                git fast-export master~2..master~1 > output &&
 371                test_cmp expected output
 372        )
 373'
 374
 375test_expect_success 'path limiting with import-marks does not lose unmodified files'        '
 376        git checkout -b simple marks~2 &&
 377        git fast-export --export-marks=marks simple -- file > /dev/null &&
 378        echo more content >> file &&
 379        test_tick &&
 380        git commit -mnext file &&
 381        git fast-export --import-marks=marks simple -- file file0 >actual &&
 382        grep file0 actual
 383'
 384
 385test_expect_success 'avoid corrupt stream with non-existent mark' '
 386        test_create_repo avoid_non_existent_mark &&
 387        (
 388                cd avoid_non_existent_mark &&
 389
 390                test_commit important-path &&
 391
 392                test_commit ignored &&
 393
 394                git branch A &&
 395                git branch B &&
 396
 397                echo foo >>important-path.t &&
 398                git add important-path.t &&
 399                test_commit more changes &&
 400
 401                git fast-export --all -- important-path.t | git fast-import --force
 402        )
 403'
 404
 405test_expect_success 'full-tree re-shows unmodified files'        '
 406        git checkout -f simple &&
 407        git fast-export --full-tree simple >actual &&
 408        test $(grep -c file0 actual) -eq 3
 409'
 410
 411test_expect_success 'set-up a few more tags for tag export tests' '
 412        git checkout -f master &&
 413        HEAD_TREE=$(git show -s --pretty=raw HEAD | grep tree | sed "s/tree //") &&
 414        git tag    tree_tag        -m "tagging a tree" $HEAD_TREE &&
 415        git tag -a tree_tag-obj    -m "tagging a tree" $HEAD_TREE &&
 416        git tag    tag-obj_tag     -m "tagging a tag" tree_tag-obj &&
 417        git tag -a tag-obj_tag-obj -m "tagging a tag" tree_tag-obj
 418'
 419
 420test_expect_success 'tree_tag'        '
 421        mkdir result &&
 422        (cd result && git init) &&
 423        git fast-export tree_tag > fe-stream &&
 424        (cd result && git fast-import < ../fe-stream)
 425'
 426
 427# NEEDSWORK: not just check return status, but validate the output
 428test_expect_success 'tree_tag-obj'    'git fast-export tree_tag-obj'
 429test_expect_success 'tag-obj_tag'     'git fast-export tag-obj_tag'
 430test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj'
 431
 432test_expect_success 'directory becomes symlink'        '
 433        git init dirtosymlink &&
 434        git init result &&
 435        (
 436                cd dirtosymlink &&
 437                mkdir foo &&
 438                mkdir bar &&
 439                echo hello > foo/world &&
 440                echo hello > bar/world &&
 441                git add foo/world bar/world &&
 442                git commit -q -mone &&
 443                git rm -r foo &&
 444                test_ln_s_add bar foo &&
 445                git commit -q -mtwo
 446        ) &&
 447        (
 448                cd dirtosymlink &&
 449                git fast-export master -- foo |
 450                (cd ../result && git fast-import --quiet)
 451        ) &&
 452        (cd result && git show master:foo)
 453'
 454
 455test_expect_success 'fast-export quotes pathnames' '
 456        git init crazy-paths &&
 457        (cd crazy-paths &&
 458         blob=$(echo foo | git hash-object -w --stdin) &&
 459         git update-index --add \
 460                --cacheinfo 100644 $blob "$(printf "path with\\nnewline")" \
 461                --cacheinfo 100644 $blob "path with \"quote\"" \
 462                --cacheinfo 100644 $blob "path with \\backslash" \
 463                --cacheinfo 100644 $blob "path with space" &&
 464         git commit -m addition &&
 465         git ls-files -z -s | perl -0pe "s{\\t}{$&subdir/}" >index &&
 466         git read-tree --empty &&
 467         git update-index -z --index-info <index &&
 468         git commit -m rename &&
 469         git read-tree --empty &&
 470         git commit -m deletion &&
 471         git fast-export -M HEAD >export.out &&
 472         git rev-list HEAD >expect &&
 473         git init result &&
 474         cd result &&
 475         git fast-import <../export.out &&
 476         git rev-list HEAD >actual &&
 477         test_cmp ../expect actual
 478        )
 479'
 480
 481test_expect_success 'test bidirectionality' '
 482        >marks-cur &&
 483        >marks-new &&
 484        git init marks-test &&
 485        git fast-export --export-marks=marks-cur --import-marks=marks-cur --branches | \
 486        git --git-dir=marks-test/.git fast-import --export-marks=marks-new --import-marks=marks-new &&
 487        (cd marks-test &&
 488        git reset --hard &&
 489        echo Wohlauf > file &&
 490        git commit -a -m "back in time") &&
 491        git --git-dir=marks-test/.git fast-export --export-marks=marks-new --import-marks=marks-new --branches | \
 492        git fast-import --export-marks=marks-cur --import-marks=marks-cur
 493'
 494
 495cat > expected << EOF
 496blob
 497mark :13
 498data 5
 499bump
 500
 501commit refs/heads/master
 502mark :14
 503author A U Thor <author@example.com> 1112912773 -0700
 504committer C O Mitter <committer@example.com> 1112912773 -0700
 505data 5
 506bump
 507from :12
 508M 100644 :13 file
 509
 510EOF
 511
 512test_expect_success 'avoid uninteresting refs' '
 513        > tmp-marks &&
 514        git fast-export --import-marks=tmp-marks \
 515                --export-marks=tmp-marks master > /dev/null &&
 516        git tag v1.0 &&
 517        git branch uninteresting &&
 518        echo bump > file &&
 519        git commit -a -m bump &&
 520        git fast-export --import-marks=tmp-marks \
 521                --export-marks=tmp-marks ^uninteresting ^v1.0 master > actual &&
 522        test_cmp expected actual
 523'
 524
 525cat > expected << EOF
 526reset refs/heads/master
 527from :14
 528
 529EOF
 530
 531test_expect_success 'refs are updated even if no commits need to be exported' '
 532        > tmp-marks &&
 533        git fast-export --import-marks=tmp-marks \
 534                --export-marks=tmp-marks master > /dev/null &&
 535        git fast-export --import-marks=tmp-marks \
 536                --export-marks=tmp-marks master > actual &&
 537        test_cmp expected actual
 538'
 539
 540test_expect_success 'use refspec' '
 541        git fast-export --refspec refs/heads/master:refs/heads/foobar master >actual2 &&
 542        grep "^commit " actual2 | sort | uniq >actual &&
 543        echo "commit refs/heads/foobar" > expected &&
 544        test_cmp expected actual
 545'
 546
 547test_expect_success 'delete ref because entire history excluded' '
 548        git branch to-delete &&
 549        git fast-export to-delete ^to-delete >actual &&
 550        cat >expected <<-EOF &&
 551        reset refs/heads/to-delete
 552        from 0000000000000000000000000000000000000000
 553
 554        EOF
 555        test_cmp expected actual
 556'
 557
 558test_expect_success 'delete refspec' '
 559        git fast-export --refspec :refs/heads/to-delete >actual &&
 560        cat >expected <<-EOF &&
 561        reset refs/heads/to-delete
 562        from 0000000000000000000000000000000000000000
 563
 564        EOF
 565        test_cmp expected actual
 566'
 567
 568test_expect_success 'when using -C, do not declare copy when source of copy is also modified' '
 569        test_create_repo src &&
 570        echo a_line >src/file.txt &&
 571        git -C src add file.txt &&
 572        git -C src commit -m 1st_commit &&
 573
 574        cp src/file.txt src/file2.txt &&
 575        echo another_line >>src/file.txt &&
 576        git -C src add file.txt file2.txt &&
 577        git -C src commit -m 2nd_commit &&
 578
 579        test_create_repo dst &&
 580        git -C src fast-export --all -C >actual &&
 581        git -C dst fast-import <actual &&
 582        git -C src show >expected &&
 583        git -C dst show >actual &&
 584        test_cmp expected actual
 585'
 586
 587test_expect_success 'merge commit gets exported with --import-marks' '
 588        test_create_repo merging &&
 589        (
 590                cd merging &&
 591                test_commit initial &&
 592                git checkout -b topic &&
 593                test_commit on-topic &&
 594                git checkout master &&
 595                test_commit on-master &&
 596                test_tick &&
 597                git merge --no-ff -m Yeah topic &&
 598
 599                echo ":1 $(git rev-parse HEAD^^)" >marks &&
 600                git fast-export --import-marks=marks master >out &&
 601                grep Yeah out
 602        )
 603'
 604
 605test_done