1 #include "clar_libgit2.h"
3 #include "git2/sys/diff.h"
7 #include "repository.h"
9 static git_repository
*repo
;
11 void test_diff_binary__initialize(void)
15 void test_diff_binary__cleanup(void)
17 cl_git_sandbox_cleanup();
20 static void test_patch(
23 const git_diff_options
*opts
,
26 git_oid id_one
, id_two
;
27 git_index
*index
= NULL
;
28 git_commit
*commit_one
, *commit_two
= NULL
;
29 git_tree
*tree_one
, *tree_two
;
32 git_buf actual
= GIT_BUF_INIT
;
34 cl_git_pass(git_oid_fromstr(&id_one
, one
));
35 cl_git_pass(git_commit_lookup(&commit_one
, repo
, &id_one
));
36 cl_git_pass(git_commit_tree(&tree_one
, commit_one
));
39 cl_git_pass(git_oid_fromstr(&id_two
, two
));
40 cl_git_pass(git_commit_lookup(&commit_two
, repo
, &id_two
));
41 cl_git_pass(git_commit_tree(&tree_two
, commit_two
));
43 cl_git_pass(git_repository_index(&index
, repo
));
44 cl_git_pass(git_index_write_tree(&id_two
, index
));
45 cl_git_pass(git_tree_lookup(&tree_two
, repo
, &id_two
));
48 cl_git_pass(git_diff_tree_to_tree(&diff
, repo
, tree_one
, tree_two
, opts
));
50 cl_git_pass(git_patch_from_diff(&patch
, diff
, 0));
51 cl_git_pass(git_patch_to_buf(&actual
, patch
));
53 cl_assert_equal_s(expected
, actual
.ptr
);
55 git_buf_dispose(&actual
);
56 cl_git_pass(git_diff_print(diff
, GIT_DIFF_FORMAT_PATCH
, git_diff_print_callback__to_buf
, &actual
));
58 cl_assert_equal_s(expected
, actual
.ptr
);
60 git_buf_dispose(&actual
);
61 git_patch_free(patch
);
63 git_tree_free(tree_one
);
64 git_tree_free(tree_two
);
65 git_commit_free(commit_one
);
66 git_commit_free(commit_two
);
67 git_index_free(index
);
70 void test_diff_binary__add_normal(void)
72 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
73 const char *expected
=
74 "diff --git a/binary.bin b/binary.bin\n" \
75 "new file mode 100644\n" \
76 "index 0000000..bd474b2\n" \
77 "Binary files /dev/null and b/binary.bin differ\n";
79 repo
= cl_git_sandbox_init("diff_format_email");
81 "873806f6f27e631eb0b23e4b56bea2bfac14a373",
82 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
87 void test_diff_binary__add(void)
89 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
90 const char *expected
=
91 "diff --git a/binary.bin b/binary.bin\n" \
92 "new file mode 100644\n" \
93 "index 0000000000000000000000000000000000000000..bd474b2519cc15eab801ff851cc7d50f0dee49a1\n" \
94 "GIT binary patch\n" \
102 opts
.flags
= GIT_DIFF_SHOW_BINARY
;
103 opts
.id_abbrev
= GIT_OID_HEXSZ
;
105 repo
= cl_git_sandbox_init("diff_format_email");
107 "873806f6f27e631eb0b23e4b56bea2bfac14a373",
108 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
113 void test_diff_binary__modify_normal(void)
115 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
116 const char *expected
=
117 "diff --git a/binary.bin b/binary.bin\n" \
118 "index bd474b2..9ac35ff 100644\n" \
119 "Binary files a/binary.bin and b/binary.bin differ\n";
121 repo
= cl_git_sandbox_init("diff_format_email");
123 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
124 "8d7523f6fcb2404257889abe0d96f093d9f524f9",
129 void test_diff_binary__modify(void)
131 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
132 const char *expected
=
133 "diff --git a/binary.bin b/binary.bin\n" \
134 "index bd474b2519cc15eab801ff851cc7d50f0dee49a1..9ac35ff15cd8864aeafd889e4826a3150f0b06c4 100644\n" \
135 "GIT binary patch\n" \
137 "Mc${NkU}WL~000&M4gdfE\n" \
140 "Kc${Nk-~s>u4FC%O\n" \
143 opts
.flags
= GIT_DIFF_SHOW_BINARY
;
145 repo
= cl_git_sandbox_init("diff_format_email");
147 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
148 "8d7523f6fcb2404257889abe0d96f093d9f524f9",
153 void test_diff_binary__delete_normal(void)
155 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
156 const char *expected
=
157 "diff --git a/binary.bin b/binary.bin\n" \
158 "deleted file mode 100644\n" \
159 "index bd474b2..0000000\n" \
160 "Binary files a/binary.bin and /dev/null differ\n";
162 repo
= cl_git_sandbox_init("diff_format_email");
164 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
165 "873806f6f27e631eb0b23e4b56bea2bfac14a373",
170 void test_diff_binary__delete(void)
172 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
173 const char *expected
=
174 "diff --git a/binary.bin b/binary.bin\n" \
175 "deleted file mode 100644\n" \
176 "index bd474b2519cc15eab801ff851cc7d50f0dee49a1..0000000000000000000000000000000000000000\n" \
177 "GIT binary patch\n" \
182 "Kc${Nk-~s>u4FC%O\n" \
185 opts
.flags
= GIT_DIFF_SHOW_BINARY
;
186 opts
.id_abbrev
= GIT_OID_HEXSZ
;
188 repo
= cl_git_sandbox_init("diff_format_email");
190 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
191 "873806f6f27e631eb0b23e4b56bea2bfac14a373",
196 void test_diff_binary__delta(void)
199 git_str contents
= GIT_STR_INIT
;
201 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
202 const char *expected
=
203 "diff --git a/songof7cities.txt b/songof7cities.txt\n" \
204 "index 4210ffd5c390b21dd5483375e75288dea9ede512..cc84ec183351c9944ed90a619ca08911924055b5 100644\n" \
205 "GIT binary patch\n" \
207 "zc$}LmI8{(0BqLQJI6p64AwNwaIJGP_Pa)Ye#M3o+qJ$<Jl;sX*mF<MGCYv&*L7AHu\n" \
208 "zGA1*^gt?gYVN82wTbPO_W)+x<&1+cP;HrPHR>PQ;Y(X&QMK*C5^Br3bjG4d=XI^5@\n" \
209 "JfH567LIG)KJdFSV\n" \
212 "zc$}LmI8{(0BqLQJI6p64AwNwaIJGP_Pr*5}Br~;mqJ$<Jl;sX*mF<MGCYv&*L7AHu\n" \
213 "zGA1*^gt?gYVN82wTbPO_W)+x<&1+cP;HrPHR>PQ;Y(X&QMK*C5^Br3bjG4d=XI^5@\n" \
214 "JfH567LIF3FM2!Fd\n" \
217 opts
.flags
= GIT_DIFF_SHOW_BINARY
| GIT_DIFF_FORCE_BINARY
;
218 opts
.id_abbrev
= GIT_OID_HEXSZ
;
220 repo
= cl_git_sandbox_init("renames");
221 cl_git_pass(git_repository_index(&index
, repo
));
223 cl_git_pass(git_futils_readbuffer(&contents
, "renames/songof7cities.txt"));
225 for (i
= 0; i
< contents
.size
- 6; i
++) {
226 if (strncmp(&contents
.ptr
[i
], "Cities", 6) == 0)
227 memcpy(&contents
.ptr
[i
], "cITIES", 6);
230 cl_git_rewritefile("renames/songof7cities.txt", contents
.ptr
);
231 cl_git_pass(git_index_add_bypath(index
, "songof7cities.txt"));
232 cl_git_pass(git_index_write(index
));
235 "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13",
240 git_index_free(index
);
241 git_str_dispose(&contents
);
244 void test_diff_binary__delta_append(void)
247 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
248 const char *expected
=
249 "diff --git a/untimely.txt b/untimely.txt\n" \
250 "index 9a69d960ae94b060f56c2a8702545e2bb1abb935..1111d4f11f4b35bf6759e0fb714fe09731ef0840 100644\n" \
251 "GIT binary patch\n" \
253 "nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
256 "Oc%18D`@*{63ljhg(E~C7\n" \
259 opts
.flags
= GIT_DIFF_SHOW_BINARY
| GIT_DIFF_FORCE_BINARY
;
260 opts
.id_abbrev
= GIT_OID_HEXSZ
;
262 repo
= cl_git_sandbox_init("renames");
263 cl_git_pass(git_repository_index(&index
, repo
));
265 cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n");
266 cl_git_pass(git_index_add_bypath(index
, "untimely.txt"));
267 cl_git_pass(git_index_write(index
));
270 "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13",
275 git_index_free(index
);
278 void test_diff_binary__empty_for_no_diff(void)
280 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
285 git_str actual
= GIT_STR_INIT
;
287 opts
.flags
= GIT_DIFF_SHOW_BINARY
| GIT_DIFF_FORCE_BINARY
;
288 opts
.id_abbrev
= GIT_OID_HEXSZ
;
290 repo
= cl_git_sandbox_init("renames");
292 cl_git_pass(git_oid_fromstr(&id
, "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13"));
293 cl_git_pass(git_commit_lookup(&commit
, repo
, &id
));
294 cl_git_pass(git_commit_tree(&tree
, commit
));
296 cl_git_pass(git_diff_tree_to_tree(&diff
, repo
, tree
, tree
, &opts
));
297 cl_git_pass(git_diff_print(diff
, GIT_DIFF_FORMAT_PATCH
, git_diff_print_callback__to_buf
, &actual
));
299 cl_assert_equal_s("", actual
.ptr
);
301 git_str_dispose(&actual
);
303 git_commit_free(commit
);
307 void test_diff_binary__index_to_workdir(void)
312 git_buf actual
= GIT_BUF_INIT
;
313 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
314 const char *expected
=
315 "diff --git a/untimely.txt b/untimely.txt\n" \
316 "index 9a69d960ae94b060f56c2a8702545e2bb1abb935..1111d4f11f4b35bf6759e0fb714fe09731ef0840 100644\n" \
317 "GIT binary patch\n" \
319 "nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
322 "Oc%18D`@*{63ljhg(E~C7\n" \
325 opts
.flags
= GIT_DIFF_SHOW_BINARY
| GIT_DIFF_FORCE_BINARY
;
326 opts
.id_abbrev
= GIT_OID_HEXSZ
;
328 repo
= cl_git_sandbox_init("renames");
329 cl_git_pass(git_repository_index(&index
, repo
));
331 cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n");
333 cl_git_pass(git_diff_index_to_workdir(&diff
, repo
, index
, &opts
));
335 cl_git_pass(git_patch_from_diff(&patch
, diff
, 0));
336 cl_git_pass(git_patch_to_buf(&actual
, patch
));
338 cl_assert_equal_s(expected
, actual
.ptr
);
340 cl_git_pass(git_index_add_bypath(index
, "untimely.txt"));
341 cl_git_pass(git_index_write(index
));
344 "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13",
349 git_buf_dispose(&actual
);
350 git_patch_free(patch
);
352 git_index_free(index
);
356 const git_diff_delta
*delta
,
357 const git_diff_hunk
*hunk
,
358 const git_diff_line
*line
,
361 git_str
*buf
= (git_str
*)payload
;
366 git_str_put(buf
, hunk
->header
, hunk
->header_len
);
369 git_str_put(buf
, line
->content
, line
->content_len
);
371 return git_str_oom(buf
) ? -1 : 0;
374 void test_diff_binary__print_patch_from_diff(void)
378 git_str actual
= GIT_STR_INIT
;
379 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
380 const char *expected
=
381 "diff --git a/untimely.txt b/untimely.txt\n" \
382 "index 9a69d960ae94b060f56c2a8702545e2bb1abb935..1111d4f11f4b35bf6759e0fb714fe09731ef0840 100644\n" \
383 "GIT binary patch\n" \
385 "nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
388 "Oc%18D`@*{63ljhg(E~C7\n" \
391 opts
.flags
= GIT_DIFF_SHOW_BINARY
| GIT_DIFF_FORCE_BINARY
;
392 opts
.id_abbrev
= GIT_OID_HEXSZ
;
394 repo
= cl_git_sandbox_init("renames");
395 cl_git_pass(git_repository_index(&index
, repo
));
397 cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n");
399 cl_git_pass(git_diff_index_to_workdir(&diff
, repo
, index
, &opts
));
401 cl_git_pass(git_diff_print(diff
, GIT_DIFF_FORMAT_PATCH
, print_cb
, &actual
));
403 cl_assert_equal_s(expected
, actual
.ptr
);
405 git_str_dispose(&actual
);
407 git_index_free(index
);
413 git_str old_binary_base85
;
414 size_t old_binary_inflatedlen
;
415 git_diff_binary_t old_binary_type
;
419 git_str new_binary_base85
;
420 size_t new_binary_inflatedlen
;
421 git_diff_binary_t new_binary_type
;
425 const git_diff_delta
*delta
,
429 struct diff_data
*diff_data
= payload
;
431 GIT_UNUSED(progress
);
433 if (delta
->old_file
.path
)
434 diff_data
->old_path
= git__strdup(delta
->old_file
.path
);
436 if (delta
->new_file
.path
)
437 diff_data
->new_path
= git__strdup(delta
->new_file
.path
);
439 git_oid_cpy(&diff_data
->old_id
, &delta
->old_file
.id
);
440 git_oid_cpy(&diff_data
->new_id
, &delta
->new_file
.id
);
445 static int binary_cb(
446 const git_diff_delta
*delta
,
447 const git_diff_binary
*binary
,
450 struct diff_data
*diff_data
= payload
;
454 git_str_encode_base85(&diff_data
->old_binary_base85
,
455 binary
->old_file
.data
, binary
->old_file
.datalen
);
456 diff_data
->old_binary_inflatedlen
= binary
->old_file
.inflatedlen
;
457 diff_data
->old_binary_type
= binary
->old_file
.type
;
459 git_str_encode_base85(&diff_data
->new_binary_base85
,
460 binary
->new_file
.data
, binary
->new_file
.datalen
);
461 diff_data
->new_binary_inflatedlen
= binary
->new_file
.inflatedlen
;
462 diff_data
->new_binary_type
= binary
->new_file
.type
;
468 const git_diff_delta
*delta
,
469 const git_diff_hunk
*hunk
,
476 cl_fail("did not expect hunk callback");
481 const git_diff_delta
*delta
,
482 const git_diff_hunk
*hunk
,
483 const git_diff_line
*line
,
491 cl_fail("did not expect line callback");
495 void test_diff_binary__blob_to_blob(void)
498 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
499 git_blob
*old_blob
, *new_blob
;
500 git_oid old_id
, new_id
;
501 struct diff_data diff_data
= {0};
503 opts
.flags
= GIT_DIFF_SHOW_BINARY
| GIT_DIFF_FORCE_BINARY
;
504 opts
.id_abbrev
= GIT_OID_HEXSZ
;
506 repo
= cl_git_sandbox_init("renames");
507 cl_git_pass(git_repository_index__weakptr(&index
, repo
));
509 cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n");
510 cl_git_pass(git_index_add_bypath(index
, "untimely.txt"));
511 cl_git_pass(git_index_write(index
));
513 git_oid_fromstr(&old_id
, "9a69d960ae94b060f56c2a8702545e2bb1abb935");
514 git_oid_fromstr(&new_id
, "1111d4f11f4b35bf6759e0fb714fe09731ef0840");
516 cl_git_pass(git_blob_lookup(&old_blob
, repo
, &old_id
));
517 cl_git_pass(git_blob_lookup(&new_blob
, repo
, &new_id
));
519 cl_git_pass(git_diff_blobs(old_blob
,
520 "untimely.txt", new_blob
, "untimely.txt", &opts
,
521 file_cb
, binary_cb
, hunk_cb
, line_cb
, &diff_data
));
523 cl_assert_equal_s("untimely.txt", diff_data
.old_path
);
524 cl_assert_equal_oid(&old_id
, &diff_data
.old_id
);
525 cl_assert_equal_i(GIT_DIFF_BINARY_DELTA
, diff_data
.old_binary_type
);
526 cl_assert_equal_i(7, diff_data
.old_binary_inflatedlen
);
527 cl_assert_equal_s("c%18D`@*{63ljhg(E~C7",
528 diff_data
.old_binary_base85
.ptr
);
530 cl_assert_equal_s("untimely.txt", diff_data
.new_path
);
531 cl_assert_equal_oid(&new_id
, &diff_data
.new_id
);
532 cl_assert_equal_i(GIT_DIFF_BINARY_DELTA
, diff_data
.new_binary_type
);
533 cl_assert_equal_i(32, diff_data
.new_binary_inflatedlen
);
534 cl_assert_equal_s("c%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW",
535 diff_data
.new_binary_base85
.ptr
);
537 git_blob_free(old_blob
);
538 git_blob_free(new_blob
);
540 git__free(diff_data
.old_path
);
541 git__free(diff_data
.new_path
);
543 git_str_dispose(&diff_data
.old_binary_base85
);
544 git_str_dispose(&diff_data
.new_binary_base85
);