git@vger.kernel.org list mirror (unofficial, one of many)
 help / color / Atom feed
From: Phillip Wood <phillip.wood123@gmail.com>
To: Git Mailing List <git@vger.kernel.org>
Cc: Johannes Schindelin <Johannes.Schindelin@gmx.de>,
	Junio C Hamano <gitster@pobox.com>,
	Elijah Newren <newren@gmail.com>, Duy Nguyen <pclouds@gmail.com>,
	Alban Gruin <alban.gruin@gmail.com>,
	Josh Steadmon <steadmon@google.com>,
	Ævar Arnfjörð Bjarmason  <avarab@gmail.com>,
	Phillip Wood <phillip.wood@dunelm.org.uk>
Subject: [PATCH v1 09/12] rebase -i: use struct rebase_options to parse args
Date: Wed, 17 Apr 2019 15:30:41 +0100
Message-ID: <20190417143044.17655-10-phillip.wood123@gmail.com> (raw)
In-Reply-To: <20190417143044.17655-1-phillip.wood123@gmail.com>

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

In order to run `rebase -i` without forking `rebase--interactive` it
will be convenient to use the same structure when parsing the options in
cmd_rebase() and cmd_rebase__interactive().

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 builtin/rebase.c | 203 ++++++++++++++++++++++++++---------------------
 1 file changed, 112 insertions(+), 91 deletions(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 3b9da69473..aa97d81ab8 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -50,6 +50,73 @@ enum rebase_type {
 	REBASE_PRESERVE_MERGES
 };
 
+struct rebase_options {
+	enum rebase_type type;
+	const char *state_dir;
+	struct commit *upstream;
+	const char *upstream_name;
+	const char *upstream_arg;
+	char *head_name;
+	struct object_id orig_head;
+	struct commit *onto;
+	const char *onto_name;
+	const char *revisions;
+	const char *switch_to;
+	int root;
+	struct object_id *squash_onto;
+	struct commit *restrict_revision;
+	int dont_finish_rebase;
+	enum {
+		REBASE_NO_QUIET = 1<<0,
+		REBASE_VERBOSE = 1<<1,
+		REBASE_DIFFSTAT = 1<<2,
+		REBASE_FORCE = 1<<3,
+		REBASE_INTERACTIVE_EXPLICIT = 1<<4,
+	} flags;
+	struct argv_array git_am_opts;
+	const char *action;
+	int signoff;
+	int allow_rerere_autoupdate;
+	int keep_empty;
+	int autosquash;
+	char *gpg_sign_opt;
+	int autostash;
+	char *cmd;
+	int allow_empty_message;
+	int rebase_merges, rebase_cousins;
+	char *strategy, *strategy_opts;
+	struct strbuf git_format_patch_opt;
+	int reschedule_failed_exec;
+};
+
+#define REBASE_OPTIONS_INIT {			  	\
+		.type = REBASE_UNSPECIFIED,	  	\
+		.flags = REBASE_NO_QUIET, 		\
+		.git_am_opts = ARGV_ARRAY_INIT,		\
+		.git_format_patch_opt = STRBUF_INIT	\
+	}
+
+static struct replay_opts get_replay_opts(const struct rebase_options *opts)
+{
+	struct replay_opts replay = REPLAY_OPTS_INIT;
+
+	replay.action = REPLAY_INTERACTIVE_REBASE;
+	sequencer_init_config(&replay);
+
+	replay.signoff = opts->signoff;
+	replay.allow_ff = !(opts->flags & REBASE_FORCE);
+	if (opts->allow_rerere_autoupdate)
+		replay.allow_rerere_auto = opts->allow_rerere_autoupdate;
+	replay.allow_empty = 1;
+	replay.allow_empty_message = opts->allow_empty_message;
+	replay.verbose = opts->flags & REBASE_VERBOSE;
+	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
+	replay.strategy = opts->strategy;
+
+	return replay;
+}
+
 static int add_exec_commands(struct string_list *commands)
 {
 	const char *todo_file = rebase_path_todo();
@@ -265,32 +332,30 @@ static const char * const builtin_rebase_interactive_usage[] = {
 
 int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 {
-	struct replay_opts opts = REPLAY_OPTS_INIT;
-	unsigned flags = 0, keep_empty = 0, rebase_merges = 0, autosquash = 0;
-	int abbreviate_commands = 0, rebase_cousins = -1, ret = 0;
-	const char *onto_name = NULL, *head_name = NULL, *switch_to = NULL,
-		*cmd = NULL;
-	struct commit *onto = NULL, *upstream = NULL, *restrict_revision = NULL;
+	struct rebase_options opts = REBASE_OPTIONS_INIT;
+	unsigned flags = 0;
+	int abbreviate_commands = 0, ret = 0;
 	struct object_id squash_onto = null_oid;
-	struct object_id *squash_onto_opt = NULL;
 	struct string_list commands = STRING_LIST_INIT_DUP;
-	char *raw_strategies = NULL;
 	enum {
 		NONE = 0, CONTINUE, SKIP, EDIT_TODO, SHOW_CURRENT_PATCH,
 		SHORTEN_OIDS, EXPAND_OIDS, CHECK_TODO_LIST, REARRANGE_SQUASH, ADD_EXEC
 	} command = 0;
 	struct option options[] = {
-		OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")),
-		OPT_BOOL(0, "keep-empty", &keep_empty, N_("keep empty commits")),
+		OPT_NEGBIT(0, "ff", &opts.flags, N_("allow fast-forward"),
+			   REBASE_FORCE),
+		OPT_BOOL(0, "keep-empty", &opts.keep_empty, N_("keep empty commits")),
 		OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message,
 			 N_("allow commits with empty messages")),
-		OPT_BOOL(0, "rebase-merges", &rebase_merges, N_("rebase merge commits")),
-		OPT_BOOL(0, "rebase-cousins", &rebase_cousins,
+		OPT_BOOL(0, "rebase-merges", &opts.rebase_merges, N_("rebase merge commits")),
+		OPT_BOOL(0, "rebase-cousins", &opts.rebase_cousins,
 			 N_("keep original branch points of cousins")),
-		OPT_BOOL(0, "autosquash", &autosquash,
+		OPT_BOOL(0, "autosquash", &opts.autosquash,
 			 N_("move commits that begin with squash!/fixup!")),
 		OPT_BOOL(0, "signoff", &opts.signoff, N_("sign commits")),
-		OPT__VERBOSE(&opts.verbose, N_("be verbose")),
+		OPT_BIT('v', "verbose", &opts.flags,
+			N_("display a diffstat of what changed upstream"),
+			REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
 		OPT_CMDMODE(0, "continue", &command, N_("continue rebase"),
 			    CONTINUE),
 		OPT_CMDMODE(0, "skip", &command, N_("skip commit"), SKIP),
@@ -308,86 +373,86 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 			N_("rearrange fixup/squash lines"), REARRANGE_SQUASH),
 		OPT_CMDMODE(0, "add-exec-commands", &command,
 			N_("insert exec commands in todo list"), ADD_EXEC),
-		{ OPTION_CALLBACK, 0, "onto", &onto, N_("onto"), N_("onto"),
+		{ OPTION_CALLBACK, 0, "onto", &opts.onto, N_("onto"), N_("onto"),
 		  PARSE_OPT_NONEG, parse_opt_commit, 0 },
-		{ OPTION_CALLBACK, 0, "restrict-revision", &restrict_revision,
+		{ OPTION_CALLBACK, 0, "restrict-revision", &opts.restrict_revision,
 		  N_("restrict-revision"), N_("restrict revision"),
 		  PARSE_OPT_NONEG, parse_opt_commit, 0 },
 		{ OPTION_CALLBACK, 0, "squash-onto", &squash_onto, N_("squash-onto"),
 		  N_("squash onto"), PARSE_OPT_NONEG, parse_opt_object_id, 0 },
-		{ OPTION_CALLBACK, 0, "upstream", &upstream, N_("upstream"),
+		{ OPTION_CALLBACK, 0, "upstream", &opts.upstream, N_("upstream"),
 		  N_("the upstream commit"), PARSE_OPT_NONEG, parse_opt_commit,
 		  0 },
-		OPT_STRING(0, "head-name", &head_name, N_("head-name"), N_("head name")),
-		{ OPTION_STRING, 'S', "gpg-sign", &opts.gpg_sign, N_("key-id"),
+		OPT_STRING(0, "head-name", &opts.head_name, N_("head-name"), N_("head name")),
+		{ OPTION_STRING, 'S', "gpg-sign", &opts.gpg_sign_opt, N_("key-id"),
 			N_("GPG-sign commits"),
 			PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 		OPT_STRING(0, "strategy", &opts.strategy, N_("strategy"),
 			   N_("rebase strategy")),
-		OPT_STRING(0, "strategy-opts", &raw_strategies, N_("strategy-opts"),
+		OPT_STRING(0, "strategy-opts", &opts.strategy_opts, N_("strategy-opts"),
 			   N_("strategy options")),
-		OPT_STRING(0, "switch-to", &switch_to, N_("switch-to"),
+		OPT_STRING(0, "switch-to", &opts.switch_to, N_("switch-to"),
 			   N_("the branch or commit to checkout")),
-		OPT_STRING(0, "onto-name", &onto_name, N_("onto-name"), N_("onto name")),
-		OPT_STRING(0, "cmd", &cmd, N_("cmd"), N_("the command to run")),
-		OPT_RERERE_AUTOUPDATE(&opts.allow_rerere_auto),
+		OPT_STRING(0, "onto-name", &opts.onto_name, N_("onto-name"), N_("onto name")),
+		OPT_STRING(0, "cmd", &opts.cmd, N_("cmd"), N_("the command to run")),
+		OPT_RERERE_AUTOUPDATE(&opts.allow_rerere_autoupdate),
 		OPT_BOOL(0, "reschedule-failed-exec", &opts.reschedule_failed_exec,
 			 N_("automatically re-schedule any `exec` that fails")),
 		OPT_END()
 	};
 
-	sequencer_init_config(&opts);
+	opts.rebase_cousins = -1;
+
 	git_config_get_bool("rebase.abbreviatecommands", &abbreviate_commands);
 
-	opts.action = REPLAY_INTERACTIVE_REBASE;
-	opts.allow_ff = 1;
-	opts.allow_empty = 1;
-
 	if (argc == 1)
 		usage_with_options(builtin_rebase_interactive_usage, options);
 
 	argc = parse_options(argc, argv, NULL, options,
 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 
-	opts.gpg_sign = xstrdup_or_null(opts.gpg_sign);
-
 	if (!is_null_oid(&squash_onto))
-		squash_onto_opt = &squash_onto;
+		opts.squash_onto = &squash_onto;
 
-	flags |= keep_empty ? TODO_LIST_KEEP_EMPTY : 0;
+	flags |= opts.keep_empty ? TODO_LIST_KEEP_EMPTY : 0;
 	flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
-	flags |= rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
-	flags |= rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
+	flags |= opts.rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
+	flags |= opts.rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
 	flags |= command == SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
 
-	if (rebase_cousins >= 0 && !rebase_merges)
+	if (opts.rebase_cousins >= 0 && !opts.rebase_merges)
 		warning(_("--[no-]rebase-cousins has no effect without "
 			  "--rebase-merges"));
 
-	if (cmd && *cmd) {
-		string_list_split(&commands, cmd, '\n', -1);
+	if (opts.cmd && *opts.cmd) {
+		string_list_split(&commands, opts.cmd, '\n', -1);
 
 		/* rebase.c adds a new line to cmd after every command,
 		 * so here the last command is always empty */
 		string_list_remove_empty_items(&commands, 0);
 	}
 
 	switch (command) {
-	case NONE:
-		if (!onto && !upstream)
+	case NONE: {
+		struct replay_opts replay_opts = get_replay_opts(&opts);
+		if (!opts.onto && !opts.upstream)
 			die(_("a base commit must be provided with --upstream or --onto"));
 
-		ret = do_interactive_rebase(&opts, flags, switch_to, upstream, onto,
-					    onto_name, squash_onto_opt, head_name, restrict_revision,
-					    raw_strategies, &commands, autosquash);
+		ret = do_interactive_rebase(&replay_opts, flags, opts.switch_to, opts.upstream, opts.onto,
+					    opts.onto_name, opts.squash_onto, opts.head_name, opts.restrict_revision,
+					    opts.strategy_opts, &commands, opts.autosquash);
 		break;
+	}
 	case SKIP: {
 		struct string_list merge_rr = STRING_LIST_INIT_DUP;
 
 		rerere_clear(the_repository, &merge_rr);
+	}
 		/* fallthrough */
-	case CONTINUE:
-		ret = sequencer_continue(the_repository, &opts);
+	case CONTINUE: {
+		struct replay_opts replay_opts = get_replay_opts(&opts);
+
+		ret = sequencer_continue(the_repository, &replay_opts);
 		break;
 	}
 	case EDIT_TODO:
@@ -446,45 +511,6 @@ static int use_builtin_rebase(void)
 	return ret;
 }
 
-struct rebase_options {
-	enum rebase_type type;
-	const char *state_dir;
-	struct commit *upstream;
-	const char *upstream_name;
-	const char *upstream_arg;
-	char *head_name;
-	struct object_id orig_head;
-	struct commit *onto;
-	const char *onto_name;
-	const char *revisions;
-	const char *switch_to;
-	int root;
-	struct object_id *squash_onto;
-	struct commit *restrict_revision;
-	int dont_finish_rebase;
-	enum {
-		REBASE_NO_QUIET = 1<<0,
-		REBASE_VERBOSE = 1<<1,
-		REBASE_DIFFSTAT = 1<<2,
-		REBASE_FORCE = 1<<3,
-		REBASE_INTERACTIVE_EXPLICIT = 1<<4,
-	} flags;
-	struct argv_array git_am_opts;
-	const char *action;
-	int signoff;
-	int allow_rerere_autoupdate;
-	int keep_empty;
-	int autosquash;
-	char *gpg_sign_opt;
-	int autostash;
-	char *cmd;
-	int allow_empty_message;
-	int rebase_merges, rebase_cousins;
-	char *strategy, *strategy_opts;
-	struct strbuf git_format_patch_opt;
-	int reschedule_failed_exec;
-};
-
 static int is_interactive(struct rebase_options *opts)
 {
 	return opts->type == REBASE_INTERACTIVE ||
@@ -1380,13 +1406,7 @@ static int check_exec_cmd(const char *cmd)
 
 int cmd_rebase(int argc, const char **argv, const char *prefix)
 {
-	struct rebase_options options = {
-		.type = REBASE_UNSPECIFIED,
-		.flags = REBASE_NO_QUIET,
-		.git_am_opts = ARGV_ARRAY_INIT,
-		.allow_empty_message = 1,
-		.git_format_patch_opt = STRBUF_INIT,
-	};
+	struct rebase_options options = REBASE_OPTIONS_INIT;
 	const char *branch_name;
 	int ret, flags, total_argc, in_progress = 0;
 	int ok_to_skip_pre_rebase = 0;
@@ -1539,6 +1559,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	trace_repo_setup(prefix);
 	setup_work_tree();
 
+	options.allow_empty_message = 1;
 	git_config(rebase_config, &options);
 
 	strbuf_reset(&buf);
-- 
2.21.0


  parent reply index

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-19 19:03 [RFC PATCH 00/11] rebase -i run without forking rebase--interactive Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 01/11] sequencer: always discard index after checkout Phillip Wood
2019-03-20  1:50   ` Duy Nguyen
2019-03-21 14:35     ` Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 02/11] rebase: rename write_basic_state() Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 03/11] rebase: use OPT_RERERE_AUTOUPDATE() Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 04/11] rebase -i: combine rebase--interactive.c with rebase.c Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 05/11] rebase -i: remove duplication Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 06/11] rebase -i: use struct commit when parsing options Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 07/11] rebase -i: use struct object_id for squash_onto Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 08/11] rebase -i: use struct rebase_options to parse args Phillip Wood
2019-03-21  4:21   ` Junio C Hamano
2019-03-21 14:59     ` Phillip Wood
2019-03-22  3:34       ` Junio C Hamano
2019-03-21 21:13   ` Alban Gruin
2019-04-10 19:16     ` Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 09/11] rebase -i: use struct rebase_options in do_interactive_rebase() Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 10/11] rebase: use a common action enum Phillip Wood
2019-03-19 20:24   ` Ævar Arnfjörð Bjarmason
2019-03-21 14:43     ` Phillip Wood
2019-03-19 19:03 ` [RFC PATCH 11/11] rebase -i: run without forking rebase--interactive Phillip Wood
2019-03-20 20:50 ` [RFC PATCH 00/11] rebase -i " Josh Steadmon
2019-03-20 23:05 ` Ævar Arnfjörð Bjarmason
2019-03-21 14:40   ` Phillip Wood
2019-03-21  1:44 ` Junio C Hamano
2019-04-17 14:30 ` [PATCH v1 00/12] Run rebase -i " Phillip Wood
2019-04-17 14:30   ` [PATCH v1 01/12] sequencer: always discard index after checkout Phillip Wood
2019-04-17 14:30   ` [PATCH v1 02/12] rebase: don't translate trace strings Phillip Wood
2019-04-19  5:53     ` Junio C Hamano
2019-04-17 14:30   ` [PATCH v1 03/12] rebase: rename write_basic_state() Phillip Wood
2019-04-17 14:30   ` [PATCH v1 04/12] rebase: use OPT_RERERE_AUTOUPDATE() Phillip Wood
2019-04-17 14:30   ` [PATCH v1 05/12] rebase -i: combine rebase--interactive.c with rebase.c Phillip Wood
2019-04-17 14:30   ` [PATCH v1 06/12] rebase -i: remove duplication Phillip Wood
2019-04-17 14:30   ` [PATCH v1 07/12] rebase -i: use struct commit when parsing options Phillip Wood
2019-04-17 14:30   ` [PATCH v1 08/12] rebase -i: use struct object_id for squash_onto Phillip Wood
2019-04-17 14:30   ` Phillip Wood [this message]
2019-04-17 14:30   ` [PATCH v1 10/12] rebase -i: use struct rebase_options in do_interactive_rebase() Phillip Wood
2019-04-17 14:30   ` [PATCH v1 11/12] rebase: use a common action enum Phillip Wood
2019-04-17 14:30   ` [PATCH v1 12/12] rebase -i: run without forking rebase--interactive Phillip Wood

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190417143044.17655-10-phillip.wood123@gmail.com \
    --to=phillip.wood123@gmail.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=alban.gruin@gmail.com \
    --cc=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=newren@gmail.com \
    --cc=pclouds@gmail.com \
    --cc=phillip.wood@dunelm.org.uk \
    --cc=steadmon@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

git@vger.kernel.org list mirror (unofficial, one of many)

Archives are clonable:
	git clone --mirror https://public-inbox.org/git
	git clone --mirror http://ou63pmih66umazou.onion/git
	git clone --mirror http://czquwvybam4bgbro.onion/git
	git clone --mirror http://hjrcffqmbrq6wope.onion/git

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.version-control.git
	nntp://ou63pmih66umazou.onion/inbox.comp.version-control.git
	nntp://czquwvybam4bgbro.onion/inbox.comp.version-control.git
	nntp://hjrcffqmbrq6wope.onion/inbox.comp.version-control.git
	nntp://news.gmane.org/gmane.comp.version-control.git

 note: .onion URLs require Tor: https://www.torproject.org/
       or Tor2web: https://www.tor2web.org/

AGPL code for this site: git clone https://public-inbox.org/ public-inbox