Git fork
at reftables-rust 677 lines 16 kB view raw
1# This file isn't used as a test script directly, instead it is 2# sourced from t8001-annotate.sh and t8002-blame.sh. 3 4if test_have_prereq MINGW 5then 6 sanitize_L () { 7 echo "$1" | sed 'sX\(^-L\|,\)\^\?/X&\\;*Xg' 8 } 9else 10 sanitize_L () { 11 echo "$1" 12 } 13fi 14 15check_count () { 16 head= && 17 file='file' && 18 options= && 19 while : 20 do 21 case "$1" in 22 -h) head="$2"; shift; shift ;; 23 -f) file="$2"; shift; shift ;; 24 -L*) options="$options $(sanitize_L "$1")"; shift ;; 25 -*) options="$options $1"; shift ;; 26 *) break ;; 27 esac 28 done && 29 echo "$PROG $options $file $head" >&4 && 30 $PROG $options $file $head >actual && 31 perl -e ' 32 my %expect = (@ARGV); 33 my %count = map { $_ => 0 } keys %expect; 34 while (<STDIN>) { 35 if (/^[0-9a-f]+\t\(([^\t]+)\t/) { 36 my $author = $1; 37 for ($author) { s/^\s*//; s/\s*$//; } 38 $count{$author}++; 39 } 40 } 41 my $bad = 0; 42 while (my ($author, $count) = each %count) { 43 my $ok; 44 my $value = 0; 45 $value = $expect{$author} if defined $expect{$author}; 46 if ($value != $count) { 47 $bad = 1; 48 $ok = "bad"; 49 } 50 else { 51 $ok = "good"; 52 } 53 print STDERR "Author $author (expected $value, attributed $count) $ok\n"; 54 } 55 exit($bad); 56 ' "$@" <actual 57} 58 59get_progress_result () { 60 tr '\015' '\012' | tail -n 1 61} 62 63test_expect_success 'setup A lines' ' 64 echo "1A quick brown fox jumps over the" >file && 65 echo "lazy dog" >>file && 66 git add file && 67 GIT_AUTHOR_NAME="A" GIT_AUTHOR_EMAIL="A@test.git" \ 68 git commit -a -m "Initial." 69' 70 71test_expect_success 'blame 1 author' ' 72 check_count A 2 73' 74 75test_expect_success 'blame working copy' ' 76 test_when_finished "git restore file" && 77 echo "1A quick brown fox jumps over the" >file && 78 echo "another lazy dog" >>file && 79 check_count A 1 "Not Committed Yet" 1 80' 81 82test_expect_success 'blame with --contents' ' 83 check_count --contents=file A 2 84' 85 86test_expect_success 'blame with --contents in a bare repo' ' 87 git clone --bare . bare-contents.git && 88 ( 89 cd bare-contents.git && 90 echo "1A quick brown fox jumps over the" >contents && 91 check_count --contents=contents A 1 92 ) 93' 94 95test_expect_success 'blame with --contents changed' ' 96 echo "1A quick brown fox jumps over the" >contents && 97 echo "another lazy dog" >>contents && 98 check_count --contents=contents A 1 "External file (--contents)" 1 99' 100 101test_expect_success 'blame in a bare repo without starting commit' ' 102 git clone --bare . bare.git && 103 ( 104 cd bare.git && 105 check_count A 2 106 ) 107' 108 109test_expect_success 'blame by tag objects' ' 110 git tag -m "test tag" testTag && 111 git tag -m "test tag #2" testTag2 testTag && 112 check_count -h testTag A 2 && 113 check_count -h testTag2 A 2 114' 115 116test_expect_success 'setup B lines' ' 117 echo "2A quick brown fox jumps over the" >>file && 118 echo "lazy dog" >>file && 119 GIT_AUTHOR_NAME="B" GIT_AUTHOR_EMAIL="B@test.git" \ 120 git commit -a -m "Second." 121' 122 123test_expect_success 'blame 2 authors' ' 124 check_count A 2 B 2 125' 126 127test_expect_success 'blame with --contents and revision' ' 128 check_count -h testTag --contents=file A 2 "External file (--contents)" 2 129' 130 131test_expect_success 'setup B1 lines (branch1)' ' 132 git checkout -b branch1 main && 133 echo "3A slow green fox jumps into the" >>file && 134 echo "well." >>file && 135 GIT_AUTHOR_NAME="B1" GIT_AUTHOR_EMAIL="B1@test.git" \ 136 git commit -a -m "Branch1-1" 137' 138 139test_expect_success 'blame 2 authors + 1 branch1 author' ' 140 check_count A 2 B 2 B1 2 141' 142 143test_expect_success 'setup B2 lines (branch2)' ' 144 git checkout -b branch2 main && 145 sed -e "s/2A quick brown/4A quick brown lazy dog/" <file >file.new && 146 mv file.new file && 147 GIT_AUTHOR_NAME="B2" GIT_AUTHOR_EMAIL="B2@test.git" \ 148 git commit -a -m "Branch2-1" 149' 150 151test_expect_success 'blame 2 authors + 1 branch2 author' ' 152 check_count A 2 B 1 B2 1 153' 154 155test_expect_success 'merge branch1 & branch2' ' 156 git merge branch1 157' 158 159test_expect_success 'blame 2 authors + 2 merged-in authors' ' 160 check_count A 2 B 1 B1 2 B2 1 161' 162 163test_expect_success 'blame --first-parent blames merge for branch1' ' 164 check_count --first-parent A 2 B 1 "A U Thor" 2 B2 1 165' 166 167test_expect_success 'blame ancestor' ' 168 check_count -h main A 2 B 2 169' 170 171test_expect_success 'blame great-ancestor' ' 172 check_count -h main^ A 2 173' 174 175test_expect_success 'setup evil merge' ' 176 echo "evil merge." >>file && 177 git commit -a --amend 178' 179 180test_expect_success 'blame evil merge' ' 181 check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1 182' 183 184test_expect_success 'blame huge graft' ' 185 test_when_finished "git checkout branch2" && 186 test_when_finished "rm -rf .git/info" && 187 graft= && 188 for i in 0 1 2 189 do 190 for j in 0 1 2 3 4 5 6 7 8 9 191 do 192 git checkout --orphan "$i$j" && 193 printf "%s\n" "$i" "$j" >file && 194 test_tick && 195 GIT_AUTHOR_NAME=$i$j GIT_AUTHOR_EMAIL=$i$j@test.git \ 196 git commit -a -m "$i$j" && 197 commit=$(git rev-parse --verify HEAD) && 198 graft="$graft$commit " || return 1 199 done 200 done && 201 mkdir .git/info && 202 printf "%s " $graft >.git/info/grafts && 203 check_count -h 00 01 1 10 1 204' 205 206test_expect_success 'setup incomplete line' ' 207 echo "incomplete" | tr -d "\\012" >>file && 208 GIT_AUTHOR_NAME="C" GIT_AUTHOR_EMAIL="C@test.git" \ 209 git commit -a -m "Incomplete" 210' 211 212test_expect_success 'blame incomplete line' ' 213 check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1 C 1 214' 215 216test_expect_success 'setup edits' ' 217 mv file file.orig && 218 { 219 cat file.orig && 220 echo 221 } | sed -e "s/^3A/99/" -e "/^1A/d" -e "/^incomplete/d" >file && 222 echo "incomplete" | tr -d "\\012" >>file && 223 GIT_AUTHOR_NAME="D" GIT_AUTHOR_EMAIL="D@test.git" \ 224 git commit -a -m "edit" 225' 226 227test_expect_success 'blame edits' ' 228 check_count A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 229' 230 231test_expect_success 'setup obfuscated email' ' 232 echo "No robots allowed" >file.new && 233 cat file >>file.new && 234 mv file.new file && 235 GIT_AUTHOR_NAME="E" GIT_AUTHOR_EMAIL="E at test dot git" \ 236 git commit -a -m "norobots" 237' 238 239test_expect_success 'blame obfuscated email' ' 240 check_count A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1 241' 242 243test_expect_success 'blame -L 1 (all)' ' 244 check_count -L1 A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1 245' 246 247test_expect_success 'blame -L , (all)' ' 248 check_count -L, A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1 249' 250 251test_expect_success 'blame -L X (X to end)' ' 252 check_count -L5 B1 1 C 1 D 1 "A U Thor" 1 253' 254 255test_expect_success 'blame -L X, (X to end)' ' 256 check_count -L5, B1 1 C 1 D 1 "A U Thor" 1 257' 258 259test_expect_success 'blame -L ,Y (up to Y)' ' 260 check_count -L,3 A 1 B2 1 E 1 261' 262 263test_expect_success 'blame -L X,X' ' 264 check_count -L3,3 B2 1 265' 266 267test_expect_success 'blame -L X,Y' ' 268 check_count -L3,6 B 1 B1 1 B2 1 D 1 269' 270 271test_expect_success 'blame -L Y,X (undocumented)' ' 272 check_count -L6,3 B 1 B1 1 B2 1 D 1 273' 274 275test_expect_success 'blame -L -X' ' 276 test_must_fail $PROG -L-1 file 277' 278 279test_expect_success 'blame -L 0' ' 280 test_must_fail $PROG -L0 file 281' 282 283test_expect_success 'blame -L ,0' ' 284 test_must_fail $PROG -L,0 file 285' 286 287test_expect_success 'blame -L ,+0' ' 288 test_must_fail $PROG -L,+0 file 289' 290 291test_expect_success 'blame -L X,+0' ' 292 test_must_fail $PROG -L1,+0 file 293' 294 295test_expect_success 'blame -L X,+1' ' 296 check_count -L3,+1 B2 1 297' 298 299test_expect_success 'blame -L X,+N' ' 300 check_count -L3,+4 B 1 B1 1 B2 1 D 1 301' 302 303test_expect_success 'blame -L ,-0' ' 304 test_must_fail $PROG -L,-0 file 305' 306 307test_expect_success 'blame -L X,-0' ' 308 test_must_fail $PROG -L1,-0 file 309' 310 311test_expect_success 'blame -L X,-1' ' 312 check_count -L3,-1 B2 1 313' 314 315test_expect_success 'blame -L X,-N' ' 316 check_count -L6,-4 B 1 B1 1 B2 1 D 1 317' 318 319test_expect_success 'blame -L /RE/ (RE to end)' ' 320 check_count -L/evil/ C 1 "A U Thor" 1 321' 322 323test_expect_success 'blame -L /RE/,/RE2/' ' 324 check_count -L/robot/,/green/ A 1 B 1 B2 1 D 1 E 1 325' 326 327test_expect_success 'blame -L X,/RE/' ' 328 check_count -L5,/evil/ B1 1 D 1 "A U Thor" 1 329' 330 331test_expect_success 'blame -L /RE/,Y' ' 332 check_count -L/99/,7 B1 1 D 1 "A U Thor" 1 333' 334 335test_expect_success 'blame -L /RE/,+N' ' 336 check_count -L/99/,+3 B1 1 D 1 "A U Thor" 1 337' 338 339test_expect_success 'blame -L /RE/,-N' ' 340 check_count -L/99/,-3 B 1 B2 1 D 1 341' 342 343# 'file' ends with an incomplete line, so 'wc' reports one fewer lines than 344# git-blame sees, hence the last line is actually $(wc...)+1. 345test_expect_success 'blame -L X (X == nlines)' ' 346 n=$(expr $(wc -l <file) + 1) && 347 check_count -L$n C 1 348' 349 350test_expect_success 'blame -L X (X == nlines + 1)' ' 351 n=$(expr $(wc -l <file) + 2) && 352 test_must_fail $PROG -L$n file 353' 354 355test_expect_success 'blame -L X (X > nlines)' ' 356 test_must_fail $PROG -L12345 file 357' 358 359test_expect_success 'blame -L ,Y (Y == nlines)' ' 360 n=$(expr $(wc -l <file) + 1) && 361 check_count -L,$n A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1 362' 363 364test_expect_success 'blame -L ,Y (Y == nlines + 1)' ' 365 n=$(expr $(wc -l <file) + 2) && 366 check_count -L,$n A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1 367' 368 369test_expect_success 'blame -L ,Y (Y > nlines)' ' 370 check_count -L,12345 A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1 371' 372 373test_expect_success 'blame -L multiple (disjoint)' ' 374 check_count -L2,3 -L6,7 A 1 B1 1 B2 1 "A U Thor" 1 375' 376 377test_expect_success 'blame -L multiple (disjoint: unordered)' ' 378 check_count -L6,7 -L2,3 A 1 B1 1 B2 1 "A U Thor" 1 379' 380 381test_expect_success 'blame -L multiple (adjacent)' ' 382 check_count -L2,3 -L4,5 A 1 B 1 B2 1 D 1 383' 384 385test_expect_success 'blame -L multiple (adjacent: unordered)' ' 386 check_count -L4,5 -L2,3 A 1 B 1 B2 1 D 1 387' 388 389test_expect_success 'blame -L multiple (overlapping)' ' 390 check_count -L2,4 -L3,5 A 1 B 1 B2 1 D 1 391' 392 393test_expect_success 'blame -L multiple (overlapping: unordered)' ' 394 check_count -L3,5 -L2,4 A 1 B 1 B2 1 D 1 395' 396 397test_expect_success 'blame -L multiple (superset/subset)' ' 398 check_count -L2,8 -L3,5 A 1 B 1 B1 1 B2 1 C 1 D 1 "A U Thor" 1 399' 400 401test_expect_success 'blame -L multiple (superset/subset: unordered)' ' 402 check_count -L3,5 -L2,8 A 1 B 1 B1 1 B2 1 C 1 D 1 "A U Thor" 1 403' 404 405test_expect_success 'blame -L /RE/ (relative)' ' 406 check_count -L3,3 -L/fox/ B1 1 B2 1 C 1 D 1 "A U Thor" 1 407' 408 409test_expect_success 'blame -L /RE/ (relative: no preceding range)' ' 410 check_count -L/dog/ A 1 B 1 B1 1 B2 1 C 1 D 1 "A U Thor" 1 411' 412 413test_expect_success 'blame -L /RE/ (relative: adjacent)' ' 414 check_count -L1,1 -L/dog/,+1 A 1 E 1 415' 416 417test_expect_success 'blame -L /RE/ (relative: not found)' ' 418 test_must_fail $PROG -L4,4 -L/dog/ file 419' 420 421test_expect_success 'blame -L /RE/ (relative: end-of-file)' ' 422 test_must_fail $PROG -L, -L/$/ file 423' 424 425test_expect_success 'blame -L ^/RE/ (absolute)' ' 426 check_count -L3,3 -L^/dog/,+2 A 1 B2 1 427' 428 429test_expect_success 'blame -L ^/RE/ (absolute: no preceding range)' ' 430 check_count -L^/dog/,+2 A 1 B2 1 431' 432 433test_expect_success 'blame -L ^/RE/ (absolute: not found)' ' 434 test_must_fail $PROG -L4,4 -L^/tambourine/ file 435' 436 437test_expect_success 'blame -L ^/RE/ (absolute: end-of-file)' ' 438 n=$(expr $(wc -l <file) + 1) && 439 check_count -L$n -L^/$/,+2 A 1 C 1 E 1 440' 441 442test_expect_success 'setup -L :regex' ' 443 tr Q "\\t" >hello.c <<-\EOF && 444 int main(int argc, const char *argv[]) 445 { 446 Qputs("hello"); 447 } 448 EOF 449 git add hello.c && 450 GIT_AUTHOR_NAME="F" GIT_AUTHOR_EMAIL="F@test.git" \ 451 git commit -m "hello" && 452 453 mv hello.c hello.orig && 454 sed -e "/}/ {x; s/$/Qputs(\"goodbye\");/; G;}" <hello.orig | 455 tr Q "\\t" >hello.c && 456 GIT_AUTHOR_NAME="G" GIT_AUTHOR_EMAIL="G@test.git" \ 457 git commit -a -m "goodbye" && 458 459 mv hello.c hello.orig && 460 echo "#include <stdio.h>" >hello.c && 461 cat hello.orig >>hello.c && 462 tr Q "\\t" >>hello.c <<-\EOF && 463 void mail() 464 { 465 Qputs("mail"); 466 } 467 EOF 468 GIT_AUTHOR_NAME="H" GIT_AUTHOR_EMAIL="H@test.git" \ 469 git commit -a -m "mail" 470' 471 472test_expect_success 'blame -L :literal' ' 473 check_count -f hello.c -L:main F 4 G 1 474' 475 476test_expect_success 'blame -L :regex' ' 477 check_count -f hello.c "-L:m[a-z][a-z]l" H 4 478' 479 480test_expect_success 'blame -L :nomatch' ' 481 test_must_fail $PROG -L:nomatch hello.c 482' 483 484test_expect_success 'blame -L :RE (relative)' ' 485 check_count -f hello.c -L3,3 -L:ma.. F 1 H 4 486' 487 488test_expect_success 'blame -L :RE (relative: no preceding range)' ' 489 check_count -f hello.c -L:ma.. F 4 G 1 490' 491 492test_expect_success 'blame -L :RE (relative: not found)' ' 493 test_must_fail $PROG -L3,3 -L:tambourine hello.c 494' 495 496test_expect_success 'blame -L :RE (relative: end-of-file)' ' 497 test_must_fail $PROG -L, -L:main hello.c 498' 499 500test_expect_success 'blame -L ^:RE (absolute)' ' 501 check_count -f hello.c -L3,3 -L^:ma.. F 4 G 1 502' 503 504test_expect_success 'blame -L ^:RE (absolute: no preceding range)' ' 505 check_count -f hello.c -L^:ma.. F 4 G 1 506' 507 508test_expect_success 'blame -L ^:RE (absolute: not found)' ' 509 test_must_fail $PROG -L4,4 -L^:tambourine hello.c 510' 511 512test_expect_success 'blame -L ^:RE (absolute: end-of-file)' ' 513 n=$(printf "%d" $(wc -l <hello.c)) && 514 check_count -f hello.c -L$n -L^:ma.. F 4 G 1 H 1 515' 516 517test_expect_success 'blame -L :funcname with userdiff driver' ' 518 cat >file.template <<-\EOF && 519 DO NOT MATCH THIS LINE 520 function RIGHT(a, b) result(c) 521 AS THE DEFAULT DRIVER WOULD 522 523 integer, intent(in) :: ChangeMe 524 EOF 525 526 fortran_file=file.f03 && 527 test_when_finished "rm .gitattributes" && 528 echo "$fortran_file diff=fortran" >.gitattributes && 529 530 test_commit --author "A <A@test.git>" \ 531 "add" "$fortran_file" \ 532 "$(cat file.template)" && 533 test_commit --author "B <B@test.git>" \ 534 "change" "$fortran_file" \ 535 "$(sed -e s/ChangeMe/IWasChanged/ file.template)" && 536 check_count -f "$fortran_file" -L:RIGHT A 3 B 1 537' 538 539test_expect_success 'setup incremental' ' 540 ( 541 GIT_AUTHOR_NAME=I && 542 export GIT_AUTHOR_NAME && 543 GIT_AUTHOR_EMAIL=I@test.git && 544 export GIT_AUTHOR_EMAIL && 545 >incremental && 546 git add incremental && 547 git commit -m "step 0" && 548 printf "partial" >>incremental && 549 git commit -a -m "step 0.5" && 550 echo >>incremental && 551 git commit -a -m "step 1" 552 ) 553' 554 555test_expect_success 'blame empty' ' 556 check_count -h HEAD^^ -f incremental 557' 558 559test_expect_success 'blame -L 0 empty' ' 560 test_must_fail $PROG -L0 incremental HEAD^^ 561' 562 563test_expect_success 'blame -L 1 empty' ' 564 test_must_fail $PROG -L1 incremental HEAD^^ 565' 566 567test_expect_success 'blame -L 2 empty' ' 568 test_must_fail $PROG -L2 incremental HEAD^^ 569' 570 571test_expect_success 'blame half' ' 572 check_count -h HEAD^ -f incremental I 1 573' 574 575test_expect_success 'blame -L 0 half' ' 576 test_must_fail $PROG -L0 incremental HEAD^ 577' 578 579test_expect_success 'blame -L 1 half' ' 580 check_count -h HEAD^ -f incremental -L1 I 1 581' 582 583test_expect_success 'blame -L 2 half' ' 584 test_must_fail $PROG -L2 incremental HEAD^ 585' 586 587test_expect_success 'blame -L 3 half' ' 588 test_must_fail $PROG -L3 incremental HEAD^ 589' 590 591test_expect_success 'blame full' ' 592 check_count -f incremental I 1 593' 594 595test_expect_success 'blame -L 0 full' ' 596 test_must_fail $PROG -L0 incremental 597' 598 599test_expect_success 'blame -L 1 full' ' 600 check_count -f incremental -L1 I 1 601' 602 603test_expect_success 'blame -L 2 full' ' 604 test_must_fail $PROG -L2 incremental 605' 606 607test_expect_success 'blame -L 3 full' ' 608 test_must_fail $PROG -L3 incremental 609' 610 611test_expect_success 'blame -L' ' 612 test_must_fail $PROG -L file 613' 614 615test_expect_success 'blame -L X,+' ' 616 test_must_fail $PROG -L1,+ file 617' 618 619test_expect_success 'blame -L X,-' ' 620 test_must_fail $PROG -L1,- file 621' 622 623test_expect_success 'blame -L X (non-numeric X)' ' 624 test_must_fail $PROG -LX file 625' 626 627test_expect_success 'blame -L X,Y (non-numeric Y)' ' 628 test_must_fail $PROG -L1,Y file 629' 630 631test_expect_success 'blame -L X,+N (non-numeric N)' ' 632 test_must_fail $PROG -L1,+N file 633' 634 635test_expect_success 'blame -L X,-N (non-numeric N)' ' 636 test_must_fail $PROG -L1,-N file 637' 638 639test_expect_success 'blame -L ,^/RE/' ' 640 test_must_fail $PROG -L1,^/99/ file 641' 642 643test_expect_success 'blame progress on a full file' ' 644 cat >expect <<-\EOF && 645 Blaming lines: 100% (10/10), done. 646 EOF 647 648 GIT_PROGRESS_DELAY=0 \ 649 git blame --progress hello.c 2>stderr && 650 651 get_progress_result <stderr >actual && 652 test_cmp expect actual 653' 654 655test_expect_success 'blame progress on a single range' ' 656 cat >expect <<-\EOF && 657 Blaming lines: 100% (4/4), done. 658 EOF 659 660 GIT_PROGRESS_DELAY=0 \ 661 git blame --progress -L 3,6 hello.c 2>stderr && 662 663 get_progress_result <stderr >actual && 664 test_cmp expect actual 665' 666 667test_expect_success 'blame progress on multiple ranges' ' 668 cat >expect <<-\EOF && 669 Blaming lines: 100% (7/7), done. 670 EOF 671 672 GIT_PROGRESS_DELAY=0 \ 673 git blame --progress -L 3,6 -L 8,10 hello.c 2>stderr && 674 675 get_progress_result <stderr >actual && 676 test_cmp expect actual 677'