1 #include "clar_libgit2.h"
3 #include "patch_parse.h"
4 #include "diff_helpers.h"
5 #include "../src/diff.h"
7 #include "../patch/patch_common.h"
9 void test_diff_parse__cleanup(void)
11 cl_git_sandbox_cleanup();
14 void test_diff_parse__nonpatches_fail_with_notfound(void)
17 const char *not = PATCH_NOT_A_PATCH
;
18 const char *not_with_leading
= "Leading text.\n" PATCH_NOT_A_PATCH
;
19 const char *not_with_trailing
= PATCH_NOT_A_PATCH
"Trailing text.\n";
20 const char *not_with_both
= "Lead.\n" PATCH_NOT_A_PATCH
"Trail.\n";
22 cl_git_fail_with(GIT_ENOTFOUND
,
23 git_diff_from_buffer(&diff
,
26 cl_git_fail_with(GIT_ENOTFOUND
,
27 git_diff_from_buffer(&diff
,
29 strlen(not_with_leading
)));
30 cl_git_fail_with(GIT_ENOTFOUND
,
31 git_diff_from_buffer(&diff
,
33 strlen(not_with_trailing
)));
34 cl_git_fail_with(GIT_ENOTFOUND
,
35 git_diff_from_buffer(&diff
,
37 strlen(not_with_both
)));
40 static void test_parse_invalid_diff(const char *invalid_diff
)
43 git_buf buf
= GIT_BUF_INIT
;
45 /* throw some random (legitimate) diffs in with the given invalid
48 git_buf_puts(&buf
, PATCH_ORIGINAL_TO_CHANGE_FIRSTLINE
);
49 git_buf_puts(&buf
, PATCH_BINARY_DELTA
);
50 git_buf_puts(&buf
, invalid_diff
);
51 git_buf_puts(&buf
, PATCH_ORIGINAL_TO_CHANGE_MIDDLE
);
52 git_buf_puts(&buf
, PATCH_BINARY_LITERAL
);
54 cl_git_fail_with(GIT_ERROR
,
55 git_diff_from_buffer(&diff
, buf
.ptr
, buf
.size
));
57 git_buf_dispose(&buf
);
60 void test_diff_parse__exact_rename(void)
64 " old_name.c => new_name.c | 0\n"
65 " 1 file changed, 0 insertions(+), 0 deletions(-)\n"
66 " rename old_name.c => new_name.c (100%)\n"
68 "diff --git a/old_name.c b/new_name.c\n"
69 "similarity index 100%\n"
70 "rename from old_name.c\n"
71 "rename to new_name.c\n"
76 cl_git_pass(git_diff_from_buffer(
77 &diff
, content
, strlen(content
)));
81 void test_diff_parse__invalid_patches_fails(void)
83 test_parse_invalid_diff(PATCH_CORRUPT_MISSING_NEW_FILE
);
84 test_parse_invalid_diff(PATCH_CORRUPT_MISSING_OLD_FILE
);
85 test_parse_invalid_diff(PATCH_CORRUPT_NO_CHANGES
);
86 test_parse_invalid_diff(PATCH_CORRUPT_MISSING_HUNK_HEADER
);
89 static void test_tree_to_tree_computed_to_parsed(
90 const char *sandbox
, const char *a_id
, const char *b_id
,
91 uint32_t diff_flags
, uint32_t find_flags
)
94 git_diff
*computed
, *parsed
;
96 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
97 git_diff_find_options findopts
= GIT_DIFF_FIND_OPTIONS_INIT
;
98 git_buf computed_buf
= GIT_BUF_INIT
;
100 repo
= cl_git_sandbox_init(sandbox
);
102 opts
.id_abbrev
= GIT_OID_HEXSZ
;
103 opts
.flags
= GIT_DIFF_SHOW_BINARY
| diff_flags
;
104 findopts
.flags
= find_flags
;
106 cl_assert((a
= resolve_commit_oid_to_tree(repo
, a_id
)) != NULL
);
107 cl_assert((b
= resolve_commit_oid_to_tree(repo
, b_id
)) != NULL
);
109 cl_git_pass(git_diff_tree_to_tree(&computed
, repo
, a
, b
, &opts
));
112 cl_git_pass(git_diff_find_similar(computed
, &findopts
));
114 cl_git_pass(git_diff_to_buf(&computed_buf
,
115 computed
, GIT_DIFF_FORMAT_PATCH
));
117 cl_git_pass(git_diff_from_buffer(&parsed
,
118 computed_buf
.ptr
, computed_buf
.size
));
120 diff_assert_equal(computed
, parsed
);
125 git_diff_free(computed
);
126 git_diff_free(parsed
);
128 git_buf_dispose(&computed_buf
);
130 cl_git_sandbox_cleanup();
133 void test_diff_parse__can_parse_generated_diff(void)
135 test_tree_to_tree_computed_to_parsed(
136 "diff", "d70d245e", "7a9e0b02", 0, 0);
137 test_tree_to_tree_computed_to_parsed(
138 "unsymlinked.git", "806999", "a8595c", 0, 0);
139 test_tree_to_tree_computed_to_parsed("diff",
140 "d70d245ed97ed2aa596dd1af6536e4bfdb047b69",
141 "7a9e0b02e63179929fed24f0a3e0f19168114d10", 0, 0);
142 test_tree_to_tree_computed_to_parsed(
143 "unsymlinked.git", "7fccd7", "806999", 0, 0);
144 test_tree_to_tree_computed_to_parsed(
145 "unsymlinked.git", "7fccd7", "a8595c", 0, 0);
146 test_tree_to_tree_computed_to_parsed(
147 "attr", "605812a", "370fe9ec22", 0, 0);
148 test_tree_to_tree_computed_to_parsed(
149 "attr", "f5b0af1fb4f5c", "370fe9ec22", 0, 0);
150 test_tree_to_tree_computed_to_parsed(
151 "diff", "d70d245e", "d70d245e", 0, 0);
152 test_tree_to_tree_computed_to_parsed("diff_format_email",
153 "873806f6f27e631eb0b23e4b56bea2bfac14a373",
154 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
155 GIT_DIFF_SHOW_BINARY
, 0);
156 test_tree_to_tree_computed_to_parsed("diff_format_email",
157 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
158 "873806f6f27e631eb0b23e4b56bea2bfac14a373",
159 GIT_DIFF_SHOW_BINARY
, 0);
160 test_tree_to_tree_computed_to_parsed("renames",
161 "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2",
162 "2bc7f351d20b53f1c72c16c4b036e491c478c49a",
163 0, GIT_DIFF_FIND_RENAMES
);
164 test_tree_to_tree_computed_to_parsed("renames",
165 "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2",
166 "2bc7f351d20b53f1c72c16c4b036e491c478c49a",
167 GIT_DIFF_INCLUDE_UNMODIFIED
,
169 test_tree_to_tree_computed_to_parsed("renames",
170 "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2",
171 "2bc7f351d20b53f1c72c16c4b036e491c478c49a",
172 GIT_DIFF_INCLUDE_UNMODIFIED
,
173 GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED
| GIT_DIFF_FIND_EXACT_MATCH_ONLY
);
176 void test_diff_parse__get_patch_from_diff(void)
178 git_repository
*repo
;
179 git_diff
*computed
, *parsed
;
181 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
182 git_buf computed_buf
= GIT_BUF_INIT
;
183 git_patch
*patch_computed
, *patch_parsed
;
185 repo
= cl_git_sandbox_init("diff");
187 opts
.flags
= GIT_DIFF_SHOW_BINARY
;
189 cl_assert((a
= resolve_commit_oid_to_tree(repo
,
190 "d70d245ed97ed2aa596dd1af6536e4bfdb047b69")) != NULL
);
191 cl_assert((b
= resolve_commit_oid_to_tree(repo
,
192 "7a9e0b02e63179929fed24f0a3e0f19168114d10")) != NULL
);
194 cl_git_pass(git_diff_tree_to_tree(&computed
, repo
, a
, b
, &opts
));
195 cl_git_pass(git_diff_to_buf(&computed_buf
,
196 computed
, GIT_DIFF_FORMAT_PATCH
));
197 cl_git_pass(git_patch_from_diff(&patch_computed
, computed
, 0));
199 cl_git_pass(git_diff_from_buffer(&parsed
,
200 computed_buf
.ptr
, computed_buf
.size
));
201 cl_git_pass(git_patch_from_diff(&patch_parsed
, parsed
, 0));
204 git_patch_num_hunks(patch_computed
),
205 git_patch_num_hunks(patch_parsed
));
207 git_patch_free(patch_computed
);
208 git_patch_free(patch_parsed
);
213 git_diff_free(computed
);
214 git_diff_free(parsed
);
216 git_buf_dispose(&computed_buf
);
218 cl_git_sandbox_cleanup();
221 static int file_cb(const git_diff_delta
*delta
, float progress
, void *payload
)
223 int *called
= (int *) payload
;
225 GIT_UNUSED(progress
);
230 void test_diff_parse__foreach_works_with_parsed_patch(void)
233 "diff --git a/obj1 b/obj2\n"
234 "index 1234567..7654321 10644\n"
243 cl_git_pass(git_diff_from_buffer(&diff
, patch
, strlen(patch
)));
244 cl_git_pass(git_diff_foreach(diff
, file_cb
, NULL
, NULL
, NULL
, &called
));
245 cl_assert_equal_i(called
, 1);
250 void test_diff_parse__parsing_minimal_patch_succeeds(void)
253 "diff --git a/obj1 b/obj2\n"
254 "index 1234567..7654321 10644\n"
260 git_buf buf
= GIT_BUF_INIT
;
263 cl_git_pass(git_diff_from_buffer(&diff
, patch
, strlen(patch
)));
264 cl_git_pass(git_diff_to_buf(&buf
, diff
, GIT_DIFF_FORMAT_PATCH
));
265 cl_assert_equal_s(patch
, buf
.ptr
);
268 git_buf_dispose(&buf
);
271 void test_diff_parse__patch_roundtrip_succeeds(void)
273 const char buf1
[] = "a\n", buf2
[] = "b\n";
274 git_buf patchbuf
= GIT_BUF_INIT
, diffbuf
= GIT_BUF_INIT
;
278 cl_git_pass(git_patch_from_buffers(&patch
, buf1
, strlen(buf1
), "obj1", buf2
, strlen(buf2
), "obj2", NULL
));
279 cl_git_pass(git_patch_to_buf(&patchbuf
, patch
));
281 cl_git_pass(git_diff_from_buffer(&diff
, patchbuf
.ptr
, patchbuf
.size
));
282 cl_git_pass(git_diff_to_buf(&diffbuf
, diff
, GIT_DIFF_FORMAT_PATCH
));
284 cl_assert_equal_s(patchbuf
.ptr
, diffbuf
.ptr
);
286 git_patch_free(patch
);
288 git_buf_dispose(&patchbuf
);
289 git_buf_dispose(&diffbuf
);
292 #define cl_assert_equal_i_src(i1,i2,file,line) clar__assert_equal(file,line,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2))
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
)
296 const git_diff_line
*line
;
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
);
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__)
308 void test_diff_parse__issue4672(void)
310 const char *text
= "diff --git a/a b/a\n"
311 "index 7f129fd..af431f2 100644\n"
320 const git_diff_hunk
*hunk
;
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));
327 cl_git_assert_lineinfo(3, -1, 1, patch
, 0, l
++);
328 cl_git_assert_lineinfo(-1, 3, 1, patch
, 0, l
++);
330 cl_assert_equal_i(n
, l
);
332 git_patch_free(patch
);
336 void test_diff_parse__lineinfo(void)
338 const char *text
= PATCH_ORIGINAL_TO_CHANGE_MIDDLE
;
341 const git_diff_hunk
*hunk
;
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));
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
++);
357 cl_assert_equal_i(n
, l
);
359 git_patch_free(patch
);
364 void test_diff_parse__new_file_with_space(void)
366 const char *content
= PATCH_ORIGINAL_NEW_FILE_WITH_SPACE
;
370 cl_git_pass(git_diff_from_buffer(&diff
, content
, strlen(content
)));
371 cl_git_pass(git_patch_from_diff((git_patch
**) &patch
, diff
, 0));
373 cl_assert_equal_p(patch
->diff_opts
.old_prefix
, NULL
);
374 cl_assert_equal_p(patch
->delta
->old_file
.path
, NULL
);
375 cl_assert_equal_s(patch
->diff_opts
.new_prefix
, "b/");
376 cl_assert_equal_s(patch
->delta
->new_file
.path
, "sp ace.txt");
378 git_patch_free(patch
);
382 void test_diff_parse__crlf(void)
384 const char *text
= PATCH_CRLF
;
387 const git_diff_delta
*delta
;
389 cl_git_pass(git_diff_from_buffer(&diff
, text
, strlen(text
)));
390 cl_git_pass(git_patch_from_diff(&patch
, diff
, 0));
391 delta
= git_patch_get_delta(patch
);
393 cl_assert_equal_s(delta
->old_file
.path
, "test-file");
394 cl_assert_equal_s(delta
->new_file
.path
, "test-file");
396 git_patch_free(patch
);