summaryrefslogtreecommitdiff
path: root/parse-options.c
diff options
context:
space:
mode:
Diffstat (limited to 'parse-options.c')
-rw-r--r--parse-options.c85
1 files changed, 52 insertions, 33 deletions
diff --git a/parse-options.c b/parse-options.c
index b42f54d48b..2abff136a1 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -61,7 +61,7 @@ static enum parse_opt_result opt_command_mode_error(
*/
for (that = all_opts; that->type != OPTION_END; that++) {
if (that == opt ||
- that->type != OPTION_CMDMODE ||
+ !(that->flags & PARSE_OPT_CMDMODE) ||
that->value != opt->value ||
that->defval != *(int *)opt->value)
continue;
@@ -95,6 +95,14 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
if (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))
return error(_("%s takes no value"), optname(opt, flags));
+ /*
+ * Giving the same mode option twice, although unnecessary,
+ * is not a grave error, so let it pass.
+ */
+ if ((opt->flags & PARSE_OPT_CMDMODE) &&
+ *(int *)opt->value && *(int *)opt->value != opt->defval)
+ return opt_command_mode_error(opt, all_opts, flags);
+
switch (opt->type) {
case OPTION_LOWLEVEL_CALLBACK:
return opt->ll_callback(p, opt, NULL, unset);
@@ -130,16 +138,6 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
*(int *)opt->value = unset ? 0 : opt->defval;
return 0;
- case OPTION_CMDMODE:
- /*
- * Giving the same mode option twice, although is unnecessary,
- * is not a grave error, so let it pass.
- */
- if (*(int *)opt->value && *(int *)opt->value != opt->defval)
- return opt_command_mode_error(opt, all_opts, flags);
- *(int *)opt->value = opt->defval;
- return 0;
-
case OPTION_STRING:
if (unset)
*(const char **)opt->value = NULL;
@@ -357,8 +355,7 @@ is_abbreviated:
}
/* negated? */
if (!starts_with(arg, "no-")) {
- if (starts_with(long_name, "no-")) {
- long_name += 3;
+ if (skip_prefix(long_name, "no-", &long_name)) {
opt_flags |= OPT_UNSET;
goto again;
}
@@ -420,7 +417,7 @@ static void check_typos(const char *arg, const struct option *options)
return;
if (starts_with(arg, "no-")) {
- error(_("did you mean `--%s` (with two dashes ?)"), arg);
+ error(_("did you mean `--%s` (with two dashes)?"), arg);
exit(129);
}
@@ -428,7 +425,7 @@ static void check_typos(const char *arg, const struct option *options)
if (!options->long_name)
continue;
if (starts_with(options->long_name, arg)) {
- error(_("did you mean `--%s` (with two dashes ?)"), arg);
+ error(_("did you mean `--%s` (with two dashes)?"), arg);
exit(129);
}
}
@@ -528,7 +525,8 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
parse_options_start_1(ctx, argc, argv, prefix, options, flags);
}
-static void show_negated_gitcomp(const struct option *opts, int nr_noopts)
+static void show_negated_gitcomp(const struct option *opts, int show_all,
+ int nr_noopts)
{
int printed_dashdash = 0;
@@ -538,7 +536,8 @@ static void show_negated_gitcomp(const struct option *opts, int nr_noopts)
if (!opts->long_name)
continue;
- if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE))
+ if (!show_all &&
+ (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE)))
continue;
if (opts->flags & PARSE_OPT_NONEG)
continue;
@@ -575,7 +574,7 @@ static void show_negated_gitcomp(const struct option *opts, int nr_noopts)
}
}
-static int show_gitcomp(const struct option *opts)
+static int show_gitcomp(const struct option *opts, int show_all)
{
const struct option *original_opts = opts;
int nr_noopts = 0;
@@ -585,7 +584,8 @@ static int show_gitcomp(const struct option *opts)
if (!opts->long_name)
continue;
- if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE))
+ if (!show_all &&
+ (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE | PARSE_OPT_FROM_ALIAS)))
continue;
switch (opts->type) {
@@ -613,8 +613,8 @@ static int show_gitcomp(const struct option *opts)
nr_noopts++;
printf(" --%s%s", opts->long_name, suffix);
}
- show_negated_gitcomp(original_opts, -1);
- show_negated_gitcomp(original_opts, nr_noopts);
+ show_negated_gitcomp(original_opts, show_all, -1);
+ show_negated_gitcomp(original_opts, show_all, nr_noopts);
fputc('\n', stdout);
return PARSE_OPT_COMPLETE;
}
@@ -623,8 +623,10 @@ static int show_gitcomp(const struct option *opts)
* Scan and may produce a new option[] array, which should be used
* instead of the original 'options'.
*
- * Right now this is only used to preprocess and substitue
+ * Right now this is only used to preprocess and substitute
* OPTION_ALIAS.
+ *
+ * The returned options should be freed using free_preprocessed_options.
*/
static struct option *preprocess_options(struct parse_opt_ctx_t *ctx,
const struct option *options)
@@ -651,6 +653,7 @@ static struct option *preprocess_options(struct parse_opt_ctx_t *ctx,
int short_name;
const char *long_name;
const char *source;
+ struct strbuf help = STRBUF_INIT;
int j;
if (newopt[i].type != OPTION_ALIAS)
@@ -662,6 +665,7 @@ static struct option *preprocess_options(struct parse_opt_ctx_t *ctx,
if (!long_name)
BUG("An alias must have long option name");
+ strbuf_addf(&help, _("alias of --%s"), source);
for (j = 0; j < nr; j++) {
const char *name = options[j].long_name;
@@ -672,15 +676,11 @@ static struct option *preprocess_options(struct parse_opt_ctx_t *ctx,
if (options[j].type == OPTION_ALIAS)
BUG("No please. Nested aliases are not supported.");
- /*
- * NEEDSWORK: this is a bit inconsistent because
- * usage_with_options() on the original options[] will print
- * help string as "alias of %s" but "git cmd -h" will
- * print the original help string.
- */
memcpy(newopt + i, options + j, sizeof(*newopt));
newopt[i].short_name = short_name;
newopt[i].long_name = long_name;
+ newopt[i].help = strbuf_detach(&help, NULL);
+ newopt[i].flags |= PARSE_OPT_FROM_ALIAS;
break;
}
@@ -696,6 +696,20 @@ static struct option *preprocess_options(struct parse_opt_ctx_t *ctx,
return newopt;
}
+static void free_preprocessed_options(struct option *options)
+{
+ int i;
+
+ if (!options)
+ return;
+
+ for (i = 0; options[i].type != OPTION_END; i++) {
+ if (options[i].flags & PARSE_OPT_FROM_ALIAS)
+ free((void *)options[i].help);
+ }
+ free(options);
+}
+
static int usage_with_options_internal(struct parse_opt_ctx_t *,
const char * const *,
const struct option *, int, int);
@@ -729,9 +743,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h"))
goto show_usage;
- /* lone --git-completion-helper is asked by git-completion.bash */
- if (ctx->total == 1 && !strcmp(arg + 1, "-git-completion-helper"))
- return show_gitcomp(options);
+ /*
+ * lone --git-completion-helper and --git-completion-helper-all
+ * are asked by git-completion.bash
+ */
+ if (ctx->total == 1 && !strcmp(arg, "--git-completion-helper"))
+ return show_gitcomp(options, 0);
+ if (ctx->total == 1 && !strcmp(arg, "--git-completion-helper-all"))
+ return show_gitcomp(options, 1);
if (arg[1] != '-') {
ctx->opt = arg + 1;
@@ -867,8 +886,8 @@ int parse_options(int argc, const char **argv, const char *prefix,
usage_with_options(usagestr, options);
}
- precompose_argv(argc, argv);
- free(real_options);
+ precompose_argv_prefix(argc, argv, NULL);
+ free_preprocessed_options(real_options);
free(ctx.alias_groups);
return parse_options_end(&ctx);
}