From d9c07a46aebfc43eeea0db38ba02a4c80f54de20 Mon Sep 17 00:00:00 2001 From: John Cai Date: Tue, 24 Sep 2024 14:44:24 -0400 Subject: [PATCH] parse-options: add subcommand that takes a repository argument The process of migrating away from using the global variable the_repository may involve subcommands that also take a repository argument. Allow this by adding a new function pointer type and enums. Signed-off-by: John Cai --- parse-options.c | 14 ++++++++++---- parse-options.h | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/parse-options.c b/parse-options.c index 30b9e68f8ac85d..7509c893c55f8e 100644 --- a/parse-options.c +++ b/parse-options.c @@ -470,13 +470,19 @@ static enum parse_opt_result parse_nodash_opt(struct parse_opt_ctx_t *p, static enum parse_opt_result parse_subcommand(const char *arg, const struct option *options) { - for (; options->type != OPTION_END; options++) + for (; options->type != OPTION_END; options++) { if (options->type == OPTION_SUBCOMMAND && !strcmp(options->long_name, arg)) { *(parse_opt_subcommand_fn **)options->value = options->subcommand_fn; return PARSE_OPT_SUBCOMMAND; } + if (options->type == OPTION_REPO_SUBCOMMAND && + !strcmp(options->long_name, arg)) { + *(parse_opt_subcommand_repo_fn **)options->value = options->subcommand_repo_fn; + return PARSE_OPT_SUBCOMMAND; + } + } return PARSE_OPT_UNKNOWN; } @@ -575,7 +581,8 @@ static void parse_options_check(const struct option *opts) static int has_subcommands(const struct option *options) { for (; options->type != OPTION_END; options++) - if (options->type == OPTION_SUBCOMMAND) + if (options->type == OPTION_SUBCOMMAND || + options->type == OPTION_REPO_SUBCOMMAND) return 1; return 0; } @@ -598,8 +605,7 @@ static void parse_options_start_1(struct parse_opt_ctx_t *ctx, ctx->flags = flags; ctx->has_subcommands = has_subcommands(options); if (!ctx->has_subcommands && (flags & PARSE_OPT_SUBCOMMAND_OPTIONAL)) - BUG("Using PARSE_OPT_SUBCOMMAND_OPTIONAL without subcommands"); - if (ctx->has_subcommands) { + BUG("Using PARSE_OPT_SUBCOMMAND_OPTIONAL without subcommands"); if (ctx->has_subcommands) { if (flags & PARSE_OPT_STOP_AT_NON_OPTION) BUG("subcommands are incompatible with PARSE_OPT_STOP_AT_NON_OPTION"); if (!(flags & PARSE_OPT_SUBCOMMAND_OPTIONAL)) { diff --git a/parse-options.h b/parse-options.h index ae15342390837c..970427c475b0ca 100644 --- a/parse-options.h +++ b/parse-options.h @@ -2,6 +2,7 @@ #define PARSE_OPTIONS_H #include "gettext.h" +#include "repository.h" /** * Refer to Documentation/technical/api-parse-options.txt for the API doc. @@ -14,6 +15,7 @@ enum parse_opt_type { OPTION_NUMBER, OPTION_ALIAS, OPTION_SUBCOMMAND, + OPTION_REPO_SUBCOMMAND, /* options with no arguments */ OPTION_BIT, OPTION_NEGBIT, @@ -75,6 +77,11 @@ typedef enum parse_opt_result parse_opt_ll_cb(struct parse_opt_ctx_t *ctx, typedef int parse_opt_subcommand_fn(int argc, const char **argv, const char *prefix); +typedef int parse_opt_subcommand_repo_fn(struct repository *repo, + int argc, const char **argv, + const char *prefix); + + /* * `type`:: * holds the type of the option, you must have an OPTION_END last in your @@ -158,6 +165,7 @@ struct option { parse_opt_ll_cb *ll_callback; intptr_t extra; parse_opt_subcommand_fn *subcommand_fn; + parse_opt_subcommand_repo_fn *subcommand_repo_fn; }; #define OPT_BIT_F(s, l, v, h, b, f) { \ @@ -367,6 +375,16 @@ struct option { } #define OPT_SUBCOMMAND(l, v, fn) OPT_SUBCOMMAND_F((l), (v), (fn), 0) +#define OPT_SUBCOMMAND_REPO_F(l, v, repo_fn) { \ + .type = OPTION_REPO_SUBCOMMAND, \ + .long_name = (l), \ + .value = (v), \ + .flags = 0, \ + .subcommand_repo_fn = (repo_fn), \ +} +#define OPT_REPO_SUBCOMMAND(l, v, repo_fn) OPT_SUBCOMMAND_REPO_F((l), (v), (repo_fn)) + + /* * parse_options() will filter out the processed options and leave the * non-option arguments in argv[]. argv0 is assumed program name and