Code

Merge branch 'jn/gitweb-unspecified-action' into maint-1.7.8
[git.git] / builtin / revert.c
index f7f4bb35774db6445348b41c61dd2c27883d2381..028bcbcd75d21ada2bc0406ff74e3073014bb41f 100644 (file)
@@ -944,7 +944,7 @@ static int sequencer_rollback(struct replay_opts *opts)
        }
        if (reset_for_rollback(sha1))
                goto fail;
-       remove_sequencer_state(1);
+       remove_sequencer_state();
        strbuf_release(&buf);
        return 0;
 fail:
@@ -1018,25 +1018,15 @@ static int pick_commits(struct commit_list *todo_list, struct replay_opts *opts)
        for (cur = todo_list; cur; cur = cur->next) {
                save_todo(cur, opts);
                res = do_pick_commit(cur->item, opts);
-               if (res) {
-                       if (!cur->next)
-                               /*
-                                * An error was encountered while
-                                * picking the last commit; the
-                                * sequencer state is useless now --
-                                * the user simply needs to resolve
-                                * the conflict and commit
-                                */
-                               remove_sequencer_state(0);
+               if (res)
                        return res;
-               }
        }
 
        /*
         * Sequence of picks finished successfully; cleanup by
         * removing the .git/sequencer directory
         */
-       remove_sequencer_state(1);
+       remove_sequencer_state();
        return 0;
 }
 
@@ -1072,6 +1062,12 @@ static int sequencer_continue(struct replay_opts *opts)
        return pick_commits(todo_list, opts);
 }
 
+static int single_pick(struct commit *cmit, struct replay_opts *opts)
+{
+       setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
+       return do_pick_commit(cmit, opts);
+}
+
 static int pick_revisions(struct replay_opts *opts)
 {
        struct commit_list *todo_list = NULL;
@@ -1088,7 +1084,7 @@ static int pick_revisions(struct replay_opts *opts)
         * one that is being continued
         */
        if (opts->subcommand == REPLAY_REMOVE_STATE) {
-               remove_sequencer_state(1);
+               remove_sequencer_state();
                return 0;
        }
        if (opts->subcommand == REPLAY_ROLLBACK)
@@ -1096,6 +1092,26 @@ static int pick_revisions(struct replay_opts *opts)
        if (opts->subcommand == REPLAY_CONTINUE)
                return sequencer_continue(opts);
 
+       /*
+        * If we were called as "git cherry-pick <commit>", just
+        * cherry-pick/revert it, set CHERRY_PICK_HEAD /
+        * REVERT_HEAD, and don't touch the sequencer state.
+        * This means it is possible to cherry-pick in the middle
+        * of a cherry-pick sequence.
+        */
+       if (opts->revs->cmdline.nr == 1 &&
+           opts->revs->cmdline.rev->whence == REV_CMD_REV &&
+           opts->revs->no_walk &&
+           !opts->revs->cmdline.rev->flags) {
+               struct commit *cmit;
+               if (prepare_revision_walk(opts->revs))
+                       die(_("revision walk setup failed"));
+               cmit = get_revision(opts->revs);
+               if (!cmit || get_revision(opts->revs))
+                       die("BUG: expected exactly one commit from walk");
+               return single_pick(cmit, opts);
+       }
+
        /*
         * Start a new cherry-pick/ revert sequence; but
         * first, make sure that an existing one isn't in