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