1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include "common.h"
9
10 #include "buffer.h"
11 #include "repository.h"
12 #include "posix.h"
13 #include "filebuf.h"
14 #include "merge.h"
15 #include "array.h"
16 #include "config.h"
17 #include "annotated_commit.h"
18 #include "index.h"
19
20 #include <git2/types.h>
21 #include <git2/annotated_commit.h>
22 #include <git2/rebase.h>
23 #include <git2/commit.h>
24 #include <git2/reset.h>
25 #include <git2/revwalk.h>
26 #include <git2/notes.h>
27
28 #define REBASE_APPLY_DIR "rebase-apply"
29 #define REBASE_MERGE_DIR "rebase-merge"
30
31 #define HEAD_NAME_FILE "head-name"
32 #define ORIG_HEAD_FILE "orig-head"
33 #define HEAD_FILE "head"
34 #define ONTO_FILE "onto"
35 #define ONTO_NAME_FILE "onto_name"
36 #define QUIET_FILE "quiet"
37
38 #define MSGNUM_FILE "msgnum"
39 #define END_FILE "end"
40 #define CMT_FILE_FMT "cmt.%" PRIuZ
41 #define CURRENT_FILE "current"
42 #define REWRITTEN_FILE "rewritten"
43
44 #define ORIG_DETACHED_HEAD "detached HEAD"
45
46 #define NOTES_DEFAULT_REF NULL
47
48 #define REBASE_DIR_MODE 0777
49 #define REBASE_FILE_MODE 0666
50
51 typedef enum {
52 GIT_REBASE_NONE = 0,
53 GIT_REBASE_APPLY = 1,
54 GIT_REBASE_MERGE = 2,
55 GIT_REBASE_INTERACTIVE = 3,
56 } git_rebase_t;
57
58 struct git_rebase {
59 git_repository *repo;
60
61 git_rebase_options options;
62
63 git_rebase_t type;
64 char *state_path;
65
66 int head_detached : 1,
67 inmemory : 1,
68 quiet : 1,
69 started : 1;
70
71 git_array_t(git_rebase_operation) operations;
72 size_t current;
73
74 /* Used by in-memory rebase */
75 git_index *index;
76 git_commit *last_commit;
77
78 /* Used by regular (not in-memory) merge-style rebase */
79 git_oid orig_head_id;
80 char *orig_head_name;
81
82 git_oid onto_id;
83 char *onto_name;
84 };
85
86 #define GIT_REBASE_STATE_INIT {0}
87
rebase_state_type(git_rebase_t * type_out,char ** path_out,git_repository * repo)88 static int rebase_state_type(
89 git_rebase_t *type_out,
90 char **path_out,
91 git_repository *repo)
92 {
93 git_buf path = GIT_BUF_INIT;
94 git_rebase_t type = GIT_REBASE_NONE;
95
96 if (git_buf_joinpath(&path, repo->gitdir, REBASE_APPLY_DIR) < 0)
97 return -1;
98
99 if (git_path_isdir(git_buf_cstr(&path))) {
100 type = GIT_REBASE_APPLY;
101 goto done;
102 }
103
104 git_buf_clear(&path);
105 if (git_buf_joinpath(&path, repo->gitdir, REBASE_MERGE_DIR) < 0)
106 return -1;
107
108 if (git_path_isdir(git_buf_cstr(&path))) {
109 type = GIT_REBASE_MERGE;
110 goto done;
111 }
112
113 done:
114 *type_out = type;
115
116 if (type != GIT_REBASE_NONE && path_out)
117 *path_out = git_buf_detach(&path);
118
119 git_buf_dispose(&path);
120
121 return 0;
122 }
123
rebase_readfile(git_buf * out,git_buf * state_path,const char * filename)124 GIT_INLINE(int) rebase_readfile(
125 git_buf *out,
126 git_buf *state_path,
127 const char *filename)
128 {
129 size_t state_path_len = state_path->size;
130 int error;
131
132 git_buf_clear(out);
133
134 if ((error = git_buf_joinpath(state_path, state_path->ptr, filename)) < 0 ||
135 (error = git_futils_readbuffer(out, state_path->ptr)) < 0)
136 goto done;
137
138 git_buf_rtrim(out);
139
140 done:
141 git_buf_truncate(state_path, state_path_len);
142 return error;
143 }
144
rebase_readint(size_t * out,git_buf * asc_out,git_buf * state_path,const char * filename)145 GIT_INLINE(int) rebase_readint(
146 size_t *out, git_buf *asc_out, git_buf *state_path, const char *filename)
147 {
148 int32_t num;
149 const char *eol;
150 int error = 0;
151
152 if ((error = rebase_readfile(asc_out, state_path, filename)) < 0)
153 return error;
154
155 if (git__strntol32(&num, asc_out->ptr, asc_out->size, &eol, 10) < 0 || num < 0 || *eol) {
156 git_error_set(GIT_ERROR_REBASE, "the file '%s' contains an invalid numeric value", filename);
157 return -1;
158 }
159
160 *out = (size_t) num;
161
162 return 0;
163 }
164
rebase_readoid(git_oid * out,git_buf * str_out,git_buf * state_path,const char * filename)165 GIT_INLINE(int) rebase_readoid(
166 git_oid *out, git_buf *str_out, git_buf *state_path, const char *filename)
167 {
168 int error;
169
170 if ((error = rebase_readfile(str_out, state_path, filename)) < 0)
171 return error;
172
173 if (str_out->size != GIT_OID_HEXSZ || git_oid_fromstr(out, str_out->ptr) < 0) {
174 git_error_set(GIT_ERROR_REBASE, "the file '%s' contains an invalid object ID", filename);
175 return -1;
176 }
177
178 return 0;
179 }
180
rebase_operation_alloc(git_rebase * rebase,git_rebase_operation_t type,git_oid * id,const char * exec)181 static git_rebase_operation *rebase_operation_alloc(
182 git_rebase *rebase,
183 git_rebase_operation_t type,
184 git_oid *id,
185 const char *exec)
186 {
187 git_rebase_operation *operation;
188
189 GIT_ASSERT_WITH_RETVAL((type == GIT_REBASE_OPERATION_EXEC) == !id, NULL);
190 GIT_ASSERT_WITH_RETVAL((type == GIT_REBASE_OPERATION_EXEC) == !!exec, NULL);
191
192 if ((operation = git_array_alloc(rebase->operations)) == NULL)
193 return NULL;
194
195 operation->type = type;
196 git_oid_cpy((git_oid *)&operation->id, id);
197 operation->exec = exec;
198
199 return operation;
200 }
201
rebase_open_merge(git_rebase * rebase)202 static int rebase_open_merge(git_rebase *rebase)
203 {
204 git_buf state_path = GIT_BUF_INIT, buf = GIT_BUF_INIT, cmt = GIT_BUF_INIT;
205 git_oid id;
206 git_rebase_operation *operation;
207 size_t i, msgnum = 0, end;
208 int error;
209
210 if ((error = git_buf_puts(&state_path, rebase->state_path)) < 0)
211 goto done;
212
213 /* Read 'msgnum' if it exists (otherwise, let msgnum = 0) */
214 if ((error = rebase_readint(&msgnum, &buf, &state_path, MSGNUM_FILE)) < 0 &&
215 error != GIT_ENOTFOUND)
216 goto done;
217
218 if (msgnum) {
219 rebase->started = 1;
220 rebase->current = msgnum - 1;
221 }
222
223 /* Read 'end' */
224 if ((error = rebase_readint(&end, &buf, &state_path, END_FILE)) < 0)
225 goto done;
226
227 /* Read 'current' if it exists */
228 if ((error = rebase_readoid(&id, &buf, &state_path, CURRENT_FILE)) < 0 &&
229 error != GIT_ENOTFOUND)
230 goto done;
231
232 /* Read cmt.* */
233 git_array_init_to_size(rebase->operations, end);
234 GIT_ERROR_CHECK_ARRAY(rebase->operations);
235
236 for (i = 0; i < end; i++) {
237 git_buf_clear(&cmt);
238
239 if ((error = git_buf_printf(&cmt, "cmt.%" PRIuZ, (i+1))) < 0 ||
240 (error = rebase_readoid(&id, &buf, &state_path, cmt.ptr)) < 0)
241 goto done;
242
243 operation = rebase_operation_alloc(rebase, GIT_REBASE_OPERATION_PICK, &id, NULL);
244 GIT_ERROR_CHECK_ALLOC(operation);
245 }
246
247 /* Read 'onto_name' */
248 if ((error = rebase_readfile(&buf, &state_path, ONTO_NAME_FILE)) < 0)
249 goto done;
250
251 rebase->onto_name = git_buf_detach(&buf);
252
253 done:
254 git_buf_dispose(&cmt);
255 git_buf_dispose(&state_path);
256 git_buf_dispose(&buf);
257
258 return error;
259 }
260
rebase_alloc(git_rebase ** out,const git_rebase_options * rebase_opts)261 static int rebase_alloc(git_rebase **out, const git_rebase_options *rebase_opts)
262 {
263 git_rebase *rebase = git__calloc(1, sizeof(git_rebase));
264 GIT_ERROR_CHECK_ALLOC(rebase);
265
266 *out = NULL;
267
268 if (rebase_opts)
269 memcpy(&rebase->options, rebase_opts, sizeof(git_rebase_options));
270 else
271 git_rebase_options_init(&rebase->options, GIT_REBASE_OPTIONS_VERSION);
272
273 if (rebase_opts && rebase_opts->rewrite_notes_ref) {
274 rebase->options.rewrite_notes_ref = git__strdup(rebase_opts->rewrite_notes_ref);
275 GIT_ERROR_CHECK_ALLOC(rebase->options.rewrite_notes_ref);
276 }
277
278 *out = rebase;
279
280 return 0;
281 }
282
rebase_check_versions(const git_rebase_options * given_opts)283 static int rebase_check_versions(const git_rebase_options *given_opts)
284 {
285 GIT_ERROR_CHECK_VERSION(given_opts, GIT_REBASE_OPTIONS_VERSION, "git_rebase_options");
286
287 if (given_opts)
288 GIT_ERROR_CHECK_VERSION(&given_opts->checkout_options, GIT_CHECKOUT_OPTIONS_VERSION, "git_checkout_options");
289
290 return 0;
291 }
292
git_rebase_open(git_rebase ** out,git_repository * repo,const git_rebase_options * given_opts)293 int git_rebase_open(
294 git_rebase **out,
295 git_repository *repo,
296 const git_rebase_options *given_opts)
297 {
298 git_rebase *rebase;
299 git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT,
300 orig_head_id = GIT_BUF_INIT, onto_id = GIT_BUF_INIT;
301 size_t state_path_len;
302 int error;
303
304 GIT_ASSERT_ARG(repo);
305
306 if ((error = rebase_check_versions(given_opts)) < 0)
307 return error;
308
309 if (rebase_alloc(&rebase, given_opts) < 0)
310 return -1;
311
312 rebase->repo = repo;
313
314 if ((error = rebase_state_type(&rebase->type, &rebase->state_path, repo)) < 0)
315 goto done;
316
317 if (rebase->type == GIT_REBASE_NONE) {
318 git_error_set(GIT_ERROR_REBASE, "there is no rebase in progress");
319 error = GIT_ENOTFOUND;
320 goto done;
321 }
322
323 if ((error = git_buf_puts(&path, rebase->state_path)) < 0)
324 goto done;
325
326 state_path_len = git_buf_len(&path);
327
328 if ((error = git_buf_joinpath(&path, path.ptr, HEAD_NAME_FILE)) < 0 ||
329 (error = git_futils_readbuffer(&orig_head_name, path.ptr)) < 0)
330 goto done;
331
332 git_buf_rtrim(&orig_head_name);
333
334 if (strcmp(ORIG_DETACHED_HEAD, orig_head_name.ptr) == 0)
335 rebase->head_detached = 1;
336
337 git_buf_truncate(&path, state_path_len);
338
339 if ((error = git_buf_joinpath(&path, path.ptr, ORIG_HEAD_FILE)) < 0)
340 goto done;
341
342 if (!git_path_isfile(path.ptr)) {
343 /* Previous versions of git.git used 'head' here; support that. */
344 git_buf_truncate(&path, state_path_len);
345
346 if ((error = git_buf_joinpath(&path, path.ptr, HEAD_FILE)) < 0)
347 goto done;
348 }
349
350 if ((error = git_futils_readbuffer(&orig_head_id, path.ptr)) < 0)
351 goto done;
352
353 git_buf_rtrim(&orig_head_id);
354
355 if ((error = git_oid_fromstr(&rebase->orig_head_id, orig_head_id.ptr)) < 0)
356 goto done;
357
358 git_buf_truncate(&path, state_path_len);
359
360 if ((error = git_buf_joinpath(&path, path.ptr, ONTO_FILE)) < 0 ||
361 (error = git_futils_readbuffer(&onto_id, path.ptr)) < 0)
362 goto done;
363
364 git_buf_rtrim(&onto_id);
365
366 if ((error = git_oid_fromstr(&rebase->onto_id, onto_id.ptr)) < 0)
367 goto done;
368
369 if (!rebase->head_detached)
370 rebase->orig_head_name = git_buf_detach(&orig_head_name);
371
372 switch (rebase->type) {
373 case GIT_REBASE_INTERACTIVE:
374 git_error_set(GIT_ERROR_REBASE, "interactive rebase is not supported");
375 error = -1;
376 break;
377 case GIT_REBASE_MERGE:
378 error = rebase_open_merge(rebase);
379 break;
380 case GIT_REBASE_APPLY:
381 git_error_set(GIT_ERROR_REBASE, "patch application rebase is not supported");
382 error = -1;
383 break;
384 default:
385 abort();
386 }
387
388 done:
389 if (error == 0)
390 *out = rebase;
391 else
392 git_rebase_free(rebase);
393
394 git_buf_dispose(&path);
395 git_buf_dispose(&orig_head_name);
396 git_buf_dispose(&orig_head_id);
397 git_buf_dispose(&onto_id);
398 return error;
399 }
400
rebase_cleanup(git_rebase * rebase)401 static int rebase_cleanup(git_rebase *rebase)
402 {
403 if (!rebase || rebase->inmemory)
404 return 0;
405
406 return git_path_isdir(rebase->state_path) ?
407 git_futils_rmdir_r(rebase->state_path, NULL, GIT_RMDIR_REMOVE_FILES) :
408 0;
409 }
410
rebase_setupfile(git_rebase * rebase,const char * filename,int flags,const char * fmt,...)411 static int rebase_setupfile(git_rebase *rebase, const char *filename, int flags, const char *fmt, ...)
412 {
413 git_buf path = GIT_BUF_INIT,
414 contents = GIT_BUF_INIT;
415 va_list ap;
416 int error;
417
418 va_start(ap, fmt);
419 git_buf_vprintf(&contents, fmt, ap);
420 va_end(ap);
421
422 if ((error = git_buf_joinpath(&path, rebase->state_path, filename)) == 0)
423 error = git_futils_writebuffer(&contents, path.ptr, flags, REBASE_FILE_MODE);
424
425 git_buf_dispose(&path);
426 git_buf_dispose(&contents);
427
428 return error;
429 }
430
rebase_onto_name(const git_annotated_commit * onto)431 static const char *rebase_onto_name(const git_annotated_commit *onto)
432 {
433 if (onto->ref_name && git__strncmp(onto->ref_name, "refs/heads/", 11) == 0)
434 return onto->ref_name + 11;
435 else if (onto->ref_name)
436 return onto->ref_name;
437 else
438 return onto->id_str;
439 }
440
rebase_setupfiles_merge(git_rebase * rebase)441 static int rebase_setupfiles_merge(git_rebase *rebase)
442 {
443 git_buf commit_filename = GIT_BUF_INIT;
444 char id_str[GIT_OID_HEXSZ];
445 git_rebase_operation *operation;
446 size_t i;
447 int error = 0;
448
449 if ((error = rebase_setupfile(rebase, END_FILE, 0, "%" PRIuZ "\n", git_array_size(rebase->operations))) < 0 ||
450 (error = rebase_setupfile(rebase, ONTO_NAME_FILE, 0, "%s\n", rebase->onto_name)) < 0)
451 goto done;
452
453 for (i = 0; i < git_array_size(rebase->operations); i++) {
454 operation = git_array_get(rebase->operations, i);
455
456 git_buf_clear(&commit_filename);
457 git_buf_printf(&commit_filename, CMT_FILE_FMT, i+1);
458
459 git_oid_fmt(id_str, &operation->id);
460
461 if ((error = rebase_setupfile(rebase, commit_filename.ptr, 0,
462 "%.*s\n", GIT_OID_HEXSZ, id_str)) < 0)
463 goto done;
464 }
465
466 done:
467 git_buf_dispose(&commit_filename);
468 return error;
469 }
470
rebase_setupfiles(git_rebase * rebase)471 static int rebase_setupfiles(git_rebase *rebase)
472 {
473 char onto[GIT_OID_HEXSZ], orig_head[GIT_OID_HEXSZ];
474 const char *orig_head_name;
475
476 git_oid_fmt(onto, &rebase->onto_id);
477 git_oid_fmt(orig_head, &rebase->orig_head_id);
478
479 if (p_mkdir(rebase->state_path, REBASE_DIR_MODE) < 0) {
480 git_error_set(GIT_ERROR_OS, "failed to create rebase directory '%s'", rebase->state_path);
481 return -1;
482 }
483
484 orig_head_name = rebase->head_detached ? ORIG_DETACHED_HEAD :
485 rebase->orig_head_name;
486
487 if (git_repository__set_orig_head(rebase->repo, &rebase->orig_head_id) < 0 ||
488 rebase_setupfile(rebase, HEAD_NAME_FILE, 0, "%s\n", orig_head_name) < 0 ||
489 rebase_setupfile(rebase, ONTO_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 ||
490 rebase_setupfile(rebase, ORIG_HEAD_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 ||
491 rebase_setupfile(rebase, QUIET_FILE, 0, rebase->quiet ? "t\n" : "\n") < 0)
492 return -1;
493
494 return rebase_setupfiles_merge(rebase);
495 }
496
git_rebase_options_init(git_rebase_options * opts,unsigned int version)497 int git_rebase_options_init(git_rebase_options *opts, unsigned int version)
498 {
499 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
500 opts, version, git_rebase_options, GIT_REBASE_OPTIONS_INIT);
501 return 0;
502 }
503
504 #ifndef GIT_DEPRECATE_HARD
git_rebase_init_options(git_rebase_options * opts,unsigned int version)505 int git_rebase_init_options(git_rebase_options *opts, unsigned int version)
506 {
507 return git_rebase_options_init(opts, version);
508 }
509 #endif
510
rebase_ensure_not_in_progress(git_repository * repo)511 static int rebase_ensure_not_in_progress(git_repository *repo)
512 {
513 int error;
514 git_rebase_t type;
515
516 if ((error = rebase_state_type(&type, NULL, repo)) < 0)
517 return error;
518
519 if (type != GIT_REBASE_NONE) {
520 git_error_set(GIT_ERROR_REBASE, "there is an existing rebase in progress");
521 return -1;
522 }
523
524 return 0;
525 }
526
rebase_ensure_not_dirty(git_repository * repo,bool check_index,bool check_workdir,int fail_with)527 static int rebase_ensure_not_dirty(
528 git_repository *repo,
529 bool check_index,
530 bool check_workdir,
531 int fail_with)
532 {
533 git_tree *head = NULL;
534 git_index *index = NULL;
535 git_diff *diff = NULL;
536 int error = 0;
537
538 if (check_index) {
539 if ((error = git_repository_head_tree(&head, repo)) < 0 ||
540 (error = git_repository_index(&index, repo)) < 0 ||
541 (error = git_diff_tree_to_index(&diff, repo, head, index, NULL)) < 0)
542 goto done;
543
544 if (git_diff_num_deltas(diff) > 0) {
545 git_error_set(GIT_ERROR_REBASE, "uncommitted changes exist in index");
546 error = fail_with;
547 goto done;
548 }
549
550 git_diff_free(diff);
551 diff = NULL;
552 }
553
554 if (check_workdir) {
555 git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
556 diff_opts.ignore_submodules = GIT_SUBMODULE_IGNORE_UNTRACKED;
557 if ((error = git_diff_index_to_workdir(&diff, repo, index, &diff_opts)) < 0)
558 goto done;
559
560 if (git_diff_num_deltas(diff) > 0) {
561 git_error_set(GIT_ERROR_REBASE, "unstaged changes exist in workdir");
562 error = fail_with;
563 goto done;
564 }
565 }
566
567 done:
568 git_diff_free(diff);
569 git_index_free(index);
570 git_tree_free(head);
571
572 return error;
573 }
574
rebase_init_operations(git_rebase * rebase,git_repository * repo,const git_annotated_commit * branch,const git_annotated_commit * upstream,const git_annotated_commit * onto)575 static int rebase_init_operations(
576 git_rebase *rebase,
577 git_repository *repo,
578 const git_annotated_commit *branch,
579 const git_annotated_commit *upstream,
580 const git_annotated_commit *onto)
581 {
582 git_revwalk *revwalk = NULL;
583 git_commit *commit;
584 git_oid id;
585 bool merge;
586 git_rebase_operation *operation;
587 int error;
588
589 if (!upstream)
590 upstream = onto;
591
592 if ((error = git_revwalk_new(&revwalk, rebase->repo)) < 0 ||
593 (error = git_revwalk_push(revwalk, git_annotated_commit_id(branch))) < 0 ||
594 (error = git_revwalk_hide(revwalk, git_annotated_commit_id(upstream))) < 0)
595 goto done;
596
597 git_revwalk_sorting(revwalk, GIT_SORT_REVERSE);
598
599 while ((error = git_revwalk_next(&id, revwalk)) == 0) {
600 if ((error = git_commit_lookup(&commit, repo, &id)) < 0)
601 goto done;
602
603 merge = (git_commit_parentcount(commit) > 1);
604 git_commit_free(commit);
605
606 if (merge)
607 continue;
608
609 operation = rebase_operation_alloc(rebase, GIT_REBASE_OPERATION_PICK, &id, NULL);
610 GIT_ERROR_CHECK_ALLOC(operation);
611 }
612
613 error = 0;
614
615 done:
616 git_revwalk_free(revwalk);
617 return error;
618 }
619
rebase_init_merge(git_rebase * rebase,git_repository * repo,const git_annotated_commit * branch,const git_annotated_commit * upstream,const git_annotated_commit * onto)620 static int rebase_init_merge(
621 git_rebase *rebase,
622 git_repository *repo,
623 const git_annotated_commit *branch,
624 const git_annotated_commit *upstream,
625 const git_annotated_commit *onto)
626 {
627 git_reference *head_ref = NULL;
628 git_commit *onto_commit = NULL;
629 git_buf reflog = GIT_BUF_INIT;
630 git_buf state_path = GIT_BUF_INIT;
631 int error;
632
633 GIT_UNUSED(upstream);
634
635 if ((error = git_buf_joinpath(&state_path, repo->gitdir, REBASE_MERGE_DIR)) < 0)
636 goto done;
637
638 rebase->state_path = git_buf_detach(&state_path);
639 GIT_ERROR_CHECK_ALLOC(rebase->state_path);
640
641 if (branch->ref_name && strcmp(branch->ref_name, "HEAD")) {
642 rebase->orig_head_name = git__strdup(branch->ref_name);
643 GIT_ERROR_CHECK_ALLOC(rebase->orig_head_name);
644 } else {
645 rebase->head_detached = 1;
646 }
647
648 rebase->onto_name = git__strdup(rebase_onto_name(onto));
649 GIT_ERROR_CHECK_ALLOC(rebase->onto_name);
650
651 rebase->quiet = rebase->options.quiet;
652
653 git_oid_cpy(&rebase->orig_head_id, git_annotated_commit_id(branch));
654 git_oid_cpy(&rebase->onto_id, git_annotated_commit_id(onto));
655
656 if ((error = rebase_setupfiles(rebase)) < 0 ||
657 (error = git_buf_printf(&reflog,
658 "rebase: checkout %s", rebase_onto_name(onto))) < 0 ||
659 (error = git_commit_lookup(
660 &onto_commit, repo, git_annotated_commit_id(onto))) < 0 ||
661 (error = git_checkout_tree(repo,
662 (git_object *)onto_commit, &rebase->options.checkout_options)) < 0 ||
663 (error = git_reference_create(&head_ref, repo, GIT_HEAD_FILE,
664 git_annotated_commit_id(onto), 1, reflog.ptr)) < 0)
665 goto done;
666
667 done:
668 git_reference_free(head_ref);
669 git_commit_free(onto_commit);
670 git_buf_dispose(&reflog);
671 git_buf_dispose(&state_path);
672
673 return error;
674 }
675
rebase_init_inmemory(git_rebase * rebase,git_repository * repo,const git_annotated_commit * branch,const git_annotated_commit * upstream,const git_annotated_commit * onto)676 static int rebase_init_inmemory(
677 git_rebase *rebase,
678 git_repository *repo,
679 const git_annotated_commit *branch,
680 const git_annotated_commit *upstream,
681 const git_annotated_commit *onto)
682 {
683 GIT_UNUSED(branch);
684 GIT_UNUSED(upstream);
685
686 return git_commit_lookup(
687 &rebase->last_commit, repo, git_annotated_commit_id(onto));
688 }
689
git_rebase_init(git_rebase ** out,git_repository * repo,const git_annotated_commit * branch,const git_annotated_commit * upstream,const git_annotated_commit * onto,const git_rebase_options * given_opts)690 int git_rebase_init(
691 git_rebase **out,
692 git_repository *repo,
693 const git_annotated_commit *branch,
694 const git_annotated_commit *upstream,
695 const git_annotated_commit *onto,
696 const git_rebase_options *given_opts)
697 {
698 git_rebase *rebase = NULL;
699 git_annotated_commit *head_branch = NULL;
700 git_reference *head_ref = NULL;
701 bool inmemory = (given_opts && given_opts->inmemory);
702 int error;
703
704 GIT_ASSERT_ARG(repo);
705 GIT_ASSERT_ARG(upstream || onto);
706
707 *out = NULL;
708
709 if (!onto)
710 onto = upstream;
711
712 if ((error = rebase_check_versions(given_opts)) < 0)
713 goto done;
714
715 if (!inmemory) {
716 if ((error = git_repository__ensure_not_bare(repo, "rebase")) < 0 ||
717 (error = rebase_ensure_not_in_progress(repo)) < 0 ||
718 (error = rebase_ensure_not_dirty(repo, true, true, GIT_ERROR)) < 0)
719 goto done;
720 }
721
722 if (!branch) {
723 if ((error = git_repository_head(&head_ref, repo)) < 0 ||
724 (error = git_annotated_commit_from_ref(&head_branch, repo, head_ref)) < 0)
725 goto done;
726
727 branch = head_branch;
728 }
729
730 if (rebase_alloc(&rebase, given_opts) < 0)
731 return -1;
732
733 rebase->repo = repo;
734 rebase->inmemory = inmemory;
735 rebase->type = GIT_REBASE_MERGE;
736
737 if ((error = rebase_init_operations(rebase, repo, branch, upstream, onto)) < 0)
738 goto done;
739
740 if (inmemory)
741 error = rebase_init_inmemory(rebase, repo, branch, upstream, onto);
742 else
743 error = rebase_init_merge(rebase, repo, branch ,upstream, onto);
744
745 if (error == 0)
746 *out = rebase;
747
748 done:
749 git_reference_free(head_ref);
750 git_annotated_commit_free(head_branch);
751
752 if (error < 0) {
753 rebase_cleanup(rebase);
754 git_rebase_free(rebase);
755 }
756
757 return error;
758 }
759
normalize_checkout_options_for_apply(git_checkout_options * checkout_opts,git_rebase * rebase,git_commit * current_commit)760 static void normalize_checkout_options_for_apply(
761 git_checkout_options *checkout_opts,
762 git_rebase *rebase,
763 git_commit *current_commit)
764 {
765 memcpy(checkout_opts, &rebase->options.checkout_options, sizeof(git_checkout_options));
766
767 if (!checkout_opts->ancestor_label)
768 checkout_opts->ancestor_label = "ancestor";
769
770 if (rebase->type == GIT_REBASE_MERGE) {
771 if (!checkout_opts->our_label)
772 checkout_opts->our_label = rebase->onto_name;
773
774 if (!checkout_opts->their_label)
775 checkout_opts->their_label = git_commit_summary(current_commit);
776 } else {
777 abort();
778 }
779 }
780
rebase_movenext(git_rebase * rebase)781 GIT_INLINE(int) rebase_movenext(git_rebase *rebase)
782 {
783 size_t next = rebase->started ? rebase->current + 1 : 0;
784
785 if (next == git_array_size(rebase->operations))
786 return GIT_ITEROVER;
787
788 rebase->started = 1;
789 rebase->current = next;
790
791 return 0;
792 }
793
rebase_next_merge(git_rebase_operation ** out,git_rebase * rebase)794 static int rebase_next_merge(
795 git_rebase_operation **out,
796 git_rebase *rebase)
797 {
798 git_buf path = GIT_BUF_INIT;
799 git_commit *current_commit = NULL, *parent_commit = NULL;
800 git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL;
801 git_index *index = NULL;
802 git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
803 git_rebase_operation *operation;
804 git_checkout_options checkout_opts;
805 char current_idstr[GIT_OID_HEXSZ];
806 unsigned int parent_count;
807 int error;
808
809 *out = NULL;
810
811 operation = git_array_get(rebase->operations, rebase->current);
812
813 if ((error = git_commit_lookup(¤t_commit, rebase->repo, &operation->id)) < 0 ||
814 (error = git_commit_tree(¤t_tree, current_commit)) < 0 ||
815 (error = git_repository_head_tree(&head_tree, rebase->repo)) < 0)
816 goto done;
817
818 if ((parent_count = git_commit_parentcount(current_commit)) > 1) {
819 git_error_set(GIT_ERROR_REBASE, "cannot rebase a merge commit");
820 error = -1;
821 goto done;
822 } else if (parent_count) {
823 if ((error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 ||
824 (error = git_commit_tree(&parent_tree, parent_commit)) < 0)
825 goto done;
826 }
827
828 git_oid_fmt(current_idstr, &operation->id);
829
830 normalize_checkout_options_for_apply(&checkout_opts, rebase, current_commit);
831
832 if ((error = git_indexwriter_init_for_operation(&indexwriter, rebase->repo, &checkout_opts.checkout_strategy)) < 0 ||
833 (error = rebase_setupfile(rebase, MSGNUM_FILE, 0, "%" PRIuZ "\n", rebase->current+1)) < 0 ||
834 (error = rebase_setupfile(rebase, CURRENT_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0 ||
835 (error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0 ||
836 (error = git_merge__check_result(rebase->repo, index)) < 0 ||
837 (error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0 ||
838 (error = git_indexwriter_commit(&indexwriter)) < 0)
839 goto done;
840
841 *out = operation;
842
843 done:
844 git_indexwriter_cleanup(&indexwriter);
845 git_index_free(index);
846 git_tree_free(current_tree);
847 git_tree_free(head_tree);
848 git_tree_free(parent_tree);
849 git_commit_free(parent_commit);
850 git_commit_free(current_commit);
851 git_buf_dispose(&path);
852
853 return error;
854 }
855
rebase_next_inmemory(git_rebase_operation ** out,git_rebase * rebase)856 static int rebase_next_inmemory(
857 git_rebase_operation **out,
858 git_rebase *rebase)
859 {
860 git_commit *current_commit = NULL, *parent_commit = NULL;
861 git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL;
862 git_rebase_operation *operation;
863 git_index *index = NULL;
864 unsigned int parent_count;
865 int error;
866
867 *out = NULL;
868
869 operation = git_array_get(rebase->operations, rebase->current);
870
871 if ((error = git_commit_lookup(¤t_commit, rebase->repo, &operation->id)) < 0 ||
872 (error = git_commit_tree(¤t_tree, current_commit)) < 0)
873 goto done;
874
875 if ((parent_count = git_commit_parentcount(current_commit)) > 1) {
876 git_error_set(GIT_ERROR_REBASE, "cannot rebase a merge commit");
877 error = -1;
878 goto done;
879 } else if (parent_count) {
880 if ((error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 ||
881 (error = git_commit_tree(&parent_tree, parent_commit)) < 0)
882 goto done;
883 }
884
885 if ((error = git_commit_tree(&head_tree, rebase->last_commit)) < 0 ||
886 (error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0)
887 goto done;
888
889 if (!rebase->index) {
890 rebase->index = index;
891 index = NULL;
892 } else {
893 if ((error = git_index_read_index(rebase->index, index)) < 0)
894 goto done;
895 }
896
897 *out = operation;
898
899 done:
900 git_commit_free(current_commit);
901 git_commit_free(parent_commit);
902 git_tree_free(current_tree);
903 git_tree_free(head_tree);
904 git_tree_free(parent_tree);
905 git_index_free(index);
906
907 return error;
908 }
909
git_rebase_next(git_rebase_operation ** out,git_rebase * rebase)910 int git_rebase_next(
911 git_rebase_operation **out,
912 git_rebase *rebase)
913 {
914 int error;
915
916 GIT_ASSERT_ARG(out);
917 GIT_ASSERT_ARG(rebase);
918
919 if ((error = rebase_movenext(rebase)) < 0)
920 return error;
921
922 if (rebase->inmemory)
923 error = rebase_next_inmemory(out, rebase);
924 else if (rebase->type == GIT_REBASE_MERGE)
925 error = rebase_next_merge(out, rebase);
926 else
927 abort();
928
929 return error;
930 }
931
git_rebase_inmemory_index(git_index ** out,git_rebase * rebase)932 int git_rebase_inmemory_index(
933 git_index **out,
934 git_rebase *rebase)
935 {
936 GIT_ASSERT_ARG(out);
937 GIT_ASSERT_ARG(rebase);
938 GIT_ASSERT_ARG(rebase->index);
939
940 GIT_REFCOUNT_INC(rebase->index);
941 *out = rebase->index;
942
943 return 0;
944 }
945
rebase_commit__create(git_commit ** out,git_rebase * rebase,git_index * index,git_commit * parent_commit,const git_signature * author,const git_signature * committer,const char * message_encoding,const char * message)946 static int rebase_commit__create(
947 git_commit **out,
948 git_rebase *rebase,
949 git_index *index,
950 git_commit *parent_commit,
951 const git_signature *author,
952 const git_signature *committer,
953 const char *message_encoding,
954 const char *message)
955 {
956 git_rebase_operation *operation;
957 git_commit *current_commit = NULL, *commit = NULL;
958 git_tree *parent_tree = NULL, *tree = NULL;
959 git_oid tree_id, commit_id;
960 git_buf commit_content = GIT_BUF_INIT, commit_signature = GIT_BUF_INIT,
961 signature_field = GIT_BUF_INIT;
962 const char *signature_field_string = NULL,
963 *commit_signature_string = NULL;
964 int error;
965
966 operation = git_array_get(rebase->operations, rebase->current);
967
968 if (git_index_has_conflicts(index)) {
969 git_error_set(GIT_ERROR_REBASE, "conflicts have not been resolved");
970 error = GIT_EUNMERGED;
971 goto done;
972 }
973
974 if ((error = git_commit_lookup(¤t_commit, rebase->repo, &operation->id)) < 0 ||
975 (error = git_commit_tree(&parent_tree, parent_commit)) < 0 ||
976 (error = git_index_write_tree_to(&tree_id, index, rebase->repo)) < 0 ||
977 (error = git_tree_lookup(&tree, rebase->repo, &tree_id)) < 0)
978 goto done;
979
980 if (git_oid_equal(&tree_id, git_tree_id(parent_tree))) {
981 git_error_set(GIT_ERROR_REBASE, "this patch has already been applied");
982 error = GIT_EAPPLIED;
983 goto done;
984 }
985
986 if (!author)
987 author = git_commit_author(current_commit);
988
989 if (!message) {
990 message_encoding = git_commit_message_encoding(current_commit);
991 message = git_commit_message(current_commit);
992 }
993
994 if ((error = git_commit_create_buffer(&commit_content, rebase->repo, author, committer,
995 message_encoding, message, tree, 1, (const git_commit **)&parent_commit)) < 0)
996 goto done;
997
998 if (rebase->options.signing_cb) {
999 git_error_clear();
1000 error = git_error_set_after_callback_function(rebase->options.signing_cb(
1001 &commit_signature, &signature_field, git_buf_cstr(&commit_content),
1002 rebase->options.payload), "commit signing_cb failed");
1003 if (error == GIT_PASSTHROUGH) {
1004 git_buf_dispose(&commit_signature);
1005 git_buf_dispose(&signature_field);
1006 git_error_clear();
1007 error = GIT_OK;
1008 } else if (error < 0)
1009 goto done;
1010 }
1011
1012 if (git_buf_is_allocated(&commit_signature)) {
1013 GIT_ASSERT(git_buf_contains_nul(&commit_signature));
1014 commit_signature_string = git_buf_cstr(&commit_signature);
1015 }
1016
1017 if (git_buf_is_allocated(&signature_field)) {
1018 GIT_ASSERT(git_buf_contains_nul(&signature_field));
1019 signature_field_string = git_buf_cstr(&signature_field);
1020 }
1021
1022 if ((error = git_commit_create_with_signature(&commit_id, rebase->repo,
1023 git_buf_cstr(&commit_content), commit_signature_string,
1024 signature_field_string)))
1025 goto done;
1026
1027 if ((error = git_commit_lookup(&commit, rebase->repo, &commit_id)) < 0)
1028 goto done;
1029
1030 *out = commit;
1031
1032 done:
1033 if (error < 0)
1034 git_commit_free(commit);
1035
1036 git_buf_dispose(&commit_signature);
1037 git_buf_dispose(&signature_field);
1038 git_buf_dispose(&commit_content);
1039 git_commit_free(current_commit);
1040 git_tree_free(parent_tree);
1041 git_tree_free(tree);
1042
1043 return error;
1044 }
1045
rebase_commit_merge(git_oid * commit_id,git_rebase * rebase,const git_signature * author,const git_signature * committer,const char * message_encoding,const char * message)1046 static int rebase_commit_merge(
1047 git_oid *commit_id,
1048 git_rebase *rebase,
1049 const git_signature *author,
1050 const git_signature *committer,
1051 const char *message_encoding,
1052 const char *message)
1053 {
1054 git_rebase_operation *operation;
1055 git_reference *head = NULL;
1056 git_commit *head_commit = NULL, *commit = NULL;
1057 git_index *index = NULL;
1058 char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ];
1059 int error;
1060
1061 operation = git_array_get(rebase->operations, rebase->current);
1062 GIT_ASSERT(operation);
1063
1064 if ((error = rebase_ensure_not_dirty(rebase->repo, false, true, GIT_EUNMERGED)) < 0 ||
1065 (error = git_repository_head(&head, rebase->repo)) < 0 ||
1066 (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJECT_COMMIT)) < 0 ||
1067 (error = git_repository_index(&index, rebase->repo)) < 0 ||
1068 (error = rebase_commit__create(&commit, rebase, index, head_commit,
1069 author, committer, message_encoding, message)) < 0 ||
1070 (error = git_reference__update_for_commit(
1071 rebase->repo, NULL, "HEAD", git_commit_id(commit), "rebase")) < 0)
1072 goto done;
1073
1074 git_oid_fmt(old_idstr, &operation->id);
1075 git_oid_fmt(new_idstr, git_commit_id(commit));
1076
1077 if ((error = rebase_setupfile(rebase, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND,
1078 "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr)) < 0)
1079 goto done;
1080
1081 git_oid_cpy(commit_id, git_commit_id(commit));
1082
1083 done:
1084 git_index_free(index);
1085 git_reference_free(head);
1086 git_commit_free(head_commit);
1087 git_commit_free(commit);
1088 return error;
1089 }
1090
rebase_commit_inmemory(git_oid * commit_id,git_rebase * rebase,const git_signature * author,const git_signature * committer,const char * message_encoding,const char * message)1091 static int rebase_commit_inmemory(
1092 git_oid *commit_id,
1093 git_rebase *rebase,
1094 const git_signature *author,
1095 const git_signature *committer,
1096 const char *message_encoding,
1097 const char *message)
1098 {
1099 git_commit *commit = NULL;
1100 int error = 0;
1101
1102 GIT_ASSERT_ARG(rebase->index);
1103 GIT_ASSERT_ARG(rebase->last_commit);
1104 GIT_ASSERT_ARG(rebase->current < rebase->operations.size);
1105
1106 if ((error = rebase_commit__create(&commit, rebase, rebase->index,
1107 rebase->last_commit, author, committer, message_encoding, message)) < 0)
1108 goto done;
1109
1110 git_commit_free(rebase->last_commit);
1111 rebase->last_commit = commit;
1112
1113 git_oid_cpy(commit_id, git_commit_id(commit));
1114
1115 done:
1116 if (error < 0)
1117 git_commit_free(commit);
1118
1119 return error;
1120 }
1121
git_rebase_commit(git_oid * id,git_rebase * rebase,const git_signature * author,const git_signature * committer,const char * message_encoding,const char * message)1122 int git_rebase_commit(
1123 git_oid *id,
1124 git_rebase *rebase,
1125 const git_signature *author,
1126 const git_signature *committer,
1127 const char *message_encoding,
1128 const char *message)
1129 {
1130 int error;
1131
1132 GIT_ASSERT_ARG(rebase);
1133 GIT_ASSERT_ARG(committer);
1134
1135 if (rebase->inmemory)
1136 error = rebase_commit_inmemory(
1137 id, rebase, author, committer, message_encoding, message);
1138 else if (rebase->type == GIT_REBASE_MERGE)
1139 error = rebase_commit_merge(
1140 id, rebase, author, committer, message_encoding, message);
1141 else
1142 abort();
1143
1144 return error;
1145 }
1146
git_rebase_abort(git_rebase * rebase)1147 int git_rebase_abort(git_rebase *rebase)
1148 {
1149 git_reference *orig_head_ref = NULL;
1150 git_commit *orig_head_commit = NULL;
1151 int error;
1152
1153 GIT_ASSERT_ARG(rebase);
1154
1155 if (rebase->inmemory)
1156 return 0;
1157
1158 error = rebase->head_detached ?
1159 git_reference_create(&orig_head_ref, rebase->repo, GIT_HEAD_FILE,
1160 &rebase->orig_head_id, 1, "rebase: aborting") :
1161 git_reference_symbolic_create(
1162 &orig_head_ref, rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
1163 "rebase: aborting");
1164
1165 if (error < 0)
1166 goto done;
1167
1168 if ((error = git_commit_lookup(
1169 &orig_head_commit, rebase->repo, &rebase->orig_head_id)) < 0 ||
1170 (error = git_reset(rebase->repo, (git_object *)orig_head_commit,
1171 GIT_RESET_HARD, &rebase->options.checkout_options)) < 0)
1172 goto done;
1173
1174 error = rebase_cleanup(rebase);
1175
1176 done:
1177 git_commit_free(orig_head_commit);
1178 git_reference_free(orig_head_ref);
1179
1180 return error;
1181 }
1182
notes_ref_lookup(git_buf * out,git_rebase * rebase)1183 static int notes_ref_lookup(git_buf *out, git_rebase *rebase)
1184 {
1185 git_config *config = NULL;
1186 int do_rewrite, error;
1187
1188 if (rebase->options.rewrite_notes_ref) {
1189 git_buf_attach_notowned(out,
1190 rebase->options.rewrite_notes_ref,
1191 strlen(rebase->options.rewrite_notes_ref));
1192 return 0;
1193 }
1194
1195 if ((error = git_repository_config(&config, rebase->repo)) < 0 ||
1196 (error = git_config_get_bool(&do_rewrite, config, "notes.rewrite.rebase")) < 0) {
1197
1198 if (error != GIT_ENOTFOUND)
1199 goto done;
1200
1201 git_error_clear();
1202 do_rewrite = 1;
1203 }
1204
1205 error = do_rewrite ?
1206 git_config_get_string_buf(out, config, "notes.rewriteref") :
1207 GIT_ENOTFOUND;
1208
1209 done:
1210 git_config_free(config);
1211 return error;
1212 }
1213
rebase_copy_note(git_rebase * rebase,const char * notes_ref,git_oid * from,git_oid * to,const git_signature * committer)1214 static int rebase_copy_note(
1215 git_rebase *rebase,
1216 const char *notes_ref,
1217 git_oid *from,
1218 git_oid *to,
1219 const git_signature *committer)
1220 {
1221 git_note *note = NULL;
1222 git_oid note_id;
1223 git_signature *who = NULL;
1224 int error;
1225
1226 if ((error = git_note_read(¬e, rebase->repo, notes_ref, from)) < 0) {
1227 if (error == GIT_ENOTFOUND) {
1228 git_error_clear();
1229 error = 0;
1230 }
1231
1232 goto done;
1233 }
1234
1235 if (!committer) {
1236 if((error = git_signature_default(&who, rebase->repo)) < 0) {
1237 if (error != GIT_ENOTFOUND ||
1238 (error = git_signature_now(&who, "unknown", "unknown")) < 0)
1239 goto done;
1240
1241 git_error_clear();
1242 }
1243
1244 committer = who;
1245 }
1246
1247 error = git_note_create(¬e_id, rebase->repo, notes_ref,
1248 git_note_author(note), committer, to, git_note_message(note), 0);
1249
1250 done:
1251 git_note_free(note);
1252 git_signature_free(who);
1253
1254 return error;
1255 }
1256
rebase_copy_notes(git_rebase * rebase,const git_signature * committer)1257 static int rebase_copy_notes(
1258 git_rebase *rebase,
1259 const git_signature *committer)
1260 {
1261 git_buf path = GIT_BUF_INIT, rewritten = GIT_BUF_INIT, notes_ref = GIT_BUF_INIT;
1262 char *pair_list, *fromstr, *tostr, *end;
1263 git_oid from, to;
1264 unsigned int linenum = 1;
1265 int error = 0;
1266
1267 if ((error = notes_ref_lookup(¬es_ref, rebase)) < 0) {
1268 if (error == GIT_ENOTFOUND) {
1269 git_error_clear();
1270 error = 0;
1271 }
1272
1273 goto done;
1274 }
1275
1276 if ((error = git_buf_joinpath(&path, rebase->state_path, REWRITTEN_FILE)) < 0 ||
1277 (error = git_futils_readbuffer(&rewritten, path.ptr)) < 0)
1278 goto done;
1279
1280 pair_list = rewritten.ptr;
1281
1282 while (*pair_list) {
1283 fromstr = pair_list;
1284
1285 if ((end = strchr(fromstr, '\n')) == NULL)
1286 goto on_error;
1287
1288 pair_list = end+1;
1289 *end = '\0';
1290
1291 if ((end = strchr(fromstr, ' ')) == NULL)
1292 goto on_error;
1293
1294 tostr = end+1;
1295 *end = '\0';
1296
1297 if (strlen(fromstr) != GIT_OID_HEXSZ ||
1298 strlen(tostr) != GIT_OID_HEXSZ ||
1299 git_oid_fromstr(&from, fromstr) < 0 ||
1300 git_oid_fromstr(&to, tostr) < 0)
1301 goto on_error;
1302
1303 if ((error = rebase_copy_note(rebase, notes_ref.ptr, &from, &to, committer)) < 0)
1304 goto done;
1305
1306 linenum++;
1307 }
1308
1309 goto done;
1310
1311 on_error:
1312 git_error_set(GIT_ERROR_REBASE, "invalid rewritten file at line %d", linenum);
1313 error = -1;
1314
1315 done:
1316 git_buf_dispose(&rewritten);
1317 git_buf_dispose(&path);
1318 git_buf_dispose(¬es_ref);
1319
1320 return error;
1321 }
1322
return_to_orig_head(git_rebase * rebase)1323 static int return_to_orig_head(git_rebase *rebase)
1324 {
1325 git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL;
1326 git_commit *terminal_commit = NULL;
1327 git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT;
1328 char onto[GIT_OID_HEXSZ];
1329 int error = 0;
1330
1331 git_oid_fmt(onto, &rebase->onto_id);
1332
1333 if ((error = git_buf_printf(&branch_msg,
1334 "rebase finished: %s onto %.*s",
1335 rebase->orig_head_name, GIT_OID_HEXSZ, onto)) == 0 &&
1336 (error = git_buf_printf(&head_msg,
1337 "rebase finished: returning to %s",
1338 rebase->orig_head_name)) == 0 &&
1339 (error = git_repository_head(&terminal_ref, rebase->repo)) == 0 &&
1340 (error = git_reference_peel((git_object **)&terminal_commit,
1341 terminal_ref, GIT_OBJECT_COMMIT)) == 0 &&
1342 (error = git_reference_create_matching(&branch_ref,
1343 rebase->repo, rebase->orig_head_name,
1344 git_commit_id(terminal_commit), 1,
1345 &rebase->orig_head_id, branch_msg.ptr)) == 0)
1346 error = git_reference_symbolic_create(&head_ref,
1347 rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
1348 head_msg.ptr);
1349
1350 git_buf_dispose(&head_msg);
1351 git_buf_dispose(&branch_msg);
1352 git_commit_free(terminal_commit);
1353 git_reference_free(head_ref);
1354 git_reference_free(branch_ref);
1355 git_reference_free(terminal_ref);
1356
1357 return error;
1358 }
1359
git_rebase_finish(git_rebase * rebase,const git_signature * signature)1360 int git_rebase_finish(
1361 git_rebase *rebase,
1362 const git_signature *signature)
1363 {
1364 int error = 0;
1365
1366 GIT_ASSERT_ARG(rebase);
1367
1368 if (rebase->inmemory)
1369 return 0;
1370
1371 if (!rebase->head_detached)
1372 error = return_to_orig_head(rebase);
1373
1374 if (error == 0 && (error = rebase_copy_notes(rebase, signature)) == 0)
1375 error = rebase_cleanup(rebase);
1376
1377 return error;
1378 }
1379
git_rebase_orig_head_name(git_rebase * rebase)1380 const char *git_rebase_orig_head_name(git_rebase *rebase) {
1381 GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
1382 return rebase->orig_head_name;
1383 }
1384
git_rebase_orig_head_id(git_rebase * rebase)1385 const git_oid *git_rebase_orig_head_id(git_rebase *rebase) {
1386 GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
1387 return &rebase->orig_head_id;
1388 }
1389
git_rebase_onto_name(git_rebase * rebase)1390 const char *git_rebase_onto_name(git_rebase *rebase) {
1391 GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
1392 return rebase->onto_name;
1393 }
1394
git_rebase_onto_id(git_rebase * rebase)1395 const git_oid *git_rebase_onto_id(git_rebase *rebase) {
1396 return &rebase->onto_id;
1397 }
1398
git_rebase_operation_entrycount(git_rebase * rebase)1399 size_t git_rebase_operation_entrycount(git_rebase *rebase)
1400 {
1401 GIT_ASSERT_ARG_WITH_RETVAL(rebase, 0);
1402
1403 return git_array_size(rebase->operations);
1404 }
1405
git_rebase_operation_current(git_rebase * rebase)1406 size_t git_rebase_operation_current(git_rebase *rebase)
1407 {
1408 GIT_ASSERT_ARG_WITH_RETVAL(rebase, 0);
1409
1410 return rebase->started ? rebase->current : GIT_REBASE_NO_OPERATION;
1411 }
1412
git_rebase_operation_byindex(git_rebase * rebase,size_t idx)1413 git_rebase_operation *git_rebase_operation_byindex(git_rebase *rebase, size_t idx)
1414 {
1415 GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
1416
1417 return git_array_get(rebase->operations, idx);
1418 }
1419
git_rebase_free(git_rebase * rebase)1420 void git_rebase_free(git_rebase *rebase)
1421 {
1422 if (rebase == NULL)
1423 return;
1424
1425 git_index_free(rebase->index);
1426 git_commit_free(rebase->last_commit);
1427 git__free(rebase->onto_name);
1428 git__free(rebase->orig_head_name);
1429 git__free(rebase->state_path);
1430 git_array_clear(rebase->operations);
1431 git__free((char *)rebase->options.rewrite_notes_ref);
1432 git__free(rebase);
1433 }
1434