All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "Pranit Bauva" <pranit.bauva@gmail.com>,
	"Tanushree Tumane" <tanushreetumane@gmail.com>,
	"Miriam Rubio" <mirucam@gmail.com>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
	"Elijah Newren" <newren@gmail.com>,
	"Bagas Sanjaya" <bagasdotme@gmail.com>,
	"Junio C Hamano" <gitster@pobox.com>,
	"Johannes Schindelin" <johannes.schindelin@gmx.de>,
	"Johannes Schindelin" <johannes.schindelin@gmx.de>
Subject: [PATCH v5 07/16] bisect--helper: migrate to OPT_SUBCOMMAND()
Date: Sat, 27 Aug 2022 12:44:15 +0000	[thread overview]
Message-ID: <5b7a3d58b4f84f72e1ae2196fa67c76b0a6302ad.1661604264.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1132.v5.git.1661604264.gitgitgadget@gmail.com>

From: Johannes Schindelin <johannes.schindelin@gmx.de>

We just introduced a new way to process subcommands, and the
`bisect--helper` learns about it in preparation for replacing the
`git-bisect.sh` script altogether.

Note that a couple of `bisect_*()` functions are not converted into
`cmd_bisect_*()` functions directly, as they have callers other than the
`OPT_SUBCOMMAND()` one (and the original functions did not expect
a subcommand name to be passed as `argv[0]`, unlike the convention for
the `cmd_*()` functions. In those cases, we introduce wrapper functions
`cmd_*()` that also call the original function.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/bisect--helper.c | 462 +++++++++++++++++++++++----------------
 git-bisect.sh            |  20 +-
 2 files changed, 288 insertions(+), 194 deletions(-)

diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 0d7cc20f9c9..d797cd1cef8 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -20,18 +20,71 @@ static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
 static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
 static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
 
-static const char * const git_bisect_helper_usage[] = {
-	N_("git bisect--helper --bisect-reset [<commit>]"),
-	"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]",
-	N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
-					    " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
-	"git bisect--helper --bisect-next",
-	N_("git bisect--helper --bisect-state (bad|new) [<rev>]"),
-	N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
-	N_("git bisect--helper --bisect-replay <filename>"),
-	N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"),
-	"git bisect--helper --bisect-visualize",
-	N_("git bisect--helper --bisect-run <cmd>..."),
+static const char * const bisect_usage[] = {
+	N_("git bisect start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
+	   "    [--no-checkout] [--first-parent] [<bad> [<good>...]] [--]"
+	   "    [<pathspec>...]"),
+	N_("git bisect (bad|new) [<rev>]"),
+	N_("git bisect (good|old) [<rev>...]"),
+	N_("git bisect terms [--term-good | --term-bad]"),
+	N_("git bisect skip [(<rev>|<range>)...]"),
+	N_("git bisect next"),
+	N_("git bisect reset [<commit>]"),
+	N_("git bisect (visualize|view)"),
+	N_("git bisect replay <logfile>"),
+	N_("git bisect log"),
+	N_("git bisect run <cmd>..."),
+	NULL
+};
+
+static const char * const bisect_start_usage[] = {
+	N_("git bisect start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
+	   "    [--no-checkout] [--first-parent] [<bad> [<good>...]] [--]"
+	   "    [<pathspec>...]"),
+	NULL
+};
+static const char * const bisect_state_usage[] = {
+	N_("git bisect (good|bad) [<rev>...]"),
+	NULL
+};
+
+static const char * const bisect_terms_usage[] = {
+	N_("git bisect terms [--term-good | --term-bad]"),
+	NULL
+};
+
+static const char * const bisect_skip_usage[] = {
+	N_("git bisect skip [(<rev>|<range>)...]"),
+	NULL
+};
+
+static const char * const bisect_next_usage[] = {
+	N_("git bisect next"),
+	NULL
+};
+
+static const char * const bisect_reset_usage[] = {
+	N_("git bisect reset [<commit>]"),
+	NULL
+};
+
+static const char * const bisect_visualize_usage[] = {
+	N_("git bisect visualize"),
+	NULL
+};
+
+static const char * const bisect_replay_usage[] = {
+	N_("git bisect replay <logfile>"),
+	NULL
+};
+
+static const char * const bisect_log_usage[] = {
+	N_("git bisect log"),
+	NULL
+};
+
+static const char * const bisect_run_usage[] = {
+	N_("git bisect run <cmd>..."),
 	NULL
 };
 
@@ -63,7 +116,7 @@ static void set_terms(const char *bad,
 static const char vocab_bad[] = "bad|new";
 static const char vocab_good[] = "good|old";
 
-static int bisect_autostart(void);
+static int bisect_autostart(const char *prefix);
 
 /*
  * Check whether the string `term` belongs to the set of strings
@@ -238,6 +291,21 @@ static int bisect_reset(const char *commit)
 	return bisect_clean_state();
 }
 
+static int cmd_bisect_reset(int argc, const char **argv, const char *prefix)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, prefix, options,
+			     bisect_reset_usage,  PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (argc > 1)
+		usage_msg_opt(_("requires either no argument or a commit"),
+			      bisect_reset_usage, options);
+
+	return bisect_reset(argc == 1 ? argv[0] : NULL);
+}
+
 static void log_commit(FILE *fp, char *fmt, const char *state,
 		       struct commit *commit)
 {
@@ -465,26 +533,41 @@ finish:
 	return res;
 }
 
-static int bisect_terms(const char *option)
+static int cmd_bisect_terms(int argc, const char **argv, const char *prefix)
 {
+	int mode = -1;
+	struct option options[] = {
+		OPT_SET_INT(0, "term-good", &mode,
+			    N_("show term for good/old"), 1),
+		OPT_SET_INT(0, "term-old", &mode,
+			    N_("show term for good/old"), 1),
+		OPT_SET_INT(0, "term-bad", &mode,
+			    N_("show term for bad/new"), 0),
+		OPT_SET_INT(0, "term-new", &mode,
+			    N_("show term for bad/new"), 0),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, options,
+			     bisect_terms_usage,  PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (argc > 1)
+		usage_msg_opt(_("terms: requires 0 or 1 argument"),
+			      bisect_terms_usage, options);
+
 	if (get_terms())
 		return error(_("no terms defined"));
 
-	if (!option) {
+	if (mode < 0) {
 		printf(_("Your current terms are %s for the old state\n"
 			 "and %s for the new state.\n"),
 		       terms.term_good, terms.term_bad);
 		return 0;
 	}
-	if (one_of(option, "--term-good", "--term-old", NULL))
+	if (mode == 1)
 		printf("%s\n", terms.term_good);
-	else if (one_of(option, "--term-bad", "--term-new", NULL))
-		printf("%s\n", terms.term_bad);
 	else
-		return error(_("invalid argument %s for 'git bisect terms'.\n"
-			       "Supported options are: "
-			       "--term-good|--term-old and "
-			       "--term-bad|--term-new."), option);
+		printf("%s\n", terms.term_bad);
 
 	return 0;
 }
@@ -623,7 +706,7 @@ static enum bisect_error bisect_next(const char *prefix)
 {
 	enum bisect_error res;
 
-	if (bisect_autostart())
+	if (bisect_autostart(prefix))
 		return BISECT_FAILED;
 
 	if (bisect_next_check(terms.term_good))
@@ -642,6 +725,24 @@ static enum bisect_error bisect_next(const char *prefix)
 	return res;
 }
 
+static int cmd_bisect_next(int argc, const char **argv, const char *prefix)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+
+	get_terms();
+	argc = parse_options(argc, argv, prefix, options,
+				bisect_next_usage,
+				PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (argc > 0)
+		usage_msg_opt(_("requires 0 argument"),
+			      bisect_next_usage, options);
+
+	return bisect_next(prefix);
+}
+
 static enum bisect_error bisect_auto_next(const char *prefix)
 {
 	if (bisect_next_check(NULL)) {
@@ -652,8 +753,9 @@ static enum bisect_error bisect_auto_next(const char *prefix)
 	return bisect_next(prefix);
 }
 
-static enum bisect_error bisect_start(int argc, const char **argv)
+static int cmd_bisect_start(int argc, const char **argv, const char *prefix)
 {
+	struct strvec orig_argv = STRVEC_INIT;
 	int no_checkout = 0;
 	int first_parent_only = 0;
 	int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;
@@ -665,66 +767,64 @@ static enum bisect_error bisect_start(int argc, const char **argv)
 	struct strbuf bisect_names = STRBUF_INIT;
 	struct object_id head_oid;
 	struct object_id oid;
-	const char *head;
+	const char *head, *term_good = NULL, *term_bad = NULL;
+	struct option options[] = {
+		OPT_BOOL(0, "no-checkout", &no_checkout,
+			 N_("do not update worktree")),
+		OPT_BOOL(0, "first-parent", &first_parent_only,
+			 N_("follow only first parent of merge commits")),
+		OPT_STRING(0, "term-good", &term_good, N_("term"),
+			   N_("use this term instead of 'good'")),
+		OPT_STRING(0, "term-bad", &term_bad, N_("term"),
+			   N_("use this term instead of 'bad'")),
+		OPT_STRING(0, "term-old", &term_good, N_("term"),
+			   N_("use this term instead of 'good'")),
+		OPT_STRING(0, "term-new", &term_bad, N_("term"),
+			   N_("use this term instead of 'bad'")),
+		OPT_END()
+	};
+
+	set_terms("bad", "good");
 
 	if (is_bare_repository())
 		no_checkout = 1;
 
-	/*
-	 * Check for one bad and then some good revisions
-	 */
-	for (i = 0; i < argc; i++) {
+	strvec_pushv(&orig_argv, argv); /* save the command-line for logging */
+	argc = parse_options(argc, argv, prefix, options, bisect_start_usage,
+			     PARSE_OPT_KEEP_DASHDASH);
+
+	if (term_good) {
+		free(terms.term_good);
+		terms.term_good = xstrdup(term_good);
+		must_write_terms = 1;
+	}
+
+	if (term_bad) {
+		free(terms.term_bad);
+		terms.term_bad = xstrdup(term_bad);
+		must_write_terms = 1;
+	}
+
+	for (i = 0; i < argc; i++)
 		if (!strcmp(argv[i], "--")) {
 			has_double_dash = 1;
 			break;
 		}
-	}
 
-	for (i = 0; i < argc; i++) {
-		const char *arg = argv[i];
-		if (!strcmp(argv[i], "--")) {
-			break;
-		} else if (!strcmp(arg, "--no-checkout")) {
-			no_checkout = 1;
-		} else if (!strcmp(arg, "--first-parent")) {
-			first_parent_only = 1;
-		} else if (!strcmp(arg, "--term-good") ||
-			 !strcmp(arg, "--term-old")) {
-			i++;
-			if (argc <= i)
-				return error(_("'' is not a valid term"));
-			must_write_terms = 1;
-			free((void *) terms.term_good);
-			terms.term_good = xstrdup(argv[i]);
-		} else if (skip_prefix(arg, "--term-good=", &arg) ||
-			   skip_prefix(arg, "--term-old=", &arg)) {
-			must_write_terms = 1;
-			free((void *) terms.term_good);
-			terms.term_good = xstrdup(arg);
-		} else if (!strcmp(arg, "--term-bad") ||
-			 !strcmp(arg, "--term-new")) {
-			i++;
-			if (argc <= i)
-				return error(_("'' is not a valid term"));
-			must_write_terms = 1;
-			free((void *) terms.term_bad);
-			terms.term_bad = xstrdup(argv[i]);
-		} else if (skip_prefix(arg, "--term-bad=", &arg) ||
-			   skip_prefix(arg, "--term-new=", &arg)) {
-			must_write_terms = 1;
-			free((void *) terms.term_bad);
-			terms.term_bad = xstrdup(arg);
-		} else if (starts_with(arg, "--")) {
-			return error(_("unrecognized option: '%s'"), arg);
-		} else if (!get_oidf(&oid, "%s^{commit}", arg)) {
+	/*
+	 * Check for one bad and then some good revisions
+	 */
+
+	for (i = 0; i < argc && strcmp(argv[i], "--"); i++)
+		if (!get_oidf(&oid, "%s^{commit}", argv[i])) {
 			string_list_append(&revs, oid_to_hex(&oid));
 		} else if (has_double_dash) {
 			die(_("'%s' does not appear to be a valid "
-			      "revision"), arg);
+			      "revision"), argv[i]);
 		} else {
 			break;
 		}
-	}
+
 	pathspec_pos = i;
 
 	/*
@@ -836,11 +936,13 @@ static enum bisect_error bisect_start(int argc, const char **argv)
 		goto finish;
 	}
 
-	res = bisect_append_log_quoted(argv);
+	res = bisect_append_log_quoted(orig_argv.v + 1);
 	if (res)
 		res = BISECT_FAILED;
 
 finish:
+	strvec_clear(&orig_argv);
+
 	string_list_clear(&revs, 0);
 	string_list_clear(&states, 0);
 	strbuf_release(&start_head);
@@ -848,7 +950,7 @@ finish:
 	if (res)
 		return res;
 
-	res = bisect_auto_next(NULL);
+	res = bisect_auto_next(prefix);
 	if (!is_bisect_success(res))
 		bisect_clean_state();
 	return res;
@@ -859,7 +961,7 @@ static inline int file_is_not_empty(const char *path)
 	return !is_empty_or_missing_file(path);
 }
 
-static int bisect_autostart(void)
+static int bisect_autostart(const char *prefix)
 {
 	int res;
 	const char *yesno;
@@ -881,12 +983,13 @@ static int bisect_autostart(void)
 	yesno = git_prompt(_("Do you want me to do it for you "
 			     "[Y/n]? "), PROMPT_ECHO);
 	res = tolower(*yesno) == 'n' ?
-		-1 : bisect_start(0, empty_strvec);
+		-1 : cmd_bisect_start(1, &yesno, prefix);
 
 	return res;
 }
 
-static enum bisect_error bisect_state(int argc, const char **argv)
+static enum bisect_error bisect_state(int argc, const char **argv,
+				      const char *prefix)
 {
 	const char *state;
 	int i, verify_expected = 1;
@@ -894,10 +997,8 @@ static enum bisect_error bisect_state(int argc, const char **argv)
 	struct strbuf buf = STRBUF_INIT;
 	struct oid_array revs = OID_ARRAY_INIT;
 
-	if (!argc)
-		return error(_("Please call `--bisect-state` with at least one argument"));
 
-	if (bisect_autostart())
+	if (bisect_autostart(prefix))
 		return BISECT_FAILED;
 
 	state = argv[0];
@@ -966,11 +1067,41 @@ static enum bisect_error bisect_state(int argc, const char **argv)
 	return bisect_auto_next(NULL);
 }
 
-static enum bisect_error bisect_log(void)
+static int cmd_bisect_state(int argc, const char **argv,
+				const char *prefix)
 {
+	struct option options[] = {
+		OPT_END()
+	};
+
+	set_terms("bad", "good");
+	get_terms();
+
+	argc = parse_options(argc, argv, prefix, options,
+			     bisect_state_usage,  PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (!argc)
+		usage_msg_opt(_("need at least one argument"),
+			      bisect_state_usage, options);
+
+	return bisect_state(argc, argv, prefix);
+}
+
+static int cmd_bisect_log(int argc, const char **argv, const char *prefix)
+{
+	struct option options[] = {
+		OPT_END()
+	};
 	int fd, status;
 	const char* filename = git_path_bisect_log();
 
+	argc = parse_options(argc, argv, prefix, options,
+			     bisect_log_usage,  PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (argc > 0)
+		usage_msg_opt(_("require 0 argument"), bisect_log_usage,
+			      options);
+
 	if (is_empty_or_missing_file(filename))
 		return error(_("We are not bisecting."));
 
@@ -983,7 +1114,7 @@ static enum bisect_error bisect_log(void)
 	return status ? BISECT_FAILED : BISECT_OK;
 }
 
-static int process_replay_line(struct strbuf *line)
+static int process_replay_line(struct strbuf *line, const char *prefix)
 {
 	const char *p = line->buf + strspn(line->buf, " \t");
 	char *word_end, *rev;
@@ -1004,8 +1135,10 @@ static int process_replay_line(struct strbuf *line)
 	if (!strcmp(p, "start")) {
 		struct strvec argv = STRVEC_INIT;
 		int res;
+
+		strvec_push(&argv, p);
 		sq_dequote_to_strvec(rev, &argv);
-		res = bisect_start(argv.nr, argv.v);
+		res = cmd_bisect_start(argv.nr, argv.v, prefix);
 		strvec_clear(&argv);
 		return res;
 	}
@@ -1017,8 +1150,11 @@ static int process_replay_line(struct strbuf *line)
 	if (!strcmp(p, "terms")) {
 		struct strvec argv = STRVEC_INIT;
 		int res;
+
+		strvec_push(&argv, p);
 		sq_dequote_to_strvec(rev, &argv);
-		res = bisect_terms(argv.nr == 1 ? argv.v[0] : NULL);
+		res = cmd_bisect_terms(argv.nr, argv.v, NULL);
+
 		strvec_clear(&argv);
 		return res;
 	}
@@ -1027,12 +1163,25 @@ static int process_replay_line(struct strbuf *line)
 	return -1;
 }
 
-static enum bisect_error bisect_replay(const char *filename)
+static int cmd_bisect_replay(int argc, const char **argv, const char *prefix)
 {
+	struct option options[] = {
+		OPT_END()
+	};
+	const char *filename;
 	FILE *fp = NULL;
 	enum bisect_error res = BISECT_OK;
 	struct strbuf line = STRBUF_INIT;
 
+	set_terms("bad", "good");
+	argc = parse_options(argc, argv, prefix, options,
+			     bisect_reset_usage,  PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (argc != 1)
+		usage_msg_opt(_("no logfile given"), bisect_replay_usage,
+			      options);
+
+	filename = argv[0];
 	if (is_empty_or_missing_file(filename))
 		return error(_("cannot read file '%s' for replaying"), filename);
 
@@ -1044,7 +1193,7 @@ static enum bisect_error bisect_replay(const char *filename)
 		return BISECT_FAILED;
 
 	while ((strbuf_getline(&line, fp) != EOF) && !res)
-		res = process_replay_line(&line);
+		res = process_replay_line(&line, prefix);
 
 	strbuf_release(&line);
 	fclose(fp);
@@ -1055,12 +1204,20 @@ static enum bisect_error bisect_replay(const char *filename)
 	return bisect_auto_next(NULL);
 }
 
-static enum bisect_error bisect_skip(int argc, const char **argv)
+static int cmd_bisect_skip(int argc, const char **argv, const char *prefix)
 {
+	struct option options[] = {
+		OPT_END()
+	};
 	int i;
 	enum bisect_error res;
 	struct strvec argv_state = STRVEC_INIT;
 
+	set_terms("bad", "good");
+	get_terms();
+	argc = parse_options(argc, argv, prefix, options,
+			     bisect_skip_usage,  PARSE_OPT_STOP_AT_NON_OPTION);
+
 	strvec_push(&argv_state, "skip");
 
 	for (i = 0; i < argc; i++) {
@@ -1085,18 +1242,28 @@ static enum bisect_error bisect_skip(int argc, const char **argv)
 			strvec_push(&argv_state, argv[i]);
 		}
 	}
-	res = bisect_state(argv_state.nr, argv_state.v);
+	res = bisect_state(argv_state.nr, argv_state.v, prefix);
 
 	strvec_clear(&argv_state);
 	return res;
 }
 
-static int bisect_visualize(int argc, const char **argv)
+static int cmd_bisect_visualize(int argc, const char **argv, const char *prefix)
 {
+	struct option options[] = {
+		OPT_END()
+	};
 	struct strvec args = STRVEC_INIT;
 	int flags = RUN_COMMAND_NO_STDIN, res = 0;
 	struct strbuf sb = STRBUF_INIT;
 
+	set_terms("bad", "good");
+	get_terms();
+	argc = parse_options(argc, argv, prefix, options,
+			     bisect_visualize_usage,
+			     PARSE_OPT_KEEP_DASHDASH |
+			     PARSE_OPT_KEEP_UNKNOWN_OPT);
+
 	if (bisect_next_check(NULL) != 0)
 		return BISECT_FAILED;
 
@@ -1166,8 +1333,11 @@ static int verify_good(const char **quoted_argv)
 	return rc;
 }
 
-static int bisect_run(int argc, const char **argv)
+static int cmd_bisect_run(int argc, const char **argv, const char *prefix)
 {
+	struct option options[] = {
+		OPT_END()
+	};
 	int res = BISECT_OK;
 	struct strbuf command = STRBUF_INIT;
 	struct strvec run_args = STRVEC_INIT;
@@ -1175,15 +1345,18 @@ static int bisect_run(int argc, const char **argv)
 	int temporary_stdout_fd, saved_stdout;
 	int is_first_run = 1;
 
+	get_terms();
+	argc = parse_options(argc, argv, prefix, options,
+			     bisect_run_usage,  PARSE_OPT_STOP_AT_NON_OPTION);
+
 	if (bisect_next_check(NULL))
 		return BISECT_FAILED;
 
 	if (argc)
 		sq_quote_argv(&command, argv);
-	else {
-		error(_("bisect run failed: no command provided."));
-		return BISECT_FAILED;
-	}
+	else
+		usage_msg_opt(_("bisect run failed: no command provided."),
+			      bisect_run_usage, options);
 
 	strvec_push(&run_args, command.buf);
 
@@ -1239,7 +1412,7 @@ static int bisect_run(int argc, const char **argv)
 		saved_stdout = dup(1);
 		dup2(temporary_stdout_fd, 1);
 
-		res = bisect_state(1, &new_state);
+		res = bisect_state(1, &new_state, prefix);
 
 		fflush(stdout);
 		dup2(saved_stdout, 1);
@@ -1272,105 +1445,26 @@ static int bisect_run(int argc, const char **argv)
 
 int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
 {
-	enum {
-		BISECT_RESET = 1,
-		BISECT_TERMS,
-		BISECT_START,
-		BISECT_NEXT,
-		BISECT_STATE,
-		BISECT_LOG,
-		BISECT_REPLAY,
-		BISECT_SKIP,
-		BISECT_VISUALIZE,
-		BISECT_RUN,
-	} cmdmode = 0;
+	parse_opt_subcommand_fn *fn = NULL;
 	int res = 0;
 	struct option options[] = {
-		OPT_CMDMODE(0, "bisect-reset", &cmdmode,
-			 N_("reset the bisection state"), BISECT_RESET),
-		OPT_CMDMODE(0, "bisect-terms", &cmdmode,
-			 N_("print out the bisect terms"), BISECT_TERMS),
-		OPT_CMDMODE(0, "bisect-start", &cmdmode,
-			 N_("start the bisect session"), BISECT_START),
-		OPT_CMDMODE(0, "bisect-next", &cmdmode,
-			 N_("find the next bisection commit"), BISECT_NEXT),
-		OPT_CMDMODE(0, "bisect-state", &cmdmode,
-			 N_("mark the state of ref (or refs)"), BISECT_STATE),
-		OPT_CMDMODE(0, "bisect-log", &cmdmode,
-			 N_("list the bisection steps so far"), BISECT_LOG),
-		OPT_CMDMODE(0, "bisect-replay", &cmdmode,
-			 N_("replay the bisection process from the given file"), BISECT_REPLAY),
-		OPT_CMDMODE(0, "bisect-skip", &cmdmode,
-			 N_("skip some commits for checkout"), BISECT_SKIP),
-		OPT_CMDMODE(0, "bisect-visualize", &cmdmode,
-			 N_("visualize the bisection"), BISECT_VISUALIZE),
-		OPT_CMDMODE(0, "bisect-run", &cmdmode,
-			 N_("use <cmd>... to automatically bisect"), BISECT_RUN),
+		OPT_SUBCOMMAND("reset", &fn, cmd_bisect_reset),
+		OPT_SUBCOMMAND("terms", &fn, cmd_bisect_terms),
+		OPT_SUBCOMMAND("start", &fn, cmd_bisect_start),
+		OPT_SUBCOMMAND("next", &fn, cmd_bisect_next),
+		OPT_SUBCOMMAND("state", &fn, cmd_bisect_state),
+		OPT_SUBCOMMAND("log", &fn, cmd_bisect_log),
+		OPT_SUBCOMMAND("replay", &fn, cmd_bisect_replay),
+		OPT_SUBCOMMAND("skip", &fn, cmd_bisect_skip),
+		OPT_SUBCOMMAND("visualize", &fn, cmd_bisect_visualize),
+		OPT_SUBCOMMAND("run", &fn, cmd_bisect_run),
 		OPT_END()
 	};
 
 	argc = parse_options(argc, argv, prefix, options,
-			     git_bisect_helper_usage,
-			     PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN_OPT);
-
-	if (!cmdmode)
-		usage_with_options(git_bisect_helper_usage, options);
+			     bisect_usage, 0);
 
-	switch (cmdmode) {
-	case BISECT_RESET:
-		if (argc > 1)
-			return error(_("--bisect-reset requires either no argument or a commit"));
-		res = bisect_reset(argc ? argv[0] : NULL);
-		break;
-	case BISECT_TERMS:
-		if (argc > 1)
-			return error(_("--bisect-terms requires 0 or 1 argument"));
-		res = bisect_terms(argc == 1 ? argv[0] : NULL);
-		break;
-	case BISECT_START:
-		set_terms("bad", "good");
-		res = bisect_start(argc, argv);
-		break;
-	case BISECT_NEXT:
-		if (argc)
-			return error(_("--bisect-next requires 0 arguments"));
-		get_terms();
-		res = bisect_next(prefix);
-		break;
-	case BISECT_STATE:
-		set_terms("bad", "good");
-		get_terms();
-		res = bisect_state(argc, argv);
-		break;
-	case BISECT_LOG:
-		if (argc)
-			return error(_("--bisect-log requires 0 arguments"));
-		res = bisect_log();
-		break;
-	case BISECT_REPLAY:
-		if (argc != 1)
-			return error(_("no logfile given"));
-		set_terms("bad", "good");
-		res = bisect_replay(argv[0]);
-		break;
-	case BISECT_SKIP:
-		set_terms("bad", "good");
-		get_terms();
-		res = bisect_skip(argc, argv);
-		break;
-	case BISECT_VISUALIZE:
-		get_terms();
-		res = bisect_visualize(argc, argv);
-		break;
-	case BISECT_RUN:
-		if (!argc)
-			return error(_("bisect run failed: no command provided."));
-		get_terms();
-		res = bisect_run(argc, argv);
-		break;
-	default:
-		BUG("unknown subcommand %d", cmdmode);
-	}
+	res = fn(argc, argv, prefix);
 	free_terms();
 
 	return is_bisect_success(res) ? 0 : -res;
diff --git a/git-bisect.sh b/git-bisect.sh
index 405cf76f2a3..e19847eba0d 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -58,26 +58,26 @@ case "$#" in
 	help)
 		git bisect -h ;;
 	start)
-		git bisect--helper --bisect-start "$@" ;;
+		git bisect--helper start "$@" ;;
 	bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD")
-		git bisect--helper --bisect-state "$cmd" "$@" ;;
+		git bisect--helper state "$cmd" "$@" ;;
 	skip)
-		git bisect--helper --bisect-skip "$@" || exit;;
+		git bisect--helper skip "$@" || exit;;
 	next)
 		# Not sure we want "next" at the UI level anymore.
-		git bisect--helper --bisect-next "$@" || exit ;;
+		git bisect--helper next "$@" || exit ;;
 	visualize|view)
-		git bisect--helper --bisect-visualize "$@" || exit;;
+		git bisect--helper visualize "$@" || exit;;
 	reset)
-		git bisect--helper --bisect-reset "$@" ;;
+		git bisect--helper reset "$@" ;;
 	replay)
-		git bisect--helper --bisect-replay "$@" || exit;;
+		git bisect--helper replay "$@" || exit;;
 	log)
-		git bisect--helper --bisect-log || exit ;;
+		git bisect--helper log || exit ;;
 	run)
-		git bisect--helper --bisect-run "$@" || exit;;
+		git bisect--helper run "$@" || exit;;
 	terms)
-		git bisect--helper --bisect-terms "$@" || exit;;
+		git bisect--helper terms "$@" || exit;;
 	*)
 		usage ;;
 	esac
-- 
gitgitgadget


  parent reply	other threads:[~2022-08-27 12:44 UTC|newest]

Thread overview: 147+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-28  0:12 [PATCH 00/11] Finish converting git bisect into a built-in Johannes Schindelin via GitGitGadget
2022-01-28  0:12 ` [PATCH 01/11] bisect run: fix the error message Johannes Schindelin via GitGitGadget
2022-02-08 22:05   ` Elijah Newren
2022-02-22 14:38     ` Johannes Schindelin
2022-01-28  0:12 ` [PATCH 02/11] bisect--helper: retire the --no-log option Johannes Schindelin via GitGitGadget
2022-01-28  0:12 ` [PATCH 03/11] bisect--helper: really retire --bisect-next-check Johannes Schindelin via GitGitGadget
2022-01-28  0:12 ` [PATCH 04/11] bisect--helper: really retire `--bisect-autostart` Johannes Schindelin via GitGitGadget
2022-01-28  0:12 ` [PATCH 05/11] bisect--helper: align the sub-command order with git-bisect.sh Johannes Schindelin via GitGitGadget
2022-01-28  0:12 ` [PATCH 06/11] bisect--helper: make `--bisect-state` optional Johannes Schindelin via GitGitGadget
2022-02-08 23:03   ` Elijah Newren
2022-02-22 15:12     ` Johannes Schindelin
2022-02-09 19:45   ` Junio C Hamano
2022-02-22 15:53     ` Johannes Schindelin
2022-01-28  0:12 ` [PATCH 07/11] bisect: move even the option parsing to `bisect--helper` Johannes Schindelin via GitGitGadget
2022-01-29  6:47   ` Ævar Arnfjörð Bjarmason
2022-02-09  0:12   ` Elijah Newren
2022-02-22 15:49     ` Johannes Schindelin
2022-01-28  0:12 ` [PATCH 08/11] bisect--helper: using `--bisect-state` without an argument is a bug Johannes Schindelin via GitGitGadget
2022-01-29  7:04   ` Ævar Arnfjörð Bjarmason
2022-02-09  0:26   ` Elijah Newren
2022-01-28  0:12 ` [PATCH 09/11] Turn `git bisect` into a full built-in Johannes Schindelin via GitGitGadget
2022-01-29  7:09   ` Ævar Arnfjörð Bjarmason
2022-01-28  0:12 ` [PATCH 10/11] bisect: remove Cogito-related code Johannes Schindelin via GitGitGadget
2022-01-28  0:12 ` [PATCH 11/11] bisect: no longer try to clean up left-over `.git/head-name` files Johannes Schindelin via GitGitGadget
     [not found] ` <CAN7CjDC+O883DB1iaJAXF5ZCis7FP2Z9z0y2qS2-JVAKfQA8aA@mail.gmail.com>
2022-01-28  8:54   ` Fwd: [PATCH 00/11] Finish converting git bisect into a built-in Miriam R.
2022-01-28 12:42   ` Johannes Schindelin
2022-01-28 15:11     ` Miriam R.
2022-01-30  6:39 ` Elijah Newren
2022-02-09  4:41   ` Elijah Newren
2022-02-22 15:55     ` Johannes Schindelin
2022-02-22 16:30 ` [PATCH v2 00/14] " Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 01/14] bisect run: fix the error message Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 02/14] bisect: avoid double-quoting when printing the failed command Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 03/14] bisect--helper: retire the --no-log option Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 04/14] bisect--helper: really retire --bisect-next-check Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 05/14] bisect--helper: really retire `--bisect-autostart` Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 06/14] bisect--helper: using `--bisect-state` without an argument is a bug Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 07/14] bisect--helper: align the sub-command order with git-bisect.sh Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 08/14] bisect--helper: make `--bisect-state` optional Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 09/14] bisect--helper: move the `BISECT_STATE` case to the end Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 10/14] bisect--helper: return only correct exit codes in `cmd_*()` Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 11/14] bisect: move even the option parsing to `bisect--helper` Johannes Schindelin via GitGitGadget
2022-02-23  9:47     ` Ævar Arnfjörð Bjarmason
2022-02-25 15:59       ` Johannes Schindelin
2022-02-25 16:49         ` Ævar Arnfjörð Bjarmason
2022-02-22 16:30   ` [PATCH v2 12/14] Turn `git bisect` into a full built-in Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 13/14] bisect: remove Cogito-related code Johannes Schindelin via GitGitGadget
2022-02-22 16:30   ` [PATCH v2 14/14] bisect: no longer try to clean up left-over `.git/head-name` files Johannes Schindelin via GitGitGadget
2022-02-23  1:41   ` [PATCH v2 00/14] Finish converting git bisect into a built-in Elijah Newren
2022-02-25 15:59     ` Johannes Schindelin
2022-02-23 21:35   ` Junio C Hamano
2022-02-25 16:03     ` Johannes Schindelin
2022-02-25 16:44       ` Ævar Arnfjörð Bjarmason
2022-05-21 14:48   ` [PATCH v3 00/15] " Johannes Schindelin via GitGitGadget
2022-05-21 14:48     ` [PATCH v3 01/15] bisect run: fix the error message Johannes Schindelin via GitGitGadget
2022-05-21 14:48     ` [PATCH v3 02/15] bisect: avoid double-quoting when printing the failed command Johannes Schindelin via GitGitGadget
2022-05-21 14:48     ` [PATCH v3 03/15] bisect--helper: retire the --no-log option Johannes Schindelin via GitGitGadget
2022-05-21 14:48     ` [PATCH v3 04/15] bisect--helper: really retire --bisect-next-check Johannes Schindelin via GitGitGadget
2022-05-21 14:48     ` [PATCH v3 05/15] bisect--helper: really retire `--bisect-autostart` Johannes Schindelin via GitGitGadget
2022-05-21 14:48     ` [PATCH v3 06/15] bisect--helper: using `--bisect-state` without an argument is a bug Johannes Schindelin via GitGitGadget
2022-05-21 14:48     ` [PATCH v3 07/15] bisect--helper: align the sub-command order with git-bisect.sh Johannes Schindelin via GitGitGadget
2022-05-21 14:48     ` [PATCH v3 08/15] bisect--helper: make `--bisect-state` optional Johannes Schindelin via GitGitGadget
2022-05-21 14:49     ` [PATCH v3 09/15] bisect--helper: move the `BISECT_STATE` case to the end Johannes Schindelin via GitGitGadget
2022-05-21 14:49     ` [PATCH v3 10/15] bisect--helper: return only correct exit codes in `cmd_*()` Johannes Schindelin via GitGitGadget
2022-05-21 16:45       ` Ævar Arnfjörð Bjarmason
2022-05-21 14:49     ` [PATCH v3 11/15] bisect: move even the command-line parsing to `bisect--helper` Johannes Schindelin via GitGitGadget
2022-05-21 16:52       ` Ævar Arnfjörð Bjarmason
2022-05-21 14:49     ` [PATCH v3 12/15] bisect: teach the `bisect--helper` command to show the correct usage strings Johannes Schindelin via GitGitGadget
2022-05-21 14:49     ` [PATCH v3 13/15] Turn `git bisect` into a full built-in Johannes Schindelin via GitGitGadget
2022-05-21 14:49     ` [PATCH v3 14/15] bisect: remove Cogito-related code Johannes Schindelin via GitGitGadget
2022-05-21 14:49     ` [PATCH v3 15/15] bisect: no longer try to clean up left-over `.git/head-name` files Johannes Schindelin via GitGitGadget
2022-05-22  3:07     ` [PATCH v3 00/15] Finish converting git bisect into a built-in Bagas Sanjaya
2022-05-23 10:22       ` Ævar Arnfjörð Bjarmason
2022-06-27 18:31     ` [PATCH v4 00/16] " Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 01/16] bisect: verify that a bogus option won't try to start a bisection Johannes Schindelin via GitGitGadget
2022-06-28  2:12         ` Junio C Hamano
2022-06-27 18:31       ` [PATCH v4 02/16] bisect run: fix the error message Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 03/16] bisect: avoid double-quoting when printing the failed command Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 04/16] bisect--helper: retire the --no-log option Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 05/16] bisect--helper: really retire --bisect-next-check Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 06/16] bisect--helper: really retire `--bisect-autostart` Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 07/16] bisect--helper: using `--bisect-state` without an argument is a bug Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 08/16] bisect--helper: align the sub-command order with git-bisect.sh Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 09/16] bisect--helper: make `--bisect-state` optional Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 10/16] bisect--helper: move the `BISECT_STATE` case to the end Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 11/16] bisect--helper: return only correct exit codes in `cmd_*()` Johannes Schindelin via GitGitGadget
2022-06-27 20:09         ` Ævar Arnfjörð Bjarmason
2022-06-27 18:31       ` [PATCH v4 12/16] bisect: teach the `bisect--helper` command to show the correct usage strings Johannes Schindelin via GitGitGadget
2022-06-27 22:11         ` Junio C Hamano
2022-06-27 18:31       ` [PATCH v4 13/16] bisect: move even the command-line parsing to `bisect--helper` Johannes Schindelin via GitGitGadget
2022-06-27 18:31       ` [PATCH v4 14/16] Turn `git bisect` into a full built-in Johannes Schindelin via GitGitGadget
2022-06-27 22:13         ` Junio C Hamano
2022-06-27 18:31       ` [PATCH v4 15/16] bisect: remove Cogito-related code Johannes Schindelin via GitGitGadget
2022-06-27 22:18         ` Junio C Hamano
2022-06-27 18:31       ` [PATCH v4 16/16] bisect: no longer try to clean up left-over `.git/head-name` files Johannes Schindelin via GitGitGadget
2022-06-27 19:45       ` [PATCH v4 00/16] Finish converting git bisect into a built-in Ævar Arnfjörð Bjarmason
2022-08-27 12:44       ` [PATCH v5 " Johannes Schindelin via GitGitGadget
2022-08-27 12:44         ` [PATCH v5 01/16] bisect--helper: retire the --no-log option Johannes Schindelin via GitGitGadget
2022-08-27 12:44         ` [PATCH v5 02/16] bisect--helper: really retire --bisect-next-check Johannes Schindelin via GitGitGadget
2022-08-27 12:44         ` [PATCH v5 03/16] bisect--helper: really retire `--bisect-autostart` Johannes Schindelin via GitGitGadget
2022-08-27 12:44         ` [PATCH v5 04/16] bisect--helper: simplify exit code computation Johannes Schindelin via GitGitGadget
2022-08-28  6:43           ` Junio C Hamano
2022-08-27 12:44         ` [PATCH v5 05/16] bisect--helper: make `terms` an explicit singleton Johannes Schindelin via GitGitGadget
2022-08-28  6:53           ` Junio C Hamano
2022-08-29 12:13             ` Johannes Schindelin
2022-08-29 17:04               ` Junio C Hamano
2022-08-29 10:20           ` Ævar Arnfjörð Bjarmason
2022-08-29 12:30             ` Johannes Schindelin
2022-08-29 17:47             ` Junio C Hamano
2022-08-27 12:44         ` [PATCH v5 06/16] bisect--helper: make the order consistently `argc, argv` Johannes Schindelin via GitGitGadget
2022-08-28  6:53           ` Junio C Hamano
2022-08-27 12:44         ` Johannes Schindelin via GitGitGadget [this message]
2022-08-29  9:38           ` [PATCH v5 07/16] bisect--helper: migrate to OPT_SUBCOMMAND() Ævar Arnfjörð Bjarmason
2022-08-30 15:42             ` Johannes Schindelin
2022-08-27 12:44         ` [PATCH v5 08/16] bisect: verify that a bogus option won't try to start a bisection Johannes Schindelin via GitGitGadget
2022-08-27 12:44         ` [PATCH v5 09/16] bisect run: fix the error message Johannes Schindelin via GitGitGadget
2022-08-28  7:03           ` Junio C Hamano
2022-08-29 12:20             ` Johannes Schindelin
2022-08-27 12:44         ` [PATCH v5 10/16] bisect: avoid double-quoting when printing the failed command Johannes Schindelin via GitGitGadget
2022-08-27 12:44         ` [PATCH v5 11/16] bisect--helper: calling `bisect_state()` without an argument is a bug Johannes Schindelin via GitGitGadget
2022-08-29 10:11           ` Ævar Arnfjörð Bjarmason
2022-08-30 14:47             ` Johannes Schindelin
2022-08-27 12:44         ` [PATCH v5 12/16] bisect--helper: make `state` optional Johannes Schindelin via GitGitGadget
2022-08-27 12:44         ` [PATCH v5 13/16] bisect: move even the command-line parsing to `bisect--helper` Johannes Schindelin via GitGitGadget
2022-08-27 12:44         ` [PATCH v5 14/16] Turn `git bisect` into a full built-in Johannes Schindelin via GitGitGadget
2022-08-27 12:44         ` [PATCH v5 15/16] bisect: remove Cogito-related code Johannes Schindelin via GitGitGadget
2022-08-27 12:44         ` [PATCH v5 16/16] bisect: no longer try to clean up left-over `.git/head-name` files Johannes Schindelin via GitGitGadget
2022-08-30 18:50         ` [PATCH v6 00/16] Finish converting git bisect into a built-in Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 01/16] bisect--helper: retire the --no-log option Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 02/16] bisect--helper: really retire --bisect-next-check Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 03/16] bisect--helper: really retire `--bisect-autostart` Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 04/16] bisect--helper: simplify exit code computation Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 05/16] bisect--helper: make `terms` an explicit singleton Johannes Schindelin via GitGitGadget
2022-08-30 21:11             ` Junio C Hamano
2022-08-30 21:28               ` Junio C Hamano
2022-08-30 18:50           ` [PATCH v6 06/16] bisect--helper: make the order consistently `argc, argv` Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 07/16] bisect--helper: migrate to OPT_SUBCOMMAND() Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 08/16] bisect: verify that a bogus option won't try to start a bisection Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 09/16] bisect run: fix the error message Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 10/16] bisect: avoid double-quoting when printing the failed command Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 11/16] bisect--helper: calling `bisect_state()` without an argument is a bug Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 12/16] bisect--helper: make `state` optional Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 13/16] bisect: move even the command-line parsing to `bisect--helper` Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 14/16] Turn `git bisect` into a full built-in Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 15/16] bisect: remove Cogito-related code Johannes Schindelin via GitGitGadget
2022-08-30 18:50           ` [PATCH v6 16/16] bisect: no longer try to clean up left-over `.git/head-name` files Johannes Schindelin via GitGitGadget
2022-09-13 17:44           ` [PATCH v6 00/16] Finish converting git bisect into a built-in Junio C Hamano

Reply instructions:

You may reply publicly 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

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

  git send-email \
    --in-reply-to=5b7a3d58b4f84f72e1ae2196fa67c76b0a6302ad.1661604264.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=avarab@gmail.com \
    --cc=bagasdotme@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=johannes.schindelin@gmx.de \
    --cc=mirucam@gmail.com \
    --cc=newren@gmail.com \
    --cc=pranit.bauva@gmail.com \
    --cc=tanushreetumane@gmail.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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.