diff options
-rw-r--r-- | src/patch_parse.c | 7 | ||||
-rw-r--r-- | tests/diff/parse.c | 71 |
2 files changed, 78 insertions, 0 deletions
diff --git a/src/patch_parse.c b/src/patch_parse.c index 2fd6e9766..f9dcecd1c 100644 --- a/src/patch_parse.c +++ b/src/patch_parse.c @@ -563,6 +563,8 @@ static int parse_hunk_body( char c; int origin; int prefix = 1; + int old_lineno = hunk->hunk.old_start + (hunk->hunk.old_lines - oldlines); + int new_lineno = hunk->hunk.new_start + (hunk->hunk.new_lines - newlines); if (ctx->parse_ctx.line_len == 0 || ctx->parse_ctx.line[ctx->parse_ctx.line_len - 1] != '\n') { error = git_parse_err("invalid patch instruction at line %"PRIuZ, @@ -586,11 +588,13 @@ static int parse_hunk_body( case '-': origin = GIT_DIFF_LINE_DELETION; oldlines--; + new_lineno = -1; break; case '+': origin = GIT_DIFF_LINE_ADDITION; newlines--; + old_lineno = -1; break; default: @@ -607,6 +611,9 @@ static int parse_hunk_body( line->content_len = ctx->parse_ctx.line_len - prefix; line->content_offset = ctx->parse_ctx.content_len - ctx->parse_ctx.remain_len; line->origin = origin; + line->num_lines = 1; + line->old_lineno = old_lineno; + line->new_lineno = new_lineno; hunk->line_count++; } diff --git a/tests/diff/parse.c b/tests/diff/parse.c index bb18196b0..9cdaa92fb 100644 --- a/tests/diff/parse.c +++ b/tests/diff/parse.c @@ -288,3 +288,74 @@ void test_diff_parse__patch_roundtrip_succeeds(void) git_buf_dispose(&patchbuf); git_buf_dispose(&diffbuf); } + +#define cl_assert_equal_i_src(i1,i2,file,line) clar__assert_equal(file,line,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) + +static void cl_git_assert_lineinfo_(int old_lineno, int new_lineno, int num_lines, git_patch *patch, size_t hunk_idx, size_t line_idx, const char *file, int lineno) +{ + const git_diff_line *line; + + cl_git_expect(git_patch_get_line_in_hunk(&line, patch, hunk_idx, line_idx), 0, file, lineno); + cl_assert_equal_i_src(old_lineno, line->old_lineno, file, lineno); + cl_assert_equal_i_src(new_lineno, line->new_lineno, file, lineno); + cl_assert_equal_i_src(num_lines, line->num_lines, file, lineno); +} + +#define cl_git_assert_lineinfo(old, new, num, p, h, l) \ + cl_git_assert_lineinfo_(old,new,num,p,h,l,__FILE__,__LINE__) + + +void test_diff_parse__issue4672(void) +{ + const char *text = "diff --git a/a b/a\n" + "index 7f129fd..af431f2 100644\n" + "--- a/a\n" + "+++ b/a\n" + "@@ -3 +3 @@\n" + "-a contents 2\n" + "+a contents\n"; + + git_diff *diff; + git_patch *patch; + const git_diff_hunk *hunk; + size_t n, l = 0; + + cl_git_pass(git_diff_from_buffer(&diff, text, strlen(text))); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_get_hunk(&hunk, &n, patch, 0)); + + cl_git_assert_lineinfo(3, -1, 1, patch, 0, l++); + cl_git_assert_lineinfo(-1, 3, 1, patch, 0, l++); + + cl_assert_equal_i(n, l); + + git_patch_free(patch); + git_diff_free(diff); +} + +void test_diff_parse__lineinfo(void) +{ + const char *text = PATCH_ORIGINAL_TO_CHANGE_MIDDLE; + git_diff *diff; + git_patch *patch; + const git_diff_hunk *hunk; + size_t n, l = 0; + + cl_git_pass(git_diff_from_buffer(&diff, text, strlen(text))); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_get_hunk(&hunk, &n, patch, 0)); + + cl_git_assert_lineinfo(3, 3, 1, patch, 0, l++); + cl_git_assert_lineinfo(4, 4, 1, patch, 0, l++); + cl_git_assert_lineinfo(5, 5, 1, patch, 0, l++); + cl_git_assert_lineinfo(6, -1, 1, patch, 0, l++); + cl_git_assert_lineinfo(-1, 6, 1, patch, 0, l++); + cl_git_assert_lineinfo(7, 7, 1, patch, 0, l++); + cl_git_assert_lineinfo(8, 8, 1, patch, 0, l++); + cl_git_assert_lineinfo(9, 9, 1, patch, 0, l++); + + cl_assert_equal_i(n, l); + + git_patch_free(patch); + git_diff_free(diff); +} |