1 #include "clar_libgit2.h"
2 #include "diff_helpers.h"
5 "diff --git a/file b/file\n" \
6 "index 45141a7..4d713dc 100644\n" \
10 " Hello from the root\n" \
12 "+Some additional lines\n" \
14 "+Down here below\n" \
17 static git_repository
*g_repo
= NULL
;
18 static diff_expects expected
;
19 static git_diff_options opts
;
20 static git_blob
*d
, *alien
;
22 static void quick_diff_blob_to_str(
23 const git_blob
*blob
, const char *blob_path
,
24 const char *str
, size_t len
, const char *str_path
)
26 memset(&expected
, 0, sizeof(expected
));
31 cl_git_pass(git_diff_blob_to_buffer(
32 blob
, blob_path
, str
, len
, str_path
,
33 &opts
, diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
36 void test_diff_blob__initialize(void)
40 g_repo
= cl_git_sandbox_init("attr");
42 cl_git_pass(git_diff_options_init(&opts
, GIT_DIFF_OPTIONS_VERSION
));
43 opts
.context_lines
= 1;
45 memset(&expected
, 0, sizeof(expected
));
47 /* tests/resources/attr/root_test4.txt */
48 cl_git_pass(git_oid_fromstrn(&oid
, "a0f7217a", 8));
49 cl_git_pass(git_blob_lookup_prefix(&d
, g_repo
, &oid
, 8));
52 cl_git_pass(git_oid_fromstrn(&oid
, "edf3dcee", 8));
53 cl_git_pass(git_blob_lookup_prefix(&alien
, g_repo
, &oid
, 8));
56 void test_diff_blob__cleanup(void)
64 cl_git_sandbox_cleanup();
67 static void assert_one_modified(
68 int hunks
, int lines
, int ctxt
, int adds
, int dels
, diff_expects
*exp
)
70 cl_assert_equal_i(1, exp
->files
);
71 cl_assert_equal_i(1, exp
->file_status
[GIT_DELTA_MODIFIED
]);
72 cl_assert_equal_i(0, exp
->files_binary
);
74 cl_assert_equal_i(hunks
, exp
->hunks
);
75 cl_assert_equal_i(lines
, exp
->lines
);
76 cl_assert_equal_i(ctxt
, exp
->line_ctxt
);
77 cl_assert_equal_i(adds
, exp
->line_adds
);
78 cl_assert_equal_i(dels
, exp
->line_dels
);
81 void test_diff_blob__patch_with_freed_blobs(void)
86 git_buf buf
= GIT_BUF_INIT
;
88 /* tests/resources/attr/root_test1 */
89 cl_git_pass(git_oid_fromstrn(&a_oid
, "45141a79", 8));
90 cl_git_pass(git_blob_lookup_prefix(&a
, g_repo
, &a_oid
, 4));
91 /* tests/resources/attr/root_test2 */
92 cl_git_pass(git_oid_fromstrn(&b_oid
, "4d713dc4", 8));
93 cl_git_pass(git_blob_lookup_prefix(&b
, g_repo
, &b_oid
, 4));
95 cl_git_pass(git_patch_from_blobs(&p
, a
, NULL
, b
, NULL
, NULL
));
100 cl_git_pass(git_patch_to_buf(&buf
, p
));
101 cl_assert_equal_s(buf
.ptr
, BLOB_DIFF
);
104 git_buf_dispose(&buf
);
107 void test_diff_blob__can_compare_text_blobs(void)
110 git_oid a_oid
, b_oid
, c_oid
;
112 /* tests/resources/attr/root_test1 */
113 cl_git_pass(git_oid_fromstrn(&a_oid
, "45141a79", 8));
114 cl_git_pass(git_blob_lookup_prefix(&a
, g_repo
, &a_oid
, 4));
116 /* tests/resources/attr/root_test2 */
117 cl_git_pass(git_oid_fromstrn(&b_oid
, "4d713dc4", 8));
118 cl_git_pass(git_blob_lookup_prefix(&b
, g_repo
, &b_oid
, 4));
120 /* tests/resources/attr/root_test3 */
121 cl_git_pass(git_oid_fromstrn(&c_oid
, "c96bbb2c2557a832", 16));
122 cl_git_pass(git_blob_lookup_prefix(&c
, g_repo
, &c_oid
, 16));
124 /* Doing the equivalent of a `git diff -U1` on these files */
126 /* diff on tests/resources/attr/root_test1 */
127 memset(&expected
, 0, sizeof(expected
));
128 cl_git_pass(git_diff_blobs(
129 a
, NULL
, b
, NULL
, &opts
,
130 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
131 assert_one_modified(1, 6, 1, 5, 0, &expected
);
133 /* same diff but use direct buffers */
134 memset(&expected
, 0, sizeof(expected
));
135 cl_git_pass(git_diff_buffers(
136 git_blob_rawcontent(a
), (size_t)git_blob_rawsize(a
), NULL
,
137 git_blob_rawcontent(b
), (size_t)git_blob_rawsize(b
), NULL
, &opts
,
138 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
139 assert_one_modified(1, 6, 1, 5, 0, &expected
);
141 /* diff on tests/resources/attr/root_test2 */
142 memset(&expected
, 0, sizeof(expected
));
143 cl_git_pass(git_diff_blobs(
144 b
, NULL
, c
, NULL
, &opts
,
145 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
146 assert_one_modified(1, 15, 3, 9, 3, &expected
);
148 /* diff on tests/resources/attr/root_test3 */
149 memset(&expected
, 0, sizeof(expected
));
150 cl_git_pass(git_diff_blobs(
151 a
, NULL
, c
, NULL
, &opts
,
152 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
153 assert_one_modified(1, 13, 0, 12, 1, &expected
);
155 memset(&expected
, 0, sizeof(expected
));
156 cl_git_pass(git_diff_blobs(
157 c
, NULL
, d
, NULL
, &opts
,
158 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
159 assert_one_modified(2, 14, 4, 6, 4, &expected
);
166 static void assert_patch_matches_blobs(
167 git_patch
*p
, git_blob
*a
, git_blob
*b
,
168 int hunks
, int l0
, int l1
, int ctxt
, int adds
, int dels
)
170 const git_diff_delta
*delta
;
173 cl_assert(p
!= NULL
);
175 delta
= git_patch_get_delta(p
);
176 cl_assert(delta
!= NULL
);
178 cl_assert_equal_i(GIT_DELTA_MODIFIED
, delta
->status
);
179 cl_assert_equal_oid(git_blob_id(a
), &delta
->old_file
.id
);
180 cl_assert_equal_sz(git_blob_rawsize(a
), delta
->old_file
.size
);
181 cl_assert_equal_oid(git_blob_id(b
), &delta
->new_file
.id
);
182 cl_assert_equal_sz(git_blob_rawsize(b
), delta
->new_file
.size
);
184 cl_assert_equal_i(hunks
, (int)git_patch_num_hunks(p
));
187 cl_assert_equal_i(l0
, git_patch_num_lines_in_hunk(p
, 0));
189 cl_assert_equal_i(l1
, git_patch_num_lines_in_hunk(p
, 1));
191 cl_git_pass(git_patch_line_stats(&tc
, &ta
, &td
, p
));
192 cl_assert_equal_i(ctxt
, (int)tc
);
193 cl_assert_equal_i(adds
, (int)ta
);
194 cl_assert_equal_i(dels
, (int)td
);
197 void test_diff_blob__can_compare_text_blobs_with_patch(void)
200 git_oid a_oid
, b_oid
, c_oid
;
203 /* tests/resources/attr/root_test1 */
204 cl_git_pass(git_oid_fromstrn(&a_oid
, "45141a79", 8));
205 cl_git_pass(git_blob_lookup_prefix(&a
, g_repo
, &a_oid
, 8));
207 /* tests/resources/attr/root_test2 */
208 cl_git_pass(git_oid_fromstrn(&b_oid
, "4d713dc4", 8));
209 cl_git_pass(git_blob_lookup_prefix(&b
, g_repo
, &b_oid
, 8));
211 /* tests/resources/attr/root_test3 */
212 cl_git_pass(git_oid_fromstrn(&c_oid
, "c96bbb2c2557a832", 16));
213 cl_git_pass(git_blob_lookup_prefix(&c
, g_repo
, &c_oid
, 16));
215 /* Doing the equivalent of a `git diff -U1` on these files */
217 /* diff on tests/resources/attr/root_test1 */
218 cl_git_pass(git_patch_from_blobs(&p
, a
, NULL
, b
, NULL
, &opts
));
219 assert_patch_matches_blobs(p
, a
, b
, 1, 6, 0, 1, 5, 0);
222 /* diff on tests/resources/attr/root_test2 */
223 cl_git_pass(git_patch_from_blobs(&p
, b
, NULL
, c
, NULL
, &opts
));
224 assert_patch_matches_blobs(p
, b
, c
, 1, 15, 0, 3, 9, 3);
227 /* diff on tests/resources/attr/root_test3 */
228 cl_git_pass(git_patch_from_blobs(&p
, a
, NULL
, c
, NULL
, &opts
));
229 assert_patch_matches_blobs(p
, a
, c
, 1, 13, 0, 0, 12, 1);
233 cl_git_pass(git_patch_from_blobs(&p
, c
, NULL
, d
, NULL
, &opts
));
234 assert_patch_matches_blobs(p
, c
, d
, 2, 5, 9, 4, 6, 4);
242 void test_diff_blob__can_compare_against_null_blobs(void)
246 cl_git_pass(git_diff_blobs(
247 d
, NULL
, e
, NULL
, &opts
,
248 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
250 cl_assert_equal_i(1, expected
.files
);
251 cl_assert_equal_i(1, expected
.file_status
[GIT_DELTA_DELETED
]);
252 cl_assert_equal_i(0, expected
.files_binary
);
254 cl_assert_equal_i(1, expected
.hunks
);
255 cl_assert_equal_i(14, expected
.hunk_old_lines
);
256 cl_assert_equal_i(14, expected
.lines
);
257 cl_assert_equal_i(14, expected
.line_dels
);
259 opts
.flags
|= GIT_DIFF_REVERSE
;
260 memset(&expected
, 0, sizeof(expected
));
262 cl_git_pass(git_diff_blobs(
263 d
, NULL
, e
, NULL
, &opts
,
264 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
266 cl_assert_equal_i(1, expected
.files
);
267 cl_assert_equal_i(1, expected
.file_status
[GIT_DELTA_ADDED
]);
268 cl_assert_equal_i(0, expected
.files_binary
);
270 cl_assert_equal_i(1, expected
.hunks
);
271 cl_assert_equal_i(14, expected
.hunk_new_lines
);
272 cl_assert_equal_i(14, expected
.lines
);
273 cl_assert_equal_i(14, expected
.line_adds
);
275 opts
.flags
^= GIT_DIFF_REVERSE
;
276 memset(&expected
, 0, sizeof(expected
));
278 cl_git_pass(git_diff_blobs(
279 alien
, NULL
, NULL
, NULL
, &opts
,
280 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
282 cl_assert_equal_i(1, expected
.files
);
283 cl_assert_equal_i(1, expected
.files_binary
);
284 cl_assert_equal_i(1, expected
.file_status
[GIT_DELTA_DELETED
]);
285 cl_assert_equal_i(0, expected
.hunks
);
286 cl_assert_equal_i(0, expected
.lines
);
288 memset(&expected
, 0, sizeof(expected
));
290 cl_git_pass(git_diff_blobs(
291 NULL
, NULL
, alien
, NULL
, &opts
,
292 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
294 cl_assert_equal_i(1, expected
.files
);
295 cl_assert_equal_i(1, expected
.files_binary
);
296 cl_assert_equal_i(1, expected
.file_status
[GIT_DELTA_ADDED
]);
297 cl_assert_equal_i(0, expected
.hunks
);
298 cl_assert_equal_i(0, expected
.lines
);
301 void test_diff_blob__can_compare_against_null_blobs_with_patch(void)
305 const git_diff_delta
*delta
;
306 const git_diff_line
*line
;
309 cl_git_pass(git_patch_from_blobs(&p
, d
, NULL
, e
, NULL
, &opts
));
311 cl_assert(p
!= NULL
);
313 delta
= git_patch_get_delta(p
);
314 cl_assert(delta
!= NULL
);
315 cl_assert_equal_i(GIT_DELTA_DELETED
, delta
->status
);
316 cl_assert_equal_oid(git_blob_id(d
), &delta
->old_file
.id
);
317 cl_assert_equal_sz(git_blob_rawsize(d
), delta
->old_file
.size
);
318 cl_assert(git_oid_is_zero(&delta
->new_file
.id
));
319 cl_assert_equal_sz(0, delta
->new_file
.size
);
321 cl_assert_equal_i(1, (int)git_patch_num_hunks(p
));
322 cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p
, 0));
324 max_l
= git_patch_num_lines_in_hunk(p
, 0);
325 for (l
= 0; l
< max_l
; ++l
) {
326 cl_git_pass(git_patch_get_line_in_hunk(&line
, p
, 0, l
));
327 cl_assert_equal_i(GIT_DIFF_LINE_DELETION
, (int)line
->origin
);
332 opts
.flags
|= GIT_DIFF_REVERSE
;
334 cl_git_pass(git_patch_from_blobs(&p
, d
, NULL
, e
, NULL
, &opts
));
336 cl_assert(p
!= NULL
);
338 delta
= git_patch_get_delta(p
);
339 cl_assert(delta
!= NULL
);
340 cl_assert_equal_i(GIT_DELTA_ADDED
, delta
->status
);
341 cl_assert(git_oid_is_zero(&delta
->old_file
.id
));
342 cl_assert_equal_sz(0, delta
->old_file
.size
);
343 cl_assert_equal_oid(git_blob_id(d
), &delta
->new_file
.id
);
344 cl_assert_equal_sz(git_blob_rawsize(d
), delta
->new_file
.size
);
346 cl_assert_equal_i(1, (int)git_patch_num_hunks(p
));
347 cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p
, 0));
349 max_l
= git_patch_num_lines_in_hunk(p
, 0);
350 for (l
= 0; l
< max_l
; ++l
) {
351 cl_git_pass(git_patch_get_line_in_hunk(&line
, p
, 0, l
));
352 cl_assert_equal_i(GIT_DIFF_LINE_ADDITION
, (int)line
->origin
);
357 opts
.flags
^= GIT_DIFF_REVERSE
;
359 cl_git_pass(git_patch_from_blobs(&p
, alien
, NULL
, NULL
, NULL
, &opts
));
361 cl_assert(p
!= NULL
);
363 delta
= git_patch_get_delta(p
);
364 cl_assert(delta
!= NULL
);
365 cl_assert_equal_i(GIT_DELTA_DELETED
, delta
->status
);
366 cl_assert((delta
->flags
& GIT_DIFF_FLAG_BINARY
) != 0);
368 cl_assert_equal_i(0, (int)git_patch_num_hunks(p
));
372 cl_git_pass(git_patch_from_blobs(&p
, NULL
, NULL
, alien
, NULL
, &opts
));
374 cl_assert(p
!= NULL
);
376 delta
= git_patch_get_delta(p
);
377 cl_assert(delta
!= NULL
);
378 cl_assert_equal_i(GIT_DELTA_ADDED
, delta
->status
);
379 cl_assert((delta
->flags
& GIT_DIFF_FLAG_BINARY
) != 0);
381 cl_assert_equal_i(0, (int)git_patch_num_hunks(p
));
386 static void assert_identical_blobs_comparison(diff_expects
*expected
)
388 cl_assert_equal_i(1, expected
->files
);
389 cl_assert_equal_i(1, expected
->file_status
[GIT_DELTA_UNMODIFIED
]);
390 cl_assert_equal_i(0, expected
->hunks
);
391 cl_assert_equal_i(0, expected
->lines
);
394 void test_diff_blob__can_compare_identical_blobs(void)
396 opts
.flags
|= GIT_DIFF_INCLUDE_UNMODIFIED
;
398 cl_git_pass(git_diff_blobs(
399 d
, NULL
, d
, NULL
, &opts
,
400 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
402 assert_identical_blobs_comparison(&expected
);
403 cl_assert_equal_i(0, expected
.files_binary
);
405 memset(&expected
, 0, sizeof(expected
));
406 cl_git_pass(git_diff_blobs(
407 NULL
, NULL
, NULL
, NULL
, &opts
,
408 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
410 assert_identical_blobs_comparison(&expected
);
411 cl_assert_equal_i(0, expected
.files_binary
);
413 memset(&expected
, 0, sizeof(expected
));
414 cl_git_pass(git_diff_blobs(
415 alien
, NULL
, alien
, NULL
, &opts
,
416 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
418 assert_identical_blobs_comparison(&expected
);
419 cl_assert(expected
.files_binary
> 0);
422 void test_diff_blob__can_compare_identical_blobs_with_patch(void)
425 const git_diff_delta
*delta
;
427 cl_git_pass(git_patch_from_blobs(&p
, d
, NULL
, d
, NULL
, &opts
));
428 cl_assert(p
!= NULL
);
430 delta
= git_patch_get_delta(p
);
431 cl_assert(delta
!= NULL
);
432 cl_assert_equal_i(GIT_DELTA_UNMODIFIED
, delta
->status
);
433 cl_assert_equal_sz(delta
->old_file
.size
, git_blob_rawsize(d
));
434 cl_assert_equal_oid(git_blob_id(d
), &delta
->old_file
.id
);
435 cl_assert_equal_sz(delta
->new_file
.size
, git_blob_rawsize(d
));
436 cl_assert_equal_oid(git_blob_id(d
), &delta
->new_file
.id
);
438 cl_assert_equal_i(0, (int)git_patch_num_hunks(p
));
441 cl_git_pass(git_patch_from_blobs(&p
, NULL
, NULL
, NULL
, NULL
, &opts
));
442 cl_assert(p
!= NULL
);
444 delta
= git_patch_get_delta(p
);
445 cl_assert(delta
!= NULL
);
446 cl_assert_equal_i(GIT_DELTA_UNMODIFIED
, delta
->status
);
447 cl_assert_equal_sz(0, delta
->old_file
.size
);
448 cl_assert(git_oid_is_zero(&delta
->old_file
.id
));
449 cl_assert_equal_sz(0, delta
->new_file
.size
);
450 cl_assert(git_oid_is_zero(&delta
->new_file
.id
));
452 cl_assert_equal_i(0, (int)git_patch_num_hunks(p
));
455 cl_git_pass(git_patch_from_blobs(&p
, alien
, NULL
, alien
, NULL
, &opts
));
456 cl_assert(p
!= NULL
);
457 cl_assert_equal_i(GIT_DELTA_UNMODIFIED
, git_patch_get_delta(p
)->status
);
458 cl_assert_equal_i(0, (int)git_patch_num_hunks(p
));
462 static void assert_binary_blobs_comparison(diff_expects
*expected
)
464 cl_assert(expected
->files_binary
> 0);
466 cl_assert_equal_i(1, expected
->files
);
467 cl_assert_equal_i(1, expected
->file_status
[GIT_DELTA_MODIFIED
]);
468 cl_assert_equal_i(0, expected
->hunks
);
469 cl_assert_equal_i(0, expected
->lines
);
472 void test_diff_blob__can_compare_two_binary_blobs(void)
478 cl_git_pass(git_oid_fromstrn(&h_oid
, "de863bff", 8));
479 cl_git_pass(git_blob_lookup_prefix(&heart
, g_repo
, &h_oid
, 8));
481 cl_git_pass(git_diff_blobs(
482 alien
, NULL
, heart
, NULL
, &opts
,
483 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
485 assert_binary_blobs_comparison(&expected
);
487 memset(&expected
, 0, sizeof(expected
));
489 cl_git_pass(git_diff_blobs(
490 heart
, NULL
, alien
, NULL
, &opts
,
491 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
493 assert_binary_blobs_comparison(&expected
);
495 git_blob_free(heart
);
498 void test_diff_blob__can_compare_a_binary_blob_and_a_text_blob(void)
500 cl_git_pass(git_diff_blobs(
501 alien
, NULL
, d
, NULL
, &opts
,
502 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
504 assert_binary_blobs_comparison(&expected
);
506 memset(&expected
, 0, sizeof(expected
));
508 cl_git_pass(git_diff_blobs(
509 d
, NULL
, alien
, NULL
, &opts
,
510 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
512 assert_binary_blobs_comparison(&expected
);
516 * $ git diff fe773770 a0f7217
517 * diff --git a/fe773770 b/a0f7217
518 * index fe77377..a0f7217 100644
522 * Here is some stuff at the start
524 * -This should go in one hunk
525 * +This should go in one hunk (first)
527 * Some additional lines
529 * @@ -8,7 +8,7 @@ Down here below the other lines
531 * With even more at the end
533 * -Followed by a second hunk of stuff
534 * +Followed by a second hunk of stuff (second)
536 * That happens down here
538 void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void)
543 opts
.context_lines
= 3;
545 /* tests/resources/attr/root_test1 from commit f5b0af1 */
546 cl_git_pass(git_oid_fromstrn(&old_d_oid
, "fe773770", 8));
547 cl_git_pass(git_blob_lookup_prefix(&old_d
, g_repo
, &old_d_oid
, 8));
549 /* Test with default inter-hunk-context (not set) => default is 0 */
550 cl_git_pass(git_diff_blobs(
551 old_d
, NULL
, d
, NULL
, &opts
,
552 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
554 cl_assert_equal_i(2, expected
.hunks
);
556 /* Test with inter-hunk-context explicitly set to 0 */
557 opts
.interhunk_lines
= 0;
558 memset(&expected
, 0, sizeof(expected
));
559 cl_git_pass(git_diff_blobs(
560 old_d
, NULL
, d
, NULL
, &opts
,
561 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
563 cl_assert_equal_i(2, expected
.hunks
);
565 /* Test with inter-hunk-context explicitly set to 1 */
566 opts
.interhunk_lines
= 1;
567 memset(&expected
, 0, sizeof(expected
));
568 cl_git_pass(git_diff_blobs(
569 old_d
, NULL
, d
, NULL
, &opts
,
570 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
572 cl_assert_equal_i(1, expected
.hunks
);
574 git_blob_free(old_d
);
577 void test_diff_blob__checks_options_version_too_low(void)
579 const git_error
*err
;
582 cl_git_fail(git_diff_blobs(
583 d
, NULL
, alien
, NULL
, &opts
,
584 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
585 err
= git_error_last();
586 cl_assert_equal_i(GIT_ERROR_INVALID
, err
->klass
);
589 void test_diff_blob__checks_options_version_too_high(void)
591 const git_error
*err
;
594 cl_git_fail(git_diff_blobs(
595 d
, NULL
, alien
, NULL
, &opts
,
596 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
597 err
= git_error_last();
598 cl_assert_equal_i(GIT_ERROR_INVALID
, err
->klass
);
601 void test_diff_blob__can_correctly_detect_a_binary_blob_as_binary(void)
604 cl_assert_equal_i(true, git_blob_is_binary(alien
));
607 void test_diff_blob__can_correctly_detect_a_textual_blob_as_non_binary(void)
609 /* tests/resources/attr/root_test4.txt */
610 cl_assert_equal_i(false, git_blob_is_binary(d
));
614 * git_diff_blob_to_buffer tests
617 static void assert_changed_single_one_line_file(
618 diff_expects
*expected
, git_delta_t mod
)
620 cl_assert_equal_i(1, expected
->files
);
621 cl_assert_equal_i(1, expected
->file_status
[mod
]);
622 cl_assert_equal_i(1, expected
->hunks
);
623 cl_assert_equal_i(1, expected
->lines
);
625 if (mod
== GIT_DELTA_ADDED
)
626 cl_assert_equal_i(1, expected
->line_adds
);
627 else if (mod
== GIT_DELTA_DELETED
)
628 cl_assert_equal_i(1, expected
->line_dels
);
631 void test_diff_blob__can_compare_blob_to_buffer(void)
635 const char *a_content
= "Hello from the root\n";
636 const char *b_content
= "Hello from the root\n\nSome additional lines\n\nDown here below\n\n";
638 /* tests/resources/attr/root_test1 */
639 cl_git_pass(git_oid_fromstrn(&a_oid
, "45141a79", 8));
640 cl_git_pass(git_blob_lookup_prefix(&a
, g_repo
, &a_oid
, 8));
642 /* diff from blob a to content of b */
643 quick_diff_blob_to_str(a
, NULL
, b_content
, 0, NULL
);
644 assert_one_modified(1, 6, 1, 5, 0, &expected
);
646 /* diff from blob a to content of a */
647 opts
.flags
|= GIT_DIFF_INCLUDE_UNMODIFIED
;
648 quick_diff_blob_to_str(a
, NULL
, a_content
, 0, NULL
);
649 assert_identical_blobs_comparison(&expected
);
651 /* diff from NULL blob to content of a */
652 memset(&expected
, 0, sizeof(expected
));
653 quick_diff_blob_to_str(NULL
, NULL
, a_content
, 0, NULL
);
654 assert_changed_single_one_line_file(&expected
, GIT_DELTA_ADDED
);
656 /* diff from blob a to NULL buffer */
657 memset(&expected
, 0, sizeof(expected
));
658 quick_diff_blob_to_str(a
, NULL
, NULL
, 0, NULL
);
659 assert_changed_single_one_line_file(&expected
, GIT_DELTA_DELETED
);
661 /* diff with reverse */
662 opts
.flags
^= GIT_DIFF_REVERSE
;
664 memset(&expected
, 0, sizeof(expected
));
665 quick_diff_blob_to_str(a
, NULL
, NULL
, 0, NULL
);
666 assert_changed_single_one_line_file(&expected
, GIT_DELTA_ADDED
);
671 void test_diff_blob__can_compare_blob_to_buffer_with_patch(void)
676 const char *a_content
= "Hello from the root\n";
677 const char *b_content
= "Hello from the root\n\nSome additional lines\n\nDown here below\n\n";
680 /* tests/resources/attr/root_test1 */
681 cl_git_pass(git_oid_fromstrn(&a_oid
, "45141a79", 8));
682 cl_git_pass(git_blob_lookup_prefix(&a
, g_repo
, &a_oid
, 8));
684 /* diff from blob a to content of b */
685 cl_git_pass(git_patch_from_blob_and_buffer(
686 &p
, a
, NULL
, b_content
, strlen(b_content
), NULL
, &opts
));
688 cl_assert(p
!= NULL
);
689 cl_assert_equal_i(GIT_DELTA_MODIFIED
, git_patch_get_delta(p
)->status
);
690 cl_assert_equal_i(1, (int)git_patch_num_hunks(p
));
691 cl_assert_equal_i(6, git_patch_num_lines_in_hunk(p
, 0));
693 cl_git_pass(git_patch_line_stats(&tc
, &ta
, &td
, p
));
694 cl_assert_equal_i(1, (int)tc
);
695 cl_assert_equal_i(5, (int)ta
);
696 cl_assert_equal_i(0, (int)td
);
700 /* diff from blob a to content of a */
701 opts
.flags
|= GIT_DIFF_INCLUDE_UNMODIFIED
;
702 cl_git_pass(git_patch_from_blob_and_buffer(
703 &p
, a
, NULL
, a_content
, strlen(a_content
), NULL
, &opts
));
704 cl_assert(p
!= NULL
);
705 cl_assert_equal_i(GIT_DELTA_UNMODIFIED
, git_patch_get_delta(p
)->status
);
706 cl_assert_equal_i(0, (int)git_patch_num_hunks(p
));
709 /* diff from NULL blob to content of a */
710 cl_git_pass(git_patch_from_blob_and_buffer(
711 &p
, NULL
, NULL
, a_content
, strlen(a_content
), NULL
, &opts
));
712 cl_assert(p
!= NULL
);
713 cl_assert_equal_i(GIT_DELTA_ADDED
, git_patch_get_delta(p
)->status
);
714 cl_assert_equal_i(1, (int)git_patch_num_hunks(p
));
715 cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p
, 0));
718 /* diff from blob a to NULL buffer */
719 cl_git_pass(git_patch_from_blob_and_buffer(
720 &p
, a
, NULL
, NULL
, 0, NULL
, &opts
));
721 cl_assert(p
!= NULL
);
722 cl_assert_equal_i(GIT_DELTA_DELETED
, git_patch_get_delta(p
)->status
);
723 cl_assert_equal_i(1, (int)git_patch_num_hunks(p
));
724 cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p
, 0));
727 /* diff with reverse */
728 opts
.flags
^= GIT_DIFF_REVERSE
;
730 cl_git_pass(git_patch_from_blob_and_buffer(
731 &p
, a
, NULL
, NULL
, 0, NULL
, &opts
));
732 cl_assert(p
!= NULL
);
733 cl_assert_equal_i(GIT_DELTA_ADDED
, git_patch_get_delta(p
)->status
);
734 cl_assert_equal_i(1, (int)git_patch_num_hunks(p
));
735 cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p
, 0));
741 static void assert_one_modified_with_lines(diff_expects
*expected
, int lines
)
743 cl_assert_equal_i(1, expected
->files
);
744 cl_assert_equal_i(1, expected
->file_status
[GIT_DELTA_MODIFIED
]);
745 cl_assert_equal_i(0, expected
->files_binary
);
746 cl_assert_equal_i(lines
, expected
->lines
);
749 void test_diff_blob__binary_data_comparisons(void)
751 git_blob
*bin
, *nonbin
;
753 const char *nonbin_content
= "Hello from the root\n";
754 size_t nonbin_len
= 20;
755 const char *bin_content
= "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n";
758 opts
.flags
|= GIT_DIFF_INCLUDE_UNMODIFIED
;
760 cl_git_pass(git_oid_fromstrn(&oid
, "45141a79", 8));
761 cl_git_pass(git_blob_lookup_prefix(&nonbin
, g_repo
, &oid
, 8));
763 cl_git_pass(git_oid_fromstrn(&oid
, "b435cd56", 8));
764 cl_git_pass(git_blob_lookup_prefix(&bin
, g_repo
, &oid
, 8));
766 /* non-binary to reference content */
768 quick_diff_blob_to_str(nonbin
, NULL
, nonbin_content
, nonbin_len
, NULL
);
769 assert_identical_blobs_comparison(&expected
);
770 cl_assert_equal_i(0, expected
.files_binary
);
772 /* binary to reference content */
774 quick_diff_blob_to_str(bin
, NULL
, bin_content
, bin_len
, NULL
);
775 assert_identical_blobs_comparison(&expected
);
777 cl_assert_equal_i(1, expected
.files_binary
);
779 /* non-binary to binary content */
781 quick_diff_blob_to_str(nonbin
, NULL
, bin_content
, bin_len
, NULL
);
782 assert_binary_blobs_comparison(&expected
);
784 /* binary to non-binary content */
786 quick_diff_blob_to_str(bin
, NULL
, nonbin_content
, nonbin_len
, NULL
);
787 assert_binary_blobs_comparison(&expected
);
789 /* non-binary to binary blob */
791 memset(&expected
, 0, sizeof(expected
));
792 cl_git_pass(git_diff_blobs(
793 bin
, NULL
, nonbin
, NULL
, &opts
,
794 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
795 assert_binary_blobs_comparison(&expected
);
798 * repeat with FORCE_TEXT
801 opts
.flags
|= GIT_DIFF_FORCE_TEXT
;
803 quick_diff_blob_to_str(bin
, NULL
, bin_content
, bin_len
, NULL
);
804 assert_identical_blobs_comparison(&expected
);
806 quick_diff_blob_to_str(nonbin
, NULL
, bin_content
, bin_len
, NULL
);
807 assert_one_modified_with_lines(&expected
, 4);
809 quick_diff_blob_to_str(bin
, NULL
, nonbin_content
, nonbin_len
, NULL
);
810 assert_one_modified_with_lines(&expected
, 4);
812 memset(&expected
, 0, sizeof(expected
));
813 cl_git_pass(git_diff_blobs(
814 bin
, NULL
, nonbin
, NULL
, &opts
,
815 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
816 assert_one_modified_with_lines(&expected
, 4);
820 git_blob_free(nonbin
);
823 void test_diff_blob__using_path_and_attributes(void)
826 git_blob
*bin
, *nonbin
;
828 const char *nonbin_content
= "Hello from the root\n";
829 const char *bin_content
=
830 "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n";
834 git_buf buf
= GIT_BUF_INIT
;
836 /* set up custom diff drivers and 'diff' attribute mappings for them */
838 cl_git_pass(git_repository_config(&cfg
, g_repo
));
839 cl_git_pass(git_config_set_bool(cfg
, "diff.iam_binary.binary", 1));
840 cl_git_pass(git_config_set_bool(cfg
, "diff.iam_text.binary", 0));
841 cl_git_pass(git_config_set_string(
842 cfg
, "diff.iam_alphactx.xfuncname", "^[A-Za-z].*$"));
843 cl_git_pass(git_config_set_bool(cfg
, "diff.iam_textalpha.binary", 0));
844 cl_git_pass(git_config_set_string(
845 cfg
, "diff.iam_textalpha.xfuncname", "^[A-Za-z].*$"));
846 cl_git_pass(git_config_set_string(
847 cfg
, "diff.iam_numctx.funcname", "^[0-9][0-9]*"));
848 cl_git_pass(git_config_set_bool(cfg
, "diff.iam_textnum.binary", 0));
849 cl_git_pass(git_config_set_string(
850 cfg
, "diff.iam_textnum.funcname", "^[0-9][0-9]*"));
851 git_config_free(cfg
);
854 "attr/.gitattributes",
855 "\n\n# test_diff_blob__using_path_and_attributes extra\n\n"
856 "*.binary diff=iam_binary\n"
857 "*.textary diff=iam_text\n"
858 "*.alphary diff=iam_alphactx\n"
859 "*.textalphary diff=iam_textalpha\n"
860 "*.textnumary diff=iam_textnum\n"
861 "*.numary diff=iam_numctx\n\n");
863 opts
.context_lines
= 0;
864 opts
.flags
|= GIT_DIFF_INCLUDE_UNMODIFIED
;
866 cl_git_pass(git_oid_fromstrn(&oid
, "45141a79", 8));
867 cl_git_pass(git_blob_lookup_prefix(&nonbin
, g_repo
, &oid
, 8));
868 /* 20b: "Hello from the root\n" */
870 cl_git_pass(git_oid_fromstrn(&oid
, "b435cd56", 8));
871 cl_git_pass(git_blob_lookup_prefix(&bin
, g_repo
, &oid
, 8));
872 /* 33b: "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\n0123456789\n" */
874 /* non-binary to reference content */
876 quick_diff_blob_to_str(nonbin
, NULL
, nonbin_content
, 0, NULL
);
877 assert_identical_blobs_comparison(&expected
);
878 cl_assert_equal_i(0, expected
.files_binary
);
880 /* binary to reference content */
882 quick_diff_blob_to_str(bin
, NULL
, bin_content
, bin_len
, NULL
);
883 assert_identical_blobs_comparison(&expected
);
884 cl_assert_equal_i(1, expected
.files_binary
);
888 changed
= "Hello from the root\nMore lines\nAnd more\nGo here\n";
890 quick_diff_blob_to_str(nonbin
, NULL
, changed
, 0, NULL
);
891 assert_one_modified(1, 3, 0, 3, 0, &expected
);
893 quick_diff_blob_to_str(nonbin
, "foo/bar.binary", changed
, 0, NULL
);
894 cl_assert_equal_i(1, expected
.files
);
895 cl_assert_equal_i(1, expected
.file_status
[GIT_DELTA_MODIFIED
]);
896 cl_assert_equal_i(1, expected
.files_binary
);
897 cl_assert_equal_i(0, expected
.hunks
);
898 cl_assert_equal_i(0, expected
.lines
);
900 quick_diff_blob_to_str(nonbin
, "foo/bar.textary", changed
, 0, NULL
);
901 assert_one_modified(1, 3, 0, 3, 0, &expected
);
903 quick_diff_blob_to_str(nonbin
, "foo/bar.alphary", changed
, 0, NULL
);
904 assert_one_modified(1, 3, 0, 3, 0, &expected
);
906 cl_git_pass(git_patch_from_blob_and_buffer(
907 &p
, nonbin
, "zzz.normal", changed
, strlen(changed
), NULL
, &opts
));
908 cl_git_pass(git_patch_to_buf(&buf
, p
));
910 "diff --git a/zzz.normal b/zzz.normal\n"
911 "index 45141a7..75b0dbb 100644\n"
914 "@@ -1,0 +2,3 @@ Hello from the root\n"
917 "+Go here\n", buf
.ptr
);
921 cl_git_pass(git_patch_from_blob_and_buffer(
922 &p
, nonbin
, "zzz.binary", changed
, strlen(changed
), NULL
, &opts
));
923 cl_git_pass(git_patch_to_buf(&buf
, p
));
925 "diff --git a/zzz.binary b/zzz.binary\n"
926 "index 45141a7..75b0dbb 100644\n"
927 "Binary files a/zzz.binary and b/zzz.binary differ\n", buf
.ptr
);
931 cl_git_pass(git_patch_from_blob_and_buffer(
932 &p
, nonbin
, "zzz.alphary", changed
, strlen(changed
), NULL
, &opts
));
933 cl_git_pass(git_patch_to_buf(&buf
, p
));
935 "diff --git a/zzz.alphary b/zzz.alphary\n"
936 "index 45141a7..75b0dbb 100644\n"
937 "--- a/zzz.alphary\n"
938 "+++ b/zzz.alphary\n"
939 "@@ -1,0 +2,3 @@ Hello from the root\n"
942 "+Go here\n", buf
.ptr
);
946 cl_git_pass(git_patch_from_blob_and_buffer(
947 &p
, nonbin
, "zzz.numary", changed
, strlen(changed
), NULL
, &opts
));
948 cl_git_pass(git_patch_to_buf(&buf
, p
));
950 "diff --git a/zzz.numary b/zzz.numary\n"
951 "index 45141a7..75b0dbb 100644\n"
957 "+Go here\n", buf
.ptr
);
961 /* "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n"
965 changed
= "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\nreplace a line\n";
967 cl_git_pass(git_patch_from_blob_and_buffer(
968 &p
, bin
, "zzz.normal", changed
, 37, NULL
, &opts
));
969 cl_git_pass(git_patch_to_buf(&buf
, p
));
971 "diff --git a/zzz.normal b/zzz.normal\n"
972 "index b435cd5..1604519 100644\n"
973 "Binary files a/zzz.normal and b/zzz.normal differ\n", buf
.ptr
);
977 cl_git_pass(git_patch_from_blob_and_buffer(
978 &p
, bin
, "zzz.textary", changed
, 37, NULL
, &opts
));
979 cl_git_pass(git_patch_to_buf(&buf
, p
));
981 "diff --git a/zzz.textary b/zzz.textary\n"
982 "index b435cd5..1604519 100644\n"
983 "--- a/zzz.textary\n"
984 "+++ b/zzz.textary\n"
987 "+replace a line\n", buf
.ptr
);
991 cl_git_pass(git_patch_from_blob_and_buffer(
992 &p
, bin
, "zzz.textalphary", changed
, 37, NULL
, &opts
));
993 cl_git_pass(git_patch_to_buf(&buf
, p
));
995 "diff --git a/zzz.textalphary b/zzz.textalphary\n"
996 "index b435cd5..1604519 100644\n"
997 "--- a/zzz.textalphary\n"
998 "+++ b/zzz.textalphary\n"
1001 "+replace a line\n", buf
.ptr
);
1002 git_buf_clear(&buf
);
1005 cl_git_pass(git_patch_from_blob_and_buffer(
1006 &p
, bin
, "zzz.textnumary", changed
, 37, NULL
, &opts
));
1007 cl_git_pass(git_patch_to_buf(&buf
, p
));
1009 "diff --git a/zzz.textnumary b/zzz.textnumary\n"
1010 "index b435cd5..1604519 100644\n"
1011 "--- a/zzz.textnumary\n"
1012 "+++ b/zzz.textnumary\n"
1013 "@@ -3 +3 @@ 0123456789\n"
1015 "+replace a line\n", buf
.ptr
);
1016 git_buf_clear(&buf
);
1019 git_buf_dispose(&buf
);
1020 git_blob_free(nonbin
);
1024 void test_diff_blob__can_compare_buffer_to_buffer(void)
1026 const char *a
= "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\n";
1027 const char *b
= "a\nB\nc\nd\nE\nF\nh\nj\nk\n";
1029 opts
.interhunk_lines
= 0;
1030 opts
.context_lines
= 0;
1032 memset(&expected
, 0, sizeof(expected
));
1034 cl_git_pass(git_diff_buffers(
1035 a
, strlen(a
), NULL
, b
, strlen(b
), NULL
, &opts
,
1036 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
1037 assert_one_modified(4, 9, 0, 4, 5, &expected
);
1039 opts
.flags
^= GIT_DIFF_REVERSE
;
1041 memset(&expected
, 0, sizeof(expected
));
1043 cl_git_pass(git_diff_buffers(
1044 a
, strlen(a
), NULL
, b
, strlen(b
), NULL
, &opts
,
1045 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expected
));
1046 assert_one_modified(4, 9, 0, 5, 4, &expected
);