2008-02-13 10:50:51 +00:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='add -i basic tests'
|
2020-11-18 23:44:26 +00:00
|
|
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
tests: mark tests relying on the current default for `init.defaultBranch`
In addition to the manual adjustment to let the `linux-gcc` CI job run
the test suite with `master` and then with `main`, this patch makes sure
that GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME is set in all test scripts
that currently rely on the initial branch name being `master by default.
To determine which test scripts to mark up, the first step was to
force-set the default branch name to `master` in
- all test scripts that contain the keyword `master`,
- t4211, which expects `t/t4211/history.export` with a hard-coded ref to
initialize the default branch,
- t5560 because it sources `t/t556x_common` which uses `master`,
- t8002 and t8012 because both source `t/annotate-tests.sh` which also
uses `master`)
This trick was performed by this command:
$ sed -i '/^ *\. \.\/\(test-lib\|lib-\(bash\|cvs\|git-svn\)\|gitweb-lib\)\.sh$/i\
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master\
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\
' $(git grep -l master t/t[0-9]*.sh) \
t/t4211*.sh t/t5560*.sh t/t8002*.sh t/t8012*.sh
After that, careful, manual inspection revealed that some of the test
scripts containing the needle `master` do not actually rely on a
specific default branch name: either they mention `master` only in a
comment, or they initialize that branch specificially, or they do not
actually refer to the current default branch. Therefore, the
aforementioned modification was undone in those test scripts thusly:
$ git checkout HEAD -- \
t/t0027-auto-crlf.sh t/t0060-path-utils.sh \
t/t1011-read-tree-sparse-checkout.sh \
t/t1305-config-include.sh t/t1309-early-config.sh \
t/t1402-check-ref-format.sh t/t1450-fsck.sh \
t/t2024-checkout-dwim.sh \
t/t2106-update-index-assume-unchanged.sh \
t/t3040-subprojects-basic.sh t/t3301-notes.sh \
t/t3308-notes-merge.sh t/t3423-rebase-reword.sh \
t/t3436-rebase-more-options.sh \
t/t4015-diff-whitespace.sh t/t4257-am-interactive.sh \
t/t5323-pack-redundant.sh t/t5401-update-hooks.sh \
t/t5511-refspec.sh t/t5526-fetch-submodules.sh \
t/t5529-push-errors.sh t/t5530-upload-pack-error.sh \
t/t5548-push-porcelain.sh \
t/t5552-skipping-fetch-negotiator.sh \
t/t5572-pull-submodule.sh t/t5608-clone-2gb.sh \
t/t5614-clone-submodules-shallow.sh \
t/t7508-status.sh t/t7606-merge-custom.sh \
t/t9302-fast-import-unpack-limit.sh
We excluded one set of test scripts in these commands, though: the range
of `git p4` tests. The reason? `git p4` stores the (foreign) remote
branch in the branch called `p4/master`, which is obviously not the
default branch. Manual analysis revealed that only five of these tests
actually require a specific default branch name to pass; They were
modified thusly:
$ sed -i '/^ *\. \.\/lib-git-p4\.sh$/i\
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master\
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\
' t/t980[0167]*.sh t/t9811*.sh
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-18 23:44:19 +00:00
|
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
|
|
|
2024-04-22 22:54:18 +00:00
|
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
2008-02-13 10:50:51 +00:00
|
|
|
. ./test-lib.sh
|
2017-10-03 13:42:15 +00:00
|
|
|
. "$TEST_DIRECTORY"/lib-terminal.sh
|
2008-02-13 10:50:51 +00:00
|
|
|
|
2024-04-29 18:37:12 +00:00
|
|
|
SP=" "
|
|
|
|
|
2018-03-01 10:50:58 +00:00
|
|
|
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"
|
|
|
|
}
|
|
|
|
|
2019-12-06 13:08:20 +00:00
|
|
|
# This function uses a trick to manipulate the interactive add to use color:
|
|
|
|
# the `want_color()` function special-cases the situation where a pager was
|
|
|
|
# spawned and Git now wants to output colored text: to detect that situation,
|
|
|
|
# the environment variable `GIT_PAGER_IN_USE` is set. However, color is
|
|
|
|
# suppressed despite that environment variable if the `TERM` variable
|
|
|
|
# indicates a dumb terminal, so we set that variable, too.
|
|
|
|
|
|
|
|
force_color () {
|
2020-07-07 06:04:34 +00:00
|
|
|
# The first element of $@ may be a shell function, as a result POSIX
|
|
|
|
# does not guarantee that "one-shot assignment" will not persist after
|
|
|
|
# the function call. Thus, we prevent these variables from escaping
|
|
|
|
# this function's context with this subshell.
|
|
|
|
(
|
|
|
|
GIT_PAGER_IN_USE=true &&
|
|
|
|
TERM=vt100 &&
|
|
|
|
export GIT_PAGER_IN_USE TERM &&
|
|
|
|
"$@"
|
|
|
|
)
|
2019-12-06 13:08:20 +00:00
|
|
|
}
|
|
|
|
|
2023-02-06 22:58:56 +00:00
|
|
|
test_expect_success 'warn about add.interactive.useBuiltin' '
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
warning: the add.interactive.useBuiltin setting has been removed!
|
|
|
|
See its entry in '\''git help config'\'' for details.
|
|
|
|
EOF
|
2024-04-29 18:37:03 +00:00
|
|
|
echo "No changes." >expect.out &&
|
2023-02-06 22:58:56 +00:00
|
|
|
|
|
|
|
for v in = =true =false
|
|
|
|
do
|
|
|
|
git -c "add.interactive.useBuiltin$v" add -p >out 2>actual &&
|
2024-04-29 18:37:03 +00:00
|
|
|
test_cmp expect.out out &&
|
2023-02-06 22:58:56 +00:00
|
|
|
test_cmp expect actual || return 1
|
|
|
|
done
|
|
|
|
'
|
|
|
|
|
2024-04-29 18:37:12 +00:00
|
|
|
test_expect_success 'unknown command' '
|
|
|
|
test_when_finished "git reset --hard; rm -f command" &&
|
|
|
|
echo W >command &&
|
|
|
|
git add -N command &&
|
|
|
|
git diff command >expect &&
|
|
|
|
cat >>expect <<-EOF &&
|
|
|
|
(1/1) Stage addition [y,n,q,a,d,e,p,?]? Unknown command ${SQ}W${SQ} (use ${SQ}?${SQ} for help)
|
|
|
|
(1/1) Stage addition [y,n,q,a,d,e,p,?]?$SP
|
|
|
|
EOF
|
|
|
|
git add -p -- command <command >actual 2>&1 &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup (initial)' '
|
2008-02-13 10:50:51 +00:00
|
|
|
echo content >file &&
|
|
|
|
git add file &&
|
|
|
|
echo more >>file &&
|
|
|
|
echo lines >>file
|
|
|
|
'
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'status works (initial)' '
|
2008-02-13 10:50:51 +00:00
|
|
|
git add -i </dev/null >output &&
|
|
|
|
grep "+1/-0 *+2/-0 file" output
|
|
|
|
'
|
2010-08-13 20:40:05 +00:00
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup expected' '
|
2018-02-19 11:29:03 +00:00
|
|
|
cat >expected <<-\EOF
|
|
|
|
new file mode 100644
|
|
|
|
index 0000000..d95f3ad
|
|
|
|
--- /dev/null
|
|
|
|
+++ b/file
|
|
|
|
@@ -0,0 +1 @@
|
|
|
|
+content
|
|
|
|
EOF
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'diff works (initial)' '
|
2018-07-02 00:23:42 +00:00
|
|
|
test_write_lines d 1 | git add -i >output &&
|
2008-02-13 10:50:51 +00:00
|
|
|
sed -ne "/new file/,/content/p" <output >diff &&
|
2018-03-01 10:50:58 +00:00
|
|
|
diff_cmp expected diff
|
2008-02-13 10:50:51 +00:00
|
|
|
'
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'revert works (initial)' '
|
2008-02-13 10:50:51 +00:00
|
|
|
git add file &&
|
2018-07-02 00:23:42 +00:00
|
|
|
test_write_lines r 1 | git add -i &&
|
2008-02-13 10:50:51 +00:00
|
|
|
git ls-files >output &&
|
|
|
|
! grep . output
|
|
|
|
'
|
|
|
|
|
2020-01-16 08:33:07 +00:00
|
|
|
test_expect_success 'add untracked (multiple)' '
|
|
|
|
test_when_finished "git reset && rm [1-9]" &&
|
|
|
|
touch $(test_seq 9) &&
|
|
|
|
test_write_lines a "2-5 8-" | git add -i -- [1-9] &&
|
|
|
|
test_write_lines 2 3 4 5 8 9 >expected &&
|
|
|
|
git ls-files [1-9] >output &&
|
|
|
|
test_cmp expected output
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup (commit)' '
|
2008-02-13 10:50:51 +00:00
|
|
|
echo baseline >file &&
|
|
|
|
git add file &&
|
|
|
|
git commit -m commit &&
|
|
|
|
echo content >>file &&
|
|
|
|
git add file &&
|
|
|
|
echo more >>file &&
|
|
|
|
echo lines >>file
|
|
|
|
'
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'status works (commit)' '
|
2008-02-13 10:50:51 +00:00
|
|
|
git add -i </dev/null >output &&
|
|
|
|
grep "+1/-0 *+2/-0 file" output
|
|
|
|
'
|
2010-08-13 20:40:05 +00:00
|
|
|
|
2022-06-28 22:22:44 +00:00
|
|
|
test_expect_success 'update can stage deletions' '
|
|
|
|
>to-delete &&
|
|
|
|
git add to-delete &&
|
|
|
|
rm to-delete &&
|
|
|
|
test_write_lines u t "" | git add -i &&
|
|
|
|
git ls-files to-delete >output &&
|
|
|
|
test_must_be_empty output
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup expected' '
|
2018-02-19 11:29:03 +00:00
|
|
|
cat >expected <<-\EOF
|
|
|
|
index 180b47c..b6f2c08 100644
|
|
|
|
--- a/file
|
|
|
|
+++ b/file
|
|
|
|
@@ -1 +1,2 @@
|
|
|
|
baseline
|
|
|
|
+content
|
|
|
|
EOF
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'diff works (commit)' '
|
2018-07-02 00:23:42 +00:00
|
|
|
test_write_lines d 1 | git add -i >output &&
|
2008-02-13 10:50:51 +00:00
|
|
|
sed -ne "/^index/,/content/p" <output >diff &&
|
2018-03-01 10:50:58 +00:00
|
|
|
diff_cmp expected diff
|
2008-02-13 10:50:51 +00:00
|
|
|
'
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'revert works (commit)' '
|
2008-02-13 10:50:51 +00:00
|
|
|
git add file &&
|
2018-07-02 00:23:42 +00:00
|
|
|
test_write_lines r 1 | git add -i &&
|
2008-02-13 10:50:51 +00:00
|
|
|
git add -i </dev/null >output &&
|
|
|
|
grep "unchanged *+3/-0 file" output
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup expected' '
|
2018-02-19 11:29:03 +00:00
|
|
|
cat >expected <<-\EOF
|
|
|
|
EOF
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'dummy edit works' '
|
2018-02-19 11:29:04 +00:00
|
|
|
test_set_editor : &&
|
2018-07-02 00:23:42 +00:00
|
|
|
test_write_lines e a | git add -p &&
|
2008-07-02 22:00:00 +00:00
|
|
|
git diff > diff &&
|
2018-03-01 10:50:58 +00:00
|
|
|
diff_cmp expected diff
|
2008-07-02 22:00:00 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup patch' '
|
2018-02-19 11:29:03 +00:00
|
|
|
cat >patch <<-\EOF
|
|
|
|
@@ -1,1 +1,4 @@
|
|
|
|
this
|
|
|
|
+patch
|
|
|
|
-does not
|
|
|
|
apply
|
|
|
|
EOF
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup fake editor' '
|
2018-02-19 11:29:04 +00:00
|
|
|
write_script "fake_editor.sh" <<-\EOF &&
|
2018-02-19 11:29:03 +00:00
|
|
|
mv -f "$1" oldpatch &&
|
|
|
|
mv -f patch "$1"
|
|
|
|
EOF
|
2010-08-13 20:40:05 +00:00
|
|
|
test_set_editor "$(pwd)/fake_editor.sh"
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'bad edit rejected' '
|
2008-07-02 22:00:00 +00:00
|
|
|
git reset &&
|
2018-07-02 00:23:42 +00:00
|
|
|
test_write_lines e n d | git add -p >output &&
|
2008-07-02 22:00:00 +00:00
|
|
|
grep "hunk does not apply" output
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup patch' '
|
2018-02-19 11:29:03 +00:00
|
|
|
cat >patch <<-\EOF
|
|
|
|
this patch
|
|
|
|
is garbage
|
|
|
|
EOF
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'garbage edit rejected' '
|
2008-07-02 22:00:00 +00:00
|
|
|
git reset &&
|
2018-07-02 00:23:42 +00:00
|
|
|
test_write_lines e n d | git add -p >output &&
|
2008-07-02 22:00:00 +00:00
|
|
|
grep "hunk does not apply" output
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup patch' '
|
2018-02-19 11:29:03 +00:00
|
|
|
cat >patch <<-\EOF
|
|
|
|
@@ -1,0 +1,0 @@
|
|
|
|
baseline
|
|
|
|
+content
|
|
|
|
+newcontent
|
|
|
|
+lines
|
|
|
|
EOF
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup expected' '
|
2018-02-19 11:29:03 +00:00
|
|
|
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
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'real edit works' '
|
2018-07-02 00:23:42 +00:00
|
|
|
test_write_lines e n d | git add -p &&
|
2008-07-02 22:00:00 +00:00
|
|
|
git diff >output &&
|
2018-03-01 10:50:58 +00:00
|
|
|
diff_cmp expected output
|
2008-07-02 22:00:00 +00:00
|
|
|
'
|
|
|
|
|
2018-06-11 09:46:02 +00:00
|
|
|
test_expect_success 'setup file' '
|
|
|
|
test_write_lines a "" b "" c >file &&
|
|
|
|
git add file &&
|
|
|
|
test_write_lines a "" d "" c >file
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'setup patch' '
|
|
|
|
NULL="" &&
|
|
|
|
cat >patch <<-EOF
|
|
|
|
@@ -1,4 +1,4 @@
|
|
|
|
a
|
|
|
|
$NULL
|
|
|
|
-b
|
|
|
|
+f
|
|
|
|
$SP
|
|
|
|
c
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'setup expected' '
|
|
|
|
cat >expected <<-EOF
|
|
|
|
diff --git a/file b/file
|
|
|
|
index b5dd6c9..f910ae9 100644
|
|
|
|
--- a/file
|
|
|
|
+++ b/file
|
|
|
|
@@ -1,5 +1,5 @@
|
|
|
|
a
|
|
|
|
$SP
|
|
|
|
-f
|
|
|
|
+d
|
|
|
|
$SP
|
|
|
|
c
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'edit can strip spaces from empty context lines' '
|
|
|
|
test_write_lines e n q | git add -p 2>error &&
|
|
|
|
test_must_be_empty error &&
|
|
|
|
git diff >output &&
|
|
|
|
diff_cmp expected output
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'skip files similarly as commit -a' '
|
2009-10-10 15:51:45 +00:00
|
|
|
git reset &&
|
|
|
|
echo file >.gitignore &&
|
|
|
|
echo changed >file &&
|
|
|
|
echo y | git add -p file &&
|
|
|
|
git diff >output &&
|
|
|
|
git reset &&
|
|
|
|
git commit -am commit &&
|
|
|
|
git diff >expected &&
|
2018-03-01 10:50:58 +00:00
|
|
|
diff_cmp expected output &&
|
2009-10-10 15:51:45 +00:00
|
|
|
git reset --hard HEAD^
|
|
|
|
'
|
|
|
|
rm -f .gitignore
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success FILEMODE 'patch does not affect mode' '
|
2008-03-27 07:30:43 +00:00
|
|
|
git reset --hard &&
|
|
|
|
echo content >>file &&
|
|
|
|
chmod +x file &&
|
2008-03-27 07:32:25 +00:00
|
|
|
printf "n\\ny\\n" | git add -p &&
|
2008-03-27 07:30:43 +00:00
|
|
|
git show :file | grep content &&
|
|
|
|
git diff file | grep "new mode"
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success FILEMODE 'stage mode but not hunk' '
|
2008-03-27 07:32:25 +00:00
|
|
|
git reset --hard &&
|
|
|
|
echo content >>file &&
|
|
|
|
chmod +x file &&
|
|
|
|
printf "y\\nn\\n" | git add -p &&
|
|
|
|
git diff --cached file | grep "new mode" &&
|
|
|
|
git diff file | grep "+content"
|
|
|
|
'
|
|
|
|
|
git add -p: demonstrate failure when staging both mode and hunk
When trying to stage changes to file which has also pending `chmod +x`,
`git add -p` produces lots of 'Use of uninitialized value ...' warnings
and fails to do the job:
$ echo content >> file
$ chmod +x file
$ git add -p
diff --git a/file b/file
index e69de29..d95f3ad
--- a/file
+++ b/file
old mode 100644
new mode 100755
Stage mode change [y,n,q,a,d,/,j,J,g,?]? y
@@ -0,0 +1 @@
+content
Stage this hunk [y,n,q,a,d,/,K,g,e,?]? y
Use of uninitialized value $o_ofs in addition (+) at .../git-add--interactive line 776.
Use of uninitialized value $ofs in numeric le (<=) at .../git-add--interactive line 806.
Use of uninitialized value $o0_ofs in concatenation (.) or string at .../git-add--interactive line 830.
Use of uninitialized value $n0_ofs in concatenation (.) or string at .../git-add--interactive line 830.
Use of uninitialized value $o_ofs in addition (+) at .../git-add--interactive line 776.
fatal: corrupt patch at line 5
diff --git a/file b/file
index e69de29..d95f3ad
--- a/file
+++ b/file
@@ -,0 + @@
+content
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-08-15 12:26:49 +00:00
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success FILEMODE 'stage mode and hunk' '
|
git add -p: demonstrate failure when staging both mode and hunk
When trying to stage changes to file which has also pending `chmod +x`,
`git add -p` produces lots of 'Use of uninitialized value ...' warnings
and fails to do the job:
$ echo content >> file
$ chmod +x file
$ git add -p
diff --git a/file b/file
index e69de29..d95f3ad
--- a/file
+++ b/file
old mode 100644
new mode 100755
Stage mode change [y,n,q,a,d,/,j,J,g,?]? y
@@ -0,0 +1 @@
+content
Stage this hunk [y,n,q,a,d,/,K,g,e,?]? y
Use of uninitialized value $o_ofs in addition (+) at .../git-add--interactive line 776.
Use of uninitialized value $ofs in numeric le (<=) at .../git-add--interactive line 806.
Use of uninitialized value $o0_ofs in concatenation (.) or string at .../git-add--interactive line 830.
Use of uninitialized value $n0_ofs in concatenation (.) or string at .../git-add--interactive line 830.
Use of uninitialized value $o_ofs in addition (+) at .../git-add--interactive line 776.
fatal: corrupt patch at line 5
diff --git a/file b/file
index e69de29..d95f3ad
--- a/file
+++ b/file
@@ -,0 + @@
+content
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-08-15 12:26:49 +00:00
|
|
|
git reset --hard &&
|
|
|
|
echo content >>file &&
|
|
|
|
chmod +x file &&
|
|
|
|
printf "y\\ny\\n" | git add -p &&
|
2023-02-06 22:44:33 +00:00
|
|
|
git diff --cached file >out &&
|
|
|
|
grep "new mode" out &&
|
|
|
|
grep "+content" out &&
|
|
|
|
git diff file >out &&
|
|
|
|
test_must_be_empty out
|
git add -p: demonstrate failure when staging both mode and hunk
When trying to stage changes to file which has also pending `chmod +x`,
`git add -p` produces lots of 'Use of uninitialized value ...' warnings
and fails to do the job:
$ echo content >> file
$ chmod +x file
$ git add -p
diff --git a/file b/file
index e69de29..d95f3ad
--- a/file
+++ b/file
old mode 100644
new mode 100755
Stage mode change [y,n,q,a,d,/,j,J,g,?]? y
@@ -0,0 +1 @@
+content
Stage this hunk [y,n,q,a,d,/,K,g,e,?]? y
Use of uninitialized value $o_ofs in addition (+) at .../git-add--interactive line 776.
Use of uninitialized value $ofs in numeric le (<=) at .../git-add--interactive line 806.
Use of uninitialized value $o0_ofs in concatenation (.) or string at .../git-add--interactive line 830.
Use of uninitialized value $n0_ofs in concatenation (.) or string at .../git-add--interactive line 830.
Use of uninitialized value $o_ofs in addition (+) at .../git-add--interactive line 776.
fatal: corrupt patch at line 5
diff --git a/file b/file
index e69de29..d95f3ad
--- a/file
+++ b/file
@@ -,0 + @@
+content
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-08-15 12:26:49 +00:00
|
|
|
'
|
|
|
|
|
2008-05-20 21:59:32 +00:00
|
|
|
# end of tests disabled when filemode is not usable
|
2008-03-27 07:32:25 +00:00
|
|
|
|
2019-12-06 13:08:21 +00:00
|
|
|
test_expect_success 'different prompts for mode change/deleted' '
|
|
|
|
git reset --hard &&
|
|
|
|
>file &&
|
|
|
|
>deleted &&
|
|
|
|
git add --chmod=+x file deleted &&
|
|
|
|
echo changed >file &&
|
|
|
|
rm deleted &&
|
|
|
|
test_write_lines n n n |
|
|
|
|
git -c core.filemode=true add -p >actual &&
|
|
|
|
sed -n "s/^\(([0-9/]*) Stage .*?\).*/\1/p" actual >actual.filtered &&
|
|
|
|
cat >expect <<-\EOF &&
|
2024-03-29 03:58:28 +00:00
|
|
|
(1/1) Stage deletion [y,n,q,a,d,p,?]?
|
|
|
|
(1/2) Stage mode change [y,n,q,a,d,j,J,g,/,p,?]?
|
|
|
|
(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]?
|
2019-12-06 13:08:21 +00:00
|
|
|
EOF
|
|
|
|
test_cmp expect actual.filtered
|
|
|
|
'
|
|
|
|
|
2019-12-06 13:08:22 +00:00
|
|
|
test_expect_success 'correct message when there is nothing to do' '
|
|
|
|
git reset --hard &&
|
2024-04-29 18:37:03 +00:00
|
|
|
git add -p >out &&
|
|
|
|
test_grep "No changes" out &&
|
2019-12-06 13:08:22 +00:00
|
|
|
printf "\\0123" >binary &&
|
|
|
|
git add binary &&
|
|
|
|
printf "\\0abc" >binary &&
|
2024-04-29 18:37:03 +00:00
|
|
|
git add -p >out &&
|
|
|
|
test_grep "Only binary files changed" out
|
2019-12-06 13:08:22 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup again' '
|
2009-05-25 12:07:55 +00:00
|
|
|
git reset --hard &&
|
|
|
|
test_chmod +x file &&
|
2022-01-11 11:12:10 +00:00
|
|
|
echo content >>file &&
|
|
|
|
test_write_lines A B C D>file2 &&
|
|
|
|
git add file2
|
2009-05-25 12:07:55 +00:00
|
|
|
'
|
|
|
|
|
2009-05-16 03:10:19 +00:00
|
|
|
# Write the patch file with a new line at the top and bottom
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup patch' '
|
2018-02-19 11:29:03 +00:00
|
|
|
cat >patch <<-\EOF
|
|
|
|
index 180b47c..b6f2c08 100644
|
|
|
|
--- a/file
|
|
|
|
+++ b/file
|
|
|
|
@@ -1,2 +1,4 @@
|
|
|
|
+firstline
|
|
|
|
baseline
|
|
|
|
content
|
|
|
|
+lastline
|
2018-03-05 10:56:29 +00:00
|
|
|
\ No newline at end of file
|
2022-01-11 11:12:10 +00:00
|
|
|
diff --git a/file2 b/file2
|
|
|
|
index 8422d40..35b930a 100644
|
|
|
|
--- a/file2
|
|
|
|
+++ b/file2
|
|
|
|
@@ -1,4 +1,5 @@
|
|
|
|
-A
|
|
|
|
+Z
|
|
|
|
B
|
|
|
|
+Y
|
|
|
|
C
|
|
|
|
-D
|
|
|
|
+X
|
2018-02-19 11:29:03 +00:00
|
|
|
EOF
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
|
|
|
|
2018-03-05 10:56:29 +00:00
|
|
|
# Expected output, diff is similar to the patch but w/ diff at the top
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup expected' '
|
2018-03-05 10:56:29 +00:00
|
|
|
echo diff --git a/file b/file >expected &&
|
2022-01-11 11:12:10 +00:00
|
|
|
sed -e "/^index 180b47c/s/ 100644/ 100755/" \
|
|
|
|
-e /1,5/s//1,4/ \
|
|
|
|
-e /Y/d patch >>expected &&
|
2018-03-05 10:56:29 +00:00
|
|
|
cat >expected-output <<-\EOF
|
2018-02-19 11:29:03 +00:00
|
|
|
--- a/file
|
|
|
|
+++ b/file
|
|
|
|
@@ -1,2 +1,4 @@
|
|
|
|
+firstline
|
|
|
|
baseline
|
|
|
|
content
|
|
|
|
+lastline
|
2018-03-05 10:56:29 +00:00
|
|
|
\ 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
|
2022-01-11 11:12:10 +00:00
|
|
|
--- a/file2
|
|
|
|
+++ b/file2
|
|
|
|
@@ -1,4 +1,5 @@
|
|
|
|
-A
|
|
|
|
+Z
|
|
|
|
B
|
|
|
|
+Y
|
|
|
|
C
|
|
|
|
-D
|
|
|
|
+X
|
|
|
|
@@ -1,2 +1,2 @@
|
|
|
|
-A
|
|
|
|
+Z
|
|
|
|
B
|
|
|
|
@@ -2,2 +2,3 @@
|
|
|
|
B
|
|
|
|
+Y
|
|
|
|
C
|
|
|
|
@@ -3,2 +4,2 @@
|
|
|
|
C
|
|
|
|
-D
|
|
|
|
+X
|
2018-02-19 11:29:03 +00:00
|
|
|
EOF
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
|
|
|
|
2009-05-16 03:10:19 +00:00
|
|
|
# Test splitting the first patch, then adding both
|
2021-02-11 01:53:51 +00:00
|
|
|
test_expect_success 'add first line works' '
|
2009-05-16 03:10:19 +00:00
|
|
|
git commit -am "clear local changes" &&
|
|
|
|
git apply patch &&
|
2022-01-11 11:12:10 +00:00
|
|
|
test_write_lines s y y s y n y | git add -p 2>error >raw-output &&
|
|
|
|
sed -n -e "s/^([1-9]\/[1-9]) Stage this hunk[^@]*\(@@ .*\)/\1/" \
|
2022-01-11 11:12:09 +00:00
|
|
|
-e "/^[-+@ \\\\]"/p raw-output >output &&
|
2018-03-05 10:56:29 +00:00
|
|
|
test_must_be_empty error &&
|
|
|
|
git diff --cached >diff &&
|
|
|
|
diff_cmp expected diff &&
|
|
|
|
test_cmp expected-output output
|
2009-05-16 03:10:19 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup expected' '
|
2018-02-19 11:29:03 +00:00
|
|
|
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
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'deleting a non-empty file' '
|
2009-12-08 07:49:35 +00:00
|
|
|
git reset --hard &&
|
|
|
|
echo content >non-empty &&
|
|
|
|
git add non-empty &&
|
|
|
|
git commit -m non-empty &&
|
|
|
|
rm non-empty &&
|
|
|
|
echo y | git add -p non-empty &&
|
|
|
|
git diff --cached >diff &&
|
2018-03-01 10:50:58 +00:00
|
|
|
diff_cmp expected diff
|
2009-12-08 07:49:35 +00:00
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'setup expected' '
|
2018-02-19 11:29:03 +00:00
|
|
|
cat >expected <<-\EOF
|
|
|
|
diff --git a/empty b/empty
|
|
|
|
deleted file mode 100644
|
|
|
|
index e69de29..0000000
|
|
|
|
EOF
|
2010-08-13 20:40:05 +00:00
|
|
|
'
|
2009-10-28 00:52:57 +00:00
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'deleting an empty file' '
|
2009-10-28 00:52:57 +00:00
|
|
|
git reset --hard &&
|
|
|
|
> empty &&
|
|
|
|
git add empty &&
|
|
|
|
git commit -m empty &&
|
|
|
|
rm empty &&
|
|
|
|
echo y | git add -p empty &&
|
|
|
|
git diff --cached >diff &&
|
2018-03-01 10:50:58 +00:00
|
|
|
diff_cmp expected diff
|
2009-10-28 00:52:57 +00:00
|
|
|
'
|
|
|
|
|
2020-05-27 21:09:06 +00:00
|
|
|
test_expect_success 'adding an empty file' '
|
|
|
|
git init added &&
|
|
|
|
(
|
|
|
|
cd added &&
|
|
|
|
test_commit initial &&
|
|
|
|
>empty &&
|
|
|
|
git add empty &&
|
|
|
|
test_tick &&
|
|
|
|
git commit -m empty &&
|
|
|
|
git tag added-file &&
|
|
|
|
git reset --hard HEAD^ &&
|
|
|
|
test_path_is_missing empty &&
|
|
|
|
|
|
|
|
echo y | git checkout -p added-file -- >actual &&
|
|
|
|
test_path_is_file empty &&
|
2023-10-31 05:23:30 +00:00
|
|
|
test_grep "Apply addition to index and worktree" actual
|
2020-05-27 21:09:06 +00:00
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'split hunk setup' '
|
2011-04-29 19:41:16 +00:00
|
|
|
git reset --hard &&
|
2018-02-19 11:29:04 +00:00
|
|
|
test_write_lines 10 20 30 40 50 60 >test &&
|
2011-04-29 19:41:16 +00:00
|
|
|
git add test &&
|
|
|
|
test_tick &&
|
|
|
|
git commit -m test &&
|
|
|
|
|
2018-02-19 11:29:04 +00:00
|
|
|
test_write_lines 10 15 20 21 22 23 24 30 40 50 60 >test
|
2011-04-29 19:41:16 +00:00
|
|
|
'
|
|
|
|
|
2019-12-13 08:08:02 +00:00
|
|
|
test_expect_success 'goto hunk' '
|
|
|
|
test_when_finished "git reset" &&
|
|
|
|
tr _ " " >expect <<-EOF &&
|
2024-03-29 03:58:28 +00:00
|
|
|
(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? + 1: -1,2 +1,3 +15
|
2019-12-13 08:08:02 +00:00
|
|
|
_ 2: -2,4 +3,8 +21
|
|
|
|
go to which hunk? @@ -1,2 +1,3 @@
|
|
|
|
_10
|
|
|
|
+15
|
|
|
|
_20
|
2024-03-29 03:58:28 +00:00
|
|
|
(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
|
2019-12-13 08:08:02 +00:00
|
|
|
EOF
|
|
|
|
test_write_lines s y g 1 | git add -p >actual &&
|
|
|
|
tail -n 7 <actual >actual.trimmed &&
|
|
|
|
test_cmp expect actual.trimmed
|
|
|
|
'
|
|
|
|
|
2019-12-13 08:08:03 +00:00
|
|
|
test_expect_success 'navigate to hunk via regex' '
|
|
|
|
test_when_finished "git reset" &&
|
|
|
|
tr _ " " >expect <<-EOF &&
|
2024-03-29 03:58:28 +00:00
|
|
|
(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? @@ -1,2 +1,3 @@
|
2019-12-13 08:08:03 +00:00
|
|
|
_10
|
|
|
|
+15
|
|
|
|
_20
|
2024-03-29 03:58:28 +00:00
|
|
|
(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
|
2019-12-13 08:08:03 +00:00
|
|
|
EOF
|
|
|
|
test_write_lines s y /1,2 | git add -p >actual &&
|
|
|
|
tail -n 5 <actual >actual.trimmed &&
|
|
|
|
test_cmp expect actual.trimmed
|
|
|
|
'
|
|
|
|
|
2013-08-24 20:13:32 +00:00
|
|
|
test_expect_success 'split hunk "add -p (edit)"' '
|
2011-04-29 19:41:16 +00:00
|
|
|
# Split, say Edit and do nothing. Then:
|
|
|
|
#
|
|
|
|
# 1. Broken version results in a patch that does not apply and
|
|
|
|
# only takes [y/n] (edit again) so the first q is discarded
|
|
|
|
# and then n attempts to discard the edit. Repeat q enough
|
|
|
|
# times to get out.
|
|
|
|
#
|
|
|
|
# 2. Correct version applies the (not)edited version, and asks
|
2013-04-11 22:36:10 +00:00
|
|
|
# about the next hunk, against which we say q and program
|
2011-04-29 19:41:16 +00:00
|
|
|
# exits.
|
2015-04-16 07:02:27 +00:00
|
|
|
printf "%s\n" s e q n q q |
|
2011-04-29 19:41:16 +00:00
|
|
|
EDITOR=: git add -p &&
|
|
|
|
git diff >actual &&
|
|
|
|
! grep "^+15" actual
|
|
|
|
'
|
|
|
|
|
2023-02-06 22:58:56 +00:00
|
|
|
test_expect_success 'split hunk "add -p (no, yes, edit)"' '
|
2018-02-19 11:29:04 +00:00
|
|
|
test_write_lines 5 10 20 21 30 31 40 50 60 >test &&
|
2015-04-16 07:02:28 +00:00
|
|
|
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.
|
|
|
|
printf "%s\n" s n y e q n q q |
|
|
|
|
EDITOR=: git add -p 2>error &&
|
|
|
|
test_must_be_empty error &&
|
|
|
|
git diff >actual &&
|
|
|
|
! grep "^+31" actual
|
|
|
|
'
|
|
|
|
|
built-in add -p: implement the hunk splitting feature
If this developer's workflow is any indication, then this is *the* most
useful feature of Git's interactive `add `command.
Note: once again, this is not a verbatim conversion from the Perl code
to C: the `hunk_splittable()` function, for example, essentially did all
the work of splitting the hunk, just to find out whether more than one
hunk would have been the result (and then tossed that result into the
trash). In C we instead count the number of resulting hunks (without
actually doing the work of splitting, but just counting the transitions
from non-context lines to context lines), and store that information
with the hunk, and we do that *while* parsing the diff in the first
place.
Another deviation: the built-in `git add -p` was designed with a single
strbuf holding the diff (and another one holding the colored diff, if
that one was asked for) in mind, and hunks essentially store just the
start and end offsets pointing into that strbuf. As a consequence, when
we split hunks, we now use a special mode where the hunk header is
generated dynamically, and only the rest of the hunk is stored using
such start/end offsets. This way, we also avoid the frequent
formatting/re-parsing of the hunk header of the Perl version.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-12-13 08:07:58 +00:00
|
|
|
test_expect_success 'split hunk with incomplete line at end' '
|
|
|
|
git reset --hard &&
|
|
|
|
printf "missing LF" >>test &&
|
|
|
|
git add test &&
|
|
|
|
test_write_lines before 10 20 30 40 50 60 70 >test &&
|
|
|
|
git grep --cached missing &&
|
|
|
|
test_write_lines s n y q | git add -p &&
|
|
|
|
test_must_fail git grep --cached missing &&
|
|
|
|
git grep before &&
|
|
|
|
test_must_fail git grep --cached before
|
|
|
|
'
|
|
|
|
|
2023-02-06 22:58:56 +00:00
|
|
|
test_expect_success 'edit, adding lines to the first hunk' '
|
2019-12-06 13:08:19 +00:00
|
|
|
test_write_lines 10 11 20 30 40 50 51 60 >test &&
|
|
|
|
git reset &&
|
|
|
|
tr _ " " >patch <<-EOF &&
|
|
|
|
@@ -1,5 +1,6 @@
|
|
|
|
_10
|
|
|
|
+11
|
|
|
|
+12
|
|
|
|
_20
|
|
|
|
+21
|
|
|
|
+22
|
|
|
|
_30
|
|
|
|
EOF
|
|
|
|
# test sequence is s(plit), e(dit), n(o)
|
|
|
|
# q n q q is there to make sure we exit at the end.
|
|
|
|
printf "%s\n" s e n q n q q |
|
|
|
|
EDITOR=./fake_editor.sh git add -p 2>error &&
|
|
|
|
test_must_be_empty error &&
|
|
|
|
git diff --cached >actual &&
|
|
|
|
grep "^+22" actual
|
|
|
|
'
|
|
|
|
|
add--interactive: ignore unmerged entries in patch mode
When "add -p" sees an unmerged entry, it shows the combined
diff and then immediately skips the hunk. This can be
confusing in a variety of ways, depending on whether there
are other changes to stage (in which case you get the
superfluous combined diff output in between other hunks) or
not (in which case you get the combined diff and the program
exits immediately, rather than seeing "No changes").
The current behavior was not planned, and is just what the
implementation happens to do. Instead, let's explicitly
remove unmerged entries from our list of modified files, and
print a warning that we are ignoring them.
We can cheaply find which entries are unmerged by adding
"--raw" output to the "diff-files --numstat" we already run.
There is one non-obvious thing we must change when parsing
this combined output. Before this patch, when we saw a
numstat line for a file that did not have index changes, we
would create a new record with 'unchanged' in the 'INDEX'
field. Because "--raw" comes before "--numstat", we must
move this special-case down to the raw-line case (and it is
sufficient to move it rather than handle it in both places,
since any file which has a --numstat will also have a --raw
entry).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-05 12:30:08 +00:00
|
|
|
test_expect_success 'patch mode ignores unmerged entries' '
|
|
|
|
git reset --hard &&
|
|
|
|
test_commit conflict &&
|
|
|
|
test_commit non-conflict &&
|
|
|
|
git checkout -b side &&
|
|
|
|
test_commit side conflict.t &&
|
2020-11-18 23:44:26 +00:00
|
|
|
git checkout main &&
|
|
|
|
test_commit main conflict.t &&
|
add--interactive: ignore unmerged entries in patch mode
When "add -p" sees an unmerged entry, it shows the combined
diff and then immediately skips the hunk. This can be
confusing in a variety of ways, depending on whether there
are other changes to stage (in which case you get the
superfluous combined diff output in between other hunks) or
not (in which case you get the combined diff and the program
exits immediately, rather than seeing "No changes").
The current behavior was not planned, and is just what the
implementation happens to do. Instead, let's explicitly
remove unmerged entries from our list of modified files, and
print a warning that we are ignoring them.
We can cheaply find which entries are unmerged by adding
"--raw" output to the "diff-files --numstat" we already run.
There is one non-obvious thing we must change when parsing
this combined output. Before this patch, when we saw a
numstat line for a file that did not have index changes, we
would create a new record with 'unchanged' in the 'INDEX'
field. Because "--raw" comes before "--numstat", we must
move this special-case down to the raw-line case (and it is
sufficient to move it rather than handle it in both places,
since any file which has a --numstat will also have a --raw
entry).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-05 12:30:08 +00:00
|
|
|
test_must_fail git merge side &&
|
|
|
|
echo changed >non-conflict.t &&
|
|
|
|
echo y | git add -p >output &&
|
|
|
|
! grep a/conflict.t output &&
|
|
|
|
cat >expected <<-\EOF &&
|
|
|
|
* Unmerged path conflict.t
|
|
|
|
diff --git a/non-conflict.t b/non-conflict.t
|
|
|
|
index f766221..5ea2ed4 100644
|
|
|
|
--- a/non-conflict.t
|
|
|
|
+++ b/non-conflict.t
|
|
|
|
@@ -1 +1 @@
|
|
|
|
-non-conflict
|
|
|
|
+changed
|
|
|
|
EOF
|
|
|
|
git diff --cached >diff &&
|
2018-03-01 10:50:58 +00:00
|
|
|
diff_cmp expected diff
|
add--interactive: ignore unmerged entries in patch mode
When "add -p" sees an unmerged entry, it shows the combined
diff and then immediately skips the hunk. This can be
confusing in a variety of ways, depending on whether there
are other changes to stage (in which case you get the
superfluous combined diff output in between other hunks) or
not (in which case you get the combined diff and the program
exits immediately, rather than seeing "No changes").
The current behavior was not planned, and is just what the
implementation happens to do. Instead, let's explicitly
remove unmerged entries from our list of modified files, and
print a warning that we are ignoring them.
We can cheaply find which entries are unmerged by adding
"--raw" output to the "diff-files --numstat" we already run.
There is one non-obvious thing we must change when parsing
this combined output. Before this patch, when we saw a
numstat line for a file that did not have index changes, we
would create a new record with 'unchanged' in the 'INDEX'
field. Because "--raw" comes before "--numstat", we must
move this special-case down to the raw-line case (and it is
sufficient to move it rather than handle it in both places,
since any file which has a --numstat will also have a --raw
entry).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-05 12:30:08 +00:00
|
|
|
'
|
|
|
|
|
2020-09-07 08:08:53 +00:00
|
|
|
test_expect_success 'index is refreshed after applying patch' '
|
|
|
|
git reset --hard &&
|
|
|
|
echo content >test &&
|
|
|
|
printf y | git add -p &&
|
|
|
|
git diff-files --exit-code
|
|
|
|
'
|
|
|
|
|
2019-12-06 13:08:20 +00:00
|
|
|
test_expect_success 'diffs can be colorized' '
|
color_parse_mem: allow empty color spec
Prior to c2f41bf52 (color.c: fix color_parse_mem() with
value_len == 0, 2017-01-19), the empty string was
interpreted as a color "reset". This was an accidental
outcome, and that commit turned it into an error.
However, scripts may pass the empty string as a default
value to "git config --get-color" to disable color when the
value is not defined. The git-add--interactive script does
this. As a result, the script is unusable since c2f41bf52
unless you have color.diff.plain defined (if it is defined,
then we don't parse the empty default at all).
Our test scripts didn't notice the recent breakage because
they run without a terminal, and thus without color. They
never hit this code path at all. And nobody noticed the
original buggy "reset" behavior, because it was effectively
a noop.
Let's fix the code to have an empty color name produce an
empty sequence of color codes. The tests need a few fixups:
- we'll add a new test in t4026 to cover this case. But
note that we need to tweak the color() helper. While
we're there, let's factor out the literal ANSI ESC
character. Otherwise it makes the diff quite hard to
read.
- we'll add a basic sanity-check in t4026 that "git add
-p" works at all when color is enabled. That would have
caught this bug, as well as any others that are specific
to the color code paths.
- 73c727d69 (log --graph: customize the graph lines with
config log.graphColors, 2017-01-19) added a test to
t4202 that checks some "invalid" graph color config.
Since ",, blue" before yielded only "blue" as valid, and
now yields "empty, empty, blue", we don't match the
expected output.
One way to fix this would be to change the expectation
to the empty color strings. But that makes the test much
less interesting, since we show only two graph lines,
both of which would be colorless.
Since the empty-string case is now covered by t4026,
let's remove them entirely here. They're just in the way
of the primary thing the test is supposed to be
checking.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-02-01 00:21:29 +00:00
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
echo content >test &&
|
2019-12-06 13:08:20 +00:00
|
|
|
printf y >y &&
|
|
|
|
force_color git add -p >output 2>&1 <y &&
|
add--interactive.perl: specify --no-color explicitly
Our color tests of "git add -p" do something a bit different from how a
normal user would behave: we pretend there's a pager in use, so that Git
thinks it's OK to write color to a non-tty stdout. This comes from
8539b46534 (t3701: avoid depending on the TTY prerequisite, 2019-12-06),
which allows us to avoid a lot of complicated mock-tty code.
However, those environment variables also make their way down to
sub-processes of add--interactive, including the "diff-files" we run to
generate the patches. As a result, it thinks it should output color,
too. So in t3701.50, for example, the machine-readable version of the
diff we get unexpectedly has color in it. We fail to parse it as a diff
and think there are zero hunks.
The test does still pass, though, because even with zero hunks we'll
dump the diff header (and we consider those unparseable bits to be part
of the header!), and so the output still has the expected color codes in
it. We don't notice that the command was totally broken and failed to
apply anything.
And in fact we're not really testing what we think we are about the
color, either. While add--interactive does correctly show the version we
got from running "diff-files --color", we'd also pass the test if we had
accidentally shown the machine-readable version, too, since it
(erroneously) has color codes in it.
One could argue that the test isn't very realistic; it's setting up this
"pretend there's a pager" situation to get around the tty restrictions
of the test environment. So one option would be to move back towards
using a real tty. But the behavior of add--interactive really is
user-visible here. If a user, for whatever reason, did run "git
--paginate add --patch" (perhaps because their pager is really a filter
or something), the command would totally fail to do anything useful.
Since we know that we don't want color in this output, let's just make
add--interactive more defensive, and say "--no-color" explicitly. It
doesn't hurt anything in the common case, but it fixes this odd case and
lets our test function properly again.
Note that the C builtin run_add_p() already passes --no-color, so it
doesn't need a similar fix. That will eventually replace this perl code
anyway, but the test change here will be valuable for ensuring that.
Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-09-07 08:17:39 +00:00
|
|
|
git diff-files --exit-code &&
|
color_parse_mem: allow empty color spec
Prior to c2f41bf52 (color.c: fix color_parse_mem() with
value_len == 0, 2017-01-19), the empty string was
interpreted as a color "reset". This was an accidental
outcome, and that commit turned it into an error.
However, scripts may pass the empty string as a default
value to "git config --get-color" to disable color when the
value is not defined. The git-add--interactive script does
this. As a result, the script is unusable since c2f41bf52
unless you have color.diff.plain defined (if it is defined,
then we don't parse the empty default at all).
Our test scripts didn't notice the recent breakage because
they run without a terminal, and thus without color. They
never hit this code path at all. And nobody noticed the
original buggy "reset" behavior, because it was effectively
a noop.
Let's fix the code to have an empty color name produce an
empty sequence of color codes. The tests need a few fixups:
- we'll add a new test in t4026 to cover this case. But
note that we need to tweak the color() helper. While
we're there, let's factor out the literal ANSI ESC
character. Otherwise it makes the diff quite hard to
read.
- we'll add a basic sanity-check in t4026 that "git add
-p" works at all when color is enabled. That would have
caught this bug, as well as any others that are specific
to the color code paths.
- 73c727d69 (log --graph: customize the graph lines with
config log.graphColors, 2017-01-19) added a test to
t4202 that checks some "invalid" graph color config.
Since ",, blue" before yielded only "blue" as valid, and
now yields "empty, empty, blue", we don't match the
expected output.
One way to fix this would be to change the expectation
to the empty color strings. But that makes the test much
less interesting, since we show only two graph lines,
both of which would be colorless.
Since the empty-string case is now covered by t4026,
let's remove them entirely here. They're just in the way
of the primary thing the test is supposed to be
checking.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-02-01 00:21:29 +00:00
|
|
|
|
|
|
|
# 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
|
|
|
|
'
|
|
|
|
|
2020-11-16 16:08:32 +00:00
|
|
|
test_expect_success 'colors can be overridden' '
|
|
|
|
git reset --hard &&
|
|
|
|
test_when_finished "git rm -f color-test" &&
|
|
|
|
test_write_lines context old more-context >color-test &&
|
|
|
|
git add color-test &&
|
|
|
|
test_write_lines context new more-context another-one >color-test &&
|
|
|
|
|
|
|
|
echo trigger an error message >input &&
|
|
|
|
force_color git \
|
|
|
|
-c color.interactive.error=blue \
|
|
|
|
add -i 2>err.raw <input &&
|
|
|
|
test_decode_color <err.raw >err &&
|
|
|
|
grep "<BLUE>Huh (trigger)?<RESET>" err &&
|
|
|
|
|
|
|
|
test_write_lines help quit >input &&
|
|
|
|
force_color git \
|
|
|
|
-c color.interactive.header=red \
|
|
|
|
-c color.interactive.help=green \
|
|
|
|
-c color.interactive.prompt=yellow \
|
|
|
|
add -i >actual.raw <input &&
|
|
|
|
test_decode_color <actual.raw >actual &&
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
<RED> staged unstaged path<RESET>
|
|
|
|
1: +3/-0 +2/-1 color-test
|
|
|
|
|
|
|
|
<RED>*** Commands ***<RESET>
|
|
|
|
1: <YELLOW>s<RESET>tatus 2: <YELLOW>u<RESET>pdate 3: <YELLOW>r<RESET>evert 4: <YELLOW>a<RESET>dd untracked
|
|
|
|
5: <YELLOW>p<RESET>atch 6: <YELLOW>d<RESET>iff 7: <YELLOW>q<RESET>uit 8: <YELLOW>h<RESET>elp
|
|
|
|
<YELLOW>What now<RESET>> <GREEN>status - show paths with changes<RESET>
|
|
|
|
<GREEN>update - add working tree state to the staged set of changes<RESET>
|
|
|
|
<GREEN>revert - revert staged set of changes back to the HEAD version<RESET>
|
|
|
|
<GREEN>patch - pick hunks and update selectively<RESET>
|
|
|
|
<GREEN>diff - view diff between HEAD and index<RESET>
|
|
|
|
<GREEN>add untracked - add contents of untracked files to the staged set of changes<RESET>
|
|
|
|
<RED>*** Commands ***<RESET>
|
|
|
|
1: <YELLOW>s<RESET>tatus 2: <YELLOW>u<RESET>pdate 3: <YELLOW>r<RESET>evert 4: <YELLOW>a<RESET>dd untracked
|
|
|
|
5: <YELLOW>p<RESET>atch 6: <YELLOW>d<RESET>iff 7: <YELLOW>q<RESET>uit 8: <YELLOW>h<RESET>elp
|
|
|
|
<YELLOW>What now<RESET>> Bye.
|
|
|
|
EOF
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
|
|
: exercise recolor_hunk by editing and then look at the hunk again &&
|
|
|
|
test_write_lines s e K q >input &&
|
|
|
|
force_color git \
|
|
|
|
-c color.interactive.prompt=yellow \
|
|
|
|
-c color.diff.meta=italic \
|
|
|
|
-c color.diff.frag=magenta \
|
|
|
|
-c color.diff.context=cyan \
|
|
|
|
-c color.diff.old=bold \
|
|
|
|
-c color.diff.new=blue \
|
|
|
|
-c core.editor=touch \
|
|
|
|
add -p >actual.raw <input &&
|
|
|
|
test_decode_color <actual.raw >actual.decoded &&
|
|
|
|
sed "s/index [0-9a-f]*\\.\\.[0-9a-f]* 100644/<INDEX-LINE>/" <actual.decoded >actual &&
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
<ITALIC>diff --git a/color-test b/color-test<RESET>
|
|
|
|
<ITALIC><INDEX-LINE><RESET>
|
|
|
|
<ITALIC>--- a/color-test<RESET>
|
|
|
|
<ITALIC>+++ b/color-test<RESET>
|
|
|
|
<MAGENTA>@@ -1,3 +1,4 @@<RESET>
|
|
|
|
<CYAN> context<RESET>
|
|
|
|
<BOLD>-old<RESET>
|
|
|
|
<BLUE>+<RESET><BLUE>new<RESET>
|
|
|
|
<CYAN> more-context<RESET>
|
|
|
|
<BLUE>+<RESET><BLUE>another-one<RESET>
|
2024-03-29 03:58:28 +00:00
|
|
|
<YELLOW>(1/1) Stage this hunk [y,n,q,a,d,s,e,p,?]? <RESET><BOLD>Split into 2 hunks.<RESET>
|
2020-11-16 16:08:32 +00:00
|
|
|
<MAGENTA>@@ -1,3 +1,3 @@<RESET>
|
|
|
|
<CYAN> context<RESET>
|
|
|
|
<BOLD>-old<RESET>
|
|
|
|
<BLUE>+<RESET><BLUE>new<RESET>
|
|
|
|
<CYAN> more-context<RESET>
|
2024-03-29 03:58:28 +00:00
|
|
|
<YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET><MAGENTA>@@ -3 +3,2 @@<RESET>
|
2020-11-16 16:08:32 +00:00
|
|
|
<CYAN> more-context<RESET>
|
|
|
|
<BLUE>+<RESET><BLUE>another-one<RESET>
|
2024-03-29 03:58:28 +00:00
|
|
|
<YELLOW>(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? <RESET><MAGENTA>@@ -1,3 +1,3 @@<RESET>
|
2020-11-16 16:08:32 +00:00
|
|
|
<CYAN> context<RESET>
|
|
|
|
<BOLD>-old<RESET>
|
|
|
|
<BLUE>+new<RESET>
|
|
|
|
<CYAN> more-context<RESET>
|
2024-03-29 03:58:28 +00:00
|
|
|
<YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>
|
2020-11-16 16:08:32 +00:00
|
|
|
EOF
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2023-06-07 13:44:48 +00:00
|
|
|
test_expect_success 'brackets appear without color' '
|
|
|
|
git reset --hard &&
|
|
|
|
test_when_finished "git rm -f bracket-test" &&
|
|
|
|
test_write_lines context old more-context >bracket-test &&
|
|
|
|
git add bracket-test &&
|
|
|
|
test_write_lines context new more-context another-one >bracket-test &&
|
|
|
|
|
|
|
|
test_write_lines quit >input &&
|
|
|
|
git add -i >actual <input &&
|
|
|
|
|
|
|
|
sed "s/^|//" >expect <<-\EOF &&
|
|
|
|
| staged unstaged path
|
|
|
|
| 1: +3/-0 +2/-1 bracket-test
|
|
|
|
|
|
|
|
|
|*** Commands ***
|
|
|
|
| 1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked
|
|
|
|
| 5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp
|
|
|
|
|What now> Bye.
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2023-06-06 14:20:18 +00:00
|
|
|
test_expect_success 'colors can be skipped with color.ui=false' '
|
|
|
|
git reset --hard &&
|
|
|
|
test_when_finished "git rm -f color-test" &&
|
|
|
|
test_write_lines context old more-context >color-test &&
|
|
|
|
git add color-test &&
|
|
|
|
test_write_lines context new more-context another-one >color-test &&
|
|
|
|
|
|
|
|
test_write_lines help quit >input &&
|
|
|
|
force_color git \
|
|
|
|
-c color.ui=false \
|
|
|
|
add -i >actual.raw <input &&
|
|
|
|
test_decode_color <actual.raw >actual &&
|
|
|
|
test_cmp actual.raw actual
|
|
|
|
'
|
|
|
|
|
2020-01-31 09:57:49 +00:00
|
|
|
test_expect_success 'colorized diffs respect diff.wsErrorHighlight' '
|
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
echo "old " >test &&
|
|
|
|
git add test &&
|
|
|
|
echo "new " >test &&
|
|
|
|
|
|
|
|
printf y >y &&
|
|
|
|
force_color git -c diff.wsErrorHighlight=all add -p >output.raw 2>&1 <y &&
|
|
|
|
test_decode_color <output.raw >output &&
|
|
|
|
grep "old<" output
|
|
|
|
'
|
|
|
|
|
2019-12-06 13:08:20 +00:00
|
|
|
test_expect_success 'diffFilter filters diff' '
|
2018-03-03 05:58:10 +00:00
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
echo content >test &&
|
|
|
|
test_config interactive.diffFilter "sed s/^/foo:/" &&
|
2019-12-06 13:08:20 +00:00
|
|
|
printf y >y &&
|
|
|
|
force_color git add -p >output 2>&1 <y &&
|
2018-03-03 05:58:10 +00:00
|
|
|
|
|
|
|
# avoid depending on the exact coloring or content of the prompts,
|
|
|
|
# and just make sure we saw our diff prefixed
|
|
|
|
grep foo:.*content output
|
|
|
|
'
|
|
|
|
|
2019-12-06 13:08:20 +00:00
|
|
|
test_expect_success 'detect bogus diffFilter output' '
|
2018-03-03 05:58:49 +00:00
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
echo content >test &&
|
2022-09-01 15:42:17 +00:00
|
|
|
test_config interactive.diffFilter "sed 6d" &&
|
2019-12-06 13:08:20 +00:00
|
|
|
printf y >y &&
|
2022-09-01 15:42:17 +00:00
|
|
|
force_color test_must_fail git add -p <y >output 2>&1 &&
|
|
|
|
grep "mismatched output" output
|
2018-03-03 05:58:49 +00:00
|
|
|
'
|
|
|
|
|
2022-09-01 15:42:18 +00:00
|
|
|
test_expect_success 'handle iffy colored hunk headers' '
|
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
echo content >test &&
|
|
|
|
printf n >n &&
|
|
|
|
force_color git -c interactive.diffFilter="sed s/.*@@.*/XX/" \
|
|
|
|
add -p >output 2>&1 <n &&
|
|
|
|
grep "^XX$" output
|
2018-03-03 05:58:49 +00:00
|
|
|
'
|
|
|
|
|
pipe_command(): mark stdin descriptor as non-blocking
Our pipe_command() helper lets you both write to and read from a child
process on its stdin/stdout. It's supposed to work without deadlocks
because we use poll() to check when descriptors are ready for reading or
writing. But there's a bug: if both the data to be written and the data
to be read back exceed the pipe buffer, we'll deadlock.
The issue is that the code assumes that if you have, say, a 2MB buffer
to write and poll() tells you that the pipe descriptor is ready for
writing, that calling:
write(cmd->in, buf, 2*1024*1024);
will do a partial write, filling the pipe buffer and then returning what
it did write. And that is what it would do on a socket, but not for a
pipe. When writing to a pipe, at least on Linux, it will block waiting
for the child process to read() more. And now we have a potential
deadlock, because the child may be writing back to us, waiting for us to
read() ourselves.
An easy way to trigger this is:
git -c add.interactive.useBuiltin=true \
-c interactive.diffFilter=cat \
checkout -p HEAD~200
The diff against HEAD~200 will be big, and the filter wants to write all
of it back to us (obviously this is a dummy filter, but in the real
world something like diff-highlight would similarly stream back a big
output).
If you set add.interactive.useBuiltin to false, the problem goes away,
because now we're not using pipe_command() anymore (instead, that part
happens in perl). But this isn't a bug in the interactive code at all.
It's the underlying pipe_command() code which is broken, and has been
all along.
We presumably didn't notice because most calls only do input _or_
output, not both. And the few that do both, like gpg calls, may have
large inputs or outputs, but never both at the same time (e.g., consider
signing, which has a large payload but a small signature comes back).
The obvious fix is to put the descriptor into non-blocking mode, and
indeed, that makes the problem go away. Callers shouldn't need to
care, because they never see the descriptor (they hand us a buffer to
feed into it).
The included test fails reliably on Linux without this patch. Curiously,
it doesn't fail in our Windows CI environment, but has been reported to
do so for individual developers. It should pass in any environment after
this patch (courtesy of the compat/ layers added in the last few
commits).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-08-17 06:10:22 +00:00
|
|
|
test_expect_success 'handle very large filtered diff' '
|
|
|
|
git reset --hard &&
|
|
|
|
# The specific number here is not important, but it must
|
|
|
|
# be large enough that the output of "git diff --color"
|
|
|
|
# fills up the pipe buffer. 10,000 results in ~200k of
|
|
|
|
# colored output.
|
|
|
|
test_seq 10000 >test &&
|
|
|
|
test_config interactive.diffFilter cat &&
|
|
|
|
printf y >y &&
|
|
|
|
force_color git add -p >output 2>&1 <y &&
|
|
|
|
git diff-files --exit-code -- test
|
|
|
|
'
|
|
|
|
|
2019-12-06 13:08:23 +00:00
|
|
|
test_expect_success 'diff.algorithm is passed to `git diff-files`' '
|
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
>file &&
|
|
|
|
git add file &&
|
|
|
|
echo changed >file &&
|
2019-12-06 13:08:24 +00:00
|
|
|
test_must_fail git -c diff.algorithm=bogus add -p 2>err &&
|
2023-10-31 05:23:30 +00:00
|
|
|
test_grep "error: option diff-algorithm accepts " err
|
2019-12-06 13:08:23 +00:00
|
|
|
'
|
|
|
|
|
2017-03-02 09:48:22 +00:00
|
|
|
test_expect_success 'patch-mode via -i prompts for files' '
|
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
echo one >file &&
|
|
|
|
echo two >test &&
|
|
|
|
git add -i <<-\EOF &&
|
|
|
|
patch
|
|
|
|
test
|
|
|
|
|
|
|
|
y
|
|
|
|
quit
|
|
|
|
EOF
|
|
|
|
|
|
|
|
echo test >expect &&
|
|
|
|
git diff --cached --name-only >actual &&
|
2018-03-01 10:50:58 +00:00
|
|
|
diff_cmp expect actual
|
2017-03-02 09:48:22 +00:00
|
|
|
'
|
|
|
|
|
add--interactive: do not expand pathspecs with ls-files
When we want to get the list of modified files, we first
expand any user-provided pathspecs with "ls-files", and then
feed the resulting list of paths as arguments to
"diff-index" and "diff-files". If your pathspec expands into
a large number of paths, you may run into one of two
problems:
1. The OS may complain about the size of the argument
list, and refuse to run. For example:
$ (ulimit -s 128 && git add -p drivers)
Can't exec "git": Argument list too long at .../git-add--interactive line 177.
Died at .../git-add--interactive line 177.
That's on the linux.git repository, which has about 20K
files in the "drivers" directory (none of them modified
in this case). The "ulimit -s" trick is necessary to
show the problem on Linux even for such a gigantic set
of paths. Other operating systems have much smaller
limits (e.g., a real-world case was seen with only 5K
files on OS X).
2. Even when it does work, it's really slow. The pathspec
code is not optimized for huge numbers of paths. Here's
the same case without the ulimit:
$ time git add -p drivers
No changes.
real 0m16.559s
user 0m53.140s
sys 0m0.220s
We can improve this by skipping "ls-files" completely, and
just feeding the original pathspecs to the diff commands.
This solution was discussed in 2010:
http://public-inbox.org/git/20100105041438.GB12574@coredump.intra.peff.net/
but at the time the diff code's pathspecs were more
primitive than those used by ls-files (e.g., they did not
support globs). Making the change would have caused a
user-visible regression, so we didn't.
Since then, the pathspec code has been unified, and the diff
commands natively understand pathspecs like '*.c'.
This patch implements that solution. That skips the
argument-list limits, and the result runs much faster:
$ time git add -p drivers
No changes.
real 0m0.149s
user 0m0.116s
sys 0m0.080s
There are two new tests. The first just exercises the
globbing behavior to confirm that we are not causing a
regression there. The second checks the actual argument
behavior using GIT_TRACE. We _could_ do it with the "ulimit
-s" trick, as above. But that would mean the test could only
run where "ulimit -s" works. And tests of that sort are
expensive, because we have to come up with enough files to
actually bust the limit (we can't just shrink the "128" down
infinitely, since it is also the in-program stack size).
Finally, two caveats and possibilities for future work:
a. This fixes one argument-list expansion, but there may
be others. In fact, it's very likely that if you run
"git add -i" and select a large number of modified
files that the script would try to feed them all to a
single git command.
In practice this is probably fine. The real issue here
is that the argument list was growing with the _total_
number of files, not the number of modified or selected
files.
b. If the repository contains filenames with literal wildcard
characters (e.g., "foo*"), the original code expanded
them via "ls-files" and then fed those wildcard names
to "diff-index", which would have treated them as
wildcards. This was a bug, which is now fixed (though
unless you really go through some contortions with
":(literal)", it's likely that your original pathspec
would match whatever the accidentally-expanded wildcard
would anyway).
So this takes us one step closer to working correctly
with files whose names contain wildcard characters, but
it's likely that others remain (e.g., if "git add -i"
feeds the selected paths to "git add").
Reported-by: Wincent Colaiuta <win@wincent.com>
Reported-by: Mislav Marohnić <mislav.marohnic@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 16:30:24 +00:00
|
|
|
test_expect_success 'add -p handles globs' '
|
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
mkdir -p subdir &&
|
|
|
|
echo base >one.c &&
|
|
|
|
echo base >subdir/two.c &&
|
|
|
|
git add "*.c" &&
|
|
|
|
git commit -m base &&
|
|
|
|
|
|
|
|
echo change >one.c &&
|
|
|
|
echo change >subdir/two.c &&
|
|
|
|
git add -p "*.c" <<-\EOF &&
|
|
|
|
y
|
|
|
|
y
|
|
|
|
EOF
|
|
|
|
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
one.c
|
|
|
|
subdir/two.c
|
|
|
|
EOF
|
|
|
|
git diff --cached --name-only >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
pathspec: honor `PATHSPEC_PREFIX_ORIGIN` with empty prefix
Previous to commit 5d8f084a5 (pathspec: simpler logic to prefix original
pathspec elements, 2017-01-04), we were always using the computed
`match` variable to perform pathspec matching whenever
`PATHSPEC_PREFIX_ORIGIN` is set. This is for example useful when passing
the parsed pathspecs to other commands, as the computed `match` may
contain a pathspec relative to the repository root. The commit changed
this logic to only do so when we do have an actual prefix and when
literal pathspecs are deactivated.
But this change may actually break some commands which expect passed
pathspecs to be relative to the repository root. One such case is `git
add --patch`, which now fails when using relative paths from a
subdirectory. For example if executing "git add -p ../foo.c" in a
subdirectory, the `git-add--interactive` command will directly pass
"../foo.c" to `git-ls-files`. As ls-files is executed at the
repository's root, the command will notice that "../foo.c" is outside
the repository and fail.
Fix the issue by again using the computed `match` variable when
`PATHSPEC_PREFIX_ORIGIN` is set and global literal pathspecs are
deactivated. Note that in contrast to previous behavior, we will now
always call `prefix_magic` regardless of whether a prefix is actually
set. But this is the right thing to do: when the `match` variable has
been resolved to the repository's root, it will be set to an empty
string. When passing the empty string directly to other commands, it
will result in a warning regarding deprecated empty pathspecs. By always
adding the prefix magic, we will end up with at least the string
":(prefix:0)" and thus avoid the warning.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Acked-by: Brandon Williams <bmwill@google.com>
Reviewed-by: Duy Nguyen <pclouds@gmail.com>
2017-04-04 09:16:56 +00:00
|
|
|
test_expect_success 'add -p handles relative paths' '
|
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
echo base >relpath.c &&
|
|
|
|
git add "*.c" &&
|
|
|
|
git commit -m relpath &&
|
|
|
|
|
|
|
|
echo change >relpath.c &&
|
|
|
|
mkdir -p subdir &&
|
|
|
|
git -C subdir add -p .. 2>error <<-\EOF &&
|
|
|
|
y
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_must_be_empty error &&
|
|
|
|
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
relpath.c
|
|
|
|
EOF
|
|
|
|
git diff --cached --name-only >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
add--interactive: do not expand pathspecs with ls-files
When we want to get the list of modified files, we first
expand any user-provided pathspecs with "ls-files", and then
feed the resulting list of paths as arguments to
"diff-index" and "diff-files". If your pathspec expands into
a large number of paths, you may run into one of two
problems:
1. The OS may complain about the size of the argument
list, and refuse to run. For example:
$ (ulimit -s 128 && git add -p drivers)
Can't exec "git": Argument list too long at .../git-add--interactive line 177.
Died at .../git-add--interactive line 177.
That's on the linux.git repository, which has about 20K
files in the "drivers" directory (none of them modified
in this case). The "ulimit -s" trick is necessary to
show the problem on Linux even for such a gigantic set
of paths. Other operating systems have much smaller
limits (e.g., a real-world case was seen with only 5K
files on OS X).
2. Even when it does work, it's really slow. The pathspec
code is not optimized for huge numbers of paths. Here's
the same case without the ulimit:
$ time git add -p drivers
No changes.
real 0m16.559s
user 0m53.140s
sys 0m0.220s
We can improve this by skipping "ls-files" completely, and
just feeding the original pathspecs to the diff commands.
This solution was discussed in 2010:
http://public-inbox.org/git/20100105041438.GB12574@coredump.intra.peff.net/
but at the time the diff code's pathspecs were more
primitive than those used by ls-files (e.g., they did not
support globs). Making the change would have caused a
user-visible regression, so we didn't.
Since then, the pathspec code has been unified, and the diff
commands natively understand pathspecs like '*.c'.
This patch implements that solution. That skips the
argument-list limits, and the result runs much faster:
$ time git add -p drivers
No changes.
real 0m0.149s
user 0m0.116s
sys 0m0.080s
There are two new tests. The first just exercises the
globbing behavior to confirm that we are not causing a
regression there. The second checks the actual argument
behavior using GIT_TRACE. We _could_ do it with the "ulimit
-s" trick, as above. But that would mean the test could only
run where "ulimit -s" works. And tests of that sort are
expensive, because we have to come up with enough files to
actually bust the limit (we can't just shrink the "128" down
infinitely, since it is also the in-program stack size).
Finally, two caveats and possibilities for future work:
a. This fixes one argument-list expansion, but there may
be others. In fact, it's very likely that if you run
"git add -i" and select a large number of modified
files that the script would try to feed them all to a
single git command.
In practice this is probably fine. The real issue here
is that the argument list was growing with the _total_
number of files, not the number of modified or selected
files.
b. If the repository contains filenames with literal wildcard
characters (e.g., "foo*"), the original code expanded
them via "ls-files" and then fed those wildcard names
to "diff-index", which would have treated them as
wildcards. This was a bug, which is now fixed (though
unless you really go through some contortions with
":(literal)", it's likely that your original pathspec
would match whatever the accidentally-expanded wildcard
would anyway).
So this takes us one step closer to working correctly
with files whose names contain wildcard characters, but
it's likely that others remain (e.g., if "git add -i"
feeds the selected paths to "git add").
Reported-by: Wincent Colaiuta <win@wincent.com>
Reported-by: Mislav Marohnić <mislav.marohnic@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 16:30:24 +00:00
|
|
|
test_expect_success 'add -p does not expand argument lists' '
|
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
echo content >not-changed &&
|
|
|
|
git add not-changed &&
|
|
|
|
git commit -m "add not-changed file" &&
|
|
|
|
|
|
|
|
echo change >file &&
|
|
|
|
GIT_TRACE=$(pwd)/trace.out git add -p . <<-\EOF &&
|
|
|
|
y
|
|
|
|
EOF
|
|
|
|
|
|
|
|
# we know that "file" must be mentioned since we actually
|
|
|
|
# update it, but we want to be sure that our "." pathspec
|
|
|
|
# was not expanded into the argument list of any command.
|
|
|
|
# So look only for "not-changed".
|
t3701-add-interactive: tighten the check of trace output
The test 'add -p does not expand argument lists' in
't3701-add-interactive.sh', added in 7288e12cce (add--interactive: do
not expand pathspecs with ls-files, 2017-03-14), checks the GIT_TRACE
of 'git add -p' to ensure that the name of a tracked file wasn't
passed around as argument to any of the commands executed as a result
of undesired pathspec expansion. This check is done with 'grep' using
the filename on its own as the pattern, which is too loose a pattern,
and would match any occurrences of the filename in the trace output,
not just those as command arguments. E.g. if a developer were to
litter the index handling code with trace_printf()s printing, among
other things, the name of the just processed cache entry, then that
pattern would mistakenly match these as well, and would fail the test.
Tighten this 'grep' pattern to only match trace lines that show the
executed commands.
Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-09-10 14:07:14 +00:00
|
|
|
! grep -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out
|
add--interactive: do not expand pathspecs with ls-files
When we want to get the list of modified files, we first
expand any user-provided pathspecs with "ls-files", and then
feed the resulting list of paths as arguments to
"diff-index" and "diff-files". If your pathspec expands into
a large number of paths, you may run into one of two
problems:
1. The OS may complain about the size of the argument
list, and refuse to run. For example:
$ (ulimit -s 128 && git add -p drivers)
Can't exec "git": Argument list too long at .../git-add--interactive line 177.
Died at .../git-add--interactive line 177.
That's on the linux.git repository, which has about 20K
files in the "drivers" directory (none of them modified
in this case). The "ulimit -s" trick is necessary to
show the problem on Linux even for such a gigantic set
of paths. Other operating systems have much smaller
limits (e.g., a real-world case was seen with only 5K
files on OS X).
2. Even when it does work, it's really slow. The pathspec
code is not optimized for huge numbers of paths. Here's
the same case without the ulimit:
$ time git add -p drivers
No changes.
real 0m16.559s
user 0m53.140s
sys 0m0.220s
We can improve this by skipping "ls-files" completely, and
just feeding the original pathspecs to the diff commands.
This solution was discussed in 2010:
http://public-inbox.org/git/20100105041438.GB12574@coredump.intra.peff.net/
but at the time the diff code's pathspecs were more
primitive than those used by ls-files (e.g., they did not
support globs). Making the change would have caused a
user-visible regression, so we didn't.
Since then, the pathspec code has been unified, and the diff
commands natively understand pathspecs like '*.c'.
This patch implements that solution. That skips the
argument-list limits, and the result runs much faster:
$ time git add -p drivers
No changes.
real 0m0.149s
user 0m0.116s
sys 0m0.080s
There are two new tests. The first just exercises the
globbing behavior to confirm that we are not causing a
regression there. The second checks the actual argument
behavior using GIT_TRACE. We _could_ do it with the "ulimit
-s" trick, as above. But that would mean the test could only
run where "ulimit -s" works. And tests of that sort are
expensive, because we have to come up with enough files to
actually bust the limit (we can't just shrink the "128" down
infinitely, since it is also the in-program stack size).
Finally, two caveats and possibilities for future work:
a. This fixes one argument-list expansion, but there may
be others. In fact, it's very likely that if you run
"git add -i" and select a large number of modified
files that the script would try to feed them all to a
single git command.
In practice this is probably fine. The real issue here
is that the argument list was growing with the _total_
number of files, not the number of modified or selected
files.
b. If the repository contains filenames with literal wildcard
characters (e.g., "foo*"), the original code expanded
them via "ls-files" and then fed those wildcard names
to "diff-index", which would have treated them as
wildcards. This was a bug, which is now fixed (though
unless you really go through some contortions with
":(literal)", it's likely that your original pathspec
would match whatever the accidentally-expanded wildcard
would anyway).
So this takes us one step closer to working correctly
with files whose names contain wildcard characters, but
it's likely that others remain (e.g., if "git add -i"
feeds the selected paths to "git add").
Reported-by: Wincent Colaiuta <win@wincent.com>
Reported-by: Mislav Marohnić <mislav.marohnic@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 16:30:24 +00:00
|
|
|
'
|
|
|
|
|
2017-06-21 19:28:59 +00:00
|
|
|
test_expect_success 'hunk-editing handles custom comment char' '
|
|
|
|
git reset --hard &&
|
|
|
|
echo change >>file &&
|
|
|
|
test_config core.commentChar "\$" &&
|
|
|
|
echo e | GIT_EDITOR=true git add -p &&
|
|
|
|
git diff --exit-code
|
|
|
|
'
|
|
|
|
|
color: make "always" the same as "auto" in config
It can be handy to use `--color=always` (or it's synonym
`--color`) on the command-line to convince a command to
produce color even if it's stdout isn't going to the
terminal or a pager.
What's less clear is whether it makes sense to set config
variables like color.ui to `always`. For a one-shot like:
git -c color.ui=always ...
it's potentially useful (especially if the command doesn't
directly support the `--color` option). But setting `always`
in your on-disk config is much muddier, as you may be
surprised when piped commands generate colors (and send them
to whatever is consuming the pipe downstream).
Some people have done this anyway, because:
1. The documentation for color.ui makes it sound like
using `always` is a good idea, when you almost
certainly want `auto`.
2. Traditionally not every command (and especially not
plumbing) respected color.ui in the first place. So
the confusion came up less frequently than it might
have.
The situation changed in 136c8c8b8f (color: check color.ui
in git_default_config(), 2017-07-13), which negated point
(2): now scripts using only plumbing commands (like
add-interactive) are broken by this setting.
That commit was fixing real issues (e.g., by making
`color.ui=never` work, since `auto` is the default), so we
don't want to just revert it. We could turn `always` into a
noop in plumbing commands, but that creates a hard-to-explain
inconsistency between the plumbing and other commands.
Instead, let's just turn `always` into `auto` for all config.
This does break the "one-shot" config shown above, but again,
we're probably better to have simple and consistent rules than
to try to special-case command-line config.
There is one place where `always` should retain its meaning:
on the command line, `--color=always` should continue to be
the same as `--color`, overriding any isatty checks. Since the
command-line parser also depends on git_config_colorbool(), we
can use the existence of the "var" string to deterine whether
we are serving the command-line or the config.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-10-03 13:46:06 +00:00
|
|
|
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
|
|
|
|
'
|
|
|
|
|
2018-01-13 12:10:38 +00:00
|
|
|
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
|
2020-11-10 08:39:00 +00:00
|
|
|
EOF
|
|
|
|
test_cmp expected actual &&
|
|
|
|
git -C for-submodules diff-files --name-only --ignore-submodules=none >actual &&
|
|
|
|
cat >expected <<-\EOF &&
|
|
|
|
dirty-both-ways
|
|
|
|
dirty-head
|
2018-01-13 12:10:38 +00:00
|
|
|
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
|
|
|
|
'
|
|
|
|
|
2022-09-01 15:42:19 +00:00
|
|
|
test_expect_success 'handle submodules' '
|
|
|
|
echo 123 >>for-submodules/dirty-otherwise/initial.t &&
|
|
|
|
|
|
|
|
force_color git -C for-submodules add -p dirty-otherwise >output 2>&1 &&
|
|
|
|
grep "No changes" output &&
|
|
|
|
|
|
|
|
force_color git -C for-submodules add -p dirty-head >output 2>&1 <y &&
|
|
|
|
git -C for-submodules ls-files --stage dirty-head >actual &&
|
|
|
|
rev="$(git -C for-submodules/dirty-head rev-parse HEAD)" &&
|
|
|
|
grep "$rev" actual
|
|
|
|
'
|
|
|
|
|
2018-03-01 10:50:59 +00:00
|
|
|
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
|
|
|
|
'
|
|
|
|
|
2018-03-01 10:51:00 +00:00
|
|
|
test_expect_success 'add -p works with pathological context lines' '
|
2018-03-01 10:50:59 +00:00
|
|
|
git reset &&
|
|
|
|
printf "%s\n" n y |
|
|
|
|
git add -p &&
|
|
|
|
git cat-file blob :a >actual &&
|
|
|
|
test_cmp expected-1 actual
|
|
|
|
'
|
|
|
|
|
2018-03-05 10:56:28 +00:00
|
|
|
test_expect_success 'add -p patch editing works with pathological context lines' '
|
2018-03-01 10:50:59 +00:00
|
|
|
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
|
|
|
|
'
|
|
|
|
|
2019-06-12 09:25:27 +00:00
|
|
|
test_expect_success 'checkout -p works with pathological context lines' '
|
|
|
|
test_write_lines a a a a a a >a &&
|
|
|
|
git add a &&
|
2020-03-22 21:14:22 +00:00
|
|
|
test_write_lines a b a b a b a b a b a >a &&
|
2019-06-12 09:25:27 +00:00
|
|
|
test_write_lines s n n y q | git checkout -p &&
|
|
|
|
test_write_lines a b a b a a b a b a >expect &&
|
|
|
|
test_cmp expect a
|
|
|
|
'
|
2019-11-15 11:11:20 +00:00
|
|
|
|
2020-09-09 13:58:52 +00:00
|
|
|
# This should be called from a subshell as it sets a temporary editor
|
|
|
|
setup_new_file() {
|
|
|
|
write_script new-file-editor.sh <<-\EOF &&
|
|
|
|
sed /^#/d "$1" >patch &&
|
|
|
|
sed /^+c/d patch >"$1"
|
|
|
|
EOF
|
|
|
|
test_set_editor "$(pwd)/new-file-editor.sh" &&
|
|
|
|
test_write_lines a b c d e f >new-file &&
|
|
|
|
test_write_lines a b d e f >new-file-expect &&
|
|
|
|
test_write_lines "@@ -0,0 +1,6 @@" +a +b +c +d +e +f >patch-expect
|
|
|
|
}
|
|
|
|
|
|
|
|
test_expect_success 'add -N followed by add -p patch editing' '
|
|
|
|
git reset --hard &&
|
|
|
|
(
|
|
|
|
setup_new_file &&
|
|
|
|
git add -N new-file &&
|
|
|
|
test_write_lines e n q | git add -p &&
|
|
|
|
git cat-file blob :new-file >actual &&
|
|
|
|
test_cmp new-file-expect actual &&
|
|
|
|
test_cmp patch-expect patch
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'checkout -p patch editing of added file' '
|
|
|
|
git reset --hard &&
|
|
|
|
(
|
|
|
|
setup_new_file &&
|
|
|
|
git add new-file &&
|
|
|
|
git commit -m "add new file" &&
|
|
|
|
git rm new-file &&
|
|
|
|
git commit -m "remove new file" &&
|
|
|
|
test_write_lines e n q | git checkout -p HEAD^ &&
|
|
|
|
test_cmp new-file-expect new-file &&
|
|
|
|
test_cmp patch-expect patch
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2019-11-15 11:11:20 +00:00
|
|
|
test_expect_success 'show help from add--helper' '
|
|
|
|
git reset --hard &&
|
|
|
|
cat >expect <<-EOF &&
|
|
|
|
|
|
|
|
<BOLD>*** Commands ***<RESET>
|
|
|
|
1: <BOLD;BLUE>s<RESET>tatus 2: <BOLD;BLUE>u<RESET>pdate 3: <BOLD;BLUE>r<RESET>evert 4: <BOLD;BLUE>a<RESET>dd untracked
|
|
|
|
5: <BOLD;BLUE>p<RESET>atch 6: <BOLD;BLUE>d<RESET>iff 7: <BOLD;BLUE>q<RESET>uit 8: <BOLD;BLUE>h<RESET>elp
|
|
|
|
<BOLD;BLUE>What now<RESET>> <BOLD;RED>status - show paths with changes<RESET>
|
|
|
|
<BOLD;RED>update - add working tree state to the staged set of changes<RESET>
|
|
|
|
<BOLD;RED>revert - revert staged set of changes back to the HEAD version<RESET>
|
|
|
|
<BOLD;RED>patch - pick hunks and update selectively<RESET>
|
|
|
|
<BOLD;RED>diff - view diff between HEAD and index<RESET>
|
|
|
|
<BOLD;RED>add untracked - add contents of untracked files to the staged set of changes<RESET>
|
|
|
|
<BOLD>*** Commands ***<RESET>
|
|
|
|
1: <BOLD;BLUE>s<RESET>tatus 2: <BOLD;BLUE>u<RESET>pdate 3: <BOLD;BLUE>r<RESET>evert 4: <BOLD;BLUE>a<RESET>dd untracked
|
|
|
|
5: <BOLD;BLUE>p<RESET>atch 6: <BOLD;BLUE>d<RESET>iff 7: <BOLD;BLUE>q<RESET>uit 8: <BOLD;BLUE>h<RESET>elp
|
|
|
|
<BOLD;BLUE>What now<RESET>>$SP
|
|
|
|
Bye.
|
|
|
|
EOF
|
2019-12-06 13:08:20 +00:00
|
|
|
test_write_lines h | force_color git add -i >actual.colored &&
|
2019-11-15 11:11:20 +00:00
|
|
|
test_decode_color <actual.colored >actual &&
|
2021-02-11 01:53:53 +00:00
|
|
|
test_cmp expect actual
|
2019-11-15 11:11:20 +00:00
|
|
|
'
|
|
|
|
|
add-patch: handle "* Unmerged path" lines
When we generate a diff with --cached, unmerged entries have no oid for
their index entry:
$ git diff-index --abbrev --cached HEAD
:100644 000000 f719efd 0000000 U my-conflict
So when we are asked to produce a patch, since we only have one side, we
just emit a special message:
$ git diff-index --cached -p HEAD
* Unmerged path my-conflict
This confuses interactive-patch modes that look at cached diffs. For
example:
$ git reset -p
BUG: add-patch.c:498: diff starts with unexpected line:
* Unmerged path my-conflict
Making things even more confusing, you'll get that error only if the
unmerged entry is alphabetically the first changed file. Otherwise, we
simply stick the unrecognized line to the end of the previous hunk.
There it's mostly harmless, as it eventually gets fed back to "git
apply", which happily ignores it. But it's still shown to the user
attached to the hunk, which is wrong.
So let's handle these lines as a noop. There's not really anything
useful to do with a conflicted merge in this case, and that's what we do
for other cases like "add -p". There we get a "diff --cc" line, which we
accept as starting a new file, but we refuse to use any of its hunks
(their headers start with "@@@" and not "@@ ", so we silently ignore
them).
It seems like simply recognizing the line and continuing in our parsing
loop would work. But we actually need to run the rest of the loop body
to handle matching up our colored/filtered output. But that code assumes
that we have some active file_diff we're working on. So instead, we'll
just insert a dummy entry into our array. This ends up the same as if we
saw a "diff --cc" line (a file with no hunks).
Reported-by: Philippe Blain <levraiphilippeblain@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-03-09 08:58:16 +00:00
|
|
|
test_expect_success 'reset -p with unmerged files' '
|
|
|
|
test_when_finished "git checkout --force main" &&
|
|
|
|
test_commit one conflict &&
|
|
|
|
git checkout -B side HEAD^ &&
|
|
|
|
test_commit two conflict &&
|
|
|
|
test_must_fail git merge one &&
|
|
|
|
|
|
|
|
# this is a noop with only an unmerged entry
|
|
|
|
git reset -p &&
|
|
|
|
|
|
|
|
# add files that sort before and after unmerged entry
|
|
|
|
echo a >a &&
|
|
|
|
echo z >z &&
|
|
|
|
git add a z &&
|
|
|
|
|
|
|
|
# confirm that we can reset those files
|
|
|
|
printf "%s\n" y y | git reset -p &&
|
|
|
|
git diff-index --cached --diff-filter=u HEAD >staged &&
|
|
|
|
test_must_be_empty staged
|
|
|
|
'
|
|
|
|
|
2008-02-13 10:50:51 +00:00
|
|
|
test_done
|