From: Phillip Wood <phillip.w...@dunelm.org.uk>

When the builtin rebase starts an interactive rebase it parses the
options and then repackages them and forks
`rebase--interactive`. Separate the option parsing in
cmd_rebase__interactive() from the business logic to allow interactive
rebases can be run without forking `rebase__interactive` by calling
run_rebase_interactive() directly. This makes it easy to debug the
sequencer without worrying about attaching to child processes. It also
makes it easy to remove cmd_rebase__interactive() in the future when
git-legacy-rebase.sh and git-rebase--preserve-merges.sh are retired.

Signed-off-by: Phillip Wood <phillip.w...@dunelm.org.uk>
---
 builtin/rebase.c | 221 ++++++++++++++++++-----------------------------
 1 file changed, 86 insertions(+), 135 deletions(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 26d25a5242..2e26d350f0 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -317,7 +317,9 @@ static int do_interactive_rebase(struct rebase_options 
*opts, unsigned flags)
                                &revisions, &shortrevisions))
                return -1;
 
-       if (init_basic_state(&replay, opts->head_name, opts->onto, head_hash)) {
+       if (init_basic_state(&replay,
+                            opts->head_name ? opts->head_name : "detached 
HEAD",
+                            opts->onto, head_hash)) {
                free(revisions);
                free(shortrevisions);
 
@@ -360,6 +362,77 @@ static int do_interactive_rebase(struct rebase_options 
*opts, unsigned flags)
        return ret;
 }
 
+static int run_rebase_interactive(struct rebase_options *opts,
+                                 enum action command)
+{
+       unsigned flags = 0;
+       int abbreviate_commands = 0, ret = 0;
+
+       git_config_get_bool("rebase.abbreviatecommands", &abbreviate_commands);
+
+       flags |= opts->keep_empty ? TODO_LIST_KEEP_EMPTY : 0;
+       flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
+       flags |= opts->rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
+       flags |= opts->rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
+       flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
+
+       switch (command) {
+       case ACTION_NONE: {
+               if (!opts->onto && !opts->upstream)
+                       die(_("a base commit must be provided with --upstream 
or --onto"));
+
+               ret = do_interactive_rebase(opts, flags);
+               break;
+       }
+       case ACTION_SKIP: {
+               struct string_list merge_rr = STRING_LIST_INIT_DUP;
+
+               rerere_clear(the_repository, &merge_rr);
+       }
+               /* fallthrough */
+       case ACTION_CONTINUE: {
+               struct replay_opts replay_opts = get_replay_opts(opts);
+
+               ret = sequencer_continue(the_repository, &replay_opts);
+               break;
+       }
+       case ACTION_EDIT_TODO:
+               ret = edit_todo_file(flags);
+               break;
+       case ACTION_SHOW_CURRENT_PATCH: {
+               struct child_process cmd = CHILD_PROCESS_INIT;
+
+               cmd.git_cmd = 1;
+               argv_array_pushl(&cmd.args, "show", "REBASE_HEAD", "--", NULL);
+               ret = run_command(&cmd);
+
+               break;
+       }
+       case ACTION_SHORTEN_OIDS:
+       case ACTION_EXPAND_OIDS:
+               ret = transform_todo_file(flags);
+               break;
+       case ACTION_CHECK_TODO_LIST:
+               ret = check_todo_list_from_file(the_repository);
+               break;
+       case ACTION_REARRANGE_SQUASH:
+               ret = rearrange_squash_in_todo_file();
+               break;
+       case ACTION_ADD_EXEC: {
+               struct string_list commands = STRING_LIST_INIT_DUP;
+
+               split_exec_commands(opts->cmd, &commands);
+               ret = add_exec_commands(&commands);
+               string_list_clear(&commands, 0);
+               break;
+       }
+       default:
+               BUG("invalid command '%d'", command);
+       }
+
+       return ret;
+}
+
 static const char * const builtin_rebase_interactive_usage[] = {
        N_("git rebase--interactive [<options>]"),
        NULL
@@ -368,8 +441,6 @@ static const char * const 
builtin_rebase_interactive_usage[] = {
 int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 {
        struct rebase_options opts = REBASE_OPTIONS_INIT;
-       unsigned flags = 0;
-       int abbreviate_commands = 0, ret = 0;
        struct object_id squash_onto = null_oid;
        enum action command = ACTION_NONE;
        struct option options[] = {
@@ -434,8 +505,6 @@ int cmd_rebase__interactive(int argc, const char **argv, 
const char *prefix)
 
        opts.rebase_cousins = -1;
 
-       git_config_get_bool("rebase.abbreviatecommands", &abbreviate_commands);
-
        if (argc == 1)
                usage_with_options(builtin_rebase_interactive_usage, options);
 
@@ -445,71 +514,11 @@ int cmd_rebase__interactive(int argc, const char **argv, 
const char *prefix)
        if (!is_null_oid(&squash_onto))
                opts.squash_onto = &squash_onto;
 
-       flags |= opts.keep_empty ? TODO_LIST_KEEP_EMPTY : 0;
-       flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
-       flags |= opts.rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
-       flags |= opts.rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
-       flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
-
        if (opts.rebase_cousins >= 0 && !opts.rebase_merges)
                warning(_("--[no-]rebase-cousins has no effect without "
                          "--rebase-merges"));
 
-       switch (command) {
-       case ACTION_NONE: {
-               if (!opts.onto && !opts.upstream)
-                       die(_("a base commit must be provided with --upstream 
or --onto"));
-
-               ret = do_interactive_rebase(&opts, flags);
-               break;
-       }
-       case ACTION_SKIP: {
-               struct string_list merge_rr = STRING_LIST_INIT_DUP;
-
-               rerere_clear(the_repository, &merge_rr);
-       }
-               /* fallthrough */
-       case ACTION_CONTINUE: {
-               struct replay_opts replay_opts = get_replay_opts(&opts);
-
-               ret = sequencer_continue(the_repository, &replay_opts);
-               break;
-       }
-       case ACTION_EDIT_TODO:
-               ret = edit_todo_file(flags);
-               break;
-       case ACTION_SHOW_CURRENT_PATCH: {
-               struct child_process cmd = CHILD_PROCESS_INIT;
-
-               cmd.git_cmd = 1;
-               argv_array_pushl(&cmd.args, "show", "REBASE_HEAD", "--", NULL);
-               ret = run_command(&cmd);
-
-               break;
-       }
-       case ACTION_SHORTEN_OIDS:
-       case ACTION_EXPAND_OIDS:
-               ret = transform_todo_file(flags);
-               break;
-       case ACTION_CHECK_TODO_LIST:
-               ret = check_todo_list_from_file(the_repository);
-               break;
-       case ACTION_REARRANGE_SQUASH:
-               ret = rearrange_squash_in_todo_file();
-               break;
-       case ACTION_ADD_EXEC: {
-               struct string_list commands = STRING_LIST_INIT_DUP;
-
-               split_exec_commands(opts.cmd, &commands);
-               ret = add_exec_commands(&commands);
-               string_list_clear(&commands, 0);
-               break;
-       }
-       default:
-               BUG("invalid command '%d'", command);
-       }
-
-       return !!ret;
+       return !!run_rebase_interactive(&opts, command);
 }
 
 static int use_builtin_rebase(void)
@@ -1072,7 +1081,7 @@ static int run_am(struct rebase_options *opts)
        return status;
 }
 
-static int run_specific_rebase(struct rebase_options *opts)
+static int run_specific_rebase(struct rebase_options *opts, enum action action)
 {
        const char *argv[] = { NULL, NULL };
        struct strbuf script_snippet = STRBUF_INIT, buf = STRBUF_INIT;
@@ -1081,77 +1090,19 @@ static int run_specific_rebase(struct rebase_options 
*opts)
 
        if (opts->type == REBASE_INTERACTIVE) {
                /* Run builtin interactive rebase */
-               struct child_process child = CHILD_PROCESS_INIT;
-
-               argv_array_pushf(&child.env_array, "GIT_CHERRY_PICK_HELP=%s",
-                                resolvemsg);
+               setenv("GIT_CHERRY_PICK_HELP", resolvemsg, 1);
                if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
-                       argv_array_push(&child.env_array,
-                                       "GIT_SEQUENCE_EDITOR=:");
+                       setenv("GIT_SEQUENCE_EDITOR", ":", 1);
                        opts->autosquash = 0;
                }
+               if (opts->gpg_sign_opt) {
+                       /* remove the leading "-S" */
+                       char *tmp = xstrdup(opts->gpg_sign_opt + 2);
+                       free(opts->gpg_sign_opt);
+                       opts->gpg_sign_opt = tmp;
+               }
 
-               child.git_cmd = 1;
-               argv_array_push(&child.args, "rebase--interactive");
-
-               if (opts->action)
-                       argv_array_pushf(&child.args, "--%s", opts->action);
-               if (opts->keep_empty)
-                       argv_array_push(&child.args, "--keep-empty");
-               if (opts->rebase_merges)
-                       argv_array_push(&child.args, "--rebase-merges");
-               if (opts->rebase_cousins)
-                       argv_array_push(&child.args, "--rebase-cousins");
-               if (opts->autosquash)
-                       argv_array_push(&child.args, "--autosquash");
-               if (opts->flags & REBASE_VERBOSE)
-                       argv_array_push(&child.args, "--verbose");
-               if (opts->flags & REBASE_FORCE)
-                       argv_array_push(&child.args, "--no-ff");
-               if (opts->restrict_revision)
-                       argv_array_pushf(&child.args,
-                                        "--restrict-revision=^%s",
-                                        
oid_to_hex(&opts->restrict_revision->object.oid));
-               if (opts->upstream)
-                       argv_array_pushf(&child.args, "--upstream=%s",
-                                        
oid_to_hex(&opts->upstream->object.oid));
-               if (opts->onto)
-                       argv_array_pushf(&child.args, "--onto=%s",
-                                        oid_to_hex(&opts->onto->object.oid));
-               if (opts->squash_onto)
-                       argv_array_pushf(&child.args, "--squash-onto=%s",
-                                        oid_to_hex(opts->squash_onto));
-               if (opts->onto_name)
-                       argv_array_pushf(&child.args, "--onto-name=%s",
-                                        opts->onto_name);
-               argv_array_pushf(&child.args, "--head-name=%s",
-                                opts->head_name ?
-                                opts->head_name : "detached HEAD");
-               if (opts->strategy)
-                       argv_array_pushf(&child.args, "--strategy=%s",
-                                        opts->strategy);
-               if (opts->strategy_opts)
-                       argv_array_pushf(&child.args, "--strategy-opts=%s",
-                                        opts->strategy_opts);
-               if (opts->switch_to)
-                       argv_array_pushf(&child.args, "--switch-to=%s",
-                                        opts->switch_to);
-               if (opts->cmd)
-                       argv_array_pushf(&child.args, "--cmd=%s", opts->cmd);
-               if (opts->allow_empty_message)
-                       argv_array_push(&child.args, "--allow-empty-message");
-               if (opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE)
-                       argv_array_push(&child.args, "--rerere-autoupdate");
-               else if (opts->allow_rerere_autoupdate == RERERE_NOAUTOUPDATE)
-                       argv_array_push(&child.args, "--no-rerere-autoupdate");
-               if (opts->gpg_sign_opt)
-                       argv_array_push(&child.args, opts->gpg_sign_opt);
-               if (opts->signoff)
-                       argv_array_push(&child.args, "--signoff");
-               if (opts->reschedule_failed_exec)
-                       argv_array_push(&child.args, 
"--reschedule-failed-exec");
-
-               status = run_command(&child);
+               status = run_rebase_interactive(opts, action);
                goto finished_rebase;
        }
 
@@ -2212,7 +2163,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
        options.revisions = revisions.buf;
 
 run_rebase:
-       ret = !!run_specific_rebase(&options);
+       ret = !!run_specific_rebase(&options, action);
 
 cleanup:
        strbuf_release(&revisions);
-- 
2.21.0

Reply via email to