{"thread":{"id":"19453","subject":"[PATCH 0/4] Add OPT_FILENAME to parse-opts","startedAt":"2009-05-23T18:53:09Z","lastAt":"2009-05-23T18:53:13Z","messageCount":5,"participants":["Stephen Boyd"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"114518","messageId":"1243104793-3254-1-git-send-email-bebarino@gmail.com","threadId":"19453","inReplyTo":null,"subject":"[PATCH 0/4] Add OPT_FILENAME to parse-opts","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-05-23T18:53:09Z","receivedAt":"2009-05-23T18:53:09Z","isPatch":true,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"OPT_FILENAME is used to prefix filenames given on the command line, so\nthat they are relative to the current working directory. For a more \nin-depth description see the fourth patch.\n\nThis series is really two parts, two bug fixes and the introduction\nof OPT_FILNAME, but they're all related to one commit\ndbd0f5c (Files given on the command line are relative to $cwd,\n2008-08-06).\n\nIt touches a lot of files, but that's mostly because of\npatch three.\n\nStephen Boyd (4):\n  commit: -F overrides -t\n  apply, fmt-merge-msg: use relative filenames\n  parse-opts: prepare for OPT_FILENAME\n  parse-opts: add OPT_FILENAME and transition builtins\n\n Documentation/technical/api-parse-options.txt |    9 ++++-\n archive.c                                     |    2 +-\n builtin-add.c                                 |    2 +-\n builtin-apply.c                               |    5 ++-\n builtin-archive.c                             |    3 +-\n builtin-bisect--helper.c                      |    3 +-\n builtin-blame.c                               |    2 +-\n builtin-branch.c                              |    3 +-\n builtin-cat-file.c                            |    2 +-\n builtin-check-attr.c                          |    4 +-\n builtin-checkout-index.c                      |    2 +-\n builtin-checkout.c                            |    2 +-\n builtin-clean.c                               |    3 +-\n builtin-clone.c                               |    2 +-\n builtin-commit.c                              |    9 ++---\n builtin-config.c                              |    3 +-\n builtin-count-objects.c                       |    2 +-\n builtin-describe.c                            |    2 +-\n builtin-fast-export.c                         |    2 +-\n builtin-fetch.c                               |    2 +-\n builtin-fmt-merge-msg.c                       |    5 ++-\n builtin-for-each-ref.c                        |    2 +-\n builtin-fsck.c                                |    2 +-\n builtin-gc.c                                  |    3 +-\n builtin-grep.c                                |    2 +-\n builtin-help.c                                |    2 +-\n builtin-ls-files.c                            |    2 +-\n builtin-merge-base.c                          |    2 +-\n builtin-merge-file.c                          |    2 +-\n builtin-merge.c                               |    4 +-\n builtin-mv.c                                  |    3 +-\n builtin-name-rev.c                            |    2 +-\n builtin-pack-refs.c                           |    2 +-\n builtin-prune.c                               |    2 +-\n builtin-push.c                                |    2 +-\n builtin-remote.c                              |   16 +++++---\n builtin-reset.c                               |    2 +-\n builtin-rev-parse.c                           |    4 +-\n builtin-revert.c                              |    2 +-\n builtin-rm.c                                  |    3 +-\n builtin-shortlog.c                            |    2 +-\n builtin-symbolic-ref.c                        |    3 +-\n builtin-tag.c                                 |    5 +--\n builtin-update-ref.c                          |    3 +-\n hash-object.c                                 |    3 +-\n parse-options.c                               |   47 ++++++++++++++++--------\n parse-options.h                               |   11 ++++--\n t/t0040-parse-options.sh                      |   19 +++++++++-\n t/t4131-apply-fake-ancestor.sh                |   42 ++++++++++++++++++++++\n t/t6200-fmt-merge-msg.sh                      |   32 +++++++++++++++++\n t/t7500-commit.sh                             |   10 +++++\n test-parse-options.c                          |    6 +++-\n 52 files changed, 226 insertions(+), 85 deletions(-)\n create mode 100755 t/t4131-apply-fake-ancestor.sh\n"},{"id":"114519","messageId":"1243104793-3254-2-git-send-email-bebarino@gmail.com","threadId":"19453","inReplyTo":"1243104793-3254-1-git-send-email-bebarino@gmail.com","subject":"[PATCH 1/4] commit: -F overrides -t","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-05-23T18:53:10Z","receivedAt":"2009-05-23T18:53:10Z","isPatch":true,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"Commit dbd0f5c7 (Files given on the command line are relative to $cwd,\n2008-08-06) introduced parse_options_fix_filename() as a quick fix for\nfilename arguments used in the parse options API.\n\ngit-commit was still broken. This means\n\n    git commit -F log -t temp\n\nin a subdirectory would make git think the log message should be taken\nfrom temp instead of log.\n\nThis is because parse_options_fix_filename() calls prefix_filename()\nwhich uses a single static char buffer to do its work. Making two calls\nwith two char pointers causes the pointers to alias. To prevent\naliasing, we duplicate the string returned by\nparse_options_fix_filename().\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n builtin-commit.c  |    4 ++++\n t/t7500-commit.sh |   10 ++++++++++\n 2 files changed, 14 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex 81371b1..baaa75c 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -699,7 +699,11 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \n \targc = parse_options(argc, argv, builtin_commit_options, usage, 0);\n \tlogfile = parse_options_fix_filename(prefix, logfile);\n+\tif (logfile)\n+\t\tlogfile = xstrdup(logfile);\n \ttemplate_file = parse_options_fix_filename(prefix, template_file);\n+\tif (template_file)\n+\t\ttemplate_file = xstrdup(template_file);\n \n \tif (force_author && !strchr(force_author, '>'))\n \t\tforce_author = find_author_by_nickname(force_author);\ndiff --git a/t/t7500-commit.sh b/t/t7500-commit.sh\nindex 5998baf..8eec0fa 100755\n--- a/t/t7500-commit.sh\n+++ b/t/t7500-commit.sh\n@@ -183,4 +183,14 @@ test_expect_success 'commit message from stdin' '\n \tcommit_msg_is \"Log with foo word\"\n '\n \n+test_expect_success 'commit -F overrides -t' '\n+\t(\n+\t\tcd subdir &&\n+\t\techo \"-F log\" > f.log &&\n+\t\techo \"-t template\" > t.template &&\n+\t\tgit commit --allow-empty -F f.log -t t.template\n+\t) &&\n+\tcommit_msg_is \"-F log\"\n+'\n+\n test_done\n-- \n1.6.3.1.145.gb74d77\n"},{"id":"114520","messageId":"1243104793-3254-3-git-send-email-bebarino@gmail.com","threadId":"19453","inReplyTo":"1243104793-3254-2-git-send-email-bebarino@gmail.com","subject":"[PATCH 2/4] apply, fmt-merge-msg: use relative filenames","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-05-23T18:53:11Z","receivedAt":"2009-05-23T18:53:11Z","isPatch":true,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"Commit dbd0f5c7 (Files given on the command line are relative to $cwd,\n2008-08-06) only fixed git-commit and git-tag. But, git-apply and\ngit-fmt-merge-msg didn't get the update and exhibit the same behavior.\n\nFix them and add tests for \"apply --build-fake-ancestor\" and\n\"fmt-merge-msg -F\".\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n\nIf anyone knows a better way to test for build-fake-ancestor please\nlet me know. Right now it's just testing for file.\n\n builtin-apply.c                |    4 +++\n builtin-fmt-merge-msg.c        |    1 +\n t/t4131-apply-fake-ancestor.sh |   42 ++++++++++++++++++++++++++++++++++++++++\n t/t6200-fmt-merge-msg.sh       |   32 ++++++++++++++++++++++++++++++\n 4 files changed, 79 insertions(+), 0 deletions(-)\n create mode 100755 t/t4131-apply-fake-ancestor.sh\n\ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex 8a3771e..a40b982 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -3315,6 +3315,10 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)\n \n \targc = parse_options(argc, argv, builtin_apply_options,\n \t\t\tapply_usage, 0);\n+\tfake_ancestor = parse_options_fix_filename(prefix, fake_ancestor);\n+\tif (fake_ancestor)\n+\t\tfake_ancestor = xstrdup(fake_ancestor);\n+\n \tif (apply_with_reject)\n \t\tapply = apply_verbosely = 1;\n \tif (!force_apply && (diffstat || numstat || summary || check || fake_ancestor))\ndiff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c\nindex a788369..fae1482 100644\n--- a/builtin-fmt-merge-msg.c\n+++ b/builtin-fmt-merge-msg.c\n@@ -363,6 +363,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, options, fmt_merge_msg_usage, 0);\n \tif (argc > 0)\n \t\tusage_with_options(fmt_merge_msg_usage, options);\n+\tinpath = parse_options_fix_filename(prefix, inpath);\n \n \tif (inpath && strcmp(inpath, \"-\")) {\n \t\tin = fopen(inpath, \"r\");\ndiff --git a/t/t4131-apply-fake-ancestor.sh b/t/t4131-apply-fake-ancestor.sh\nnew file mode 100755\nindex 0000000..94373ca\n--- /dev/null\n+++ b/t/t4131-apply-fake-ancestor.sh\n@@ -0,0 +1,42 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2009 Stephen Boyd\n+#\n+\n+test_description='git apply --build-fake-ancestor handling.'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\ttest_commit 1 &&\n+\ttest_commit 2 &&\n+\tmkdir sub &&\n+\ttest_commit 3 sub/3 &&\n+\ttest_commit 4\n+'\n+\n+test_expect_success 'apply --build-fake-ancestor' '\n+\tgit checkout 2 &&\n+\techo \"A\" > 1.t &&\n+\tgit diff > 1.patch &&\n+\tgit reset --hard &&\n+\tgit checkout 1 &&\n+\tgit apply --build-fake-ancestor 1.ancestor 1.patch\n+'\n+\n+test_expect_success 'apply --build-fake-ancestor in a subdirectory' '\n+\tgit checkout 3 &&\n+\techo \"C\" > sub/3.t &&\n+\tgit diff > 3.patch &&\n+\tgit reset --hard &&\n+\tgit checkout 4 &&\n+\t(\n+\t\tcd sub &&\n+\t\tgit apply --build-fake-ancestor 3.ancestor ../3.patch &&\n+\t\ttest -f 3.ancestor\n+\t) &&\n+\tgit apply --build-fake-ancestor 3.ancestor 3.patch &&\n+\ttest_cmp sub/3.ancestor 3.ancestor\n+'\n+\n+test_done\ndiff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh\nindex 2049ab6..42f6fff 100755\n--- a/t/t6200-fmt-merge-msg.sh\n+++ b/t/t6200-fmt-merge-msg.sh\n@@ -208,4 +208,36 @@ test_expect_success 'merge-msg test #5-2' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'merge-msg -F' '\n+\n+\tgit config --unset-all merge.log\n+\tgit config --unset-all merge.summary\n+\tgit config merge.summary yes &&\n+\n+\tgit checkout master &&\n+\tsetdate &&\n+\tgit fetch . left right &&\n+\n+\tgit fmt-merge-msg -F .git/FETCH_HEAD >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'merge-msg -F in subdirectory' '\n+\n+\tgit config --unset-all merge.log\n+\tgit config --unset-all merge.summary\n+\tgit config merge.summary yes &&\n+\n+\tgit checkout master &&\n+\tsetdate &&\n+\tgit fetch . left right &&\n+\tmkdir sub &&\n+\tcp .git/FETCH_HEAD sub/FETCH_HEAD &&\n+\t(\n+\t\tcd sub &&\n+\t\tgit fmt-merge-msg -F FETCH_HEAD >../actual\n+\t) &&\n+\ttest_cmp expected actual\n+'\n+\n test_done\n-- \n1.6.3.1.145.gb74d77\n"},{"id":"114522","messageId":"1243104793-3254-4-git-send-email-bebarino@gmail.com","threadId":"19453","inReplyTo":"1243104793-3254-3-git-send-email-bebarino@gmail.com","subject":"[PATCH 3/4] parse-opts: prepare for OPT_FILENAME","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-05-23T18:53:12Z","receivedAt":"2009-05-23T18:53:12Z","isPatch":true,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"To give OPT_FILENAME the prefix, we pass the prefix to parse_options()\nwhich passes the prefix to parse_options_start() which sets the prefix\nmember of parse_opts_ctx accordingly. If there isn't a prefix in the\ncalling context, passing NULL will suffice.\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n\nThis is mostly passing prefix through.\n\n Documentation/technical/api-parse-options.txt |    4 ++--\n archive.c                                     |    2 +-\n builtin-add.c                                 |    2 +-\n builtin-apply.c                               |    2 +-\n builtin-archive.c                             |    3 ++-\n builtin-bisect--helper.c                      |    3 ++-\n builtin-blame.c                               |    2 +-\n builtin-branch.c                              |    3 ++-\n builtin-cat-file.c                            |    2 +-\n builtin-check-attr.c                          |    4 ++--\n builtin-checkout-index.c                      |    2 +-\n builtin-checkout.c                            |    2 +-\n builtin-clean.c                               |    3 ++-\n builtin-clone.c                               |    2 +-\n builtin-commit.c                              |    3 ++-\n builtin-config.c                              |    3 ++-\n builtin-count-objects.c                       |    2 +-\n builtin-describe.c                            |    2 +-\n builtin-fast-export.c                         |    2 +-\n builtin-fetch.c                               |    2 +-\n builtin-fmt-merge-msg.c                       |    3 ++-\n builtin-for-each-ref.c                        |    2 +-\n builtin-fsck.c                                |    2 +-\n builtin-gc.c                                  |    3 ++-\n builtin-grep.c                                |    2 +-\n builtin-help.c                                |    2 +-\n builtin-ls-files.c                            |    2 +-\n builtin-merge-base.c                          |    2 +-\n builtin-merge-file.c                          |    2 +-\n builtin-merge.c                               |    4 ++--\n builtin-mv.c                                  |    3 ++-\n builtin-name-rev.c                            |    2 +-\n builtin-pack-refs.c                           |    2 +-\n builtin-prune.c                               |    2 +-\n builtin-push.c                                |    2 +-\n builtin-remote.c                              |   16 ++++++++++------\n builtin-reset.c                               |    2 +-\n builtin-rev-parse.c                           |    4 ++--\n builtin-revert.c                              |    2 +-\n builtin-rm.c                                  |    3 ++-\n builtin-shortlog.c                            |    2 +-\n builtin-symbolic-ref.c                        |    3 ++-\n builtin-tag.c                                 |    2 +-\n builtin-update-ref.c                          |    3 ++-\n hash-object.c                                 |    3 ++-\n parse-options.c                               |   11 +++++++----\n parse-options.h                               |    6 ++++--\n test-parse-options.c                          |    2 +-\n 48 files changed, 83 insertions(+), 61 deletions(-)\n\ndiff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt\nindex b43458e..aace580 100644\n--- a/Documentation/technical/api-parse-options.txt\n+++ b/Documentation/technical/api-parse-options.txt\n@@ -60,13 +60,13 @@ Steps to parse options\n . in `cmd_foo(int argc, const char **argv, const char *prefix)`\n   call\n \n-\targc = parse_options(argc, argv, builtin_foo_options, builtin_foo_usage, flags);\n+\targc = parse_options(argc, argv, prefix, builtin_foo_options, builtin_foo_usage, flags);\n +\n `parse_options()` will filter out the processed options of `argv[]` and leave the\n non-option arguments in `argv[]`.\n `argc` is updated appropriately because of the assignment.\n +\n-You can also pass NULL instead of a usage array as fourth parameter of\n+You can also pass NULL instead of a usage array as the fifth parameter of\n parse_options(), to avoid displaying a help screen with usage info and\n option list.  This should only be done if necessary, e.g. to implement\n a limited parser for only a subset of the options that needs to be run\ndiff --git a/archive.c b/archive.c\nindex b2b90d3..0bca9ca 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -309,7 +309,7 @@ static int parse_archive_args(int argc, const char **argv,\n \t\tOPT_END()\n \t};\n \n-\targc = parse_options(argc, argv, opts, archive_usage, 0);\n+\targc = parse_options(argc, argv, NULL, opts, archive_usage, 0);\n \n \tif (remote)\n \t\tdie(\"Unexpected option --remote\");\ndiff --git a/builtin-add.c b/builtin-add.c\nindex bee45f0..c1b229a 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -298,7 +298,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \tint add_new_files;\n \tint require_pathspec;\n \n-\targc = parse_options(argc, argv, builtin_add_options,\n+\targc = parse_options(argc, argv, prefix, builtin_add_options,\n \t\t\t  builtin_add_usage, PARSE_OPT_KEEP_ARGV0);\n \tif (patch_interactive)\n \t\tadd_interactive = 1;\ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex a40b982..bac03d7 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -3313,7 +3313,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)\n \tif (apply_default_whitespace)\n \t\tparse_whitespace_option(apply_default_whitespace);\n \n-\targc = parse_options(argc, argv, builtin_apply_options,\n+\targc = parse_options(argc, argv, prefix, builtin_apply_options,\n \t\t\tapply_usage, 0);\n \tfake_ancestor = parse_options_fix_filename(prefix, fake_ancestor);\n \tif (fake_ancestor)\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex ab50ceb..3c5a5a7 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -80,7 +80,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix)\n \t\tOPT_END()\n \t};\n \n-\targc = parse_options(argc, argv, local_opts, NULL, PARSE_OPT_KEEP_ALL);\n+\targc = parse_options(argc, argv, prefix, local_opts, NULL,\n+\t\t\t     PARSE_OPT_KEEP_ALL);\n \n \tif (output)\n \t\tcreate_output_file(output);\ndiff --git a/builtin-bisect--helper.c b/builtin-bisect--helper.c\nindex cb3e155..5b22639 100644\n--- a/builtin-bisect--helper.c\n+++ b/builtin-bisect--helper.c\n@@ -17,7 +17,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)\n \t\tOPT_END()\n \t};\n \n-\targc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options,\n+\t\t\t     git_bisect_helper_usage, 0);\n \n \tif (!next_all)\n \t\tusage_with_options(git_bisect_helper_usage, options);\ndiff --git a/builtin-blame.c b/builtin-blame.c\nindex cf74a92..9dc3335 100644\n--- a/builtin-blame.c\n+++ b/builtin-blame.c\n@@ -2229,7 +2229,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \tsave_commit_buffer = 0;\n \tdashdash_pos = 0;\n \n-\tparse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |\n+\tparse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |\n \t\t\t    PARSE_OPT_KEEP_ARGV0);\n \tfor (;;) {\n \t\tswitch (parse_options_step(&ctx, options, blame_opt_usage)) {\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 6aaa708..5687d60 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -610,7 +610,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t}\n \thashcpy(merge_filter_ref, head_sha1);\n \n-\targc = parse_options(argc, argv, options, builtin_branch_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, builtin_branch_usage,\n+\t\t\t     0);\n \tif (!!delete + !!rename + !!force_create > 1)\n \t\tusage_with_options(builtin_branch_usage, options);\n \ndiff --git a/builtin-cat-file.c b/builtin-cat-file.c\nindex 8fad19d..991e40f 100644\n--- a/builtin-cat-file.c\n+++ b/builtin-cat-file.c\n@@ -231,7 +231,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n \tif (argc != 3 && argc != 2)\n \t\tusage_with_options(cat_file_usage, options);\n \n-\targc = parse_options(argc, argv, options, cat_file_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);\n \n \tif (opt) {\n \t\tif (argc == 1)\ndiff --git a/builtin-check-attr.c b/builtin-check-attr.c\nindex 15a04b7..8bd0430 100644\n--- a/builtin-check-attr.c\n+++ b/builtin-check-attr.c\n@@ -69,8 +69,8 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)\n \tint cnt, i, doubledash;\n \tconst char *errstr = NULL;\n \n-\targc = parse_options(argc, argv, check_attr_options, check_attr_usage,\n-\t\tPARSE_OPT_KEEP_DASHDASH);\n+\targc = parse_options(argc, argv, prefix, check_attr_options,\n+\t\t\t     check_attr_usage, PARSE_OPT_KEEP_DASHDASH);\n \tif (!argc)\n \t\tusage_with_options(check_attr_usage, check_attr_options);\n \ndiff --git a/builtin-checkout-index.c b/builtin-checkout-index.c\nindex afe35e2..a7a5ee1 100644\n--- a/builtin-checkout-index.c\n+++ b/builtin-checkout-index.c\n@@ -249,7 +249,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)\n \t\tdie(\"invalid cache\");\n \t}\n \n-\targc = parse_options(argc, argv, builtin_checkout_index_options,\n+\targc = parse_options(argc, argv, prefix, builtin_checkout_index_options,\n \t\t\tbuiltin_checkout_index_usage, 0);\n \tstate.force = force;\n \tstate.quiet = quiet;\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex b8a4b01..8a9a474 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -605,7 +605,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \n \topts.track = BRANCH_TRACK_UNSPECIFIED;\n \n-\targc = parse_options(argc, argv, options, checkout_usage,\n+\targc = parse_options(argc, argv, prefix, options, checkout_usage,\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n \n \t/* --track without -b should DWIM */\ndiff --git a/builtin-clean.c b/builtin-clean.c\nindex c5ad33d..1c1b6d2 100644\n--- a/builtin-clean.c\n+++ b/builtin-clean.c\n@@ -56,7 +56,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \telse\n \t\tconfig_set = 1;\n \n-\targc = parse_options(argc, argv, options, builtin_clean_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, builtin_clean_usage,\n+\t\t\t     0);\n \n \tmemset(&dir, 0, sizeof(dir));\n \tif (ignored_only)\ndiff --git a/builtin-clone.c b/builtin-clone.c\nindex c935833..5c46496 100644\n--- a/builtin-clone.c\n+++ b/builtin-clone.c\n@@ -360,7 +360,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \n \tjunk_pid = getpid();\n \n-\targc = parse_options(argc, argv, builtin_clone_options,\n+\targc = parse_options(argc, argv, prefix, builtin_clone_options,\n \t\t\t     builtin_clone_usage, 0);\n \n \tif (argc == 0)\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex baaa75c..b9a1528 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -697,7 +697,8 @@ static int parse_and_validate_options(int argc, const char *argv[],\n {\n \tint f = 0;\n \n-\targc = parse_options(argc, argv, builtin_commit_options, usage, 0);\n+\targc = parse_options(argc, argv, prefix, builtin_commit_options, usage,\n+\t\t\t     0);\n \tlogfile = parse_options_fix_filename(prefix, logfile);\n \tif (logfile)\n \t\tlogfile = xstrdup(logfile);\ndiff --git a/builtin-config.c b/builtin-config.c\nindex a81bc8b..60915f9 100644\n--- a/builtin-config.c\n+++ b/builtin-config.c\n@@ -316,7 +316,8 @@ int cmd_config(int argc, const char **argv, const char *unused_prefix)\n \n \tconfig_exclusive_filename = getenv(CONFIG_ENVIRONMENT);\n \n-\targc = parse_options(argc, argv, builtin_config_options, builtin_config_usage,\n+\targc = parse_options(argc, argv, prefix, builtin_config_options,\n+\t\t\t     builtin_config_usage,\n \t\t\t     PARSE_OPT_STOP_AT_NON_OPTION);\n \n \tif (use_global_config + use_system_config + !!given_config_file > 1) {\ndiff --git a/builtin-count-objects.c b/builtin-count-objects.c\nindex b814fe5..1b0b6c8 100644\n--- a/builtin-count-objects.c\n+++ b/builtin-count-objects.c\n@@ -83,7 +83,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)\n \t\tOPT_END(),\n \t};\n \n-\targc = parse_options(argc, argv, opts, count_objects_usage, 0);\n+\targc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0);\n \t/* we do not take arguments other than flags for now */\n \tif (argc)\n \t\tusage_with_options(count_objects_usage, opts);\ndiff --git a/builtin-describe.c b/builtin-describe.c\nindex 63c6a19..7a66298 100644\n--- a/builtin-describe.c\n+++ b/builtin-describe.c\n@@ -322,7 +322,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)\n \t\tOPT_END(),\n \t};\n \n-\targc = parse_options(argc, argv, options, describe_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, describe_usage, 0);\n \tif (max_candidates < 0)\n \t\tmax_candidates = 0;\n \telse if (max_candidates > MAX_TAGS)\ndiff --git a/builtin-fast-export.c b/builtin-fast-export.c\nindex 6731713..6cef810 100644\n--- a/builtin-fast-export.c\n+++ b/builtin-fast-export.c\n@@ -515,7 +515,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \n \tinit_revisions(&revs, prefix);\n \targc = setup_revisions(argc, argv, &revs, NULL);\n-\targc = parse_options(argc, argv, options, fast_export_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, fast_export_usage, 0);\n \tif (argc > 1)\n \t\tusage_with_options (fast_export_usage, options);\n \ndiff --git a/builtin-fetch.c b/builtin-fetch.c\nindex 77acabf..0ed6016 100644\n--- a/builtin-fetch.c\n+++ b/builtin-fetch.c\n@@ -634,7 +634,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)\n \tfor (i = 1; i < argc; i++)\n \t\tstrbuf_addf(&default_rla, \" %s\", argv[i]);\n \n-\targc = parse_options(argc, argv,\n+\targc = parse_options(argc, argv, prefix,\n \t\t\t     builtin_fetch_options, builtin_fetch_usage, 0);\n \n \tif (argc == 0)\ndiff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c\nindex fae1482..d4c7206 100644\n--- a/builtin-fmt-merge-msg.c\n+++ b/builtin-fmt-merge-msg.c\n@@ -360,7 +360,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \tint ret;\n \n \tgit_config(fmt_merge_msg_config, NULL);\n-\targc = parse_options(argc, argv, options, fmt_merge_msg_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage,\n+\t\t\t     0);\n \tif (argc > 0)\n \t\tusage_with_options(fmt_merge_msg_usage, options);\n \tinpath = parse_options_fix_filename(prefix, inpath);\ndiff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c\nindex d091e04..784733b 100644\n--- a/builtin-for-each-ref.c\n+++ b/builtin-for-each-ref.c\n@@ -905,7 +905,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \t\tOPT_END(),\n \t};\n \n-\tparse_options(argc, argv, opts, for_each_ref_usage, 0);\n+\tparse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);\n \tif (maxcount < 0) {\n \t\terror(\"invalid --count argument: `%d'\", maxcount);\n \t\tusage_with_options(for_each_ref_usage, opts);\ndiff --git a/builtin-fsck.c b/builtin-fsck.c\nindex 6436bc2..7da706c 100644\n--- a/builtin-fsck.c\n+++ b/builtin-fsck.c\n@@ -590,7 +590,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \n \terrors_found = 0;\n \n-\targc = parse_options(argc, argv, fsck_opts, fsck_usage, 0);\n+\targc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);\n \tif (write_lost_and_found) {\n \t\tcheck_full = 1;\n \t\tinclude_reflogs = 0;\ndiff --git a/builtin-gc.c b/builtin-gc.c\nindex fc556ed..7d3e9cc 100644\n--- a/builtin-gc.c\n+++ b/builtin-gc.c\n@@ -194,7 +194,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)\n \tif (pack_refs < 0)\n \t\tpack_refs = !is_bare_repository();\n \n-\targc = parse_options(argc, argv, builtin_gc_options, builtin_gc_usage, 0);\n+\targc = parse_options(argc, argv, prefix, builtin_gc_options,\n+\t\t\t     builtin_gc_usage, 0);\n \tif (argc > 0)\n \t\tusage_with_options(builtin_gc_usage, builtin_gc_options);\n \ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex 5308b34..73fc922 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -765,7 +765,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t * unrecognized non option is the beginning of the refs list\n \t * that continues up to the -- (if exists), and then paths.\n \t */\n-\targc = parse_options(argc, argv, options, grep_usage,\n+\targc = parse_options(argc, argv, prefix, options, grep_usage,\n \t\t\t     PARSE_OPT_KEEP_DASHDASH |\n \t\t\t     PARSE_OPT_STOP_AT_NON_OPTION |\n \t\t\t     PARSE_OPT_NO_INTERNAL_HELP);\ndiff --git a/builtin-help.c b/builtin-help.c\nindex 67dda3e..af565fb 100644\n--- a/builtin-help.c\n+++ b/builtin-help.c\n@@ -423,7 +423,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)\n \tsetup_git_directory_gently(&nongit);\n \tgit_config(git_help_config, NULL);\n \n-\targc = parse_options(argc, argv, builtin_help_options,\n+\targc = parse_options(argc, argv, prefix, builtin_help_options,\n \t\t\tbuiltin_help_usage, 0);\n \n \tif (show_all) {\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex 3d59b0e..2312866 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -486,7 +486,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \t\tprefix_offset = strlen(prefix);\n \tgit_config(git_default_config, NULL);\n \n-\targc = parse_options(argc, argv, builtin_ls_files_options,\n+\targc = parse_options(argc, argv, prefix, builtin_ls_files_options,\n \t\t\tls_files_usage, 0);\n \tif (show_tag || show_valid_bit) {\n \t\ttag_cached = \"H \";\ndiff --git a/builtin-merge-base.c b/builtin-merge-base.c\nindex 03fc1c2..a6ec2f7 100644\n--- a/builtin-merge-base.c\n+++ b/builtin-merge-base.c\n@@ -53,7 +53,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)\n \t};\n \n \tgit_config(git_default_config, NULL);\n-\targc = parse_options(argc, argv, options, merge_base_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);\n \tif (argc < 2)\n \t\tusage_with_options(merge_base_usage, options);\n \trev = xmalloc(argc * sizeof(*rev));\ndiff --git a/builtin-merge-file.c b/builtin-merge-file.c\nindex 96edb97..afd2ea7 100644\n--- a/builtin-merge-file.c\n+++ b/builtin-merge-file.c\n@@ -48,7 +48,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)\n \t\t\tmerge_style = git_xmerge_style;\n \t}\n \n-\targc = parse_options(argc, argv, options, merge_file_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);\n \tif (argc != 3)\n \t\tusage_with_options(merge_file_usage, options);\n \tif (quiet) {\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex 0b58e5e..8d101ef 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -462,7 +462,7 @@ static int git_merge_config(const char *k, const char *v, void *cb)\n \t\targv = xrealloc(argv, sizeof(*argv) * (argc + 2));\n \t\tmemmove(argv + 1, argv, sizeof(*argv) * (argc + 1));\n \t\targc++;\n-\t\tparse_options(argc, argv, builtin_merge_options,\n+\t\tparse_options(argc, argv, NULL, builtin_merge_options,\n \t\t\t      builtin_merge_usage, 0);\n \t\tfree(buf);\n \t}\n@@ -855,7 +855,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \tif (diff_use_color_default == -1)\n \t\tdiff_use_color_default = git_use_color_default;\n \n-\targc = parse_options(argc, argv, builtin_merge_options,\n+\targc = parse_options(argc, argv, prefix, builtin_merge_options,\n \t\t\tbuiltin_merge_usage, 0);\n \tif (verbosity < 0)\n \t\tshow_diffstat = 0;\ndiff --git a/builtin-mv.c b/builtin-mv.c\nindex 01270fe..8b81d4b 100644\n--- a/builtin-mv.c\n+++ b/builtin-mv.c\n@@ -72,7 +72,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \tif (read_cache() < 0)\n \t\tdie(\"index file corrupt\");\n \n-\targc = parse_options(argc, argv, builtin_mv_options, builtin_mv_usage, 0);\n+\targc = parse_options(argc, argv, prefix, builtin_mv_options,\n+\t\t\t     builtin_mv_usage, 0);\n \tif (--argc < 1)\n \t\tusage_with_options(builtin_mv_usage, builtin_mv_options);\n \ndiff --git a/builtin-name-rev.c b/builtin-name-rev.c\nindex 08c8aab..06a38ac 100644\n--- a/builtin-name-rev.c\n+++ b/builtin-name-rev.c\n@@ -238,7 +238,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)\n \t};\n \n \tgit_config(git_default_config, NULL);\n-\targc = parse_options(argc, argv, opts, name_rev_usage, 0);\n+\targc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);\n \tif (!!all + !!transform_stdin + !!argc > 1) {\n \t\terror(\"Specify either a list, or --all, not both!\");\n \t\tusage_with_options(name_rev_usage, opts);\ndiff --git a/builtin-pack-refs.c b/builtin-pack-refs.c\nindex 34246df..091860b 100644\n--- a/builtin-pack-refs.c\n+++ b/builtin-pack-refs.c\n@@ -15,7 +15,7 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)\n \t\tOPT_BIT(0, \"prune\", &flags, \"prune loose refs (default)\", PACK_REFS_PRUNE),\n \t\tOPT_END(),\n \t};\n-\tif (parse_options(argc, argv, opts, pack_refs_usage, 0))\n+\tif (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))\n \t\tusage_with_options(pack_refs_usage, opts);\n \treturn pack_refs(flags);\n }\ndiff --git a/builtin-prune.c b/builtin-prune.c\nindex 145ba83..0ed9cce 100644\n--- a/builtin-prune.c\n+++ b/builtin-prune.c\n@@ -142,7 +142,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)\n \tsave_commit_buffer = 0;\n \tinit_revisions(&revs, prefix);\n \n-\targc = parse_options(argc, argv, options, prune_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, prune_usage, 0);\n \twhile (argc--) {\n \t\tunsigned char sha1[20];\n \t\tconst char *name = *argv++;\ndiff --git a/builtin-push.c b/builtin-push.c\nindex 2eabcd3..c869974 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -198,7 +198,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \t\tOPT_END()\n \t};\n \n-\targc = parse_options(argc, argv, options, push_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, push_usage, 0);\n \n \tif (tags)\n \t\tadd_refspec(\"refs/tags/*\");\ndiff --git a/builtin-remote.c b/builtin-remote.c\nindex 71abf68..13d5db1 100644\n--- a/builtin-remote.c\n+++ b/builtin-remote.c\n@@ -79,7 +79,8 @@ static int add(int argc, const char **argv)\n \t\tOPT_END()\n \t};\n \n-\targc = parse_options(argc, argv, options, builtin_remote_usage, 0);\n+\targc = parse_options(argc, argv, NULL, options, builtin_remote_usage,\n+\t\t\t     0);\n \n \tif (argc < 2)\n \t\tusage_with_options(builtin_remote_usage, options);\n@@ -986,7 +987,8 @@ static int show(int argc, const char **argv)\n \tstruct string_list info_list = { NULL, 0, 0, 0 };\n \tstruct show_info info;\n \n-\targc = parse_options(argc, argv, options, builtin_remote_usage, 0);\n+\targc = parse_options(argc, argv, NULL, options, builtin_remote_usage,\n+\t\t\t     0);\n \n \tif (argc < 1)\n \t\treturn show_all();\n@@ -1076,7 +1078,8 @@ static int set_head(int argc, const char **argv)\n \t\t\t    \"delete refs/remotes/<name>/HEAD\"),\n \t\tOPT_END()\n \t};\n-\targc = parse_options(argc, argv, options, builtin_remote_usage, 0);\n+\targc = parse_options(argc, argv, NULL, options, builtin_remote_usage,\n+\t\t\t     0);\n \tif (argc)\n \t\tstrbuf_addf(&buf, \"refs/remotes/%s/HEAD\", argv[0]);\n \n@@ -1130,7 +1133,8 @@ static int prune(int argc, const char **argv)\n \t\tOPT_END()\n \t};\n \n-\targc = parse_options(argc, argv, options, builtin_remote_usage, 0);\n+\targc = parse_options(argc, argv, NULL, options, builtin_remote_usage,\n+\t\t\t     0);\n \n \tif (argc < 1)\n \t\tusage_with_options(builtin_remote_usage, options);\n@@ -1220,7 +1224,7 @@ static int update(int argc, const char **argv)\n \t\tOPT_END()\n \t};\n \n-\targc = parse_options(argc, argv, options, builtin_remote_usage,\n+\targc = parse_options(argc, argv, NULL, options, builtin_remote_usage,\n \t\t\t     PARSE_OPT_KEEP_ARGV0);\n \tif (argc < 2) {\n \t\targc = 2;\n@@ -1306,7 +1310,7 @@ int cmd_remote(int argc, const char **argv, const char *prefix)\n \t};\n \tint result;\n \n-\targc = parse_options(argc, argv, options, builtin_remote_usage,\n+\targc = parse_options(argc, argv, prefix, options, builtin_remote_usage,\n \t\tPARSE_OPT_STOP_AT_NON_OPTION);\n \n \tif (argc < 1)\ndiff --git a/builtin-reset.c b/builtin-reset.c\nindex 7e7ebab..5fa1789 100644\n--- a/builtin-reset.c\n+++ b/builtin-reset.c\n@@ -203,7 +203,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \n \tgit_config(git_default_config, NULL);\n \n-\targc = parse_options(argc, argv, options, git_reset_usage,\n+\targc = parse_options(argc, argv, prefix, options, git_reset_usage,\n \t\t\t\t\t\tPARSE_OPT_KEEP_DASHDASH);\n \treflog_action = args_to_str(argv);\n \tsetenv(\"GIT_REFLOG_ACTION\", reflog_action, 0);\ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex c5b3d6e..112d622 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -318,7 +318,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \tint onb = 0, osz = 0, unb = 0, usz = 0;\n \n \tstrbuf_addstr(&parsed, \"set --\");\n-\targc = parse_options(argc, argv, parseopt_opts, parseopt_usage,\n+\targc = parse_options(argc, argv, prefix, parseopt_opts, parseopt_usage,\n \t                     PARSE_OPT_KEEP_DASHDASH);\n \tif (argc < 1 || strcmp(argv[0], \"--\"))\n \t\tusage_with_options(parseopt_usage, parseopt_opts);\n@@ -393,7 +393,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \t/* put an OPT_END() */\n \tALLOC_GROW(opts, onb + 1, osz);\n \tmemset(opts + onb, 0, sizeof(opts[onb]));\n-\targc = parse_options(argc, argv, opts, usage,\n+\targc = parse_options(argc, argv, prefix, opts, usage,\n \t                     keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0);\n \n \tstrbuf_addf(&parsed, \" --\");\ndiff --git a/builtin-revert.c b/builtin-revert.c\nindex 3f2614e..fa4752f 100644\n--- a/builtin-revert.c\n+++ b/builtin-revert.c\n@@ -60,7 +60,7 @@ static void parse_args(int argc, const char **argv)\n \t\tOPT_END(),\n \t};\n \n-\tif (parse_options(argc, argv, options, usage_str, 0) != 1)\n+\tif (parse_options(argc, argv, NULL, options, usage_str, 0) != 1)\n \t\tusage_with_options(usage_str, options);\n \targ = argv[0];\n \ndiff --git a/builtin-rm.c b/builtin-rm.c\nindex 269d608..0cc4912 100644\n--- a/builtin-rm.c\n+++ b/builtin-rm.c\n@@ -157,7 +157,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix)\n \n \tgit_config(git_default_config, NULL);\n \n-\targc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0);\n+\targc = parse_options(argc, argv, prefix, builtin_rm_options,\n+\t\t\t     builtin_rm_usage, 0);\n \tif (!argc)\n \t\tusage_with_options(builtin_rm_usage, builtin_rm_options);\n \ndiff --git a/builtin-shortlog.c b/builtin-shortlog.c\nindex b28091b..6a3812e 100644\n--- a/builtin-shortlog.c\n+++ b/builtin-shortlog.c\n@@ -263,7 +263,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)\n \tgit_config(git_default_config, NULL);\n \tshortlog_init(&log);\n \tinit_revisions(&rev, prefix);\n-\tparse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |\n+\tparse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |\n \t\t\t    PARSE_OPT_KEEP_ARGV0);\n \n \tfor (;;) {\ndiff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c\nindex 6ae6bcc..ca855a5 100644\n--- a/builtin-symbolic-ref.c\n+++ b/builtin-symbolic-ref.c\n@@ -36,7 +36,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)\n \t};\n \n \tgit_config(git_default_config, NULL);\n-\targc = parse_options(argc, argv, options, git_symbolic_ref_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options,\n+\t\t\t     git_symbolic_ref_usage, 0);\n \tif (msg &&!*msg)\n \t\tdie(\"Refusing to perform update with empty message\");\n \tswitch (argc) {\ndiff --git a/builtin-tag.c b/builtin-tag.c\nindex e544430..6e8b464 100644\n--- a/builtin-tag.c\n+++ b/builtin-tag.c\n@@ -405,7 +405,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \n \tgit_config(git_tag_config, NULL);\n \n-\targc = parse_options(argc, argv, options, git_tag_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);\n \tmsgfile = parse_options_fix_filename(prefix, msgfile);\n \n \tif (keyid) {\ndiff --git a/builtin-update-ref.c b/builtin-update-ref.c\nindex 378dc1b..76ba1d5 100644\n--- a/builtin-update-ref.c\n+++ b/builtin-update-ref.c\n@@ -23,7 +23,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)\n \t};\n \n \tgit_config(git_default_config, NULL);\n-\targc = parse_options(argc, argv, options, git_update_ref_usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, git_update_ref_usage,\n+\t\t\t     0);\n \tif (msg && !*msg)\n \t\tdie(\"Refusing to perform update with empty message.\");\n \ndiff --git a/hash-object.c b/hash-object.c\nindex ebb3bed..47cf43c 100644\n--- a/hash-object.c\n+++ b/hash-object.c\n@@ -84,7 +84,8 @@ int main(int argc, const char **argv)\n \n \tgit_extract_argv0_path(argv[0]);\n \n-\targc = parse_options(argc, argv, hash_object_options, hash_object_usage, 0);\n+\targc = parse_options(argc, argv, NULL, hash_object_options,\n+\t\t\t     hash_object_usage, 0);\n \n \tif (write_object) {\n \t\tprefix = setup_git_directory();\ndiff --git a/parse-options.c b/parse-options.c\nindex c52b8cc..bfeb9d3 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -285,12 +285,14 @@ static void check_typos(const char *arg, const struct option *options)\n }\n \n void parse_options_start(struct parse_opt_ctx_t *ctx,\n-\t\t\t int argc, const char **argv, int flags)\n+\t\t\t int argc, const char **argv, const char *prefix,\n+\t\t\t int flags)\n {\n \tmemset(ctx, 0, sizeof(*ctx));\n \tctx->argc = argc - 1;\n \tctx->argv = argv + 1;\n \tctx->out  = argv;\n+\tctx->prefix = prefix;\n \tctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);\n \tctx->flags = flags;\n \tif ((flags & PARSE_OPT_KEEP_UNKNOWN) &&\n@@ -389,12 +391,13 @@ int parse_options_end(struct parse_opt_ctx_t *ctx)\n \treturn ctx->cpidx + ctx->argc;\n }\n \n-int parse_options(int argc, const char **argv, const struct option *options,\n-\t\t  const char * const usagestr[], int flags)\n+int parse_options(int argc, const char **argv, const char *prefix,\n+\t\t  const struct option *options, const char * const usagestr[],\n+\t\t  int flags)\n {\n \tstruct parse_opt_ctx_t ctx;\n \n-\tparse_options_start(&ctx, argc, argv, flags);\n+\tparse_options_start(&ctx, argc, argv, prefix, flags);\n \tswitch (parse_options_step(&ctx, options, usagestr)) {\n \tcase PARSE_OPT_HELP:\n \t\texit(129);\ndiff --git a/parse-options.h b/parse-options.h\nindex 919b9b4..624f192 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -118,7 +118,7 @@ struct option {\n  * non-option arguments in argv[].\n  * Returns the number of arguments left in argv[].\n  */\n-extern int parse_options(int argc, const char **argv,\n+extern int parse_options(int argc, const char **argv, const char *prefix,\n                          const struct option *options,\n                          const char * const usagestr[], int flags);\n \n@@ -144,13 +144,15 @@ struct parse_opt_ctx_t {\n \tint argc, cpidx;\n \tconst char *opt;\n \tint flags;\n+\tconst char *prefix;\n };\n \n extern int parse_options_usage(const char * const *usagestr,\n \t\t\t       const struct option *opts);\n \n extern void parse_options_start(struct parse_opt_ctx_t *ctx,\n-\t\t\t\tint argc, const char **argv, int flags);\n+\t\t\t\tint argc, const char **argv, const char *prefix,\n+\t\t\t\tint flags);\n \n extern int parse_options_step(struct parse_opt_ctx_t *ctx,\n \t\t\t      const struct option *options,\ndiff --git a/test-parse-options.c b/test-parse-options.c\nindex e0669dc..da3d658 100644\n--- a/test-parse-options.c\n+++ b/test-parse-options.c\n@@ -65,7 +65,7 @@ int main(int argc, const char **argv)\n \t};\n \tint i;\n \n-\targc = parse_options(argc, argv, options, usage, 0);\n+\targc = parse_options(argc, argv, NULL, options, usage, 0);\n \n \tprintf(\"boolean: %d\\n\", boolean);\n \tprintf(\"integer: %u\\n\", integer);\n-- \n1.6.3.1.145.gb74d77\n"},{"id":"114521","messageId":"1243104793-3254-5-git-send-email-bebarino@gmail.com","threadId":"19453","inReplyTo":"1243104793-3254-4-git-send-email-bebarino@gmail.com","subject":"[PATCH 4/4] parse-opts: add OPT_FILENAME and transition builtins","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-05-23T18:53:13Z","receivedAt":"2009-05-23T18:53:13Z","isPatch":true,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"Commit dbd0f5c (Files given on the command line are relative to $cwd,\n2008-08-06) introduced parse_options_fix_filename() as a minimal fix.\nOPT_FILENAME is intended to be a more robust fix for the same issue.\nOPT_FILENAME and its associated enum OPTION_FILENAME are used to\nrepresent filename options within the parse options API.\n\nThis option is similar to OPTION_STRING. If --no is prefixed to the\noption the filename is unset. If no argument is given and the default\nvalue is set, the filename is set to the default value. The difference\nis that the filename is prefixed with the prefix passed to\nparse_options() (or parse_options_start()).\n\nUpdate git-apply, git-commit, git-fmt-merge-msg, and git-tag to use\nOPT_FILENAME with their filename options. Also, rename\nparse_options_fix_filename() to fix_filename() as it is no longer\nextern.\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n Documentation/technical/api-parse-options.txt |    5 +++\n builtin-apply.c                               |    5 +---\n builtin-commit.c                              |   10 +-----\n builtin-fmt-merge-msg.c                       |    3 +-\n builtin-tag.c                                 |    3 +-\n parse-options.c                               |   36 ++++++++++++++++--------\n parse-options.h                               |    5 ++-\n t/t0040-parse-options.sh                      |   19 +++++++++++-\n test-parse-options.c                          |    6 +++-\n 9 files changed, 59 insertions(+), 33 deletions(-)\n\ndiff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt\nindex aace580..50f9e9a 100644\n--- a/Documentation/technical/api-parse-options.txt\n+++ b/Documentation/technical/api-parse-options.txt\n@@ -167,6 +167,11 @@ There are some macros to easily define options:\n \tand the result will be put into `var`.\n \tSee 'Option Callbacks' below for a more elaborate description.\n \n+`OPT_FILENAME(short, long, &var, description)`::\n+\tIntroduce an option with a filename argument.\n+\tThe filename will be prefixed by passing the filename along with\n+\tthe prefix argument of `parse_options()` to `prefix_filename()`.\n+\n `OPT_ARGUMENT(long, description)`::\n \tIntroduce a long-option argument that will be kept in `argv[]`.\n \ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex bac03d7..5329186 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -3278,7 +3278,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)\n \t\t\t\"apply a patch without touching the working tree\"),\n \t\tOPT_BOOLEAN(0, \"apply\", &force_apply,\n \t\t\t\"also apply the patch (use with --stat/--summary/--check)\"),\n-\t\tOPT_STRING(0, \"build-fake-ancestor\", &fake_ancestor, \"file\",\n+\t\tOPT_FILENAME(0, \"build-fake-ancestor\", &fake_ancestor,\n \t\t\t\"build a temporary index based on embedded index information\"),\n \t\t{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,\n \t\t\t\"paths are separated with NUL character\",\n@@ -3315,9 +3315,6 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)\n \n \targc = parse_options(argc, argv, prefix, builtin_apply_options,\n \t\t\tapply_usage, 0);\n-\tfake_ancestor = parse_options_fix_filename(prefix, fake_ancestor);\n-\tif (fake_ancestor)\n-\t\tfake_ancestor = xstrdup(fake_ancestor);\n \n \tif (apply_with_reject)\n \t\tapply = apply_verbosely = 1;\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex b9a1528..41e222d 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -88,13 +88,13 @@ static struct option builtin_commit_options[] = {\n \tOPT__VERBOSE(&verbose),\n \tOPT_GROUP(\"Commit message options\"),\n \n-\tOPT_STRING('F', \"file\", &logfile, \"FILE\", \"read log from file\"),\n+\tOPT_FILENAME('F', \"file\", &logfile, \"read log from file\"),\n \tOPT_STRING(0, \"author\", &force_author, \"AUTHOR\", \"override author for commit\"),\n \tOPT_CALLBACK('m', \"message\", &message, \"MESSAGE\", \"specify commit message\", opt_parse_m),\n \tOPT_STRING('c', \"reedit-message\", &edit_message, \"COMMIT\", \"reuse and edit message from specified commit \"),\n \tOPT_STRING('C', \"reuse-message\", &use_message, \"COMMIT\", \"reuse message from specified commit\"),\n \tOPT_BOOLEAN('s', \"signoff\", &signoff, \"add Signed-off-by:\"),\n-\tOPT_STRING('t', \"template\", &template_file, \"FILE\", \"use specified template file\"),\n+\tOPT_FILENAME('t', \"template\", &template_file, \"use specified template file\"),\n \tOPT_BOOLEAN('e', \"edit\", &edit_flag, \"force edit of commit\"),\n \n \tOPT_GROUP(\"Commit contents options\"),\n@@ -699,12 +699,6 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \n \targc = parse_options(argc, argv, prefix, builtin_commit_options, usage,\n \t\t\t     0);\n-\tlogfile = parse_options_fix_filename(prefix, logfile);\n-\tif (logfile)\n-\t\tlogfile = xstrdup(logfile);\n-\ttemplate_file = parse_options_fix_filename(prefix, template_file);\n-\tif (template_file)\n-\t\ttemplate_file = xstrdup(template_file);\n \n \tif (force_author && !strchr(force_author, '>'))\n \t\tforce_author = find_author_by_nickname(force_author);\ndiff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c\nindex d4c7206..fbf9582 100644\n--- a/builtin-fmt-merge-msg.c\n+++ b/builtin-fmt-merge-msg.c\n@@ -351,7 +351,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \tstruct option options[] = {\n \t\tOPT_BOOLEAN(0, \"log\",     &merge_summary, \"populate log with the shortlog\"),\n \t\tOPT_BOOLEAN(0, \"summary\", &merge_summary, \"alias for --log\"),\n-\t\tOPT_STRING('F', \"file\",   &inpath, \"file\", \"file to read from\"),\n+\t\tOPT_FILENAME('F', \"file\", &inpath, \"file to read from\"),\n \t\tOPT_END()\n \t};\n \n@@ -364,7 +364,6 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \t\t\t     0);\n \tif (argc > 0)\n \t\tusage_with_options(fmt_merge_msg_usage, options);\n-\tinpath = parse_options_fix_filename(prefix, inpath);\n \n \tif (inpath && strcmp(inpath, \"-\")) {\n \t\tin = fopen(inpath, \"r\");\ndiff --git a/builtin-tag.c b/builtin-tag.c\nindex 6e8b464..dc3db62 100644\n--- a/builtin-tag.c\n+++ b/builtin-tag.c\n@@ -387,7 +387,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\t\t\t\t\"annotated tag, needs a message\"),\n \t\tOPT_CALLBACK('m', NULL, &msg, \"msg\",\n \t\t\t     \"message for the tag\", parse_msg_arg),\n-\t\tOPT_STRING('F', NULL, &msgfile, \"file\", \"message in a file\"),\n+\t\tOPT_FILENAME('F', NULL, &msgfile, \"message in a file\"),\n \t\tOPT_BOOLEAN('s', NULL, &sign, \"annotated and GPG-signed tag\"),\n \t\tOPT_STRING('u', NULL, &keyid, \"key-id\",\n \t\t\t\t\t\"use another key to sign the tag\"),\n@@ -406,7 +406,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \tgit_config(git_tag_config, NULL);\n \n \targc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);\n-\tmsgfile = parse_options_fix_filename(prefix, msgfile);\n \n \tif (keyid) {\n \t\tsign = 1;\ndiff --git a/parse-options.c b/parse-options.c\nindex bfeb9d3..896ecef 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -31,11 +31,20 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,\n \treturn 0;\n }\n \n+static void fix_filename(const char *prefix, const char **file)\n+{\n+\tif (!file || !*file || !prefix || is_absolute_path(*file)\n+\t    || !strcmp(\"-\", *file))\n+\t\treturn;\n+\t*file = xstrdup(prefix_filename(prefix, strlen(prefix), *file));\n+}\n+\n static int get_value(struct parse_opt_ctx_t *p,\n \t\t     const struct option *opt, int flags)\n {\n \tconst char *s, *arg;\n \tconst int unset = flags & OPT_UNSET;\n+\tint err;\n \n \tif (unset && p->opt)\n \t\treturn opterror(opt, \"takes no value\", flags);\n@@ -95,6 +104,19 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\t\treturn get_arg(p, opt, flags, (const char **)opt->value);\n \t\treturn 0;\n \n+\tcase OPTION_FILENAME:\n+\t\terr = 0;\n+\t\tif (unset)\n+\t\t\t*(const char **)opt->value = NULL;\n+\t\telse if (opt->flags & PARSE_OPT_OPTARG && !p->opt)\n+\t\t\t*(const char **)opt->value = (const char *)opt->defval;\n+\t\telse\n+\t\t\terr = get_arg(p, opt, flags, (const char **)opt->value);\n+\n+\t\tif (!err)\n+\t\t\tfix_filename(p->prefix, (const char **)opt->value);\n+\t\treturn err;\n+\n \tcase OPTION_CALLBACK:\n \t\tif (unset)\n \t\t\treturn (*opt->callback)(opt, NULL, 1) ? (-1) : 0;\n@@ -480,6 +502,8 @@ int usage_with_options_internal(const char * const *usagestr,\n \t\t\tif (opts->flags & PARSE_OPT_NOARG)\n \t\t\t\tbreak;\n \t\t\t/* FALLTHROUGH */\n+\t\tcase OPTION_FILENAME:\n+\t\t\t/* FALLTHROUGH */\n \t\tcase OPTION_STRING:\n \t\t\tif (opts->argh) {\n \t\t\t\tif (opts->flags & PARSE_OPT_OPTARG)\n@@ -596,15 +620,3 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)\n \tcommit_list_insert(commit, opt->value);\n \treturn 0;\n }\n-\n-/*\n- * This should really be OPTION_FILENAME type as a part of\n- * parse_options that take prefix to do this while parsing.\n- */\n-extern const char *parse_options_fix_filename(const char *prefix, const char *file)\n-{\n-\tif (!file || !prefix || is_absolute_path(file) || !strcmp(\"-\", file))\n-\t\treturn file;\n-\treturn prefix_filename(prefix, strlen(prefix), file);\n-}\n-\ndiff --git a/parse-options.h b/parse-options.h\nindex 624f192..6fe3d5d 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -17,6 +17,7 @@ enum parse_opt_type {\n \tOPTION_STRING,\n \tOPTION_INTEGER,\n \tOPTION_CALLBACK,\n+\tOPTION_FILENAME\n };\n \n enum parse_opt_flags {\n@@ -113,6 +114,8 @@ struct option {\n #define OPT_NUMBER_CALLBACK(v, h, f) \\\n \t{ OPTION_NUMBER, 0, NULL, (v), NULL, (h), \\\n \t  PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }\n+#define OPT_FILENAME(s, l, v, h)    { OPTION_FILENAME, (s), (l), (v), \\\n+\t\t\t\t       \"FILE\", (h) }\n \n /* parse_options() will filter out the processed options and leave the\n  * non-option arguments in argv[].\n@@ -180,6 +183,4 @@ extern int parse_opt_with_commit(const struct option *, const char *, int);\n \t  \"use <n> digits to display SHA-1s\", \\\n \t  PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }\n \n-extern const char *parse_options_fix_filename(const char *prefix, const char *file);\n-\n #endif\ndiff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh\nindex a40c123..bbc821e 100755\n--- a/t/t0040-parse-options.sh\n+++ b/t/t0040-parse-options.sh\n@@ -19,6 +19,7 @@ usage: test-parse-options <options>\n     --set23               set integer to 23\n     -t <time>             get timestamp of <time>\n     -L, --length <str>    get length of <str>\n+    -F, --file <FILE>     set file to <FILE>\n \n String options\n     -s, --string <string>\n@@ -56,10 +57,12 @@ abbrev: 7\n verbose: 2\n quiet: no\n dry run: yes\n+file: prefix/my.file\n EOF\n \n test_expect_success 'short options' '\n-\ttest-parse-options -s123 -b -i 1729 -b -vv -n > output 2> output.err &&\n+\ttest-parse-options -s123 -b -i 1729 -b -vv -n -F my.file \\\n+\t> output 2> output.err &&\n \ttest_cmp expect output &&\n \ttest ! -s output.err\n '\n@@ -73,11 +76,12 @@ abbrev: 10\n verbose: 2\n quiet: no\n dry run: no\n+file: prefix/fi.le\n EOF\n \n test_expect_success 'long options' '\n \ttest-parse-options --boolean --integer 1729 --boolean --string2=321 \\\n-\t\t--verbose --verbose --no-dry-run --abbrev=10 \\\n+\t\t--verbose --verbose --no-dry-run --abbrev=10 --file fi.le\\\n \t\t> output 2> output.err &&\n \ttest ! -s output.err &&\n \ttest_cmp expect output\n@@ -87,6 +91,8 @@ test_expect_success 'missing required value' '\n \ttest-parse-options -s;\n \ttest $? = 129 &&\n \ttest-parse-options --string;\n+\ttest $? = 129 &&\n+\ttest-parse-options --file;\n \ttest $? = 129\n '\n \n@@ -99,6 +105,7 @@ abbrev: 7\n verbose: 0\n quiet: no\n dry run: no\n+file: (not set)\n arg 00: a1\n arg 01: b1\n arg 02: --boolean\n@@ -120,6 +127,7 @@ abbrev: 7\n verbose: 0\n quiet: no\n dry run: no\n+file: (not set)\n EOF\n \n test_expect_success 'unambiguously abbreviated option' '\n@@ -148,6 +156,7 @@ abbrev: 7\n verbose: 0\n quiet: no\n dry run: no\n+file: (not set)\n EOF\n \n test_expect_success 'non ambiguous option (after two options it abbreviates)' '\n@@ -175,6 +184,7 @@ abbrev: 7\n verbose: 0\n quiet: no\n dry run: no\n+file: (not set)\n arg 00: --quux\n EOF\n \n@@ -193,6 +203,7 @@ abbrev: 7\n verbose: 0\n quiet: yes\n dry run: no\n+file: (not set)\n arg 00: foo\n EOF\n \n@@ -213,6 +224,7 @@ abbrev: 7\n verbose: 0\n quiet: no\n dry run: no\n+file: (not set)\n EOF\n \n test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '\n@@ -240,6 +252,7 @@ abbrev: 7\n verbose: 0\n quiet: no\n dry run: no\n+file: (not set)\n EOF\n \n test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '\n@@ -263,6 +276,7 @@ abbrev: 7\n verbose: 0\n quiet: no\n dry run: no\n+file: (not set)\n EOF\n \n test_expect_success 'OPT_BIT() works' '\n@@ -292,6 +306,7 @@ abbrev: 7\n verbose: 0\n quiet: no\n dry run: no\n+file: (not set)\n EOF\n \n test_expect_success 'OPT_NUMBER_CALLBACK() works' '\ndiff --git a/test-parse-options.c b/test-parse-options.c\nindex da3d658..a90bc30 100644\n--- a/test-parse-options.c\n+++ b/test-parse-options.c\n@@ -7,6 +7,7 @@ static unsigned long timestamp;\n static int abbrev = 7;\n static int verbose = 0, dry_run = 0, quiet = 0;\n static char *string = NULL;\n+static char *file = NULL;\n \n int length_callback(const struct option *opt, const char *arg, int unset)\n {\n@@ -27,6 +28,7 @@ int number_callback(const struct option *opt, const char *arg, int unset)\n \n int main(int argc, const char **argv)\n {\n+\tconst char *prefix = \"prefix/\";\n \tconst char *usage[] = {\n \t\t\"test-parse-options <options>\",\n \t\tNULL\n@@ -43,6 +45,7 @@ int main(int argc, const char **argv)\n \t\tOPT_DATE('t', NULL, &timestamp, \"get timestamp of <time>\"),\n \t\tOPT_CALLBACK('L', \"length\", &integer, \"str\",\n \t\t\t\"get length of <str>\", length_callback),\n+\t\tOPT_FILENAME('F', \"file\", &file, \"set file to <FILE>\"),\n \t\tOPT_GROUP(\"String options\"),\n \t\tOPT_STRING('s', \"string\", &string, \"string\", \"get a string\"),\n \t\tOPT_STRING(0, \"string2\", &string, \"str\", \"get another string\"),\n@@ -65,7 +68,7 @@ int main(int argc, const char **argv)\n \t};\n \tint i;\n \n-\targc = parse_options(argc, argv, NULL, options, usage, 0);\n+\targc = parse_options(argc, argv, prefix, options, usage, 0);\n \n \tprintf(\"boolean: %d\\n\", boolean);\n \tprintf(\"integer: %u\\n\", integer);\n@@ -75,6 +78,7 @@ int main(int argc, const char **argv)\n \tprintf(\"verbose: %d\\n\", verbose);\n \tprintf(\"quiet: %s\\n\", quiet ? \"yes\" : \"no\");\n \tprintf(\"dry run: %s\\n\", dry_run ? \"yes\" : \"no\");\n+\tprintf(\"file: %s\\n\", file ? file : \"(not set)\");\n \n \tfor (i = 0; i < argc; i++)\n \t\tprintf(\"arg %02d: %s\\n\", i, argv[i]);\n-- \n1.6.3.1.145.gb74d77\n"}]}