Commit c3a7892f30fea72692fafae0e6ff567e5cb8726c

Edward Thomson 2019-09-09T13:10:24

Merge pull request #5209 from mkostyuk/apply-wrong-patch apply: Fix a patch corruption related to EOFNL handling

diff --git a/src/apply.c b/src/apply.c
index e0ddef4..0424262 100644
--- a/src/apply.c
+++ b/src/apply.c
@@ -219,7 +219,7 @@ static int apply_hunk(
 			case GIT_DIFF_LINE_CONTEXT_EOFNL:
 			case GIT_DIFF_LINE_DEL_EOFNL:
 			case GIT_DIFF_LINE_ADD_EOFNL:
-				prev = i ? git_array_get(patch->lines, i - 1) : NULL;
+				prev = i ? git_array_get(patch->lines, linenum - 1) : NULL;
 				if (prev && prev->content[prev->content_len - 1] == '\n')
 					prev->content_len -= 1;
 				break;
diff --git a/tests/apply/fromdiff.c b/tests/apply/fromdiff.c
index 832415d..e9329f6 100644
--- a/tests/apply/fromdiff.c
+++ b/tests/apply/fromdiff.c
@@ -131,6 +131,17 @@ void test_apply_fromdiff__lastline(void)
 		PATCH_ORIGINAL_TO_CHANGE_LASTLINE, NULL));
 }
 
+void test_apply_fromdiff__change_middle_and_lastline_nocontext(void)
+{
+	git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
+	diff_opts.context_lines = 0;
+
+	cl_git_pass(apply_buf(
+		FILE_ORIGINAL, "file.txt",
+		FILE_CHANGE_MIDDLE_AND_LASTLINE, "file.txt",
+		PATCH_ORIGINAL_TO_CHANGE_MIDDLE_AND_LASTLINE_NOCONTEXT, &diff_opts));
+}
+
 void test_apply_fromdiff__prepend(void)
 {
 	cl_git_pass(apply_buf(
diff --git a/tests/patch/patch_common.h b/tests/patch/patch_common.h
index 2db8d93..690e0a6 100644
--- a/tests/patch/patch_common.h
+++ b/tests/patch/patch_common.h
@@ -263,6 +263,32 @@
 	"-(this line is changed)\n" \
 	"+(THIS line is changed!)\n"
 
+/* A change in the middle and a deletion of the newline at the end of the file */
+
+#define FILE_CHANGE_MIDDLE_AND_LASTLINE \
+	"hey!\n" \
+	"this is some context!\n" \
+	"around some lines\n" \
+	"that will change\n" \
+	"yes it is!\n" \
+	"(THIS line is changed!)\n" \
+	"and this\n" \
+	"is additional context\n" \
+	"BELOW it! - (THIS line is changed!)"
+
+#define PATCH_ORIGINAL_TO_CHANGE_MIDDLE_AND_LASTLINE_NOCONTEXT \
+	"diff --git a/file.txt b/file.txt\n" \
+	"index 9432026..e05d36c 100644\n" \
+	"--- a/file.txt\n" \
+	"+++ b/file.txt\n" \
+	"@@ -6 +6 @@ yes it is!\n" \
+	"-(this line is changed)\n" \
+	"+(THIS line is changed!)\n" \
+	"@@ -9 +9 @@ is additional context\n" \
+	"-below it!\n" \
+	"+BELOW it! - (THIS line is changed!)\n" \
+	"\\ No newline at end of file\n"
+
 /* A deletion at the beginning of the file and a change in the middle */
 
 #define FILE_DELETE_AND_CHANGE \