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