static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
+static GIT_PATH_FUNC(rebase_path_head_name, "rebase-merge/head-name")
+static GIT_PATH_FUNC(rebase_path_onto, "rebase-merge/onto")
static inline int is_rebase_i(const struct replay_opts *opts)
{
TODO_PICK = 0,
TODO_REVERT,
TODO_EDIT,
+ TODO_REWORD,
TODO_FIXUP,
TODO_SQUASH,
/* commands that do something else than handling a single commit */
{ 'p', "pick" },
{ 0, "revert" },
{ 'e', "edit" },
+ { 'r', "reword" },
{ 'f', "fixup" },
{ 's', "squash" },
{ 'x', "exec" },
}
}
- if (is_fixup(command)) {
+ if (command == TODO_REWORD)
+ edit = 1;
+ else if (is_fixup(command)) {
if (update_squash_messages(command, commit, opts))
return -1;
amend = 1;
else if (!is_noop(item->command))
fixup_okay = 1;
}
- if (!todo_list->nr)
- return error(_("no commits parsed."));
+
return res;
}
if (res)
return error(_("unusable instruction sheet: '%s'"), todo_file);
+ if (!todo_list->nr &&
+ (!is_rebase_i(opts) || !file_exists(rebase_path_done())))
+ return error(_("no commits parsed."));
+
if (!is_rebase_i(opts)) {
enum todo_command valid =
opts->action == REPLAY_PICK ? TODO_PICK : TODO_REVERT;
intend_to_amend();
return error_failed_squash(item->commit, opts,
item->arg_len, item->arg);
- }
+ } else if (res && is_rebase_i(opts))
+ return res | error_with_patch(item->commit,
+ item->arg, item->arg_len, opts, res,
+ item->command == TODO_REWORD);
} else if (item->command == TODO_EXEC) {
char *end_of_arg = (char *)(item->arg + item->arg_len);
int saved = *end_of_arg;
}
if (is_rebase_i(opts)) {
- struct strbuf buf = STRBUF_INIT;
+ struct strbuf head_ref = STRBUF_INIT, buf = STRBUF_INIT;
/* Stopped in the middle, as planned? */
if (todo_list->current < todo_list->nr)
return 0;
+ if (read_oneliner(&head_ref, rebase_path_head_name(), 0) &&
+ starts_with(head_ref.buf, "refs/")) {
+ unsigned char head[20], orig[20];
+ int res;
+
+ if (get_sha1("HEAD", head)) {
+ res = error(_("cannot read HEAD"));
+cleanup_head_ref:
+ strbuf_release(&head_ref);
+ strbuf_release(&buf);
+ return res;
+ }
+ if (!read_oneliner(&buf, rebase_path_orig_head(), 0) ||
+ get_sha1_hex(buf.buf, orig)) {
+ res = error(_("could not read orig-head"));
+ goto cleanup_head_ref;
+ }
+ strbuf_addf(&buf, "rebase -i (finish): %s onto ",
+ head_ref.buf);
+ if (!read_oneliner(&buf, rebase_path_onto(), 0)) {
+ res = error(_("could not read 'onto'"));
+ goto cleanup_head_ref;
+ }
+ if (update_ref(buf.buf, head_ref.buf, head, orig,
+ REF_NODEREF, UPDATE_REFS_MSG_ON_ERR)) {
+ res = error(_("could not update %s"),
+ head_ref.buf);
+ goto cleanup_head_ref;
+ }
+ strbuf_reset(&buf);
+ strbuf_addf(&buf,
+ "rebase -i (finish): returning to %s",
+ head_ref.buf);
+ if (create_symref("HEAD", head_ref.buf, buf.buf)) {
+ res = error(_("could not update HEAD to %s"),
+ head_ref.buf);
+ goto cleanup_head_ref;
+ }
+ strbuf_reset(&buf);
+ }
+
if (opts->verbose) {
struct rev_info log_tree_opt;
struct object_id orig, head;
}
}
strbuf_release(&buf);
+ strbuf_release(&head_ref);
}
/*