1 #include "clar_libgit2.h"
2 #include "apply_helpers.h"
4 static git_repository
*repo
;
6 #define TEST_REPO_PATH "merge-recursive"
8 void test_apply_both__initialize(void)
13 repo
= cl_git_sandbox_init(TEST_REPO_PATH
);
15 git_oid_fromstr(&oid
, "539bd011c4822c560c1d17cab095006b7a10f707");
16 cl_git_pass(git_commit_lookup(&commit
, repo
, &oid
));
17 cl_git_pass(git_reset(repo
, (git_object
*)commit
, GIT_RESET_HARD
, NULL
));
18 git_commit_free(commit
);
21 void test_apply_both__cleanup(void)
23 cl_git_sandbox_cleanup();
26 void test_apply_both__generated_diff(void)
29 git_commit
*a_commit
, *b_commit
;
30 git_tree
*a_tree
, *b_tree
;
32 git_diff_options diff_opts
= GIT_DIFF_OPTIONS_INIT
;
34 struct merge_index_entry both_expected
[] = {
35 { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
36 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
37 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
38 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
39 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
40 { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" },
42 size_t both_expected_cnt
= sizeof(both_expected
) /
43 sizeof(struct merge_index_entry
);
45 git_oid_fromstr(&a_oid
, "539bd011c4822c560c1d17cab095006b7a10f707");
46 git_oid_fromstr(&b_oid
, "7c7bf85e978f1d18c0566f702d2cb7766b9c8d4f");
47 cl_git_pass(git_commit_lookup(&a_commit
, repo
, &a_oid
));
48 cl_git_pass(git_commit_lookup(&b_commit
, repo
, &b_oid
));
50 cl_git_pass(git_commit_tree(&a_tree
, a_commit
));
51 cl_git_pass(git_commit_tree(&b_tree
, b_commit
));
53 cl_git_pass(git_diff_tree_to_tree(&diff
, repo
, a_tree
, b_tree
, &diff_opts
));
54 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
56 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
57 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
60 git_tree_free(a_tree
);
61 git_tree_free(b_tree
);
62 git_commit_free(a_commit
);
63 git_commit_free(b_commit
);
66 void test_apply_both__parsed_diff(void)
70 struct merge_index_entry both_expected
[] = {
71 { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
72 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
73 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
74 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
75 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
76 { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" },
78 size_t both_expected_cnt
= sizeof(both_expected
) /
79 sizeof(struct merge_index_entry
);
81 cl_git_pass(git_diff_from_buffer(&diff
,
82 DIFF_MODIFY_TWO_FILES
, strlen(DIFF_MODIFY_TWO_FILES
)));
83 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
85 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
86 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
91 void test_apply_both__removes_file(void)
95 struct merge_index_entry both_expected
[] = {
96 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" },
97 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
98 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
99 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
100 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" },
102 size_t both_expected_cnt
= sizeof(both_expected
) /
103 sizeof(struct merge_index_entry
);
105 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_DELETE_FILE
,
106 strlen(DIFF_DELETE_FILE
)));
107 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
109 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
110 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
115 void test_apply_both__adds_file(void)
119 struct merge_index_entry both_expected
[] = {
120 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" },
121 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
122 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
123 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
124 { 0100644, "6370543fcfedb3e6516ec53b06158f3687dc1447", 0, "newfile.txt" },
125 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
126 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" },
128 size_t both_expected_cnt
= sizeof(both_expected
) /
129 sizeof(struct merge_index_entry
);
131 cl_git_pass(git_diff_from_buffer(&diff
,
132 DIFF_ADD_FILE
, strlen(DIFF_ADD_FILE
)));
133 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
135 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
136 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
141 void test_apply_both__application_failure_leaves_index_unmodified(void)
146 const char *diff_file
= DIFF_MODIFY_TWO_FILES
;
148 struct merge_index_entry index_expected
[] = {
149 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" },
150 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
151 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
152 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
153 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
155 size_t index_expected_cnt
= sizeof(index_expected
) /
156 sizeof(struct merge_index_entry
);
158 /* mutate the index */
159 cl_git_pass(git_repository_index(&index
, repo
));
160 cl_git_pass(git_index_remove(index
, "veal.txt", 0));
161 cl_git_pass(git_index_write(index
));
162 git_index_free(index
);
164 cl_git_pass(git_diff_from_buffer(&diff
, diff_file
, strlen(diff_file
)));
165 cl_git_fail_with(GIT_EAPPLYFAIL
, git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
167 validate_apply_index(repo
, index_expected
, index_expected_cnt
);
168 validate_workdir_unchanged(repo
);
173 void test_apply_both__index_must_match_workdir(void)
177 git_index_entry idx_entry
;
179 const char *diff_file
= DIFF_MODIFY_TWO_FILES
;
182 * Append a line to the end of the file in both the index and the
183 * working directory. Although the appended line would allow for
184 * patch application in each, the line appended is different in
185 * each, so the application should not be allowed.
187 cl_git_append2file("merge-recursive/asparagus.txt",
188 "This is a modification.\n");
190 cl_git_pass(git_repository_index(&index
, repo
));
192 memset(&idx_entry
, 0, sizeof(git_index_entry
));
193 idx_entry
.mode
= 0100644;
194 idx_entry
.path
= "asparagus.txt";
195 cl_git_pass(git_oid_fromstr(&idx_entry
.id
, "06d3fefb8726ab1099acc76e02dfb85e034b2538"));
196 cl_git_pass(git_index_add(index
, &idx_entry
));
198 cl_git_pass(git_index_write(index
));
199 git_index_free(index
);
201 cl_git_pass(git_diff_from_buffer(&diff
, diff_file
, strlen(diff_file
)));
202 cl_git_fail_with(GIT_EAPPLYFAIL
, git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
207 void test_apply_both__index_mode_must_match_workdir(void)
211 if (!cl_is_chmod_supported())
214 /* Set a file in the working directory executable. */
215 cl_must_pass(p_chmod("merge-recursive/asparagus.txt", 0755));
217 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_MODIFY_TWO_FILES
,
218 strlen(DIFF_MODIFY_TWO_FILES
)));
219 cl_git_fail_with(GIT_EAPPLYFAIL
, git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
224 void test_apply_both__application_failure_leaves_workdir_unmodified(void)
229 const char *diff_file
= DIFF_MODIFY_TWO_FILES
;
231 struct merge_index_entry workdir_expected
[] = {
232 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" },
233 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
234 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
235 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
236 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
237 { 0100644, "8684724651336001c5dbce74bed6736d2443958d", 0, "veal.txt" },
239 size_t workdir_expected_cnt
= sizeof(workdir_expected
) /
240 sizeof(struct merge_index_entry
);
242 /* mutate the workdir */
243 cl_git_rewritefile("merge-recursive/veal.txt",
244 "This is a modification.\n");
246 cl_git_pass(git_repository_index(&index
, repo
));
247 cl_git_pass(git_index_add_bypath(index
, "veal.txt"));
248 cl_git_pass(git_index_write(index
));
249 git_index_free(index
);
251 cl_git_pass(git_diff_from_buffer(&diff
, diff_file
, strlen(diff_file
)));
252 cl_git_fail_with(GIT_EAPPLYFAIL
, git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
254 validate_apply_workdir(repo
, workdir_expected
, workdir_expected_cnt
);
259 void test_apply_both__keeps_nonconflicting_changes(void)
263 git_index_entry idx_entry
;
265 const char *diff_file
= DIFF_MODIFY_TWO_FILES
;
267 struct merge_index_entry index_expected
[] = {
268 { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
269 { 0100644, "898d12687fb35be271c27c795a6b32c8b51da79e", 0, "beef.txt" },
270 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
271 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
272 { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" },
274 size_t index_expected_cnt
= sizeof(index_expected
) /
275 sizeof(struct merge_index_entry
);
277 struct merge_index_entry workdir_expected
[] = {
278 { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
279 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
280 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
281 { 0100644, "f75ba05f340c51065cbea2e1fdbfe5fe13144c97", 0, "gravy.txt" },
282 { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" },
284 size_t workdir_expected_cnt
= sizeof(workdir_expected
) /
285 sizeof(struct merge_index_entry
);
287 /* mutate the index */
288 cl_git_pass(git_repository_index(&index
, repo
));
290 memset(&idx_entry
, 0, sizeof(git_index_entry
));
291 idx_entry
.mode
= 0100644;
292 idx_entry
.path
= "beef.txt";
293 cl_git_pass(git_oid_fromstr(&idx_entry
.id
, "898d12687fb35be271c27c795a6b32c8b51da79e"));
294 cl_git_pass(git_index_add(index
, &idx_entry
));
296 cl_git_pass(git_index_remove(index
, "bouilli.txt", 0));
297 cl_git_pass(git_index_write(index
));
298 git_index_free(index
);
300 /* and mutate the working directory */
301 cl_git_rmfile("merge-recursive/oyster.txt");
302 cl_git_rewritefile("merge-recursive/gravy.txt", "Hello, world.\n");
304 cl_git_pass(git_diff_from_buffer(&diff
, diff_file
, strlen(diff_file
)));
305 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
307 validate_apply_index(repo
, index_expected
, index_expected_cnt
);
308 validate_apply_workdir(repo
, workdir_expected
, workdir_expected_cnt
);
313 void test_apply_both__can_apply_nonconflicting_file_changes(void)
318 const char *diff_file
= DIFF_MODIFY_TWO_FILES
;
320 struct merge_index_entry both_expected
[] = {
321 { 0100644, "f8a701c8a1a22c1729ee50faff1111f2d64f96fc", 0, "asparagus.txt" },
322 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
323 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
324 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
325 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
326 { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" },
328 size_t both_expected_cnt
= sizeof(both_expected
) /
329 sizeof(struct merge_index_entry
);
332 * Replace the workdir file with a version that is different than
333 * HEAD but such that the patch still applies cleanly. This item
334 * has a new line appended.
336 cl_git_append2file("merge-recursive/asparagus.txt",
337 "This line is added in the index and the workdir.\n");
339 cl_git_pass(git_repository_index(&index
, repo
));
340 cl_git_pass(git_index_add_bypath(index
, "asparagus.txt"));
341 cl_git_pass(git_index_write(index
));
342 git_index_free(index
);
344 cl_git_pass(git_diff_from_buffer(&diff
, diff_file
, strlen(diff_file
)));
345 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
347 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
348 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
353 void test_apply_both__honors_crlf_attributes(void)
359 const char *diff_file
= DIFF_MODIFY_TWO_FILES
;
361 struct merge_index_entry index_expected
[] = {
362 { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
363 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
364 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
365 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
366 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
367 { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" },
369 size_t index_expected_cnt
= sizeof(index_expected
) /
370 sizeof(struct merge_index_entry
);
372 struct merge_index_entry workdir_expected
[] = {
373 { 0100644, "176a458f94e0ea5272ce67c36bf30b6be9caf623", 0, ".gitattributes" },
374 { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
375 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
376 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
377 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
378 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
379 { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" },
381 size_t workdir_expected_cnt
= sizeof(workdir_expected
) /
382 sizeof(struct merge_index_entry
);
384 cl_git_mkfile("merge-recursive/.gitattributes", "* text=auto\n");
386 cl_git_rmfile("merge-recursive/asparagus.txt");
387 cl_git_rmfile("merge-recursive/veal.txt");
389 git_oid_fromstr(&oid
, "539bd011c4822c560c1d17cab095006b7a10f707");
390 cl_git_pass(git_commit_lookup(&commit
, repo
, &oid
));
391 cl_git_pass(git_reset(repo
, (git_object
*)commit
, GIT_RESET_HARD
, NULL
));
392 git_commit_free(commit
);
394 cl_git_pass(git_diff_from_buffer(&diff
, diff_file
, strlen(diff_file
)));
395 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
397 validate_apply_index(repo
, index_expected
, index_expected_cnt
);
398 validate_apply_workdir(repo
, workdir_expected
, workdir_expected_cnt
);
403 void test_apply_both__rename(void)
407 struct merge_index_entry both_expected
[] = {
408 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" },
409 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
410 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
411 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "notbeef.txt" },
412 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
413 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" },
415 size_t both_expected_cnt
= sizeof(both_expected
) /
416 sizeof(struct merge_index_entry
);
418 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_FILE
,
419 strlen(DIFF_RENAME_FILE
)));
420 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
422 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
423 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
428 void test_apply_both__rename_and_modify(void)
432 struct merge_index_entry both_expected
[] = {
433 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" },
434 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
435 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
436 { 0100644, "6fa10147f00fe1fab1d5e835529a9dad53db8552", 0, "notbeef.txt" },
437 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
438 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" },
440 size_t both_expected_cnt
= sizeof(both_expected
) /
441 sizeof(struct merge_index_entry
);
443 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_AND_MODIFY_FILE
,
444 strlen(DIFF_RENAME_AND_MODIFY_FILE
)));
445 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
447 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
448 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
453 void test_apply_both__rename_a_to_b_to_c(void)
457 struct merge_index_entry both_expected
[] = {
458 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "beef.txt" },
459 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
460 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
461 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "notbeef.txt" },
462 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
463 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" },
465 size_t both_expected_cnt
= sizeof(both_expected
) /
466 sizeof(struct merge_index_entry
);
468 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_A_TO_B_TO_C
,
469 strlen(DIFF_RENAME_A_TO_B_TO_C
)));
470 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
472 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
473 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
478 void test_apply_both__rename_a_to_b_to_c_exact(void)
482 struct merge_index_entry both_expected
[] = {
483 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "beef.txt" },
484 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
485 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
486 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "notbeef.txt" },
487 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
488 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" },
490 size_t both_expected_cnt
= sizeof(both_expected
) /
491 sizeof(struct merge_index_entry
);
493 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_A_TO_B_TO_C_EXACT
,
494 strlen(DIFF_RENAME_A_TO_B_TO_C_EXACT
)));
495 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
497 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
498 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
503 void test_apply_both__rename_circular(void)
507 struct merge_index_entry both_expected
[] = {
508 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "asparagus.txt" },
509 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "beef.txt" },
510 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
511 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
512 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
513 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" }
515 size_t both_expected_cnt
= sizeof(both_expected
) /
516 sizeof(struct merge_index_entry
);
518 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_CIRCULAR
,
519 strlen(DIFF_RENAME_CIRCULAR
)));
520 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
522 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
523 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
528 void test_apply_both__rename_2_to_1(void)
532 struct merge_index_entry both_expected
[] = {
533 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "2.txt" },
534 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
535 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
536 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
537 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" }
539 size_t both_expected_cnt
= sizeof(both_expected
) /
540 sizeof(struct merge_index_entry
);
542 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_2_TO_1
,
543 strlen(DIFF_RENAME_2_TO_1
)));
544 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
546 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
547 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
552 void test_apply_both__rename_1_to_2(void)
556 struct merge_index_entry both_expected
[] = {
557 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "1.txt" },
558 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "2.txt" },
559 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
560 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
561 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
562 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
563 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" }
565 size_t both_expected_cnt
= sizeof(both_expected
) /
566 sizeof(struct merge_index_entry
);
568 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_1_TO_2
,
569 strlen(DIFF_RENAME_1_TO_2
)));
570 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
572 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
573 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
578 void test_apply_both__two_deltas_one_file(void)
582 struct merge_index_entry both_expected
[] = {
583 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" },
584 { 0100644, "0a9fd4415635e72573f0f6b5e68084cfe18f5075", 0, "beef.txt" },
585 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
586 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
587 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
588 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" }
590 size_t both_expected_cnt
= sizeof(both_expected
) /
591 sizeof(struct merge_index_entry
);
593 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_TWO_DELTAS_ONE_FILE
,
594 strlen(DIFF_TWO_DELTAS_ONE_FILE
)));
595 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
597 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
598 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
603 void test_apply_both__two_deltas_one_new_file(void)
607 struct merge_index_entry both_expected
[] = {
608 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" },
609 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
610 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
611 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
612 { 0100644, "08d4c445cf0078f3d9b604b82f32f4d87e083325", 0, "newfile.txt" },
613 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
614 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" }
616 size_t both_expected_cnt
= sizeof(both_expected
) /
617 sizeof(struct merge_index_entry
);
619 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_TWO_DELTAS_ONE_NEW_FILE
,
620 strlen(DIFF_TWO_DELTAS_ONE_NEW_FILE
)));
621 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
623 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
624 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
629 void test_apply_both__rename_and_modify_deltas(void)
633 struct merge_index_entry both_expected
[] = {
634 { 0100644, "61c686bed39684eee8a2757ceb1291004a21333f", 0, "asdf.txt" },
635 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" },
636 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
637 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
638 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
639 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
641 size_t both_expected_cnt
= sizeof(both_expected
) /
642 sizeof(struct merge_index_entry
);
644 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_AND_MODIFY_DELTAS
,
645 strlen(DIFF_RENAME_AND_MODIFY_DELTAS
)));
646 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
648 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
649 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
654 void test_apply_both__rename_delta_after_modify_delta(void)
658 struct merge_index_entry both_expected
[] = {
659 { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" },
660 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
661 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
662 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
663 { 0100644, "292cb60ce5e25c337c5b6e12957bbbfe1be4bf49", 0, "other.txt" },
664 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
665 { 0100644, "c8c120f466591bbe3b8867361d5ec3cdd9fda756", 0, "veal.txt" }
667 size_t both_expected_cnt
= sizeof(both_expected
) /
668 sizeof(struct merge_index_entry
);
670 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_AFTER_MODIFY
,
671 strlen(DIFF_RENAME_AFTER_MODIFY
)));
672 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
674 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
675 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
680 void test_apply_both__cant_rename_after_modify_nonexistent_target_path(void)
684 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_AFTER_MODIFY_TARGET_PATH
,
685 strlen(DIFF_RENAME_AFTER_MODIFY_TARGET_PATH
)));
686 cl_git_fail(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
691 void test_apply_both__cant_modify_source_path_after_rename(void)
695 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_RENAME_AND_MODIFY_SOURCE_PATH
,
696 strlen(DIFF_RENAME_AND_MODIFY_SOURCE_PATH
)));
697 cl_git_fail(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
702 void test_apply_both__readd_deleted_file(void)
706 struct merge_index_entry both_expected
[] = {
707 { 0100644, "2dc7f8b24ba27f3888368bd180df03ff4c6c6fab", 0, "asparagus.txt" },
708 { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
709 { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
710 { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
711 { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
712 { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" }
714 size_t both_expected_cnt
= sizeof(both_expected
) /
715 sizeof(struct merge_index_entry
);
717 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_DELETE_AND_READD_FILE
,
718 strlen(DIFF_DELETE_AND_READD_FILE
)));
719 cl_git_pass(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
721 validate_apply_index(repo
, both_expected
, both_expected_cnt
);
722 validate_apply_workdir(repo
, both_expected
, both_expected_cnt
);
727 void test_apply_both__cant_remove_file_twice(void)
731 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_REMOVE_FILE_TWICE
,
732 strlen(DIFF_REMOVE_FILE_TWICE
)));
733 cl_git_fail(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));
738 void test_apply_both__cant_add_invalid_filename(void)
742 cl_git_pass(git_diff_from_buffer(&diff
, DIFF_ADD_INVALID_FILENAME
,
743 strlen(DIFF_ADD_INVALID_FILENAME
)));
744 cl_git_fail(git_apply(repo
, diff
, GIT_APPLY_LOCATION_BOTH
, NULL
));