When running a rebase in non-am mode, it uses the recursive merge to
cherry-pick the commits, and the rebase command allows to configure
the merge strategy to be used in this operation.

This commit adds that support to the builtin rebase.

Signed-off-by: Pratik Karki <predatoram...@gmail.com>
---
 builtin/rebase.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 72e64868b2..65e7be1c48 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -96,6 +96,7 @@ struct rebase_options {
        char *cmd;
        int allow_empty_message;
        int rebase_merges, rebase_cousins;
+       char *strategy, *strategy_opts;
 };
 
 static int is_interactive(struct rebase_options *opts)
@@ -217,6 +218,22 @@ static int read_basic_state(struct rebase_options *opts)
                opts->gpg_sign_opt = xstrdup(buf.buf);
        }
 
+       if (file_exists(state_dir_path("strategy", opts))) {
+               strbuf_reset(&buf);
+               if (read_one(state_dir_path("strategy", opts), &buf))
+                       return -1;
+               free(opts->strategy);
+               opts->strategy = xstrdup(buf.buf);
+       }
+
+       if (file_exists(state_dir_path("strategy_opts", opts))) {
+               strbuf_reset(&buf);
+               if (read_one(state_dir_path("strategy_opts", opts), &buf))
+                       return -1;
+               free(opts->strategy_opts);
+               opts->strategy_opts = xstrdup(buf.buf);
+       }
+
        strbuf_release(&buf);
 
        return 0;
@@ -356,6 +373,8 @@ static int run_specific_rebase(struct rebase_options *opts)
                opts->rebase_merges ? "t" : "");
        add_var(&script_snippet, "rebase_cousins",
                opts->rebase_cousins ? "t" : "");
+       add_var(&script_snippet, "strategy", opts->strategy);
+       add_var(&script_snippet, "strategy_opts", opts->strategy_opts);
 
        switch (opts->type) {
        case REBASE_AM:
@@ -633,6 +652,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
        struct string_list exec = STRING_LIST_INIT_NODUP;
        const char *rebase_merges = NULL;
        int fork_point = -1;
+       struct string_list strategy_options = STRING_LIST_INIT_NODUP;
        struct option builtin_rebase_options[] = {
                OPT_STRING(0, "onto", &options.onto_name,
                           N_("revision"),
@@ -717,6 +737,12 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
                        PARSE_OPT_OPTARG, NULL, (intptr_t)""},
                OPT_BOOL(0, "fork-point", &fork_point,
                         N_("use 'merge-base --fork-point' to refine 
upstream")),
+               OPT_STRING('s', "strategy", &options.strategy,
+                          N_("strategy"), N_("use the given merge strategy")),
+               OPT_STRING_LIST('X', "strategy-option", &strategy_options,
+                               N_("option"),
+                               N_("pass the argument through to the merge "
+                                  "strategy")),
                OPT_END(),
        };
 
@@ -963,6 +989,37 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
                imply_interactive(&options, "--rebase-merges");
        }
 
+       if (strategy_options.nr) {
+               int i;
+
+               if (!options.strategy)
+                       options.strategy = "recursive";
+
+               strbuf_reset(&buf);
+               for (i = 0; i < strategy_options.nr; i++)
+                       strbuf_addf(&buf, " --%s",
+                                   strategy_options.items[i].string);
+               options.strategy_opts = xstrdup(buf.buf);
+       }
+
+       if (options.strategy) {
+               options.strategy = xstrdup(options.strategy);
+               switch (options.type) {
+               case REBASE_AM:
+                       die(_("--strategy requires --merge or --interactive"));
+               case REBASE_MERGE:
+               case REBASE_INTERACTIVE:
+               case REBASE_PRESERVE_MERGES:
+                       /* compatible */
+                       break;
+               case REBASE_UNSPECIFIED:
+                       options.type = REBASE_MERGE;
+                       break;
+               default:
+                       BUG("unhandled rebase type (%d)", options.type);
+               }
+       }
+
        switch (options.type) {
        case REBASE_MERGE:
        case REBASE_INTERACTIVE:
-- 
2.18.0

Reply via email to