]> asedeno.scripts.mit.edu Git - git.git/blobdiff - parse-options.c
restore legacy behavior for read_sha1_file()
[git.git] / parse-options.c
index 04adf219cace134e2e51440b037b0e8a2622b3f7..469831d21b99e2ea6d5d0be51555d853d68a7682 100644 (file)
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "parse-options.h"
+#include "cache.h"
 
 #define OPT_SHORT 1
 #define OPT_UNSET 2
@@ -94,14 +95,14 @@ static int get_value(struct parse_opt_ctx_t *p,
 
        case OPTION_CALLBACK:
                if (unset)
-                       return (*opt->callback)(opt, NULL, 1);
+                       return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
                if (opt->flags & PARSE_OPT_NOARG)
-                       return (*opt->callback)(opt, NULL, 0);
+                       return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
                if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
-                       return (*opt->callback)(opt, NULL, 0);
+                       return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
                if (!arg)
                        return opterror(opt, "requires a value", flags);
-               return (*opt->callback)(opt, get_arg(p), 0);
+               return (*opt->callback)(opt, get_arg(p), 0) ? (-1) : 0;
 
        case OPTION_INTEGER:
                if (unset) {
@@ -132,7 +133,7 @@ static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *optio
                        return get_value(p, options, OPT_SHORT);
                }
        }
-       return error("unknown switch `%c'", *p->opt);
+       return -2;
 }
 
 static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
@@ -217,7 +218,7 @@ is_abbreviated:
                        abbrev_option->long_name);
        if (abbrev_option)
                return get_value(p, abbrev_option, abbrev_flags);
-       return error("unknown option `%s'", arg);
+       return -2;
 }
 
 void check_typos(const char *arg, const struct option *options)
@@ -247,6 +248,7 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
        ctx->argc = argc - 1;
        ctx->argv = argv + 1;
        ctx->out  = argv;
+       ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
        ctx->flags = flags;
 }
 
@@ -257,6 +259,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                       const struct option *options,
                       const char * const usagestr[])
 {
+       /* we must reset ->opt, unknown short option leave it dangling */
+       ctx->opt = NULL;
+
        for (; ctx->argc; ctx->argc--, ctx->argv++) {
                const char *arg = ctx->argv[0];
 
@@ -271,15 +276,30 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                        ctx->opt = arg + 1;
                        if (*ctx->opt == 'h')
                                return parse_options_usage(usagestr, options);
-                       if (parse_short_opt(ctx, options) < 0)
-                               usage_with_options(usagestr, options);
+                       switch (parse_short_opt(ctx, options)) {
+                       case -1:
+                               return parse_options_usage(usagestr, options);
+                       case -2:
+                               return PARSE_OPT_UNKNOWN;
+                       }
                        if (ctx->opt)
                                check_typos(arg + 1, options);
                        while (ctx->opt) {
                                if (*ctx->opt == 'h')
                                        return parse_options_usage(usagestr, options);
-                               if (parse_short_opt(ctx, options) < 0)
-                                       usage_with_options(usagestr, options);
+                               switch (parse_short_opt(ctx, options)) {
+                               case -1:
+                                       return parse_options_usage(usagestr, options);
+                               case -2:
+                                       /* fake a short option thing to hide the fact that we may have
+                                        * started to parse aggregated stuff
+                                        *
+                                        * This is leaky, too bad.
+                                        */
+                                       ctx->argv[0] = xstrdup(ctx->opt - 1);
+                                       *(char *)ctx->argv[0] = '-';
+                                       return PARSE_OPT_UNKNOWN;
+                               }
                        }
                        continue;
                }
@@ -296,8 +316,12 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                        return usage_with_options_internal(usagestr, options, 1);
                if (!strcmp(arg + 2, "help"))
                        return parse_options_usage(usagestr, options);
-               if (parse_long_opt(ctx, arg + 2, options))
-                       usage_with_options(usagestr, options);
+               switch (parse_long_opt(ctx, arg + 2, options)) {
+               case -1:
+                       return parse_options_usage(usagestr, options);
+               case -2:
+                       return PARSE_OPT_UNKNOWN;
+               }
        }
        return PARSE_OPT_DONE;
 }
@@ -321,7 +345,12 @@ int parse_options(int argc, const char **argv, const struct option *options,
        case PARSE_OPT_DONE:
                break;
        default: /* PARSE_OPT_UNKNOWN */
-               abort(); /* unreached yet */
+               if (ctx.argv[0][1] == '-') {
+                       error("unknown option `%s'", ctx.argv[0] + 2);
+               } else {
+                       error("unknown switch `%c'", *ctx.opt);
+               }
+               usage_with_options(usagestr, options);
        }
 
        return parse_options_end(&ctx);