t / t3701-add-interactive.shon commit Merge branch 'sb/packfiles-in-repository' into next (caa68db)
   1#!/bin/sh
   2
   3test_description='add -i basic tests'
   4. ./test-lib.sh
   5. "$TEST_DIRECTORY"/lib-terminal.sh
   6
   7if ! test_have_prereq PERL
   8then
   9        skip_all='skipping add -i tests, perl not available'
  10        test_done
  11fi
  12
  13diff_cmp () {
  14        for x
  15        do
  16                sed  -e '/^index/s/[0-9a-f]*[1-9a-f][0-9a-f]*\.\./1234567../' \
  17                     -e '/^index/s/\.\.[0-9a-f]*[1-9a-f][0-9a-f]*/..9abcdef/' \
  18                     -e '/^index/s/ 00*\.\./ 0000000../' \
  19                     -e '/^index/s/\.\.00*$/..0000000/' \
  20                     -e '/^index/s/\.\.00* /..0000000 /' \
  21                     "$x" >"$x.filtered"
  22        done
  23        test_cmp "$1.filtered" "$2.filtered"
  24}
  25
  26test_expect_success 'setup (initial)' '
  27        echo content >file &&
  28        git add file &&
  29        echo more >>file &&
  30        echo lines >>file
  31'
  32test_expect_success 'status works (initial)' '
  33        git add -i </dev/null >output &&
  34        grep "+1/-0 *+2/-0 file" output
  35'
  36
  37test_expect_success 'setup expected' '
  38        cat >expected <<-\EOF
  39        new file mode 100644
  40        index 0000000..d95f3ad
  41        --- /dev/null
  42        +++ b/file
  43        @@ -0,0 +1 @@
  44        +content
  45        EOF
  46'
  47
  48test_expect_success 'diff works (initial)' '
  49        (echo d; echo 1) | git add -i >output &&
  50        sed -ne "/new file/,/content/p" <output >diff &&
  51        diff_cmp expected diff
  52'
  53test_expect_success 'revert works (initial)' '
  54        git add file &&
  55        (echo r; echo 1) | git add -i &&
  56        git ls-files >output &&
  57        ! grep . output
  58'
  59
  60test_expect_success 'setup (commit)' '
  61        echo baseline >file &&
  62        git add file &&
  63        git commit -m commit &&
  64        echo content >>file &&
  65        git add file &&
  66        echo more >>file &&
  67        echo lines >>file
  68'
  69test_expect_success 'status works (commit)' '
  70        git add -i </dev/null >output &&
  71        grep "+1/-0 *+2/-0 file" output
  72'
  73
  74test_expect_success 'setup expected' '
  75        cat >expected <<-\EOF
  76        index 180b47c..b6f2c08 100644
  77        --- a/file
  78        +++ b/file
  79        @@ -1 +1,2 @@
  80         baseline
  81        +content
  82        EOF
  83'
  84
  85test_expect_success 'diff works (commit)' '
  86        (echo d; echo 1) | git add -i >output &&
  87        sed -ne "/^index/,/content/p" <output >diff &&
  88        diff_cmp expected diff
  89'
  90test_expect_success 'revert works (commit)' '
  91        git add file &&
  92        (echo r; echo 1) | git add -i &&
  93        git add -i </dev/null >output &&
  94        grep "unchanged *+3/-0 file" output
  95'
  96
  97
  98test_expect_success 'setup expected' '
  99        cat >expected <<-\EOF
 100        EOF
 101'
 102
 103test_expect_success 'dummy edit works' '
 104        test_set_editor : &&
 105        (echo e; echo a) | git add -p &&
 106        git diff > diff &&
 107        diff_cmp expected diff
 108'
 109
 110test_expect_success 'setup patch' '
 111        cat >patch <<-\EOF
 112        @@ -1,1 +1,4 @@
 113         this
 114        +patch
 115        -does not
 116         apply
 117        EOF
 118'
 119
 120test_expect_success 'setup fake editor' '
 121        write_script "fake_editor.sh" <<-\EOF &&
 122        mv -f "$1" oldpatch &&
 123        mv -f patch "$1"
 124        EOF
 125        test_set_editor "$(pwd)/fake_editor.sh"
 126'
 127
 128test_expect_success 'bad edit rejected' '
 129        git reset &&
 130        (echo e; echo n; echo d) | git add -p >output &&
 131        grep "hunk does not apply" output
 132'
 133
 134test_expect_success 'setup patch' '
 135        cat >patch <<-\EOF
 136        this patch
 137        is garbage
 138        EOF
 139'
 140
 141test_expect_success 'garbage edit rejected' '
 142        git reset &&
 143        (echo e; echo n; echo d) | git add -p >output &&
 144        grep "hunk does not apply" output
 145'
 146
 147test_expect_success 'setup patch' '
 148        cat >patch <<-\EOF
 149        @@ -1,0 +1,0 @@
 150         baseline
 151        +content
 152        +newcontent
 153        +lines
 154        EOF
 155'
 156
 157test_expect_success 'setup expected' '
 158        cat >expected <<-\EOF
 159        diff --git a/file b/file
 160        index b5dd6c9..f910ae9 100644
 161        --- a/file
 162        +++ b/file
 163        @@ -1,4 +1,4 @@
 164         baseline
 165         content
 166        -newcontent
 167        +more
 168         lines
 169        EOF
 170'
 171
 172test_expect_success 'real edit works' '
 173        (echo e; echo n; echo d) | git add -p &&
 174        git diff >output &&
 175        diff_cmp expected output
 176'
 177
 178test_expect_success 'skip files similarly as commit -a' '
 179        git reset &&
 180        echo file >.gitignore &&
 181        echo changed >file &&
 182        echo y | git add -p file &&
 183        git diff >output &&
 184        git reset &&
 185        git commit -am commit &&
 186        git diff >expected &&
 187        diff_cmp expected output &&
 188        git reset --hard HEAD^
 189'
 190rm -f .gitignore
 191
 192test_expect_success FILEMODE 'patch does not affect mode' '
 193        git reset --hard &&
 194        echo content >>file &&
 195        chmod +x file &&
 196        printf "n\\ny\\n" | git add -p &&
 197        git show :file | grep content &&
 198        git diff file | grep "new mode"
 199'
 200
 201test_expect_success FILEMODE 'stage mode but not hunk' '
 202        git reset --hard &&
 203        echo content >>file &&
 204        chmod +x file &&
 205        printf "y\\nn\\n" | git add -p &&
 206        git diff --cached file | grep "new mode" &&
 207        git diff          file | grep "+content"
 208'
 209
 210
 211test_expect_success FILEMODE 'stage mode and hunk' '
 212        git reset --hard &&
 213        echo content >>file &&
 214        chmod +x file &&
 215        printf "y\\ny\\n" | git add -p &&
 216        git diff --cached file | grep "new mode" &&
 217        git diff --cached file | grep "+content" &&
 218        test -z "$(git diff file)"
 219'
 220
 221# end of tests disabled when filemode is not usable
 222
 223test_expect_success 'setup again' '
 224        git reset --hard &&
 225        test_chmod +x file &&
 226        echo content >>file
 227'
 228
 229# Write the patch file with a new line at the top and bottom
 230test_expect_success 'setup patch' '
 231        cat >patch <<-\EOF
 232        index 180b47c..b6f2c08 100644
 233        --- a/file
 234        +++ b/file
 235        @@ -1,2 +1,4 @@
 236        +firstline
 237         baseline
 238         content
 239        +lastline
 240        \ No newline at end of file
 241        EOF
 242'
 243
 244# Expected output, diff is similar to the patch but w/ diff at the top
 245test_expect_success 'setup expected' '
 246        echo diff --git a/file b/file >expected &&
 247        cat patch |sed "/^index/s/ 100644/ 100755/" >>expected &&
 248        cat >expected-output <<-\EOF
 249        --- a/file
 250        +++ b/file
 251        @@ -1,2 +1,4 @@
 252        +firstline
 253         baseline
 254         content
 255        +lastline
 256        \ No newline at end of file
 257        @@ -1,2 +1,3 @@
 258        +firstline
 259         baseline
 260         content
 261        @@ -1,2 +2,3 @@
 262         baseline
 263         content
 264        +lastline
 265        \ No newline at end of file
 266        EOF
 267'
 268
 269# Test splitting the first patch, then adding both
 270test_expect_success C_LOCALE_OUTPUT 'add first line works' '
 271        git commit -am "clear local changes" &&
 272        git apply patch &&
 273        printf "%s\n" s y y | git add -p file 2>error |
 274                sed -n -e "s/^Stage this hunk[^@]*\(@@ .*\)/\1/" \
 275                       -e "/^[-+@ \\\\]"/p  >output &&
 276        test_must_be_empty error &&
 277        git diff --cached >diff &&
 278        diff_cmp expected diff &&
 279        test_cmp expected-output output
 280'
 281
 282test_expect_success 'setup expected' '
 283        cat >expected <<-\EOF
 284        diff --git a/non-empty b/non-empty
 285        deleted file mode 100644
 286        index d95f3ad..0000000
 287        --- a/non-empty
 288        +++ /dev/null
 289        @@ -1 +0,0 @@
 290        -content
 291        EOF
 292'
 293
 294test_expect_success 'deleting a non-empty file' '
 295        git reset --hard &&
 296        echo content >non-empty &&
 297        git add non-empty &&
 298        git commit -m non-empty &&
 299        rm non-empty &&
 300        echo y | git add -p non-empty &&
 301        git diff --cached >diff &&
 302        diff_cmp expected diff
 303'
 304
 305test_expect_success 'setup expected' '
 306        cat >expected <<-\EOF
 307        diff --git a/empty b/empty
 308        deleted file mode 100644
 309        index e69de29..0000000
 310        EOF
 311'
 312
 313test_expect_success 'deleting an empty file' '
 314        git reset --hard &&
 315        > empty &&
 316        git add empty &&
 317        git commit -m empty &&
 318        rm empty &&
 319        echo y | git add -p empty &&
 320        git diff --cached >diff &&
 321        diff_cmp expected diff
 322'
 323
 324test_expect_success 'split hunk setup' '
 325        git reset --hard &&
 326        test_write_lines 10 20 30 40 50 60 >test &&
 327        git add test &&
 328        test_tick &&
 329        git commit -m test &&
 330
 331        test_write_lines 10 15 20 21 22 23 24 30 40 50 60 >test
 332'
 333
 334test_expect_success 'split hunk "add -p (edit)"' '
 335        # Split, say Edit and do nothing.  Then:
 336        #
 337        # 1. Broken version results in a patch that does not apply and
 338        # only takes [y/n] (edit again) so the first q is discarded
 339        # and then n attempts to discard the edit. Repeat q enough
 340        # times to get out.
 341        #
 342        # 2. Correct version applies the (not)edited version, and asks
 343        #    about the next hunk, against which we say q and program
 344        #    exits.
 345        printf "%s\n" s e     q n q q |
 346        EDITOR=: git add -p &&
 347        git diff >actual &&
 348        ! grep "^+15" actual
 349'
 350
 351test_expect_failure 'split hunk "add -p (no, yes, edit)"' '
 352        test_write_lines 5 10 20 21 30 31 40 50 60 >test &&
 353        git reset &&
 354        # test sequence is s(plit), n(o), y(es), e(dit)
 355        # q n q q is there to make sure we exit at the end.
 356        printf "%s\n" s n y e   q n q q |
 357        EDITOR=: git add -p 2>error &&
 358        test_must_be_empty error &&
 359        git diff >actual &&
 360        ! grep "^+31" actual
 361'
 362
 363test_expect_success 'setup expected diff' '
 364        cat >expected <<-\EOF
 365        diff --git a/test b/test
 366        index 0889435..341cc6b 100644
 367        --- a/test
 368        +++ b/test
 369        @@ -1,6 +1,9 @@
 370        +5
 371         10
 372         20
 373        +21
 374         30
 375         40
 376         50
 377         60
 378        +61
 379        \ No newline at end of file
 380        EOF
 381'
 382
 383test_expect_success 'can stage individual lines of patch' '
 384        git reset &&
 385        printf 61 >>test &&
 386        printf "%s\n" l "1,2 4-" |
 387        EDITOR=: git add -p 2>error &&
 388        test_must_be_empty error &&
 389        git diff --cached HEAD >actual &&
 390        diff_cmp expected actual
 391'
 392
 393test_expect_success 'setup expected diff' '
 394        cat >expected <<-\EOF
 395        diff --git a/test b/test
 396        index 0889435..cc6163b 100644
 397        --- a/test
 398        +++ b/test
 399        @@ -1,6 +1,8 @@
 400        +5
 401         10
 402         20
 403         30
 404         40
 405         50
 406         60
 407        +61
 408        \ No newline at end of file
 409        EOF
 410'
 411
 412test_expect_success 'can reset individual lines of patch' '
 413        printf "%s\n" l -13 |
 414        EDITOR=: git reset -p 2>error &&
 415        test_must_be_empty error &&
 416        git diff --cached HEAD >actual &&
 417        diff_cmp expected actual
 418'
 419
 420test_expect_success 'patch mode ignores unmerged entries' '
 421        git reset --hard &&
 422        test_commit conflict &&
 423        test_commit non-conflict &&
 424        git checkout -b side &&
 425        test_commit side conflict.t &&
 426        git checkout master &&
 427        test_commit master conflict.t &&
 428        test_must_fail git merge side &&
 429        echo changed >non-conflict.t &&
 430        echo y | git add -p >output &&
 431        ! grep a/conflict.t output &&
 432        cat >expected <<-\EOF &&
 433        * Unmerged path conflict.t
 434        diff --git a/non-conflict.t b/non-conflict.t
 435        index f766221..5ea2ed4 100644
 436        --- a/non-conflict.t
 437        +++ b/non-conflict.t
 438        @@ -1 +1 @@
 439        -non-conflict
 440        +changed
 441        EOF
 442        git diff --cached >diff &&
 443        diff_cmp expected diff
 444'
 445
 446test_expect_success TTY 'diffs can be colorized' '
 447        git reset --hard &&
 448
 449        echo content >test &&
 450        printf y | test_terminal git add -p >output 2>&1 &&
 451
 452        # We do not want to depend on the exact coloring scheme
 453        # git uses for diffs, so just check that we saw some kind of color.
 454        grep "$(printf "\\033")" output
 455'
 456
 457test_expect_success TTY 'diffFilter filters diff' '
 458        git reset --hard &&
 459
 460        echo content >test &&
 461        test_config interactive.diffFilter "sed s/^/foo:/" &&
 462        printf y | test_terminal git add -p >output 2>&1 &&
 463
 464        # avoid depending on the exact coloring or content of the prompts,
 465        # and just make sure we saw our diff prefixed
 466        grep foo:.*content output
 467'
 468
 469test_expect_success TTY 'detect bogus diffFilter output' '
 470        git reset --hard &&
 471
 472        echo content >test &&
 473        test_config interactive.diffFilter "echo too-short" &&
 474        printf y | test_must_fail test_terminal git add -p
 475'
 476
 477test_expect_success 'patch-mode via -i prompts for files' '
 478        git reset --hard &&
 479
 480        echo one >file &&
 481        echo two >test &&
 482        git add -i <<-\EOF &&
 483        patch
 484        test
 485
 486        y
 487        quit
 488        EOF
 489
 490        echo test >expect &&
 491        git diff --cached --name-only >actual &&
 492        diff_cmp expect actual
 493'
 494
 495test_expect_success 'add -p handles globs' '
 496        git reset --hard &&
 497
 498        mkdir -p subdir &&
 499        echo base >one.c &&
 500        echo base >subdir/two.c &&
 501        git add "*.c" &&
 502        git commit -m base &&
 503
 504        echo change >one.c &&
 505        echo change >subdir/two.c &&
 506        git add -p "*.c" <<-\EOF &&
 507        y
 508        y
 509        EOF
 510
 511        cat >expect <<-\EOF &&
 512        one.c
 513        subdir/two.c
 514        EOF
 515        git diff --cached --name-only >actual &&
 516        test_cmp expect actual
 517'
 518
 519test_expect_success 'add -p handles relative paths' '
 520        git reset --hard &&
 521
 522        echo base >relpath.c &&
 523        git add "*.c" &&
 524        git commit -m relpath &&
 525
 526        echo change >relpath.c &&
 527        mkdir -p subdir &&
 528        git -C subdir add -p .. 2>error <<-\EOF &&
 529        y
 530        EOF
 531
 532        test_must_be_empty error &&
 533
 534        cat >expect <<-\EOF &&
 535        relpath.c
 536        EOF
 537        git diff --cached --name-only >actual &&
 538        test_cmp expect actual
 539'
 540
 541test_expect_success 'add -p does not expand argument lists' '
 542        git reset --hard &&
 543
 544        echo content >not-changed &&
 545        git add not-changed &&
 546        git commit -m "add not-changed file" &&
 547
 548        echo change >file &&
 549        GIT_TRACE=$(pwd)/trace.out git add -p . <<-\EOF &&
 550        y
 551        EOF
 552
 553        # we know that "file" must be mentioned since we actually
 554        # update it, but we want to be sure that our "." pathspec
 555        # was not expanded into the argument list of any command.
 556        # So look only for "not-changed".
 557        ! grep not-changed trace.out
 558'
 559
 560test_expect_success 'hunk-editing handles custom comment char' '
 561        git reset --hard &&
 562        echo change >>file &&
 563        test_config core.commentChar "\$" &&
 564        echo e | GIT_EDITOR=true git add -p &&
 565        git diff --exit-code
 566'
 567
 568test_expect_success 'add -p works even with color.ui=always' '
 569        git reset --hard &&
 570        echo change >>file &&
 571        test_config color.ui always &&
 572        echo y | git add -p &&
 573        echo file >expect &&
 574        git diff --cached --name-only >actual &&
 575        test_cmp expect actual
 576'
 577
 578test_expect_success 'setup different kinds of dirty submodules' '
 579        test_create_repo for-submodules &&
 580        (
 581                cd for-submodules &&
 582                test_commit initial &&
 583                test_create_repo dirty-head &&
 584                (
 585                        cd dirty-head &&
 586                        test_commit initial
 587                ) &&
 588                cp -R dirty-head dirty-otherwise &&
 589                cp -R dirty-head dirty-both-ways &&
 590                git add dirty-head &&
 591                git add dirty-otherwise dirty-both-ways &&
 592                git commit -m initial &&
 593
 594                cd dirty-head &&
 595                test_commit updated &&
 596                cd ../dirty-both-ways &&
 597                test_commit updated &&
 598                echo dirty >>initial &&
 599                : >untracked &&
 600                cd ../dirty-otherwise &&
 601                echo dirty >>initial &&
 602                : >untracked
 603        ) &&
 604        git -C for-submodules diff-files --name-only >actual &&
 605        cat >expected <<-\EOF &&
 606        dirty-both-ways
 607        dirty-head
 608        dirty-otherwise
 609        EOF
 610        test_cmp expected actual &&
 611        git -C for-submodules diff-files --name-only --ignore-submodules=dirty >actual &&
 612        cat >expected <<-\EOF &&
 613        dirty-both-ways
 614        dirty-head
 615        EOF
 616        test_cmp expected actual
 617'
 618
 619test_expect_success 'status ignores dirty submodules (except HEAD)' '
 620        git -C for-submodules add -i </dev/null >output &&
 621        grep dirty-head output &&
 622        grep dirty-both-ways output &&
 623        ! grep dirty-otherwise output
 624'
 625
 626test_expect_success 'set up pathological context' '
 627        git reset --hard &&
 628        test_write_lines a a a a a a a a a a a >a &&
 629        git add a &&
 630        git commit -m a &&
 631        test_write_lines c b a a a a a a a b a a a a >a &&
 632        test_write_lines     a a a a a a a b a a a a >expected-1 &&
 633        test_write_lines   b a a a a a a a b a a a a >expected-2 &&
 634        # check editing can cope with missing header and deleted context lines
 635        # as well as changes to other lines
 636        test_write_lines +b " a" >patch
 637'
 638
 639test_expect_success 'add -p works with pathological context lines' '
 640        git reset &&
 641        printf "%s\n" n y |
 642        git add -p &&
 643        git cat-file blob :a >actual &&
 644        test_cmp expected-1 actual
 645'
 646
 647test_expect_success 'add -p patch editing works with pathological context lines' '
 648        git reset &&
 649        # n q q below is in case edit fails
 650        printf "%s\n" e y    n q q |
 651        git add -p &&
 652        git cat-file blob :a >actual &&
 653        test_cmp expected-2 actual
 654'
 655
 656test_expect_success 'add -p selecting lines works with pathological context lines' '
 657        git reset &&
 658        printf "%s\n" l 2 y |
 659        GIT_EDITOR=./editor git add -p &&
 660        git cat-file blob :a >actual &&
 661        test_cmp expected-2 actual
 662'
 663
 664test_done