4a369fcb518c0dcbada86968a83e1d7d137de706
   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
  13test_expect_success 'setup (initial)' '
  14        echo content >file &&
  15        git add file &&
  16        echo more >>file &&
  17        echo lines >>file
  18'
  19test_expect_success 'status works (initial)' '
  20        git add -i </dev/null >output &&
  21        grep "+1/-0 *+2/-0 file" output
  22'
  23
  24test_expect_success 'setup expected' '
  25        cat >expected <<-\EOF
  26        new file mode 100644
  27        index 0000000..d95f3ad
  28        --- /dev/null
  29        +++ b/file
  30        @@ -0,0 +1 @@
  31        +content
  32        EOF
  33'
  34
  35test_expect_success 'diff works (initial)' '
  36        (echo d; echo 1) | git add -i >output &&
  37        sed -ne "/new file/,/content/p" <output >diff &&
  38        test_cmp expected diff
  39'
  40test_expect_success 'revert works (initial)' '
  41        git add file &&
  42        (echo r; echo 1) | git add -i &&
  43        git ls-files >output &&
  44        ! grep . output
  45'
  46
  47test_expect_success 'setup (commit)' '
  48        echo baseline >file &&
  49        git add file &&
  50        git commit -m commit &&
  51        echo content >>file &&
  52        git add file &&
  53        echo more >>file &&
  54        echo lines >>file
  55'
  56test_expect_success 'status works (commit)' '
  57        git add -i </dev/null >output &&
  58        grep "+1/-0 *+2/-0 file" output
  59'
  60
  61test_expect_success 'setup expected' '
  62        cat >expected <<-\EOF
  63        index 180b47c..b6f2c08 100644
  64        --- a/file
  65        +++ b/file
  66        @@ -1 +1,2 @@
  67         baseline
  68        +content
  69        EOF
  70'
  71
  72test_expect_success 'diff works (commit)' '
  73        (echo d; echo 1) | git add -i >output &&
  74        sed -ne "/^index/,/content/p" <output >diff &&
  75        test_cmp expected diff
  76'
  77test_expect_success 'revert works (commit)' '
  78        git add file &&
  79        (echo r; echo 1) | git add -i &&
  80        git add -i </dev/null >output &&
  81        grep "unchanged *+3/-0 file" output
  82'
  83
  84
  85test_expect_success 'setup expected' '
  86        cat >expected <<-\EOF
  87        EOF
  88'
  89
  90test_expect_success 'dummy edit works' '
  91        test_set_editor : &&
  92        (echo e; echo a) | git add -p &&
  93        git diff > diff &&
  94        test_cmp expected diff
  95'
  96
  97test_expect_success 'setup patch' '
  98        cat >patch <<-\EOF
  99        @@ -1,1 +1,4 @@
 100         this
 101        +patch
 102        -does not
 103         apply
 104        EOF
 105'
 106
 107test_expect_success 'setup fake editor' '
 108        write_script "fake_editor.sh" <<-\EOF &&
 109        mv -f "$1" oldpatch &&
 110        mv -f patch "$1"
 111        EOF
 112        test_set_editor "$(pwd)/fake_editor.sh"
 113'
 114
 115test_expect_success 'bad edit rejected' '
 116        git reset &&
 117        (echo e; echo n; echo d) | git add -p >output &&
 118        grep "hunk does not apply" output
 119'
 120
 121test_expect_success 'setup patch' '
 122        cat >patch <<-\EOF
 123        this patch
 124        is garbage
 125        EOF
 126'
 127
 128test_expect_success 'garbage 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        @@ -1,0 +1,0 @@
 137         baseline
 138        +content
 139        +newcontent
 140        +lines
 141        EOF
 142'
 143
 144test_expect_success 'setup expected' '
 145        cat >expected <<-\EOF
 146        diff --git a/file b/file
 147        index b5dd6c9..f910ae9 100644
 148        --- a/file
 149        +++ b/file
 150        @@ -1,4 +1,4 @@
 151         baseline
 152         content
 153        -newcontent
 154        +more
 155         lines
 156        EOF
 157'
 158
 159test_expect_success 'real edit works' '
 160        (echo e; echo n; echo d) | git add -p &&
 161        git diff >output &&
 162        test_cmp expected output
 163'
 164
 165test_expect_success 'skip files similarly as commit -a' '
 166        git reset &&
 167        echo file >.gitignore &&
 168        echo changed >file &&
 169        echo y | git add -p file &&
 170        git diff >output &&
 171        git reset &&
 172        git commit -am commit &&
 173        git diff >expected &&
 174        test_cmp expected output &&
 175        git reset --hard HEAD^
 176'
 177rm -f .gitignore
 178
 179test_expect_success FILEMODE 'patch does not affect mode' '
 180        git reset --hard &&
 181        echo content >>file &&
 182        chmod +x file &&
 183        printf "n\\ny\\n" | git add -p &&
 184        git show :file | grep content &&
 185        git diff file | grep "new mode"
 186'
 187
 188test_expect_success FILEMODE 'stage mode but not hunk' '
 189        git reset --hard &&
 190        echo content >>file &&
 191        chmod +x file &&
 192        printf "y\\nn\\n" | git add -p &&
 193        git diff --cached file | grep "new mode" &&
 194        git diff          file | grep "+content"
 195'
 196
 197
 198test_expect_success FILEMODE 'stage mode and hunk' '
 199        git reset --hard &&
 200        echo content >>file &&
 201        chmod +x file &&
 202        printf "y\\ny\\n" | git add -p &&
 203        git diff --cached file | grep "new mode" &&
 204        git diff --cached file | grep "+content" &&
 205        test -z "$(git diff file)"
 206'
 207
 208# end of tests disabled when filemode is not usable
 209
 210test_expect_success 'setup again' '
 211        git reset --hard &&
 212        test_chmod +x file &&
 213        echo content >>file
 214'
 215
 216# Write the patch file with a new line at the top and bottom
 217test_expect_success 'setup patch' '
 218        cat >patch <<-\EOF
 219        index 180b47c..b6f2c08 100644
 220        --- a/file
 221        +++ b/file
 222        @@ -1,2 +1,4 @@
 223        +firstline
 224         baseline
 225         content
 226        +lastline
 227        EOF
 228'
 229
 230# Expected output, similar to the patch but w/ diff at the top
 231test_expect_success 'setup expected' '
 232        cat >expected <<-\EOF
 233        diff --git a/file b/file
 234        index b6f2c08..61b9053 100755
 235        --- a/file
 236        +++ b/file
 237        @@ -1,2 +1,4 @@
 238        +firstline
 239         baseline
 240         content
 241        +lastline
 242        EOF
 243'
 244
 245# Test splitting the first patch, then adding both
 246test_expect_success 'add first line works' '
 247        git commit -am "clear local changes" &&
 248        git apply patch &&
 249        (echo s; echo y; echo y) | git add -p file &&
 250        git diff --cached > diff &&
 251        test_cmp expected diff
 252'
 253
 254test_expect_success 'setup expected' '
 255        cat >expected <<-\EOF
 256        diff --git a/non-empty b/non-empty
 257        deleted file mode 100644
 258        index d95f3ad..0000000
 259        --- a/non-empty
 260        +++ /dev/null
 261        @@ -1 +0,0 @@
 262        -content
 263        EOF
 264'
 265
 266test_expect_success 'deleting a non-empty file' '
 267        git reset --hard &&
 268        echo content >non-empty &&
 269        git add non-empty &&
 270        git commit -m non-empty &&
 271        rm non-empty &&
 272        echo y | git add -p non-empty &&
 273        git diff --cached >diff &&
 274        test_cmp expected diff
 275'
 276
 277test_expect_success 'setup expected' '
 278        cat >expected <<-\EOF
 279        diff --git a/empty b/empty
 280        deleted file mode 100644
 281        index e69de29..0000000
 282        EOF
 283'
 284
 285test_expect_success 'deleting an empty file' '
 286        git reset --hard &&
 287        > empty &&
 288        git add empty &&
 289        git commit -m empty &&
 290        rm empty &&
 291        echo y | git add -p empty &&
 292        git diff --cached >diff &&
 293        test_cmp expected diff
 294'
 295
 296test_expect_success 'split hunk setup' '
 297        git reset --hard &&
 298        test_write_lines 10 20 30 40 50 60 >test &&
 299        git add test &&
 300        test_tick &&
 301        git commit -m test &&
 302
 303        test_write_lines 10 15 20 21 22 23 24 30 40 50 60 >test
 304'
 305
 306test_expect_success 'split hunk "add -p (edit)"' '
 307        # Split, say Edit and do nothing.  Then:
 308        #
 309        # 1. Broken version results in a patch that does not apply and
 310        # only takes [y/n] (edit again) so the first q is discarded
 311        # and then n attempts to discard the edit. Repeat q enough
 312        # times to get out.
 313        #
 314        # 2. Correct version applies the (not)edited version, and asks
 315        #    about the next hunk, against which we say q and program
 316        #    exits.
 317        printf "%s\n" s e     q n q q |
 318        EDITOR=: git add -p &&
 319        git diff >actual &&
 320        ! grep "^+15" actual
 321'
 322
 323test_expect_failure 'split hunk "add -p (no, yes, edit)"' '
 324        test_write_lines 5 10 20 21 30 31 40 50 60 >test &&
 325        git reset &&
 326        # test sequence is s(plit), n(o), y(es), e(dit)
 327        # q n q q is there to make sure we exit at the end.
 328        printf "%s\n" s n y e   q n q q |
 329        EDITOR=: git add -p 2>error &&
 330        test_must_be_empty error &&
 331        git diff >actual &&
 332        ! grep "^+31" actual
 333'
 334
 335test_expect_success 'patch mode ignores unmerged entries' '
 336        git reset --hard &&
 337        test_commit conflict &&
 338        test_commit non-conflict &&
 339        git checkout -b side &&
 340        test_commit side conflict.t &&
 341        git checkout master &&
 342        test_commit master conflict.t &&
 343        test_must_fail git merge side &&
 344        echo changed >non-conflict.t &&
 345        echo y | git add -p >output &&
 346        ! grep a/conflict.t output &&
 347        cat >expected <<-\EOF &&
 348        * Unmerged path conflict.t
 349        diff --git a/non-conflict.t b/non-conflict.t
 350        index f766221..5ea2ed4 100644
 351        --- a/non-conflict.t
 352        +++ b/non-conflict.t
 353        @@ -1 +1 @@
 354        -non-conflict
 355        +changed
 356        EOF
 357        git diff --cached >diff &&
 358        test_cmp expected diff
 359'
 360
 361test_expect_success TTY 'diffs can be colorized' '
 362        git reset --hard &&
 363
 364        echo content >test &&
 365        printf y | test_terminal git add -p >output 2>&1 &&
 366
 367        # We do not want to depend on the exact coloring scheme
 368        # git uses for diffs, so just check that we saw some kind of color.
 369        grep "$(printf "\\033")" output
 370'
 371
 372test_expect_success 'patch-mode via -i prompts for files' '
 373        git reset --hard &&
 374
 375        echo one >file &&
 376        echo two >test &&
 377        git add -i <<-\EOF &&
 378        patch
 379        test
 380
 381        y
 382        quit
 383        EOF
 384
 385        echo test >expect &&
 386        git diff --cached --name-only >actual &&
 387        test_cmp expect actual
 388'
 389
 390test_expect_success 'add -p handles globs' '
 391        git reset --hard &&
 392
 393        mkdir -p subdir &&
 394        echo base >one.c &&
 395        echo base >subdir/two.c &&
 396        git add "*.c" &&
 397        git commit -m base &&
 398
 399        echo change >one.c &&
 400        echo change >subdir/two.c &&
 401        git add -p "*.c" <<-\EOF &&
 402        y
 403        y
 404        EOF
 405
 406        cat >expect <<-\EOF &&
 407        one.c
 408        subdir/two.c
 409        EOF
 410        git diff --cached --name-only >actual &&
 411        test_cmp expect actual
 412'
 413
 414test_expect_success 'add -p handles relative paths' '
 415        git reset --hard &&
 416
 417        echo base >relpath.c &&
 418        git add "*.c" &&
 419        git commit -m relpath &&
 420
 421        echo change >relpath.c &&
 422        mkdir -p subdir &&
 423        git -C subdir add -p .. 2>error <<-\EOF &&
 424        y
 425        EOF
 426
 427        test_must_be_empty error &&
 428
 429        cat >expect <<-\EOF &&
 430        relpath.c
 431        EOF
 432        git diff --cached --name-only >actual &&
 433        test_cmp expect actual
 434'
 435
 436test_expect_success 'add -p does not expand argument lists' '
 437        git reset --hard &&
 438
 439        echo content >not-changed &&
 440        git add not-changed &&
 441        git commit -m "add not-changed file" &&
 442
 443        echo change >file &&
 444        GIT_TRACE=$(pwd)/trace.out git add -p . <<-\EOF &&
 445        y
 446        EOF
 447
 448        # we know that "file" must be mentioned since we actually
 449        # update it, but we want to be sure that our "." pathspec
 450        # was not expanded into the argument list of any command.
 451        # So look only for "not-changed".
 452        ! grep not-changed trace.out
 453'
 454
 455test_expect_success 'hunk-editing handles custom comment char' '
 456        git reset --hard &&
 457        echo change >>file &&
 458        test_config core.commentChar "\$" &&
 459        echo e | GIT_EDITOR=true git add -p &&
 460        git diff --exit-code
 461'
 462
 463test_expect_success 'add -p works even with color.ui=always' '
 464        git reset --hard &&
 465        echo change >>file &&
 466        test_config color.ui always &&
 467        echo y | git add -p &&
 468        echo file >expect &&
 469        git diff --cached --name-only >actual &&
 470        test_cmp expect actual
 471'
 472
 473test_done