From fce56648056acf476aa810a02c6eb33cbcabb6c9 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2018 01:38:39 -0500 Subject: am: handle --no-patch-format option Running "git am --no-patch-format" will currently segfault, since it tries to parse a NULL argument. Instead, let's have it cancel any previous --patch-format option. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/am.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/am.c b/builtin/am.c index 3ee9a9d2a9..dcb880b699 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -2165,7 +2165,9 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int { int *opt_value = opt->value; - if (!strcmp(arg, "mbox")) + if (unset) + *opt_value = PATCH_FORMAT_UNKNOWN; + else if (!strcmp(arg, "mbox")) *opt_value = PATCH_FORMAT_MBOX; else if (!strcmp(arg, "stgit")) *opt_value = PATCH_FORMAT_STGIT; -- cgit v1.2.3 From ccf659e87c8fdb4edb5d2653c53bc9062c8eee76 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2018 01:39:20 -0500 Subject: ls-files: mark exclude options as NONEG Running "git ls-files --no-exclude" will currently segfault, as its option callback does not handle the "unset" parameter. In theory this could be used to clear the exclude list, but it is not clear how that would interact with the other exclude options, nor is the current code capable of clearing the list. Let's just disable the broken option. Note that --no-exclude-from will similarly segfault, but --no-exclude-standard will not. It just silently does the wrong thing (pretending as if --exclude-standard was specified). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/ls-files.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'builtin') diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 7f9919a362..2787453eb1 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -548,15 +548,16 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) N_("show resolve-undo information")), { OPTION_CALLBACK, 'x', "exclude", &exclude_list, N_("pattern"), N_("skip files matching pattern"), - 0, option_parse_exclude }, + PARSE_OPT_NONEG, option_parse_exclude }, { OPTION_CALLBACK, 'X', "exclude-from", &dir, N_("file"), N_("exclude patterns are read from "), - 0, option_parse_exclude_from }, + PARSE_OPT_NONEG, option_parse_exclude_from }, OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, N_("file"), N_("read additional per-directory exclude patterns in ")), { OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL, N_("add the standard git exclusions"), - PARSE_OPT_NOARG, option_parse_exclude_standard }, + PARSE_OPT_NOARG | PARSE_OPT_NONEG, + option_parse_exclude_standard }, OPT_SET_INT_F(0, "full-name", &prefix_len, N_("make the output relative to the project top directory"), 0, PARSE_OPT_NONEG), -- cgit v1.2.3 From f53c163bcd7ae9bf83aa87be81dc6a4661924f3e Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2018 01:39:38 -0500 Subject: pack-objects: mark index-version option as NONEG Running "git pack-objects --no-index-version" will segfault, since the callback is not prepared to handle the "unset" flag. In theory this might be used to counteract an earlier "--index-version", or override a pack.indexversion config setting. But the semantics aren't immediately obvious, and it's unlikely anybody wants this. Let's just disable the broken option for now. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/pack-objects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index e50c6cd1ff..4eac2f997b 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -3252,7 +3252,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) N_("similar to --all-progress when progress meter is shown")), { OPTION_CALLBACK, 0, "index-version", NULL, N_("[,]"), N_("write the pack index file in the specified idx format version"), - 0, option_parse_index_version }, + PARSE_OPT_NONEG, option_parse_index_version }, OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit, N_("maximum size of each output pack file")), OPT_BOOL(0, "local", &local, -- cgit v1.2.3 From 0ad1efb4b379b4d47166c04b3103c6ead3a79673 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2018 01:40:10 -0500 Subject: cat-file: mark batch options with NONEG Running "cat-file --no-batch" will behave as if "--batch" was given, since the option callback does not handle the "unset" flag (likewise for "--no-batch-check"). In theory this might be used to cancel an earlier --batch, but it's not immediately obvious how that would interact with --batch-check. Let's just disallow the negated form of both options. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/cat-file.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'builtin') diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 8d97c84725..4a5289079c 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -631,10 +631,12 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "buffer", &batch.buffer_output, N_("buffer --batch output")), { OPTION_CALLBACK, 0, "batch", &batch, "format", N_("show info and content of objects fed from the standard input"), - PARSE_OPT_OPTARG, batch_option_callback }, + PARSE_OPT_OPTARG | PARSE_OPT_NONEG, + batch_option_callback }, { OPTION_CALLBACK, 0, "batch-check", &batch, "format", N_("show info about objects fed from the standard input"), - PARSE_OPT_OPTARG, batch_option_callback }, + PARSE_OPT_OPTARG | PARSE_OPT_NONEG, + batch_option_callback }, OPT_BOOL(0, "follow-symlinks", &batch.follow_symlinks, N_("follow in-tree symlinks (used with --batch or --batch-check)")), OPT_BOOL(0, "batch-all-objects", &batch.all_objects, -- cgit v1.2.3 From d6627fb8999ac7275c1eeb42482dabd4fabfbd61 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2018 01:40:53 -0500 Subject: status: mark --find-renames option with NONEG If you run "git status --no-find-renames", it will behave the same as "--find-renames", because we ignore the "unset" parameter (we see a NULL "arg", but since the score argument is optional, we just think that the user did not provide a score). We already have a separate "--no-renames" to disable renames, so there's not much point in supporting "--no-find-renames". Let's just flag it as an error. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/commit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/commit.c b/builtin/commit.c index 074bd9a551..4d7754ca43 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1335,7 +1335,7 @@ int cmd_status(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "no-renames", &no_renames, N_("do not detect renames")), { OPTION_CALLBACK, 'M', "find-renames", &rename_score_arg, N_("n"), N_("detect renames, optionally set similarity index"), - PARSE_OPT_OPTARG, opt_parse_rename_score }, + PARSE_OPT_OPTARG | PARSE_OPT_NONEG, opt_parse_rename_score }, OPT_END(), }; -- cgit v1.2.3 From 964fd83b12cbf7907f0bdb4671a467fe381487d3 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2018 01:41:12 -0500 Subject: format-patch: mark "--no-numbered" option with NONEG We have separate parse-options entries for "numbered" and "no-numbered", which means that we accept "--no-no-numbered". It does not behave sensibly, though (it ignores the "unset" flag and acts like "--no-numbered"). We could fix that, but obviously this is silly and unintentional. Let's just disallow it. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/log.c b/builtin/log.c index 061d4fd864..41188e723c 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1508,7 +1508,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) PARSE_OPT_NOARG, numbered_callback }, { OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL, N_("use [PATCH] even with multiple patches"), - PARSE_OPT_NOARG, no_numbered_callback }, + PARSE_OPT_NOARG | PARSE_OPT_NONEG, no_numbered_callback }, OPT_BOOL('s', "signoff", &do_signoff, N_("add Signed-off-by:")), OPT_BOOL(0, "stdout", &use_stdout, N_("print patches to standard out")), -- cgit v1.2.3 From 403d2ba52cb63d4bf5a8baf5480efc538f405c09 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2018 01:42:40 -0500 Subject: show-branch: mark --reflog option as NONEG Running "git show-branch --no-reflog" will behave as if "--reflog" was given with no options, which makes no sense. In theory this option might be used to cancel an earlier "--reflog" option, but the semantics are not clear. Let's punt on it and just disallow the broken option. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/show-branch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 65f4a4c83c..b1b540f7f6 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -674,7 +674,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) { OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("[,]"), N_("show most recent ref-log entries starting at " "base"), - PARSE_OPT_OPTARG, + PARSE_OPT_OPTARG | PARSE_OPT_NONEG, parse_reflog_param }, OPT_END() }; -- cgit v1.2.3 From 1f5db32d89b62317cf59486d14e8b2d4d004cd1e Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2018 01:43:12 -0500 Subject: tag: mark "--message" option with NONEG We do not allow "--no-message" to work now, as the option callback returns "-1" when it sees a NULL arg. However, that will cause parse-options to exit(129) without printing anything further, leaving the user confused about what happened. Instead, let's explicitly mark it as PARSE_OPT_NONEG, which will give a useful error message (and print the usual -h output). In theory this could be used to override an earlier "-m", but it's not clear how it would interact with other message options (e.g., would it also clear data read for "-F"?). Since it's already disabled and nobody is asking for it, let's punt on that and just improve the error message. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/tag.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'builtin') diff --git a/builtin/tag.c b/builtin/tag.c index f623632186..6a396a5090 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -390,8 +390,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix) OPT_GROUP(N_("Tag creation options")), OPT_BOOL('a', "annotate", &annotate, N_("annotated tag, needs a message")), - OPT_CALLBACK('m', "message", &msg, N_("message"), - N_("tag message"), parse_msg_arg), + { OPTION_CALLBACK, 'm', "message", &msg, N_("message"), + N_("tag message"), PARSE_OPT_NONEG, parse_msg_arg }, OPT_FILENAME('F', "file", &msgfile, N_("read message from file")), OPT_BOOL('e', "edit", &edit_flag, N_("force edit of tag message")), OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")), -- cgit v1.2.3 From 0eb8d3767c8f5c87f3bdcbbf9d3d5f73c39422d9 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2018 01:43:44 -0500 Subject: cat-file: report an error on multiple --batch options The options callback for --batch and --batch-check detects when the two mutually incompatible options are used. But it simply returns an error code to parse-options, meaning the program will quit without any kind of message to the user. Instead, let's use error() to print something and return -1. Note that this flips the error return from 1 to -1, but negative values are more idiomatic here (and parse-options treats them the same). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/cat-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 4a5289079c..0f6b692df6 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -596,7 +596,7 @@ static int batch_option_callback(const struct option *opt, struct batch_options *bo = opt->value; if (bo->enabled) { - return 1; + return error(_("only one batch option may be specified")); } bo->enabled = 1; -- cgit v1.2.3 From 517fe807d6903c629a739b23fe0e75b892096998 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2018 01:45:42 -0500 Subject: assert NOARG/NONEG behavior of parse-options callbacks When we define a parse-options callback, the flags we put in the option struct must match what the callback expects. For example, a callback which does not handle the "unset" parameter should only be used with PARSE_OPT_NONEG. But since the callback and the option struct are not defined next to each other, it's easy to get this wrong (as earlier patches in this series show). Fortunately, the compiler can help us here: compiling with -Wunused-parameters can show us which callbacks ignore their "unset" parameters (and likewise, ones that ignore "arg" expect to be triggered with PARSE_OPT_NOARG). But after we've inspected a callback and determined that all of its callers use the right flags, what do we do next? We'd like to silence the compiler warning, but do so in a way that will catch any wrong calls in the future. We can do that by actually checking those variables and asserting that they match our expectations. Because this is such a common pattern, we'll introduce some helper macros. The resulting messages aren't as descriptive as we could make them, but the file/line information from BUG() is enough to identify the problem (and anyway, the point is that these should never be seen). Each of the annotated callbacks in this patch triggers -Wunused-parameters, and was manually inspected to make sure all callers use the correct options (so none of these BUGs should be triggerable). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/blame.c | 4 ++++ builtin/cat-file.c | 2 ++ builtin/checkout-index.c | 2 ++ builtin/clean.c | 1 + builtin/commit.c | 3 +++ builtin/fetch.c | 2 ++ builtin/grep.c | 14 +++++++++++++- builtin/init-db.c | 1 + builtin/interpret-trailers.c | 2 ++ builtin/log.c | 10 ++++++++++ builtin/ls-files.c | 7 +++++++ builtin/merge-file.c | 2 ++ builtin/merge.c | 1 + builtin/notes.c | 7 +++++++ builtin/pack-objects.c | 3 +++ builtin/read-tree.c | 3 +++ builtin/rebase.c | 6 ++++++ builtin/show-branch.c | 1 + builtin/show-ref.c | 1 + builtin/tag.c | 2 ++ builtin/update-index.c | 21 +++++++++++++++++++-- 21 files changed, 92 insertions(+), 3 deletions(-) (limited to 'builtin') diff --git a/builtin/blame.c b/builtin/blame.c index a443af9ee9..06a7163ffe 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -732,6 +732,8 @@ static int blame_copy_callback(const struct option *option, const char *arg, int { int *opt = option->value; + BUG_ON_OPT_NEG(unset); + /* * -C enables copy from removed files; * -C -C enables copy from existing files, but only @@ -754,6 +756,8 @@ static int blame_move_callback(const struct option *option, const char *arg, int { int *opt = option->value; + BUG_ON_OPT_NEG(unset); + *opt |= PICKAXE_BLAME_MOVE; if (arg) diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 0f6b692df6..1cdd357d52 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -595,6 +595,8 @@ static int batch_option_callback(const struct option *opt, { struct batch_options *bo = opt->value; + BUG_ON_OPT_NEG(unset); + if (bo->enabled) { return error(_("only one batch option may be specified")); } diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index 88b86c8d9f..eb74774cbc 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -132,6 +132,8 @@ static const char * const builtin_checkout_index_usage[] = { static int option_parse_stage(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); + if (!strcmp(arg, "all")) { to_tempfile = 1; checkout_stage = CHECKOUT_ALL; diff --git a/builtin/clean.c b/builtin/clean.c index 8d9a7dc206..bbcdeb2d9e 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -140,6 +140,7 @@ static void clean_print_color(enum color_clean ix) static int exclude_cb(const struct option *opt, const char *arg, int unset) { struct string_list *exclude_list = opt->value; + BUG_ON_OPT_NEG(unset); string_list_append(exclude_list, arg); return 0; } diff --git a/builtin/commit.c b/builtin/commit.c index 4d7754ca43..500f793fa6 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -161,6 +161,9 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset) static int opt_parse_rename_score(const struct option *opt, const char *arg, int unset) { const char **value = opt->value; + + BUG_ON_OPT_NEG(unset); + if (arg != NULL && *arg == '=') arg = arg + 1; diff --git a/builtin/fetch.c b/builtin/fetch.c index 8f7249f2b1..354ed8bdef 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -98,6 +98,8 @@ static int git_fetch_config(const char *k, const char *v, void *cb) static int parse_refmap_arg(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); + /* * "git fetch --refmap='' origin foo" * can be used to tell the command not to store anywhere diff --git a/builtin/grep.c b/builtin/grep.c index d8508ddf79..33c8b61595 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -712,11 +712,14 @@ static int context_callback(const struct option *opt, const char *arg, static int file_callback(const struct option *opt, const char *arg, int unset) { struct grep_opt *grep_opt = opt->value; - int from_stdin = !strcmp(arg, "-"); + int from_stdin; FILE *patterns; int lno = 0; struct strbuf sb = STRBUF_INIT; + BUG_ON_OPT_NEG(unset); + + from_stdin = !strcmp(arg, "-"); patterns = from_stdin ? stdin : fopen(arg, "r"); if (!patterns) die_errno(_("cannot open '%s'"), arg); @@ -737,6 +740,8 @@ static int file_callback(const struct option *opt, const char *arg, int unset) static int not_callback(const struct option *opt, const char *arg, int unset) { struct grep_opt *grep_opt = opt->value; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT); return 0; } @@ -744,6 +749,8 @@ static int not_callback(const struct option *opt, const char *arg, int unset) static int and_callback(const struct option *opt, const char *arg, int unset) { struct grep_opt *grep_opt = opt->value; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND); return 0; } @@ -751,6 +758,8 @@ static int and_callback(const struct option *opt, const char *arg, int unset) static int open_callback(const struct option *opt, const char *arg, int unset) { struct grep_opt *grep_opt = opt->value; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN); return 0; } @@ -758,6 +767,8 @@ static int open_callback(const struct option *opt, const char *arg, int unset) static int close_callback(const struct option *opt, const char *arg, int unset) { struct grep_opt *grep_opt = opt->value; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN); return 0; } @@ -766,6 +777,7 @@ static int pattern_callback(const struct option *opt, const char *arg, int unset) { struct grep_opt *grep_opt = opt->value; + BUG_ON_OPT_NEG(unset); append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN); return 0; } diff --git a/builtin/init-db.c b/builtin/init-db.c index 12ddda7e7b..41faffd28d 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -451,6 +451,7 @@ static int guess_repository_type(const char *git_dir) static int shared_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); *((int *) opt->value) = (arg) ? git_config_perm("arg", arg) : PERM_GROUP; return 0; } diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 4b87e0dd2e..8ae40dec47 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -80,6 +80,8 @@ static int parse_opt_parse(const struct option *opt, const char *arg, v->only_trailers = 1; v->only_input = 1; v->unfold = 1; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); return 0; } diff --git a/builtin/log.c b/builtin/log.c index 41188e723c..9f2d987294 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -107,6 +107,8 @@ static int log_line_range_callback(const struct option *option, const char *arg, { struct line_opt_callback_data *data = option->value; + BUG_ON_OPT_NEG(unset); + if (!arg) return -1; @@ -1151,6 +1153,8 @@ static int keep_subject = 0; static int keep_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); ((struct rev_info *)opt->value)->total = -1; keep_subject = 1; return 0; @@ -1161,6 +1165,7 @@ static int subject_prefix = 0; static int subject_prefix_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); subject_prefix = 1; ((struct rev_info *)opt->value)->subject_prefix = arg; return 0; @@ -1168,6 +1173,8 @@ static int subject_prefix_callback(const struct option *opt, const char *arg, static int rfc_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); return subject_prefix_callback(opt, "RFC PATCH", unset); } @@ -1176,6 +1183,7 @@ static int numbered_cmdline_opt = 0; static int numbered_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_ARG(arg); *(int *)opt->value = numbered_cmdline_opt = unset ? 0 : 1; if (unset) auto_number = 0; @@ -1185,6 +1193,7 @@ static int numbered_callback(const struct option *opt, const char *arg, static int no_numbered_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); return numbered_callback(opt, arg, 1); } @@ -1192,6 +1201,7 @@ static int output_directory_callback(const struct option *opt, const char *arg, int unset) { const char **dir = (const char **)opt->value; + BUG_ON_OPT_NEG(unset); if (*dir) die(_("Two output directories?")); *dir = arg; diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 2787453eb1..c70a9c7158 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -475,6 +475,8 @@ static int option_parse_exclude(const struct option *opt, { struct string_list *exclude_list = opt->value; + BUG_ON_OPT_NEG(unset); + exc_given = 1; string_list_append(exclude_list, arg); @@ -486,6 +488,8 @@ static int option_parse_exclude_from(const struct option *opt, { struct dir_struct *dir = opt->value; + BUG_ON_OPT_NEG(unset); + exc_given = 1; add_excludes_from_file(dir, arg); @@ -497,6 +501,9 @@ static int option_parse_exclude_standard(const struct option *opt, { struct dir_struct *dir = opt->value; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); + exc_given = 1; setup_standard_excludes(dir); diff --git a/builtin/merge-file.c b/builtin/merge-file.c index b08803e611..06a2f90c48 100644 --- a/builtin/merge-file.c +++ b/builtin/merge-file.c @@ -15,6 +15,8 @@ static int label_cb(const struct option *opt, const char *arg, int unset) static int label_count = 0; const char **names = (const char **)opt->value; + BUG_ON_OPT_NEG(unset); + if (label_count >= 3) return error("too many labels on the command line"); names[label_count++] = arg; diff --git a/builtin/merge.c b/builtin/merge.c index 4aa6071598..adb0402e84 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -224,6 +224,7 @@ static int option_parse_x(const struct option *opt, static int option_parse_n(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_ARG(arg); show_diffstat = unset; return 0; } diff --git a/builtin/notes.c b/builtin/notes.c index c05cd004ab..91faa514aa 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -215,6 +215,8 @@ static int parse_msg_arg(const struct option *opt, const char *arg, int unset) { struct note_data *d = opt->value; + BUG_ON_OPT_NEG(unset); + strbuf_grow(&d->buf, strlen(arg) + 2); if (d->buf.len) strbuf_addch(&d->buf, '\n'); @@ -229,6 +231,8 @@ static int parse_file_arg(const struct option *opt, const char *arg, int unset) { struct note_data *d = opt->value; + BUG_ON_OPT_NEG(unset); + if (d->buf.len) strbuf_addch(&d->buf, '\n'); if (!strcmp(arg, "-")) { @@ -250,6 +254,8 @@ static int parse_reuse_arg(const struct option *opt, const char *arg, int unset) enum object_type type; unsigned long len; + BUG_ON_OPT_NEG(unset); + if (d->buf.len) strbuf_addch(&d->buf, '\n'); @@ -273,6 +279,7 @@ static int parse_reuse_arg(const struct option *opt, const char *arg, int unset) static int parse_reedit_arg(const struct option *opt, const char *arg, int unset) { struct note_data *d = opt->value; + BUG_ON_OPT_NEG(unset); d->use_editor = 1; return parse_reuse_arg(opt, arg, unset); } diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 4eac2f997b..6718e62c15 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -3206,6 +3206,9 @@ static int option_parse_index_version(const struct option *opt, { char *c; const char *val = arg; + + BUG_ON_OPT_NEG(unset); + pack_idx_opts.version = strtoul(val, &c, 10); if (pack_idx_opts.version > 2) die(_("unsupported index version %s"), val); diff --git a/builtin/read-tree.c b/builtin/read-tree.c index fbbc98e516..183ee8c1e5 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -44,6 +44,7 @@ static const char * const read_tree_usage[] = { static int index_output_cb(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); set_alternate_index_output(arg); return 0; } @@ -54,6 +55,8 @@ static int exclude_per_directory_cb(const struct option *opt, const char *arg, struct dir_struct *dir; struct unpack_trees_options *opts; + BUG_ON_OPT_NEG(unset); + opts = (struct unpack_trees_options *)opt->value; if (opts->dir) diff --git a/builtin/rebase.c b/builtin/rebase.c index 0ee06aa363..b84568fc4e 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -703,6 +703,9 @@ static int parse_opt_merge(const struct option *opt, const char *arg, int unset) { struct rebase_options *opts = opt->value; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); + if (!is_interactive(opts)) opts->type = REBASE_MERGE; @@ -715,6 +718,9 @@ static int parse_opt_interactive(const struct option *opt, const char *arg, { struct rebase_options *opts = opt->value; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); + opts->type = REBASE_INTERACTIVE; opts->flags |= REBASE_INTERACTIVE_EXPLICIT; diff --git a/builtin/show-branch.c b/builtin/show-branch.c index b1b540f7f6..934e514944 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -604,6 +604,7 @@ static int parse_reflog_param(const struct option *opt, const char *arg, { char *ep; const char **base = (const char **)opt->value; + BUG_ON_OPT_NEG(unset); if (!arg) arg = ""; reflog = strtoul(arg, &ep, 10); diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 2f13f1316f..ed888ffa48 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -151,6 +151,7 @@ static int hash_callback(const struct option *opt, const char *arg, int unset) static int exclude_existing_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); exclude_arg = 1; *(const char **)opt->value = arg; return 0; diff --git a/builtin/tag.c b/builtin/tag.c index 6a396a5090..02f6bd1279 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -338,6 +338,8 @@ static int parse_msg_arg(const struct option *opt, const char *arg, int unset) { struct msg_arg *msg = opt->value; + BUG_ON_OPT_NEG(unset); + if (!arg) return -1; if (msg->buf.len) diff --git a/builtin/update-index.c b/builtin/update-index.c index 07c10bcb7d..faa16c61f1 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -790,12 +790,16 @@ static int refresh(struct refresh_params *o, unsigned int flag) static int refresh_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); return refresh(opt->value, 0); } static int really_refresh_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); return refresh(opt->value, REFRESH_REALLY); } @@ -803,6 +807,7 @@ static int chmod_callback(const struct option *opt, const char *arg, int unset) { char *flip = opt->value; + BUG_ON_OPT_NEG(unset); if ((arg[0] != '-' && arg[0] != '+') || arg[1] != 'x' || arg[2]) return error("option 'chmod' expects \"+x\" or \"-x\""); *flip = arg[0]; @@ -812,6 +817,8 @@ static int chmod_callback(const struct option *opt, static int resolve_undo_clear_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); resolve_undo_clear(); return 0; } @@ -847,6 +854,8 @@ static int cacheinfo_callback(struct parse_opt_ctx_t *ctx, unsigned int mode; const char *path; + BUG_ON_OPT_NEG(unset); + if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, &oid, &path)) { if (add_cacheinfo(mode, &oid, path, 0)) die("git update-index: --cacheinfo cannot add %s", path); @@ -869,6 +878,8 @@ static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx, { int *nul_term_line = opt->value; + BUG_ON_OPT_NEG(unset); + if (ctx->argc != 1) return error("option '%s' must be the last argument", opt->long_name); allow_add = allow_replace = allow_remove = 1; @@ -881,6 +892,8 @@ static int stdin_callback(struct parse_opt_ctx_t *ctx, { int *read_from_stdin = opt->value; + BUG_ON_OPT_NEG(unset); + if (ctx->argc != 1) return error("option '%s' must be the last argument", opt->long_name); *read_from_stdin = 1; @@ -888,11 +901,13 @@ static int stdin_callback(struct parse_opt_ctx_t *ctx, } static int unresolve_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int flags) + const struct option *opt, int unset) { int *has_errors = opt->value; const char *prefix = startup_info->prefix; + BUG_ON_OPT_NEG(unset); + /* consume remaining arguments. */ *has_errors = do_unresolve(ctx->argc, ctx->argv, prefix, prefix ? strlen(prefix) : 0); @@ -905,11 +920,13 @@ static int unresolve_callback(struct parse_opt_ctx_t *ctx, } static int reupdate_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int flags) + const struct option *opt, int unset) { int *has_errors = opt->value; const char *prefix = startup_info->prefix; + BUG_ON_OPT_NEG(unset); + /* consume remaining arguments. */ setup_work_tree(); *has_errors = do_reupdate(ctx->argc, ctx->argv, -- cgit v1.2.3