Commit 3f855fe8 by Patrick Steinhardt

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.
parent b30dab8f
...@@ -578,6 +578,16 @@ static int parse_hunk_body( ...@@ -578,6 +578,16 @@ static int parse_hunk_body(
old_lineno = -1; old_lineno = -1;
break; 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: default:
error = git_parse_err("invalid patch hunk at line %"PRIuZ, ctx->parse_ctx.line_num); error = git_parse_err("invalid patch hunk at line %"PRIuZ, ctx->parse_ctx.line_num);
goto done; goto done;
...@@ -606,7 +616,8 @@ static int parse_hunk_body( ...@@ -606,7 +616,8 @@ static int parse_hunk_body(
goto done; 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 * backslash, though, because the rest of the string could be
* localized. Because `diff` optimizes for the case where you * localized. Because `diff` optimizes for the case where you
* want to apply the patch by hand. * want to apply the patch by hand.
......
...@@ -102,6 +102,20 @@ void test_patch_parse__invalid_patches_fails(void) ...@@ -102,6 +102,20 @@ void test_patch_parse__invalid_patches_fails(void)
strlen(PATCH_CORRUPT_MISSING_HUNK_HEADER), NULL)); 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) void test_patch_parse__files_with_whitespaces_succeeds(void)
{ {
git_patch *patch; git_patch *patch;
......
...@@ -681,6 +681,16 @@ ...@@ -681,6 +681,16 @@
"+added line with no nl\n" \ "+added line with no nl\n" \
"\\ No newline at end of file\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 \ #define PATCH_NAME_WHITESPACE \
"diff --git a/file with spaces.txt b/file with spaces.txt\n" \ "diff --git a/file with spaces.txt b/file with spaces.txt\n" \
"index 9432026..83759c0 100644\n" \ "index 9432026..83759c0 100644\n" \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment