summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/technical/api-parse-options.txt9
-rw-r--r--archive.c2
-rw-r--r--builtin-add.c2
-rw-r--r--builtin-apply.c7
-rw-r--r--builtin-archive.c3
-rw-r--r--builtin-bisect--helper.c3
-rw-r--r--builtin-blame.c2
-rw-r--r--builtin-branch.c3
-rw-r--r--builtin-cat-file.c2
-rw-r--r--builtin-check-attr.c4
-rw-r--r--builtin-checkout-index.c2
-rw-r--r--builtin-checkout.c2
-rw-r--r--builtin-clean.c3
-rw-r--r--builtin-clone.c2
-rw-r--r--builtin-commit.c13
-rw-r--r--builtin-config.c3
-rw-r--r--builtin-count-objects.c2
-rw-r--r--builtin-describe.c2
-rw-r--r--builtin-fast-export.c2
-rw-r--r--builtin-fetch.c2
-rw-r--r--builtin-fmt-merge-msg.c6
-rw-r--r--builtin-for-each-ref.c2
-rw-r--r--builtin-fsck.c2
-rw-r--r--builtin-gc.c3
-rw-r--r--builtin-grep.c2
-rw-r--r--builtin-help.c2
-rw-r--r--builtin-log.c2
-rw-r--r--builtin-ls-files.c2
-rw-r--r--builtin-merge-base.c2
-rw-r--r--builtin-merge-file.c2
-rw-r--r--builtin-merge.c4
-rw-r--r--builtin-mktree.c2
-rw-r--r--builtin-mv.c3
-rw-r--r--builtin-name-rev.c2
-rw-r--r--builtin-pack-refs.c2
-rw-r--r--builtin-prune.c2
-rw-r--r--builtin-push.c2
-rw-r--r--builtin-remote.c16
-rw-r--r--builtin-reset.c2
-rw-r--r--builtin-rev-parse.c4
-rw-r--r--builtin-revert.c2
-rw-r--r--builtin-rm.c3
-rw-r--r--builtin-shortlog.c2
-rw-r--r--builtin-show-branch.c2
-rw-r--r--builtin-symbolic-ref.c3
-rw-r--r--builtin-tag.c5
-rw-r--r--builtin-update-ref.c3
-rw-r--r--hash-object.c3
-rw-r--r--parse-options.c47
-rw-r--r--parse-options.h11
-rwxr-xr-xt/t0040-parse-options.sh19
-rw-r--r--test-parse-options.c6
52 files changed, 144 insertions, 96 deletions
diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt
index b43458eae6..50f9e9ac17 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -60,13 +60,13 @@ Steps to parse options
. in `cmd_foo(int argc, const char **argv, const char *prefix)`
call
- argc = parse_options(argc, argv, builtin_foo_options, builtin_foo_usage, flags);
+ argc = parse_options(argc, argv, prefix, builtin_foo_options, builtin_foo_usage, flags);
+
`parse_options()` will filter out the processed options of `argv[]` and leave the
non-option arguments in `argv[]`.
`argc` is updated appropriately because of the assignment.
+
-You can also pass NULL instead of a usage array as fourth parameter of
+You can also pass NULL instead of a usage array as the fifth parameter of
parse_options(), to avoid displaying a help screen with usage info and
option list. This should only be done if necessary, e.g. to implement
a limited parser for only a subset of the options that needs to be run
@@ -167,6 +167,11 @@ There are some macros to easily define options:
and the result will be put into `var`.
See 'Option Callbacks' below for a more elaborate description.
+`OPT_FILENAME(short, long, &var, description)`::
+ Introduce an option with a filename argument.
+ The filename will be prefixed by passing the filename along with
+ the prefix argument of `parse_options()` to `prefix_filename()`.
+
`OPT_ARGUMENT(long, description)`::
Introduce a long-option argument that will be kept in `argv[]`.
diff --git a/archive.c b/archive.c
index b2b90d3170..0bca9ca403 100644
--- a/archive.c
+++ b/archive.c
@@ -309,7 +309,7 @@ static int parse_archive_args(int argc, const char **argv,
OPT_END()
};
- argc = parse_options(argc, argv, opts, archive_usage, 0);
+ argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
if (remote)
die("Unexpected option --remote");
diff --git a/builtin-add.c b/builtin-add.c
index bee45f00de..c1b229a9d8 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -298,7 +298,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
int add_new_files;
int require_pathspec;
- argc = parse_options(argc, argv, builtin_add_options,
+ argc = parse_options(argc, argv, prefix, builtin_add_options,
builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
if (patch_interactive)
add_interactive = 1;
diff --git a/builtin-apply.c b/builtin-apply.c
index ebbf084639..94ba2bdd5b 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -3292,7 +3292,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
"apply a patch without touching the working tree"),
OPT_BOOLEAN(0, "apply", &force_apply,
"also apply the patch (use with --stat/--summary/--check)"),
- OPT_STRING(0, "build-fake-ancestor", &fake_ancestor, "file",
+ OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor,
"build a temporary index based on embedded index information"),
{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
"paths are separated with NUL character",
@@ -3327,11 +3327,8 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
if (apply_default_whitespace)
parse_whitespace_option(apply_default_whitespace);
- argc = parse_options(argc, argv, builtin_apply_options,
+ argc = parse_options(argc, argv, prefix, builtin_apply_options,
apply_usage, 0);
- fake_ancestor = parse_options_fix_filename(prefix, fake_ancestor);
- if (fake_ancestor)
- fake_ancestor = xstrdup(fake_ancestor);
if (apply_with_reject)
apply = apply_verbosely = 1;
diff --git a/builtin-archive.c b/builtin-archive.c
index ab50cebba0..3c5a5a7822 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -80,7 +80,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
OPT_END()
};
- argc = parse_options(argc, argv, local_opts, NULL, PARSE_OPT_KEEP_ALL);
+ argc = parse_options(argc, argv, prefix, local_opts, NULL,
+ PARSE_OPT_KEEP_ALL);
if (output)
create_output_file(output);
diff --git a/builtin-bisect--helper.c b/builtin-bisect--helper.c
index cb3e155116..5b226399e1 100644
--- a/builtin-bisect--helper.c
+++ b/builtin-bisect--helper.c
@@ -17,7 +17,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
OPT_END()
};
- argc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);
+ argc = parse_options(argc, argv, prefix, options,
+ git_bisect_helper_usage, 0);
if (!next_all)
usage_with_options(git_bisect_helper_usage, options);
diff --git a/builtin-blame.c b/builtin-blame.c
index cf74a92614..9dc3335910 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -2229,7 +2229,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
save_commit_buffer = 0;
dashdash_pos = 0;
- parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
+ parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |
PARSE_OPT_KEEP_ARGV0);
for (;;) {
switch (parse_options_step(&ctx, options, blame_opt_usage)) {
diff --git a/builtin-branch.c b/builtin-branch.c
index 6aaa708473..5687d6042c 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -610,7 +610,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
}
hashcpy(merge_filter_ref, head_sha1);
- argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
+ 0);
if (!!delete + !!rename + !!force_create > 1)
usage_with_options(builtin_branch_usage, options);
diff --git a/builtin-cat-file.c b/builtin-cat-file.c
index 43ffe7ffae..5906842008 100644
--- a/builtin-cat-file.c
+++ b/builtin-cat-file.c
@@ -231,7 +231,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
if (argc != 3 && argc != 2)
usage_with_options(cat_file_usage, options);
- argc = parse_options(argc, argv, options, cat_file_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);
if (opt) {
if (argc == 1)
diff --git a/builtin-check-attr.c b/builtin-check-attr.c
index 15a04b7179..8bd0430098 100644
--- a/builtin-check-attr.c
+++ b/builtin-check-attr.c
@@ -69,8 +69,8 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
int cnt, i, doubledash;
const char *errstr = NULL;
- argc = parse_options(argc, argv, check_attr_options, check_attr_usage,
- PARSE_OPT_KEEP_DASHDASH);
+ argc = parse_options(argc, argv, prefix, check_attr_options,
+ check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
if (!argc)
usage_with_options(check_attr_usage, check_attr_options);
diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c
index afe35e246c..a7a5ee10f3 100644
--- a/builtin-checkout-index.c
+++ b/builtin-checkout-index.c
@@ -249,7 +249,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
die("invalid cache");
}
- argc = parse_options(argc, argv, builtin_checkout_index_options,
+ argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
builtin_checkout_index_usage, 0);
state.force = force;
state.quiet = quiet;
diff --git a/builtin-checkout.c b/builtin-checkout.c
index b8a4b0139b..8a9a474218 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -605,7 +605,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
opts.track = BRANCH_TRACK_UNSPECIFIED;
- argc = parse_options(argc, argv, options, checkout_usage,
+ argc = parse_options(argc, argv, prefix, options, checkout_usage,
PARSE_OPT_KEEP_DASHDASH);
/* --track without -b should DWIM */
diff --git a/builtin-clean.c b/builtin-clean.c
index c5ad33d3e6..1c1b6d26e9 100644
--- a/builtin-clean.c
+++ b/builtin-clean.c
@@ -56,7 +56,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
else
config_set = 1;
- argc = parse_options(argc, argv, options, builtin_clean_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
+ 0);
memset(&dir, 0, sizeof(dir));
if (ignored_only)
diff --git a/builtin-clone.c b/builtin-clone.c
index c935833c6c..5c46496a43 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -360,7 +360,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
junk_pid = getpid();
- argc = parse_options(argc, argv, builtin_clone_options,
+ argc = parse_options(argc, argv, prefix, builtin_clone_options,
builtin_clone_usage, 0);
if (argc == 0)
diff --git a/builtin-commit.c b/builtin-commit.c
index baaa75cf90..41e222d267 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -88,13 +88,13 @@ static struct option builtin_commit_options[] = {
OPT__VERBOSE(&verbose),
OPT_GROUP("Commit message options"),
- OPT_STRING('F', "file", &logfile, "FILE", "read log from file"),
+ OPT_FILENAME('F', "file", &logfile, "read log from file"),
OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit "),
OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
- OPT_STRING('t', "template", &template_file, "FILE", "use specified template file"),
+ OPT_FILENAME('t', "template", &template_file, "use specified template file"),
OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
OPT_GROUP("Commit contents options"),
@@ -697,13 +697,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
{
int f = 0;
- argc = parse_options(argc, argv, builtin_commit_options, usage, 0);
- logfile = parse_options_fix_filename(prefix, logfile);
- if (logfile)
- logfile = xstrdup(logfile);
- template_file = parse_options_fix_filename(prefix, template_file);
- if (template_file)
- template_file = xstrdup(template_file);
+ argc = parse_options(argc, argv, prefix, builtin_commit_options, usage,
+ 0);
if (force_author && !strchr(force_author, '>'))
force_author = find_author_by_nickname(force_author);
diff --git a/builtin-config.c b/builtin-config.c
index a81bc8bbf0..60915f91ca 100644
--- a/builtin-config.c
+++ b/builtin-config.c
@@ -316,7 +316,8 @@ int cmd_config(int argc, const char **argv, const char *unused_prefix)
config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
- argc = parse_options(argc, argv, builtin_config_options, builtin_config_usage,
+ argc = parse_options(argc, argv, prefix, builtin_config_options,
+ builtin_config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (use_global_config + use_system_config + !!given_config_file > 1) {
diff --git a/builtin-count-objects.c b/builtin-count-objects.c
index b814fe5070..1b0b6c84ea 100644
--- a/builtin-count-objects.c
+++ b/builtin-count-objects.c
@@ -83,7 +83,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
OPT_END(),
};
- argc = parse_options(argc, argv, opts, count_objects_usage, 0);
+ argc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0);
/* we do not take arguments other than flags for now */
if (argc)
usage_with_options(count_objects_usage, opts);
diff --git a/builtin-describe.c b/builtin-describe.c
index 63c6a19da5..7a662980d1 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -322,7 +322,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
OPT_END(),
};
- argc = parse_options(argc, argv, options, describe_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, describe_usage, 0);
if (max_candidates < 0)
max_candidates = 0;
else if (max_candidates > MAX_TAGS)
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index 6731713223..6cef810312 100644
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
@@ -515,7 +515,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
init_revisions(&revs, prefix);
argc = setup_revisions(argc, argv, &revs, NULL);
- argc = parse_options(argc, argv, options, fast_export_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, fast_export_usage, 0);
if (argc > 1)
usage_with_options (fast_export_usage, options);
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 1eec64e9c4..cd5eb9aff5 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -639,7 +639,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
for (i = 1; i < argc; i++)
strbuf_addf(&default_rla, " %s", argv[i]);
- argc = parse_options(argc, argv,
+ argc = parse_options(argc, argv, prefix,
builtin_fetch_options, builtin_fetch_usage, 0);
if (argc == 0)
diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c
index fae1482ba9..fbf9582e66 100644
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
@@ -351,7 +351,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT_BOOLEAN(0, "log", &merge_summary, "populate log with the shortlog"),
OPT_BOOLEAN(0, "summary", &merge_summary, "alias for --log"),
- OPT_STRING('F', "file", &inpath, "file", "file to read from"),
+ OPT_FILENAME('F', "file", &inpath, "file to read from"),
OPT_END()
};
@@ -360,10 +360,10 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
int ret;
git_config(fmt_merge_msg_config, NULL);
- argc = parse_options(argc, argv, options, fmt_merge_msg_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage,
+ 0);
if (argc > 0)
usage_with_options(fmt_merge_msg_usage, options);
- inpath = parse_options_fix_filename(prefix, inpath);
if (inpath && strcmp(inpath, "-")) {
in = fopen(inpath, "r");
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index d091e04af9..784733b25d 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -905,7 +905,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
OPT_END(),
};
- parse_options(argc, argv, opts, for_each_ref_usage, 0);
+ parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
if (maxcount < 0) {
error("invalid --count argument: `%d'", maxcount);
usage_with_options(for_each_ref_usage, opts);
diff --git a/builtin-fsck.c b/builtin-fsck.c
index 6436bc2248..7da706cac3 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -590,7 +590,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
errors_found = 0;
- argc = parse_options(argc, argv, fsck_opts, fsck_usage, 0);
+ argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
if (write_lost_and_found) {
check_full = 1;
include_reflogs = 0;
diff --git a/builtin-gc.c b/builtin-gc.c
index fc556ed7f3..7d3e9cc7a0 100644
--- a/builtin-gc.c
+++ b/builtin-gc.c
@@ -194,7 +194,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
if (pack_refs < 0)
pack_refs = !is_bare_repository();
- argc = parse_options(argc, argv, builtin_gc_options, builtin_gc_usage, 0);
+ argc = parse_options(argc, argv, prefix, builtin_gc_options,
+ builtin_gc_usage, 0);
if (argc > 0)
usage_with_options(builtin_gc_usage, builtin_gc_options);
diff --git a/builtin-grep.c b/builtin-grep.c
index 5308b346e6..73fc922c49 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -765,7 +765,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
* unrecognized non option is the beginning of the refs list
* that continues up to the -- (if exists), and then paths.
*/
- argc = parse_options(argc, argv, options, grep_usage,
+ argc = parse_options(argc, argv, prefix, options, grep_usage,
PARSE_OPT_KEEP_DASHDASH |
PARSE_OPT_STOP_AT_NON_OPTION |
PARSE_OPT_NO_INTERNAL_HELP);
diff --git a/builtin-help.c b/builtin-help.c
index 67dda3e6e6..af565fb658 100644
--- a/builtin-help.c
+++ b/builtin-help.c
@@ -423,7 +423,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
setup_git_directory_gently(&nongit);
git_config(git_help_config, NULL);
- argc = parse_options(argc, argv, builtin_help_options,
+ argc = parse_options(argc, argv, prefix, builtin_help_options,
builtin_help_usage, 0);
if (show_all) {
diff --git a/builtin-log.c b/builtin-log.c
index c8c6208275..0d34050556 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -936,7 +936,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
* like "git format-patch -o a123 HEAD^.." may fail; a123 is
* possibly a valid SHA1.
*/
- argc = parse_options(argc, argv, builtin_format_patch_options,
+ argc = parse_options(argc, argv, prefix, builtin_format_patch_options,
builtin_format_patch_usage,
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index 3d59b0e140..2312866605 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -486,7 +486,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
prefix_offset = strlen(prefix);
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, builtin_ls_files_options,
+ argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
ls_files_usage, 0);
if (show_tag || show_valid_bit) {
tag_cached = "H ";
diff --git a/builtin-merge-base.c b/builtin-merge-base.c
index 03fc1c2114..a6ec2f7ab7 100644
--- a/builtin-merge-base.c
+++ b/builtin-merge-base.c
@@ -53,7 +53,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, options, merge_base_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
if (argc < 2)
usage_with_options(merge_base_usage, options);
rev = xmalloc(argc * sizeof(*rev));
diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index 96edb97a83..afd2ea7a73 100644
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
@@ -48,7 +48,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
merge_style = git_xmerge_style;
}
- argc = parse_options(argc, argv, options, merge_file_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
if (argc != 3)
usage_with_options(merge_file_usage, options);
if (quiet) {
diff --git a/builtin-merge.c b/builtin-merge.c
index 0b58e5eda1..8d101eff0b 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -462,7 +462,7 @@ static int git_merge_config(const char *k, const char *v, void *cb)
argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
argc++;
- parse_options(argc, argv, builtin_merge_options,
+ parse_options(argc, argv, NULL, builtin_merge_options,
builtin_merge_usage, 0);
free(buf);
}
@@ -855,7 +855,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
if (diff_use_color_default == -1)
diff_use_color_default = git_use_color_default;
- argc = parse_options(argc, argv, builtin_merge_options,
+ argc = parse_options(argc, argv, prefix, builtin_merge_options,
builtin_merge_usage, 0);
if (verbosity < 0)
show_diffstat = 0;
diff --git a/builtin-mktree.c b/builtin-mktree.c
index dc4f1a711d..098395fda1 100644
--- a/builtin-mktree.c
+++ b/builtin-mktree.c
@@ -155,7 +155,7 @@ int cmd_mktree(int ac, const char **av, const char *prefix)
OPT_END()
};
- ac = parse_options(ac, av, option, mktree_usage, 0);
+ ac = parse_options(ac, av, prefix, option, mktree_usage, 0);
while (!got_eof) {
while (1) {
diff --git a/builtin-mv.c b/builtin-mv.c
index 01270fefdf..8b81d4b51d 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -72,7 +72,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (read_cache() < 0)
die("index file corrupt");
- argc = parse_options(argc, argv, builtin_mv_options, builtin_mv_usage, 0);
+ argc = parse_options(argc, argv, prefix, builtin_mv_options,
+ builtin_mv_usage, 0);
if (--argc < 1)
usage_with_options(builtin_mv_usage, builtin_mv_options);
diff --git a/builtin-name-rev.c b/builtin-name-rev.c
index 08c8aabf94..06a38ac8c1 100644
--- a/builtin-name-rev.c
+++ b/builtin-name-rev.c
@@ -238,7 +238,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, opts, name_rev_usage, 0);
+ argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
if (!!all + !!transform_stdin + !!argc > 1) {
error("Specify either a list, or --all, not both!");
usage_with_options(name_rev_usage, opts);
diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c
index 34246df4ec..091860b2e3 100644
--- a/builtin-pack-refs.c
+++ b/builtin-pack-refs.c
@@ -15,7 +15,7 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
OPT_BIT(0, "prune", &flags, "prune loose refs (default)", PACK_REFS_PRUNE),
OPT_END(),
};
- if (parse_options(argc, argv, opts, pack_refs_usage, 0))
+ if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
usage_with_options(pack_refs_usage, opts);
return pack_refs(flags);
}
diff --git a/builtin-prune.c b/builtin-prune.c
index 145ba83651..0ed9cce4a2 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -142,7 +142,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
save_commit_buffer = 0;
init_revisions(&revs, prefix);
- argc = parse_options(argc, argv, options, prune_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
while (argc--) {
unsigned char sha1[20];
const char *name = *argv++;
diff --git a/builtin-push.c b/builtin-push.c
index 2eabcd3bdf..c869974013 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -198,7 +198,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
OPT_END()
};
- argc = parse_options(argc, argv, options, push_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, push_usage, 0);
if (tags)
add_refspec("refs/tags/*");
diff --git a/builtin-remote.c b/builtin-remote.c
index fda9a54a0c..f7d66189cc 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -79,7 +79,8 @@ static int add(int argc, const char **argv)
OPT_END()
};
- argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+ 0);
if (argc < 2)
usage_with_options(builtin_remote_usage, options);
@@ -986,7 +987,8 @@ static int show(int argc, const char **argv)
struct string_list info_list = { NULL, 0, 0, 0 };
struct show_info info;
- argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+ 0);
if (argc < 1)
return show_all();
@@ -1076,7 +1078,8 @@ static int set_head(int argc, const char **argv)
"delete refs/remotes/<name>/HEAD"),
OPT_END()
};
- argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+ 0);
if (argc)
strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
@@ -1130,7 +1133,8 @@ static int prune(int argc, const char **argv)
OPT_END()
};
- argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+ 0);
if (argc < 1)
usage_with_options(builtin_remote_usage, options);
@@ -1220,7 +1224,7 @@ static int update(int argc, const char **argv)
OPT_END()
};
- argc = parse_options(argc, argv, options, builtin_remote_usage,
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
PARSE_OPT_KEEP_ARGV0);
if (argc < 2) {
argc = 2;
@@ -1306,7 +1310,7 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
};
int result;
- argc = parse_options(argc, argv, options, builtin_remote_usage,
+ argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (argc < 1)
diff --git a/builtin-reset.c b/builtin-reset.c
index 7e7ebabaa8..5fa1789d0c 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -203,7 +203,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, options, git_reset_usage,
+ argc = parse_options(argc, argv, prefix, options, git_reset_usage,
PARSE_OPT_KEEP_DASHDASH);
reflog_action = args_to_str(argv);
setenv("GIT_REFLOG_ACTION", reflog_action, 0);
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index c5b3d6e31b..112d622cda 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -318,7 +318,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
int onb = 0, osz = 0, unb = 0, usz = 0;
strbuf_addstr(&parsed, "set --");
- argc = parse_options(argc, argv, parseopt_opts, parseopt_usage,
+ argc = parse_options(argc, argv, prefix, parseopt_opts, parseopt_usage,
PARSE_OPT_KEEP_DASHDASH);
if (argc < 1 || strcmp(argv[0], "--"))
usage_with_options(parseopt_usage, parseopt_opts);
@@ -393,7 +393,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
/* put an OPT_END() */
ALLOC_GROW(opts, onb + 1, osz);
memset(opts + onb, 0, sizeof(opts[onb]));
- argc = parse_options(argc, argv, opts, usage,
+ argc = parse_options(argc, argv, prefix, opts, usage,
keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0);
strbuf_addf(&parsed, " --");
diff --git a/builtin-revert.c b/builtin-revert.c
index ae0139500a..c87115af30 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -60,7 +60,7 @@ static void parse_args(int argc, const char **argv)
OPT_END(),
};
- if (parse_options(argc, argv, options, usage_str, 0) != 1)
+ if (parse_options(argc, argv, NULL, options, usage_str, 0) != 1)
usage_with_options(usage_str, options);
arg = argv[0];
diff --git a/builtin-rm.c b/builtin-rm.c
index 269d60890a..0cc4912718 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -157,7 +157,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0);
+ argc = parse_options(argc, argv, prefix, builtin_rm_options,
+ builtin_rm_usage, 0);
if (!argc)
usage_with_options(builtin_rm_usage, builtin_rm_options);
diff --git a/builtin-shortlog.c b/builtin-shortlog.c
index b28091b445..6a3812ee18 100644
--- a/builtin-shortlog.c
+++ b/builtin-shortlog.c
@@ -263,7 +263,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
shortlog_init(&log);
init_revisions(&rev, prefix);
- parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
+ parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |
PARSE_OPT_KEEP_ARGV0);
for (;;) {
diff --git a/builtin-show-branch.c b/builtin-show-branch.c
index b1affd2ffb..9433811956 100644
--- a/builtin-show-branch.c
+++ b/builtin-show-branch.c
@@ -697,7 +697,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
av = default_arg - 1; /* ick; we would not address av[0] */
}
- ac = parse_options(ac, av, builtin_show_branch_options,
+ ac = parse_options(ac, av, prefix, builtin_show_branch_options,
show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION);
if (all_heads)
all_remotes = 1;
diff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c
index 6ae6bcc0e8..ca855a5eb2 100644
--- a/builtin-symbolic-ref.c
+++ b/builtin-symbolic-ref.c
@@ -36,7 +36,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, options, git_symbolic_ref_usage, 0);
+ argc = parse_options(argc, argv, prefix, options,
+ git_symbolic_ref_usage, 0);
if (msg &&!*msg)
die("Refusing to perform update with empty message");
switch (argc) {
diff --git a/builtin-tag.c b/builtin-tag.c
index e544430094..dc3db62811 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -387,7 +387,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
"annotated tag, needs a message"),
OPT_CALLBACK('m', NULL, &msg, "msg",
"message for the tag", parse_msg_arg),
- OPT_STRING('F', NULL, &msgfile, "file", "message in a file"),
+ OPT_FILENAME('F', NULL, &msgfile, "message in a file"),
OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
OPT_STRING('u', NULL, &keyid, "key-id",
"use another key to sign the tag"),
@@ -405,8 +405,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
git_config(git_tag_config, NULL);
- argc = parse_options(argc, argv, options, git_tag_usage, 0);
- msgfile = parse_options_fix_filename(prefix, msgfile);
+ argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
if (keyid) {
sign = 1;
diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index 378dc1b7a6..76ba1d5881 100644
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
@@ -23,7 +23,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, options, git_update_ref_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, git_update_ref_usage,
+ 0);
if (msg && !*msg)
die("Refusing to perform update with empty message.");
diff --git a/hash-object.c b/hash-object.c
index ebb3bedb07..47cf43c3cd 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -84,7 +84,8 @@ int main(int argc, const char **argv)
git_extract_argv0_path(argv[0]);
- argc = parse_options(argc, argv, hash_object_options, hash_object_usage, 0);
+ argc = parse_options(argc, argv, NULL, hash_object_options,
+ hash_object_usage, 0);
if (write_object) {
prefix = setup_git_directory();
diff --git a/parse-options.c b/parse-options.c
index 1d25b94c72..b85cab2466 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -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;
@@ -285,12 +307,14 @@ static void check_typos(const char *arg, const struct option *options)
}
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) &&
@@ -389,12 +413,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);
@@ -491,6 +516,8 @@ int usage_with_options_internal(const char * const *usagestr,
if (opts->flags & PARSE_OPT_NOARG)
break;
/* FALLTHROUGH */
+ case OPTION_FILENAME:
+ /* FALLTHROUGH */
case OPTION_STRING:
if (opts->argh)
pos += usage_argh(opts);
@@ -601,15 +628,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);
-}
-
diff --git a/parse-options.h b/parse-options.h
index fe41ab2c67..b374ade95c 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -17,6 +17,7 @@ enum parse_opt_type {
OPTION_STRING,
OPTION_INTEGER,
OPTION_CALLBACK,
+ OPTION_FILENAME
};
enum parse_opt_flags {
@@ -117,12 +118,14 @@ struct option {
#define OPT_NUMBER_CALLBACK(v, h, f) \
{ OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }
+#define OPT_FILENAME(s, l, v, h) { OPTION_FILENAME, (s), (l), (v), \
+ "FILE", (h) }
/* parse_options() will filter out the processed options and leave the
* non-option arguments in argv[].
* Returns the number of arguments left in argv[].
*/
-extern int parse_options(int argc, const char **argv,
+extern int parse_options(int argc, const char **argv, const char *prefix,
const struct option *options,
const char * const usagestr[], int flags);
@@ -148,13 +151,15 @@ struct parse_opt_ctx_t {
int argc, cpidx;
const char *opt;
int flags;
+ const char *prefix;
};
extern int parse_options_usage(const char * const *usagestr,
const struct option *opts);
extern 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);
extern int parse_options_step(struct parse_opt_ctx_t *ctx,
const struct option *options,
@@ -182,6 +187,4 @@ extern int parse_opt_with_commit(const struct option *, const char *, int);
"use <n> digits to display SHA-1s", \
PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
-extern const char *parse_options_fix_filename(const char *prefix, const char *file);
-
#endif
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index a40c1236c0..bbc821ef97 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -19,6 +19,7 @@ usage: test-parse-options <options>
--set23 set integer to 23
-t <time> get timestamp of <time>
-L, --length <str> get length of <str>
+ -F, --file <FILE> set file to <FILE>
String options
-s, --string <string>
@@ -56,10 +57,12 @@ abbrev: 7
verbose: 2
quiet: no
dry run: yes
+file: prefix/my.file
EOF
test_expect_success 'short options' '
- test-parse-options -s123 -b -i 1729 -b -vv -n > output 2> output.err &&
+ test-parse-options -s123 -b -i 1729 -b -vv -n -F my.file \
+ > output 2> output.err &&
test_cmp expect output &&
test ! -s output.err
'
@@ -73,11 +76,12 @@ abbrev: 10
verbose: 2
quiet: no
dry run: no
+file: prefix/fi.le
EOF
test_expect_success 'long options' '
test-parse-options --boolean --integer 1729 --boolean --string2=321 \
- --verbose --verbose --no-dry-run --abbrev=10 \
+ --verbose --verbose --no-dry-run --abbrev=10 --file fi.le\
> output 2> output.err &&
test ! -s output.err &&
test_cmp expect output
@@ -87,6 +91,8 @@ test_expect_success 'missing required value' '
test-parse-options -s;
test $? = 129 &&
test-parse-options --string;
+ test $? = 129 &&
+ test-parse-options --file;
test $? = 129
'
@@ -99,6 +105,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
arg 00: a1
arg 01: b1
arg 02: --boolean
@@ -120,6 +127,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
EOF
test_expect_success 'unambiguously abbreviated option' '
@@ -148,6 +156,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
EOF
test_expect_success 'non ambiguous option (after two options it abbreviates)' '
@@ -175,6 +184,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
arg 00: --quux
EOF
@@ -193,6 +203,7 @@ abbrev: 7
verbose: 0
quiet: yes
dry run: no
+file: (not set)
arg 00: foo
EOF
@@ -213,6 +224,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
EOF
test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
@@ -240,6 +252,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
EOF
test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
@@ -263,6 +276,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
EOF
test_expect_success 'OPT_BIT() works' '
@@ -292,6 +306,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
EOF
test_expect_success 'OPT_NUMBER_CALLBACK() works' '
diff --git a/test-parse-options.c b/test-parse-options.c
index e0669dcb41..a90bc3003d 100644
--- a/test-parse-options.c
+++ b/test-parse-options.c
@@ -7,6 +7,7 @@ static unsigned long timestamp;
static int abbrev = 7;
static int verbose = 0, dry_run = 0, quiet = 0;
static char *string = NULL;
+static char *file = NULL;
int length_callback(const struct option *opt, const char *arg, int unset)
{
@@ -27,6 +28,7 @@ int number_callback(const struct option *opt, const char *arg, int unset)
int main(int argc, const char **argv)
{
+ const char *prefix = "prefix/";
const char *usage[] = {
"test-parse-options <options>",
NULL
@@ -43,6 +45,7 @@ int main(int argc, const char **argv)
OPT_DATE('t', NULL, &timestamp, "get timestamp of <time>"),
OPT_CALLBACK('L', "length", &integer, "str",
"get length of <str>", length_callback),
+ OPT_FILENAME('F', "file", &file, "set file to <FILE>"),
OPT_GROUP("String options"),
OPT_STRING('s', "string", &string, "string", "get a string"),
OPT_STRING(0, "string2", &string, "str", "get another string"),
@@ -65,7 +68,7 @@ int main(int argc, const char **argv)
};
int i;
- argc = parse_options(argc, argv, options, usage, 0);
+ argc = parse_options(argc, argv, prefix, options, usage, 0);
printf("boolean: %d\n", boolean);
printf("integer: %u\n", integer);
@@ -75,6 +78,7 @@ int main(int argc, const char **argv)
printf("verbose: %d\n", verbose);
printf("quiet: %s\n", quiet ? "yes" : "no");
printf("dry run: %s\n", dry_run ? "yes" : "no");
+ printf("file: %s\n", file ? file : "(not set)");
for (i = 0; i < argc; i++)
printf("arg %02d: %s\n", i, argv[i]);