summaryrefslogtreecommitdiff
path: root/sequencer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sequencer.c')
-rw-r--r--sequencer.c91
1 files changed, 61 insertions, 30 deletions
diff --git a/sequencer.c b/sequencer.c
index 1f729b053b..10c3b4ff81 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -602,6 +602,12 @@ N_("you have staged changes in your working tree\n"
"\n"
" git rebase --continue\n");
+#define ALLOW_EMPTY (1<<0)
+#define EDIT_MSG (1<<1)
+#define AMEND_MSG (1<<2)
+#define CLEANUP_MSG (1<<3)
+#define VERIFY_MSG (1<<4)
+
/*
* If we are cherry-pick, and if the merge did not result in
* hand-editing, we will hit this commit and inherit the original
@@ -615,8 +621,7 @@ N_("you have staged changes in your working tree\n"
* author metadata.
*/
static int run_git_commit(const char *defmsg, struct replay_opts *opts,
- int allow_empty, int edit, int amend,
- int cleanup_commit_message)
+ unsigned int flags)
{
struct child_process cmd = CHILD_PROCESS_INIT;
const char *value;
@@ -624,7 +629,7 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
cmd.git_cmd = 1;
if (is_rebase_i(opts)) {
- if (!edit) {
+ if (!(flags & EDIT_MSG)) {
cmd.stdout_to_stderr = 1;
cmd.err = -1;
}
@@ -638,9 +643,10 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
}
argv_array_push(&cmd.args, "commit");
- argv_array_push(&cmd.args, "-n");
- if (amend)
+ if (!(flags & VERIFY_MSG))
+ argv_array_push(&cmd.args, "-n");
+ if ((flags & AMEND_MSG))
argv_array_push(&cmd.args, "--amend");
if (opts->gpg_sign)
argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
@@ -648,16 +654,16 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
argv_array_push(&cmd.args, "-s");
if (defmsg)
argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
- if (cleanup_commit_message)
+ if ((flags & CLEANUP_MSG))
argv_array_push(&cmd.args, "--cleanup=strip");
- if (edit)
+ if ((flags & EDIT_MSG))
argv_array_push(&cmd.args, "-e");
- else if (!cleanup_commit_message &&
+ else if (!(flags & CLEANUP_MSG) &&
!opts->signoff && !opts->record_origin &&
git_config_get_value("commit.cleanup", &value))
argv_array_push(&cmd.args, "--cleanup=verbatim");
- if (allow_empty)
+ if ((flags & ALLOW_EMPTY))
argv_array_push(&cmd.args, "--allow-empty");
if (opts->allow_empty_message)
@@ -926,14 +932,14 @@ static void record_in_rewritten(struct object_id *oid,
static int do_pick_commit(enum todo_command command, struct commit *commit,
struct replay_opts *opts, int final_fixup)
{
- int edit = opts->edit, cleanup_commit_message = 0;
- const char *msg_file = edit ? NULL : git_path_merge_msg();
+ unsigned int flags = opts->edit ? EDIT_MSG : 0;
+ const char *msg_file = opts->edit ? NULL : git_path_merge_msg();
unsigned char head[20];
struct commit *base, *next, *parent;
const char *base_label, *next_label;
struct commit_message msg = { NULL, NULL, NULL, NULL };
struct strbuf msgbuf = STRBUF_INIT;
- int res, unborn = 0, amend = 0, allow = 0;
+ int res, unborn = 0, allow;
if (opts->no_commit) {
/*
@@ -991,7 +997,9 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
opts);
if (res || command != TODO_REWORD)
goto leave;
- edit = amend = 1;
+ flags |= EDIT_MSG | AMEND_MSG;
+ if (command == TODO_REWORD)
+ flags |= VERIFY_MSG;
msg_file = NULL;
goto fast_forward_edit;
}
@@ -1046,25 +1054,25 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
}
if (command == TODO_REWORD)
- edit = 1;
+ flags |= EDIT_MSG | VERIFY_MSG;
else if (is_fixup(command)) {
if (update_squash_messages(command, commit, opts))
return -1;
- amend = 1;
+ flags |= AMEND_MSG;
if (!final_fixup)
msg_file = rebase_path_squash_msg();
else if (file_exists(rebase_path_fixup_msg())) {
- cleanup_commit_message = 1;
+ flags |= CLEANUP_MSG;
msg_file = rebase_path_fixup_msg();
} else {
- const char *dest = git_path("SQUASH_MSG");
+ const char *dest = git_path_squash_msg();
unlink(dest);
if (copy_file(dest, rebase_path_squash_msg(), 0666))
return error(_("could not rename '%s' to '%s'"),
rebase_path_squash_msg(), dest);
- unlink(git_path("MERGE_MSG"));
+ unlink(git_path_merge_msg());
msg_file = dest;
- edit = 1;
+ flags |= EDIT_MSG;
}
}
@@ -1123,11 +1131,11 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
if (allow < 0) {
res = allow;
goto leave;
- }
+ } else if (allow)
+ flags |= ALLOW_EMPTY;
if (!opts->no_commit)
fast_forward_edit:
- res = run_git_commit(msg_file, opts, allow, edit, amend,
- cleanup_commit_message);
+ res = run_git_commit(msg_file, opts, flags);
if (!res && final_fixup) {
unlink(rebase_path_fixup_msg());
@@ -1192,6 +1200,7 @@ struct todo_list {
struct todo_item *items;
int nr, alloc, current;
int done_nr, total_nr;
+ struct stat_data stat;
};
#define TODO_LIST_INIT { STRBUF_INIT }
@@ -1322,6 +1331,7 @@ static int count_commands(struct todo_list *todo_list)
static int read_populate_todo(struct todo_list *todo_list,
struct replay_opts *opts)
{
+ struct stat st;
const char *todo_file = get_todo_path(opts);
int fd, res;
@@ -1335,6 +1345,11 @@ static int read_populate_todo(struct todo_list *todo_list,
}
close(fd);
+ res = stat(todo_file, &st);
+ if (res)
+ return error(_("could not stat '%s'"), todo_file);
+ fill_stat_data(&todo_list->stat, &st);
+
res = parse_insn_buffer(todo_list->buf.buf, todo_list);
if (res) {
if (is_rebase_i(opts))
@@ -1812,10 +1827,10 @@ static int error_failed_squash(struct commit *commit,
return error(_("could not rename '%s' to '%s'"),
rebase_path_squash_msg(), rebase_path_message());
unlink(rebase_path_fixup_msg());
- unlink(git_path("MERGE_MSG"));
- if (copy_file(git_path("MERGE_MSG"), rebase_path_message(), 0666))
+ unlink(git_path_merge_msg());
+ if (copy_file(git_path_merge_msg(), rebase_path_message(), 0666))
return error(_("could not copy '%s' to '%s'"),
- rebase_path_message(), git_path("MERGE_MSG"));
+ rebase_path_message(), git_path_merge_msg());
return error_with_patch(commit, subject, subject_len, opts, 1, 0);
}
@@ -1997,7 +2012,8 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
if (item->command == TODO_EDIT) {
struct commit *commit = item->commit;
if (!res)
- warning(_("stopped at %s... %.*s"),
+ fprintf(stderr,
+ _("Stopped at %s... %.*s\n"),
short_commit_name(commit),
item->arg_len, item->arg);
return error_with_patch(commit,
@@ -2019,10 +2035,25 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
} else if (item->command == TODO_EXEC) {
char *end_of_arg = (char *)(item->arg + item->arg_len);
int saved = *end_of_arg;
+ struct stat st;
*end_of_arg = '\0';
res = do_exec(item->arg);
*end_of_arg = saved;
+
+ /* Reread the todo file if it has changed. */
+ if (res)
+ ; /* fall through */
+ else if (stat(get_todo_path(opts), &st))
+ res = error_errno(_("could not stat '%s'"),
+ get_todo_path(opts));
+ else if (match_stat_data(&todo_list->stat, &st)) {
+ todo_list_release(todo_list);
+ if (read_populate_todo(todo_list, opts))
+ res = -1; /* message was printed */
+ /* `current` will be incremented below */
+ todo_list->current = -1;
+ }
} else if (!is_noop(item->command))
return error(_("unknown command %d"), item->command);
@@ -2153,12 +2184,12 @@ static int continue_single_pick(void)
static int commit_staged_changes(struct replay_opts *opts)
{
- int amend = 0;
+ unsigned int flags = ALLOW_EMPTY | EDIT_MSG;
if (has_unstaged_changes(1))
return error(_("cannot rebase: You have unstaged changes."));
if (!has_uncommitted_changes(0)) {
- const char *cherry_pick_head = git_path("CHERRY_PICK_HEAD");
+ const char *cherry_pick_head = git_path_cherry_pick_head();
if (file_exists(cherry_pick_head) && unlink(cherry_pick_head))
return error(_("could not remove CHERRY_PICK_HEAD"));
@@ -2183,10 +2214,10 @@ static int commit_staged_changes(struct replay_opts *opts)
"--continue' again."));
strbuf_release(&rev);
- amend = 1;
+ flags |= AMEND_MSG;
}
- if (run_git_commit(rebase_path_message(), opts, 1, 1, amend, 0))
+ if (run_git_commit(rebase_path_message(), opts, flags))
return error(_("could not commit staged changes."));
unlink(rebase_path_amend());
return 0;