]> git.proxmox.com Git - libgit2.git/blob - tests/rebase/merge.c
d24e4facffe648fc097e6744c4f7337f3c278ee0
[libgit2.git] / tests / rebase / merge.c
1 #include "clar_libgit2.h"
2 #include "git2/checkout.h"
3 #include "git2/rebase.h"
4 #include "posix.h"
5 #include "signature.h"
6
7 #include <fcntl.h>
8
9 static git_repository *repo;
10 static git_signature *signature;
11
12 static void set_core_autocrlf_to(git_repository *repo, bool value)
13 {
14 git_config *cfg;
15
16 cl_git_pass(git_repository_config(&cfg, repo));
17 cl_git_pass(git_config_set_bool(cfg, "core.autocrlf", value));
18
19 git_config_free(cfg);
20 }
21
22 /* Fixture setup and teardown */
23 void test_rebase_merge__initialize(void)
24 {
25 repo = cl_git_sandbox_init("rebase");
26 cl_git_pass(git_signature_new(&signature,
27 "Rebaser", "rebaser@rebaser.rb", 1405694510, 0));
28
29 set_core_autocrlf_to(repo, false);
30 }
31
32 void test_rebase_merge__cleanup(void)
33 {
34 git_signature_free(signature);
35 cl_git_sandbox_cleanup();
36 }
37
38 void test_rebase_merge__next(void)
39 {
40 git_rebase *rebase;
41 git_reference *branch_ref, *upstream_ref;
42 git_annotated_commit *branch_head, *upstream_head;
43 git_rebase_operation *rebase_operation;
44 git_status_list *status_list;
45 const git_status_entry *status_entry;
46 git_oid pick_id, file1_id;
47 git_oid master_id, beef_id;
48
49 git_oid_fromstr(&master_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00");
50 git_oid_fromstr(&beef_id, "b146bd7608eac53d9bf9e1a6963543588b555c64");
51
52 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef"));
53 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
54
55 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
56 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
57
58 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
59
60 cl_assert_equal_s("refs/heads/beef", git_rebase_orig_head_name(rebase));
61 cl_assert_equal_oid(&beef_id, git_rebase_orig_head_id(rebase));
62
63 cl_assert_equal_s("master", git_rebase_onto_name(rebase));
64 cl_assert_equal_oid(&master_id, git_rebase_onto_id(rebase));
65
66 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
67
68 git_oid_fromstr(&pick_id, "da9c51a23d02d931a486f45ad18cda05cf5d2b94");
69
70 cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation->type);
71 cl_assert_equal_oid(&pick_id, &rebase_operation->id);
72 cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n", 41, "rebase/.git/rebase-merge/current");
73 cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum");
74
75 cl_git_pass(git_status_list_new(&status_list, repo, NULL));
76 cl_assert_equal_i(1, git_status_list_entrycount(status_list));
77 cl_assert(status_entry = git_status_byindex(status_list, 0));
78
79 cl_assert_equal_s("beef.txt", status_entry->head_to_index->new_file.path);
80
81 git_oid_fromstr(&file1_id, "8d95ea62e621f1d38d230d9e7d206e41096d76af");
82 cl_assert_equal_oid(&file1_id, &status_entry->head_to_index->new_file.id);
83
84 git_status_list_free(status_list);
85 git_annotated_commit_free(branch_head);
86 git_annotated_commit_free(upstream_head);
87 git_reference_free(branch_ref);
88 git_reference_free(upstream_ref);
89 git_rebase_free(rebase);
90 }
91
92 void test_rebase_merge__next_with_conflicts(void)
93 {
94 git_rebase *rebase;
95 git_reference *branch_ref, *upstream_ref;
96 git_annotated_commit *branch_head, *upstream_head;
97 git_rebase_operation *rebase_operation;
98 git_status_list *status_list;
99 const git_status_entry *status_entry;
100 git_oid pick_id, commit_id;
101
102 const char *expected_merge =
103 "ASPARAGUS SOUP.\n"
104 "\n"
105 "<<<<<<< master\n"
106 "TAKE FOUR LARGE BUNCHES of asparagus, scrape it nicely, cut off one inch\n"
107 "OF THE TOPS, and lay them in water, chop the stalks and put them on the\n"
108 "FIRE WITH A PIECE OF BACON, a large onion cut up, and pepper and salt;\n"
109 "ADD TWO QUARTS OF WATER, boil them till the stalks are quite soft, then\n"
110 "PULP THEM THROUGH A SIEVE, and strain the water to it, which must be put\n"
111 "=======\n"
112 "Take four large bunches of asparagus, scrape it nicely, CUT OFF ONE INCH\n"
113 "of the tops, and lay them in water, chop the stalks and PUT THEM ON THE\n"
114 "fire with a piece of bacon, a large onion cut up, and pepper and salt;\n"
115 "add two quarts of water, boil them till the stalks are quite soft, then\n"
116 "pulp them through a sieve, and strain the water to it, which must be put\n"
117 ">>>>>>> Conflicting modification 1 to asparagus\n"
118 "back in the pot; put into it a chicken cut up, with the tops of\n"
119 "asparagus which had been laid by, boil it until these last articles are\n"
120 "sufficiently done, thicken with flour, butter and milk, and serve it up.\n";
121
122 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/asparagus"));
123 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
124
125 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
126 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
127
128 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
129
130 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
131
132 git_oid_fromstr(&pick_id, "33f915f9e4dbd9f4b24430e48731a59b45b15500");
133
134 cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation->type);
135 cl_assert_equal_oid(&pick_id, &rebase_operation->id);
136 cl_assert_equal_file("33f915f9e4dbd9f4b24430e48731a59b45b15500\n", 41, "rebase/.git/rebase-merge/current");
137 cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum");
138
139 cl_git_pass(git_status_list_new(&status_list, repo, NULL));
140 cl_assert_equal_i(1, git_status_list_entrycount(status_list));
141 cl_assert(status_entry = git_status_byindex(status_list, 0));
142
143 cl_assert_equal_s("asparagus.txt", status_entry->head_to_index->new_file.path);
144
145 cl_assert_equal_file(expected_merge, strlen(expected_merge), "rebase/asparagus.txt");
146
147 cl_git_fail_with(GIT_EUNMERGED, git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL));
148
149 git_status_list_free(status_list);
150 git_annotated_commit_free(branch_head);
151 git_annotated_commit_free(upstream_head);
152 git_reference_free(branch_ref);
153 git_reference_free(upstream_ref);
154 git_rebase_free(rebase);
155 }
156
157 void test_rebase_merge__next_stops_with_iterover(void)
158 {
159 git_rebase *rebase;
160 git_reference *branch_ref, *upstream_ref;
161 git_annotated_commit *branch_head, *upstream_head;
162 git_rebase_operation *rebase_operation;
163 git_oid commit_id;
164 int error;
165
166 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef"));
167 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
168
169 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
170 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
171
172 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
173
174 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
175 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
176 NULL, NULL));
177
178 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
179 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
180 NULL, NULL));
181
182 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
183 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
184 NULL, NULL));
185
186 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
187 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
188 NULL, NULL));
189
190 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
191 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
192 NULL, NULL));
193
194 cl_git_fail(error = git_rebase_next(&rebase_operation, rebase));
195 cl_assert_equal_i(GIT_ITEROVER, error);
196
197 cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end");
198 cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/msgnum");
199
200 git_annotated_commit_free(branch_head);
201 git_annotated_commit_free(upstream_head);
202 git_reference_free(branch_ref);
203 git_reference_free(upstream_ref);
204 git_rebase_free(rebase);
205 }
206
207 void test_rebase_merge__commit(void)
208 {
209 git_rebase *rebase;
210 git_reference *branch_ref, *upstream_ref;
211 git_annotated_commit *branch_head, *upstream_head;
212 git_rebase_operation *rebase_operation;
213 git_oid commit_id, tree_id, parent_id;
214 git_signature *author;
215 git_commit *commit;
216 git_reflog *reflog;
217 const git_reflog_entry *reflog_entry;
218
219 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef"));
220 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
221
222 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
223 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
224
225 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
226
227 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
228 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
229 NULL, NULL));
230
231 cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
232
233 git_oid_fromstr(&parent_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00");
234 cl_assert_equal_i(1, git_commit_parentcount(commit));
235 cl_assert_equal_oid(&parent_id, git_commit_parent_id(commit, 0));
236
237 git_oid_fromstr(&tree_id, "4461379789c777d2a6c1f2ee0e9d6c86731b9992");
238 cl_assert_equal_oid(&tree_id, git_commit_tree_id(commit));
239
240 cl_assert_equal_s(NULL, git_commit_message_encoding(commit));
241 cl_assert_equal_s("Modification 1 to beef\n", git_commit_message(commit));
242
243 cl_git_pass(git_signature_new(&author,
244 "Edward Thomson", "ethomson@edwardthomson.com", 1405621769, 0-(4*60)));
245 cl_assert(git_signature__equal(author, git_commit_author(commit)));
246
247 cl_assert(git_signature__equal(signature, git_commit_committer(commit)));
248
249 /* Make sure the reflogs are updated appropriately */
250 cl_git_pass(git_reflog_read(&reflog, repo, "HEAD"));
251 cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0));
252 cl_assert_equal_oid(&parent_id, git_reflog_entry_id_old(reflog_entry));
253 cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry));
254 cl_assert_equal_s("rebase: Modification 1 to beef", git_reflog_entry_message(reflog_entry));
255
256 git_reflog_free(reflog);
257 git_signature_free(author);
258 git_commit_free(commit);
259 git_annotated_commit_free(branch_head);
260 git_annotated_commit_free(upstream_head);
261 git_reference_free(branch_ref);
262 git_reference_free(upstream_ref);
263 git_rebase_free(rebase);
264 }
265
266 void test_rebase_merge__commit_with_id(void)
267 {
268 git_rebase *rebase;
269 git_oid branch_id, upstream_id;
270 git_annotated_commit *branch_head, *upstream_head;
271 git_rebase_operation *rebase_operation;
272 git_oid commit_id, tree_id, parent_id;
273 git_signature *author;
274 git_commit *commit;
275 git_reflog *reflog;
276 const git_reflog_entry *reflog_entry;
277
278 cl_git_pass(git_oid_fromstr(&branch_id, "b146bd7608eac53d9bf9e1a6963543588b555c64"));
279 cl_git_pass(git_oid_fromstr(&upstream_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"));
280
281 cl_git_pass(git_annotated_commit_lookup(&branch_head, repo, &branch_id));
282 cl_git_pass(git_annotated_commit_lookup(&upstream_head, repo, &upstream_id));
283
284 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
285
286 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
287 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
288 NULL, NULL));
289
290 cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
291
292 git_oid_fromstr(&parent_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00");
293 cl_assert_equal_i(1, git_commit_parentcount(commit));
294 cl_assert_equal_oid(&parent_id, git_commit_parent_id(commit, 0));
295
296 git_oid_fromstr(&tree_id, "4461379789c777d2a6c1f2ee0e9d6c86731b9992");
297 cl_assert_equal_oid(&tree_id, git_commit_tree_id(commit));
298
299 cl_assert_equal_s(NULL, git_commit_message_encoding(commit));
300 cl_assert_equal_s("Modification 1 to beef\n", git_commit_message(commit));
301
302 cl_git_pass(git_signature_new(&author,
303 "Edward Thomson", "ethomson@edwardthomson.com", 1405621769, 0-(4*60)));
304 cl_assert(git_signature__equal(author, git_commit_author(commit)));
305
306 cl_assert(git_signature__equal(signature, git_commit_committer(commit)));
307
308 /* Make sure the reflogs are updated appropriately */
309 cl_git_pass(git_reflog_read(&reflog, repo, "HEAD"));
310 cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0));
311 cl_assert_equal_oid(&parent_id, git_reflog_entry_id_old(reflog_entry));
312 cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry));
313 cl_assert_equal_s("rebase: Modification 1 to beef", git_reflog_entry_message(reflog_entry));
314
315 git_reflog_free(reflog);
316 git_signature_free(author);
317 git_commit_free(commit);
318 git_annotated_commit_free(branch_head);
319 git_annotated_commit_free(upstream_head);
320 git_rebase_free(rebase);
321 }
322
323 void test_rebase_merge__blocked_when_dirty(void)
324 {
325 git_rebase *rebase;
326 git_reference *branch_ref, *upstream_ref;
327 git_annotated_commit *branch_head, *upstream_head;
328 git_rebase_operation *rebase_operation;
329 git_oid commit_id;
330
331 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef"));
332 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
333
334 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
335 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
336
337 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
338
339 /* Allow untracked files */
340 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
341 cl_git_mkfile("rebase/untracked_file.txt", "This is untracked\n");
342 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
343 NULL, NULL));
344
345 /* Do not allow unstaged */
346 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
347 cl_git_mkfile("rebase/veal.txt", "This is an unstaged change\n");
348 cl_git_fail_with(GIT_EUNMERGED, git_rebase_commit(&commit_id, rebase, NULL, signature,
349 NULL, NULL));
350
351 git_annotated_commit_free(branch_head);
352 git_annotated_commit_free(upstream_head);
353 git_reference_free(branch_ref);
354 git_reference_free(upstream_ref);
355 git_rebase_free(rebase);
356 }
357
358 void test_rebase_merge__commit_updates_rewritten(void)
359 {
360 git_rebase *rebase;
361 git_reference *branch_ref, *upstream_ref;
362 git_annotated_commit *branch_head, *upstream_head;
363 git_rebase_operation *rebase_operation;
364 git_oid commit_id;
365
366 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef"));
367 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
368
369 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
370 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
371
372 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
373
374 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
375 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
376 NULL, NULL));
377
378 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
379 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
380 NULL, NULL));
381
382 cl_assert_equal_file(
383 "da9c51a23d02d931a486f45ad18cda05cf5d2b94 776e4c48922799f903f03f5f6e51da8b01e4cce0\n"
384 "8d1f13f93c4995760ac07d129246ac1ff64c0be9 ba1f9b4fd5cf8151f7818be2111cc0869f1eb95a\n",
385 164, "rebase/.git/rebase-merge/rewritten");
386
387 git_annotated_commit_free(branch_head);
388 git_annotated_commit_free(upstream_head);
389 git_reference_free(branch_ref);
390 git_reference_free(upstream_ref);
391 git_rebase_free(rebase);
392 }
393
394 void test_rebase_merge__commit_drops_already_applied(void)
395 {
396 git_rebase *rebase;
397 git_reference *branch_ref, *upstream_ref;
398 git_annotated_commit *branch_head, *upstream_head;
399 git_rebase_operation *rebase_operation;
400 git_oid commit_id;
401 int error;
402
403 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef"));
404 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/green_pea"));
405
406 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
407 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
408
409 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
410
411 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
412 cl_git_fail(error = git_rebase_commit(&commit_id, rebase, NULL, signature,
413 NULL, NULL));
414
415 cl_assert_equal_i(GIT_EAPPLIED, error);
416
417 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
418 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
419 NULL, NULL));
420
421 cl_assert_equal_file(
422 "8d1f13f93c4995760ac07d129246ac1ff64c0be9 2ac4fb7b74c1287f6c792acad759e1ec01e18dae\n",
423 82, "rebase/.git/rebase-merge/rewritten");
424
425 git_annotated_commit_free(branch_head);
426 git_annotated_commit_free(upstream_head);
427 git_reference_free(branch_ref);
428 git_reference_free(upstream_ref);
429 git_rebase_free(rebase);
430 }
431
432 void test_rebase_merge__finish(void)
433 {
434 git_rebase *rebase;
435 git_reference *branch_ref, *upstream_ref, *head_ref;
436 git_annotated_commit *branch_head, *upstream_head;
437 git_rebase_operation *rebase_operation;
438 git_oid commit_id;
439 git_reflog *reflog;
440 const git_reflog_entry *reflog_entry;
441 int error;
442
443 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy"));
444 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));
445
446 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
447 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
448
449 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
450
451 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
452 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
453 NULL, NULL));
454
455 cl_git_fail(error = git_rebase_next(&rebase_operation, rebase));
456 cl_assert_equal_i(GIT_ITEROVER, error);
457
458 cl_git_pass(git_rebase_finish(rebase, signature));
459
460 cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));
461
462 cl_git_pass(git_reference_lookup(&head_ref, repo, "HEAD"));
463 cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(head_ref));
464 cl_assert_equal_s("refs/heads/gravy", git_reference_symbolic_target(head_ref));
465
466 /* Make sure the reflogs are updated appropriately */
467 cl_git_pass(git_reflog_read(&reflog, repo, "HEAD"));
468 cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0));
469 cl_assert_equal_oid(&commit_id, git_reflog_entry_id_old(reflog_entry));
470 cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry));
471 cl_assert_equal_s("rebase finished: returning to refs/heads/gravy", git_reflog_entry_message(reflog_entry));
472 git_reflog_free(reflog);
473
474 cl_git_pass(git_reflog_read(&reflog, repo, "refs/heads/gravy"));
475 cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0));
476 cl_assert_equal_oid(git_annotated_commit_id(branch_head), git_reflog_entry_id_old(reflog_entry));
477 cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry));
478 cl_assert_equal_s("rebase finished: refs/heads/gravy onto f87d14a4a236582a0278a916340a793714256864", git_reflog_entry_message(reflog_entry));
479
480 git_reflog_free(reflog);
481 git_annotated_commit_free(branch_head);
482 git_annotated_commit_free(upstream_head);
483 git_reference_free(head_ref);
484 git_reference_free(branch_ref);
485 git_reference_free(upstream_ref);
486 git_rebase_free(rebase);
487 }
488
489 void test_rebase_merge__detached_finish(void)
490 {
491 git_rebase *rebase;
492 git_reference *branch_ref, *upstream_ref, *head_ref;
493 git_annotated_commit *branch_head, *upstream_head;
494 git_rebase_operation *rebase_operation;
495 git_oid commit_id;
496 git_reflog *reflog;
497 const git_reflog_entry *reflog_entry;
498 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
499 int error;
500
501 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy"));
502 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));
503
504 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
505 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
506
507 cl_git_pass(git_repository_set_head_detached_from_annotated(repo, branch_head));
508 opts.checkout_strategy = GIT_CHECKOUT_FORCE;
509 git_checkout_head(repo, &opts);
510
511 cl_git_pass(git_rebase_init(&rebase, repo, NULL, upstream_head, NULL, NULL));
512
513 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
514 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
515 NULL, NULL));
516
517 cl_git_fail(error = git_rebase_next(&rebase_operation, rebase));
518 cl_assert_equal_i(GIT_ITEROVER, error);
519
520 cl_git_pass(git_rebase_finish(rebase, signature));
521
522 cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));
523
524 cl_git_pass(git_reference_lookup(&head_ref, repo, "HEAD"));
525 cl_assert_equal_i(GIT_REFERENCE_DIRECT, git_reference_type(head_ref));
526
527 /* Make sure the reflogs are updated appropriately */
528 cl_git_pass(git_reflog_read(&reflog, repo, "HEAD"));
529 cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0));
530 cl_assert_equal_oid(git_annotated_commit_id(upstream_head), git_reflog_entry_id_old(reflog_entry));
531 cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry));
532
533 git_reflog_free(reflog);
534 git_annotated_commit_free(branch_head);
535 git_annotated_commit_free(upstream_head);
536 git_reference_free(head_ref);
537 git_reference_free(branch_ref);
538 git_reference_free(upstream_ref);
539 git_rebase_free(rebase);
540 }
541
542 void test_rebase_merge__finish_with_ids(void)
543 {
544 git_rebase *rebase;
545 git_reference *head_ref;
546 git_oid branch_id, upstream_id;
547 git_annotated_commit *branch_head, *upstream_head;
548 git_rebase_operation *rebase_operation;
549 git_oid commit_id;
550 git_reflog *reflog;
551 const git_reflog_entry *reflog_entry;
552 int error;
553
554 cl_git_pass(git_oid_fromstr(&branch_id, "d616d97082eb7bb2dc6f180a7cca940993b7a56f"));
555 cl_git_pass(git_oid_fromstr(&upstream_id, "f87d14a4a236582a0278a916340a793714256864"));
556
557 cl_git_pass(git_annotated_commit_lookup(&branch_head, repo, &branch_id));
558 cl_git_pass(git_annotated_commit_lookup(&upstream_head, repo, &upstream_id));
559
560 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
561
562 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
563 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
564 NULL, NULL));
565
566 cl_git_fail(error = git_rebase_next(&rebase_operation, rebase));
567 cl_assert_equal_i(GIT_ITEROVER, error);
568
569 cl_git_pass(git_rebase_finish(rebase, signature));
570
571 cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));
572
573 cl_git_pass(git_reference_lookup(&head_ref, repo, "HEAD"));
574 cl_assert_equal_i(GIT_REFERENCE_DIRECT, git_reference_type(head_ref));
575 cl_assert_equal_oid(&commit_id, git_reference_target(head_ref));
576
577 /* reflogs are not updated as if we were operating on proper
578 * branches. check that the last reflog entry is the rebase.
579 */
580 cl_git_pass(git_reflog_read(&reflog, repo, "HEAD"));
581 cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0));
582 cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry));
583 cl_assert_equal_s("rebase: Modification 3 to gravy", git_reflog_entry_message(reflog_entry));
584 git_reflog_free(reflog);
585
586 git_annotated_commit_free(branch_head);
587 git_annotated_commit_free(upstream_head);
588 git_reference_free(head_ref);
589 git_rebase_free(rebase);
590 }
591
592 void test_rebase_merge__no_common_ancestor(void)
593 {
594 git_rebase *rebase;
595 git_reference *branch_ref, *upstream_ref;
596 git_annotated_commit *branch_head, *upstream_head;
597 git_rebase_operation *rebase_operation;
598 git_oid commit_id, expected_final_id;
599
600 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/barley"));
601 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
602
603 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
604 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
605
606 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
607
608 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
609 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
610 NULL, NULL));
611
612 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
613 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
614 NULL, NULL));
615
616 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
617 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
618 NULL, NULL));
619
620 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
621 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
622 NULL, NULL));
623
624 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
625 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
626 NULL, NULL));
627
628 cl_git_pass(git_rebase_finish(rebase, signature));
629
630 git_oid_fromstr(&expected_final_id, "71e7ee8d4fe7d8bf0d107355197e0a953dfdb7f3");
631 cl_assert_equal_oid(&expected_final_id, &commit_id);
632
633 git_annotated_commit_free(branch_head);
634 git_annotated_commit_free(upstream_head);
635 git_reference_free(branch_ref);
636 git_reference_free(upstream_ref);
637 git_rebase_free(rebase);
638 }
639
640 static void test_copy_note(
641 const git_rebase_options *opts,
642 bool should_exist)
643 {
644 git_rebase *rebase;
645 git_reference *branch_ref, *upstream_ref;
646 git_annotated_commit *branch_head, *upstream_head;
647 git_commit *branch_commit;
648 git_rebase_operation *rebase_operation;
649 git_oid note_id, commit_id;
650 git_note *note = NULL;
651 int error;
652
653 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy"));
654 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));
655
656 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
657 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
658
659 cl_git_pass(git_reference_peel((git_object **)&branch_commit,
660 branch_ref, GIT_OBJECT_COMMIT));
661
662 /* Add a note to a commit */
663 cl_git_pass(git_note_create(&note_id, repo, "refs/notes/test",
664 git_commit_author(branch_commit), git_commit_committer(branch_commit),
665 git_commit_id(branch_commit),
666 "This is a commit note.", 0));
667
668 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, opts));
669
670 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
671 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
672 NULL, NULL));
673
674 cl_git_pass(git_rebase_finish(rebase, signature));
675
676 cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));
677
678 if (should_exist) {
679 cl_git_pass(git_note_read(&note, repo, "refs/notes/test", &commit_id));
680 cl_assert_equal_s("This is a commit note.", git_note_message(note));
681 } else {
682 cl_git_fail(error =
683 git_note_read(&note, repo, "refs/notes/test", &commit_id));
684 cl_assert_equal_i(GIT_ENOTFOUND, error);
685 }
686
687 git_note_free(note);
688 git_commit_free(branch_commit);
689 git_annotated_commit_free(branch_head);
690 git_annotated_commit_free(upstream_head);
691 git_reference_free(branch_ref);
692 git_reference_free(upstream_ref);
693 git_rebase_free(rebase);
694 }
695
696 void test_rebase_merge__copy_notes_off_by_default(void)
697 {
698 test_copy_note(NULL, 0);
699 }
700
701 void test_rebase_merge__copy_notes_specified_in_options(void)
702 {
703 git_rebase_options opts = GIT_REBASE_OPTIONS_INIT;
704 opts.rewrite_notes_ref = "refs/notes/test";
705
706 test_copy_note(&opts, 1);
707 }
708
709 void test_rebase_merge__copy_notes_specified_in_config(void)
710 {
711 git_config *config;
712
713 cl_git_pass(git_repository_config(&config, repo));
714 cl_git_pass(git_config_set_string(config,
715 "notes.rewriteRef", "refs/notes/test"));
716
717 test_copy_note(NULL, 1);
718 }
719
720 void test_rebase_merge__copy_notes_disabled_in_config(void)
721 {
722 git_config *config;
723
724 cl_git_pass(git_repository_config(&config, repo));
725 cl_git_pass(git_config_set_bool(config, "notes.rewrite.rebase", 0));
726 cl_git_pass(git_config_set_string(config,
727 "notes.rewriteRef", "refs/notes/test"));
728
729 test_copy_note(NULL, 0);
730 }
731
732 void rebase_checkout_progress_cb(
733 const char *path,
734 size_t completed_steps,
735 size_t total_steps,
736 void *payload)
737 {
738 int *called = payload;
739
740 GIT_UNUSED(path);
741 GIT_UNUSED(completed_steps);
742 GIT_UNUSED(total_steps);
743
744 *called = 1;
745 }
746
747 void test_rebase_merge__custom_checkout_options(void)
748 {
749 git_rebase *rebase;
750 git_reference *branch_ref, *upstream_ref;
751 git_annotated_commit *branch_head, *upstream_head;
752 git_rebase_options rebase_options = GIT_REBASE_OPTIONS_INIT;
753 git_checkout_options checkout_options = GIT_CHECKOUT_OPTIONS_INIT;
754 git_rebase_operation *rebase_operation;
755 int called = 0;
756
757 checkout_options.progress_cb = rebase_checkout_progress_cb;
758 checkout_options.progress_payload = &called;
759
760 memcpy(&rebase_options.checkout_options, &checkout_options,
761 sizeof(git_checkout_options));
762
763 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef"));
764 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
765
766 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
767 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
768
769 called = 0;
770 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &rebase_options));
771 cl_assert_equal_i(1, called);
772
773 called = 0;
774 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
775 cl_assert_equal_i(1, called);
776
777 called = 0;
778 cl_git_pass(git_rebase_abort(rebase));
779 cl_assert_equal_i(1, called);
780
781 git_annotated_commit_free(branch_head);
782 git_annotated_commit_free(upstream_head);
783 git_reference_free(branch_ref);
784 git_reference_free(upstream_ref);
785 git_rebase_free(rebase);
786 }
787
788 void test_rebase_merge__custom_merge_options(void)
789 {
790 git_rebase *rebase;
791 git_reference *branch_ref, *upstream_ref;
792 git_annotated_commit *branch_head, *upstream_head;
793 git_rebase_options rebase_options = GIT_REBASE_OPTIONS_INIT;
794 git_rebase_operation *rebase_operation;
795
796 rebase_options.merge_options.flags |=
797 GIT_MERGE_FAIL_ON_CONFLICT |
798 GIT_MERGE_SKIP_REUC;
799
800 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/asparagus"));
801 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
802
803 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
804 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
805
806 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &rebase_options));
807
808 cl_git_fail_with(GIT_EMERGECONFLICT, git_rebase_next(&rebase_operation, rebase));
809
810 git_annotated_commit_free(branch_head);
811 git_annotated_commit_free(upstream_head);
812 git_reference_free(branch_ref);
813 git_reference_free(upstream_ref);
814 git_rebase_free(rebase);
815 }
816
817 void test_rebase_merge__with_directories(void)
818 {
819 git_rebase *rebase;
820 git_reference *branch_ref, *upstream_ref;
821 git_annotated_commit *branch_head, *upstream_head;
822 git_rebase_operation *rebase_operation;
823 git_oid commit_id, tree_id;
824 git_commit *commit;
825
826 git_oid_fromstr(&tree_id, "a4d6d9c3d57308fd8e320cf2525bae8f1adafa57");
827
828 cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/deep_gravy"));
829 cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));
830
831 cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
832 cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
833
834 cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
835
836 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
837 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
838 NULL, NULL));
839
840 cl_git_pass(git_rebase_next(&rebase_operation, rebase));
841 cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
842 NULL, NULL));
843
844 cl_git_fail_with(GIT_ITEROVER, git_rebase_next(&rebase_operation, rebase));
845
846 cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
847 cl_assert_equal_oid(&tree_id, git_commit_tree_id(commit));
848
849 git_commit_free(commit);
850 git_annotated_commit_free(branch_head);
851 git_annotated_commit_free(upstream_head);
852 git_reference_free(branch_ref);
853 git_reference_free(upstream_ref);
854 git_rebase_free(rebase);
855 }