Code

revert: allow cherry-pick --continue to commit before resuming
[git.git] / builtin / revert.c
index 0c61668b858671c4817e1445de01812fcc53f92d..a43b4d85fbddb8adb024bc23785894ca4cd20ef5 100644 (file)
@@ -308,7 +308,7 @@ static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
 
        strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1));
 
-       filename = git_path(pseudoref);
+       filename = git_path("%s", pseudoref);
        fd = open(filename, O_WRONLY | O_CREAT, 0666);
        if (fd < 0)
                die_errno(_("Could not open '%s' for writing"), filename);
@@ -931,8 +931,10 @@ static int sequencer_rollback(struct replay_opts *opts)
        if (strbuf_getline(&buf, f, '\n')) {
                error(_("cannot read %s: %s"), filename, ferror(f) ?
                        strerror(errno) : _("unexpected end of file"));
+               fclose(f);
                goto fail;
        }
+       fclose(f);
        if (get_sha1_hex(buf.buf, sha1) || buf.buf[40] != '\0') {
                error(_("stored pre-cherry-pick HEAD file '%s' is corrupt"),
                        filename);
@@ -940,12 +942,11 @@ static int sequencer_rollback(struct replay_opts *opts)
        }
        if (reset_for_rollback(sha1))
                goto fail;
+       remove_sequencer_state(1);
        strbuf_release(&buf);
-       fclose(f);
        return 0;
 fail:
        strbuf_release(&buf);
-       fclose(f);
        return -1;
 }
 
@@ -1037,6 +1038,38 @@ static int pick_commits(struct commit_list *todo_list, struct replay_opts *opts)
        return 0;
 }
 
+static int continue_single_pick(void)
+{
+       const char *argv[] = { "commit", NULL };
+
+       if (!file_exists(git_path("CHERRY_PICK_HEAD")) &&
+           !file_exists(git_path("REVERT_HEAD")))
+               return error(_("no cherry-pick or revert in progress"));
+       return run_command_v_opt(argv, RUN_GIT_CMD);
+}
+
+static int sequencer_continue(struct replay_opts *opts)
+{
+       struct commit_list *todo_list = NULL;
+
+       if (!file_exists(git_path(SEQ_TODO_FILE)))
+               return continue_single_pick();
+       read_populate_opts(&opts);
+       read_populate_todo(&todo_list, opts);
+
+       /* Verify that the conflict has been resolved */
+       if (file_exists(git_path("CHERRY_PICK_HEAD")) ||
+           file_exists(git_path("REVERT_HEAD"))) {
+               int ret = continue_single_pick();
+               if (ret)
+                       return ret;
+       }
+       if (index_differs_from("HEAD", 0))
+               return error_dirty_index(opts);
+       todo_list = todo_list->next;
+       return pick_commits(todo_list, opts);
+}
+
 static int pick_revisions(struct replay_opts *opts)
 {
        struct commit_list *todo_list = NULL;
@@ -1055,17 +1088,8 @@ static int pick_revisions(struct replay_opts *opts)
        }
        if (opts->subcommand == REPLAY_ROLLBACK)
                return sequencer_rollback(opts);
-       if (opts->subcommand == REPLAY_CONTINUE) {
-               if (!file_exists(git_path(SEQ_TODO_FILE)))
-                       return error(_("No %s in progress"), action_name(opts));
-               read_populate_opts(&opts);
-               read_populate_todo(&todo_list, opts);
-
-               /* Verify that the conflict has been resolved */
-               if (!index_differs_from("HEAD", 0))
-                       todo_list = todo_list->next;
-               return pick_commits(todo_list, opts);
-       }
+       if (opts->subcommand == REPLAY_CONTINUE)
+               return sequencer_continue(opts);
 
        /*
         * Start a new cherry-pick/ revert sequence; but