]> git.proxmox.com Git - libgit2.git/blame - src/rebase.c
New upstream version 1.3.0+dfsg.1
[libgit2.git] / src / rebase.c
CommitLineData
867a36f3
ET
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"
eae0bfdc 9
867a36f3
ET
10#include "buffer.h"
11#include "repository.h"
12#include "posix.h"
13#include "filebuf.h"
14#include "merge.h"
15#include "array.h"
5ae9d296 16#include "config.h"
18b00406 17#include "annotated_commit.h"
be8404a7 18#include "index.h"
867a36f3
ET
19
20#include <git2/types.h>
18b00406 21#include <git2/annotated_commit.h>
867a36f3
ET
22#include <git2/rebase.h>
23#include <git2/commit.h>
24#include <git2/reset.h>
25#include <git2/revwalk.h>
5ae9d296 26#include <git2/notes.h>
867a36f3 27
979645a7
ET
28#define REBASE_APPLY_DIR "rebase-apply"
29#define REBASE_MERGE_DIR "rebase-merge"
867a36f3 30
979645a7
ET
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"
867a36f3 37
979645a7
ET
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"
867a36f3 43
979645a7 44#define ORIG_DETACHED_HEAD "detached HEAD"
867a36f3 45
979645a7 46#define NOTES_DEFAULT_REF NULL
5ae9d296 47
979645a7
ET
48#define REBASE_DIR_MODE 0777
49#define REBASE_FILE_MODE 0666
867a36f3
ET
50
51typedef enum {
22a2d3d5
UG
52 GIT_REBASE_NONE = 0,
53 GIT_REBASE_APPLY = 1,
54 GIT_REBASE_MERGE = 2,
55 GIT_REBASE_INTERACTIVE = 3,
56} git_rebase_t;
867a36f3 57
b6b636a7
ET
58struct git_rebase {
59 git_repository *repo;
60
f3a199dd 61 git_rebase_options options;
f3a199dd 62
22a2d3d5 63 git_rebase_t type;
4fe84d62
ET
64 char *state_path;
65
b6b636a7 66 int head_detached : 1,
ee667307 67 inmemory : 1,
f152f8ac
ET
68 quiet : 1,
69 started : 1;
4fe84d62 70
ee667307
ET
71 git_array_t(git_rebase_operation) operations;
72 size_t current;
73
74 /* Used by in-memory rebase */
f28bae0c 75 git_index *index;
ee667307 76 git_commit *last_commit;
ee667307
ET
77
78 /* Used by regular (not in-memory) merge-style rebase */
4fe84d62 79 git_oid orig_head_id;
ee667307 80 char *orig_head_name;
950a7091 81
517644cc 82 git_oid onto_id;
f152f8ac 83 char *onto_name;
b6b636a7 84};
4fe84d62
ET
85
86#define GIT_REBASE_STATE_INIT {0}
87
867a36f3 88static int rebase_state_type(
22a2d3d5 89 git_rebase_t *type_out,
867a36f3
ET
90 char **path_out,
91 git_repository *repo)
92{
93 git_buf path = GIT_BUF_INIT;
22a2d3d5 94 git_rebase_t type = GIT_REBASE_NONE;
867a36f3 95
84f56cb0 96 if (git_buf_joinpath(&path, repo->gitdir, REBASE_APPLY_DIR) < 0)
867a36f3
ET
97 return -1;
98
99 if (git_path_isdir(git_buf_cstr(&path))) {
22a2d3d5 100 type = GIT_REBASE_APPLY;
867a36f3
ET
101 goto done;
102 }
103
104 git_buf_clear(&path);
84f56cb0 105 if (git_buf_joinpath(&path, repo->gitdir, REBASE_MERGE_DIR) < 0)
867a36f3
ET
106 return -1;
107
108 if (git_path_isdir(git_buf_cstr(&path))) {
22a2d3d5 109 type = GIT_REBASE_MERGE;
867a36f3
ET
110 goto done;
111 }
112
113done:
114 *type_out = type;
115
22a2d3d5 116 if (type != GIT_REBASE_NONE && path_out)
867a36f3
ET
117 *path_out = git_buf_detach(&path);
118
ac3d33df 119 git_buf_dispose(&path);
867a36f3
ET
120
121 return 0;
122}
123
796b03bd
ET
124GIT_INLINE(int) rebase_readfile(
125 git_buf *out,
126 git_buf *state_path,
127 const char *filename)
950a7091 128{
f152f8ac
ET
129 size_t state_path_len = state_path->size;
130 int error;
950a7091 131
f152f8ac
ET
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)
950a7091
ET
136 goto done;
137
f152f8ac 138 git_buf_rtrim(out);
950a7091 139
f152f8ac
ET
140done:
141 git_buf_truncate(state_path, state_path_len);
142 return error;
143}
443d5674 144
f152f8ac
ET
145GIT_INLINE(int) rebase_readint(
146 size_t *out, git_buf *asc_out, git_buf *state_path, const char *filename)
147{
148 int32_t num;
796b03bd 149 const char *eol;
f152f8ac 150 int error = 0;
443d5674 151
f152f8ac
ET
152 if ((error = rebase_readfile(asc_out, state_path, filename)) < 0)
153 return error;
443d5674 154
6c7cee42 155 if (git__strntol32(&num, asc_out->ptr, asc_out->size, &eol, 10) < 0 || num < 0 || *eol) {
ac3d33df 156 git_error_set(GIT_ERROR_REBASE, "the file '%s' contains an invalid numeric value", filename);
f152f8ac
ET
157 return -1;
158 }
443d5674 159
f152f8ac 160 *out = (size_t) num;
443d5674 161
f152f8ac
ET
162 return 0;
163}
443d5674 164
f152f8ac
ET
165GIT_INLINE(int) rebase_readoid(
166 git_oid *out, git_buf *str_out, git_buf *state_path, const char *filename)
167{
168 int error;
443d5674 169
f152f8ac
ET
170 if ((error = rebase_readfile(str_out, state_path, filename)) < 0)
171 return error;
443d5674 172
f152f8ac 173 if (str_out->size != GIT_OID_HEXSZ || git_oid_fromstr(out, str_out->ptr) < 0) {
ac3d33df 174 git_error_set(GIT_ERROR_REBASE, "the file '%s' contains an invalid object ID", filename);
f152f8ac
ET
175 return -1;
176 }
950a7091 177
f152f8ac
ET
178 return 0;
179}
950a7091 180
92e87dd7
ET
181static 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
c25aa7cd
PP
189 GIT_ASSERT_WITH_RETVAL((type == GIT_REBASE_OPERATION_EXEC) == !id, NULL);
190 GIT_ASSERT_WITH_RETVAL((type == GIT_REBASE_OPERATION_EXEC) == !!exec, NULL);
92e87dd7
ET
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
f152f8ac
ET
202static int rebase_open_merge(git_rebase *rebase)
203{
204 git_buf state_path = GIT_BUF_INIT, buf = GIT_BUF_INIT, cmt = GIT_BUF_INIT;
92e87dd7 205 git_oid id;
f152f8ac
ET
206 git_rebase_operation *operation;
207 size_t i, msgnum = 0, end;
208 int error;
950a7091 209
f152f8ac
ET
210 if ((error = git_buf_puts(&state_path, rebase->state_path)) < 0)
211 goto done;
950a7091 212
f152f8ac
ET
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;
443d5674 217
f152f8ac
ET
218 if (msgnum) {
219 rebase->started = 1;
220 rebase->current = msgnum - 1;
221 }
950a7091 222
f152f8ac
ET
223 /* Read 'end' */
224 if ((error = rebase_readint(&end, &buf, &state_path, END_FILE)) < 0)
950a7091
ET
225 goto done;
226
f152f8ac 227 /* Read 'current' if it exists */
92e87dd7 228 if ((error = rebase_readoid(&id, &buf, &state_path, CURRENT_FILE)) < 0 &&
f152f8ac
ET
229 error != GIT_ENOTFOUND)
230 goto done;
231
232 /* Read cmt.* */
233 git_array_init_to_size(rebase->operations, end);
ac3d33df 234 GIT_ERROR_CHECK_ARRAY(rebase->operations);
950a7091 235
f152f8ac 236 for (i = 0; i < end; i++) {
f152f8ac
ET
237 git_buf_clear(&cmt);
238
239 if ((error = git_buf_printf(&cmt, "cmt.%" PRIuZ, (i+1))) < 0 ||
92e87dd7 240 (error = rebase_readoid(&id, &buf, &state_path, cmt.ptr)) < 0)
443d5674 241 goto done;
92e87dd7
ET
242
243 operation = rebase_operation_alloc(rebase, GIT_REBASE_OPERATION_PICK, &id, NULL);
ac3d33df 244 GIT_ERROR_CHECK_ALLOC(operation);
443d5674 245 }
950a7091 246
f152f8ac
ET
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
950a7091 253done:
ac3d33df
JK
254 git_buf_dispose(&cmt);
255 git_buf_dispose(&state_path);
256 git_buf_dispose(&buf);
950a7091
ET
257
258 return error;
259}
260
2afb6fa4 261static int rebase_alloc(git_rebase **out, const git_rebase_options *rebase_opts)
f3a199dd
ET
262{
263 git_rebase *rebase = git__calloc(1, sizeof(git_rebase));
ac3d33df 264 GIT_ERROR_CHECK_ALLOC(rebase);
f3a199dd 265
2afb6fa4 266 *out = NULL;
f3a199dd
ET
267
268 if (rebase_opts)
269 memcpy(&rebase->options, rebase_opts, sizeof(git_rebase_options));
270 else
22a2d3d5 271 git_rebase_options_init(&rebase->options, GIT_REBASE_OPTIONS_VERSION);
f3a199dd 272
f3a199dd 273 if (rebase_opts && rebase_opts->rewrite_notes_ref) {
2afb6fa4 274 rebase->options.rewrite_notes_ref = git__strdup(rebase_opts->rewrite_notes_ref);
ac3d33df 275 GIT_ERROR_CHECK_ALLOC(rebase->options.rewrite_notes_ref);
f3a199dd
ET
276 }
277
2afb6fa4
PS
278 *out = rebase;
279
280 return 0;
f3a199dd
ET
281}
282
283static int rebase_check_versions(const git_rebase_options *given_opts)
284{
ac3d33df 285 GIT_ERROR_CHECK_VERSION(given_opts, GIT_REBASE_OPTIONS_VERSION, "git_rebase_options");
f3a199dd
ET
286
287 if (given_opts)
ac3d33df 288 GIT_ERROR_CHECK_VERSION(&given_opts->checkout_options, GIT_CHECKOUT_OPTIONS_VERSION, "git_checkout_options");
f3a199dd
ET
289
290 return 0;
291}
292
293int git_rebase_open(
294 git_rebase **out,
295 git_repository *repo,
296 const git_rebase_options *given_opts)
4fe84d62 297{
b6b636a7 298 git_rebase *rebase;
4fe84d62 299 git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT,
517644cc 300 orig_head_id = GIT_BUF_INIT, onto_id = GIT_BUF_INIT;
22a2d3d5
UG
301 size_t state_path_len;
302 int error;
4fe84d62 303
c25aa7cd 304 GIT_ASSERT_ARG(repo);
b6b636a7 305
f3a199dd
ET
306 if ((error = rebase_check_versions(given_opts)) < 0)
307 return error;
308
2afb6fa4
PS
309 if (rebase_alloc(&rebase, given_opts) < 0)
310 return -1;
4fe84d62 311
b6b636a7
ET
312 rebase->repo = repo;
313
314 if ((error = rebase_state_type(&rebase->type, &rebase->state_path, repo)) < 0)
4fe84d62
ET
315 goto done;
316
22a2d3d5 317 if (rebase->type == GIT_REBASE_NONE) {
ac3d33df 318 git_error_set(GIT_ERROR_REBASE, "there is no rebase in progress");
6f73e026
JG
319 error = GIT_ENOTFOUND;
320 goto done;
4fe84d62
ET
321 }
322
b6b636a7 323 if ((error = git_buf_puts(&path, rebase->state_path)) < 0)
4fe84d62
ET
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)
b6b636a7 335 rebase->head_detached = 1;
4fe84d62
ET
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
b6b636a7 355 if ((error = git_oid_fromstr(&rebase->orig_head_id, orig_head_id.ptr)) < 0)
4fe84d62
ET
356 goto done;
357
517644cc
ET
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
b6b636a7 366 if ((error = git_oid_fromstr(&rebase->onto_id, onto_id.ptr)) < 0)
517644cc
ET
367 goto done;
368
b6b636a7
ET
369 if (!rebase->head_detached)
370 rebase->orig_head_name = git_buf_detach(&orig_head_name);
4fe84d62 371
b6b636a7 372 switch (rebase->type) {
22a2d3d5 373 case GIT_REBASE_INTERACTIVE:
ac3d33df 374 git_error_set(GIT_ERROR_REBASE, "interactive rebase is not supported");
950a7091
ET
375 error = -1;
376 break;
22a2d3d5 377 case GIT_REBASE_MERGE:
b6b636a7 378 error = rebase_open_merge(rebase);
950a7091 379 break;
22a2d3d5 380 case GIT_REBASE_APPLY:
ac3d33df 381 git_error_set(GIT_ERROR_REBASE, "patch application rebase is not supported");
950a7091
ET
382 error = -1;
383 break;
384 default:
385 abort();
386 }
387
4fe84d62 388done:
b6b636a7
ET
389 if (error == 0)
390 *out = rebase;
391 else
392 git_rebase_free(rebase);
393
ac3d33df
JK
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);
4fe84d62
ET
398 return error;
399}
400
b6b636a7 401static int rebase_cleanup(git_rebase *rebase)
4fe84d62 402{
ee667307
ET
403 if (!rebase || rebase->inmemory)
404 return 0;
405
b6b636a7
ET
406 return git_path_isdir(rebase->state_path) ?
407 git_futils_rmdir_r(rebase->state_path, NULL, GIT_RMDIR_REMOVE_FILES) :
4fe84d62
ET
408 0;
409}
410
b6b636a7 411static int rebase_setupfile(git_rebase *rebase, const char *filename, int flags, const char *fmt, ...)
867a36f3
ET
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
b6b636a7 422 if ((error = git_buf_joinpath(&path, rebase->state_path, filename)) == 0)
a35a9890 423 error = git_futils_writebuffer(&contents, path.ptr, flags, REBASE_FILE_MODE);
867a36f3 424
ac3d33df
JK
425 git_buf_dispose(&path);
426 git_buf_dispose(&contents);
867a36f3
ET
427
428 return error;
429}
430
18b00406 431static const char *rebase_onto_name(const git_annotated_commit *onto)
867a36f3
ET
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
18b00406 438 return onto->id_str;
867a36f3
ET
439}
440
b6b636a7 441static int rebase_setupfiles_merge(git_rebase *rebase)
867a36f3 442{
867a36f3 443 git_buf commit_filename = GIT_BUF_INIT;
867a36f3 444 char id_str[GIT_OID_HEXSZ];
b6b636a7
ET
445 git_rebase_operation *operation;
446 size_t i;
447 int error = 0;
867a36f3 448
5a747e0c
ET
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)
867a36f3
ET
451 goto done;
452
b6b636a7
ET
453 for (i = 0; i < git_array_size(rebase->operations); i++) {
454 operation = git_array_get(rebase->operations, i);
867a36f3
ET
455
456 git_buf_clear(&commit_filename);
b6b636a7
ET
457 git_buf_printf(&commit_filename, CMT_FILE_FMT, i+1);
458
459 git_oid_fmt(id_str, &operation->id);
867a36f3 460
5a747e0c 461 if ((error = rebase_setupfile(rebase, commit_filename.ptr, 0,
867a36f3
ET
462 "%.*s\n", GIT_OID_HEXSZ, id_str)) < 0)
463 goto done;
464 }
465
867a36f3 466done:
ac3d33df 467 git_buf_dispose(&commit_filename);
867a36f3
ET
468 return error;
469}
470
b6b636a7 471static int rebase_setupfiles(git_rebase *rebase)
867a36f3 472{
b6b636a7 473 char onto[GIT_OID_HEXSZ], orig_head[GIT_OID_HEXSZ];
badc7283 474 const char *orig_head_name;
867a36f3 475
b6b636a7
ET
476 git_oid_fmt(onto, &rebase->onto_id);
477 git_oid_fmt(orig_head, &rebase->orig_head_id);
867a36f3 478
b6b636a7 479 if (p_mkdir(rebase->state_path, REBASE_DIR_MODE) < 0) {
ac3d33df 480 git_error_set(GIT_ERROR_OS, "failed to create rebase directory '%s'", rebase->state_path);
b6b636a7 481 return -1;
867a36f3
ET
482 }
483
badc7283
ET
484 orig_head_name = rebase->head_detached ? ORIG_DETACHED_HEAD :
485 rebase->orig_head_name;
486
b6b636a7 487 if (git_repository__set_orig_head(rebase->repo, &rebase->orig_head_id) < 0 ||
5a747e0c
ET
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)
b6b636a7 492 return -1;
867a36f3 493
b6b636a7 494 return rebase_setupfiles_merge(rebase);
867a36f3
ET
495}
496
22a2d3d5 497int git_rebase_options_init(git_rebase_options *opts, unsigned int version)
867a36f3
ET
498{
499 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
500 opts, version, git_rebase_options, GIT_REBASE_OPTIONS_INIT);
501 return 0;
502}
503
22a2d3d5
UG
504#ifndef GIT_DEPRECATE_HARD
505int git_rebase_init_options(git_rebase_options *opts, unsigned int version)
506{
507 return git_rebase_options_init(opts, version);
508}
509#endif
510
867a36f3
ET
511static int rebase_ensure_not_in_progress(git_repository *repo)
512{
513 int error;
22a2d3d5 514 git_rebase_t type;
867a36f3
ET
515
516 if ((error = rebase_state_type(&type, NULL, repo)) < 0)
517 return error;
518
22a2d3d5 519 if (type != GIT_REBASE_NONE) {
ac3d33df 520 git_error_set(GIT_ERROR_REBASE, "there is an existing rebase in progress");
867a36f3
ET
521 return -1;
522 }
523
524 return 0;
525}
526
eaf0d688
ET
527static int rebase_ensure_not_dirty(
528 git_repository *repo,
529 bool check_index,
530 bool check_workdir,
531 int fail_with)
867a36f3
ET
532{
533 git_tree *head = NULL;
534 git_index *index = NULL;
535 git_diff *diff = NULL;
02980bdc 536 int error = 0;
867a36f3 537
eaf0d688
ET
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;
867a36f3 543
eaf0d688 544 if (git_diff_num_deltas(diff) > 0) {
ac3d33df 545 git_error_set(GIT_ERROR_REBASE, "uncommitted changes exist in index");
eaf0d688
ET
546 error = fail_with;
547 goto done;
548 }
867a36f3 549
eaf0d688
ET
550 git_diff_free(diff);
551 diff = NULL;
552 }
867a36f3 553
eaf0d688 554 if (check_workdir) {
2270ca9f
DT
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)
eaf0d688 558 goto done;
867a36f3 559
eaf0d688 560 if (git_diff_num_deltas(diff) > 0) {
ac3d33df 561 git_error_set(GIT_ERROR_REBASE, "unstaged changes exist in workdir");
eaf0d688
ET
562 error = fail_with;
563 goto done;
564 }
867a36f3
ET
565 }
566
567done:
568 git_diff_free(diff);
569 git_index_free(index);
570 git_tree_free(head);
571
572 return error;
573}
574
b6b636a7
ET
575static int rebase_init_operations(
576 git_rebase *rebase,
577 git_repository *repo,
18b00406
ET
578 const git_annotated_commit *branch,
579 const git_annotated_commit *upstream,
580 const git_annotated_commit *onto)
b6b636a7
ET
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 ||
18b00406
ET
593 (error = git_revwalk_push(revwalk, git_annotated_commit_id(branch))) < 0 ||
594 (error = git_revwalk_hide(revwalk, git_annotated_commit_id(upstream))) < 0)
b6b636a7
ET
595 goto done;
596
3cc5ec94 597 git_revwalk_sorting(revwalk, GIT_SORT_REVERSE);
b6b636a7
ET
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
92e87dd7 609 operation = rebase_operation_alloc(rebase, GIT_REBASE_OPERATION_PICK, &id, NULL);
ac3d33df 610 GIT_ERROR_CHECK_ALLOC(operation);
b6b636a7
ET
611 }
612
613 error = 0;
614
615done:
616 git_revwalk_free(revwalk);
617 return error;
618}
619
620static int rebase_init_merge(
621 git_rebase *rebase,
622 git_repository *repo,
18b00406
ET
623 const git_annotated_commit *branch,
624 const git_annotated_commit *upstream,
625 const git_annotated_commit *onto)
b6b636a7 626{
49b8293c 627 git_reference *head_ref = NULL;
ee667307
ET
628 git_commit *onto_commit = NULL;
629 git_buf reflog = GIT_BUF_INIT;
b6b636a7
ET
630 git_buf state_path = GIT_BUF_INIT;
631 int error;
632
ee667307
ET
633 GIT_UNUSED(upstream);
634
84f56cb0 635 if ((error = git_buf_joinpath(&state_path, repo->gitdir, REBASE_MERGE_DIR)) < 0)
49b8293c
ET
636 goto done;
637
b6b636a7 638 rebase->state_path = git_buf_detach(&state_path);
ac3d33df 639 GIT_ERROR_CHECK_ALLOC(rebase->state_path);
ee667307 640
4db1fc7e 641 if (branch->ref_name && strcmp(branch->ref_name, "HEAD")) {
badc7283 642 rebase->orig_head_name = git__strdup(branch->ref_name);
ac3d33df 643 GIT_ERROR_CHECK_ALLOC(rebase->orig_head_name);
badc7283
ET
644 } else {
645 rebase->head_detached = 1;
646 }
ee667307
ET
647
648 rebase->onto_name = git__strdup(rebase_onto_name(onto));
ac3d33df 649 GIT_ERROR_CHECK_ALLOC(rebase->onto_name);
ee667307 650
f3a199dd 651 rebase->quiet = rebase->options.quiet;
b6b636a7 652
18b00406
ET
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));
b6b636a7 655
ee667307
ET
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;
b6b636a7 666
49b8293c
ET
667done:
668 git_reference_free(head_ref);
ee667307 669 git_commit_free(onto_commit);
ac3d33df
JK
670 git_buf_dispose(&reflog);
671 git_buf_dispose(&state_path);
49b8293c 672
b6b636a7
ET
673 return error;
674}
675
ee667307
ET
676static 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
b6b636a7
ET
690int git_rebase_init(
691 git_rebase **out,
867a36f3 692 git_repository *repo,
18b00406
ET
693 const git_annotated_commit *branch,
694 const git_annotated_commit *upstream,
695 const git_annotated_commit *onto,
f3a199dd 696 const git_rebase_options *given_opts)
867a36f3 697{
b6b636a7 698 git_rebase *rebase = NULL;
ee667307 699 git_annotated_commit *head_branch = NULL;
659cf202 700 git_reference *head_ref = NULL;
ee667307 701 bool inmemory = (given_opts && given_opts->inmemory);
867a36f3
ET
702 int error;
703
c25aa7cd
PP
704 GIT_ASSERT_ARG(repo);
705 GIT_ASSERT_ARG(upstream || onto);
867a36f3 706
b6b636a7
ET
707 *out = NULL;
708
b6b636a7
ET
709 if (!onto)
710 onto = upstream;
711
ee667307
ET
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 }
867a36f3 729
2afb6fa4
PS
730 if (rebase_alloc(&rebase, given_opts) < 0)
731 return -1;
867a36f3 732
ee667307
ET
733 rebase->repo = repo;
734 rebase->inmemory = inmemory;
22a2d3d5 735 rebase->type = GIT_REBASE_MERGE;
ee667307
ET
736
737 if ((error = rebase_init_operations(rebase, repo, branch, upstream, onto)) < 0)
867a36f3
ET
738 goto done;
739
ee667307
ET
740 if (inmemory)
741 error = rebase_init_inmemory(rebase, repo, branch, upstream, onto);
742 else
f928c69a 743 error = rebase_init_merge(rebase, repo, branch ,upstream, onto);
ee667307
ET
744
745 if (error == 0)
746 *out = rebase;
867a36f3
ET
747
748done:
659cf202 749 git_reference_free(head_ref);
ee667307
ET
750 git_annotated_commit_free(head_branch);
751
b6b636a7
ET
752 if (error < 0) {
753 rebase_cleanup(rebase);
754 git_rebase_free(rebase);
755 }
756
867a36f3
ET
757 return error;
758}
4fe84d62 759
f3a199dd 760static void normalize_checkout_options_for_apply(
443d5674 761 git_checkout_options *checkout_opts,
f3a199dd
ET
762 git_rebase *rebase,
763 git_commit *current_commit)
443d5674 764{
94c988f6 765 memcpy(checkout_opts, &rebase->options.checkout_options, sizeof(git_checkout_options));
443d5674
ET
766
767 if (!checkout_opts->ancestor_label)
768 checkout_opts->ancestor_label = "ancestor";
769
22a2d3d5 770 if (rebase->type == GIT_REBASE_MERGE) {
443d5674 771 if (!checkout_opts->our_label)
f152f8ac 772 checkout_opts->our_label = rebase->onto_name;
443d5674 773
796b03bd
ET
774 if (!checkout_opts->their_label)
775 checkout_opts->their_label = git_commit_summary(current_commit);
443d5674
ET
776 } else {
777 abort();
778 }
443d5674
ET
779}
780
f152f8ac
ET
781GIT_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
950a7091 794static int rebase_next_merge(
f152f8ac 795 git_rebase_operation **out,
f3a199dd 796 git_rebase *rebase)
950a7091 797{
f152f8ac 798 git_buf path = GIT_BUF_INIT;
f152f8ac 799 git_commit *current_commit = NULL, *parent_commit = NULL;
950a7091
ET
800 git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL;
801 git_index *index = NULL;
be8404a7 802 git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
f152f8ac 803 git_rebase_operation *operation;
f3a199dd 804 git_checkout_options checkout_opts;
f152f8ac 805 char current_idstr[GIT_OID_HEXSZ];
950a7091
ET
806 unsigned int parent_count;
807 int error;
808
f152f8ac 809 *out = NULL;
950a7091 810
f152f8ac 811 operation = git_array_get(rebase->operations, rebase->current);
443d5674 812
f152f8ac
ET
813 if ((error = git_commit_lookup(&current_commit, rebase->repo, &operation->id)) < 0 ||
814 (error = git_commit_tree(&current_tree, current_commit)) < 0 ||
b6b636a7 815 (error = git_repository_head_tree(&head_tree, rebase->repo)) < 0)
950a7091
ET
816 goto done;
817
f152f8ac 818 if ((parent_count = git_commit_parentcount(current_commit)) > 1) {
ac3d33df 819 git_error_set(GIT_ERROR_REBASE, "cannot rebase a merge commit");
950a7091
ET
820 error = -1;
821 goto done;
822 } else if (parent_count) {
f152f8ac 823 if ((error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 ||
950a7091
ET
824 (error = git_commit_tree(&parent_tree, parent_commit)) < 0)
825 goto done;
826 }
827
f152f8ac
ET
828 git_oid_fmt(current_idstr, &operation->id);
829
f3a199dd 830 normalize_checkout_options_for_apply(&checkout_opts, rebase, current_commit);
796b03bd 831
41fae48d 832 if ((error = git_indexwriter_init_for_operation(&indexwriter, rebase->repo, &checkout_opts.checkout_strategy)) < 0 ||
5a747e0c
ET
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 ||
a202e0d4 835 (error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0 ||
b6b636a7 836 (error = git_merge__check_result(rebase->repo, index)) < 0 ||
41fae48d
ET
837 (error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0 ||
838 (error = git_indexwriter_commit(&indexwriter)) < 0)
950a7091
ET
839 goto done;
840
f152f8ac 841 *out = operation;
18b439b9 842
950a7091 843done:
be8404a7 844 git_indexwriter_cleanup(&indexwriter);
950a7091
ET
845 git_index_free(index);
846 git_tree_free(current_tree);
847 git_tree_free(head_tree);
848 git_tree_free(parent_tree);
950a7091 849 git_commit_free(parent_commit);
f152f8ac 850 git_commit_free(current_commit);
ac3d33df 851 git_buf_dispose(&path);
950a7091
ET
852
853 return error;
854}
855
ee667307
ET
856static 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;
9a363d1b 864 unsigned int parent_count;
ee667307
ET
865 int error;
866
867 *out = NULL;
868
869 operation = git_array_get(rebase->operations, rebase->current);
870
871 if ((error = git_commit_lookup(&current_commit, rebase->repo, &operation->id)) < 0 ||
9a363d1b
ET
872 (error = git_commit_tree(&current_tree, current_commit)) < 0)
873 goto done;
874
875 if ((parent_count = git_commit_parentcount(current_commit)) > 1) {
ac3d33df 876 git_error_set(GIT_ERROR_REBASE, "cannot rebase a merge commit");
9a363d1b
ET
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 ||
a202e0d4 886 (error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0)
ee667307
ET
887 goto done;
888
f28bae0c
ET
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 }
ee667307
ET
896
897 *out = operation;
898
899done:
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
443d5674 910int git_rebase_next(
f152f8ac 911 git_rebase_operation **out,
f3a199dd 912 git_rebase *rebase)
950a7091 913{
950a7091
ET
914 int error;
915
c25aa7cd
PP
916 GIT_ASSERT_ARG(out);
917 GIT_ASSERT_ARG(rebase);
18b439b9 918
ee667307
ET
919 if ((error = rebase_movenext(rebase)) < 0)
920 return error;
921
922 if (rebase->inmemory)
923 error = rebase_next_inmemory(out, rebase);
22a2d3d5 924 else if (rebase->type == GIT_REBASE_MERGE)
f3a199dd 925 error = rebase_next_merge(out, rebase);
ee667307 926 else
950a7091 927 abort();
950a7091 928
a35a9890
ET
929 return error;
930}
931
f28bae0c
ET
932int git_rebase_inmemory_index(
933 git_index **out,
934 git_rebase *rebase)
935{
c25aa7cd
PP
936 GIT_ASSERT_ARG(out);
937 GIT_ASSERT_ARG(rebase);
938 GIT_ASSERT_ARG(rebase->index);
f28bae0c
ET
939
940 GIT_REFCOUNT_INC(rebase->index);
941 *out = rebase->index;
942
943 return 0;
944}
945
c25aa7cd
PP
946#ifndef GIT_DEPRECATE_HARD
947static int create_signed(
948 git_oid *out,
949 git_rebase *rebase,
950 const git_signature *author,
951 const git_signature *committer,
952 const char *message_encoding,
953 const char *message,
954 git_tree *tree,
955 size_t parent_count,
956 const git_commit **parents)
957{
958 git_buf commit_content = GIT_BUF_INIT,
959 commit_signature = GIT_BUF_INIT,
960 signature_field = GIT_BUF_INIT;
961 int error;
962
963 git_error_clear();
964
965 if ((error = git_commit_create_buffer(&commit_content,
966 rebase->repo, author, committer, message_encoding,
967 message, tree, parent_count, parents)) < 0)
968 goto done;
969
970 error = rebase->options.signing_cb(&commit_signature,
971 &signature_field, commit_content.ptr,
972 rebase->options.payload);
973
974 if (error) {
975 if (error != GIT_PASSTHROUGH)
976 git_error_set_after_callback_function(error, "signing_cb");
977
978 goto done;
979 }
980
981 error = git_commit_create_with_signature(out, rebase->repo,
982 commit_content.ptr,
983 commit_signature.size > 0 ? commit_signature.ptr : NULL,
984 signature_field.size > 0 ? signature_field.ptr : NULL);
985
986done:
987 git_buf_dispose(&commit_signature);
988 git_buf_dispose(&signature_field);
989 git_buf_dispose(&commit_content);
990 return error;
991}
992#endif
993
ee667307
ET
994static int rebase_commit__create(
995 git_commit **out,
b6b636a7 996 git_rebase *rebase,
ee667307
ET
997 git_index *index,
998 git_commit *parent_commit,
a35a9890
ET
999 const git_signature *author,
1000 const git_signature *committer,
1001 const char *message_encoding,
1002 const char *message)
1003{
f152f8ac 1004 git_rebase_operation *operation;
ee667307
ET
1005 git_commit *current_commit = NULL, *commit = NULL;
1006 git_tree *parent_tree = NULL, *tree = NULL;
1007 git_oid tree_id, commit_id;
a35a9890
ET
1008 int error;
1009
f152f8ac 1010 operation = git_array_get(rebase->operations, rebase->current);
a35a9890
ET
1011
1012 if (git_index_has_conflicts(index)) {
ac3d33df 1013 git_error_set(GIT_ERROR_REBASE, "conflicts have not been resolved");
eaf0d688 1014 error = GIT_EUNMERGED;
a35a9890
ET
1015 goto done;
1016 }
1017
ee667307
ET
1018 if ((error = git_commit_lookup(&current_commit, rebase->repo, &operation->id)) < 0 ||
1019 (error = git_commit_tree(&parent_tree, parent_commit)) < 0 ||
1020 (error = git_index_write_tree_to(&tree_id, index, rebase->repo)) < 0 ||
1021 (error = git_tree_lookup(&tree, rebase->repo, &tree_id)) < 0)
93a7004c
ET
1022 goto done;
1023
ee667307 1024 if (git_oid_equal(&tree_id, git_tree_id(parent_tree))) {
ac3d33df 1025 git_error_set(GIT_ERROR_REBASE, "this patch has already been applied");
93a7004c
ET
1026 error = GIT_EAPPLIED;
1027 goto done;
1028 }
1029
a35a9890 1030 if (!author)
f152f8ac 1031 author = git_commit_author(current_commit);
a35a9890
ET
1032
1033 if (!message) {
f152f8ac
ET
1034 message_encoding = git_commit_message_encoding(current_commit);
1035 message = git_commit_message(current_commit);
a35a9890
ET
1036 }
1037
c25aa7cd
PP
1038 git_error_clear();
1039 error = GIT_PASSTHROUGH;
22a2d3d5 1040
c25aa7cd
PP
1041 if (rebase->options.commit_create_cb) {
1042 error = rebase->options.commit_create_cb(&commit_id,
1043 author, committer, message_encoding, message,
1044 tree, 1, (const git_commit **)&parent_commit,
1045 rebase->options.payload);
22a2d3d5 1046
c25aa7cd
PP
1047 git_error_set_after_callback_function(error,
1048 "commit_create_cb");
22a2d3d5 1049 }
c25aa7cd
PP
1050#ifndef GIT_DEPRECATE_HARD
1051 else if (rebase->options.signing_cb) {
1052 error = create_signed(&commit_id, rebase, author,
1053 committer, message_encoding, message, tree,
1054 1, (const git_commit **)&parent_commit);
22a2d3d5 1055 }
c25aa7cd 1056#endif
22a2d3d5 1057
c25aa7cd
PP
1058 if (error == GIT_PASSTHROUGH)
1059 error = git_commit_create(&commit_id, rebase->repo, NULL,
1060 author, committer, message_encoding, message,
1061 tree, 1, (const git_commit **)&parent_commit);
1062
1063 if (error)
22a2d3d5
UG
1064 goto done;
1065
1066 if ((error = git_commit_lookup(&commit, rebase->repo, &commit_id)) < 0)
ee667307
ET
1067 goto done;
1068
1069 *out = commit;
1070
1071done:
1072 if (error < 0)
1073 git_commit_free(commit);
1074
1075 git_commit_free(current_commit);
1076 git_tree_free(parent_tree);
1077 git_tree_free(tree);
1078
1079 return error;
1080}
1081
1082static int rebase_commit_merge(
1083 git_oid *commit_id,
1084 git_rebase *rebase,
1085 const git_signature *author,
1086 const git_signature *committer,
1087 const char *message_encoding,
1088 const char *message)
1089{
1090 git_rebase_operation *operation;
1091 git_reference *head = NULL;
1092 git_commit *head_commit = NULL, *commit = NULL;
1093 git_index *index = NULL;
1094 char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ];
1095 int error;
1096
1097 operation = git_array_get(rebase->operations, rebase->current);
c25aa7cd 1098 GIT_ASSERT(operation);
ee667307
ET
1099
1100 if ((error = rebase_ensure_not_dirty(rebase->repo, false, true, GIT_EUNMERGED)) < 0 ||
1101 (error = git_repository_head(&head, rebase->repo)) < 0 ||
ac3d33df 1102 (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJECT_COMMIT)) < 0 ||
ee667307
ET
1103 (error = git_repository_index(&index, rebase->repo)) < 0 ||
1104 (error = rebase_commit__create(&commit, rebase, index, head_commit,
1105 author, committer, message_encoding, message)) < 0 ||
a612a25f 1106 (error = git_reference__update_for_commit(
ee667307 1107 rebase->repo, NULL, "HEAD", git_commit_id(commit), "rebase")) < 0)
a35a9890
ET
1108 goto done;
1109
ee667307
ET
1110 git_oid_fmt(old_idstr, &operation->id);
1111 git_oid_fmt(new_idstr, git_commit_id(commit));
1112
1113 if ((error = rebase_setupfile(rebase, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND,
1114 "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr)) < 0)
1115 goto done;
a35a9890 1116
ee667307 1117 git_oid_cpy(commit_id, git_commit_id(commit));
a35a9890
ET
1118
1119done:
a35a9890 1120 git_index_free(index);
ee667307
ET
1121 git_reference_free(head);
1122 git_commit_free(head_commit);
1123 git_commit_free(commit);
1124 return error;
1125}
1126
1127static int rebase_commit_inmemory(
1128 git_oid *commit_id,
1129 git_rebase *rebase,
1130 const git_signature *author,
1131 const git_signature *committer,
1132 const char *message_encoding,
1133 const char *message)
1134{
ee667307
ET
1135 git_commit *commit = NULL;
1136 int error = 0;
1137
c25aa7cd
PP
1138 GIT_ASSERT_ARG(rebase->index);
1139 GIT_ASSERT_ARG(rebase->last_commit);
1140 GIT_ASSERT_ARG(rebase->current < rebase->operations.size);
ee667307 1141
f28bae0c 1142 if ((error = rebase_commit__create(&commit, rebase, rebase->index,
ee667307
ET
1143 rebase->last_commit, author, committer, message_encoding, message)) < 0)
1144 goto done;
1145
ee667307
ET
1146 git_commit_free(rebase->last_commit);
1147 rebase->last_commit = commit;
1148
1149 git_oid_cpy(commit_id, git_commit_id(commit));
1150
1151done:
1152 if (error < 0)
1153 git_commit_free(commit);
a35a9890
ET
1154
1155 return error;
1156}
1157
1158int git_rebase_commit(
1159 git_oid *id,
b6b636a7 1160 git_rebase *rebase,
a35a9890
ET
1161 const git_signature *author,
1162 const git_signature *committer,
1163 const char *message_encoding,
1164 const char *message)
1165{
a35a9890
ET
1166 int error;
1167
c25aa7cd
PP
1168 GIT_ASSERT_ARG(rebase);
1169 GIT_ASSERT_ARG(committer);
a35a9890 1170
ee667307
ET
1171 if (rebase->inmemory)
1172 error = rebase_commit_inmemory(
1173 id, rebase, author, committer, message_encoding, message);
22a2d3d5 1174 else if (rebase->type == GIT_REBASE_MERGE)
a35a9890 1175 error = rebase_commit_merge(
b6b636a7 1176 id, rebase, author, committer, message_encoding, message);
ee667307 1177 else
a35a9890 1178 abort();
a35a9890 1179
950a7091
ET
1180 return error;
1181}
1182
f3a199dd 1183int git_rebase_abort(git_rebase *rebase)
4fe84d62 1184{
4fe84d62
ET
1185 git_reference *orig_head_ref = NULL;
1186 git_commit *orig_head_commit = NULL;
1187 int error;
1188
c25aa7cd 1189 GIT_ASSERT_ARG(rebase);
4fe84d62 1190
ee667307
ET
1191 if (rebase->inmemory)
1192 return 0;
1193
b6b636a7
ET
1194 error = rebase->head_detached ?
1195 git_reference_create(&orig_head_ref, rebase->repo, GIT_HEAD_FILE,
659cf202 1196 &rebase->orig_head_id, 1, "rebase: aborting") :
4fe84d62 1197 git_reference_symbolic_create(
b6b636a7 1198 &orig_head_ref, rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
659cf202 1199 "rebase: aborting");
4fe84d62
ET
1200
1201 if (error < 0)
1202 goto done;
1203
1204 if ((error = git_commit_lookup(
b6b636a7
ET
1205 &orig_head_commit, rebase->repo, &rebase->orig_head_id)) < 0 ||
1206 (error = git_reset(rebase->repo, (git_object *)orig_head_commit,
94c988f6 1207 GIT_RESET_HARD, &rebase->options.checkout_options)) < 0)
4fe84d62
ET
1208 goto done;
1209
b6b636a7 1210 error = rebase_cleanup(rebase);
4fe84d62
ET
1211
1212done:
1213 git_commit_free(orig_head_commit);
1214 git_reference_free(orig_head_ref);
4fe84d62
ET
1215
1216 return error;
1217}
517644cc 1218
f3a199dd
ET
1219static int notes_ref_lookup(git_buf *out, git_rebase *rebase)
1220{
1221 git_config *config = NULL;
1222 int do_rewrite, error;
1223
1224 if (rebase->options.rewrite_notes_ref) {
1225 git_buf_attach_notowned(out,
1226 rebase->options.rewrite_notes_ref,
1227 strlen(rebase->options.rewrite_notes_ref));
1228 return 0;
1229 }
1230
1231 if ((error = git_repository_config(&config, rebase->repo)) < 0 ||
1232 (error = git_config_get_bool(&do_rewrite, config, "notes.rewrite.rebase")) < 0) {
1233
1234 if (error != GIT_ENOTFOUND)
1235 goto done;
1236
ac3d33df 1237 git_error_clear();
f3a199dd
ET
1238 do_rewrite = 1;
1239 }
1240
1241 error = do_rewrite ?
1242 git_config_get_string_buf(out, config, "notes.rewriteref") :
1243 GIT_ENOTFOUND;
1244
1245done:
1246 git_config_free(config);
1247 return error;
1248}
1249
5ae9d296 1250static int rebase_copy_note(
b6b636a7 1251 git_rebase *rebase,
f3a199dd 1252 const char *notes_ref,
5ae9d296
ET
1253 git_oid *from,
1254 git_oid *to,
f3a199dd 1255 const git_signature *committer)
517644cc 1256{
5ae9d296
ET
1257 git_note *note = NULL;
1258 git_oid note_id;
979645a7 1259 git_signature *who = NULL;
5ae9d296
ET
1260 int error;
1261
f3a199dd 1262 if ((error = git_note_read(&note, rebase->repo, notes_ref, from)) < 0) {
5ae9d296 1263 if (error == GIT_ENOTFOUND) {
ac3d33df 1264 git_error_clear();
5ae9d296
ET
1265 error = 0;
1266 }
1267
1268 goto done;
1269 }
1270
979645a7
ET
1271 if (!committer) {
1272 if((error = git_signature_default(&who, rebase->repo)) < 0) {
1273 if (error != GIT_ENOTFOUND ||
1274 (error = git_signature_now(&who, "unknown", "unknown")) < 0)
1275 goto done;
1276
ac3d33df 1277 git_error_clear();
979645a7
ET
1278 }
1279
1280 committer = who;
1281 }
1282
f3a199dd 1283 error = git_note_create(&note_id, rebase->repo, notes_ref,
21083a71 1284 git_note_author(note), committer, to, git_note_message(note), 0);
5ae9d296
ET
1285
1286done:
1287 git_note_free(note);
979645a7 1288 git_signature_free(who);
5ae9d296
ET
1289
1290 return error;
1291}
1292
1293static int rebase_copy_notes(
b6b636a7 1294 git_rebase *rebase,
f3a199dd 1295 const git_signature *committer)
5ae9d296 1296{
f3a199dd 1297 git_buf path = GIT_BUF_INIT, rewritten = GIT_BUF_INIT, notes_ref = GIT_BUF_INIT;
5ae9d296
ET
1298 char *pair_list, *fromstr, *tostr, *end;
1299 git_oid from, to;
1300 unsigned int linenum = 1;
1301 int error = 0;
1302
f3a199dd
ET
1303 if ((error = notes_ref_lookup(&notes_ref, rebase)) < 0) {
1304 if (error == GIT_ENOTFOUND) {
ac3d33df 1305 git_error_clear();
f3a199dd
ET
1306 error = 0;
1307 }
1308
5ae9d296 1309 goto done;
f3a199dd 1310 }
5ae9d296 1311
b6b636a7 1312 if ((error = git_buf_joinpath(&path, rebase->state_path, REWRITTEN_FILE)) < 0 ||
5ae9d296
ET
1313 (error = git_futils_readbuffer(&rewritten, path.ptr)) < 0)
1314 goto done;
1315
1316 pair_list = rewritten.ptr;
1317
1318 while (*pair_list) {
1319 fromstr = pair_list;
1320
1321 if ((end = strchr(fromstr, '\n')) == NULL)
1322 goto on_error;
1323
1324 pair_list = end+1;
1325 *end = '\0';
1326
1327 if ((end = strchr(fromstr, ' ')) == NULL)
1328 goto on_error;
1329
1330 tostr = end+1;
1331 *end = '\0';
1332
1333 if (strlen(fromstr) != GIT_OID_HEXSZ ||
1334 strlen(tostr) != GIT_OID_HEXSZ ||
1335 git_oid_fromstr(&from, fromstr) < 0 ||
1336 git_oid_fromstr(&to, tostr) < 0)
1337 goto on_error;
1338
f3a199dd 1339 if ((error = rebase_copy_note(rebase, notes_ref.ptr, &from, &to, committer)) < 0)
5ae9d296
ET
1340 goto done;
1341
1342 linenum++;
1343 }
1344
1345 goto done;
1346
1347on_error:
ac3d33df 1348 git_error_set(GIT_ERROR_REBASE, "invalid rewritten file at line %d", linenum);
5ae9d296
ET
1349 error = -1;
1350
1351done:
ac3d33df
JK
1352 git_buf_dispose(&rewritten);
1353 git_buf_dispose(&path);
1354 git_buf_dispose(&notes_ref);
5ae9d296
ET
1355
1356 return error;
1357}
1358
1f84caf0 1359static int return_to_orig_head(git_rebase *rebase)
5ae9d296 1360{
517644cc
ET
1361 git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL;
1362 git_commit *terminal_commit = NULL;
1363 git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT;
1364 char onto[GIT_OID_HEXSZ];
1f84caf0 1365 int error = 0;
ee667307 1366
b6b636a7 1367 git_oid_fmt(onto, &rebase->onto_id);
517644cc 1368
1f84caf0
ET
1369 if ((error = git_buf_printf(&branch_msg,
1370 "rebase finished: %s onto %.*s",
1371 rebase->orig_head_name, GIT_OID_HEXSZ, onto)) == 0 &&
1372 (error = git_buf_printf(&head_msg,
1373 "rebase finished: returning to %s",
1374 rebase->orig_head_name)) == 0 &&
1375 (error = git_repository_head(&terminal_ref, rebase->repo)) == 0 &&
517644cc 1376 (error = git_reference_peel((git_object **)&terminal_commit,
ac3d33df 1377 terminal_ref, GIT_OBJECT_COMMIT)) == 0 &&
5ae9d296 1378 (error = git_reference_create_matching(&branch_ref,
1f84caf0
ET
1379 rebase->repo, rebase->orig_head_name,
1380 git_commit_id(terminal_commit), 1,
1381 &rebase->orig_head_id, branch_msg.ptr)) == 0)
1382 error = git_reference_symbolic_create(&head_ref,
b6b636a7 1383 rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
1f84caf0 1384 head_msg.ptr);
517644cc 1385
ac3d33df
JK
1386 git_buf_dispose(&head_msg);
1387 git_buf_dispose(&branch_msg);
517644cc
ET
1388 git_commit_free(terminal_commit);
1389 git_reference_free(head_ref);
1390 git_reference_free(branch_ref);
1391 git_reference_free(terminal_ref);
517644cc
ET
1392
1393 return error;
1394}
1395
1f84caf0
ET
1396int git_rebase_finish(
1397 git_rebase *rebase,
1398 const git_signature *signature)
1399{
1400 int error = 0;
1401
c25aa7cd 1402 GIT_ASSERT_ARG(rebase);
1f84caf0
ET
1403
1404 if (rebase->inmemory)
1405 return 0;
1406
1407 if (!rebase->head_detached)
1408 error = return_to_orig_head(rebase);
1409
1410 if (error == 0 && (error = rebase_copy_notes(rebase, signature)) == 0)
1411 error = rebase_cleanup(rebase);
1412
1413 return error;
1414}
1415
22a2d3d5 1416const char *git_rebase_orig_head_name(git_rebase *rebase) {
c25aa7cd 1417 GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
22a2d3d5
UG
1418 return rebase->orig_head_name;
1419}
1420
1421const git_oid *git_rebase_orig_head_id(git_rebase *rebase) {
c25aa7cd 1422 GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
22a2d3d5
UG
1423 return &rebase->orig_head_id;
1424}
1425
1426const char *git_rebase_onto_name(git_rebase *rebase) {
c25aa7cd 1427 GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
22a2d3d5
UG
1428 return rebase->onto_name;
1429}
1430
1431const git_oid *git_rebase_onto_id(git_rebase *rebase) {
1432 return &rebase->onto_id;
1433}
1434
ed2c06a6
ET
1435size_t git_rebase_operation_entrycount(git_rebase *rebase)
1436{
c25aa7cd 1437 GIT_ASSERT_ARG_WITH_RETVAL(rebase, 0);
ed2c06a6
ET
1438
1439 return git_array_size(rebase->operations);
1440}
1441
1442size_t git_rebase_operation_current(git_rebase *rebase)
1443{
c25aa7cd 1444 GIT_ASSERT_ARG_WITH_RETVAL(rebase, 0);
ed2c06a6 1445
30640aa9 1446 return rebase->started ? rebase->current : GIT_REBASE_NO_OPERATION;
ed2c06a6
ET
1447}
1448
1449git_rebase_operation *git_rebase_operation_byindex(git_rebase *rebase, size_t idx)
1450{
c25aa7cd 1451 GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
ed2c06a6
ET
1452
1453 return git_array_get(rebase->operations, idx);
1454}
1455
b6b636a7
ET
1456void git_rebase_free(git_rebase *rebase)
1457{
1458 if (rebase == NULL)
1459 return;
1460
f28bae0c 1461 git_index_free(rebase->index);
ee667307 1462 git_commit_free(rebase->last_commit);
f152f8ac 1463 git__free(rebase->onto_name);
b6b636a7
ET
1464 git__free(rebase->orig_head_name);
1465 git__free(rebase->state_path);
f152f8ac 1466 git_array_clear(rebase->operations);
f3a199dd 1467 git__free((char *)rebase->options.rewrite_notes_ref);
f152f8ac 1468 git__free(rebase);
b6b636a7 1469}