t / t7064-wtstatus-pv2.shon commit Merge branch 'nd/pack-objects-pack-struct' (ad635e8)
   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 $_z40 $OID_A dir1/file_a
  50        1 A. N... 000000 100644 100644 $_z40 $OID_B dir1/file_b
  51        1 A. N... 000000 100644 100644 $_z40 $OID_X file_x
  52        1 A. N... 000000 100644 100644 $_z40 $OID_Y file_y
  53        1 A. N... 000000 100644 100644 $_z40 $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 $_z40 $OID_A dir1/file_a
  67        1 A. N... 000000 100644 100644 $_z40 $OID_B dir1/file_b
  68        1 A. N... 000000 100644 100644 $_z40 $OID_X file_x
  69        1 A. N... 000000 100644 100644 $_z40 $OID_Y file_y
  70        1 A. N... 000000 100644 100644 $_z40 $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 $_z40 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 $_z40 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 $_z40 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 $_z40 $_z40 intent1.add
 250        1 .A N... 000000 000000 100644 $_z40 $_z40 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 $_z40 $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                cat >expect <<-EOF &&
 368                EOF
 369
 370                git status --porcelain=v2 --untracked-files=all >actual &&
 371                test_cmp expect actual &&
 372
 373                ## Test upstream-gone case. Fake this by pointing origin/master at
 374                ## a non-existing commit.
 375                OLD=$(git rev-parse origin/master) &&
 376                NEW=$_z40 &&
 377                mv .git/packed-refs .git/old-packed-refs &&
 378                sed "s/$OLD/$NEW/g" <.git/old-packed-refs >.git/packed-refs &&
 379
 380                HUF=$(git rev-parse HEAD) &&
 381
 382                cat >expect <<-EOF &&
 383                # branch.oid $HUF
 384                # branch.head master
 385                # branch.upstream origin/master
 386                EOF
 387
 388                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 389                test_cmp expect actual
 390        )
 391'
 392
 393test_expect_success 'verify --[no-]ahead-behind with V2 format' '
 394        git checkout master &&
 395        test_when_finished "rm -rf sub_repo" &&
 396        git clone . sub_repo &&
 397        (
 398                ## Confirm local master tracks remote master.
 399                cd sub_repo &&
 400                HUF=$(git rev-parse HEAD) &&
 401
 402                # Confirm --no-ahead-behind reports traditional branch.ab with 0/0 for equal branches.
 403                cat >expect <<-EOF &&
 404                # branch.oid $HUF
 405                # branch.head master
 406                # branch.upstream origin/master
 407                # branch.ab +0 -0
 408                EOF
 409
 410                git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
 411                test_cmp expect actual &&
 412
 413                # Confirm --ahead-behind reports traditional branch.ab with 0/0.
 414                cat >expect <<-EOF &&
 415                # branch.oid $HUF
 416                # branch.head master
 417                # branch.upstream origin/master
 418                # branch.ab +0 -0
 419                EOF
 420
 421                git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
 422                test_cmp expect actual &&
 423
 424                ## Test non-equal ahead/behind.
 425                echo xyz >file_xyz &&
 426                git add file_xyz &&
 427                git commit -m xyz &&
 428
 429                HUF=$(git rev-parse HEAD) &&
 430
 431                # Confirm --no-ahead-behind reports branch.ab with ?/? for non-equal branches.
 432                cat >expect <<-EOF &&
 433                # branch.oid $HUF
 434                # branch.head master
 435                # branch.upstream origin/master
 436                # branch.ab +? -?
 437                EOF
 438
 439                git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
 440                test_cmp expect actual &&
 441
 442                # Confirm --ahead-behind reports traditional branch.ab with 1/0.
 443                cat >expect <<-EOF &&
 444                # branch.oid $HUF
 445                # branch.head master
 446                # branch.upstream origin/master
 447                # branch.ab +1 -0
 448                EOF
 449
 450                git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
 451                test_cmp expect actual
 452        )
 453'
 454
 455test_expect_success 'create and add submodule, submodule appears clean (A. S...)' '
 456        git checkout master &&
 457        git clone . sub_repo &&
 458        git clone . super_repo &&
 459        (       cd super_repo &&
 460                git submodule add ../sub_repo sub1 &&
 461
 462                ## Confirm stage/add of clean submodule.
 463                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 464                HSUP=$(git rev-parse HEAD) &&
 465                HSUB=$HSUP &&
 466
 467                cat >expect <<-EOF &&
 468                # branch.oid $HSUP
 469                # branch.head master
 470                # branch.upstream origin/master
 471                # branch.ab +0 -0
 472                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 473                1 A. S... 000000 160000 160000 $_z40 $HSUB sub1
 474                EOF
 475
 476                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 477                test_cmp expect actual
 478        )
 479'
 480
 481test_expect_success 'untracked changes in added submodule (AM S..U)' '
 482        (       cd super_repo &&
 483                ## create untracked file in the submodule.
 484                (       cd sub1 &&
 485                        echo "xxxx" >file_in_sub
 486                ) &&
 487
 488                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 489                HSUP=$(git rev-parse HEAD) &&
 490                HSUB=$HSUP &&
 491
 492                cat >expect <<-EOF &&
 493                # branch.oid $HSUP
 494                # branch.head master
 495                # branch.upstream origin/master
 496                # branch.ab +0 -0
 497                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 498                1 AM S..U 000000 160000 160000 $_z40 $HSUB sub1
 499                EOF
 500
 501                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 502                test_cmp expect actual
 503        )
 504'
 505
 506test_expect_success 'staged changes in added submodule (AM S.M.)' '
 507        (       cd super_repo &&
 508                ## stage the changes in the submodule.
 509                (       cd sub1 &&
 510                        git add file_in_sub
 511                ) &&
 512
 513                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 514                HSUP=$(git rev-parse HEAD) &&
 515                HSUB=$HSUP &&
 516
 517                cat >expect <<-EOF &&
 518                # branch.oid $HSUP
 519                # branch.head master
 520                # branch.upstream origin/master
 521                # branch.ab +0 -0
 522                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 523                1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1
 524                EOF
 525
 526                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 527                test_cmp expect actual
 528        )
 529'
 530
 531test_expect_success 'staged and unstaged changes in added (AM S.M.)' '
 532        (       cd super_repo &&
 533                (       cd sub1 &&
 534                        ## make additional unstaged changes (on the same file) in the submodule.
 535                        ## This does not cause us to get S.MU (because the submodule does not report
 536                        ## a "?" line for the unstaged changes).
 537                        echo "more changes" >>file_in_sub
 538                ) &&
 539
 540                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 541                HSUP=$(git rev-parse HEAD) &&
 542                HSUB=$HSUP &&
 543
 544                cat >expect <<-EOF &&
 545                # branch.oid $HSUP
 546                # branch.head master
 547                # branch.upstream origin/master
 548                # branch.ab +0 -0
 549                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 550                1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1
 551                EOF
 552
 553                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 554                test_cmp expect actual
 555        )
 556'
 557
 558test_expect_success 'staged and untracked changes in added submodule (AM S.MU)' '
 559        (       cd super_repo &&
 560                (       cd sub1 &&
 561                        ## stage new changes in tracked file.
 562                        git add file_in_sub &&
 563                        ## create new untracked file.
 564                        echo "yyyy" >>another_file_in_sub
 565                ) &&
 566
 567                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 568                HSUP=$(git rev-parse HEAD) &&
 569                HSUB=$HSUP &&
 570
 571                cat >expect <<-EOF &&
 572                # branch.oid $HSUP
 573                # branch.head master
 574                # branch.upstream origin/master
 575                # branch.ab +0 -0
 576                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 577                1 AM S.MU 000000 160000 160000 $_z40 $HSUB sub1
 578                EOF
 579
 580                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 581                test_cmp expect actual
 582        )
 583'
 584
 585test_expect_success 'commit within the submodule appears as new commit in super (AM SC..)' '
 586        (       cd super_repo &&
 587                (       cd sub1 &&
 588                        ## Make a new commit in the submodule.
 589                        git add file_in_sub &&
 590                        rm -f another_file_in_sub &&
 591                        git commit -m "new commit"
 592                ) &&
 593
 594                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 595                HSUP=$(git rev-parse HEAD) &&
 596                HSUB=$HSUP &&
 597
 598                cat >expect <<-EOF &&
 599                # branch.oid $HSUP
 600                # branch.head master
 601                # branch.upstream origin/master
 602                # branch.ab +0 -0
 603                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 604                1 AM SC.. 000000 160000 160000 $_z40 $HSUB sub1
 605                EOF
 606
 607                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 608                test_cmp expect actual
 609        )
 610'
 611
 612test_expect_success 'stage submodule in super and commit' '
 613        (       cd super_repo &&
 614                ## Stage the new submodule commit in the super.
 615                git add sub1 &&
 616                ## Commit the super so that the sub no longer appears as added.
 617                git commit -m "super commit" &&
 618
 619                HSUP=$(git rev-parse HEAD) &&
 620
 621                cat >expect <<-EOF &&
 622                # branch.oid $HSUP
 623                # branch.head master
 624                # branch.upstream origin/master
 625                # branch.ab +1 -0
 626                EOF
 627
 628                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 629                test_cmp expect actual
 630        )
 631'
 632
 633test_expect_success 'make unstaged changes in existing submodule (.M S.M.)' '
 634        (       cd super_repo &&
 635                (       cd sub1 &&
 636                        echo "zzzz" >>file_in_sub
 637                ) &&
 638
 639                HSUP=$(git rev-parse HEAD) &&
 640                HSUB=$(cd sub1 && git rev-parse HEAD) &&
 641
 642                cat >expect <<-EOF &&
 643                # branch.oid $HSUP
 644                # branch.head master
 645                # branch.upstream origin/master
 646                # branch.ab +1 -0
 647                1 .M S.M. 160000 160000 160000 $HSUB $HSUB sub1
 648                EOF
 649
 650                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 651                test_cmp expect actual
 652        )
 653'
 654
 655test_done