summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-07-05 11:06:33 +0200
committerPatrick Steinhardt <ps@pks.im>2019-07-11 12:11:11 +0200
commit3f855fe863e7260ea4b7bc36a0c78ea2bff37b68 (patch)
treec6fed7a801144713282860976ed1cd66510957d9
parentb30dab8fa7e1c2d6bd938cd5941c9d1cd55a0004 (diff)
downloadlibgit2-3f855fe863e7260ea4b7bc36a0c78ea2bff37b68.tar.gz
patch_parse: handle missing newline indicator in old file
When either the old or new file contents have no newline at the end of the file, then git-diff(1) will print out a "\ No newline at end of file" indicator. While we do correctly handle this in the case where the new file has this indcator, we fail to parse patches where the old file is missing a newline at EOF. Fix this bug by handling and missing newline indicators in the old file. Add tests to verify that we can parse such files.
-rw-r--r--src/patch_parse.c13
-rw-r--r--tests/patch/parse.c14
-rw-r--r--tests/patch/patch_common.h10
3 files changed, 36 insertions, 1 deletions
diff --git a/src/patch_parse.c b/src/patch_parse.c
index b44d4f02f..9f5bef5b1 100644
--- a/src/patch_parse.c
+++ b/src/patch_parse.c
@@ -578,6 +578,16 @@ static int parse_hunk_body(
old_lineno = -1;
break;
+ case '\\':
+ /*
+ * If there are no oldlines left, then this is probably
+ * the "\ No newline at end of file" marker. Do not
+ * verify its format, as it may be localized.
+ */
+ if (!oldlines)
+ continue;
+ /* fall through */
+
default:
error = git_parse_err("invalid patch hunk at line %"PRIuZ, ctx->parse_ctx.line_num);
goto done;
@@ -606,7 +616,8 @@ static int parse_hunk_body(
goto done;
}
- /* Handle "\ No newline at end of file". Only expect the leading
+ /*
+ * Handle "\ No newline at end of file". Only expect the leading
* backslash, though, because the rest of the string could be
* localized. Because `diff` optimizes for the case where you
* want to apply the patch by hand.
diff --git a/tests/patch/parse.c b/tests/patch/parse.c
index a40ad7b23..8c29e311a 100644
--- a/tests/patch/parse.c
+++ b/tests/patch/parse.c
@@ -102,6 +102,20 @@ void test_patch_parse__invalid_patches_fails(void)
strlen(PATCH_CORRUPT_MISSING_HUNK_HEADER), NULL));
}
+void test_patch_parse__no_newline_at_end_of_new_file(void)
+{
+ git_patch *patch;
+ cl_git_pass(git_patch_from_buffer(&patch, PATCH_APPEND_NO_NL, strlen(PATCH_APPEND_NO_NL), NULL));
+ git_patch_free(patch);
+}
+
+void test_patch_parse__no_newline_at_end_of_old_file(void)
+{
+ git_patch *patch;
+ cl_git_pass(git_patch_from_buffer(&patch, PATCH_APPEND_NO_NL_IN_OLD_FILE, strlen(PATCH_APPEND_NO_NL_IN_OLD_FILE), NULL));
+ git_patch_free(patch);
+}
+
void test_patch_parse__files_with_whitespaces_succeeds(void)
{
git_patch *patch;
diff --git a/tests/patch/patch_common.h b/tests/patch/patch_common.h
index 291ece9eb..2db8d933f 100644
--- a/tests/patch/patch_common.h
+++ b/tests/patch/patch_common.h
@@ -681,6 +681,16 @@
"+added line with no nl\n" \
"\\ No newline at end of file\n"
+#define PATCH_APPEND_NO_NL_IN_OLD_FILE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..83759c0 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1,1 +1,1 @@\n" \
+ "-foo\n" \
+ "\\ No newline at end of file\n" \
+ "+foo\n"
+
#define PATCH_NAME_WHITESPACE \
"diff --git a/file with spaces.txt b/file with spaces.txt\n" \
"index 9432026..83759c0 100644\n" \