On Thu, Nov 10 2022, Đoàn Trần Công Danh wrote: > In a later change, we will use OPT_SUBCOMMAND to parse sub-commands to > avoid consuming non-option opts. > > Since OPT_SUBCOMMAND needs a function pointer to operate, > let's move it now. > > Signed-off-by: Đoàn Trần Công Danh <congdanhqx@xxxxxxxxx> > --- > builtin/bisect--helper.c | 155 ++++++++++++++++++++++++++++++--------- > 1 file changed, 121 insertions(+), 34 deletions(-) > > diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c > index 5ec2e67f59..d425555d1f 100644 > --- a/builtin/bisect--helper.c > +++ b/builtin/bisect--helper.c > @@ -1279,6 +1279,117 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc) > return res; > } > > +static int cmd_bisect__reset(int argc, const char **argv, const char *prefix UNUSED) > +{ > + if (argc > 1) > + return error(_("--bisect-reset requires either no argument or a commit")); > + return bisect_reset(argc ? argv[0] : NULL); > +} > + > +static int cmd_bisect__terms(int argc, const char **argv, const char *prefix UNUSED) > +{ > + int res; > + struct bisect_terms terms = { 0 }; > + > + if (argc > 1) > + return error(_("--bisect-terms requires 0 or 1 argument")); > + res = bisect_terms(&terms, argc == 1 ? argv[0] : NULL); > + free_terms(&terms); > + return res; > +} > + > +static int cmd_bisect__start(int argc, const char **argv, const char *prefix UNUSED) > +{ > + int res; > + struct bisect_terms terms = { 0 }; > + > + set_terms(&terms, "bad", "good"); > + res = bisect_start(&terms, argv, argc); > + free_terms(&terms); > + return res; > +} > + > +static int cmd_bisect__next(int argc, const char **argv UNUSED, const char *prefix) > +{ > + int res; > + struct bisect_terms terms = { 0 }; > + > + if (argc) > + return error(_("--bisect-next requires 0 arguments")); > + get_terms(&terms); > + res = bisect_next(&terms, prefix); > + free_terms(&terms); > + return res; > +} > + > +static int cmd_bisect__state(int argc, const char **argv, const char *prefix UNUSED) > +{ > + int res; > + struct bisect_terms terms = { 0 }; > + > + set_terms(&terms, "bad", "good"); > + get_terms(&terms); > + res = bisect_state(&terms, argv, argc); > + free_terms(&terms); > + return res; > +} > + > +static int cmd_bisect__log(int argc, const char **argv UNUSED, const char *prefix UNUSED) > +{ > + if (argc) > + return error(_("--bisect-log requires 0 arguments")); > + return bisect_log(); > +} > + > +static int cmd_bisect__replay(int argc, const char **argv, const char *prefix UNUSED) > +{ > + int res; > + struct bisect_terms terms = { 0 }; > + > + if (argc != 1) > + return error(_("no logfile given")); > + set_terms(&terms, "bad", "good"); > + res = bisect_replay(&terms, argv[0]); > + free_terms(&terms); > + return res; > +} > + > +static int cmd_bisect__skip(int argc, const char **argv, const char *prefix UNUSED) > +{ > + int res; > + struct bisect_terms terms = { 0 }; > + > + set_terms(&terms, "bad", "good"); > + get_terms(&terms); > + res = bisect_skip(&terms, argv, argc); > + free_terms(&terms); > + return res; > +} > + > +static int cmd_bisect__visualize(int argc, const char **argv, const char *prefix UNUSED) > +{ > + int res; > + struct bisect_terms terms = { 0 }; > + > + get_terms(&terms); > + res = bisect_visualize(&terms, argv, argc); > + free_terms(&terms); > + return res; > +} > + > +static int cmd_bisect__run(int argc, const char **argv, const char *prefix UNUSED) > +{ > + int res; > + struct bisect_terms terms = { 0 }; > + > + if (!argc) > + return error(_("bisect run failed: no command provided.")); > + get_terms(&terms); > + res = bisect_run(&terms, argv, argc); > + free_terms(&terms); > + return res; > +} > + > int cmd_bisect__helper(int argc, const char **argv, const char *prefix) > { > enum { > @@ -1318,8 +1429,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) > N_("use <cmd>... to automatically bisect"), BISECT_RUN), > OPT_END() > }; > - struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL }; > - > argc = parse_options(argc, argv, prefix, options, > git_bisect_helper_usage, > PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN_OPT); > @@ -1329,60 +1438,38 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) > > 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); > + res = cmd_bisect__reset(argc, argv, prefix); > break; > case BISECT_TERMS: > - if (argc > 1) > - return error(_("--bisect-terms requires 0 or 1 argument")); > - res = bisect_terms(&terms, argc == 1 ? argv[0] : NULL); > + res = cmd_bisect__terms(argc, argv, prefix); > break; > case BISECT_START: > - set_terms(&terms, "bad", "good"); > - res = bisect_start(&terms, argv, argc); > + res = cmd_bisect__start(argc, argv, prefix); > break; > case BISECT_NEXT: > - if (argc) > - return error(_("--bisect-next requires 0 arguments")); > - get_terms(&terms); > - res = bisect_next(&terms, prefix); > + res = cmd_bisect__next(argc, argv, prefix); > break; > case BISECT_STATE: > - set_terms(&terms, "bad", "good"); > - get_terms(&terms); > - res = bisect_state(&terms, argv, argc); > + res = cmd_bisect__state(argc, argv, prefix); > break; > case BISECT_LOG: > - if (argc) > - return error(_("--bisect-log requires 0 arguments")); > - res = bisect_log(); > + res = cmd_bisect__log(argc, argv, prefix); > break; > case BISECT_REPLAY: > - if (argc != 1) > - return error(_("no logfile given")); > - set_terms(&terms, "bad", "good"); > - res = bisect_replay(&terms, argv[0]); > + res = cmd_bisect__replay(argc, argv, prefix); > break; > case BISECT_SKIP: > - set_terms(&terms, "bad", "good"); > - get_terms(&terms); > - res = bisect_skip(&terms, argv, argc); > + res = cmd_bisect__skip(argc, argv, prefix); > break; > case BISECT_VISUALIZE: > - get_terms(&terms); > - res = bisect_visualize(&terms, argv, argc); > + res = cmd_bisect__visualize(argc, argv, prefix); > break; > case BISECT_RUN: > - if (!argc) > - return error(_("bisect run failed: no command provided.")); > - get_terms(&terms); > - res = bisect_run(&terms, argv, argc); > + res = cmd_bisect__run(argc, argv, prefix); > break; > default: > BUG("unknown subcommand %d", cmdmode); > } > - free_terms(&terms); > > /* > * Handle early success FWIW I tried my suggestion in an earlier review of factoring this into a function, I don't know if it's worth it, but it is a net reduction in lines. Some of the error messages are changed as a result. If you think the end result looks better, feel free to pick it up / adapt it etc with my Signed-off-by. builtin/bisect--helper.c | 109 +++++++++++++++++++---------------------------- 1 file changed, 43 insertions(+), 66 deletions(-) diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index d4d813ebfce..e5a5261f9f2 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -469,8 +469,11 @@ static int get_terms(struct bisect_terms *terms) return res; } -static int bisect_terms(struct bisect_terms *terms, const char *option) +static int bisect_terms(struct bisect_terms *terms, const char **argv, + int argc) { + const char *option = argc == 1 ? argv[0] : NULL; + if (get_terms(terms)) return error(_("no terms defined")); @@ -1024,7 +1027,7 @@ static int process_replay_line(struct bisect_terms *terms, struct strbuf *line) struct strvec argv = STRVEC_INIT; int res; sq_dequote_to_strvec(rev, &argv); - res = bisect_terms(terms, argv.nr == 1 ? argv.v[0] : NULL); + res = bisect_terms(terms, argv.v, argv.nr); strvec_clear(&argv); return res; } @@ -1033,8 +1036,10 @@ static int process_replay_line(struct bisect_terms *terms, struct strbuf *line) return -1; } -static enum bisect_error bisect_replay(struct bisect_terms *terms, const char *filename) +static int bisect_replay(struct bisect_terms *terms, const char **argv, + int argc) { + const char *filename = argv[0]; FILE *fp = NULL; enum bisect_error res = BISECT_OK; struct strbuf line = STRBUF_INIT; @@ -1279,6 +1284,24 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc) return res; } +typedef int (*cmd_bisect_fn_t)(struct bisect_terms *terms, const char **argv, int argc); +static int terms_cmd(int argc, const char **argv, const char *prefix UNUSED, + cmd_bisect_fn_t fn, int set, int errcond, + const char *errmsg, const char *errcmd) +{ + int res; + struct bisect_terms terms = { 0 }; + + if (errcond) + return error(_(errmsg), errcmd); + if (set) + set_terms(&terms, "bad", "good"); + get_terms(&terms); + res = fn(&terms, argv, argc); + free_terms(&terms); + return res; +} + static int cmd_bisect__reset(int argc, const char **argv, const char *prefix UNUSED) { if (argc > 1) @@ -1286,27 +1309,15 @@ static int cmd_bisect__reset(int argc, const char **argv, const char *prefix UNU return bisect_reset(argc ? argv[0] : NULL); } -static int cmd_bisect__terms(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__terms(int argc, const char **argv, const char *prefix) { - int res; - struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL }; - - if (argc > 1) - return error(_("--bisect-terms requires 0 or 1 argument")); - res = bisect_terms(&terms, argc == 1 ? argv[0] : NULL); - free_terms(&terms); - return res; + return terms_cmd(argc, argv, prefix, bisect_terms, 0, argc > 1, + N_("'bisect %s' requires 0 or 1 argument"), "terms"); } -static int cmd_bisect__start(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__start(int argc, const char **argv, const char *prefix) { - int res; - struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL }; - - set_terms(&terms, "bad", "good"); - res = bisect_start(&terms, argv, argc); - free_terms(&terms); - return res; + return terms_cmd(argc, argv, prefix, bisect_start, 1, 0, NULL, NULL); } static int cmd_bisect__next(int argc, const char **argv UNUSED, const char *prefix) @@ -1322,16 +1333,9 @@ static int cmd_bisect__next(int argc, const char **argv UNUSED, const char *pref return res; } -static int cmd_bisect__state(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__state(int argc, const char **argv, const char *prefix) { - int res; - struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL }; - - set_terms(&terms, "bad", "good"); - get_terms(&terms); - res = bisect_state(&terms, argv, argc); - free_terms(&terms); - return res; + return terms_cmd(argc, argv, prefix, bisect_state, 1, 0, NULL, NULL); } static int cmd_bisect__log(int argc, const char **argv UNUSED, const char *prefix UNUSED) @@ -1341,53 +1345,26 @@ static int cmd_bisect__log(int argc, const char **argv UNUSED, const char *prefi return bisect_log(); } -static int cmd_bisect__replay(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__replay(int argc, const char **argv, const char *prefix) { - int res; - struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL }; - - if (argc != 1) - return error(_("no logfile given")); - set_terms(&terms, "bad", "good"); - res = bisect_replay(&terms, argv[0]); - free_terms(&terms); - return res; + return terms_cmd(argc, argv, prefix, bisect_replay, 1, argc != 1, + N_("'bisect %s': no logfile given"), "replay"); } -static int cmd_bisect__skip(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__skip(int argc, const char **argv, const char *prefix) { - int res; - struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL }; - - set_terms(&terms, "bad", "good"); - get_terms(&terms); - res = bisect_skip(&terms, argv, argc); - free_terms(&terms); - return res; + return terms_cmd(argc, argv, prefix, bisect_skip, 1, 0, NULL, NULL); } -static int cmd_bisect__visualize(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__visualize(int argc, const char **argv, const char *prefix) { - int res; - struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL }; - - get_terms(&terms); - res = bisect_visualize(&terms, argv, argc); - free_terms(&terms); - return res; + return terms_cmd(argc, argv, prefix, bisect_visualize, 0, 0, NULL, NULL); } -static int cmd_bisect__run(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__run(int argc, const char **argv, const char *prefix) { - int res; - struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL }; - - if (!argc) - return error(_("bisect run failed: no command provided.")); - get_terms(&terms); - res = bisect_run(&terms, argv, argc); - free_terms(&terms); - return res; + return terms_cmd(argc, argv, prefix, bisect_run, 0, !argc, + N_("bisect %s failed: no command provided."), "run"); } int cmd_bisect__helper(int argc, const char **argv, const char *prefix)