Subject: [PATCH 01/18] builtin rebase: allow selecting the rebase "backend"

From: Pratik Karki <[email-masked]>
Date: Wed, 8 Aug 2018 21:06:23 +0545

With this commit the builtin rebase supports selecting the "rebase
backends" (or "type") `interactive`, `preserve-merges`, and `merge`.

The `state_dir` was already handled according to the rebase type in a
previous commit.

Note that there is one quirk in the shell script: `--interactive`
followed by `--merge` won't reset the type to "merge" but keeps the type
as "interactive". And as t3418 tests this explicitly, we have to support
it in the builtin rebase, too.

Likewise, `--interactive` followed by `--preserve-merges` makes it an
"explicitly interactive" rebase, i.e. a rebase that should show the todo
list, while `--preserve-merges` alone is not interactive (and t5520
tests for this via `git pull --rebase=preserve`).

Signed-off-by: Pratik Karki <[email-masked]>
---
 builtin/rebase.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 75c4ac66e0..fc9b5a8a60 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -452,6 +452,29 @@ static int can_fast_forward(struct commit *onto, struct object_id *head_oid,
 	return res && is_linear_history(onto, head);
 }
 
+/* -i followed by -m is still -i */
+static int parse_opt_merge(const struct option *opt, const char *arg, int unset)
+{
+	struct rebase_options *opts = opt->value;
+
+	if (!is_interactive(opts))
+		opts->type = REBASE_MERGE;
+
+	return 0;
+}
+
+/* -i followed by -p is still explicitly interactive, but -p alone is not */
+static int parse_opt_interactive(const struct option *opt, const char *arg,
+				 int unset)
+{
+	struct rebase_options *opts = opt->value;
+
+	opts->type = REBASE_INTERACTIVE;
+	opts->flags |= REBASE_INTERACTIVE_EXPLICIT;
+
+	return 0;
+}
+
 int cmd_rebase(int argc, const char **argv, const char *prefix)
 {
 	struct rebase_options options = {
@@ -510,6 +533,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_CMDMODE(0, "show-current-patch", &action,
 			    N_("show the patch file being applied or merged"),
 			    ACTION_SHOW_CURRENT_PATCH),
+		{ OPTION_CALLBACK, 'm', "merge", &options, NULL,
+			N_("use merging strategies to rebase"),
+			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+			parse_opt_merge },
+		{ OPTION_CALLBACK, 'i', "interactive", &options, NULL,
+			N_("let the user edit the list of commits to rebase"),
+			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+			parse_opt_interactive },
+		OPT_SET_INT('p', "preserve-merges", &options.type,
+			    N_("try to recreate merges instead of ignoring "
+			       "them"), REBASE_PRESERVE_MERGES),
 		OPT_END(),
 	};
 
@@ -884,6 +918,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		diff_flush(&opts);
 	}
 
+	if (is_interactive(&options))
+		goto run_rebase;
+
 	/* Detach HEAD and reset the tree */
 	if (options.flags & REBASE_NO_QUIET)
 		printf(_("First, rewinding head to replay your work on top of "
-- 
2.18.0