{"thread":{"id":"18147","subject":"What's in git.git (Mar 2009, #02; Thu, 05)","startedAt":"2009-03-05T10:07:03Z","lastAt":"2009-03-09T20:57:38Z","messageCount":13,"participants":["Junio C Hamano","René Scharfe"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"107043","messageId":"7vfxhs2shk.fsf@gitster.siamese.dyndns.org","threadId":"18147","inReplyTo":null,"subject":"What's in git.git (Mar 2009, #02; Thu, 05)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-05T10:07:03Z","receivedAt":"2009-03-05T10:07:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The release is out, and immediately after that somebody spots a minor\nbug.\n\nIf things go as planned, tomorrow we will see a mass graduation to the\nmaster branch of topics that have been cooking in next during the pre\nrelease freeze period.\n\n* The 'maint' branch has these fixes since v1.6.2\n\nJohn Tapsell (1):\n  Make the 'lock file' exists error more informative\n\nJunio C Hamano (1):\n  Beginning of 1.6.2 maintenance track\n\n\n* The 'master' branch has these since v1.6.2 in addition to the above.\n\nCarlos Manuel Duclos Vergara (1):\n  git-archive: add --output=<file> to send output to a file\n\nChristian Couder (1):\n  rev-list: estimate number of bisection step left\n\nJeff King (1):\n  improve missing repository error message\n\nJohn Tapsell (3):\n  Modify description file to say what this file is\n  Google has renamed the imap folder\n  Improve error message for git-filter-branch\n\nKeith Cascio (2):\n  Use DIFF_XDL_SET/DIFF_OPT_SET instead of raw bit-masking\n  Fix neglect of diff_setup()/diff_setup_done() symmetry.\n"},{"id":"107325","messageId":"49B2C784.90800@lsrfire.ath.cx","threadId":"18147","inReplyTo":"7vfxhs2shk.fsf@gitster.siamese.dyndns.org","subject":"Re: What's in git.git (Mar 2009, #02; Thu, 05)","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-03-07T19:14:12Z","receivedAt":"2009-03-07T19:14:12Z","isPatch":false,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Junio C Hamano schrieb:\n> * The 'master' branch has these since v1.6.2 in addition to the above.\n> \n> Carlos Manuel Duclos Vergara (1):\n>   git-archive: add --output=<file> to send output to a file\n\nIt just hit me that this is option can be used for a DoS attack (or\nperhaps worse) when used in connection with --remote.  We need to apply\nit on the client side instead of sending it to the remote end.  And\ngit-upload-archive needs to filter it out.  Ugh.\n\nHere's a quick and dirty patch to do the latter.\n\n---\n archive.c |   14 +++++++++-----\n archive.h |    2 +-\n 2 files changed, 10 insertions(+), 6 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex c6aea83..c7534d7 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -260,7 +260,8 @@ static void create_output_file(const char *output_file)\n \t  PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_HIDDEN, NULL, (p) }\n \n static int parse_archive_args(int argc, const char **argv,\n-\t\tconst struct archiver **ar, struct archiver_args *args)\n+\t\t\t      const struct archiver **ar,\n+\t\t\t      struct archiver_args *args, int local)\n {\n \tconst char *format = \"tar\";\n \tconst char *base = NULL;\n@@ -310,8 +311,11 @@ static int parse_archive_args(int argc, const char **argv,\n \tif (!base)\n \t\tbase = \"\";\n \n-\tif (output)\n+\tif (output) {\n+\t\tif (!local)\n+\t\t\tdie(\"Unexpected option --output\");\n \t\tcreate_output_file(output);\n+\t}\n \n \tif (list) {\n \t\tfor (i = 0; i < ARRAY_SIZE(archivers); i++)\n@@ -343,13 +347,13 @@ static int parse_archive_args(int argc, const char **argv,\n }\n \n int write_archive(int argc, const char **argv, const char *prefix,\n-\t\tint setup_prefix)\n+\t\tint local)\n {\n \tconst struct archiver *ar = NULL;\n \tstruct archiver_args args;\n \n-\targc = parse_archive_args(argc, argv, &ar, &args);\n-\tif (setup_prefix && prefix == NULL)\n+\targc = parse_archive_args(argc, argv, &ar, &args, local);\n+\tif (local && prefix == NULL)\n \t\tprefix = setup_git_directory();\n \n \tparse_treeish_arg(argv, &args, prefix);\ndiff --git a/archive.h b/archive.h\nindex 0b15b35..f6c3c89 100644\n--- a/archive.h\n+++ b/archive.h\n@@ -24,6 +24,6 @@ extern int write_tar_archive(struct archiver_args *);\n extern int write_zip_archive(struct archiver_args *);\n \n extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);\n-extern int write_archive(int argc, const char **argv, const char *prefix, int setup_prefix);\n+extern int write_archive(int argc, const char **argv, const char *prefix, int local);\n \n #endif\t/* ARCHIVE_H */\n-- \n1.6.2\n"},{"id":"107386","messageId":"49B40A9F.7050408@lsrfire.ath.cx","threadId":"18147","inReplyTo":"49B2C784.90800@lsrfire.ath.cx","subject":"[PATCH 1/4] parseopt: add PARSE_OPT_KEEP_UNKNOWN","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-03-08T18:12:47Z","receivedAt":"2009-03-08T18:12:47Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add a parseopt flag, PARSE_OPT_KEEP_UNKNOWN, that can be used to keep\nunknown options in argv, similar to the existing KEEP flags.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n parse-options.c |   12 +++++++++---\n parse-options.h |    1 +\n 2 files changed, 10 insertions(+), 3 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex 4c5d09d..39808ae 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -274,7 +274,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n \t\t\tcase -1:\n \t\t\t\treturn parse_options_usage(usagestr, options);\n \t\t\tcase -2:\n-\t\t\t\treturn PARSE_OPT_UNKNOWN;\n+\t\t\t\tgoto unknown;\n \t\t\t}\n \t\t\tif (ctx->opt)\n \t\t\t\tcheck_typos(arg + 1, options);\n@@ -292,7 +292,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n \t\t\t\t\t */\n \t\t\t\t\tctx->argv[0] = xstrdup(ctx->opt - 1);\n \t\t\t\t\t*(char *)ctx->argv[0] = '-';\n-\t\t\t\t\treturn PARSE_OPT_UNKNOWN;\n+\t\t\t\t\tgoto unknown;\n \t\t\t\t}\n \t\t\t}\n \t\t\tcontinue;\n@@ -314,8 +314,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n \t\tcase -1:\n \t\t\treturn parse_options_usage(usagestr, options);\n \t\tcase -2:\n-\t\t\treturn PARSE_OPT_UNKNOWN;\n+\t\t\tgoto unknown;\n \t\t}\n+\t\tcontinue;\n+unknown:\n+\t\tif (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))\n+\t\t\treturn PARSE_OPT_UNKNOWN;\n+\t\tctx->out[ctx->cpidx++] = ctx->argv[0];\n+\t\tctx->opt = NULL;\n \t}\n \treturn PARSE_OPT_DONE;\n }\ndiff --git a/parse-options.h b/parse-options.h\nindex 9122905..b7d08b1 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -21,6 +21,7 @@ enum parse_opt_flags {\n \tPARSE_OPT_KEEP_DASHDASH = 1,\n \tPARSE_OPT_STOP_AT_NON_OPTION = 2,\n \tPARSE_OPT_KEEP_ARGV0 = 4,\n+\tPARSE_OPT_KEEP_UNKNOWN = 8,\n };\n \n enum parse_opt_option_flags {\n-- \n1.6.2\n"},{"id":"107387","messageId":"49B40B2C.1070008@lsrfire.ath.cx","threadId":"18147","inReplyTo":"49B2C784.90800@lsrfire.ath.cx","subject":"[PATCH 2/4] parseopt: add PARSE_OPT_NO_INTERNAL_HELP","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-03-08T18:15:08Z","receivedAt":"2009-03-08T18:15:08Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add a parseopt flag, PARSE_OPT_NO_INTERNAL_HELP, that turns off internal\nhandling of -h, --help and --help-all.  This allows the implementation\nof custom help option handlers or incremental parsers.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n parse-options.c |   10 ++++++----\n parse-options.h |    1 +\n 2 files changed, 7 insertions(+), 4 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex 39808ae..8b21dea 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -253,6 +253,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n \t\t       const struct option *options,\n \t\t       const char * const usagestr[])\n {\n+\tint internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);\n+\n \t/* we must reset ->opt, unknown short option leave it dangling */\n \tctx->opt = NULL;\n \n@@ -268,7 +270,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n \n \t\tif (arg[1] != '-') {\n \t\t\tctx->opt = arg + 1;\n-\t\t\tif (*ctx->opt == 'h')\n+\t\t\tif (internal_help && *ctx->opt == 'h')\n \t\t\t\treturn parse_options_usage(usagestr, options);\n \t\t\tswitch (parse_short_opt(ctx, options)) {\n \t\t\tcase -1:\n@@ -279,7 +281,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n \t\t\tif (ctx->opt)\n \t\t\t\tcheck_typos(arg + 1, options);\n \t\t\twhile (ctx->opt) {\n-\t\t\t\tif (*ctx->opt == 'h')\n+\t\t\t\tif (internal_help && *ctx->opt == 'h')\n \t\t\t\t\treturn parse_options_usage(usagestr, options);\n \t\t\t\tswitch (parse_short_opt(ctx, options)) {\n \t\t\t\tcase -1:\n@@ -306,9 +308,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n \t\t\tbreak;\n \t\t}\n \n-\t\tif (!strcmp(arg + 2, \"help-all\"))\n+\t\tif (internal_help && !strcmp(arg + 2, \"help-all\"))\n \t\t\treturn usage_with_options_internal(usagestr, options, 1);\n-\t\tif (!strcmp(arg + 2, \"help\"))\n+\t\tif (internal_help && !strcmp(arg + 2, \"help\"))\n \t\t\treturn parse_options_usage(usagestr, options);\n \t\tswitch (parse_long_opt(ctx, arg + 2, options)) {\n \t\tcase -1:\ndiff --git a/parse-options.h b/parse-options.h\nindex b7d08b1..f8ef1db 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -22,6 +22,7 @@ enum parse_opt_flags {\n \tPARSE_OPT_STOP_AT_NON_OPTION = 2,\n \tPARSE_OPT_KEEP_ARGV0 = 4,\n \tPARSE_OPT_KEEP_UNKNOWN = 8,\n+\tPARSE_OPT_NO_INTERNAL_HELP = 16,\n };\n \n enum parse_opt_option_flags {\n-- \n1.6.2\n"},{"id":"107388","messageId":"49B40B9A.8080202@lsrfire.ath.cx","threadId":"18147","inReplyTo":"49B2C784.90800@lsrfire.ath.cx","subject":"[PATCH 3/4] parseopt: make usage optional","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-03-08T18:16:58Z","receivedAt":"2009-03-08T18:16:58Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Allow usagestr to be NULL and don't display anything a help screen in\nthis case.  This is useful to implement incremental parsers.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n parse-options.c |    3 +++\n 1 files changed, 3 insertions(+), 0 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex 8b21dea..51e804b 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -364,6 +364,9 @@ int parse_options(int argc, const char **argv, const struct option *options,\n int usage_with_options_internal(const char * const *usagestr,\n \t\t\t\tconst struct option *opts, int full)\n {\n+\tif (!usagestr)\n+\t\treturn PARSE_OPT_HELP;\n+\n \tfprintf(stderr, \"usage: %s\\n\", *usagestr++);\n \twhile (*usagestr && **usagestr)\n \t\tfprintf(stderr, \"   or: %s\\n\", *usagestr++);\n-- \n1.6.2\n"},{"id":"107389","messageId":"49B40CC1.2090906@lsrfire.ath.cx","threadId":"18147","inReplyTo":"49B2C784.90800@lsrfire.ath.cx","subject":"[PATCH 4/4] archive: use parseopt for local-only options","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-03-08T18:21:53Z","receivedAt":"2009-03-08T18:21:53Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Replace the hand-rolled parsers that find and remove --remote and --exec\nby a parseopt parser that also handles --output.\n\nAll three options only have a meaning if no remote server is used or on\nthe local side.  They must be rejected by upload-archive and should not\nbe sent to the server by archive.\n\nWe can't use a single parser for both remote and local side because the\nremote end possibly understands a different set of options than the\nlocal side.  A local parser would then wrongly accuse options valid on\nthe other side as being incorrect.\n\nThis patch implements a very forgiving parser that understands only the\nthree options mentioned above.  All others are passed to the normal,\ncomplete parser in archive.c (running either locally in archive, or\nremotely in upload-archive).  This normal parser definition contains\ndummy entries for the three options, in order for them to appear in the\nhelp screen.\n\nThe parseopt parser allows multiple occurrences of --remote and --exec\nunlike the previous one; the one specified last wins.  This looseness\nis acceptable, I think.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n archive.c         |   18 +--------\n builtin-archive.c |  103 +++++++++++++++++++---------------------------------\n 2 files changed, 40 insertions(+), 81 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex c6aea83..96b62d4 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -239,19 +239,6 @@ static void parse_treeish_arg(const char **argv,\n \tar_args->time = archive_time;\n }\n \n-static void create_output_file(const char *output_file)\n-{\n-\tint output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);\n-\tif (output_fd < 0)\n-\t\tdie(\"could not create archive file: %s \", output_file);\n-\tif (output_fd != 1) {\n-\t\tif (dup2(output_fd, 1) < 0)\n-\t\t\tdie(\"could not redirect output\");\n-\t\telse\n-\t\t\tclose(output_fd);\n-\t}\n-}\n-\n #define OPT__COMPR(s, v, h, p) \\\n \t{ OPTION_SET_INT, (s), NULL, (v), NULL, (h), \\\n \t  PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, (p) }\n@@ -306,13 +293,12 @@ static int parse_archive_args(int argc, const char **argv,\n \t\tdie(\"Unexpected option --remote\");\n \tif (exec)\n \t\tdie(\"Option --exec can only be used together with --remote\");\n+\tif (output)\n+\t\tdie(\"Unexpected option --output\");\n \n \tif (!base)\n \t\tbase = \"\";\n \n-\tif (output)\n-\t\tcreate_output_file(output);\n-\n \tif (list) {\n \t\tfor (i = 0; i < ARRAY_SIZE(archivers); i++)\n \t\t\tprintf(\"%s\\n\", archivers[i].name);\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex 5ceec43..60adef9 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -5,44 +5,35 @@\n #include \"cache.h\"\n #include \"builtin.h\"\n #include \"archive.h\"\n+#include \"parse-options.h\"\n #include \"pkt-line.h\"\n #include \"sideband.h\"\n \n-static int run_remote_archiver(const char *remote, int argc,\n-\t\t\t       const char **argv)\n+static void create_output_file(const char *output_file)\n+{\n+\tint output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);\n+\tif (output_fd < 0)\n+\t\tdie(\"could not create archive file: %s \", output_file);\n+\tif (output_fd != 1) {\n+\t\tif (dup2(output_fd, 1) < 0)\n+\t\t\tdie(\"could not redirect output\");\n+\t\telse\n+\t\t\tclose(output_fd);\n+\t}\n+}\n+\n+static int run_remote_archiver(int argc, const char **argv,\n+\t\t\t       const char *remote, const char *exec)\n {\n \tchar *url, buf[LARGE_PACKET_MAX];\n \tint fd[2], i, len, rv;\n \tstruct child_process *conn;\n-\tconst char *exec = \"git-upload-archive\";\n-\tint exec_at = 0, exec_value_at = 0;\n-\n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\t\tif (!prefixcmp(arg, \"--exec=\")) {\n-\t\t\tif (exec_at)\n-\t\t\t\tdie(\"multiple --exec specified\");\n-\t\t\texec = arg + 7;\n-\t\t\texec_at = i;\n-\t\t} else if (!strcmp(arg, \"--exec\")) {\n-\t\t\tif (exec_at)\n-\t\t\t\tdie(\"multiple --exec specified\");\n-\t\t\tif (i + 1 >= argc)\n-\t\t\t\tdie(\"option --exec requires a value\");\n-\t\t\texec = argv[i + 1];\n-\t\t\texec_at = i;\n-\t\t\texec_value_at = ++i;\n-\t\t}\n-\t}\n \n \turl = xstrdup(remote);\n \tconn = git_connect(fd, url, exec, 0);\n \n-\tfor (i = 1; i < argc; i++) {\n-\t\tif (i == exec_at || i == exec_value_at)\n-\t\t\tcontinue;\n+\tfor (i = 1; i < argc; i++)\n \t\tpacket_write(fd[1], \"argument %s\\n\", argv[i]);\n-\t}\n \tpacket_flush(fd[1]);\n \n \tlen = packet_read_line(fd[0], buf, sizeof(buf));\n@@ -69,51 +60,33 @@ static int run_remote_archiver(const char *remote, int argc,\n \treturn !!rv;\n }\n \n-static const char *extract_remote_arg(int *ac, const char **av)\n-{\n-\tint ix, iy, cnt = *ac;\n-\tint no_more_options = 0;\n-\tconst char *remote = NULL;\n-\n-\tfor (ix = iy = 1; ix < cnt; ix++) {\n-\t\tconst char *arg = av[ix];\n-\t\tif (!strcmp(arg, \"--\"))\n-\t\t\tno_more_options = 1;\n-\t\tif (!no_more_options) {\n-\t\t\tif (!prefixcmp(arg, \"--remote=\")) {\n-\t\t\t\tif (remote)\n-\t\t\t\t\tdie(\"Multiple --remote specified\");\n-\t\t\t\tremote = arg + 9;\n-\t\t\t\tcontinue;\n-\t\t\t} else if (!strcmp(arg, \"--remote\")) {\n-\t\t\t\tif (remote)\n-\t\t\t\t\tdie(\"Multiple --remote specified\");\n-\t\t\t\tif (++ix >= cnt)\n-\t\t\t\t\tdie(\"option --remote requires a value\");\n-\t\t\t\tremote = av[ix];\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (arg[0] != '-')\n-\t\t\t\tno_more_options = 1;\n-\t\t}\n-\t\tif (ix != iy)\n-\t\t\tav[iy] = arg;\n-\t\tiy++;\n-\t}\n-\tif (remote) {\n-\t\tav[--cnt] = NULL;\n-\t\t*ac = cnt;\n-\t}\n-\treturn remote;\n-}\n+#define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH | \t\\\n+\t\t\t     PARSE_OPT_KEEP_ARGV0 | \t\\\n+\t\t\t     PARSE_OPT_KEEP_UNKNOWN |\t\\\n+\t\t\t     PARSE_OPT_NO_INTERNAL_HELP\t)\n \n int cmd_archive(int argc, const char **argv, const char *prefix)\n {\n+\tconst char *exec = \"git-upload-archive\";\n+\tconst char *output = NULL;\n \tconst char *remote = NULL;\n+\tstruct option local_opts[] = {\n+\t\tOPT_STRING(0, \"output\", &output, \"file\",\n+\t\t\t\"write the archive to this file\"),\n+\t\tOPT_STRING(0, \"remote\", &remote, \"repo\",\n+\t\t\t\"retrieve the archive from remote repository <repo>\"),\n+\t\tOPT_STRING(0, \"exec\", &exec, \"cmd\",\n+\t\t\t\"path to the remote git-upload-archive command\"),\n+\t\tOPT_END()\n+\t};\n+\n+\targc = parse_options(argc, argv, local_opts, NULL, PARSE_OPT_KEEP_ALL);\n+\n+\tif (output)\n+\t\tcreate_output_file(output);\n \n-\tremote = extract_remote_arg(&argc, argv);\n \tif (remote)\n-\t\treturn run_remote_archiver(remote, argc, argv);\n+\t\treturn run_remote_archiver(argc, argv, remote, exec);\n \n \tsetvbuf(stderr, NULL, _IOLBF, BUFSIZ);\n \n-- \n1.6.2\n"},{"id":"107398","messageId":"7v3adnlqby.fsf@gitster.siamese.dyndns.org","threadId":"18147","inReplyTo":"49B40CC1.2090906@lsrfire.ath.cx","subject":"Re: [PATCH 4/4] archive: use parseopt for local-only options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-08T20:20:01Z","receivedAt":"2009-03-08T20:20:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n\n> The parseopt parser allows multiple occurrences of --remote and --exec\n> unlike the previous one; the one specified last wins.  This looseness\n> is acceptable, I think.\n\nI agree.\n\nIf we care about this very deeply, we can add \"this option is supposed to\nbe singleton\" option to the parse_options infrastructure.  Besides, the\n\"last one wins\" rule is often more convenient than \"there has to be at\nmost one\" rule in real life.\n"},{"id":"107399","messageId":"7vvdqjkbka.fsf@gitster.siamese.dyndns.org","threadId":"18147","inReplyTo":"49B40A9F.7050408@lsrfire.ath.cx","subject":"Re: [PATCH 1/4] parseopt: add PARSE_OPT_KEEP_UNKNOWN","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-08T20:24:21Z","receivedAt":"2009-03-08T20:24:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n\n> Add a parseopt flag, PARSE_OPT_KEEP_UNKNOWN, that can be used to keep\n> unknown options in argv, similar to the existing KEEP flags.\n\nVery nice.\n\nThe only caveat I can think of is with PARSE_OPT_STOP_AT_NON_OPTION set\n(which is not default), you can correctly handle:\n\n\tgit cmd --known --unknown=value arg0 arg1\n\nbut cannot correctly handle:\n\n\tgit cmd --known --unknown value arg0 arg1\n\nAn update to Documentation/technical/api-parse-options.txt that\n\n (1) describes this new option; and\n\n (2) warns about this issue.\n\nIt might even make sense to diagnose PARSE_OPT_STOP_AT_NON_OPTION used\ntogether with PARSE_OPT_KEEP_UNKNOWN as a programming error.\n"},{"id":"107400","messageId":"7vr617kbit.fsf@gitster.siamese.dyndns.org","threadId":"18147","inReplyTo":"49B40B9A.8080202@lsrfire.ath.cx","subject":"Re: [PATCH 3/4] parseopt: make usage optional","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-08T20:25:14Z","receivedAt":"2009-03-08T20:25:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n\n> Allow usagestr to be NULL and don't display anything a help screen in\n> this case.  This is useful to implement incremental parsers.\n\nCan I amend \"s/anything a/any/\"?\n"},{"id":"107401","messageId":"7vmybvkb9b.fsf@gitster.siamese.dyndns.org","threadId":"18147","inReplyTo":"7vvdqjkbka.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/4] parseopt: add PARSE_OPT_KEEP_UNKNOWN","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-08T20:30:56Z","receivedAt":"2009-03-08T20:30:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n>\n>> Add a parseopt flag, PARSE_OPT_KEEP_UNKNOWN, that can be used to keep\n>> unknown options in argv, similar to the existing KEEP flags.\n>\n> Very nice.\n>\n> The only caveat I can think of is with PARSE_OPT_STOP_AT_NON_OPTION set\n> (which is not default), you can correctly handle:\n>\n> \tgit cmd --known --unknown=value arg0 arg1\n>\n> but cannot correctly handle:\n>\n> \tgit cmd --known --unknown value arg0 arg1\n>\n> An update to Documentation/technical/api-parse-options.txt that\n>\n>  (1) describes this new option; and\n>\n>  (2) warns about this issue.\n\n\"is necessary\" is necessary here to complete my sentence.  Sorry.\n\n> It might even make sense to diagnose PARSE_OPT_STOP_AT_NON_OPTION used\n> together with PARSE_OPT_KEEP_UNKNOWN as a programming error.\n"},{"id":"107497","messageId":"49B579ED.2090304@lsrfire.ath.cx","threadId":"18147","inReplyTo":"7vr617kbit.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 3/4] parseopt: make usage optional","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-03-09T20:19:57Z","receivedAt":"2009-03-09T20:19:57Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Junio C Hamano schrieb:\n> René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n> \n>> Allow usagestr to be NULL and don't display anything a help screen in\n>> this case.  This is useful to implement incremental parsers.\n> \n> Can I amend \"s/anything a/any/\"?\n\nOh, definitely.\n\nThanks,\nRené\n"},{"id":"107498","messageId":"49B57B90.4060409@lsrfire.ath.cx","threadId":"18147","inReplyTo":"7vvdqjkbka.fsf@gitster.siamese.dyndns.org","subject":"[PATCH 5/4] parseopt: document KEEP_ARGV0, KEEP_UNKNOWN, NO_INTERNAL_HELP","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-03-09T20:26:56Z","receivedAt":"2009-03-09T20:26:56Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n Documentation/technical/api-parse-options.txt |   27 +++++++++++++++++++++++++\n 1 files changed, 27 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt\nindex 539863b..dc72987 100644\n--- a/Documentation/technical/api-parse-options.txt\n+++ b/Documentation/technical/api-parse-options.txt\n@@ -66,6 +66,12 @@ Steps to parse options\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+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\n+before the full parser, which in turn shows the full help message.\n++\n Flags are the bitwise-or of:\n \n `PARSE_OPT_KEEP_DASHDASH`::\n@@ -77,6 +83,27 @@ Flags are the bitwise-or of:\n \tUsing this flag, processing is stopped at the first non-option\n \targument.\n \n+`PARSE_OPT_KEEP_ARGV0`::\n+\tKeep the first argument, which contains the program name.  It's\n+\tremoved from argv[] by default.\n+\n+`PARSE_OPT_KEEP_UNKNOWN`::\n+\tKeep unknown arguments instead of erroring out.  This doesn't\n+\twork for all combinations of arguments as users might expect\n+\tit to do.  E.g. if the first argument in `--unknown --known`\n+\ttakes a value (which we can't know), the second one is\n+\tmistakenly interpreted as a known option.  Similarly, if\n+\t`PARSE_OPT_STOP_AT_NON_OPTION` is set, the second argument in\n+\t`--unknown value` will be mistakenly interpreted as a\n+\tnon-option, not as a value belonging to the unknown option,\n+\tstopping the parser early.\n+\n+`PARSE_OPT_NO_INTERNAL_HELP`::\n+\tBy default, parse_options() handles `-h`, `--help` and\n+\t`--help-all` internally, by showing a help screen.  This option\n+\tturns it off and allows one to add custom handlers for these\n+\toptions, or to just leave them unknown.\n+\n Data Structure\n --------------\n \n-- \n1.6.2\n"},{"id":"107501","messageId":"49B582C2.2080803@lsrfire.ath.cx","threadId":"18147","inReplyTo":"7vvdqjkbka.fsf@gitster.siamese.dyndns.org","subject":"[PATCH 6/4] parseopt: prevent KEEP_UNKNOWN and STOP_AT_NON_OPTION from being used together","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-03-09T20:57:38Z","receivedAt":"2009-03-09T20:57:38Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"As suggested by Junio, disallow the flags PARSE_OPT_KEEP_UNKNOWN and\nPARSE_OPT_STOP_AT_NON_OPTION to be turned on at the same time, as a\nvalue of an unknown option could be mistakenly classified as a\nnon-option, stopping the parser early.  E.g.:\n\n\tgit cmd --known --unknown value arg0 arg1\n\nThe parser should have stopped at \"arg0\", but it already stops at\n\"value\".\n\nThis patch makes parse_options() die if the two flags are used in\ncombination.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n Documentation/technical/api-parse-options.txt |    3 ++-\n parse-options.c                               |    3 +++\n 2 files changed, 5 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt\nindex dc72987..f5d4ac1 100644\n--- a/Documentation/technical/api-parse-options.txt\n+++ b/Documentation/technical/api-parse-options.txt\n@@ -96,7 +96,8 @@ Flags are the bitwise-or of:\n \t`PARSE_OPT_STOP_AT_NON_OPTION` is set, the second argument in\n \t`--unknown value` will be mistakenly interpreted as a\n \tnon-option, not as a value belonging to the option, stopping\n-\tthe parser early.\n+\tthe parser early.  That's why parse_options() errors out if\n+\tboth options are set.\n \n `PARSE_OPT_NO_INTERNAL_HELP`::\n \tBy default, parse_options() handles `-h`, `--help` and\ndiff --git a/parse-options.c b/parse-options.c\nindex 51e804b..cf71bcf 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -244,6 +244,9 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,\n \tctx->out  = argv;\n \tctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);\n \tctx->flags = flags;\n+\tif ((flags & PARSE_OPT_KEEP_UNKNOWN) &&\n+\t    (flags & PARSE_OPT_STOP_AT_NON_OPTION))\n+\t\tdie(\"STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together\");\n }\n \n static int usage_with_options_internal(const char * const *,\n-- \n1.6.2\n"}]}