t / t7064-wtstatus-pv2.shon commit Merge branch 'sg/line-log-tree-diff-optim' (de67293)
   1#!/bin/sh
   2
   3test_description='git status --porcelain=v2
   4
   5This test exercises porcelain V2 output for git status.'
   6
   7
   8. ./test-lib.sh
   9
  10
  11test_expect_success setup '
  12        test_tick &&
  13        git config core.autocrlf false &&
  14        echo x >file_x &&
  15        echo y >file_y &&
  16        echo z >file_z &&
  17        mkdir dir1 &&
  18        echo a >dir1/file_a &&
  19        echo b >dir1/file_b
  20'
  21
  22test_expect_success 'before initial commit, nothing added, only untracked' '
  23        cat >expect <<-EOF &&
  24        # branch.oid (initial)
  25        # branch.head master
  26        ? actual
  27        ? dir1/
  28        ? expect
  29        ? file_x
  30        ? file_y
  31        ? file_z
  32        EOF
  33
  34        git status --porcelain=v2 --branch --untracked-files=normal >actual &&
  35        test_cmp expect actual
  36'
  37
  38test_expect_success 'before initial commit, things added' '
  39        git add file_x file_y file_z dir1 &&
  40        OID_A=$(git hash-object -t blob -- dir1/file_a) &&
  41        OID_B=$(git hash-object -t blob -- dir1/file_b) &&
  42        OID_X=$(git hash-object -t blob -- file_x) &&
  43        OID_Y=$(git hash-object -t blob -- file_y) &&
  44        OID_Z=$(git hash-object -t blob -- file_z) &&
  45
  46        cat >expect <<-EOF &&
  47        # branch.oid (initial)
  48        # branch.head master
  49        1 A. N... 000000 100644 100644 $ZERO_OID $OID_A dir1/file_a
  50        1 A. N... 000000 100644 100644 $ZERO_OID $OID_B dir1/file_b
  51        1 A. N... 000000 100644 100644 $ZERO_OID $OID_X file_x
  52        1 A. N... 000000 100644 100644 $ZERO_OID $OID_Y file_y
  53        1 A. N... 000000 100644 100644 $ZERO_OID $OID_Z file_z
  54        ? actual
  55        ? expect
  56        EOF
  57
  58        git status --porcelain=v2 --branch --untracked-files=all >actual &&
  59        test_cmp expect actual
  60'
  61
  62test_expect_success 'before initial commit, things added (-z)' '
  63        lf_to_nul >expect <<-EOF &&
  64        # branch.oid (initial)
  65        # branch.head master
  66        1 A. N... 000000 100644 100644 $ZERO_OID $OID_A dir1/file_a
  67        1 A. N... 000000 100644 100644 $ZERO_OID $OID_B dir1/file_b
  68        1 A. N... 000000 100644 100644 $ZERO_OID $OID_X file_x
  69        1 A. N... 000000 100644 100644 $ZERO_OID $OID_Y file_y
  70        1 A. N... 000000 100644 100644 $ZERO_OID $OID_Z file_z
  71        ? actual
  72        ? expect
  73        EOF
  74
  75        git status -z --porcelain=v2 --branch --untracked-files=all >actual &&
  76        test_cmp expect actual
  77'
  78
  79test_expect_success 'make first commit, comfirm HEAD oid and branch' '
  80        git commit -m initial &&
  81        H0=$(git rev-parse HEAD) &&
  82        cat >expect <<-EOF &&
  83        # branch.oid $H0
  84        # branch.head master
  85        ? actual
  86        ? expect
  87        EOF
  88
  89        git status --porcelain=v2 --branch --untracked-files=all >actual &&
  90        test_cmp expect actual
  91'
  92
  93test_expect_success 'after first commit, create unstaged changes' '
  94        echo x >>file_x &&
  95        OID_X1=$(git hash-object -t blob -- file_x) &&
  96        rm file_z &&
  97        H0=$(git rev-parse HEAD) &&
  98
  99        cat >expect <<-EOF &&
 100        # branch.oid $H0
 101        # branch.head master
 102        1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
 103        1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z
 104        ? actual
 105        ? expect
 106        EOF
 107
 108        git status --porcelain=v2 --branch --untracked-files=all >actual &&
 109        test_cmp expect actual
 110'
 111
 112test_expect_success 'after first commit but omit untracked files and branch' '
 113        cat >expect <<-EOF &&
 114        1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
 115        1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z
 116        EOF
 117
 118        git status --porcelain=v2 --untracked-files=no >actual &&
 119        test_cmp expect actual
 120'
 121
 122test_expect_success 'after first commit, stage existing changes' '
 123        git add file_x &&
 124        git rm file_z &&
 125        H0=$(git rev-parse HEAD) &&
 126
 127        cat >expect <<-EOF &&
 128        # branch.oid $H0
 129        # branch.head master
 130        1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
 131        1 D. N... 100644 000000 000000 $OID_Z $ZERO_OID file_z
 132        ? actual
 133        ? expect
 134        EOF
 135
 136        git status --porcelain=v2 --branch --untracked-files=all >actual &&
 137        test_cmp expect actual
 138'
 139
 140test_expect_success 'rename causes 2 path lines' '
 141        git mv file_y renamed_y &&
 142        H0=$(git rev-parse HEAD) &&
 143
 144        q_to_tab >expect <<-EOF &&
 145        # branch.oid $H0
 146        # branch.head master
 147        1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
 148        1 D. N... 100644 000000 000000 $OID_Z $ZERO_OID file_z
 149        2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y
 150        ? actual
 151        ? expect
 152        EOF
 153
 154        git status --porcelain=v2 --branch --untracked-files=all >actual &&
 155        test_cmp expect actual
 156'
 157
 158test_expect_success 'rename causes 2 path lines (-z)' '
 159        H0=$(git rev-parse HEAD) &&
 160
 161        ## Lines use NUL path separator and line terminator, so double transform here.
 162        q_to_nul <<-EOF | lf_to_nul >expect &&
 163        # branch.oid $H0
 164        # branch.head master
 165        1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
 166        1 D. N... 100644 000000 000000 $OID_Z $ZERO_OID file_z
 167        2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y
 168        ? actual
 169        ? expect
 170        EOF
 171
 172        git status --porcelain=v2 --branch --untracked-files=all -z >actual &&
 173        test_cmp expect actual
 174'
 175
 176test_expect_success 'make second commit, confirm clean and new HEAD oid' '
 177        git commit -m second &&
 178        H1=$(git rev-parse HEAD) &&
 179
 180        cat >expect <<-EOF &&
 181        # branch.oid $H1
 182        # branch.head master
 183        ? actual
 184        ? expect
 185        EOF
 186
 187        git status --porcelain=v2 --branch --untracked-files=all >actual &&
 188        test_cmp expect actual
 189'
 190
 191test_expect_success 'confirm ignored files are not printed' '
 192        test_when_finished "rm -f x.ign .gitignore" &&
 193        echo x.ign >.gitignore &&
 194        echo "ignore me" >x.ign &&
 195
 196        cat >expect <<-EOF &&
 197        ? .gitignore
 198        ? actual
 199        ? expect
 200        EOF
 201
 202        git status --porcelain=v2 --untracked-files=all >actual &&
 203        test_cmp expect actual
 204'
 205
 206test_expect_success 'ignored files are printed with --ignored' '
 207        test_when_finished "rm -f x.ign .gitignore" &&
 208        echo x.ign >.gitignore &&
 209        echo "ignore me" >x.ign &&
 210
 211        cat >expect <<-EOF &&
 212        ? .gitignore
 213        ? actual
 214        ? expect
 215        ! x.ign
 216        EOF
 217
 218        git status --porcelain=v2 --ignored --untracked-files=all >actual &&
 219        test_cmp expect actual
 220'
 221
 222test_expect_success 'create and commit permanent ignore file' '
 223        cat >.gitignore <<-EOF &&
 224        actual*
 225        expect*
 226        EOF
 227
 228        git add .gitignore &&
 229        git commit -m ignore_trash &&
 230        H1=$(git rev-parse HEAD) &&
 231
 232        cat >expect <<-EOF &&
 233        # branch.oid $H1
 234        # branch.head master
 235        EOF
 236
 237        git status --porcelain=v2 --branch >actual &&
 238        test_cmp expect actual
 239'
 240
 241test_expect_success 'verify --intent-to-add output' '
 242        test_when_finished "git rm -f intent1.add intent2.add" &&
 243        touch intent1.add &&
 244        echo test >intent2.add &&
 245
 246        git add --intent-to-add intent1.add intent2.add &&
 247
 248        cat >expect <<-EOF &&
 249        1 .A N... 000000 000000 100644 $ZERO_OID $ZERO_OID intent1.add
 250        1 .A N... 000000 000000 100644 $ZERO_OID $ZERO_OID intent2.add
 251        EOF
 252
 253        git status --porcelain=v2 >actual &&
 254        test_cmp expect actual
 255'
 256
 257test_expect_success 'verify AA (add-add) conflict' '
 258        test_when_finished "git reset --hard" &&
 259
 260        git branch AA_A master &&
 261        git checkout AA_A &&
 262        echo "Branch AA_A" >conflict.txt &&
 263        OID_AA_A=$(git hash-object -t blob -- conflict.txt) &&
 264        git add conflict.txt &&
 265        git commit -m "branch aa_a" &&
 266
 267        git branch AA_B master &&
 268        git checkout AA_B &&
 269        echo "Branch AA_B" >conflict.txt &&
 270        OID_AA_B=$(git hash-object -t blob -- conflict.txt) &&
 271        git add conflict.txt &&
 272        git commit -m "branch aa_b" &&
 273
 274        git branch AA_M AA_B &&
 275        git checkout AA_M &&
 276        test_must_fail git merge AA_A &&
 277
 278        HM=$(git rev-parse HEAD) &&
 279
 280        cat >expect <<-EOF &&
 281        # branch.oid $HM
 282        # branch.head AA_M
 283        u AA N... 000000 100644 100644 100644 $ZERO_OID $OID_AA_B $OID_AA_A conflict.txt
 284        EOF
 285
 286        git status --porcelain=v2 --branch --untracked-files=all >actual &&
 287        test_cmp expect actual
 288'
 289
 290test_expect_success 'verify UU (edit-edit) conflict' '
 291        test_when_finished "git reset --hard" &&
 292
 293        git branch UU_ANC master &&
 294        git checkout UU_ANC &&
 295        echo "Ancestor" >conflict.txt &&
 296        OID_UU_ANC=$(git hash-object -t blob -- conflict.txt) &&
 297        git add conflict.txt &&
 298        git commit -m "UU_ANC" &&
 299
 300        git branch UU_A UU_ANC &&
 301        git checkout UU_A &&
 302        echo "Branch UU_A" >conflict.txt &&
 303        OID_UU_A=$(git hash-object -t blob -- conflict.txt) &&
 304        git add conflict.txt &&
 305        git commit -m "branch uu_a" &&
 306
 307        git branch UU_B UU_ANC &&
 308        git checkout UU_B &&
 309        echo "Branch UU_B" >conflict.txt &&
 310        OID_UU_B=$(git hash-object -t blob -- conflict.txt) &&
 311        git add conflict.txt &&
 312        git commit -m "branch uu_b" &&
 313
 314        git branch UU_M UU_B &&
 315        git checkout UU_M &&
 316        test_must_fail git merge UU_A &&
 317
 318        HM=$(git rev-parse HEAD) &&
 319
 320        cat >expect <<-EOF &&
 321        # branch.oid $HM
 322        # branch.head UU_M
 323        u UU N... 100644 100644 100644 100644 $OID_UU_ANC $OID_UU_B $OID_UU_A conflict.txt
 324        EOF
 325
 326        git status --porcelain=v2 --branch --untracked-files=all >actual &&
 327        test_cmp expect actual
 328'
 329
 330test_expect_success 'verify upstream fields in branch header' '
 331        git checkout master &&
 332        test_when_finished "rm -rf sub_repo" &&
 333        git clone . sub_repo &&
 334        (
 335                ## Confirm local master tracks remote master.
 336                cd sub_repo &&
 337                HUF=$(git rev-parse HEAD) &&
 338
 339                cat >expect <<-EOF &&
 340                # branch.oid $HUF
 341                # branch.head master
 342                # branch.upstream origin/master
 343                # branch.ab +0 -0
 344                EOF
 345
 346                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 347                test_cmp expect actual &&
 348
 349                ## Test ahead/behind.
 350                echo xyz >file_xyz &&
 351                git add file_xyz &&
 352                git commit -m xyz &&
 353
 354                HUF=$(git rev-parse HEAD) &&
 355
 356                cat >expect <<-EOF &&
 357                # branch.oid $HUF
 358                # branch.head master
 359                # branch.upstream origin/master
 360                # branch.ab +1 -0
 361                EOF
 362
 363                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 364                test_cmp expect actual &&
 365
 366                ## Repeat the above but without --branch.
 367                git status --porcelain=v2 --untracked-files=all >actual &&
 368                test_must_be_empty actual &&
 369
 370                ## Test upstream-gone case. Fake this by pointing origin/master at
 371                ## a non-existing commit.
 372                OLD=$(git rev-parse origin/master) &&
 373                NEW=$ZERO_OID &&
 374                mv .git/packed-refs .git/old-packed-refs &&
 375                sed "s/$OLD/$NEW/g" <.git/old-packed-refs >.git/packed-refs &&
 376
 377                HUF=$(git rev-parse HEAD) &&
 378
 379                cat >expect <<-EOF &&
 380                # branch.oid $HUF
 381                # branch.head master
 382                # branch.upstream origin/master
 383                EOF
 384
 385                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 386                test_cmp expect actual
 387        )
 388'
 389
 390test_expect_success 'verify --[no-]ahead-behind with V2 format' '
 391        git checkout master &&
 392        test_when_finished "rm -rf sub_repo" &&
 393        git clone . sub_repo &&
 394        (
 395                ## Confirm local master tracks remote master.
 396                cd sub_repo &&
 397                HUF=$(git rev-parse HEAD) &&
 398
 399                # Confirm --no-ahead-behind reports traditional branch.ab with 0/0 for equal branches.
 400                cat >expect <<-EOF &&
 401                # branch.oid $HUF
 402                # branch.head master
 403                # branch.upstream origin/master
 404                # branch.ab +0 -0
 405                EOF
 406
 407                git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
 408                test_cmp expect actual &&
 409
 410                # Confirm --ahead-behind reports traditional branch.ab with 0/0.
 411                cat >expect <<-EOF &&
 412                # branch.oid $HUF
 413                # branch.head master
 414                # branch.upstream origin/master
 415                # branch.ab +0 -0
 416                EOF
 417
 418                git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
 419                test_cmp expect actual &&
 420
 421                ## Test non-equal ahead/behind.
 422                echo xyz >file_xyz &&
 423                git add file_xyz &&
 424                git commit -m xyz &&
 425
 426                HUF=$(git rev-parse HEAD) &&
 427
 428                # Confirm --no-ahead-behind reports branch.ab with ?/? for non-equal branches.
 429                cat >expect <<-EOF &&
 430                # branch.oid $HUF
 431                # branch.head master
 432                # branch.upstream origin/master
 433                # branch.ab +? -?
 434                EOF
 435
 436                git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
 437                test_cmp expect actual &&
 438
 439                # Confirm --ahead-behind reports traditional branch.ab with 1/0.
 440                cat >expect <<-EOF &&
 441                # branch.oid $HUF
 442                # branch.head master
 443                # branch.upstream origin/master
 444                # branch.ab +1 -0
 445                EOF
 446
 447                git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
 448                test_cmp expect actual &&
 449
 450                # Confirm that "status.aheadbehind" DOES NOT work on V2 format.
 451                git -c status.aheadbehind=false status --porcelain=v2 --branch --untracked-files=all >actual &&
 452                test_cmp expect actual &&
 453
 454                # Confirm that "status.aheadbehind" DOES NOT work on V2 format.
 455                git -c status.aheadbehind=true status --porcelain=v2 --branch --untracked-files=all >actual &&
 456                test_cmp expect actual
 457        )
 458'
 459
 460test_expect_success 'create and add submodule, submodule appears clean (A. S...)' '
 461        git checkout master &&
 462        git clone . sub_repo &&
 463        git clone . super_repo &&
 464        (       cd super_repo &&
 465                git submodule add ../sub_repo sub1 &&
 466
 467                ## Confirm stage/add of clean submodule.
 468                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 469                HSUP=$(git rev-parse HEAD) &&
 470                HSUB=$HSUP &&
 471
 472                cat >expect <<-EOF &&
 473                # branch.oid $HSUP
 474                # branch.head master
 475                # branch.upstream origin/master
 476                # branch.ab +0 -0
 477                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 478                1 A. S... 000000 160000 160000 $ZERO_OID $HSUB sub1
 479                EOF
 480
 481                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 482                test_cmp expect actual
 483        )
 484'
 485
 486test_expect_success 'untracked changes in added submodule (AM S..U)' '
 487        (       cd super_repo &&
 488                ## create untracked file in the submodule.
 489                (       cd sub1 &&
 490                        echo "xxxx" >file_in_sub
 491                ) &&
 492
 493                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 494                HSUP=$(git rev-parse HEAD) &&
 495                HSUB=$HSUP &&
 496
 497                cat >expect <<-EOF &&
 498                # branch.oid $HSUP
 499                # branch.head master
 500                # branch.upstream origin/master
 501                # branch.ab +0 -0
 502                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 503                1 AM S..U 000000 160000 160000 $ZERO_OID $HSUB sub1
 504                EOF
 505
 506                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 507                test_cmp expect actual
 508        )
 509'
 510
 511test_expect_success 'staged changes in added submodule (AM S.M.)' '
 512        (       cd super_repo &&
 513                ## stage the changes in the submodule.
 514                (       cd sub1 &&
 515                        git add file_in_sub
 516                ) &&
 517
 518                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 519                HSUP=$(git rev-parse HEAD) &&
 520                HSUB=$HSUP &&
 521
 522                cat >expect <<-EOF &&
 523                # branch.oid $HSUP
 524                # branch.head master
 525                # branch.upstream origin/master
 526                # branch.ab +0 -0
 527                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 528                1 AM S.M. 000000 160000 160000 $ZERO_OID $HSUB sub1
 529                EOF
 530
 531                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 532                test_cmp expect actual
 533        )
 534'
 535
 536test_expect_success 'staged and unstaged changes in added (AM S.M.)' '
 537        (       cd super_repo &&
 538                (       cd sub1 &&
 539                        ## make additional unstaged changes (on the same file) in the submodule.
 540                        ## This does not cause us to get S.MU (because the submodule does not report
 541                        ## a "?" line for the unstaged changes).
 542                        echo "more changes" >>file_in_sub
 543                ) &&
 544
 545                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 546                HSUP=$(git rev-parse HEAD) &&
 547                HSUB=$HSUP &&
 548
 549                cat >expect <<-EOF &&
 550                # branch.oid $HSUP
 551                # branch.head master
 552                # branch.upstream origin/master
 553                # branch.ab +0 -0
 554                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 555                1 AM S.M. 000000 160000 160000 $ZERO_OID $HSUB sub1
 556                EOF
 557
 558                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 559                test_cmp expect actual
 560        )
 561'
 562
 563test_expect_success 'staged and untracked changes in added submodule (AM S.MU)' '
 564        (       cd super_repo &&
 565                (       cd sub1 &&
 566                        ## stage new changes in tracked file.
 567                        git add file_in_sub &&
 568                        ## create new untracked file.
 569                        echo "yyyy" >>another_file_in_sub
 570                ) &&
 571
 572                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 573                HSUP=$(git rev-parse HEAD) &&
 574                HSUB=$HSUP &&
 575
 576                cat >expect <<-EOF &&
 577                # branch.oid $HSUP
 578                # branch.head master
 579                # branch.upstream origin/master
 580                # branch.ab +0 -0
 581                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 582                1 AM S.MU 000000 160000 160000 $ZERO_OID $HSUB sub1
 583                EOF
 584
 585                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 586                test_cmp expect actual
 587        )
 588'
 589
 590test_expect_success 'commit within the submodule appears as new commit in super (AM SC..)' '
 591        (       cd super_repo &&
 592                (       cd sub1 &&
 593                        ## Make a new commit in the submodule.
 594                        git add file_in_sub &&
 595                        rm -f another_file_in_sub &&
 596                        git commit -m "new commit"
 597                ) &&
 598
 599                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 600                HSUP=$(git rev-parse HEAD) &&
 601                HSUB=$HSUP &&
 602
 603                cat >expect <<-EOF &&
 604                # branch.oid $HSUP
 605                # branch.head master
 606                # branch.upstream origin/master
 607                # branch.ab +0 -0
 608                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 609                1 AM SC.. 000000 160000 160000 $ZERO_OID $HSUB sub1
 610                EOF
 611
 612                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 613                test_cmp expect actual
 614        )
 615'
 616
 617test_expect_success 'stage submodule in super and commit' '
 618        (       cd super_repo &&
 619                ## Stage the new submodule commit in the super.
 620                git add sub1 &&
 621                ## Commit the super so that the sub no longer appears as added.
 622                git commit -m "super commit" &&
 623
 624                HSUP=$(git rev-parse HEAD) &&
 625
 626                cat >expect <<-EOF &&
 627                # branch.oid $HSUP
 628                # branch.head master
 629                # branch.upstream origin/master
 630                # branch.ab +1 -0
 631                EOF
 632
 633                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 634                test_cmp expect actual
 635        )
 636'
 637
 638test_expect_success 'make unstaged changes in existing submodule (.M S.M.)' '
 639        (       cd super_repo &&
 640                (       cd sub1 &&
 641                        echo "zzzz" >>file_in_sub
 642                ) &&
 643
 644                HSUP=$(git rev-parse HEAD) &&
 645                HSUB=$(cd sub1 && git rev-parse HEAD) &&
 646
 647                cat >expect <<-EOF &&
 648                # branch.oid $HSUP
 649                # branch.head master
 650                # branch.upstream origin/master
 651                # branch.ab +1 -0
 652                1 .M S.M. 160000 160000 160000 $HSUB $HSUB sub1
 653                EOF
 654
 655                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 656                test_cmp expect actual
 657        )
 658'
 659
 660test_done