t / t7064-wtstatus-pv2.shon commit fsck: handle NULL return of lookup_blob() and lookup_tree() (2720f6d)
   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 'create and add submodule, submodule appears clean (A. S...)' '
 394        git checkout master &&
 395        git clone . sub_repo &&
 396        git clone . super_repo &&
 397        (       cd super_repo &&
 398                git submodule add ../sub_repo sub1 &&
 399
 400                ## Confirm stage/add of clean submodule.
 401                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 402                HSUP=$(git rev-parse HEAD) &&
 403                HSUB=$HSUP &&
 404
 405                cat >expect <<-EOF &&
 406                # branch.oid $HSUP
 407                # branch.head master
 408                # branch.upstream origin/master
 409                # branch.ab +0 -0
 410                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 411                1 A. S... 000000 160000 160000 $_z40 $HSUB sub1
 412                EOF
 413
 414                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 415                test_cmp expect actual
 416        )
 417'
 418
 419test_expect_success 'untracked changes in added submodule (AM S..U)' '
 420        (       cd super_repo &&
 421                ## create untracked file in the submodule.
 422                (       cd sub1 &&
 423                        echo "xxxx" >file_in_sub
 424                ) &&
 425
 426                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 427                HSUP=$(git rev-parse HEAD) &&
 428                HSUB=$HSUP &&
 429
 430                cat >expect <<-EOF &&
 431                # branch.oid $HSUP
 432                # branch.head master
 433                # branch.upstream origin/master
 434                # branch.ab +0 -0
 435                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 436                1 AM S..U 000000 160000 160000 $_z40 $HSUB sub1
 437                EOF
 438
 439                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 440                test_cmp expect actual
 441        )
 442'
 443
 444test_expect_success 'staged changes in added submodule (AM S.M.)' '
 445        (       cd super_repo &&
 446                ## stage the changes in the submodule.
 447                (       cd sub1 &&
 448                        git add file_in_sub
 449                ) &&
 450
 451                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 452                HSUP=$(git rev-parse HEAD) &&
 453                HSUB=$HSUP &&
 454
 455                cat >expect <<-EOF &&
 456                # branch.oid $HSUP
 457                # branch.head master
 458                # branch.upstream origin/master
 459                # branch.ab +0 -0
 460                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 461                1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1
 462                EOF
 463
 464                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 465                test_cmp expect actual
 466        )
 467'
 468
 469test_expect_success 'staged and unstaged changes in added (AM S.M.)' '
 470        (       cd super_repo &&
 471                (       cd sub1 &&
 472                        ## make additional unstaged changes (on the same file) in the submodule.
 473                        ## This does not cause us to get S.MU (because the submodule does not report
 474                        ## a "?" line for the unstaged changes).
 475                        echo "more changes" >>file_in_sub
 476                ) &&
 477
 478                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 479                HSUP=$(git rev-parse HEAD) &&
 480                HSUB=$HSUP &&
 481
 482                cat >expect <<-EOF &&
 483                # branch.oid $HSUP
 484                # branch.head master
 485                # branch.upstream origin/master
 486                # branch.ab +0 -0
 487                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 488                1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1
 489                EOF
 490
 491                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 492                test_cmp expect actual
 493        )
 494'
 495
 496test_expect_success 'staged and untracked changes in added submodule (AM S.MU)' '
 497        (       cd super_repo &&
 498                (       cd sub1 &&
 499                        ## stage new changes in tracked file.
 500                        git add file_in_sub &&
 501                        ## create new untracked file.
 502                        echo "yyyy" >>another_file_in_sub
 503                ) &&
 504
 505                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 506                HSUP=$(git rev-parse HEAD) &&
 507                HSUB=$HSUP &&
 508
 509                cat >expect <<-EOF &&
 510                # branch.oid $HSUP
 511                # branch.head master
 512                # branch.upstream origin/master
 513                # branch.ab +0 -0
 514                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 515                1 AM S.MU 000000 160000 160000 $_z40 $HSUB sub1
 516                EOF
 517
 518                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 519                test_cmp expect actual
 520        )
 521'
 522
 523test_expect_success 'commit within the submodule appears as new commit in super (AM SC..)' '
 524        (       cd super_repo &&
 525                (       cd sub1 &&
 526                        ## Make a new commit in the submodule.
 527                        git add file_in_sub &&
 528                        rm -f another_file_in_sub &&
 529                        git commit -m "new commit"
 530                ) &&
 531
 532                HMOD=$(git hash-object -t blob -- .gitmodules) &&
 533                HSUP=$(git rev-parse HEAD) &&
 534                HSUB=$HSUP &&
 535
 536                cat >expect <<-EOF &&
 537                # branch.oid $HSUP
 538                # branch.head master
 539                # branch.upstream origin/master
 540                # branch.ab +0 -0
 541                1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
 542                1 AM SC.. 000000 160000 160000 $_z40 $HSUB sub1
 543                EOF
 544
 545                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 546                test_cmp expect actual
 547        )
 548'
 549
 550test_expect_success 'stage submodule in super and commit' '
 551        (       cd super_repo &&
 552                ## Stage the new submodule commit in the super.
 553                git add sub1 &&
 554                ## Commit the super so that the sub no longer appears as added.
 555                git commit -m "super commit" &&
 556
 557                HSUP=$(git rev-parse HEAD) &&
 558
 559                cat >expect <<-EOF &&
 560                # branch.oid $HSUP
 561                # branch.head master
 562                # branch.upstream origin/master
 563                # branch.ab +1 -0
 564                EOF
 565
 566                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 567                test_cmp expect actual
 568        )
 569'
 570
 571test_expect_success 'make unstaged changes in existing submodule (.M S.M.)' '
 572        (       cd super_repo &&
 573                (       cd sub1 &&
 574                        echo "zzzz" >>file_in_sub
 575                ) &&
 576
 577                HSUP=$(git rev-parse HEAD) &&
 578                HSUB=$(cd sub1 && git rev-parse HEAD) &&
 579
 580                cat >expect <<-EOF &&
 581                # branch.oid $HSUP
 582                # branch.head master
 583                # branch.upstream origin/master
 584                # branch.ab +1 -0
 585                1 .M S.M. 160000 160000 160000 $HSUB $HSUB sub1
 586                EOF
 587
 588                git status --porcelain=v2 --branch --untracked-files=all >actual &&
 589                test_cmp expect actual
 590        )
 591'
 592
 593test_done