t / t9301-fast-import-notes.shon commit checkout: advice how to get out of detached HEAD mode (af9ded5)
   1#!/bin/sh
   2#
   3# Copyright (c) 2009 Johan Herland
   4#
   5
   6test_description='test git fast-import of notes objects'
   7. ./test-lib.sh
   8
   9
  10test_tick
  11cat >input <<INPUT_END
  12commit refs/heads/master
  13committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
  14data <<COMMIT
  15first commit
  16COMMIT
  17
  18M 644 inline foo
  19data <<EOF
  20file foo in first commit
  21EOF
  22
  23M 755 inline bar
  24data <<EOF
  25file bar in first commit
  26EOF
  27
  28M 644 inline baz/xyzzy
  29data <<EOF
  30file baz/xyzzy in first commit
  31EOF
  32
  33commit refs/heads/master
  34committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
  35data <<COMMIT
  36second commit
  37COMMIT
  38
  39M 644 inline foo
  40data <<EOF
  41file foo in second commit
  42EOF
  43
  44M 755 inline baz/xyzzy
  45data <<EOF
  46file baz/xyzzy in second commit
  47EOF
  48
  49commit refs/heads/master
  50committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
  51data <<COMMIT
  52third commit
  53COMMIT
  54
  55M 644 inline foo
  56data <<EOF
  57file foo in third commit
  58EOF
  59
  60commit refs/heads/master
  61committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
  62data <<COMMIT
  63fourth commit
  64COMMIT
  65
  66M 755 inline bar
  67data <<EOF
  68file bar in fourth commit
  69EOF
  70
  71INPUT_END
  72
  73test_expect_success 'set up master branch' '
  74
  75        git fast-import <input &&
  76        git whatchanged master
  77'
  78
  79commit4=$(git rev-parse refs/heads/master)
  80commit3=$(git rev-parse "$commit4^")
  81commit2=$(git rev-parse "$commit4~2")
  82commit1=$(git rev-parse "$commit4~3")
  83
  84test_tick
  85cat >input <<INPUT_END
  86commit refs/notes/test
  87committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
  88data <<COMMIT
  89first notes commit
  90COMMIT
  91
  92M 644 inline $commit1
  93data <<EOF
  94first note for first commit
  95EOF
  96
  97M 755 inline $commit2
  98data <<EOF
  99first note for second commit
 100EOF
 101
 102INPUT_END
 103
 104cat >expect <<EXPECT_END
 105    fourth commit
 106    third commit
 107    second commit
 108    first note for second commit
 109    first commit
 110    first note for first commit
 111EXPECT_END
 112
 113test_expect_success 'add notes with simple M command' '
 114
 115        git fast-import <input &&
 116        GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
 117        test_cmp expect actual
 118
 119'
 120
 121test_tick
 122cat >input <<INPUT_END
 123feature notes
 124commit refs/notes/test
 125committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 126data <<COMMIT
 127second notes commit
 128COMMIT
 129
 130from refs/notes/test^0
 131N inline $commit3
 132data <<EOF
 133first note for third commit
 134EOF
 135
 136N inline $commit4
 137data <<EOF
 138first note for fourth commit
 139EOF
 140
 141INPUT_END
 142
 143cat >expect <<EXPECT_END
 144    fourth commit
 145    first note for fourth commit
 146    third commit
 147    first note for third commit
 148    second commit
 149    first note for second commit
 150    first commit
 151    first note for first commit
 152EXPECT_END
 153
 154test_expect_success 'add notes with simple N command' '
 155
 156        git fast-import <input &&
 157        GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
 158        test_cmp expect actual
 159
 160'
 161
 162test_tick
 163cat >input <<INPUT_END
 164commit refs/notes/test
 165committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 166data <<COMMIT
 167third notes commit
 168COMMIT
 169
 170from refs/notes/test^0
 171N inline $commit1
 172data <<EOF
 173second note for first commit
 174EOF
 175
 176N inline $commit2
 177data <<EOF
 178second note for second commit
 179EOF
 180
 181N inline $commit3
 182data <<EOF
 183second note for third commit
 184EOF
 185
 186N inline $commit4
 187data <<EOF
 188second note for fourth commit
 189EOF
 190
 191INPUT_END
 192
 193cat >expect <<EXPECT_END
 194    fourth commit
 195    second note for fourth commit
 196    third commit
 197    second note for third commit
 198    second commit
 199    second note for second commit
 200    first commit
 201    second note for first commit
 202EXPECT_END
 203
 204test_expect_success 'update existing notes with N command' '
 205
 206        git fast-import <input &&
 207        GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
 208        test_cmp expect actual
 209
 210'
 211
 212test_tick
 213cat >input <<INPUT_END
 214commit refs/notes/test
 215committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 216data <<COMMIT
 217fourth notes commit
 218COMMIT
 219
 220from refs/notes/test^0
 221M 644 inline $(echo "$commit3" | sed "s|^..|&/|")
 222data <<EOF
 223prefix of note for third commit
 224EOF
 225
 226M 644 inline $(echo "$commit4" | sed "s|^..|&/|")
 227data <<EOF
 228prefix of note for fourth commit
 229EOF
 230
 231M 644 inline $(echo "$commit4" | sed "s|^\(..\)\(..\)|\1/\2/|")
 232data <<EOF
 233pre-prefix of note for fourth commit
 234EOF
 235
 236N inline $commit1
 237data <<EOF
 238third note for first commit
 239EOF
 240
 241N inline $commit2
 242data <<EOF
 243third note for second commit
 244EOF
 245
 246N inline $commit3
 247data <<EOF
 248third note for third commit
 249EOF
 250
 251N inline $commit4
 252data <<EOF
 253third note for fourth commit
 254EOF
 255
 256
 257INPUT_END
 258
 259whitespace="    "
 260
 261cat >expect <<EXPECT_END
 262    fourth commit
 263    pre-prefix of note for fourth commit
 264$whitespace
 265    prefix of note for fourth commit
 266$whitespace
 267    third note for fourth commit
 268    third commit
 269    prefix of note for third commit
 270$whitespace
 271    third note for third commit
 272    second commit
 273    third note for second commit
 274    first commit
 275    third note for first commit
 276EXPECT_END
 277
 278test_expect_success 'add concatentation notes with M command' '
 279
 280        git fast-import <input &&
 281        GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
 282        test_cmp expect actual
 283
 284'
 285
 286test_tick
 287cat >input <<INPUT_END
 288commit refs/notes/test
 289committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 290data <<COMMIT
 291fifth notes commit
 292COMMIT
 293
 294from refs/notes/test^0
 295deleteall
 296
 297INPUT_END
 298
 299cat >expect <<EXPECT_END
 300    fourth commit
 301    third commit
 302    second commit
 303    first commit
 304EXPECT_END
 305
 306test_expect_success 'verify that deleteall also removes notes' '
 307
 308        git fast-import <input &&
 309        GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
 310        test_cmp expect actual
 311
 312'
 313
 314test_tick
 315cat >input <<INPUT_END
 316commit refs/notes/test
 317committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 318data <<COMMIT
 319sixth notes commit
 320COMMIT
 321
 322from refs/notes/test^0
 323M 644 inline $commit1
 324data <<EOF
 325third note for first commit
 326EOF
 327
 328M 644 inline $commit3
 329data <<EOF
 330third note for third commit
 331EOF
 332
 333N inline $commit1
 334data <<EOF
 335fourth note for first commit
 336EOF
 337
 338N inline $commit3
 339data <<EOF
 340fourth note for third commit
 341EOF
 342
 343INPUT_END
 344
 345cat >expect <<EXPECT_END
 346    fourth commit
 347    third commit
 348    fourth note for third commit
 349    second commit
 350    first commit
 351    fourth note for first commit
 352EXPECT_END
 353
 354test_expect_success 'verify that later N commands override earlier M commands' '
 355
 356        git fast-import <input &&
 357        GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
 358        test_cmp expect actual
 359
 360'
 361
 362# Write fast-import commands to create the given number of commits
 363fast_import_commits () {
 364        my_ref=$1
 365        my_num_commits=$2
 366        my_append_to_file=$3
 367        my_i=0
 368        while test $my_i -lt $my_num_commits
 369        do
 370                my_i=$(($my_i + 1))
 371                test_tick
 372                cat >>"$my_append_to_file" <<INPUT_END
 373commit $my_ref
 374mark :$my_i
 375committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 376data <<COMMIT
 377commit #$my_i
 378COMMIT
 379
 380M 644 inline file
 381data <<EOF
 382file contents in commit #$my_i
 383EOF
 384
 385INPUT_END
 386        done
 387}
 388
 389# Write fast-import commands to create the given number of notes annotating
 390# the commits created by fast_import_commits()
 391fast_import_notes () {
 392        my_notes_ref=$1
 393        my_num_commits=$2
 394        my_append_to_file=$3
 395        my_note_append=$4
 396        test_tick
 397        cat >>"$my_append_to_file" <<INPUT_END
 398commit $my_notes_ref
 399committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 400data <<COMMIT
 401committing $my_num_commits notes
 402COMMIT
 403
 404INPUT_END
 405
 406        my_i=0
 407        while test $my_i -lt $my_num_commits
 408        do
 409                my_i=$(($my_i + 1))
 410                cat >>"$my_append_to_file" <<INPUT_END
 411N inline :$my_i
 412data <<EOF
 413note for commit #$my_i$my_note_append
 414EOF
 415
 416INPUT_END
 417        done
 418}
 419
 420
 421rm input expect
 422num_commits=400
 423# Create lots of commits
 424fast_import_commits "refs/heads/many_commits" $num_commits input
 425# Create one note per above commit
 426fast_import_notes "refs/notes/many_notes" $num_commits input
 427# Add a couple of non-notes as well
 428test_tick
 429cat >>input <<INPUT_END
 430commit refs/notes/many_notes
 431committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 432data <<COMMIT
 433committing some non-notes to the notes tree
 434COMMIT
 435
 436M 755 inline foobar/non-note.txt
 437data <<EOF
 438This is not a note, but rather a regular file residing in a notes tree
 439EOF
 440
 441M 644 inline deadbeef
 442data <<EOF
 443Non-note file
 444EOF
 445
 446M 644 inline de/adbeef
 447data <<EOF
 448Another non-note file
 449EOF
 450
 451INPUT_END
 452# Finally create the expected output from all these notes and commits
 453i=$num_commits
 454while test $i -gt 0
 455do
 456        cat >>expect <<EXPECT_END
 457    commit #$i
 458    note for commit #$i
 459EXPECT_END
 460        i=$(($i - 1))
 461done
 462
 463test_expect_success 'add lots of commits and notes' '
 464
 465        git fast-import <input &&
 466        GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
 467            grep "^    " > actual &&
 468        test_cmp expect actual
 469
 470'
 471
 472test_expect_success 'verify that lots of notes trigger a fanout scheme' '
 473
 474        # None of the entries in the top-level notes tree should be a full SHA1
 475        git ls-tree --name-only refs/notes/many_notes |
 476        while read path
 477        do
 478                if test $(expr length "$path") -ge 40
 479                then
 480                        return 1
 481                fi
 482        done
 483
 484'
 485
 486# Create another notes tree from the one above
 487SP=" "
 488cat >>input <<INPUT_END
 489commit refs/heads/other_commits
 490committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 491data <<COMMIT
 492commit #$(($num_commit + 1))
 493COMMIT
 494
 495from refs/heads/many_commits
 496M 644 inline file
 497data <<EOF
 498file contents in commit #$(($num_commit + 1))
 499EOF
 500
 501commit refs/notes/other_notes
 502committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 503data <<COMMIT
 504committing one more note on a tree imported from a previous notes tree
 505COMMIT
 506
 507M 040000 $(git log --no-walk --format=%T refs/notes/many_notes)$SP
 508N inline :$(($num_commit + 1))
 509data <<EOF
 510note for commit #$(($num_commit + 1))
 511EOF
 512INPUT_END
 513
 514test_expect_success 'verify that importing a notes tree respects the fanout scheme' '
 515        git fast-import <input &&
 516
 517        # None of the entries in the top-level notes tree should be a full SHA1
 518        git ls-tree --name-only refs/notes/other_notes |
 519        while read path
 520        do
 521                if test $(expr length "$path") -ge 40
 522                then
 523                        return 1
 524                fi
 525        done
 526'
 527
 528cat >>expect_non-note1 << EOF
 529This is not a note, but rather a regular file residing in a notes tree
 530EOF
 531
 532cat >>expect_non-note2 << EOF
 533Non-note file
 534EOF
 535
 536cat >>expect_non-note3 << EOF
 537Another non-note file
 538EOF
 539
 540test_expect_success 'verify that non-notes are untouched by a fanout change' '
 541
 542        git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
 543        test_cmp expect_non-note1 actual &&
 544        git cat-file -p refs/notes/many_notes:deadbeef > actual &&
 545        test_cmp expect_non-note2 actual &&
 546        git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
 547        test_cmp expect_non-note3 actual
 548
 549'
 550
 551# Change the notes for the three top commits
 552test_tick
 553cat >input <<INPUT_END
 554commit refs/notes/many_notes
 555committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 556data <<COMMIT
 557changing notes for the top three commits
 558COMMIT
 559from refs/notes/many_notes^0
 560INPUT_END
 561
 562rm expect
 563i=$num_commits
 564j=0
 565while test $j -lt 3
 566do
 567        cat >>input <<INPUT_END
 568N inline refs/heads/many_commits~$j
 569data <<EOF
 570changed note for commit #$i
 571EOF
 572INPUT_END
 573        cat >>expect <<EXPECT_END
 574    commit #$i
 575    changed note for commit #$i
 576EXPECT_END
 577        i=$(($i - 1))
 578        j=$(($j + 1))
 579done
 580
 581test_expect_success 'change a few existing notes' '
 582
 583        git fast-import <input &&
 584        GIT_NOTES_REF=refs/notes/many_notes git log -n3 refs/heads/many_commits |
 585            grep "^    " > actual &&
 586        test_cmp expect actual
 587
 588'
 589
 590test_expect_success 'verify that changing notes respect existing fanout' '
 591
 592        # None of the entries in the top-level notes tree should be a full SHA1
 593        git ls-tree --name-only refs/notes/many_notes |
 594        while read path
 595        do
 596                if test $(expr length "$path") -ge 40
 597                then
 598                        return 1
 599                fi
 600        done
 601
 602'
 603
 604remaining_notes=10
 605test_tick
 606cat >input <<INPUT_END
 607commit refs/notes/many_notes
 608committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 609data <<COMMIT
 610removing all notes but $remaining_notes
 611COMMIT
 612from refs/notes/many_notes^0
 613INPUT_END
 614
 615i=$(($num_commits - $remaining_notes))
 616for sha1 in $(git rev-list -n $i refs/heads/many_commits)
 617do
 618        cat >>input <<INPUT_END
 619N 0000000000000000000000000000000000000000 $sha1
 620INPUT_END
 621done
 622
 623i=$num_commits
 624rm expect
 625while test $i -gt 0
 626do
 627        cat >>expect <<EXPECT_END
 628    commit #$i
 629EXPECT_END
 630        if test $i -le $remaining_notes
 631        then
 632                cat >>expect <<EXPECT_END
 633    note for commit #$i
 634EXPECT_END
 635        fi
 636        i=$(($i - 1))
 637done
 638
 639test_expect_success 'remove lots of notes' '
 640
 641        git fast-import <input &&
 642        GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
 643            grep "^    " > actual &&
 644        test_cmp expect actual
 645
 646'
 647
 648test_expect_success 'verify that removing notes trigger fanout consolidation' '
 649
 650        # All entries in the top-level notes tree should be a full SHA1
 651        git ls-tree --name-only -r refs/notes/many_notes |
 652        while read path
 653        do
 654                # Explicitly ignore the non-note paths
 655                test "$path" = "foobar/non-note.txt" && continue
 656                test "$path" = "deadbeef" && continue
 657                test "$path" = "de/adbeef" && continue
 658
 659                if test $(expr length "$path") -ne 40
 660                then
 661                        return 1
 662                fi
 663        done
 664
 665'
 666
 667test_expect_success 'verify that non-notes are untouched by a fanout change' '
 668
 669        git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
 670        test_cmp expect_non-note1 actual &&
 671        git cat-file -p refs/notes/many_notes:deadbeef > actual &&
 672        test_cmp expect_non-note2 actual &&
 673        git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
 674        test_cmp expect_non-note3 actual
 675
 676'
 677
 678
 679rm input expect
 680num_notes_refs=10
 681num_commits=16
 682some_commits=8
 683# Create commits
 684fast_import_commits "refs/heads/more_commits" $num_commits input
 685# Create one note per above commit per notes ref
 686i=0
 687while test $i -lt $num_notes_refs
 688do
 689        i=$(($i + 1))
 690        fast_import_notes "refs/notes/more_notes_$i" $num_commits input
 691done
 692# Trigger branch reloading in git-fast-import by repeating the note creation
 693i=0
 694while test $i -lt $num_notes_refs
 695do
 696        i=$(($i + 1))
 697        fast_import_notes "refs/notes/more_notes_$i" $some_commits input " (2)"
 698done
 699# Finally create the expected output from the notes in refs/notes/more_notes_1
 700i=$num_commits
 701while test $i -gt 0
 702do
 703        note_data="note for commit #$i"
 704        if test $i -le $some_commits
 705        then
 706                note_data="$note_data (2)"
 707        fi
 708        cat >>expect <<EXPECT_END
 709    commit #$i
 710    $note_data
 711EXPECT_END
 712        i=$(($i - 1))
 713done
 714
 715test_expect_success "add notes to $num_commits commits in each of $num_notes_refs refs" '
 716
 717        git fast-import --active-branches=5 <input &&
 718        GIT_NOTES_REF=refs/notes/more_notes_1 git log refs/heads/more_commits |
 719            grep "^    " > actual &&
 720        test_cmp expect actual
 721
 722'
 723
 724test_done