1#!/bin/sh
   2test_description='check svn dumpfile importer'
   4. ./test-lib.sh
   6reinit_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}
  18try_dump () {
  20        input=$1 &&
  21        maybe_fail_svnfe=${2:+test_$2} &&
  22        maybe_fail_fi=${3:+test_$3} &&
  23        {
  25                $maybe_fail_svnfe test-svn-fe "$input" >stream 3<backflow &
  26        } &&
  27        $maybe_fail_fi git fast-import --cat-blob-fd=3 <stream 3>backflow &&
  28        wait $!
  29}
  30properties () {
  32        while test "$#" -ne 0
  33        do
  34                property="$1" &&
  35                value="$2" &&
  36                printf "%s\n" "K ${#property}" &&
  37                printf "%s\n" "$property" &&
  38                printf "%s\n" "V ${#value}" &&
  39                printf "%s\n" "$value" &&
  40                shift 2 ||
  41                return 1
  42        done
  43}
  44text_no_props () {
  46        text="$1
  47" &&
  48        printf "%s\n" "Prop-content-length: 10" &&
  49        printf "%s\n" "Text-content-length: ${#text}" &&
  50        printf "%s\n" "Content-length: $((${#text} + 10))" &&
  51        printf "%s\n" "" "PROPS-END" &&
  52        printf "%s\n" "$text"
  53}
  54>empty
  56test_expect_success 'setup: have pipes?' '
  58        rm -f frob &&
  59        if mkfifo frob
  60        then
  61                test_set_prereq PIPE
  62        fi
  63'
  64test_expect_success PIPE 'empty dump' '
  66        reinit_git &&
  67        echo "SVN-fs-dump-format-version: 2" >input &&
  68        try_dump input
  69'
  70test_expect_success PIPE 'v4 dumps not supported' '
  72        reinit_git &&
  73        echo "SVN-fs-dump-format-version: 4" >v4.dump &&
  74        try_dump v4.dump must_fail
  75'
  76test_expect_failure PIPE 'empty revision' '
  78        reinit_git &&
  79        printf "rev <nobody, nobody@local>: %s\n" "" "" >expect &&
  80        cat >emptyrev.dump <<-\EOF &&
  81        SVN-fs-dump-format-version: 3
  82        Revision-number: 1
  84        Prop-content-length: 0
  85        Content-length: 0
  86        Revision-number: 2
  88        Prop-content-length: 0
  89        Content-length: 0
  90        EOF
  92        try_dump emptyrev.dump &&
  93        git log -p --format="rev <%an, %ae>: %s" HEAD >actual &&
  94        test_cmp expect actual
  95'
  96test_expect_success PIPE 'empty properties' '
  98        reinit_git &&
  99        printf "rev <nobody, nobody@local>: %s\n" "" "" >expect &&
 100        cat >emptyprop.dump <<-\EOF &&
 101        SVN-fs-dump-format-version: 3
 102        Revision-number: 1
 104        Prop-content-length: 10
 105        Content-length: 10
 106        PROPS-END
 108        Revision-number: 2
 110        Prop-content-length: 10
 111        Content-length: 10
 112        PROPS-END
 114        EOF
 115        try_dump emptyprop.dump &&
 116        git log -p --format="rev <%an, %ae>: %s" HEAD >actual &&
 117        test_cmp expect actual
 118'
 119test_expect_success PIPE 'author name and commit message' '
 121        reinit_git &&
 122        echo "<author@example.com, author@example.com@local>" >expect.author &&
 123        cat >message <<-\EOF &&
 124        A concise summary of the change
 125        A detailed description of the change, why it is needed, what
 127        was broken and why applying this is the best course of action.
 128        * file.c
 130            Details pertaining to an individual file.
 131        EOF
 132        {
 133                properties \
 134                        svn:author author@example.com \
 135                        svn:log "$(cat message)" &&
 136                echo PROPS-END
 137        } >props &&
 138        {
 139                echo "SVN-fs-dump-format-version: 3" &&
 140                echo &&
 141                echo "Revision-number: 1" &&
 142                echo Prop-content-length: $(wc -c <props) &&
 143                echo Content-length: $(wc -c <props) &&
 144                echo &&
 145                cat props
 146        } >log.dump &&
 147        try_dump log.dump &&
 148        git log -p --format="%B" HEAD >actual.log &&
 149        git log --format="<%an, %ae>" >actual.author &&
 150        test_cmp message actual.log &&
 151        test_cmp expect.author actual.author
 152'
 153test_expect_success PIPE 'unsupported properties are ignored' '
 155        reinit_git &&
 156        echo author >expect &&
 157        cat >extraprop.dump <<-\EOF &&
 158        SVN-fs-dump-format-version: 3
 159        Revision-number: 1
 161        Prop-content-length: 56
 162        Content-length: 56
 163        K 8
 165        nonsense
 166        V 1
 167        y
 168        K 10
 169        svn:author
 170        V 6
 171        author
 172        PROPS-END
 173        EOF
 174        try_dump extraprop.dump &&
 175        git log -p --format=%an HEAD >actual &&
 176        test_cmp expect actual
 177'
 178test_expect_failure PIPE 'timestamp and empty file' '
 180        echo author@example.com >expect.author &&
 181        echo 1999-01-01 >expect.date &&
 182        echo file >expect.files &&
 183        reinit_git &&
 184        {
 185                properties \
 186                        svn:author author@example.com \
 187                        svn:date "1999-01-01T00:01:002.000000Z" \
 188                        svn:log "add empty file" &&
 189                echo PROPS-END
 190        } >props &&
 191        {
 192                cat <<-EOF &&
 193                SVN-fs-dump-format-version: 3
 194                Revision-number: 1
 196                EOF
 197                echo Prop-content-length: $(wc -c <props) &&
 198                echo Content-length: $(wc -c <props) &&
 199                echo &&
 200                cat props &&
 201                cat <<-\EOF
 202                Node-path: empty-file
 204                Node-kind: file
 205                Node-action: add
 206                Content-length: 0
 207                EOF
 209        } >emptyfile.dump &&
 210        try_dump emptyfile.dump &&
 211        git log --format=%an HEAD >actual.author &&
 212        git log --date=short --format=%ad HEAD >actual.date &&
 213        git ls-tree -r --name-only HEAD >actual.files &&
 214        test_cmp expect.author actual.author &&
 215        test_cmp expect.date actual.date &&
 216        test_cmp expect.files actual.files &&
 217        git checkout HEAD empty-file &&
 218        test_cmp empty file
 219'
 220test_expect_success PIPE 'directory with files' '
 222        reinit_git &&
 223        printf "%s\n" directory/file1 directory/file2 >expect.files &&
 224        echo hi >hi &&
 225        echo hello >hello &&
 226        {
 227                properties \
 228                        svn:author author@example.com \
 229                        svn:date "1999-02-01T00:01:002.000000Z" \
 230                        svn:log "add directory with some files in it" &&
 231                echo PROPS-END
 232        } >props &&
 233        {
 234                cat <<-EOF &&
 235                SVN-fs-dump-format-version: 3
 236                Revision-number: 1
 238                EOF
 239                echo Prop-content-length: $(wc -c <props) &&
 240                echo Content-length: $(wc -c <props) &&
 241                echo &&
 242                cat props &&
 243                cat <<-\EOF &&
 244                Node-path: directory
 246                Node-kind: dir
 247                Node-action: add
 248                Prop-content-length: 10
 249                Content-length: 10
 250                PROPS-END
 252                Node-path: directory/file1
 254                Node-kind: file
 255                Node-action: add
 256                EOF
 257                text_no_props hello &&
 258                cat <<-\EOF &&
 259                Node-path: directory/file2
 260                Node-kind: file
 261                Node-action: add
 262                EOF
 263                text_no_props hi
 264        } >directory.dump &&
 265        try_dump directory.dump &&
 266        git ls-tree -r --name-only HEAD >actual.files &&
 268        git checkout HEAD directory &&
 269        test_cmp expect.files actual.files &&
 270        test_cmp hello directory/file1 &&
 271        test_cmp hi directory/file2
 272'
 273test_expect_success PIPE 'branch name with backslash' '
 275        reinit_git &&
 276        sort <<-\EOF >expect.branch-files &&
 277        trunk/file1
 278        trunk/file2
 279        "branches/UpdateFOPto094\\/file1"
 280        "branches/UpdateFOPto094\\/file2"
 281        EOF
 282        echo hi >hi &&
 284        echo hello >hello &&
 285        {
 286                properties \
 287                        svn:author author@example.com \
 288                        svn:date "1999-02-02T00:01:02.000000Z" \
 289                        svn:log "add directory with some files in it" &&
 290                echo PROPS-END
 291        } >props.setup &&
 292        {
 293                properties \
 294                        svn:author brancher@example.com \
 295                        svn:date "2007-12-06T21:38:34.000000Z" \
 296                        svn:log "Updating fop to .94 and adjust fo-stylesheets" &&
 297                echo PROPS-END
 298        } >props.branch &&
 299        {
 300                cat <<-EOF &&
 301                SVN-fs-dump-format-version: 3
 302                Revision-number: 1
 304                EOF
 305                echo Prop-content-length: $(wc -c <props.setup) &&
 306                echo Content-length: $(wc -c <props.setup) &&
 307                echo &&
 308                cat props.setup &&
 309                cat <<-\EOF &&
 310                Node-path: trunk
 312                Node-kind: dir
 313                Node-action: add
 314                Prop-content-length: 10
 315                Content-length: 10
 316                PROPS-END
 318                Node-path: branches
 320                Node-kind: dir
 321                Node-action: add
 322                Prop-content-length: 10
 323                Content-length: 10
 324                PROPS-END
 326                Node-path: trunk/file1
 328                Node-kind: file
 329                Node-action: add
 330                EOF
 331                text_no_props hello &&
 332                cat <<-\EOF &&
 333                Node-path: trunk/file2
 334                Node-kind: file
 335                Node-action: add
 336                EOF
 337                text_no_props hi &&
 338                cat <<-\EOF &&
 339                Revision-number: 2
 341                EOF
 342                echo Prop-content-length: $(wc -c <props.branch) &&
 343                echo Content-length: $(wc -c <props.branch) &&
 344                echo &&
 345                cat props.branch &&
 346                cat <<-\EOF
 347                Node-path: branches/UpdateFOPto094\
 349                Node-kind: dir
 350                Node-action: add
 351                Node-copyfrom-rev: 1
 352                Node-copyfrom-path: trunk
 353                Node-kind: dir
 355                Node-action: add
 356                Prop-content-length: 34
 357                Content-length: 34
 358                K 13
 360                svn:mergeinfo
 361                V 0
 362                PROPS-END
 364                EOF
 365        } >branch.dump &&
 366        try_dump branch.dump &&
 367        git ls-tree -r --name-only HEAD |
 369        sort >actual.branch-files &&
 370        test_cmp expect.branch-files actual.branch-files
 371'
 372test_expect_success PIPE 'node without action' '
 374        reinit_git &&
 375        cat >inaction.dump <<-\EOF &&
 376        SVN-fs-dump-format-version: 3
 377        Revision-number: 1
 379        Prop-content-length: 10
 380        Content-length: 10
 381        PROPS-END
 383        Node-path: directory
 385        Node-kind: dir
 386        Prop-content-length: 10
 387        Content-length: 10
 388        PROPS-END
 390        EOF
 391        try_dump inaction.dump must_fail
 392'
 393test_expect_success PIPE 'action: add node without text' '
 395        reinit_git &&
 396        cat >textless.dump <<-\EOF &&
 397        SVN-fs-dump-format-version: 3
 398        Revision-number: 1
 400        Prop-content-length: 10
 401        Content-length: 10
 402        PROPS-END
 404        Node-path: textless
 406        Node-kind: file
 407        Node-action: add
 408        Prop-content-length: 10
 409        Content-length: 10
 410        PROPS-END
 412        EOF
 413        try_dump textless.dump must_fail
 414'
 415test_expect_failure PIPE 'change file mode but keep old content' '
 417        reinit_git &&
 418        cat >expect <<-\EOF &&
 419        OBJID
 420        :120000 100644 OBJID OBJID T    greeting
 421        OBJID
 422        :100644 120000 OBJID OBJID T    greeting
 423        OBJID
 424        :000000 100644 OBJID OBJID A    greeting
 425        EOF
 426        echo "link hello" >expect.blob &&
 427        echo hello >hello &&
 428        cat >filemode.dump <<-\EOF &&
 429        SVN-fs-dump-format-version: 3
 430        Revision-number: 1
 432        Prop-content-length: 10
 433        Content-length: 10
 434        PROPS-END
 436        Node-path: greeting
 438        Node-kind: file
 439        Node-action: add
 440        Prop-content-length: 10
 441        Text-content-length: 11
 442        Content-length: 21
 443        PROPS-END
 445        link hello
 446        Revision-number: 2
 448        Prop-content-length: 10
 449        Content-length: 10
 450        PROPS-END
 452        Node-path: greeting
 454        Node-kind: file
 455        Node-action: change
 456        Prop-content-length: 33
 457        Content-length: 33
 458        K 11
 460        svn:special
 461        V 1
 462        *
 463        PROPS-END
 464        Revision-number: 3
 466        Prop-content-length: 10
 467        Content-length: 10
 468        PROPS-END
 470        Node-path: greeting
 472        Node-kind: file
 473        Node-action: change
 474        Prop-content-length: 10
 475        Content-length: 10
 476        PROPS-END
 478        EOF
 479        try_dump filemode.dump &&
 480        {
 481                git rev-list HEAD |
 482                git diff-tree --root --stdin |
 483                sed "s/$_x40/OBJID/g"
 484        } >actual &&
 485        git show HEAD:greeting >actual.blob &&
 486        git show HEAD^:greeting >actual.target &&
 487        test_cmp expect actual &&
 488        test_cmp expect.blob actual.blob &&
 489        test_cmp hello actual.target
 490'
 491test_expect_success PIPE 'NUL in property value' '
 493        reinit_git &&
 494        echo "commit message" >expect.message &&
 495        {
 496                properties \
 497                        unimportant "something with a NUL (Q)" \
 498                        svn:log "commit message"&&
 499                echo PROPS-END
 500        } |
 501        q_to_nul >props &&
 502        {
 503                cat <<-\EOF &&
 504                SVN-fs-dump-format-version: 3
 505                Revision-number: 1
 507                EOF
 508                echo Prop-content-length: $(wc -c <props) &&
 509                echo Content-length: $(wc -c <props) &&
 510                echo &&
 511                cat props
 512        } >nulprop.dump &&
 513        try_dump nulprop.dump &&
 514        git diff-tree --always -s --format=%s HEAD >actual.message &&
 515        test_cmp expect.message actual.message
 516'
 517test_expect_success PIPE 'NUL in log message, file content, and property name' '
 519        # Caveat: svnadmin 1.6.16 (r1073529) truncates at \0 in the
 520        # svn:specialQnotreally example.
 521        reinit_git &&
 522        cat >expect <<-\EOF &&
 523        OBJID
 524        :100644 100644 OBJID OBJID M    greeting
 525        OBJID
 526        :000000 100644 OBJID OBJID A    greeting
 527        EOF
 528        printf "\n%s\n" "something with an ASCII NUL (Q)" >expect.message &&
 529        printf "%s\n" "helQo" >expect.hello1 &&
 530        printf "%s\n" "link hello" >expect.hello2 &&
 531        {
 532                properties svn:log "something with an ASCII NUL (Q)" &&
 533                echo PROPS-END
 534        } |
 535        q_to_nul >props &&
 536        {
 537                q_to_nul <<-\EOF &&
 538                SVN-fs-dump-format-version: 3
 539                Revision-number: 1
 541                Prop-content-length: 10
 542                Content-length: 10
 543                PROPS-END
 545                Node-path: greeting
 547                Node-kind: file
 548                Node-action: add
 549                Prop-content-length: 10
 550                Text-content-length: 6
 551                Content-length: 16
 552                PROPS-END
 554                helQo
 555                Revision-number: 2
 557                EOF
 558                echo Prop-content-length: $(wc -c <props) &&
 559                echo Content-length: $(wc -c <props) &&
 560                echo &&
 561                cat props &&
 562                q_to_nul <<-\EOF
 563                Node-path: greeting
 565                Node-kind: file
 566                Node-action: change
 567                Prop-content-length: 43
 568                Text-content-length: 11
 569                Content-length: 54
 570                K 21
 572                svn:specialQnotreally
 573                V 1
 574                *
 575                PROPS-END
 576                link hello
 577                EOF
 578        } >8bitclean.dump &&
 579        try_dump 8bitclean.dump &&
 580        {
 581                git rev-list HEAD |
 582                git diff-tree --root --stdin |
 583                sed "s/$_x40/OBJID/g"
 584        } >actual &&
 585        {
 586                git cat-file commit HEAD | nul_to_q &&
 587                echo
 588        } |
 589        sed -ne "/^\$/,\$ p" >actual.message &&
 590        git cat-file blob HEAD^:greeting | nul_to_q >actual.hello1 &&
 591        git cat-file blob HEAD:greeting | nul_to_q >actual.hello2 &&
 592        test_cmp expect actual &&
 593        test_cmp expect.message actual.message &&
 594        test_cmp expect.hello1 actual.hello1 &&
 595        test_cmp expect.hello2 actual.hello2
 596'
 597test_expect_success PIPE 'change file mode and reiterate content' '
 599        reinit_git &&
 600        cat >expect <<-\EOF &&
 601        OBJID
 602        :120000 100644 OBJID OBJID T    greeting
 603        OBJID
 604        :100644 120000 OBJID OBJID T    greeting
 605        OBJID
 606        :000000 100644 OBJID OBJID A    greeting
 607        EOF
 608        echo "link hello" >expect.blob &&
 609        echo hello >hello &&
 610        cat >filemode2.dump <<-\EOF &&
 611        SVN-fs-dump-format-version: 3
 612        Revision-number: 1
 614        Prop-content-length: 10
 615        Content-length: 10
 616        PROPS-END
 618        Node-path: greeting
 620        Node-kind: file
 621        Node-action: add
 622        Prop-content-length: 10
 623        Text-content-length: 11
 624        Content-length: 21
 625        PROPS-END
 627        link hello
 628        Revision-number: 2
 630        Prop-content-length: 10
 631        Content-length: 10
 632        PROPS-END
 634        Node-path: greeting
 636        Node-kind: file
 637        Node-action: change
 638        Prop-content-length: 33
 639        Text-content-length: 11
 640        Content-length: 44
 641        K 11
 643        svn:special
 644        V 1
 645        *
 646        PROPS-END
 647        link hello
 648        Revision-number: 3
 650        Prop-content-length: 10
 651        Content-length: 10
 652        PROPS-END
 654        Node-path: greeting
 656        Node-kind: file
 657        Node-action: change
 658        Prop-content-length: 10
 659        Text-content-length: 11
 660        Content-length: 21
 661        PROPS-END
 663        link hello
 664        EOF
 665        try_dump filemode2.dump &&
 666        {
 667                git rev-list HEAD |
 668                git diff-tree --root --stdin |
 669                sed "s/$_x40/OBJID/g"
 670        } >actual &&
 671        git show HEAD:greeting >actual.blob &&
 672        git show HEAD^:greeting >actual.target &&
 673        test_cmp expect actual &&
 674        test_cmp expect.blob actual.blob &&
 675        test_cmp hello actual.target
 676'
 677test_expect_success PIPE 'deltas supported' '
 679        reinit_git &&
 680        {
 681                # (old) h + (inline) ello + (old) \n
 682                printf "SVNQ%b%b%s" "Q\003\006\005\004" "\001Q\0204\001\002" "ello" |
 683                q_to_nul
 684        } >delta &&
 685        {
 686                properties \
 687                        svn:author author@example.com \
 688                        svn:date "1999-01-05T00:01:002.000000Z" \
 689                        svn:log "add greeting" &&
 690                echo PROPS-END
 691        } >props &&
 692        {
 693                properties \
 694                        svn:author author@example.com \
 695                        svn:date "1999-01-06T00:01:002.000000Z" \
 696                        svn:log "change it" &&
 697                echo PROPS-END
 698        } >props2 &&
 699        {
 700                echo SVN-fs-dump-format-version: 3 &&
 701                echo &&
 702                echo Revision-number: 1 &&
 703                echo Prop-content-length: $(wc -c <props) &&
 704                echo Content-length: $(wc -c <props) &&
 705                echo &&
 706                cat props &&
 707                cat <<-\EOF &&
 708                Node-path: hello
 710                Node-kind: file
 711                Node-action: add
 712                Prop-content-length: 10
 713                Text-content-length: 3
 714                Content-length: 13
 715                PROPS-END
 717                hi
 718                EOF
 720                echo Revision-number: 2 &&
 721                echo Prop-content-length: $(wc -c <props2) &&
 722                echo Content-length: $(wc -c <props2) &&
 723                echo &&
 724                cat props2 &&
 725                cat <<-\EOF &&
 726                Node-path: hello
 728                Node-kind: file
 729                Node-action: change
 730                Text-delta: true
 731                Prop-content-length: 10
 732                EOF
 733                echo Text-content-length: $(wc -c <delta) &&
 734                echo Content-length: $((10 + $(wc -c <delta))) &&
 735                echo &&
 736                echo PROPS-END &&
 737                cat delta
 738        } >delta.dump &&
 739        try_dump delta.dump
 740'
 741test_expect_success PIPE 'property deltas supported' '
 743        reinit_git &&
 744        cat >expect <<-\EOF &&
 745        OBJID
 746        :100755 100644 OBJID OBJID M    script.sh
 747        EOF
 748        {
 749                properties \
 750                        svn:author author@example.com \
 751                        svn:date "1999-03-06T00:01:002.000000Z" \
 752                        svn:log "make an executable, or chmod -x it" &&
 753                echo PROPS-END
 754        } >revprops &&
 755        {
 756                echo SVN-fs-dump-format-version: 3 &&
 757                echo &&
 758                echo Revision-number: 1 &&
 759                echo Prop-content-length: $(wc -c <revprops) &&
 760                echo Content-length: $(wc -c <revprops) &&
 761                echo &&
 762                cat revprops &&
 763                echo &&
 764                cat <<-\EOF &&
 765                Node-path: script.sh
 766                Node-kind: file
 767                Node-action: add
 768                Text-content-length: 0
 769                Prop-content-length: 39
 770                Content-length: 39
 771                K 14
 773                svn:executable
 774                V 4
 775                true
 776                PROPS-END
 777                EOF
 779                echo Revision-number: 2 &&
 780                echo Prop-content-length: $(wc -c <revprops) &&
 781                echo Content-length: $(wc -c <revprops) &&
 782                echo &&
 783                cat revprops &&
 784                echo &&
 785                cat <<-\EOF
 786                Node-path: script.sh
 787                Node-kind: file
 788                Node-action: change
 789                Prop-delta: true
 790                Prop-content-length: 30
 791                Content-length: 30
 792                D 14
 794                svn:executable
 795                PROPS-END
 796                EOF
 797        } >propdelta.dump &&
 798        try_dump propdelta.dump &&
 799        {
 800                git rev-list HEAD |
 801                git diff-tree --stdin |
 802                sed "s/$_x40/OBJID/g"
 803        } >actual &&
 804        test_cmp expect actual
 805'
 806test_expect_success PIPE 'properties on /' '
 808        reinit_git &&
 809        cat <<-\EOF >expect &&
 810        OBJID
 811        OBJID
 812        :000000 100644 OBJID OBJID A    greeting
 813        EOF
 814        sed -e "s/X$//" <<-\EOF >changeroot.dump &&
 815        SVN-fs-dump-format-version: 3
 816        Revision-number: 1
 818        Prop-content-length: 10
 819        Content-length: 10
 820        PROPS-END
 822        Node-path: greeting
 824        Node-kind: file
 825        Node-action: add
 826        Text-content-length: 0
 827        Prop-content-length: 10
 828        Content-length: 10
 829        PROPS-END
 831        Revision-number: 2
 833        Prop-content-length: 10
 834        Content-length: 10
 835        PROPS-END
 837        Node-path: X
 839        Node-kind: dir
 840        Node-action: change
 841        Prop-delta: true
 842        Prop-content-length: 43
 843        Content-length: 43
 844        K 10
 846        svn:ignore
 847        V 11
 848        build-area
 849        PROPS-END
 851        EOF
 852        try_dump changeroot.dump &&
 853        {
 854                git rev-list HEAD |
 855                git diff-tree --root --always --stdin |
 856                sed "s/$_x40/OBJID/g"
 857        } >actual &&
 858        test_cmp expect actual
 859'
 860test_expect_success PIPE 'deltas for typechange' '
 862        reinit_git &&
 863        cat >expect <<-\EOF &&
 864        OBJID
 865        :120000 100644 OBJID OBJID T    test-file
 866        OBJID
 867        :100755 120000 OBJID OBJID T    test-file
 868        OBJID
 869        :000000 100755 OBJID OBJID A    test-file
 870        EOF
 871        cat >deleteprop.dump <<-\EOF &&
 872        SVN-fs-dump-format-version: 3
 873        Revision-number: 1
 875        Prop-content-length: 10
 876        Content-length: 10
 877        PROPS-END
 879        Node-path: test-file
 881        Node-kind: file
 882        Node-action: add
 883        Prop-delta: true
 884        Prop-content-length: 35
 885        Text-content-length: 17
 886        Content-length: 52
 887        K 14
 889        svn:executable
 890        V 0
 891        PROPS-END
 893        link testing 123
 894        Revision-number: 2
 896        Prop-content-length: 10
 897        Content-length: 10
 898        PROPS-END
 900        Node-path: test-file
 902        Node-kind: file
 903        Node-action: change
 904        Prop-delta: true
 905        Prop-content-length: 53
 906        Text-content-length: 17
 907        Content-length: 70
 908        K 11
 910        svn:special
 911        V 1
 912        *
 913        D 14
 914        svn:executable
 915        PROPS-END
 916        link testing 231
 917        Revision-number: 3
 919        Prop-content-length: 10
 920        Content-length: 10
 921        PROPS-END
 923        Node-path: test-file
 925        Node-kind: file
 926        Node-action: change
 927        Prop-delta: true
 928        Prop-content-length: 27
 929        Text-content-length: 17
 930        Content-length: 44
 931        D 11
 933        svn:special
 934        PROPS-END
 935        link testing 321
 936        EOF
 937        try_dump deleteprop.dump &&
 938        {
 939                git rev-list HEAD |
 940                git diff-tree --root --stdin |
 941                sed "s/$_x40/OBJID/g"
 942        } >actual &&
 943        test_cmp expect actual
 944'
 945test_expect_success PIPE 'deltas need not consume the whole preimage' '
 947        reinit_git &&
 948        cat >expect <<-\EOF &&
 949        OBJID
 950        :120000 100644 OBJID OBJID T    postimage
 951        OBJID
 952        :100644 120000 OBJID OBJID T    postimage
 953        OBJID
 954        :000000 100644 OBJID OBJID A    postimage
 955        EOF
 956        echo "first preimage" >expect.1 &&
 957        printf target >expect.2 &&
 958        printf lnk >expect.3 &&
 959        {
 960                printf "SVNQ%b%b%b" "QQ\017\001\017" "\0217" "first preimage\n" |
 961                q_to_nul
 962        } >delta.1 &&
 963        {
 964                properties svn:special "*" &&
 965                echo PROPS-END
 966        } >symlink.props &&
 967        {
 968                printf "SVNQ%b%b%b" "Q\002\013\004\012" "\0201\001\001\0211" "lnk target" |
 969                q_to_nul
 970        } >delta.2 &&
 971        {
 972                printf "SVNQ%b%b" "Q\004\003\004Q" "\001Q\002\002" |
 973                q_to_nul
 974        } >delta.3 &&
 975        {
 976                cat <<-\EOF &&
 977                SVN-fs-dump-format-version: 3
 978                Revision-number: 1
 980                Prop-content-length: 10
 981                Content-length: 10
 982                PROPS-END
 984                Node-path: postimage
 986                Node-kind: file
 987                Node-action: add
 988                Text-delta: true
 989                Prop-content-length: 10
 990                EOF
 991                echo Text-content-length: $(wc -c <delta.1) &&
 992                echo Content-length: $((10 + $(wc -c <delta.1))) &&
 993                echo &&
 994                echo PROPS-END &&
 995                cat delta.1 &&
 996                cat <<-\EOF &&
 997                Revision-number: 2
 999                Prop-content-length: 10
1000                Content-length: 10
1001                PROPS-END
1003                Node-path: postimage
1005                Node-kind: file
1006                Node-action: change
1007                Text-delta: true
1008                EOF
1009                echo Prop-content-length: $(wc -c <symlink.props) &&
1010                echo Text-content-length: $(wc -c <delta.2) &&
1011                echo Content-length: $(($(wc -c <symlink.props) + $(wc -c <delta.2))) &&
1012                echo &&
1013                cat symlink.props &&
1014                cat delta.2 &&
1015                cat <<-\EOF &&
1016                Revision-number: 3
1018                Prop-content-length: 10
1019                Content-length: 10
1020                PROPS-END
1022                Node-path: postimage
1024                Node-kind: file
1025                Node-action: change
1026                Text-delta: true
1027                Prop-content-length: 10
1028                EOF
1029                echo Text-content-length: $(wc -c <delta.3) &&
1030                echo Content-length: $((10 + $(wc -c <delta.3))) &&
1031                echo &&
1032                echo PROPS-END &&
1033                cat delta.3 &&
1034                echo
1035        } >deltapartial.dump &&
1036        try_dump deltapartial.dump &&
1037        {
1038                git rev-list HEAD |
1039                git diff-tree --root --stdin |
1040                sed "s/$_x40/OBJID/g"
1041        } >actual &&
1042        test_cmp expect actual &&
1043        git show HEAD:postimage >actual.3 &&
1044        git show HEAD^:postimage >actual.2 &&
1045        git show HEAD^^:postimage >actual.1 &&
1046        test_cmp expect.1 actual.1 &&
1047        test_cmp expect.2 actual.2 &&
1048        test_cmp expect.3 actual.3
1049'
1050test_expect_success PIPE 'no hang for delta trying to read past end of preimage' '
1052        reinit_git &&
1053        {
1054                # COPY 1
1055                printf "SVNQ%b%b" "Q\001\001\002Q" "\001Q" |
1056                q_to_nul
1057        } >greedy.delta &&
1058        {
1059                cat <<-\EOF &&
1060                SVN-fs-dump-format-version: 3
1061                Revision-number: 1
1063                Prop-content-length: 10
1064                Content-length: 10
1065                PROPS-END
1067                Node-path: bootstrap
1069                Node-kind: file
1070                Node-action: add
1071                Text-delta: true
1072                Prop-content-length: 10
1073                EOF
1074                echo Text-content-length: $(wc -c <greedy.delta) &&
1075                echo Content-length: $((10 + $(wc -c <greedy.delta))) &&
1076                echo &&
1077                echo PROPS-END &&
1078                cat greedy.delta &&
1079                echo
1080        } >greedydelta.dump &&
1081        try_dump greedydelta.dump must_fail might_fail
1082'
1083test_expect_success 'set up svn repo' '
1085        svnconf=$PWD/svnconf &&
1086        mkdir -p "$svnconf" &&
1087        if
1089                svnadmin -h >/dev/null 2>&1 &&
1090                svnadmin create simple-svn &&
1091                svnadmin load simple-svn <"$TEST_DIRECTORY/t9135/svn.dump" &&
1092                svn export --config-dir "$svnconf" "file://$PWD/simple-svn" simple-svnco
1093        then
1094                test_set_prereq SVNREPO
1095        fi
1096'
1097test_expect_success SVNREPO,PIPE 't9135/svn.dump' '
1099        mkdir -p simple-git &&
1100        (
1101                cd simple-git &&
1102                reinit_git &&
1103                try_dump "$TEST_DIRECTORY/t9135/svn.dump"
1104        ) &&
1105        (
1106                cd simple-svnco &&
1107                git init &&
1108                git add . &&
1109                git fetch ../simple-git master &&
1110                git diff --exit-code FETCH_HEAD
1111        )
1112'
1113test_done