1 #include "clar_libgit2.h"
2 #include "diff_helpers.h"
4 static git_repository
*g_repo
= NULL
;
5 static git_diff_options opts
;
7 static git_tree
*a
, *b
;
8 static diff_expects expect
;
10 void test_diff_tree__initialize(void)
12 cl_git_pass(git_diff_init_options(&opts
, GIT_DIFF_OPTIONS_VERSION
));
14 memset(&expect
, 0, sizeof(expect
));
21 void test_diff_tree__cleanup(void)
27 cl_git_sandbox_cleanup();
31 void test_diff_tree__0(void)
33 /* grabbed a couple of commit oids from the history of the attr repo */
34 const char *a_commit
= "605812a";
35 const char *b_commit
= "370fe9ec22";
36 const char *c_commit
= "f5b0af1fb4f5c";
39 g_repo
= cl_git_sandbox_init("attr");
41 cl_assert((a
= resolve_commit_oid_to_tree(g_repo
, a_commit
)) != NULL
);
42 cl_assert((b
= resolve_commit_oid_to_tree(g_repo
, b_commit
)) != NULL
);
43 cl_assert((c
= resolve_commit_oid_to_tree(g_repo
, c_commit
)) != NULL
);
45 opts
.context_lines
= 1;
46 opts
.interhunk_lines
= 1;
49 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, &opts
));
51 cl_git_pass(git_diff_foreach(
52 diff
, diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expect
));
54 cl_assert_equal_i(5, expect
.files
);
55 cl_assert_equal_i(2, expect
.file_status
[GIT_DELTA_ADDED
]);
56 cl_assert_equal_i(1, expect
.file_status
[GIT_DELTA_DELETED
]);
57 cl_assert_equal_i(2, expect
.file_status
[GIT_DELTA_MODIFIED
]);
59 cl_assert_equal_i(5, expect
.hunks
);
61 cl_assert_equal_i(7 + 24 + 1 + 6 + 6, expect
.lines
);
62 cl_assert_equal_i(1, expect
.line_ctxt
);
63 cl_assert_equal_i(24 + 1 + 5 + 5, expect
.line_adds
);
64 cl_assert_equal_i(7 + 1, expect
.line_dels
);
69 memset(&expect
, 0, sizeof(expect
));
71 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, c
, b
, &opts
));
73 cl_git_pass(git_diff_foreach(
74 diff
, diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expect
));
76 cl_assert_equal_i(2, expect
.files
);
77 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_ADDED
]);
78 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_DELETED
]);
79 cl_assert_equal_i(2, expect
.file_status
[GIT_DELTA_MODIFIED
]);
81 cl_assert_equal_i(2, expect
.hunks
);
83 cl_assert_equal_i(8 + 15, expect
.lines
);
84 cl_assert_equal_i(1, expect
.line_ctxt
);
85 cl_assert_equal_i(1, expect
.line_adds
);
86 cl_assert_equal_i(7 + 14, expect
.line_dels
);
91 #define DIFF_OPTS(FLAGS, CTXT) \
92 {GIT_DIFF_OPTIONS_VERSION, (FLAGS), GIT_SUBMODULE_IGNORE_UNSPECIFIED, \
93 {NULL,0}, NULL, NULL, NULL, (CTXT), 1}
95 void test_diff_tree__options(void)
97 /* grabbed a couple of commit oids from the history of the attr repo */
98 const char *a_commit
= "6bab5c79cd5140d0";
99 const char *b_commit
= "605812ab7fe421fdd";
100 const char *c_commit
= "f5b0af1fb4f5";
101 const char *d_commit
= "a97cc019851";
104 int test_ab_or_cd
[] = { 0, 0, 0, 0, 1, 1, 1, 1, 1 };
105 git_diff_options test_options
[] = {
107 DIFF_OPTS(GIT_DIFF_NORMAL
, 1),
108 DIFF_OPTS(GIT_DIFF_NORMAL
, 3),
109 DIFF_OPTS(GIT_DIFF_REVERSE
, 2),
110 DIFF_OPTS(GIT_DIFF_FORCE_TEXT
, 2),
112 DIFF_OPTS(GIT_DIFF_NORMAL
, 3),
113 DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE
, 3),
114 DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE_CHANGE
, 3),
115 DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE_EOL
, 3),
116 DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE
| GIT_DIFF_REVERSE
, 1),
119 /* to generate these values:
120 * - cd to tests/resources/attr,
122 * - git diff [options] 6bab5c79cd5140d0 605812ab7fe421fdd
125 #define EXPECT_STATUS_ADM(ADDS,DELS,MODS) { 0, ADDS, DELS, MODS, 0, 0, 0, 0, 0 }
127 diff_expects test_expects
[] = {
129 { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 4, 0, 0, 51, 2, 46, 3 },
130 { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 4, 0, 0, 53, 4, 46, 3 },
131 { 5, 0, EXPECT_STATUS_ADM(0, 3, 2), 4, 0, 0, 52, 3, 3, 46 },
132 { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 5, 0, 0, 54, 3, 47, 4 },
134 { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 22, 9, 10, 3 },
135 { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 19, 12, 7, 0 },
136 { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 20, 11, 8, 1 },
137 { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 20, 11, 8, 1 },
138 { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 18, 11, 0, 7 },
141 diff_expects
*expected
;
144 g_repo
= cl_git_sandbox_init("attr");
146 cl_assert((a
= resolve_commit_oid_to_tree(g_repo
, a_commit
)) != NULL
);
147 cl_assert((b
= resolve_commit_oid_to_tree(g_repo
, b_commit
)) != NULL
);
148 cl_assert((c
= resolve_commit_oid_to_tree(g_repo
, c_commit
)) != NULL
);
149 cl_assert((d
= resolve_commit_oid_to_tree(g_repo
, d_commit
)) != NULL
);
151 for (i
= 0; test_expects
[i
].files
> 0; i
++) {
152 memset(&actual
, 0, sizeof(actual
)); /* clear accumulator */
153 opts
= test_options
[i
];
155 if (test_ab_or_cd
[i
] == 0)
156 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, &opts
));
158 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, c
, d
, &opts
));
160 cl_git_pass(git_diff_foreach(
161 diff
, diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &actual
));
163 expected
= &test_expects
[i
];
164 cl_assert_equal_i(actual
.files
, expected
->files
);
165 for (j
= GIT_DELTA_UNMODIFIED
; j
<= GIT_DELTA_TYPECHANGE
; ++j
)
166 cl_assert_equal_i(expected
->file_status
[j
], actual
.file_status
[j
]);
167 cl_assert_equal_i(actual
.hunks
, expected
->hunks
);
168 cl_assert_equal_i(actual
.lines
, expected
->lines
);
169 cl_assert_equal_i(actual
.line_ctxt
, expected
->line_ctxt
);
170 cl_assert_equal_i(actual
.line_adds
, expected
->line_adds
);
171 cl_assert_equal_i(actual
.line_dels
, expected
->line_dels
);
181 void test_diff_tree__bare(void)
183 const char *a_commit
= "8496071c1b46c85";
184 const char *b_commit
= "be3563ae3f79";
186 g_repo
= cl_git_sandbox_init("testrepo.git");
188 cl_assert((a
= resolve_commit_oid_to_tree(g_repo
, a_commit
)) != NULL
);
189 cl_assert((b
= resolve_commit_oid_to_tree(g_repo
, b_commit
)) != NULL
);
191 opts
.context_lines
= 1;
192 opts
.interhunk_lines
= 1;
194 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, &opts
));
196 cl_git_pass(git_diff_foreach(
197 diff
, diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expect
));
199 cl_assert_equal_i(3, expect
.files
);
200 cl_assert_equal_i(2, expect
.file_status
[GIT_DELTA_ADDED
]);
201 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_DELETED
]);
202 cl_assert_equal_i(1, expect
.file_status
[GIT_DELTA_MODIFIED
]);
204 cl_assert_equal_i(3, expect
.hunks
);
206 cl_assert_equal_i(4, expect
.lines
);
207 cl_assert_equal_i(0, expect
.line_ctxt
);
208 cl_assert_equal_i(3, expect
.line_adds
);
209 cl_assert_equal_i(1, expect
.line_dels
);
212 void test_diff_tree__merge(void)
214 /* grabbed a couple of commit oids from the history of the attr repo */
215 const char *a_commit
= "605812a";
216 const char *b_commit
= "370fe9ec22";
217 const char *c_commit
= "f5b0af1fb4f5c";
219 git_diff
*diff1
= NULL
, *diff2
= NULL
;
221 g_repo
= cl_git_sandbox_init("attr");
223 cl_assert((a
= resolve_commit_oid_to_tree(g_repo
, a_commit
)) != NULL
);
224 cl_assert((b
= resolve_commit_oid_to_tree(g_repo
, b_commit
)) != NULL
);
225 cl_assert((c
= resolve_commit_oid_to_tree(g_repo
, c_commit
)) != NULL
);
227 cl_git_pass(git_diff_tree_to_tree(&diff1
, g_repo
, a
, b
, NULL
));
229 cl_git_pass(git_diff_tree_to_tree(&diff2
, g_repo
, c
, b
, NULL
));
233 cl_git_pass(git_diff_merge(diff1
, diff2
));
235 git_diff_free(diff2
);
237 cl_git_pass(git_diff_foreach(
238 diff1
, diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expect
));
240 cl_assert_equal_i(6, expect
.files
);
241 cl_assert_equal_i(2, expect
.file_status
[GIT_DELTA_ADDED
]);
242 cl_assert_equal_i(1, expect
.file_status
[GIT_DELTA_DELETED
]);
243 cl_assert_equal_i(3, expect
.file_status
[GIT_DELTA_MODIFIED
]);
245 cl_assert_equal_i(6, expect
.hunks
);
247 cl_assert_equal_i(59, expect
.lines
);
248 cl_assert_equal_i(1, expect
.line_ctxt
);
249 cl_assert_equal_i(36, expect
.line_adds
);
250 cl_assert_equal_i(22, expect
.line_dels
);
252 git_diff_free(diff1
);
255 void test_diff_tree__larger_hunks(void)
257 const char *a_commit
= "d70d245ed97ed2aa596dd1af6536e4bfdb047b69";
258 const char *b_commit
= "7a9e0b02e63179929fed24f0a3e0f19168114d10";
259 size_t d
, num_d
, h
, num_h
, l
, num_l
;
261 const git_diff_hunk
*hunk
;
262 const git_diff_line
*line
;
264 g_repo
= cl_git_sandbox_init("diff");
266 cl_assert((a
= resolve_commit_oid_to_tree(g_repo
, a_commit
)) != NULL
);
267 cl_assert((b
= resolve_commit_oid_to_tree(g_repo
, b_commit
)) != NULL
);
269 opts
.context_lines
= 1;
270 opts
.interhunk_lines
= 0;
272 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, &opts
));
274 num_d
= git_diff_num_deltas(diff
);
275 for (d
= 0; d
< num_d
; ++d
) {
276 cl_git_pass(git_patch_from_diff(&patch
, diff
, d
));
279 num_h
= git_patch_num_hunks(patch
);
280 for (h
= 0; h
< num_h
; h
++) {
281 cl_git_pass(git_patch_get_hunk(&hunk
, &num_l
, patch
, h
));
283 for (l
= 0; l
< num_l
; ++l
) {
284 cl_git_pass(git_patch_get_line_in_hunk(&line
, patch
, h
, l
));
288 cl_git_fail(git_patch_get_line_in_hunk(&line
, patch
, h
, num_l
));
291 cl_git_fail(git_patch_get_hunk(&hunk
, &num_l
, patch
, num_h
));
293 git_patch_free(patch
);
296 cl_git_fail(git_patch_from_diff(&patch
, diff
, num_d
));
298 cl_assert_equal_i(2, (int)num_d
);
301 void test_diff_tree__checks_options_version(void)
303 const char *a_commit
= "8496071c1b46c85";
304 const char *b_commit
= "be3563ae3f79";
305 const git_error
*err
;
307 g_repo
= cl_git_sandbox_init("testrepo.git");
309 cl_assert((a
= resolve_commit_oid_to_tree(g_repo
, a_commit
)) != NULL
);
310 cl_assert((b
= resolve_commit_oid_to_tree(g_repo
, b_commit
)) != NULL
);
313 cl_git_fail(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, &opts
));
314 err
= git_error_last();
315 cl_assert_equal_i(GIT_ERROR_INVALID
, err
->klass
);
319 cl_git_fail(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, &opts
));
320 err
= git_error_last();
323 void process_tree_to_tree_diffing(
324 const char *old_commit
,
325 const char *new_commit
)
327 g_repo
= cl_git_sandbox_init("unsymlinked.git");
329 cl_assert((a
= resolve_commit_oid_to_tree(g_repo
, old_commit
)) != NULL
);
330 cl_assert((b
= resolve_commit_oid_to_tree(g_repo
, new_commit
)) != NULL
);
332 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, &opts
));
334 cl_git_pass(git_diff_foreach(
335 diff
, diff_file_cb
, NULL
, NULL
, NULL
, &expect
));
338 void test_diff_tree__symlink_blob_mode_changed_to_regular_file(void)
341 * $ git diff 7fccd7..806999
342 * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h
343 * deleted file mode 120000
344 * index 19bf568..0000000
345 * --- a/include/Nu/Nu.h
349 * \ No newline at end of file
350 * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h
351 * new file mode 100644
352 * index 0000000..f9e6561
354 * +++ b/include/Nu/Nu.h
357 * diff --git a/objc/Nu.h b/objc/Nu.h
358 * deleted file mode 100644
359 * index f9e6561..0000000
366 process_tree_to_tree_diffing("7fccd7", "806999");
368 cl_assert_equal_i(3, expect
.files
);
369 cl_assert_equal_i(2, expect
.file_status
[GIT_DELTA_DELETED
]);
370 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_MODIFIED
]);
371 cl_assert_equal_i(1, expect
.file_status
[GIT_DELTA_ADDED
]);
372 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_TYPECHANGE
]);
375 void test_diff_tree__symlink_blob_mode_changed_to_regular_file_as_typechange(void)
378 * $ git diff 7fccd7..a8595c
379 * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h
380 * deleted file mode 120000
381 * index 19bf568..0000000
382 * --- a/include/Nu/Nu.h
386 * \ No newline at end of file
387 * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h
388 * new file mode 100755
389 * index 0000000..f9e6561
391 * +++ b/include/Nu/Nu.h
394 * diff --git a/objc/Nu.h b/objc/Nu.h
395 * deleted file mode 100644
396 * index f9e6561..0000000
403 opts
.flags
= GIT_DIFF_INCLUDE_TYPECHANGE
;
404 process_tree_to_tree_diffing("7fccd7", "a8595c");
406 cl_assert_equal_i(2, expect
.files
);
407 cl_assert_equal_i(1, expect
.file_status
[GIT_DELTA_DELETED
]);
408 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_MODIFIED
]);
409 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_ADDED
]);
410 cl_assert_equal_i(1, expect
.file_status
[GIT_DELTA_TYPECHANGE
]);
413 void test_diff_tree__regular_blob_mode_changed_to_executable_file(void)
416 * $ git diff 806999..a8595c
417 * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h
422 process_tree_to_tree_diffing("806999", "a8595c");
424 cl_assert_equal_i(1, expect
.files
);
425 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_DELETED
]);
426 cl_assert_equal_i(1, expect
.file_status
[GIT_DELTA_MODIFIED
]);
427 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_ADDED
]);
428 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_TYPECHANGE
]);
431 void test_diff_tree__issue_1397(void)
433 /* this test shows that it is not needed */
435 g_repo
= cl_git_sandbox_init("issue_1397");
437 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
439 cl_assert((a
= resolve_commit_oid_to_tree(g_repo
, "8a7ef04")) != NULL
);
440 cl_assert((b
= resolve_commit_oid_to_tree(g_repo
, "7f483a7")) != NULL
);
442 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, &opts
));
444 cl_git_pass(git_diff_foreach(diff
,
445 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expect
));
447 cl_assert_equal_i(1, expect
.files
);
448 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_DELETED
]);
449 cl_assert_equal_i(1, expect
.file_status
[GIT_DELTA_MODIFIED
]);
450 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_ADDED
]);
451 cl_assert_equal_i(0, expect
.file_status
[GIT_DELTA_TYPECHANGE
]);
454 static void set_config_int(git_repository
*repo
, const char *name
, int value
)
458 cl_git_pass(git_repository_config(&cfg
, repo
));
459 cl_git_pass(git_config_set_int32(cfg
, name
, value
));
460 git_config_free(cfg
);
463 void test_diff_tree__diff_configs(void)
465 const char *a_commit
= "d70d245e";
466 const char *b_commit
= "7a9e0b02";
468 g_repo
= cl_git_sandbox_init("diff");
470 cl_assert((a
= resolve_commit_oid_to_tree(g_repo
, a_commit
)) != NULL
);
471 cl_assert((b
= resolve_commit_oid_to_tree(g_repo
, b_commit
)) != NULL
);
473 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, NULL
));
475 cl_git_pass(git_diff_foreach(diff
,
476 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expect
));
478 cl_assert_equal_i(2, expect
.files
);
479 cl_assert_equal_i(2, expect
.file_status
[GIT_DELTA_MODIFIED
]);
480 cl_assert_equal_i(6, expect
.hunks
);
481 cl_assert_equal_i(55, expect
.lines
);
482 cl_assert_equal_i(33, expect
.line_ctxt
);
483 cl_assert_equal_i(7, expect
.line_adds
);
484 cl_assert_equal_i(15, expect
.line_dels
);
489 set_config_int(g_repo
, "diff.context", 1);
491 memset(&expect
, 0, sizeof(expect
));
493 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, NULL
));
495 cl_git_pass(git_diff_foreach(diff
,
496 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expect
));
498 cl_assert_equal_i(2, expect
.files
);
499 cl_assert_equal_i(2, expect
.file_status
[GIT_DELTA_MODIFIED
]);
500 cl_assert_equal_i(7, expect
.hunks
);
501 cl_assert_equal_i(34, expect
.lines
);
502 cl_assert_equal_i(12, expect
.line_ctxt
);
503 cl_assert_equal_i(7, expect
.line_adds
);
504 cl_assert_equal_i(15, expect
.line_dels
);
509 set_config_int(g_repo
, "diff.context", 0);
510 set_config_int(g_repo
, "diff.noprefix", 1);
512 memset(&expect
, 0, sizeof(expect
));
514 cl_git_pass(git_diff_tree_to_tree(&diff
, g_repo
, a
, b
, NULL
));
516 cl_git_pass(git_diff_foreach(diff
,
517 diff_file_cb
, diff_binary_cb
, diff_hunk_cb
, diff_line_cb
, &expect
));
519 cl_assert_equal_i(2, expect
.files
);
520 cl_assert_equal_i(2, expect
.file_status
[GIT_DELTA_MODIFIED
]);
521 cl_assert_equal_i(7, expect
.hunks
);
522 cl_assert_equal_i(22, expect
.lines
);
523 cl_assert_equal_i(0, expect
.line_ctxt
);
524 cl_assert_equal_i(7, expect
.line_adds
);
525 cl_assert_equal_i(15, expect
.line_dels
);