t / t7064-wtstatus-pv2.shon commit Merge branch 'uk/merge-subtree-doc-update' (5d8b3e5)
   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'
 451
 452test_expect_success 'create and add submodule, submodule appears clean (A. S...)' '
 453        git checkout master &&
 454        git clone . sub_repo &&
 455        git clone . super_repo &&
 456        (       cd super_repo &&
 457                git submodule add ../sub_repo sub1 &&
 458
 459                ## Confirm stage/add of clean submodule.
 460                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 461                HSUP=$(git rev-parse HEAD) &&
 462                HSUB=$HSUP &&
 463
 464                cat >expect <<-EOF &&
 465                # branch.oid $HSUP
 466                # branch.head master
 467                # branch.upstream origin/master
 468                # branch.ab +0 -0
 469                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 470                1 A. S... 000000 160000 160000 $ZERO_OID $HSUB sub1
 471                EOF
 472
 473                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 474                test_cmp expect actual
 475        )
 476'
 477
 478test_expect_success 'untracked changes in added submodule (AM S..U)' '
 479        (       cd super_repo &&
 480                ## create untracked file in the submodule.
 481                (       cd sub1 &&
 482                        echo "xxxx" >file_in_sub
 483                ) &&
 484
 485                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 486                HSUP=$(git rev-parse HEAD) &&
 487                HSUB=$HSUP &&
 488
 489                cat >expect <<-EOF &&
 490                # branch.oid $HSUP
 491                # branch.head master
 492                # branch.upstream origin/master
 493                # branch.ab +0 -0
 494                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 495                1 AM S..U 000000 160000 160000 $ZERO_OID $HSUB sub1
 496                EOF
 497
 498                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 499                test_cmp expect actual
 500        )
 501'
 502
 503test_expect_success 'staged changes in added submodule (AM S.M.)' '
 504        (       cd super_repo &&
 505                ## stage the changes in the submodule.
 506                (       cd sub1 &&
 507                        git add file_in_sub
 508                ) &&
 509
 510                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 511                HSUP=$(git rev-parse HEAD) &&
 512                HSUB=$HSUP &&
 513
 514                cat >expect <<-EOF &&
 515                # branch.oid $HSUP
 516                # branch.head master
 517                # branch.upstream origin/master
 518                # branch.ab +0 -0
 519                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 520                1 AM S.M. 000000 160000 160000 $ZERO_OID $HSUB sub1
 521                EOF
 522
 523                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 524                test_cmp expect actual
 525        )
 526'
 527
 528test_expect_success 'staged and unstaged changes in added (AM S.M.)' '
 529        (       cd super_repo &&
 530                (       cd sub1 &&
 531                        ## make additional unstaged changes (on the same file) in the submodule.
 532                        ## This does not cause us to get S.MU (because the submodule does not report
 533                        ## a "?" line for the unstaged changes).
 534                        echo "more changes" >>file_in_sub
 535                ) &&
 536
 537                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 538                HSUP=$(git rev-parse HEAD) &&
 539                HSUB=$HSUP &&
 540
 541                cat >expect <<-EOF &&
 542                # branch.oid $HSUP
 543                # branch.head master
 544                # branch.upstream origin/master
 545                # branch.ab +0 -0
 546                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 547                1 AM S.M. 000000 160000 160000 $ZERO_OID $HSUB sub1
 548                EOF
 549
 550                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 551                test_cmp expect actual
 552        )
 553'
 554
 555test_expect_success 'staged and untracked changes in added submodule (AM S.MU)' '
 556        (       cd super_repo &&
 557                (       cd sub1 &&
 558                        ## stage new changes in tracked file.
 559                        git add file_in_sub &&
 560                        ## create new untracked file.
 561                        echo "yyyy" >>another_file_in_sub
 562                ) &&
 563
 564                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 565                HSUP=$(git rev-parse HEAD) &&
 566                HSUB=$HSUP &&
 567
 568                cat >expect <<-EOF &&
 569                # branch.oid $HSUP
 570                # branch.head master
 571                # branch.upstream origin/master
 572                # branch.ab +0 -0
 573                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 574                1 AM S.MU 000000 160000 160000 $ZERO_OID $HSUB sub1
 575                EOF
 576
 577                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 578                test_cmp expect actual
 579        )
 580'
 581
 582test_expect_success 'commit within the submodule appears as new commit in super (AM SC..)' '
 583        (       cd super_repo &&
 584                (       cd sub1 &&
 585                        ## Make a new commit in the submodule.
 586                        git add file_in_sub &&
 587                        rm -f another_file_in_sub &&
 588                        git commit -m "new commit"
 589                ) &&
 590
 591                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 592                HSUP=$(git rev-parse HEAD) &&
 593                HSUB=$HSUP &&
 594
 595                cat >expect <<-EOF &&
 596                # branch.oid $HSUP
 597                # branch.head master
 598                # branch.upstream origin/master
 599                # branch.ab +0 -0
 600                1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
 601                1 AM SC.. 000000 160000 160000 $ZERO_OID $HSUB sub1
 602                EOF
 603
 604                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 605                test_cmp expect actual
 606        )
 607'
 608
 609test_expect_success 'stage submodule in super and commit' '
 610        (       cd super_repo &&
 611                ## Stage the new submodule commit in the super.
 612                git add sub1 &&
 613                ## Commit the super so that the sub no longer appears as added.
 614                git commit -m "super commit" &&
 615
 616                HSUP=$(git rev-parse HEAD) &&
 617
 618                cat >expect <<-EOF &&
 619                # branch.oid $HSUP
 620                # branch.head master
 621                # branch.upstream origin/master
 622                # branch.ab +1 -0
 623                EOF
 624
 625                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 626                test_cmp expect actual
 627        )
 628'
 629
 630test_expect_success 'make unstaged changes in existing submodule (.M S.M.)' '
 631        (       cd super_repo &&
 632                (       cd sub1 &&
 633                        echo "zzzz" >>file_in_sub
 634                ) &&
 635
 636                HSUP=$(git rev-parse HEAD) &&
 637                HSUB=$(cd sub1 && git rev-parse HEAD) &&
 638
 639                cat >expect <<-EOF &&
 640                # branch.oid $HSUP
 641                # branch.head master
 642                # branch.upstream origin/master
 643                # branch.ab +1 -0
 644                1 .M S.M. 160000 160000 160000 $HSUB $HSUB sub1
 645                EOF
 646
 647                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 648                test_cmp expect actual
 649        )
 650'
 651
 652test_done