Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f463379

Browse files
authored
Merge pull request #4687 from tiennou/fix/4672
patch_parse: populate line numbers while parsing diffs
2 parents f2a1cec + f9e2802 commit f463379

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

src/patch_parse.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,8 @@ static int parse_hunk_body(
563563
char c;
564564
int origin;
565565
int prefix = 1;
566+
int old_lineno = hunk->hunk.old_start + (hunk->hunk.old_lines - oldlines);
567+
int new_lineno = hunk->hunk.new_start + (hunk->hunk.new_lines - newlines);
566568

567569
if (ctx->parse_ctx.line_len == 0 || ctx->parse_ctx.line[ctx->parse_ctx.line_len - 1] != '\n') {
568570
error = git_parse_err("invalid patch instruction at line %"PRIuZ,
@@ -586,11 +588,13 @@ static int parse_hunk_body(
586588
case '-':
587589
origin = GIT_DIFF_LINE_DELETION;
588590
oldlines--;
591+
new_lineno = -1;
589592
break;
590593

591594
case '+':
592595
origin = GIT_DIFF_LINE_ADDITION;
593596
newlines--;
597+
old_lineno = -1;
594598
break;
595599

596600
default:
@@ -607,6 +611,9 @@ static int parse_hunk_body(
607611
line->content_len = ctx->parse_ctx.line_len - prefix;
608612
line->content_offset = ctx->parse_ctx.content_len - ctx->parse_ctx.remain_len;
609613
line->origin = origin;
614+
line->num_lines = 1;
615+
line->old_lineno = old_lineno;
616+
line->new_lineno = new_lineno;
610617

611618
hunk->line_count++;
612619
}

tests/diff/parse.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,3 +288,74 @@ void test_diff_parse__patch_roundtrip_succeeds(void)
288288
git_buf_dispose(&patchbuf);
289289
git_buf_dispose(&diffbuf);
290290
}
291+
292+
#define cl_assert_equal_i_src(i1,i2,file,line) clar__assert_equal(file,line,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2))
293+
294+
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)
295+
{
296+
const git_diff_line *line;
297+
298+
cl_git_expect(git_patch_get_line_in_hunk(&line, patch, hunk_idx, line_idx), 0, file, lineno);
299+
cl_assert_equal_i_src(old_lineno, line->old_lineno, file, lineno);
300+
cl_assert_equal_i_src(new_lineno, line->new_lineno, file, lineno);
301+
cl_assert_equal_i_src(num_lines, line->num_lines, file, lineno);
302+
}
303+
304+
#define cl_git_assert_lineinfo(old, new, num, p, h, l) \
305+
cl_git_assert_lineinfo_(old,new,num,p,h,l,__FILE__,__LINE__)
306+
307+
308+
void test_diff_parse__issue4672(void)
309+
{
310+
const char *text = "diff --git a/a b/a\n"
311+
"index 7f129fd..af431f2 100644\n"
312+
"--- a/a\n"
313+
"+++ b/a\n"
314+
"@@ -3 +3 @@\n"
315+
"-a contents 2\n"
316+
"+a contents\n";
317+
318+
git_diff *diff;
319+
git_patch *patch;
320+
const git_diff_hunk *hunk;
321+
size_t n, l = 0;
322+
323+
cl_git_pass(git_diff_from_buffer(&diff, text, strlen(text)));
324+
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
325+
cl_git_pass(git_patch_get_hunk(&hunk, &n, patch, 0));
326+
327+
cl_git_assert_lineinfo(3, -1, 1, patch, 0, l++);
328+
cl_git_assert_lineinfo(-1, 3, 1, patch, 0, l++);
329+
330+
cl_assert_equal_i(n, l);
331+
332+
git_patch_free(patch);
333+
git_diff_free(diff);
334+
}
335+
336+
void test_diff_parse__lineinfo(void)
337+
{
338+
const char *text = PATCH_ORIGINAL_TO_CHANGE_MIDDLE;
339+
git_diff *diff;
340+
git_patch *patch;
341+
const git_diff_hunk *hunk;
342+
size_t n, l = 0;
343+
344+
cl_git_pass(git_diff_from_buffer(&diff, text, strlen(text)));
345+
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
346+
cl_git_pass(git_patch_get_hunk(&hunk, &n, patch, 0));
347+
348+
cl_git_assert_lineinfo(3, 3, 1, patch, 0, l++);
349+
cl_git_assert_lineinfo(4, 4, 1, patch, 0, l++);
350+
cl_git_assert_lineinfo(5, 5, 1, patch, 0, l++);
351+
cl_git_assert_lineinfo(6, -1, 1, patch, 0, l++);
352+
cl_git_assert_lineinfo(-1, 6, 1, patch, 0, l++);
353+
cl_git_assert_lineinfo(7, 7, 1, patch, 0, l++);
354+
cl_git_assert_lineinfo(8, 8, 1, patch, 0, l++);
355+
cl_git_assert_lineinfo(9, 9, 1, patch, 0, l++);
356+
357+
cl_assert_equal_i(n, l);
358+
359+
git_patch_free(patch);
360+
git_diff_free(diff);
361+
}

0 commit comments

Comments
 (0)