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