]> git.proxmox.com Git - libgit2.git/blob - tests/diff/binary.c
New upstream version 1.4.3+dfsg.1
[libgit2.git] / tests / diff / binary.c
1 #include "clar_libgit2.h"
2
3 #include "git2/sys/diff.h"
4
5 #include "delta.h"
6 #include "filebuf.h"
7 #include "repository.h"
8
9 static git_repository *repo;
10
11 void test_diff_binary__initialize(void)
12 {
13 }
14
15 void test_diff_binary__cleanup(void)
16 {
17 cl_git_sandbox_cleanup();
18 }
19
20 static void test_patch(
21 const char *one,
22 const char *two,
23 const git_diff_options *opts,
24 const char *expected)
25 {
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;
30 git_diff *diff;
31 git_patch *patch;
32 git_buf actual = GIT_BUF_INIT;
33
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));
37
38 if (two) {
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));
42 } else {
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));
46 }
47
48 cl_git_pass(git_diff_tree_to_tree(&diff, repo, tree_one, tree_two, opts));
49
50 cl_git_pass(git_patch_from_diff(&patch, diff, 0));
51 cl_git_pass(git_patch_to_buf(&actual, patch));
52
53 cl_assert_equal_s(expected, actual.ptr);
54
55 git_buf_dispose(&actual);
56 cl_git_pass(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, git_diff_print_callback__to_buf, &actual));
57
58 cl_assert_equal_s(expected, actual.ptr);
59
60 git_buf_dispose(&actual);
61 git_patch_free(patch);
62 git_diff_free(diff);
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);
68 }
69
70 void test_diff_binary__add_normal(void)
71 {
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";
78
79 repo = cl_git_sandbox_init("diff_format_email");
80 test_patch(
81 "873806f6f27e631eb0b23e4b56bea2bfac14a373",
82 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
83 &opts,
84 expected);
85 }
86
87 void test_diff_binary__add(void)
88 {
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" \
95 "literal 3\n" \
96 "Kc${Nk-~s>u4FC%O\n"
97 "\n" \
98 "literal 0\n" \
99 "Hc$@<O00001\n" \
100 "\n";
101
102 opts.flags = GIT_DIFF_SHOW_BINARY;
103 opts.id_abbrev = GIT_OID_HEXSZ;
104
105 repo = cl_git_sandbox_init("diff_format_email");
106 test_patch(
107 "873806f6f27e631eb0b23e4b56bea2bfac14a373",
108 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
109 &opts,
110 expected);
111 }
112
113 void test_diff_binary__modify_normal(void)
114 {
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";
120
121 repo = cl_git_sandbox_init("diff_format_email");
122 test_patch(
123 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
124 "8d7523f6fcb2404257889abe0d96f093d9f524f9",
125 &opts,
126 expected);
127 }
128
129 void test_diff_binary__modify(void)
130 {
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" \
136 "literal 5\n" \
137 "Mc${NkU}WL~000&M4gdfE\n" \
138 "\n" \
139 "literal 3\n" \
140 "Kc${Nk-~s>u4FC%O\n" \
141 "\n";
142
143 opts.flags = GIT_DIFF_SHOW_BINARY;
144
145 repo = cl_git_sandbox_init("diff_format_email");
146 test_patch(
147 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
148 "8d7523f6fcb2404257889abe0d96f093d9f524f9",
149 &opts,
150 expected);
151 }
152
153 void test_diff_binary__delete_normal(void)
154 {
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";
161
162 repo = cl_git_sandbox_init("diff_format_email");
163 test_patch(
164 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
165 "873806f6f27e631eb0b23e4b56bea2bfac14a373",
166 &opts,
167 expected);
168 }
169
170 void test_diff_binary__delete(void)
171 {
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" \
178 "literal 0\n" \
179 "Hc$@<O00001\n" \
180 "\n" \
181 "literal 3\n" \
182 "Kc${Nk-~s>u4FC%O\n" \
183 "\n";
184
185 opts.flags = GIT_DIFF_SHOW_BINARY;
186 opts.id_abbrev = GIT_OID_HEXSZ;
187
188 repo = cl_git_sandbox_init("diff_format_email");
189 test_patch(
190 "897d3af16ca9e420cd071b1c4541bd2b91d04c8c",
191 "873806f6f27e631eb0b23e4b56bea2bfac14a373",
192 &opts,
193 expected);
194 }
195
196 void test_diff_binary__delta(void)
197 {
198 git_index *index;
199 git_str contents = GIT_STR_INIT;
200 size_t i;
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" \
206 "delta 198\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" \
210 "\n" \
211 "delta 198\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" \
215 "\n";
216
217 opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
218 opts.id_abbrev = GIT_OID_HEXSZ;
219
220 repo = cl_git_sandbox_init("renames");
221 cl_git_pass(git_repository_index(&index, repo));
222
223 cl_git_pass(git_futils_readbuffer(&contents, "renames/songof7cities.txt"));
224
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);
228 }
229
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));
233
234 test_patch(
235 "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13",
236 NULL,
237 &opts,
238 expected);
239
240 git_index_free(index);
241 git_str_dispose(&contents);
242 }
243
244 void test_diff_binary__delta_append(void)
245 {
246 git_index *index;
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" \
252 "delta 32\n" \
253 "nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
254 "\n" \
255 "delta 7\n" \
256 "Oc%18D`@*{63ljhg(E~C7\n" \
257 "\n";
258
259 opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
260 opts.id_abbrev = GIT_OID_HEXSZ;
261
262 repo = cl_git_sandbox_init("renames");
263 cl_git_pass(git_repository_index(&index, repo));
264
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));
268
269 test_patch(
270 "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13",
271 NULL,
272 &opts,
273 expected);
274
275 git_index_free(index);
276 }
277
278 void test_diff_binary__empty_for_no_diff(void)
279 {
280 git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
281 git_oid id;
282 git_commit *commit;
283 git_tree *tree;
284 git_diff *diff;
285 git_str actual = GIT_STR_INIT;
286
287 opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
288 opts.id_abbrev = GIT_OID_HEXSZ;
289
290 repo = cl_git_sandbox_init("renames");
291
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));
295
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));
298
299 cl_assert_equal_s("", actual.ptr);
300
301 git_str_dispose(&actual);
302 git_diff_free(diff);
303 git_commit_free(commit);
304 git_tree_free(tree);
305 }
306
307 void test_diff_binary__index_to_workdir(void)
308 {
309 git_index *index;
310 git_diff *diff;
311 git_patch *patch;
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" \
318 "delta 32\n" \
319 "nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
320 "\n" \
321 "delta 7\n" \
322 "Oc%18D`@*{63ljhg(E~C7\n" \
323 "\n";
324
325 opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
326 opts.id_abbrev = GIT_OID_HEXSZ;
327
328 repo = cl_git_sandbox_init("renames");
329 cl_git_pass(git_repository_index(&index, repo));
330
331 cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n");
332
333 cl_git_pass(git_diff_index_to_workdir(&diff, repo, index, &opts));
334
335 cl_git_pass(git_patch_from_diff(&patch, diff, 0));
336 cl_git_pass(git_patch_to_buf(&actual, patch));
337
338 cl_assert_equal_s(expected, actual.ptr);
339
340 cl_git_pass(git_index_add_bypath(index, "untimely.txt"));
341 cl_git_pass(git_index_write(index));
342
343 test_patch(
344 "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13",
345 NULL,
346 &opts,
347 expected);
348
349 git_buf_dispose(&actual);
350 git_patch_free(patch);
351 git_diff_free(diff);
352 git_index_free(index);
353 }
354
355 static int print_cb(
356 const git_diff_delta *delta,
357 const git_diff_hunk *hunk,
358 const git_diff_line *line,
359 void *payload)
360 {
361 git_str *buf = (git_str *)payload;
362
363 GIT_UNUSED(delta);
364
365 if (hunk)
366 git_str_put(buf, hunk->header, hunk->header_len);
367
368 if (line)
369 git_str_put(buf, line->content, line->content_len);
370
371 return git_str_oom(buf) ? -1 : 0;
372 }
373
374 void test_diff_binary__print_patch_from_diff(void)
375 {
376 git_index *index;
377 git_diff *diff;
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" \
384 "delta 32\n" \
385 "nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
386 "\n" \
387 "delta 7\n" \
388 "Oc%18D`@*{63ljhg(E~C7\n" \
389 "\n";
390
391 opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
392 opts.id_abbrev = GIT_OID_HEXSZ;
393
394 repo = cl_git_sandbox_init("renames");
395 cl_git_pass(git_repository_index(&index, repo));
396
397 cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n");
398
399 cl_git_pass(git_diff_index_to_workdir(&diff, repo, index, &opts));
400
401 cl_git_pass(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, print_cb, &actual));
402
403 cl_assert_equal_s(expected, actual.ptr);
404
405 git_str_dispose(&actual);
406 git_diff_free(diff);
407 git_index_free(index);
408 }
409
410 struct diff_data {
411 char *old_path;
412 git_oid old_id;
413 git_str old_binary_base85;
414 size_t old_binary_inflatedlen;
415 git_diff_binary_t old_binary_type;
416
417 char *new_path;
418 git_oid new_id;
419 git_str new_binary_base85;
420 size_t new_binary_inflatedlen;
421 git_diff_binary_t new_binary_type;
422 };
423
424 static int file_cb(
425 const git_diff_delta *delta,
426 float progress,
427 void *payload)
428 {
429 struct diff_data *diff_data = payload;
430
431 GIT_UNUSED(progress);
432
433 if (delta->old_file.path)
434 diff_data->old_path = git__strdup(delta->old_file.path);
435
436 if (delta->new_file.path)
437 diff_data->new_path = git__strdup(delta->new_file.path);
438
439 git_oid_cpy(&diff_data->old_id, &delta->old_file.id);
440 git_oid_cpy(&diff_data->new_id, &delta->new_file.id);
441
442 return 0;
443 }
444
445 static int binary_cb(
446 const git_diff_delta *delta,
447 const git_diff_binary *binary,
448 void *payload)
449 {
450 struct diff_data *diff_data = payload;
451
452 GIT_UNUSED(delta);
453
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;
458
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;
463
464 return 0;
465 }
466
467 static int hunk_cb(
468 const git_diff_delta *delta,
469 const git_diff_hunk *hunk,
470 void *payload)
471 {
472 GIT_UNUSED(delta);
473 GIT_UNUSED(hunk);
474 GIT_UNUSED(payload);
475
476 cl_fail("did not expect hunk callback");
477 return 0;
478 }
479
480 static int line_cb(
481 const git_diff_delta *delta,
482 const git_diff_hunk *hunk,
483 const git_diff_line *line,
484 void *payload)
485 {
486 GIT_UNUSED(delta);
487 GIT_UNUSED(hunk);
488 GIT_UNUSED(line);
489 GIT_UNUSED(payload);
490
491 cl_fail("did not expect line callback");
492 return 0;
493 }
494
495 void test_diff_binary__blob_to_blob(void)
496 {
497 git_index *index;
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};
502
503 opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
504 opts.id_abbrev = GIT_OID_HEXSZ;
505
506 repo = cl_git_sandbox_init("renames");
507 cl_git_pass(git_repository_index__weakptr(&index, repo));
508
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));
512
513 git_oid_fromstr(&old_id, "9a69d960ae94b060f56c2a8702545e2bb1abb935");
514 git_oid_fromstr(&new_id, "1111d4f11f4b35bf6759e0fb714fe09731ef0840");
515
516 cl_git_pass(git_blob_lookup(&old_blob, repo, &old_id));
517 cl_git_pass(git_blob_lookup(&new_blob, repo, &new_id));
518
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));
522
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);
529
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);
536
537 git_blob_free(old_blob);
538 git_blob_free(new_blob);
539
540 git__free(diff_data.old_path);
541 git__free(diff_data.new_path);
542
543 git_str_dispose(&diff_data.old_binary_base85);
544 git_str_dispose(&diff_data.new_binary_base85);
545 }