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