Add the configuration option skipFetchAll
[gitweb.git] / parse-options.c
index c52b8ccf59a4848be6f3f810e01029f7c6625c78..f5594114ede8a50090c8b97987b52a660235fa56 100644 (file)
@@ -31,11 +31,20 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
        return 0;
 }
 
+static void fix_filename(const char *prefix, const char **file)
+{
+       if (!file || !*file || !prefix || is_absolute_path(*file)
+           || !strcmp("-", *file))
+               return;
+       *file = xstrdup(prefix_filename(prefix, strlen(prefix), *file));
+}
+
 static int get_value(struct parse_opt_ctx_t *p,
                     const struct option *opt, int flags)
 {
        const char *s, *arg;
        const int unset = flags & OPT_UNSET;
+       int err;
 
        if (unset && p->opt)
                return opterror(opt, "takes no value", flags);
@@ -95,6 +104,19 @@ static int get_value(struct parse_opt_ctx_t *p,
                        return get_arg(p, opt, flags, (const char **)opt->value);
                return 0;
 
+       case OPTION_FILENAME:
+               err = 0;
+               if (unset)
+                       *(const char **)opt->value = NULL;
+               else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+                       *(const char **)opt->value = (const char *)opt->defval;
+               else
+                       err = get_arg(p, opt, flags, (const char **)opt->value);
+
+               if (!err)
+                       fix_filename(p->prefix, (const char **)opt->value);
+               return err;
+
        case OPTION_CALLBACK:
                if (unset)
                        return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
@@ -208,6 +230,9 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
                                abbrev_flags = flags;
                                continue;
                        }
+                       /* negation allowed? */
+                       if (options->flags & PARSE_OPT_NONEG)
+                               continue;
                        /* negated and abbreviated very much? */
                        if (!prefixcmp("no-", arg)) {
                                flags |= OPT_UNSET;
@@ -284,13 +309,37 @@ static void check_typos(const char *arg, const struct option *options)
        }
 }
 
+static void parse_options_check(const struct option *opts)
+{
+       int err = 0;
+
+       for (; opts->type != OPTION_END; opts++) {
+               if ((opts->flags & PARSE_OPT_LASTARG_DEFAULT) &&
+                   (opts->flags & PARSE_OPT_OPTARG)) {
+                       if (opts->long_name) {
+                               error("`--%s` uses incompatible flags "
+                                     "LASTARG_DEFAULT and OPTARG", opts->long_name);
+                       } else {
+                               error("`-%c` uses incompatible flags "
+                                     "LASTARG_DEFAULT and OPTARG", opts->short_name);
+                       }
+                       err |= 1;
+               }
+       }
+
+       if (err)
+               exit(129);
+}
+
 void parse_options_start(struct parse_opt_ctx_t *ctx,
-                        int argc, const char **argv, int flags)
+                        int argc, const char **argv, const char *prefix,
+                        int flags)
 {
        memset(ctx, 0, sizeof(*ctx));
        ctx->argc = argc - 1;
        ctx->argv = argv + 1;
        ctx->out  = argv;
+       ctx->prefix = prefix;
        ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
        ctx->flags = flags;
        if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
@@ -307,6 +356,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
 {
        int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
 
+       parse_options_check(options);
+
        /* we must reset ->opt, unknown short option leave it dangling */
        ctx->opt = NULL;
 
@@ -389,12 +440,13 @@ int parse_options_end(struct parse_opt_ctx_t *ctx)
        return ctx->cpidx + ctx->argc;
 }
 
-int parse_options(int argc, const char **argv, const struct option *options,
-                 const char * const usagestr[], int flags)
+int parse_options(int argc, const char **argv, const char *prefix,
+                 const struct option *options, const char * const usagestr[],
+                 int flags)
 {
        struct parse_opt_ctx_t ctx;
 
-       parse_options_start(&ctx, argc, argv, flags);
+       parse_options_start(&ctx, argc, argv, prefix, flags);
        switch (parse_options_step(&ctx, options, usagestr)) {
        case PARSE_OPT_HELP:
                exit(129);
@@ -412,10 +464,24 @@ int parse_options(int argc, const char **argv, const struct option *options,
        return parse_options_end(&ctx);
 }
 
+static int usage_argh(const struct option *opts)
+{
+       const char *s;
+       int literal = (opts->flags & PARSE_OPT_LITERAL_ARGHELP) || !opts->argh;
+       if (opts->flags & PARSE_OPT_OPTARG)
+               if (opts->long_name)
+                       s = literal ? "[=%s]" : "[=<%s>]";
+               else
+                       s = literal ? "[%s]" : "[<%s>]";
+       else
+               s = literal ? " %s" : " <%s>";
+       return fprintf(stderr, s, opts->argh ? opts->argh : "...");
+}
+
 #define USAGE_OPTS_WIDTH 24
 #define USAGE_GAP         2
 
-int usage_with_options_internal(const char * const *usagestr,
+static int usage_with_options_internal(const char * const *usagestr,
                                const struct option *opts, int full)
 {
        if (!usagestr)
@@ -448,7 +514,7 @@ int usage_with_options_internal(const char * const *usagestr,
                        continue;
 
                pos = fprintf(stderr, "    ");
-               if (opts->short_name) {
+               if (opts->short_name && !(opts->flags & PARSE_OPT_NEGHELP)) {
                        if (opts->flags & PARSE_OPT_NODASH)
                                pos += fprintf(stderr, "%c", opts->short_name);
                        else
@@ -457,48 +523,14 @@ int usage_with_options_internal(const char * const *usagestr,
                if (opts->long_name && opts->short_name)
                        pos += fprintf(stderr, ", ");
                if (opts->long_name)
-                       pos += fprintf(stderr, "--%s", opts->long_name);
+                       pos += fprintf(stderr, "--%s%s",
+                               (opts->flags & PARSE_OPT_NEGHELP) ?  "no-" : "",
+                               opts->long_name);
                if (opts->type == OPTION_NUMBER)
                        pos += fprintf(stderr, "-NUM");
 
-               switch (opts->type) {
-               case OPTION_ARGUMENT:
-                       break;
-               case OPTION_INTEGER:
-                       if (opts->flags & PARSE_OPT_OPTARG)
-                               if (opts->long_name)
-                                       pos += fprintf(stderr, "[=<n>]");
-                               else
-                                       pos += fprintf(stderr, "[<n>]");
-                       else
-                               pos += fprintf(stderr, " <n>");
-                       break;
-               case OPTION_CALLBACK:
-                       if (opts->flags & PARSE_OPT_NOARG)
-                               break;
-                       /* FALLTHROUGH */
-               case OPTION_STRING:
-                       if (opts->argh) {
-                               if (opts->flags & PARSE_OPT_OPTARG)
-                                       if (opts->long_name)
-                                               pos += fprintf(stderr, "[=<%s>]", opts->argh);
-                                       else
-                                               pos += fprintf(stderr, "[<%s>]", opts->argh);
-                               else
-                                       pos += fprintf(stderr, " <%s>", opts->argh);
-                       } else {
-                               if (opts->flags & PARSE_OPT_OPTARG)
-                                       if (opts->long_name)
-                                               pos += fprintf(stderr, "[=...]");
-                                       else
-                                               pos += fprintf(stderr, "[...]");
-                               else
-                                       pos += fprintf(stderr, " ...");
-                       }
-                       break;
-               default: /* OPTION_{BIT,BOOLEAN,NUMBER,SET_INT,SET_PTR} */
-                       break;
-               }
+               if (!(opts->flags & PARSE_OPT_NOARG))
+                       pos += usage_argh(opts);
 
                if (pos <= USAGE_OPTS_WIDTH)
                        pad = USAGE_OPTS_WIDTH - pos;
@@ -520,6 +552,14 @@ void usage_with_options(const char * const *usagestr,
        exit(129);
 }
 
+void usage_msg_opt(const char *msg,
+                  const char * const *usagestr,
+                  const struct option *options)
+{
+       fprintf(stderr, "%s\n\n", msg);
+       usage_with_options(usagestr, options);
+}
+
 int parse_options_usage(const char * const *usagestr,
                        const struct option *opts)
 {
@@ -593,15 +633,3 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
        commit_list_insert(commit, opt->value);
        return 0;
 }
-
-/*
- * This should really be OPTION_FILENAME type as a part of
- * parse_options that take prefix to do this while parsing.
- */
-extern const char *parse_options_fix_filename(const char *prefix, const char *file)
-{
-       if (!file || !prefix || is_absolute_path(file) || !strcmp("-", file))
-               return file;
-       return prefix_filename(prefix, strlen(prefix), file);
-}
-