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