2ae5374de38a2a618713f93fd290f74bf1dff67f
   1#!/bin/sh
   2
   3test_description='check svn dumpfile importer'
   4
   5. ./test-lib.sh
   6
   7reinit_git () {
   8        if ! test_declared_prereq PIPE
   9        then
  10                echo >&4 "reinit_git: need to declare PIPE prerequisite"
  11                return 127
  12        fi
  13        rm -fr .git &&
  14        rm -f stream backflow &&
  15        git init &&
  16        mkfifo stream backflow
  17}
  18
  19try_dump () {
  20        input=$1 &&
  21        maybe_fail=${2:+test_$2} &&
  22
  23        {
  24                $maybe_fail test-svn-fe "$input" >stream 3<backflow &
  25        } &&
  26        git fast-import --cat-blob-fd=3 <stream 3>backflow &&
  27        wait $!
  28}
  29
  30properties () {
  31        while test "$#" -ne 0
  32        do
  33                property="$1" &&
  34                value="$2" &&
  35                printf "%s\n" "K ${#property}" &&
  36                printf "%s\n" "$property" &&
  37                printf "%s\n" "V ${#value}" &&
  38                printf "%s\n" "$value" &&
  39                shift 2 ||
  40                return 1
  41        done
  42}
  43
  44text_no_props () {
  45        text="$1
  46" &&
  47        printf "%s\n" "Prop-content-length: 10" &&
  48        printf "%s\n" "Text-content-length: ${#text}" &&
  49        printf "%s\n" "Content-length: $((${#text} + 10))" &&
  50        printf "%s\n" "" "PROPS-END" &&
  51        printf "%s\n" "$text"
  52}
  53
  54>empty
  55
  56test_expect_success 'setup: have pipes?' '
  57        rm -f frob &&
  58        if mkfifo frob
  59        then
  60                test_set_prereq PIPE
  61        fi
  62'
  63
  64test_expect_success PIPE 'empty dump' '
  65        reinit_git &&
  66        echo "SVN-fs-dump-format-version: 2" >input &&
  67        try_dump input
  68'
  69
  70test_expect_success PIPE 'v4 dumps not supported' '
  71        reinit_git &&
  72        echo "SVN-fs-dump-format-version: 4" >v4.dump &&
  73        try_dump v4.dump must_fail
  74'
  75
  76test_expect_failure PIPE 'empty revision' '
  77        reinit_git &&
  78        printf "rev <nobody, nobody@local>: %s\n" "" "" >expect &&
  79        cat >emptyrev.dump <<-\EOF &&
  80        SVN-fs-dump-format-version: 3
  81
  82        Revision-number: 1
  83        Prop-content-length: 0
  84        Content-length: 0
  85
  86        Revision-number: 2
  87        Prop-content-length: 0
  88        Content-length: 0
  89
  90        EOF
  91        try_dump emptyrev.dump &&
  92        git log -p --format="rev <%an, %ae>: %s" HEAD >actual &&
  93        test_cmp expect actual
  94'
  95
  96test_expect_success PIPE 'empty properties' '
  97        reinit_git &&
  98        printf "rev <nobody, nobody@local>: %s\n" "" "" >expect &&
  99        cat >emptyprop.dump <<-\EOF &&
 100        SVN-fs-dump-format-version: 3
 101
 102        Revision-number: 1
 103        Prop-content-length: 10
 104        Content-length: 10
 105
 106        PROPS-END
 107
 108        Revision-number: 2
 109        Prop-content-length: 10
 110        Content-length: 10
 111
 112        PROPS-END
 113        EOF
 114        try_dump emptyprop.dump &&
 115        git log -p --format="rev <%an, %ae>: %s" HEAD >actual &&
 116        test_cmp expect actual
 117'
 118
 119test_expect_success PIPE 'author name and commit message' '
 120        reinit_git &&
 121        echo "<author@example.com, author@example.com@local>" >expect.author &&
 122        cat >message <<-\EOF &&
 123        A concise summary of the change
 124
 125        A detailed description of the change, why it is needed, what
 126        was broken and why applying this is the best course of action.
 127
 128        * file.c
 129            Details pertaining to an individual file.
 130        EOF
 131        {
 132                properties \
 133                        svn:author author@example.com \
 134                        svn:log "$(cat message)" &&
 135                echo PROPS-END
 136        } >props &&
 137        {
 138                echo "SVN-fs-dump-format-version: 3" &&
 139                echo &&
 140                echo "Revision-number: 1" &&
 141                echo Prop-content-length: $(wc -c <props) &&
 142                echo Content-length: $(wc -c <props) &&
 143                echo &&
 144                cat props
 145        } >log.dump &&
 146        try_dump log.dump &&
 147        git log -p --format="%B" HEAD >actual.log &&
 148        git log --format="<%an, %ae>" >actual.author &&
 149        test_cmp message actual.log &&
 150        test_cmp expect.author actual.author
 151'
 152
 153test_expect_success PIPE 'unsupported properties are ignored' '
 154        reinit_git &&
 155        echo author >expect &&
 156        cat >extraprop.dump <<-\EOF &&
 157        SVN-fs-dump-format-version: 3
 158
 159        Revision-number: 1
 160        Prop-content-length: 56
 161        Content-length: 56
 162
 163        K 8
 164        nonsense
 165        V 1
 166        y
 167        K 10
 168        svn:author
 169        V 6
 170        author
 171        PROPS-END
 172        EOF
 173        try_dump extraprop.dump &&
 174        git log -p --format=%an HEAD >actual &&
 175        test_cmp expect actual
 176'
 177
 178test_expect_failure PIPE 'timestamp and empty file' '
 179        echo author@example.com >expect.author &&
 180        echo 1999-01-01 >expect.date &&
 181        echo file >expect.files &&
 182        reinit_git &&
 183        {
 184                properties \
 185                        svn:author author@example.com \
 186                        svn:date "1999-01-01T00:01:002.000000Z" \
 187                        svn:log "add empty file" &&
 188                echo PROPS-END
 189        } >props &&
 190        {
 191                cat <<-EOF &&
 192                SVN-fs-dump-format-version: 3
 193
 194                Revision-number: 1
 195                EOF
 196                echo Prop-content-length: $(wc -c <props) &&
 197                echo Content-length: $(wc -c <props) &&
 198                echo &&
 199                cat props &&
 200                cat <<-\EOF
 201
 202                Node-path: empty-file
 203                Node-kind: file
 204                Node-action: add
 205                Content-length: 0
 206
 207                EOF
 208        } >emptyfile.dump &&
 209        try_dump emptyfile.dump &&
 210        git log --format=%an HEAD >actual.author &&
 211        git log --date=short --format=%ad HEAD >actual.date &&
 212        git ls-tree -r --name-only HEAD >actual.files &&
 213        test_cmp expect.author actual.author &&
 214        test_cmp expect.date actual.date &&
 215        test_cmp expect.files actual.files &&
 216        git checkout HEAD empty-file &&
 217        test_cmp empty file
 218'
 219
 220test_expect_success PIPE 'directory with files' '
 221        reinit_git &&
 222        printf "%s\n" directory/file1 directory/file2 >expect.files &&
 223        echo hi >hi &&
 224        echo hello >hello &&
 225        {
 226                properties \
 227                        svn:author author@example.com \
 228                        svn:date "1999-02-01T00:01:002.000000Z" \
 229                        svn:log "add directory with some files in it" &&
 230                echo PROPS-END
 231        } >props &&
 232        {
 233                cat <<-EOF &&
 234                SVN-fs-dump-format-version: 3
 235
 236                Revision-number: 1
 237                EOF
 238                echo Prop-content-length: $(wc -c <props) &&
 239                echo Content-length: $(wc -c <props) &&
 240                echo &&
 241                cat props &&
 242                cat <<-\EOF &&
 243
 244                Node-path: directory
 245                Node-kind: dir
 246                Node-action: add
 247                Prop-content-length: 10
 248                Content-length: 10
 249
 250                PROPS-END
 251
 252                Node-path: directory/file1
 253                Node-kind: file
 254                Node-action: add
 255                EOF
 256                text_no_props hello &&
 257                cat <<-\EOF &&
 258                Node-path: directory/file2
 259                Node-kind: file
 260                Node-action: add
 261                EOF
 262                text_no_props hi
 263        } >directory.dump &&
 264        try_dump directory.dump &&
 265
 266        git ls-tree -r --name-only HEAD >actual.files &&
 267        git checkout HEAD directory &&
 268        test_cmp expect.files actual.files &&
 269        test_cmp hello directory/file1 &&
 270        test_cmp hi directory/file2
 271'
 272
 273test_expect_success PIPE 'node without action' '
 274        reinit_git &&
 275        cat >inaction.dump <<-\EOF &&
 276        SVN-fs-dump-format-version: 3
 277
 278        Revision-number: 1
 279        Prop-content-length: 10
 280        Content-length: 10
 281
 282        PROPS-END
 283
 284        Node-path: directory
 285        Node-kind: dir
 286        Prop-content-length: 10
 287        Content-length: 10
 288
 289        PROPS-END
 290        EOF
 291        try_dump inaction.dump must_fail
 292'
 293
 294test_expect_success PIPE 'action: add node without text' '
 295        reinit_git &&
 296        cat >textless.dump <<-\EOF &&
 297        SVN-fs-dump-format-version: 3
 298
 299        Revision-number: 1
 300        Prop-content-length: 10
 301        Content-length: 10
 302
 303        PROPS-END
 304
 305        Node-path: textless
 306        Node-kind: file
 307        Node-action: add
 308        Prop-content-length: 10
 309        Content-length: 10
 310
 311        PROPS-END
 312        EOF
 313        try_dump textless.dump must_fail
 314'
 315
 316test_expect_failure PIPE 'change file mode but keep old content' '
 317        reinit_git &&
 318        cat >expect <<-\EOF &&
 319        OBJID
 320        :120000 100644 OBJID OBJID T    greeting
 321        OBJID
 322        :100644 120000 OBJID OBJID T    greeting
 323        OBJID
 324        :000000 100644 OBJID OBJID A    greeting
 325        EOF
 326        echo "link hello" >expect.blob &&
 327        echo hello >hello &&
 328        cat >filemode.dump <<-\EOF &&
 329        SVN-fs-dump-format-version: 3
 330
 331        Revision-number: 1
 332        Prop-content-length: 10
 333        Content-length: 10
 334
 335        PROPS-END
 336
 337        Node-path: greeting
 338        Node-kind: file
 339        Node-action: add
 340        Prop-content-length: 10
 341        Text-content-length: 11
 342        Content-length: 21
 343
 344        PROPS-END
 345        link hello
 346
 347        Revision-number: 2
 348        Prop-content-length: 10
 349        Content-length: 10
 350
 351        PROPS-END
 352
 353        Node-path: greeting
 354        Node-kind: file
 355        Node-action: change
 356        Prop-content-length: 33
 357        Content-length: 33
 358
 359        K 11
 360        svn:special
 361        V 1
 362        *
 363        PROPS-END
 364
 365        Revision-number: 3
 366        Prop-content-length: 10
 367        Content-length: 10
 368
 369        PROPS-END
 370
 371        Node-path: greeting
 372        Node-kind: file
 373        Node-action: change
 374        Prop-content-length: 10
 375        Content-length: 10
 376
 377        PROPS-END
 378        EOF
 379        try_dump filemode.dump &&
 380        {
 381                git rev-list HEAD |
 382                git diff-tree --root --stdin |
 383                sed "s/$_x40/OBJID/g"
 384        } >actual &&
 385        git show HEAD:greeting >actual.blob &&
 386        git show HEAD^:greeting >actual.target &&
 387        test_cmp expect actual &&
 388        test_cmp expect.blob actual.blob &&
 389        test_cmp hello actual.target
 390'
 391
 392test_expect_success PIPE 'change file mode and reiterate content' '
 393        reinit_git &&
 394        cat >expect <<-\EOF &&
 395        OBJID
 396        :120000 100644 OBJID OBJID T    greeting
 397        OBJID
 398        :100644 120000 OBJID OBJID T    greeting
 399        OBJID
 400        :000000 100644 OBJID OBJID A    greeting
 401        EOF
 402        echo "link hello" >expect.blob &&
 403        echo hello >hello &&
 404        cat >filemode2.dump <<-\EOF &&
 405        SVN-fs-dump-format-version: 3
 406
 407        Revision-number: 1
 408        Prop-content-length: 10
 409        Content-length: 10
 410
 411        PROPS-END
 412
 413        Node-path: greeting
 414        Node-kind: file
 415        Node-action: add
 416        Prop-content-length: 10
 417        Text-content-length: 11
 418        Content-length: 21
 419
 420        PROPS-END
 421        link hello
 422
 423        Revision-number: 2
 424        Prop-content-length: 10
 425        Content-length: 10
 426
 427        PROPS-END
 428
 429        Node-path: greeting
 430        Node-kind: file
 431        Node-action: change
 432        Prop-content-length: 33
 433        Text-content-length: 11
 434        Content-length: 44
 435
 436        K 11
 437        svn:special
 438        V 1
 439        *
 440        PROPS-END
 441        link hello
 442
 443        Revision-number: 3
 444        Prop-content-length: 10
 445        Content-length: 10
 446
 447        PROPS-END
 448
 449        Node-path: greeting
 450        Node-kind: file
 451        Node-action: change
 452        Prop-content-length: 10
 453        Text-content-length: 11
 454        Content-length: 21
 455
 456        PROPS-END
 457        link hello
 458        EOF
 459        try_dump filemode2.dump &&
 460        {
 461                git rev-list HEAD |
 462                git diff-tree --root --stdin |
 463                sed "s/$_x40/OBJID/g"
 464        } >actual &&
 465        git show HEAD:greeting >actual.blob &&
 466        git show HEAD^:greeting >actual.target &&
 467        test_cmp expect actual &&
 468        test_cmp expect.blob actual.blob &&
 469        test_cmp hello actual.target
 470'
 471
 472test_expect_success PIPE 'deltas not supported' '
 473        reinit_git &&
 474        {
 475                # (old) h + (inline) ello + (old) \n
 476                printf "SVNQ%b%b%s" "Q\003\006\005\004" "\001Q\0204\001\002" "ello" |
 477                q_to_nul
 478        } >delta &&
 479        {
 480                properties \
 481                        svn:author author@example.com \
 482                        svn:date "1999-01-05T00:01:002.000000Z" \
 483                        svn:log "add greeting" &&
 484                echo PROPS-END
 485        } >props &&
 486        {
 487                properties \
 488                        svn:author author@example.com \
 489                        svn:date "1999-01-06T00:01:002.000000Z" \
 490                        svn:log "change it" &&
 491                echo PROPS-END
 492        } >props2 &&
 493        {
 494                echo SVN-fs-dump-format-version: 3 &&
 495                echo &&
 496                echo Revision-number: 1 &&
 497                echo Prop-content-length: $(wc -c <props) &&
 498                echo Content-length: $(wc -c <props) &&
 499                echo &&
 500                cat props &&
 501                cat <<-\EOF &&
 502
 503                Node-path: hello
 504                Node-kind: file
 505                Node-action: add
 506                Prop-content-length: 10
 507                Text-content-length: 3
 508                Content-length: 13
 509
 510                PROPS-END
 511                hi
 512
 513                EOF
 514                echo Revision-number: 2 &&
 515                echo Prop-content-length: $(wc -c <props2) &&
 516                echo Content-length: $(wc -c <props2) &&
 517                echo &&
 518                cat props2 &&
 519                cat <<-\EOF &&
 520
 521                Node-path: hello
 522                Node-kind: file
 523                Node-action: change
 524                Text-delta: true
 525                Prop-content-length: 10
 526                EOF
 527                echo Text-content-length: $(wc -c <delta) &&
 528                echo Content-length: $((10 + $(wc -c <delta))) &&
 529                echo &&
 530                echo PROPS-END &&
 531                cat delta
 532        } >delta.dump &&
 533        test_must_fail try_dump delta.dump
 534'
 535
 536test_expect_success PIPE 'property deltas supported' '
 537        reinit_git &&
 538        cat >expect <<-\EOF &&
 539        OBJID
 540        :100755 100644 OBJID OBJID M    script.sh
 541        EOF
 542        {
 543                properties \
 544                        svn:author author@example.com \
 545                        svn:date "1999-03-06T00:01:002.000000Z" \
 546                        svn:log "make an executable, or chmod -x it" &&
 547                echo PROPS-END
 548        } >revprops &&
 549        {
 550                echo SVN-fs-dump-format-version: 3 &&
 551                echo &&
 552                echo Revision-number: 1 &&
 553                echo Prop-content-length: $(wc -c <revprops) &&
 554                echo Content-length: $(wc -c <revprops) &&
 555                echo &&
 556                cat revprops &&
 557                echo &&
 558                cat <<-\EOF &&
 559                Node-path: script.sh
 560                Node-kind: file
 561                Node-action: add
 562                Text-content-length: 0
 563                Prop-content-length: 39
 564                Content-length: 39
 565
 566                K 14
 567                svn:executable
 568                V 4
 569                true
 570                PROPS-END
 571
 572                EOF
 573                echo Revision-number: 2 &&
 574                echo Prop-content-length: $(wc -c <revprops) &&
 575                echo Content-length: $(wc -c <revprops) &&
 576                echo &&
 577                cat revprops &&
 578                echo &&
 579                cat <<-\EOF
 580                Node-path: script.sh
 581                Node-kind: file
 582                Node-action: change
 583                Prop-delta: true
 584                Prop-content-length: 30
 585                Content-length: 30
 586
 587                D 14
 588                svn:executable
 589                PROPS-END
 590                EOF
 591        } >propdelta.dump &&
 592        try_dump propdelta.dump &&
 593        {
 594                git rev-list HEAD |
 595                git diff-tree --stdin |
 596                sed "s/$_x40/OBJID/g"
 597        } >actual &&
 598        test_cmp expect actual
 599'
 600
 601test_expect_success PIPE 'properties on /' '
 602        reinit_git &&
 603        cat <<-\EOF >expect &&
 604        OBJID
 605        OBJID
 606        :000000 100644 OBJID OBJID A    greeting
 607        EOF
 608        sed -e "s/X$//" <<-\EOF >changeroot.dump &&
 609        SVN-fs-dump-format-version: 3
 610
 611        Revision-number: 1
 612        Prop-content-length: 10
 613        Content-length: 10
 614
 615        PROPS-END
 616
 617        Node-path: greeting
 618        Node-kind: file
 619        Node-action: add
 620        Text-content-length: 0
 621        Prop-content-length: 10
 622        Content-length: 10
 623
 624        PROPS-END
 625
 626        Revision-number: 2
 627        Prop-content-length: 10
 628        Content-length: 10
 629
 630        PROPS-END
 631
 632        Node-path: X
 633        Node-kind: dir
 634        Node-action: change
 635        Prop-delta: true
 636        Prop-content-length: 43
 637        Content-length: 43
 638
 639        K 10
 640        svn:ignore
 641        V 11
 642        build-area
 643
 644        PROPS-END
 645        EOF
 646        try_dump changeroot.dump &&
 647        {
 648                git rev-list HEAD |
 649                git diff-tree --root --always --stdin |
 650                sed "s/$_x40/OBJID/g"
 651        } >actual &&
 652        test_cmp expect actual
 653'
 654
 655test_expect_success PIPE 'deltas for typechange' '
 656        reinit_git &&
 657        cat >expect <<-\EOF &&
 658        OBJID
 659        :120000 100644 OBJID OBJID T    test-file
 660        OBJID
 661        :100755 120000 OBJID OBJID T    test-file
 662        OBJID
 663        :000000 100755 OBJID OBJID A    test-file
 664        EOF
 665        cat >deleteprop.dump <<-\EOF &&
 666        SVN-fs-dump-format-version: 3
 667
 668        Revision-number: 1
 669        Prop-content-length: 10
 670        Content-length: 10
 671
 672        PROPS-END
 673
 674        Node-path: test-file
 675        Node-kind: file
 676        Node-action: add
 677        Prop-delta: true
 678        Prop-content-length: 35
 679        Text-content-length: 17
 680        Content-length: 52
 681
 682        K 14
 683        svn:executable
 684        V 0
 685
 686        PROPS-END
 687        link testing 123
 688
 689        Revision-number: 2
 690        Prop-content-length: 10
 691        Content-length: 10
 692
 693        PROPS-END
 694
 695        Node-path: test-file
 696        Node-kind: file
 697        Node-action: change
 698        Prop-delta: true
 699        Prop-content-length: 53
 700        Text-content-length: 17
 701        Content-length: 70
 702
 703        K 11
 704        svn:special
 705        V 1
 706        *
 707        D 14
 708        svn:executable
 709        PROPS-END
 710        link testing 231
 711
 712        Revision-number: 3
 713        Prop-content-length: 10
 714        Content-length: 10
 715
 716        PROPS-END
 717
 718        Node-path: test-file
 719        Node-kind: file
 720        Node-action: change
 721        Prop-delta: true
 722        Prop-content-length: 27
 723        Text-content-length: 17
 724        Content-length: 44
 725
 726        D 11
 727        svn:special
 728        PROPS-END
 729        link testing 321
 730        EOF
 731        try_dump deleteprop.dump &&
 732        {
 733                git rev-list HEAD |
 734                git diff-tree --root --stdin |
 735                sed "s/$_x40/OBJID/g"
 736        } >actual &&
 737        test_cmp expect actual
 738'
 739
 740
 741test_expect_success 'set up svn repo' '
 742        svnconf=$PWD/svnconf &&
 743        mkdir -p "$svnconf" &&
 744
 745        if
 746                svnadmin -h >/dev/null 2>&1 &&
 747                svnadmin create simple-svn &&
 748                svnadmin load simple-svn <"$TEST_DIRECTORY/t9135/svn.dump" &&
 749                svn export --config-dir "$svnconf" "file://$PWD/simple-svn" simple-svnco
 750        then
 751                test_set_prereq SVNREPO
 752        fi
 753'
 754
 755test_expect_success SVNREPO,PIPE 't9135/svn.dump' '
 756        mkdir -p simple-git &&
 757        (
 758                cd simple-git &&
 759                reinit_git &&
 760                try_dump "$TEST_DIRECTORY/t9135/svn.dump"
 761        ) &&
 762        (
 763                cd simple-svnco &&
 764                git init &&
 765                git add . &&
 766                git fetch ../simple-git master &&
 767                git diff --exit-code FETCH_HEAD
 768        )
 769'
 770
 771test_done