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