Merge branch 'pw/add-p-hunk-split-fix'

"git add -p" rewritten in C regressed hunk splitting in some cases,
which has been corrected.

* pw/add-p-hunk-split-fix:
  builtin add -p: fix hunk splitting
  t3701: clean up hunk splitting tests
This commit is contained in:
Junio C Hamano
2022-02-09 14:20:59 -08:00
2 changed files with 56 additions and 12 deletions

View File

@ -383,6 +383,17 @@ static int is_octal(const char *p, size_t len)
return 1; return 1;
} }
static void complete_file(char marker, struct hunk *hunk)
{
if (marker == '-' || marker == '+')
/*
* Last hunk ended in non-context line (i.e. it
* appended lines to the file, so there are no
* trailing context lines).
*/
hunk->splittable_into++;
}
static int parse_diff(struct add_p_state *s, const struct pathspec *ps) static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
{ {
struct strvec args = STRVEC_INIT; struct strvec args = STRVEC_INIT;
@ -472,6 +483,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
eol = pend; eol = pend;
if (starts_with(p, "diff ")) { if (starts_with(p, "diff ")) {
complete_file(marker, hunk);
ALLOC_GROW_BY(s->file_diff, s->file_diff_nr, 1, ALLOC_GROW_BY(s->file_diff, s->file_diff_nr, 1,
file_diff_alloc); file_diff_alloc);
file_diff = s->file_diff + s->file_diff_nr - 1; file_diff = s->file_diff + s->file_diff_nr - 1;
@ -598,13 +610,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
file_diff->hunk->colored_end = hunk->colored_end; file_diff->hunk->colored_end = hunk->colored_end;
} }
} }
complete_file(marker, hunk);
if (marker == '-' || marker == '+')
/*
* Last hunk ended in non-context line (i.e. it appended lines
* to the file, so there are no trailing context lines).
*/
hunk->splittable_into++;
/* non-colored shorter than colored? */ /* non-colored shorter than colored? */
if (colored_p != colored_pend) { if (colored_p != colored_pend) {

View File

@ -326,7 +326,9 @@ test_expect_success 'correct message when there is nothing to do' '
test_expect_success 'setup again' ' test_expect_success 'setup again' '
git reset --hard && git reset --hard &&
test_chmod +x file && test_chmod +x file &&
echo content >>file echo content >>file &&
test_write_lines A B C D>file2 &&
git add file2
' '
# Write the patch file with a new line at the top and bottom # Write the patch file with a new line at the top and bottom
@ -341,13 +343,27 @@ test_expect_success 'setup patch' '
content content
+lastline +lastline
\ No newline at end of file \ No newline at end of file
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
EOF EOF
' '
# Expected output, diff is similar to the patch but w/ diff at the top # Expected output, diff is similar to the patch but w/ diff at the top
test_expect_success 'setup expected' ' test_expect_success 'setup expected' '
echo diff --git a/file b/file >expected && echo diff --git a/file b/file >expected &&
cat patch |sed "/^index/s/ 100644/ 100755/" >>expected && sed -e "/^index 180b47c/s/ 100644/ 100755/" \
-e /1,5/s//1,4/ \
-e /Y/d patch >>expected &&
cat >expected-output <<-\EOF cat >expected-output <<-\EOF
--- a/file --- a/file
+++ b/file +++ b/file
@ -366,6 +382,28 @@ test_expect_success 'setup expected' '
content content
+lastline +lastline
\ No newline at end of file \ No newline at end of file
--- 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
EOF EOF
' '
@ -373,9 +411,9 @@ test_expect_success 'setup expected' '
test_expect_success 'add first line works' ' test_expect_success 'add first line works' '
git commit -am "clear local changes" && git commit -am "clear local changes" &&
git apply patch && git apply patch &&
printf "%s\n" s y y | git add -p file 2>error | test_write_lines s y y s y n y | git add -p 2>error >raw-output &&
sed -n -e "s/^([1-2]\/[1-2]) Stage this hunk[^@]*\(@@ .*\)/\1/" \ sed -n -e "s/^([1-9]\/[1-9]) Stage this hunk[^@]*\(@@ .*\)/\1/" \
-e "/^[-+@ \\\\]"/p >output && -e "/^[-+@ \\\\]"/p raw-output >output &&
test_must_be_empty error && test_must_be_empty error &&
git diff --cached >diff && git diff --cached >diff &&
diff_cmp expected diff && diff_cmp expected diff &&