Merge branch 'ra/cherry-pick-revert-skip'
[git/git.git] / sequencer.c
index 7d0e5f9..66126e0 100644 (file)
@@ -279,7 +279,7 @@ static const char *gpg_sign_opt_quoted(struct replay_opts *opts)
 int sequencer_remove_state(struct replay_opts *opts)
 {
        struct strbuf buf = STRBUF_INIT;
-       int i;
+       int i, ret = 0;
 
        if (is_rebase_i(opts) &&
            strbuf_read_file(&buf, rebase_path_refs_to_delete(), 0) > 0) {
@@ -288,8 +288,10 @@ int sequencer_remove_state(struct replay_opts *opts)
                        char *eol = strchr(p, '\n');
                        if (eol)
                                *eol = '\0';
-                       if (delete_ref("(rebase -i) cleanup", p, NULL, 0) < 0)
+                       if (delete_ref("(rebase -i) cleanup", p, NULL, 0) < 0) {
                                warning(_("could not delete '%s'"), p);
+                               ret = -1;
+                       }
                        if (!eol)
                                break;
                        p = eol + 1;
@@ -305,10 +307,11 @@ int sequencer_remove_state(struct replay_opts *opts)
 
        strbuf_reset(&buf);
        strbuf_addstr(&buf, get_dir(opts));
-       remove_dir_recursively(&buf, 0);
+       if (remove_dir_recursively(&buf, 0))
+               ret = error(_("could not remove '%s'"), buf.buf);
        strbuf_release(&buf);
 
-       return 0;
+       return ret;
 }
 
 static const char *action_name(const struct replay_opts *opts)
@@ -2076,6 +2079,18 @@ const char *todo_item_get_arg(struct todo_list *todo_list,
        return todo_list->buf.buf + item->arg_offset;
 }
 
+static int is_command(enum todo_command command, const char **bol)
+{
+       const char *str = todo_command_info[command].str;
+       const char nick = todo_command_info[command].c;
+       const char *p = *bol + 1;
+
+       return skip_prefix(*bol, str, bol) ||
+               ((nick && **bol == nick) &&
+                (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || !*p) &&
+                (*bol = p));
+}
+
 static int parse_insn_line(struct repository *r, struct todo_item *item,
                           const char *buf, const char *bol, char *eol)
 {
@@ -2097,12 +2112,7 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
        }
 
        for (i = 0; i < TODO_COMMENT; i++)
-               if (skip_prefix(bol, todo_command_info[i].str, &bol)) {
-                       item->command = i;
-                       break;
-               } else if ((bol + 1 == eol || bol[1] == ' ') &&
-                          *bol == todo_command_info[i].c) {
-                       bol++;
+               if (is_command(i, &bol)) {
                        item->command = i;
                        break;
                }
@@ -2170,34 +2180,26 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
 
 int sequencer_get_last_command(struct repository *r, enum replay_action *action)
 {
-       struct todo_item item;
-       char *eol;
-       const char *todo_file;
+       const char *todo_file, *bol;
        struct strbuf buf = STRBUF_INIT;
-       int ret = -1;
+       int ret = 0;
 
        todo_file = git_path_todo_file();
        if (strbuf_read_file(&buf, todo_file, 0) < 0) {
-               if (errno == ENOENT)
+               if (errno == ENOENT || errno == ENOTDIR)
                        return -1;
                else
                        return error_errno("unable to open '%s'", todo_file);
        }
-       eol = strchrnul(buf.buf, '\n');
-       if (buf.buf != eol && eol[-1] == '\r')
-               eol--; /* strip Carriage Return */
-       if (parse_insn_line(r, &item, buf.buf, buf.buf, eol))
-               goto fail;
-       if (item.command == TODO_PICK)
+       bol = buf.buf + strspn(buf.buf, " \t\r\n");
+       if (is_command(TODO_PICK, &bol) && (*bol == ' ' || *bol == '\t'))
                *action = REPLAY_PICK;
-       else if (item.command == TODO_REVERT)
+       else if (is_command(TODO_REVERT, &bol) &&
+                (*bol == ' ' || *bol == '\t'))
                *action = REPLAY_REVERT;
        else
-               goto fail;
-
-       ret = 0;
+               ret = -1;
 
- fail:
        strbuf_release(&buf);
 
        return ret;
@@ -2311,19 +2313,21 @@ static int have_finished_the_last_pick(void)
        return ret;
 }
 
-void sequencer_post_commit_cleanup(struct repository *r)
+void sequencer_post_commit_cleanup(struct repository *r, int verbose)
 {
        struct replay_opts opts = REPLAY_OPTS_INIT;
        int need_cleanup = 0;
 
        if (file_exists(git_path_cherry_pick_head(r))) {
-               unlink(git_path_cherry_pick_head(r));
+               if (!unlink(git_path_cherry_pick_head(r)) && verbose)
+                       warning(_("cancelling a cherry picking in progress"));
                opts.action = REPLAY_PICK;
                need_cleanup = 1;
        }
 
        if (file_exists(git_path_revert_head(r))) {
-               unlink(git_path_revert_head(r));
+               if (!unlink(git_path_revert_head(r)) && verbose)
+                       warning(_("cancelling a revert in progress"));
                opts.action = REPLAY_REVERT;
                need_cleanup = 1;
        }
@@ -3840,8 +3844,11 @@ static int pick_commits(struct repository *r,
                        unlink(git_path_merge_head(the_repository));
                        delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
 
-                       if (item->command == TODO_BREAK)
+                       if (item->command == TODO_BREAK) {
+                               if (!opts->verbose)
+                                       term_clear_line();
                                return stopped_at_head(r);
+                       }
                }
                if (item->command <= TODO_SQUASH) {
                        if (is_rebase_i(opts))
@@ -3863,11 +3870,14 @@ static int pick_commits(struct repository *r,
                        }
                        if (item->command == TODO_EDIT) {
                                struct commit *commit = item->commit;
-                               if (!res)
+                               if (!res) {
+                                       if (!opts->verbose)
+                                               term_clear_line();
                                        fprintf(stderr,
                                                _("Stopped at %s...  %.*s\n"),
                                                short_commit_name(commit),
                                                item->arg_len, arg);
+                               }
                                return error_with_patch(r, commit,
                                        arg, item->arg_len, opts, res, !res);
                        }
@@ -3905,6 +3915,8 @@ static int pick_commits(struct repository *r,
                        int saved = *end_of_arg;
                        struct stat st;
 
+                       if (!opts->verbose)
+                               term_clear_line();
                        *end_of_arg = '\0';
                        res = do_exec(r, arg);
                        *end_of_arg = saved;
@@ -4063,10 +4075,13 @@ cleanup_head_ref:
                }
                apply_autostash(opts);
 
-               if (!opts->quiet)
+               if (!opts->quiet) {
+                       if (!opts->verbose)
+                               term_clear_line();
                        fprintf(stderr,
                                "Successfully rebased and updated %s.\n",
                                head_ref.buf);
+               }
 
                strbuf_release(&buf);
                strbuf_release(&head_ref);