Imported Upstream version 2.17.1
[platform/upstream/git.git] / t / t3701-add-interactive.sh
index 2f3e7ce..b170fb0 100755 (executable)
@@ -2,6 +2,7 @@
 
 test_description='add -i basic tests'
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
 
 if ! test_have_prereq PERL
 then
@@ -9,6 +10,19 @@ then
        test_done
 fi
 
+diff_cmp () {
+       for x
+       do
+               sed  -e '/^index/s/[0-9a-f]*[1-9a-f][0-9a-f]*\.\./1234567../' \
+                    -e '/^index/s/\.\.[0-9a-f]*[1-9a-f][0-9a-f]*/..9abcdef/' \
+                    -e '/^index/s/ 00*\.\./ 0000000../' \
+                    -e '/^index/s/\.\.00*$/..0000000/' \
+                    -e '/^index/s/\.\.00* /..0000000 /' \
+                    "$x" >"$x.filtered"
+       done
+       test_cmp "$1.filtered" "$2.filtered"
+}
+
 test_expect_success 'setup (initial)' '
        echo content >file &&
        git add file &&
@@ -21,20 +35,20 @@ test_expect_success 'status works (initial)' '
 '
 
 test_expect_success 'setup expected' '
-cat >expected <<EOF
-new file mode 100644
-index 0000000..d95f3ad
---- /dev/null
-+++ b/file
-@@ -0,0 +1 @@
-+content
-EOF
+       cat >expected <<-\EOF
+       new file mode 100644
+       index 0000000..d95f3ad
+       --- /dev/null
+       +++ b/file
+       @@ -0,0 +1 @@
+       +content
+       EOF
 '
 
 test_expect_success 'diff works (initial)' '
        (echo d; echo 1) | git add -i >output &&
        sed -ne "/new file/,/content/p" <output >diff &&
-       test_cmp expected diff
+       diff_cmp expected diff
 '
 test_expect_success 'revert works (initial)' '
        git add file &&
@@ -58,20 +72,20 @@ test_expect_success 'status works (commit)' '
 '
 
 test_expect_success 'setup expected' '
-cat >expected <<EOF
-index 180b47c..b6f2c08 100644
---- a/file
-+++ b/file
-@@ -1 +1,2 @@
- baseline
-+content
-EOF
+       cat >expected <<-\EOF
+       index 180b47c..b6f2c08 100644
+       --- a/file
+       +++ b/file
+       @@ -1 +1,2 @@
       baseline
+       +content
+       EOF
 '
 
 test_expect_success 'diff works (commit)' '
        (echo d; echo 1) | git add -i >output &&
        sed -ne "/^index/,/content/p" <output >diff &&
-       test_cmp expected diff
+       diff_cmp expected diff
 '
 test_expect_success 'revert works (commit)' '
        git add file &&
@@ -82,39 +96,32 @@ test_expect_success 'revert works (commit)' '
 
 
 test_expect_success 'setup expected' '
-cat >expected <<EOF
-EOF
-'
-
-test_expect_success 'setup fake editor' '
-       >fake_editor.sh &&
-       chmod a+x fake_editor.sh &&
-       test_set_editor "$(pwd)/fake_editor.sh"
+       cat >expected <<-\EOF
+       EOF
 '
 
 test_expect_success 'dummy edit works' '
+       test_set_editor : &&
        (echo e; echo a) | git add -p &&
        git diff > diff &&
-       test_cmp expected diff
+       diff_cmp expected diff
 '
 
 test_expect_success 'setup patch' '
-cat >patch <<EOF
-@@ -1,1 +1,4 @@
- this
-+patch
--does not
- apply
-EOF
+       cat >patch <<-\EOF
+       @@ -1,1 +1,4 @@
       this
+       +patch
+       -does not
       apply
+       EOF
 '
 
 test_expect_success 'setup fake editor' '
-       echo "#!$SHELL_PATH" >fake_editor.sh &&
-       cat >>fake_editor.sh <<\EOF &&
-mv -f "$1" oldpatch &&
-mv -f patch "$1"
-EOF
-       chmod a+x fake_editor.sh &&
+       write_script "fake_editor.sh" <<-\EOF &&
+       mv -f "$1" oldpatch &&
+       mv -f patch "$1"
+       EOF
        test_set_editor "$(pwd)/fake_editor.sh"
 '
 
@@ -125,10 +132,10 @@ test_expect_success 'bad edit rejected' '
 '
 
 test_expect_success 'setup patch' '
-cat >patch <<EOF
-this patch
-is garbage
-EOF
+       cat >patch <<-\EOF
+       this patch
+       is garbage
+       EOF
 '
 
 test_expect_success 'garbage edit rejected' '
@@ -138,34 +145,34 @@ test_expect_success 'garbage edit rejected' '
 '
 
 test_expect_success 'setup patch' '
-cat >patch <<EOF
-@@ -1,0 +1,0 @@
- baseline
-+content
-+newcontent
-+lines
-EOF
+       cat >patch <<-\EOF
+       @@ -1,0 +1,0 @@
       baseline
+       +content
+       +newcontent
+       +lines
+       EOF
 '
 
 test_expect_success 'setup expected' '
-cat >expected <<EOF
-diff --git a/file b/file
-index b5dd6c9..f910ae9 100644
---- a/file
-+++ b/file
-@@ -1,4 +1,4 @@
- baseline
- content
--newcontent
-+more
- lines
-EOF
+       cat >expected <<-\EOF
+       diff --git a/file b/file
+       index b5dd6c9..f910ae9 100644
+       --- a/file
+       +++ b/file
+       @@ -1,4 +1,4 @@
       baseline
       content
+       -newcontent
+       +more
       lines
+       EOF
 '
 
 test_expect_success 'real edit works' '
        (echo e; echo n; echo d) | git add -p &&
        git diff >output &&
-       test_cmp expected output
+       diff_cmp expected output
 '
 
 test_expect_success 'skip files similarly as commit -a' '
@@ -177,7 +184,7 @@ test_expect_success 'skip files similarly as commit -a' '
        git reset &&
        git commit -am commit &&
        git diff >expected &&
-       test_cmp expected output &&
+       diff_cmp expected output &&
        git reset --hard HEAD^
 '
 rm -f .gitignore
@@ -221,52 +228,67 @@ test_expect_success 'setup again' '
 
 # Write the patch file with a new line at the top and bottom
 test_expect_success 'setup patch' '
-cat >patch <<EOF
-index 180b47c..b6f2c08 100644
---- a/file
-+++ b/file
-@@ -1,2 +1,4 @@
-+firstline
- baseline
- content
-+lastline
-EOF
-'
-
-# Expected output, similar to the patch but w/ diff at the top
+       cat >patch <<-\EOF
+       index 180b47c..b6f2c08 100644
+       --- a/file
+       +++ b/file
+       @@ -1,2 +1,4 @@
+       +firstline
+        baseline
+        content
+       +lastline
+       \ No newline at end of file
+       EOF
+'
+
+# Expected output, diff is similar to the patch but w/ diff at the top
 test_expect_success 'setup expected' '
-cat >expected <<EOF
-diff --git a/file b/file
-index b6f2c08..61b9053 100755
---- a/file
-+++ b/file
-@@ -1,2 +1,4 @@
-+firstline
- baseline
- content
-+lastline
-EOF
+       echo diff --git a/file b/file >expected &&
+       cat patch |sed "/^index/s/ 100644/ 100755/" >>expected &&
+       cat >expected-output <<-\EOF
+       --- a/file
+       +++ b/file
+       @@ -1,2 +1,4 @@
+       +firstline
+        baseline
+        content
+       +lastline
+       \ No newline at end of file
+       @@ -1,2 +1,3 @@
+       +firstline
+        baseline
+        content
+       @@ -1,2 +2,3 @@
+        baseline
+        content
+       +lastline
+       \ No newline at end of file
+       EOF
 '
 
 # Test splitting the first patch, then adding both
-test_expect_success 'add first line works' '
+test_expect_success C_LOCALE_OUTPUT 'add first line works' '
        git commit -am "clear local changes" &&
        git apply patch &&
-       (echo s; echo y; echo y) | git add -p file &&
-       git diff --cached > diff &&
-       test_cmp expected diff
+       printf "%s\n" s y y | git add -p file 2>error |
+               sed -n -e "s/^Stage this hunk[^@]*\(@@ .*\)/\1/" \
+                      -e "/^[-+@ \\\\]"/p  >output &&
+       test_must_be_empty error &&
+       git diff --cached >diff &&
+       diff_cmp expected diff &&
+       test_cmp expected-output output
 '
 
 test_expect_success 'setup expected' '
-cat >expected <<EOF
-diff --git a/non-empty b/non-empty
-deleted file mode 100644
-index d95f3ad..0000000
---- a/non-empty
-+++ /dev/null
-@@ -1 +0,0 @@
--content
-EOF
+       cat >expected <<-\EOF
+       diff --git a/non-empty b/non-empty
+       deleted file mode 100644
+       index d95f3ad..0000000
+       --- a/non-empty
+       +++ /dev/null
+       @@ -1 +0,0 @@
+       -content
+       EOF
 '
 
 test_expect_success 'deleting a non-empty file' '
@@ -277,15 +299,15 @@ test_expect_success 'deleting a non-empty file' '
        rm non-empty &&
        echo y | git add -p non-empty &&
        git diff --cached >diff &&
-       test_cmp expected diff
+       diff_cmp expected diff
 '
 
 test_expect_success 'setup expected' '
-cat >expected <<EOF
-diff --git a/empty b/empty
-deleted file mode 100644
-index e69de29..0000000
-EOF
+       cat >expected <<-\EOF
+       diff --git a/empty b/empty
+       deleted file mode 100644
+       index e69de29..0000000
+       EOF
 '
 
 test_expect_success 'deleting an empty file' '
@@ -296,23 +318,17 @@ test_expect_success 'deleting an empty file' '
        rm empty &&
        echo y | git add -p empty &&
        git diff --cached >diff &&
-       test_cmp expected diff
+       diff_cmp expected diff
 '
 
 test_expect_success 'split hunk setup' '
        git reset --hard &&
-       for i in 10 20 30 40 50 60
-       do
-               echo $i
-       done >test &&
+       test_write_lines 10 20 30 40 50 60 >test &&
        git add test &&
        test_tick &&
        git commit -m test &&
 
-       for i in 10 15 20 21 22 23 24 30 40 50 60
-       do
-               echo $i
-       done >test
+       test_write_lines 10 15 20 21 22 23 24 30 40 50 60 >test
 '
 
 test_expect_success 'split hunk "add -p (edit)"' '
@@ -333,17 +349,7 @@ test_expect_success 'split hunk "add -p (edit)"' '
 '
 
 test_expect_failure 'split hunk "add -p (no, yes, edit)"' '
-       cat >test <<-\EOF &&
-       5
-       10
-       20
-       21
-       30
-       31
-       40
-       50
-       60
-       EOF
+       test_write_lines 5 10 20 21 30 31 40 50 60 >test &&
        git reset &&
        # test sequence is s(plit), n(o), y(es), e(dit)
        # q n q q is there to make sure we exit at the end.
@@ -377,23 +383,40 @@ test_expect_success 'patch mode ignores unmerged entries' '
        +changed
        EOF
        git diff --cached >diff &&
-       test_cmp expected diff
+       diff_cmp expected diff
 '
 
-test_expect_success 'diffs can be colorized' '
+test_expect_success TTY 'diffs can be colorized' '
        git reset --hard &&
 
-       # force color even though the test script has no terminal
-       test_config color.ui always &&
-
        echo content >test &&
-       printf y | git add -p >output 2>&1 &&
+       printf y | test_terminal git add -p >output 2>&1 &&
 
        # We do not want to depend on the exact coloring scheme
        # git uses for diffs, so just check that we saw some kind of color.
        grep "$(printf "\\033")" output
 '
 
+test_expect_success TTY 'diffFilter filters diff' '
+       git reset --hard &&
+
+       echo content >test &&
+       test_config interactive.diffFilter "sed s/^/foo:/" &&
+       printf y | test_terminal git add -p >output 2>&1 &&
+
+       # avoid depending on the exact coloring or content of the prompts,
+       # and just make sure we saw our diff prefixed
+       grep foo:.*content output
+'
+
+test_expect_success TTY 'detect bogus diffFilter output' '
+       git reset --hard &&
+
+       echo content >test &&
+       test_config interactive.diffFilter "echo too-short" &&
+       printf y | test_must_fail test_terminal git add -p
+'
+
 test_expect_success 'patch-mode via -i prompts for files' '
        git reset --hard &&
 
@@ -409,7 +432,7 @@ test_expect_success 'patch-mode via -i prompts for files' '
 
        echo test >expect &&
        git diff --cached --name-only >actual &&
-       test_cmp expect actual
+       diff_cmp expect actual
 '
 
 test_expect_success 'add -p handles globs' '
@@ -485,4 +508,92 @@ test_expect_success 'hunk-editing handles custom comment char' '
        git diff --exit-code
 '
 
+test_expect_success 'add -p works even with color.ui=always' '
+       git reset --hard &&
+       echo change >>file &&
+       test_config color.ui always &&
+       echo y | git add -p &&
+       echo file >expect &&
+       git diff --cached --name-only >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'setup different kinds of dirty submodules' '
+       test_create_repo for-submodules &&
+       (
+               cd for-submodules &&
+               test_commit initial &&
+               test_create_repo dirty-head &&
+               (
+                       cd dirty-head &&
+                       test_commit initial
+               ) &&
+               cp -R dirty-head dirty-otherwise &&
+               cp -R dirty-head dirty-both-ways &&
+               git add dirty-head &&
+               git add dirty-otherwise dirty-both-ways &&
+               git commit -m initial &&
+
+               cd dirty-head &&
+               test_commit updated &&
+               cd ../dirty-both-ways &&
+               test_commit updated &&
+               echo dirty >>initial &&
+               : >untracked &&
+               cd ../dirty-otherwise &&
+               echo dirty >>initial &&
+               : >untracked
+       ) &&
+       git -C for-submodules diff-files --name-only >actual &&
+       cat >expected <<-\EOF &&
+       dirty-both-ways
+       dirty-head
+       dirty-otherwise
+       EOF
+       test_cmp expected actual &&
+       git -C for-submodules diff-files --name-only --ignore-submodules=dirty >actual &&
+       cat >expected <<-\EOF &&
+       dirty-both-ways
+       dirty-head
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'status ignores dirty submodules (except HEAD)' '
+       git -C for-submodules add -i </dev/null >output &&
+       grep dirty-head output &&
+       grep dirty-both-ways output &&
+       ! grep dirty-otherwise output
+'
+
+test_expect_success 'set up pathological context' '
+       git reset --hard &&
+       test_write_lines a a a a a a a a a a a >a &&
+       git add a &&
+       git commit -m a &&
+       test_write_lines c b a a a a a a a b a a a a >a &&
+       test_write_lines     a a a a a a a b a a a a >expected-1 &&
+       test_write_lines   b a a a a a a a b a a a a >expected-2 &&
+       # check editing can cope with missing header and deleted context lines
+       # as well as changes to other lines
+       test_write_lines +b " a" >patch
+'
+
+test_expect_success 'add -p works with pathological context lines' '
+       git reset &&
+       printf "%s\n" n y |
+       git add -p &&
+       git cat-file blob :a >actual &&
+       test_cmp expected-1 actual
+'
+
+test_expect_success 'add -p patch editing works with pathological context lines' '
+       git reset &&
+       # n q q below is in case edit fails
+       printf "%s\n" e y    n q q |
+       git add -p &&
+       git cat-file blob :a >actual &&
+       test_cmp expected-2 actual
+'
+
 test_done