#include "git-compat-util.h"
#include "parse-options.h"
#include "cache.h"
+#include "config.h"
#include "commit.h"
#include "color.h"
#include "utf8.h"
-static int parse_options_usage(struct parse_opt_ctx_t *ctx,
- const char * const *usagestr,
- const struct option *opts, int err);
-
#define OPT_SHORT 1
#define OPT_UNSET 2
if (!file || !*file || !prefix || is_absolute_path(*file)
|| !strcmp("-", *file))
return;
- *file = xstrdup(prefix_filename(prefix, strlen(prefix), *file));
+ *file = prefix_filename(prefix, *file);
}
static int opt_command_mode_error(const struct option *opt,
return 0;
case OPTION_COUNTUP:
+ if (*(int *)opt->value < 0)
+ *(int *)opt->value = 0;
*(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
return 0;
return get_value(p, options, all_opts, flags ^ opt_flags);
}
- if (ambiguous_option)
- return error("Ambiguous option: %s "
+ if (ambiguous_option) {
+ error("Ambiguous option: %s "
"(could be --%s%s or --%s%s)",
arg,
(ambiguous_flags & OPT_UNSET) ? "no-" : "",
ambiguous_option->long_name,
(abbrev_flags & OPT_UNSET) ? "no-" : "",
abbrev_option->long_name);
+ return -3;
+ }
if (abbrev_option)
return get_value(p, abbrev_option, all_opts, abbrev_flags);
return -2;
const struct option *options, int flags)
{
memset(ctx, 0, sizeof(*ctx));
- ctx->argc = argc - 1;
+ ctx->argc = ctx->total = argc - 1;
ctx->argv = argv + 1;
ctx->out = argv;
ctx->prefix = prefix;
continue;
}
+ /* lone -h asks for help */
+ if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h"))
+ goto show_usage;
+
if (arg[1] != '-') {
ctx->opt = arg + 1;
- if (internal_help && *ctx->opt == 'h')
- return parse_options_usage(ctx, usagestr, options, 0);
switch (parse_short_opt(ctx, options)) {
case -1:
- return parse_options_usage(ctx, usagestr, options, 1);
+ return PARSE_OPT_ERROR;
case -2:
if (ctx->opt)
check_typos(arg + 1, options);
+ if (internal_help && *ctx->opt == 'h')
+ goto show_usage;
goto unknown;
}
if (ctx->opt)
check_typos(arg + 1, options);
while (ctx->opt) {
- if (internal_help && *ctx->opt == 'h')
- return parse_options_usage(ctx, usagestr, options, 0);
switch (parse_short_opt(ctx, options)) {
case -1:
- return parse_options_usage(ctx, usagestr, options, 1);
+ return PARSE_OPT_ERROR;
case -2:
+ if (internal_help && *ctx->opt == 'h')
+ goto show_usage;
+
/* fake a short option thing to hide the fact that we may have
* started to parse aggregated stuff
*
if (internal_help && !strcmp(arg + 2, "help-all"))
return usage_with_options_internal(ctx, usagestr, options, 1, 0);
if (internal_help && !strcmp(arg + 2, "help"))
- return parse_options_usage(ctx, usagestr, options, 0);
+ goto show_usage;
switch (parse_long_opt(ctx, arg + 2, options)) {
case -1:
- return parse_options_usage(ctx, usagestr, options, 1);
+ return PARSE_OPT_ERROR;
case -2:
goto unknown;
+ case -3:
+ goto show_usage;
}
continue;
unknown:
ctx->opt = NULL;
}
return PARSE_OPT_DONE;
+
+ show_usage:
+ return usage_with_options_internal(ctx, usagestr, options, 0, 0);
}
int parse_options_end(struct parse_opt_ctx_t *ctx)
parse_options_start(&ctx, argc, argv, prefix, options, flags);
switch (parse_options_step(&ctx, options, usagestr)) {
case PARSE_OPT_HELP:
+ case PARSE_OPT_ERROR:
exit(129);
case PARSE_OPT_NON_OPTION:
case PARSE_OPT_DONE:
const struct option *opts, int full, int err)
{
FILE *outfile = err ? stderr : stdout;
+ int need_newline;
if (!usagestr)
return PARSE_OPT_HELP;
fprintf_ln(outfile, _("usage: %s"), _(*usagestr++));
while (*usagestr && **usagestr)
- /* TRANSLATORS: the colon here should align with the
- one in "usage: %s" translation */
+ /*
+ * TRANSLATORS: the colon here should align with the
+ * one in "usage: %s" translation.
+ */
fprintf_ln(outfile, _(" or: %s"), _(*usagestr++));
while (*usagestr) {
if (**usagestr)
fprintf_ln(outfile, _(" %s"), _(*usagestr));
else
- putchar('\n');
+ fputc('\n', outfile);
usagestr++;
}
- if (opts->type != OPTION_GROUP)
- fputc('\n', outfile);
+ need_newline = 1;
for (; opts->type != OPTION_END; opts++) {
size_t pos;
if (opts->type == OPTION_GROUP) {
fputc('\n', outfile);
+ need_newline = 0;
if (*opts->help)
fprintf(outfile, "%s\n", _(opts->help));
continue;
if (!full && (opts->flags & PARSE_OPT_HIDDEN))
continue;
+ if (need_newline) {
+ fputc('\n', outfile);
+ need_newline = 0;
+ }
+
pos = fprintf(outfile, " ");
if (opts->short_name) {
if (opts->flags & PARSE_OPT_NODASH)
const char * const *usagestr,
const struct option *options)
{
- fprintf(stderr, "%s\n\n", msg);
+ fprintf(stderr, "fatal: %s\n\n", msg);
usage_with_options(usagestr, options);
}
-static int parse_options_usage(struct parse_opt_ctx_t *ctx,
- const char * const *usagestr,
- const struct option *opts, int err)
-{
- return usage_with_options_internal(ctx, usagestr, opts, 0, err);
-}
-
#undef opterror
int opterror(const struct option *opt, const char *reason, int flags)
{