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 
set_core_autocrlf_to(git_repository * repo,bool value)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 */
test_rebase_merge__initialize(void)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 
test_rebase_merge__cleanup(void)32 void test_rebase_merge__cleanup(void)
33 {
34 	git_signature_free(signature);
35 	cl_git_sandbox_cleanup();
36 }
37 
test_rebase_merge__next(void)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 
test_rebase_merge__next_with_conflicts(void)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 
test_rebase_merge__next_stops_with_iterover(void)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 
test_rebase_merge__commit(void)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 
test_rebase_merge__commit_with_id(void)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 
test_rebase_merge__blocked_when_dirty(void)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 
test_rebase_merge__commit_updates_rewritten(void)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 
test_rebase_merge__commit_drops_already_applied(void)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 
test_rebase_merge__finish(void)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 
test_rebase_merge__detached_finish(void)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 
test_rebase_merge__finish_with_ids(void)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 
test_rebase_merge__no_common_ancestor(void)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 
test_copy_note(const git_rebase_options * opts,bool should_exist)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 
test_rebase_merge__copy_notes_off_by_default(void)696 void test_rebase_merge__copy_notes_off_by_default(void)
697 {
698 	test_copy_note(NULL, 0);
699 }
700 
test_rebase_merge__copy_notes_specified_in_options(void)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 
test_rebase_merge__copy_notes_specified_in_config(void)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 
test_rebase_merge__copy_notes_disabled_in_config(void)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 
rebase_checkout_progress_cb(const char * path,size_t completed_steps,size_t total_steps,void * payload)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 
test_rebase_merge__custom_checkout_options(void)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 
test_rebase_merge__custom_merge_options(void)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 
test_rebase_merge__with_directories(void)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 }
856