]> git.proxmox.com Git - libgit2.git/blame - tests/diff/binary.c
New upstream version 1.4.3+dfsg.1
[libgit2.git] / tests / diff / binary.c
CommitLineData
e349ed50
ET
1#include "clar_libgit2.h"
2
76633215
CMN
3#include "git2/sys/diff.h"
4
4b3ec53c 5#include "delta.h"
e349ed50 6#include "filebuf.h"
9568660f 7#include "repository.h"
e349ed50
ET
8
9static git_repository *repo;
10
11void test_diff_binary__initialize(void)
12{
13}
14
15void test_diff_binary__cleanup(void)
16{
17 cl_git_sandbox_cleanup();
18}
19
e579e0f7 20static void test_patch(
e349ed50
ET
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
e579e0f7 55 git_buf_dispose(&actual);
76633215
CMN
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
ac3d33df 60 git_buf_dispose(&actual);
e349ed50
ET
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
70void 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
87void 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" \
e4b2b919
G
99 "Hc$@<O00001\n" \
100 "\n";
e349ed50
ET
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
113void 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
129void 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" \
e4b2b919
G
140 "Kc${Nk-~s>u4FC%O\n" \
141 "\n";
e349ed50
ET
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
153void 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
170void 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" \
e4b2b919
G
182 "Kc${Nk-~s>u4FC%O\n" \
183 "\n";
e349ed50
ET
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
196void test_diff_binary__delta(void)
197{
198 git_index *index;
e579e0f7 199 git_str contents = GIT_STR_INIT;
e349ed50
ET
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" \
e4b2b919
G
214 "JfH567LIF3FM2!Fd\n" \
215 "\n";
e349ed50
ET
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);
e579e0f7 241 git_str_dispose(&contents);
e349ed50
ET
242}
243
244void 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" \
e4b2b919
G
256 "Oc%18D`@*{63ljhg(E~C7\n" \
257 "\n";
e349ed50
ET
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}
ac7012a8 277
ba8fb7c4
ET
278void 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;
e579e0f7 285 git_str actual = GIT_STR_INIT;
ba8fb7c4
ET
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
e579e0f7 301 git_str_dispose(&actual);
ba8fb7c4
ET
302 git_diff_free(diff);
303 git_commit_free(commit);
304 git_tree_free(tree);
305}
306
ac7012a8
ET
307void 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" \
e4b2b919
G
322 "Oc%18D`@*{63ljhg(E~C7\n" \
323 "\n";
ac7012a8
ET
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
ac3d33df 349 git_buf_dispose(&actual);
ac7012a8
ET
350 git_patch_free(patch);
351 git_diff_free(diff);
352 git_index_free(index);
353}
354
355static 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{
e579e0f7 361 git_str *buf = (git_str *)payload;
ac7012a8 362
0f4d9c03
POL
363 GIT_UNUSED(delta);
364
ac7012a8 365 if (hunk)
e579e0f7 366 git_str_put(buf, hunk->header, hunk->header_len);
ac7012a8
ET
367
368 if (line)
e579e0f7 369 git_str_put(buf, line->content, line->content_len);
ac7012a8 370
e579e0f7 371 return git_str_oom(buf) ? -1 : 0;
ac7012a8
ET
372}
373
374void test_diff_binary__print_patch_from_diff(void)
375{
376 git_index *index;
377 git_diff *diff;
e579e0f7 378 git_str actual = GIT_STR_INIT;
ac7012a8
ET
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" \
e4b2b919
G
388 "Oc%18D`@*{63ljhg(E~C7\n" \
389 "\n";
ac7012a8
ET
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
e579e0f7 405 git_str_dispose(&actual);
ac7012a8
ET
406 git_diff_free(diff);
407 git_index_free(index);
408}
391281ae
ET
409
410struct diff_data {
411 char *old_path;
412 git_oid old_id;
e579e0f7 413 git_str old_binary_base85;
391281ae
ET
414 size_t old_binary_inflatedlen;
415 git_diff_binary_t old_binary_type;
416
417 char *new_path;
418 git_oid new_id;
e579e0f7 419 git_str new_binary_base85;
391281ae
ET
420 size_t new_binary_inflatedlen;
421 git_diff_binary_t new_binary_type;
422};
423
424static int file_cb(
425 const git_diff_delta *delta,
426 float progress,
427 void *payload)
428{
429 struct diff_data *diff_data = payload;
430
0f4d9c03
POL
431 GIT_UNUSED(progress);
432
391281ae
ET
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
445static 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
0f4d9c03
POL
452 GIT_UNUSED(delta);
453
e579e0f7 454 git_str_encode_base85(&diff_data->old_binary_base85,
391281ae
ET
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
e579e0f7 459 git_str_encode_base85(&diff_data->new_binary_base85,
391281ae
ET
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
467static int hunk_cb(
468 const git_diff_delta *delta,
469 const git_diff_hunk *hunk,
470 void *payload)
471{
0f4d9c03
POL
472 GIT_UNUSED(delta);
473 GIT_UNUSED(hunk);
474 GIT_UNUSED(payload);
475
391281ae
ET
476 cl_fail("did not expect hunk callback");
477 return 0;
478}
479
480static 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{
0f4d9c03
POL
486 GIT_UNUSED(delta);
487 GIT_UNUSED(hunk);
488 GIT_UNUSED(line);
489 GIT_UNUSED(payload);
490
391281ae
ET
491 cl_fail("did not expect line callback");
492 return 0;
493}
494
495void 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};
391281ae
ET
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");
9568660f 507 cl_git_pass(git_repository_index__weakptr(&index, repo));
391281ae
ET
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);
9568660f 542
e579e0f7
MB
543 git_str_dispose(&diff_data.old_binary_base85);
544 git_str_dispose(&diff_data.new_binary_base85);
391281ae 545}