{"thread":{"id":"57578","subject":"[PATCH 0/8] reflog: migrate fully to parse_options()","startedAt":"2022-03-17T18:08:59Z","lastAt":"2022-03-28T22:45:11Z","messageCount":15,"participants":["Ævar Arnfjörð Bjarmason","John Cai","Junio C Hamano","SZEDER Gábor"],"isPatch":true,"patchVersion":1,"patchTotal":8},"messages":[{"id":"451578","messageId":"cover-0.8-00000000000-20220317T180439Z-avarab@gmail.com","threadId":"57578","inReplyTo":null,"subject":"[PATCH 0/8] reflog: migrate fully to parse_options()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-03-17T18:08:32Z","receivedAt":"2022-03-17T18:08:59Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"This is a follow-up to the recently landed 1b4d9b4512e (Merge branch\n'jc/reflog-parse-options', 2022-02-05). It converted a couple of\nsubcommands in builtin/reflog.c to use parse_options(), this converts\nthe rest.\n\nThe 1/8 is a technically unrelated indentation fix for the recently\nlanded 7d3d226e700 (reflog: libify delete reflog function and helpers,\n2022-03-02), but since it's also in the reflog code I figured it was\nOK and that it didn't deserve its own topic.\n\nÆvar Arnfjörð Bjarmason (8):\n  reflog.c: indent argument lists\n  reflog: refactor cmd_reflog() to \"if\" branches\n  reflog tests: add missing \"git reflog exists\" tests\n  reflog: move \"usage\" variables and use macros\n  git reflog [expire|delete]: make -h output consistent with SYNOPSIS\n  reflog exists: use parse_options() API\n  reflog: convert to parse_options() API\n  reflog [show]: display sensible -h output\n\n builtin/reflog.c         | 146 +++++++++++++++++++++++++--------------\n reflog.c                 |  20 +++---\n t/t1410-reflog.sh        |  22 ++++++\n t/t1411-reflog-show.sh   |   5 --\n t/t1418-reflog-exists.sh |  37 ++++++++++\n t/test-lib-functions.sh  |   2 +-\n 6 files changed, 165 insertions(+), 67 deletions(-)\n create mode 100755 t/t1418-reflog-exists.sh\n\n-- \n2.35.1.1384.g7d2906948a1\n\n"},{"id":"451579","messageId":"patch-1.8-5069b3fd0ff-20220317T180439Z-avarab@gmail.com","threadId":"57578","inReplyTo":"cover-0.8-00000000000-20220317T180439Z-avarab@gmail.com","subject":"[PATCH 1/8] reflog.c: indent argument lists","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-03-17T18:08:33Z","receivedAt":"2022-03-17T18:09:00Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"When reflog.c was lib-ified in 7d3d226e700 (reflog: libify delete\nreflog function and helpers, 2022-03-02) these previously \"static\"\nfunctions were made non-\"static\", but the argument lists were not\ncorrespondingly indented according to our usual coding style. Let's do\nthat.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n reflog.c | 20 ++++++++++----------\n 1 file changed, 10 insertions(+), 10 deletions(-)\n\ndiff --git a/reflog.c b/reflog.c\nindex 333fd8708fe..82e5a935117 100644\n--- a/reflog.c\n+++ b/reflog.c\n@@ -240,8 +240,8 @@ static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit\n  * Return true iff the specified reflog entry should be expired.\n  */\n int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid,\n-\t\t\t\t    const char *email, timestamp_t timestamp, int tz,\n-\t\t\t\t    const char *message, void *cb_data)\n+\t\t\t     const char *email, timestamp_t timestamp, int tz,\n+\t\t\t     const char *message, void *cb_data)\n {\n \tstruct expire_reflog_policy_cb *cb = cb_data;\n \tstruct commit *old_commit, *new_commit;\n@@ -273,10 +273,10 @@ int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid,\n }\n \n int should_expire_reflog_ent_verbose(struct object_id *ooid,\n-\t\t\t\t\t    struct object_id *noid,\n-\t\t\t\t\t    const char *email,\n-\t\t\t\t\t    timestamp_t timestamp, int tz,\n-\t\t\t\t\t    const char *message, void *cb_data)\n+\t\t\t\t     struct object_id *noid,\n+\t\t\t\t     const char *email,\n+\t\t\t\t     timestamp_t timestamp, int tz,\n+\t\t\t\t     const char *message, void *cb_data)\n {\n \tstruct expire_reflog_policy_cb *cb = cb_data;\n \tint expire;\n@@ -323,8 +323,8 @@ static int is_head(const char *refname)\n }\n \n void reflog_expiry_prepare(const char *refname,\n-\t\t\t\t  const struct object_id *oid,\n-\t\t\t\t  void *cb_data)\n+\t\t\t   const struct object_id *oid,\n+\t\t\t   void *cb_data)\n {\n \tstruct expire_reflog_policy_cb *cb = cb_data;\n \tstruct commit_list *elem;\n@@ -377,8 +377,8 @@ void reflog_expiry_cleanup(void *cb_data)\n }\n \n int count_reflog_ent(struct object_id *ooid, struct object_id *noid,\n-\t\tconst char *email, timestamp_t timestamp, int tz,\n-\t\tconst char *message, void *cb_data)\n+\t\t     const char *email, timestamp_t timestamp, int tz,\n+\t\t     const char *message, void *cb_data)\n {\n \tstruct cmd_reflog_expire_cb *cb = cb_data;\n \tif (!cb->expire_total || timestamp < cb->expire_total)\n-- \n2.35.1.1384.g7d2906948a1\n\n"},{"id":"451580","messageId":"patch-2.8-8bff6976334-20220317T180439Z-avarab@gmail.com","threadId":"57578","inReplyTo":"cover-0.8-00000000000-20220317T180439Z-avarab@gmail.com","subject":"[PATCH 2/8] reflog: refactor cmd_reflog() to \"if\" branches","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-03-17T18:08:34Z","receivedAt":"2022-03-17T18:09:02Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Refactor the \"if\" branches in cmd_reflog() to use \"else if\" instead,\nand remove the whitespace between them.\n\nAs with 92f480909f7 (multi-pack-index: refactor \"goto usage\" pattern,\n2021-08-23) this makes this code more consistent with how\nbuiltin/{bundle,stash,commit-graph,multi-pack-index}.c look and\nbehave. Their top-level commands are all similar sub-command routing\nfunctions.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/reflog.c | 9 +++------\n 1 file changed, 3 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex 9407f835cb6..c864f276308 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -384,14 +384,11 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)\n \n \tif (!strcmp(argv[1], \"show\"))\n \t\treturn cmd_log_reflog(argc - 1, argv + 1, prefix);\n-\n-\tif (!strcmp(argv[1], \"expire\"))\n+\telse if (!strcmp(argv[1], \"expire\"))\n \t\treturn cmd_reflog_expire(argc - 1, argv + 1, prefix);\n-\n-\tif (!strcmp(argv[1], \"delete\"))\n+\telse if (!strcmp(argv[1], \"delete\"))\n \t\treturn cmd_reflog_delete(argc - 1, argv + 1, prefix);\n-\n-\tif (!strcmp(argv[1], \"exists\"))\n+\telse if (!strcmp(argv[1], \"exists\"))\n \t\treturn cmd_reflog_exists(argc - 1, argv + 1, prefix);\n \n \treturn cmd_log_reflog(argc, argv, prefix);\n-- \n2.35.1.1384.g7d2906948a1\n\n"},{"id":"451581","messageId":"patch-3.8-5d6500efb55-20220317T180439Z-avarab@gmail.com","threadId":"57578","inReplyTo":"cover-0.8-00000000000-20220317T180439Z-avarab@gmail.com","subject":"[PATCH 3/8] reflog tests: add missing \"git reflog exists\" tests","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-03-17T18:08:35Z","receivedAt":"2022-03-17T18:09:06Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"There were a few \"git reflog exists\" tests scattered over the test\nsuite, but let's consolidate the testing of the main functionality\ninto a new test file. This makes it easier to run just these tests\nduring development.\n\nTo do that amend and extend an existing test added in\nafcb2e7a3b8 (git-reflog: add exists command, 2015-07-21). Let's use\n\"test_must_fail\" instead of \"!\" (in case it segfaults), and test for\nbasic usage, an unknown option etc.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t1411-reflog-show.sh   |  5 -----\n t/t1418-reflog-exists.sh | 32 ++++++++++++++++++++++++++++++++\n 2 files changed, 32 insertions(+), 5 deletions(-)\n create mode 100755 t/t1418-reflog-exists.sh\n\ndiff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh\nindex 0bb319b944a..975c4ea83a8 100755\n--- a/t/t1411-reflog-show.sh\n+++ b/t/t1411-reflog-show.sh\n@@ -169,9 +169,4 @@ test_expect_success 'git log -g -p shows diffs vs. parents' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'reflog exists works' '\n-\tgit reflog exists refs/heads/main &&\n-\t! git reflog exists refs/heads/nonexistent\n-'\n-\n test_done\ndiff --git a/t/t1418-reflog-exists.sh b/t/t1418-reflog-exists.sh\nnew file mode 100755\nindex 00000000000..60c6411ce3c\n--- /dev/null\n+++ b/t/t1418-reflog-exists.sh\n@@ -0,0 +1,32 @@\n+#!/bin/sh\n+\n+test_description='Test reflog display routines'\n+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\ttest_commit A\n+'\n+\n+test_expect_success 'usage' '\n+\ttest_expect_code 129 git reflog exists &&\n+\ttest_expect_code 129 git reflog exists -h\n+'\n+\n+test_expect_success 'usage: unknown option' '\n+\ttest_expect_code 129 git reflog exists --unknown-option\n+'\n+\n+test_expect_success 'reflog exists works' '\n+\tgit reflog exists refs/heads/main &&\n+\ttest_must_fail git reflog exists refs/heads/nonexistent\n+'\n+\n+test_expect_success 'reflog exists works with a \"--\" delimiter' '\n+\tgit reflog exists -- refs/heads/main &&\n+\ttest_must_fail git reflog exists -- refs/heads/nonexistent\n+'\n+\n+test_done\n-- \n2.35.1.1384.g7d2906948a1\n\n"},{"id":"451582","messageId":"patch-4.8-f54f1ea3118-20220317T180439Z-avarab@gmail.com","threadId":"57578","inReplyTo":"cover-0.8-00000000000-20220317T180439Z-avarab@gmail.com","subject":"[PATCH 4/8] reflog: move \"usage\" variables and use macros","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-03-17T18:08:36Z","receivedAt":"2022-03-17T18:09:08Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Move the \"usage\" variables in builtin/reflog.c to the top of the file,\nin preparation for later commits defining a common \"reflog_usage\" in\nterms of some of these strings, as was done in\n8757b35d443 (commit-graph: define common usage with a macro,\n2021-08-23).\n\nWhile we're at it let's make them \"const char *const\", as is the\nconvention with these \"usage\" variables.\n\nThe use of macros here is a bit odd, but in subsequent commits we'll\nmake these use the same pattern as builtin/commit-graph.c uses since\n8757b35d443 (commit-graph: define common usage with a macro,\n2021-08-23).\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/reflog.c | 39 ++++++++++++++++++++++++---------------\n 1 file changed, 24 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex c864f276308..25313d504a9 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -5,8 +5,31 @@\n #include \"worktree.h\"\n #include \"reflog.h\"\n \n+#define BUILTIN_REFLOG_EXPIRE_USAGE \\\n+\tN_(\"git reflog expire [--expire=<time>] \" \\\n+\t   \"[--expire-unreachable=<time>] \" \\\n+\t   \"[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] \" \\\n+\t   \"[--verbose] [--all] <refs>...\")\n+\n+#define BUILTIN_REFLOG_DELETE_USAGE \\\n+\tN_(\"git reflog delete [--rewrite] [--updateref] \" \\\n+\t   \"[--dry-run | -n] [--verbose] <refs>...\")\n+\n+#define BUILTIN_REFLOG_EXISTS_USAGE \\\n+\tN_(\"git reflog exists <ref>\")\n+\n+static const char *const reflog_expire_usage[] = {\n+\tBUILTIN_REFLOG_EXPIRE_USAGE,\n+\tNULL\n+};\n+\n+static const char *const reflog_delete_usage[] = {\n+\tBUILTIN_REFLOG_DELETE_USAGE,\n+\tNULL\n+};\n+\n static const char reflog_exists_usage[] =\n-N_(\"git reflog exists <ref>\");\n+\tBUILTIN_REFLOG_EXISTS_USAGE;\n \n static timestamp_t default_reflog_expire;\n static timestamp_t default_reflog_expire_unreachable;\n@@ -147,14 +170,6 @@ static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, const char\n \t\tcb->expire_unreachable = default_reflog_expire_unreachable;\n }\n \n-static const char * reflog_expire_usage[] = {\n-\tN_(\"git reflog expire [--expire=<time>] \"\n-\t   \"[--expire-unreachable=<time>] \"\n-\t   \"[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] \"\n-\t   \"[--verbose] [--all] <refs>...\"),\n-\tNULL\n-};\n-\n static int expire_unreachable_callback(const struct option *opt,\n \t\t\t\t const char *arg,\n \t\t\t\t int unset)\n@@ -304,12 +319,6 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \treturn status;\n }\n \n-static const char * reflog_delete_usage[] = {\n-\tN_(\"git reflog delete [--rewrite] [--updateref] \"\n-\t   \"[--dry-run | -n] [--verbose] <refs>...\"),\n-\tNULL\n-};\n-\n static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)\n {\n \tint i, status = 0;\n-- \n2.35.1.1384.g7d2906948a1\n\n"},{"id":"451583","messageId":"patch-5.8-130e718722b-20220317T180439Z-avarab@gmail.com","threadId":"57578","inReplyTo":"cover-0.8-00000000000-20220317T180439Z-avarab@gmail.com","subject":"[PATCH 5/8] git reflog [expire|delete]: make -h output consistent with SYNOPSIS","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-03-17T18:08:37Z","receivedAt":"2022-03-17T18:09:09Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Make use of the guaranteed pretty alignment of \"-h\" output added in my\n4631cfc20bd (parse-options: properly align continued usage output,\n2021-09-21) and wrap and format the \"git reflog [expire|delete] -h\"\nusage output. Also add the missing \"--single-worktree\" option, as well\nas adding other things that were in the SYNOPSIS output, but not in\nthe \"-h\" output.\n\nThis was last touched in 33d7bdd6459 (builtin/reflog.c: use\nparse-options api for expire, delete subcommands, 2022-01-06), but in\nthat commit the previous usage() output was faithfully\nreproduced. Let's follow-up on that and make this even easier to read.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/reflog.c | 11 +++++------\n 1 file changed, 5 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex 25313d504a9..458764400b5 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -6,14 +6,13 @@\n #include \"reflog.h\"\n \n #define BUILTIN_REFLOG_EXPIRE_USAGE \\\n-\tN_(\"git reflog expire [--expire=<time>] \" \\\n-\t   \"[--expire-unreachable=<time>] \" \\\n-\t   \"[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] \" \\\n-\t   \"[--verbose] [--all] <refs>...\")\n+\tN_(\"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\\n\" \\\n+\t   \"                  [--rewrite] [--updateref] [--stale-fix]\\n\" \\\n+\t   \"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>...]\")\n \n #define BUILTIN_REFLOG_DELETE_USAGE \\\n-\tN_(\"git reflog delete [--rewrite] [--updateref] \" \\\n-\t   \"[--dry-run | -n] [--verbose] <refs>...\")\n+\tN_(\"git reflog delete [--rewrite] [--updateref]\\n\" \\\n+\t   \"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}...\")\n \n #define BUILTIN_REFLOG_EXISTS_USAGE \\\n \tN_(\"git reflog exists <ref>\")\n-- \n2.35.1.1384.g7d2906948a1\n\n"},{"id":"451584","messageId":"patch-6.8-f88acdc9702-20220317T180439Z-avarab@gmail.com","threadId":"57578","inReplyTo":"cover-0.8-00000000000-20220317T180439Z-avarab@gmail.com","subject":"[PATCH 6/8] reflog exists: use parse_options() API","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-03-17T18:08:38Z","receivedAt":"2022-03-17T18:09:11Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the \"reflog exists\" command added in afcb2e7a3b8 (git-reflog:\nadd exists command, 2015-07-21) to use parse_options() instead of its\nown custom command-line parser. This continues work started in\n33d7bdd6459 (builtin/reflog.c: use parse-options api for expire,\ndelete subcommands, 2022-01-06).\n\nAs a result we'll understand the --end-of-options synonym for \"--\", so\nlet's test for that.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/reflog.c         | 38 ++++++++++++++++----------------------\n t/t1418-reflog-exists.sh |  5 +++++\n 2 files changed, 21 insertions(+), 22 deletions(-)\n\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex 458764400b5..9847e9db3de 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -27,8 +27,10 @@ static const char *const reflog_delete_usage[] = {\n \tNULL\n };\n \n-static const char reflog_exists_usage[] =\n-\tBUILTIN_REFLOG_EXISTS_USAGE;\n+static const char *const reflog_exists_usage[] = {\n+\tBUILTIN_REFLOG_EXISTS_USAGE,\n+\tNULL,\n+};\n \n static timestamp_t default_reflog_expire;\n static timestamp_t default_reflog_expire_unreachable;\n@@ -350,28 +352,20 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)\n \n static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n {\n-\tint i, start = 0;\n-\n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\t\tif (!strcmp(arg, \"--\")) {\n-\t\t\ti++;\n-\t\t\tbreak;\n-\t\t}\n-\t\telse if (arg[0] == '-')\n-\t\t\tusage(_(reflog_exists_usage));\n-\t\telse\n-\t\t\tbreak;\n-\t}\n-\n-\tstart = i;\n+\tstruct option options[] = {\n+\t\tOPT_END()\n+\t};\n+\tconst char *refname;\n \n-\tif (argc - start != 1)\n-\t\tusage(_(reflog_exists_usage));\n+\targc = parse_options(argc, argv, prefix, options, reflog_exists_usage,\n+\t\t\t     0);\n+\tif (!argc)\n+\t\tusage_with_options(reflog_exists_usage, options);\n \n-\tif (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL))\n-\t\tdie(_(\"invalid ref format: %s\"), argv[start]);\n-\treturn !reflog_exists(argv[start]);\n+\trefname = argv[0];\n+\tif (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))\n+\t\tdie(_(\"invalid ref format: %s\"), refname);\n+\treturn !reflog_exists(refname);\n }\n \n /*\ndiff --git a/t/t1418-reflog-exists.sh b/t/t1418-reflog-exists.sh\nindex 60c6411ce3c..d51ecd5e925 100755\n--- a/t/t1418-reflog-exists.sh\n+++ b/t/t1418-reflog-exists.sh\n@@ -29,4 +29,9 @@ test_expect_success 'reflog exists works with a \"--\" delimiter' '\n \ttest_must_fail git reflog exists -- refs/heads/nonexistent\n '\n \n+test_expect_success 'reflog exists works with a \"--end-of-options\" delimiter' '\n+\tgit reflog exists --end-of-options refs/heads/main &&\n+\ttest_must_fail git reflog exists --end-of-options refs/heads/nonexistent\n+'\n+\n test_done\n-- \n2.35.1.1384.g7d2906948a1\n\n"},{"id":"451585","messageId":"patch-7.8-19e1ff0c569-20220317T180439Z-avarab@gmail.com","threadId":"57578","inReplyTo":"cover-0.8-00000000000-20220317T180439Z-avarab@gmail.com","subject":"[PATCH 7/8] reflog: convert to parse_options() API","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-03-17T18:08:39Z","receivedAt":"2022-03-17T18:09:12Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Continue the work started in 33d7bdd6459 (builtin/reflog.c: use\nparse-options api for expire, delete subcommands, 2022-01-06) and\nconvert the cmd_reflog() function itself to use the parse_options()\nAPI.\n\nLet's also add a test which would fail if we forgot\nPARSE_OPT_NO_INTERNAL_HELP here, as well as making sure that we'll\nstill pass through \"--\" by supplying PARSE_OPT_KEEP_DASHDASH. For that\ntest we need to change \"test_commit()\" to accept files starting with\n\"--\".\n\nThe \"git reflog -h\" usage will now show the usage for all of the\nsub-commands, rather than a terse summary which wasn't\ncorrect (e.g. \"git reflog exists\" is not a valid command). See my\n8757b35d443 (commit-graph: define common usage with a macro,\n2021-08-23) for prior art.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/reflog.c        | 40 ++++++++++++++++++++++++++++++++--------\n t/t1410-reflog.sh       | 17 +++++++++++++++++\n t/test-lib-functions.sh |  2 +-\n 3 files changed, 50 insertions(+), 9 deletions(-)\n\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex 9847e9db3de..3971921fc14 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -32,6 +32,14 @@ static const char *const reflog_exists_usage[] = {\n \tNULL,\n };\n \n+static const char *const reflog_usage[] = {\n+\tN_(\"git reflog [show] [<log-options>] [<ref>]\"),\n+\tBUILTIN_REFLOG_EXPIRE_USAGE,\n+\tBUILTIN_REFLOG_DELETE_USAGE,\n+\tBUILTIN_REFLOG_EXISTS_USAGE,\n+\tNULL\n+};\n+\n static timestamp_t default_reflog_expire;\n static timestamp_t default_reflog_expire_unreachable;\n \n@@ -372,17 +380,28 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n  * main \"reflog\"\n  */\n \n-static const char reflog_usage[] =\n-\"git reflog [ show | expire | delete | exists ]\";\n-\n int cmd_reflog(int argc, const char **argv, const char *prefix)\n {\n-\tif (argc > 1 && !strcmp(argv[1], \"-h\"))\n-\t\tusage(_(reflog_usage));\n+\tstruct option options[] = {\n+\t\tOPT_END()\n+\t};\n \n-\t/* With no command, we default to showing it. */\n-\tif (argc < 2 || *argv[1] == '-')\n-\t\treturn cmd_log_reflog(argc, argv, prefix);\n+\targc = parse_options(argc, argv, prefix, options, reflog_usage,\n+\t\t\t     PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 |\n+\t\t\t     PARSE_OPT_KEEP_UNKNOWN |\n+\t\t\t     PARSE_OPT_NO_INTERNAL_HELP);\n+\n+\t/*\n+\t  * With \"git reflog\" we default to showing it. !argc is\n+\t  * impossible with PARSE_OPT_KEEP_ARGV0.\n+\t  */\n+\tif (argc == 1)\n+\t\tgoto log_reflog;\n+\n+\tif (!strcmp(argv[1], \"-h\"))\n+\t\tusage_with_options(reflog_usage, options);\n+\telse if (*argv[1] == '-')\n+\t\tgoto log_reflog;\n \n \tif (!strcmp(argv[1], \"show\"))\n \t\treturn cmd_log_reflog(argc - 1, argv + 1, prefix);\n@@ -393,5 +412,10 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)\n \telse if (!strcmp(argv[1], \"exists\"))\n \t\treturn cmd_reflog_exists(argc - 1, argv + 1, prefix);\n \n+\t/*\n+\t * Fall-through for e.g. \"git reflog -1\", \"git reflog master\",\n+\t * as well as the plain \"git reflog\" above goto above.\n+\t */\n+log_reflog:\n \treturn cmd_log_reflog(argc, argv, prefix);\n }\ndiff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh\nindex 68f69bb5431..0dc36d842b0 100755\n--- a/t/t1410-reflog.sh\n+++ b/t/t1410-reflog.sh\n@@ -106,6 +106,23 @@ test_expect_success setup '\n \ttest_line_count = 4 output\n '\n \n+test_expect_success 'correct usage on sub-command -h' '\n+\ttest_expect_code 129 git reflog expire -h >err &&\n+\tgrep \"git reflog expire\" err\n+'\n+\n+test_expect_success 'pass through -- to sub-command' '\n+\ttest_when_finished \"rm -rf repo\" &&\n+\tgit init repo &&\n+\ttest_commit -C repo message --a-file contents dash-tag &&\n+\n+\tgit -C repo reflog show -- --does-not-exist >out &&\n+\ttest_must_be_empty out &&\n+\tgit -C repo reflog show >expect &&\n+\tgit -C repo reflog show -- --a-file >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success rewind '\n \ttest_tick && git reset --hard HEAD~2 &&\n \ttest -f C &&\ndiff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh\nindex 0f439c99d61..1d004744589 100644\n--- a/t/test-lib-functions.sh\n+++ b/t/test-lib-functions.sh\n@@ -329,7 +329,7 @@ test_commit () {\n \telse\n \t\t$echo \"${3-$1}\" >\"$indir$file\"\n \tfi &&\n-\tgit ${indir:+ -C \"$indir\"} add \"$file\" &&\n+\tgit ${indir:+ -C \"$indir\"} add -- \"$file\" &&\n \tif test -z \"$notick\"\n \tthen\n \t\ttest_tick\n-- \n2.35.1.1384.g7d2906948a1\n\n"},{"id":"451586","messageId":"patch-8.8-618e975f8b2-20220317T180439Z-avarab@gmail.com","threadId":"57578","inReplyTo":"cover-0.8-00000000000-20220317T180439Z-avarab@gmail.com","subject":"[PATCH 8/8] reflog [show]: display sensible -h output","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-03-17T18:08:40Z","receivedAt":"2022-03-17T18:09:13Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the \"git reflog show -h\" output to show the usage summary\nrelevant to it, rather than displaying the same output that \"git log\n-h\" would show.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/reflog.c  | 25 +++++++++++++++++++++++--\n t/t1410-reflog.sh |  5 +++++\n 2 files changed, 28 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex 3971921fc14..aaf65ed31c6 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -5,6 +5,9 @@\n #include \"worktree.h\"\n #include \"reflog.h\"\n \n+#define BUILTIN_REFLOG_SHOW_USAGE \\\n+\tN_(\"git reflog [show] [<log-options>] [<ref>]\")\n+\n #define BUILTIN_REFLOG_EXPIRE_USAGE \\\n \tN_(\"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\\n\" \\\n \t   \"                  [--rewrite] [--updateref] [--stale-fix]\\n\" \\\n@@ -17,6 +20,11 @@\n #define BUILTIN_REFLOG_EXISTS_USAGE \\\n \tN_(\"git reflog exists <ref>\")\n \n+static const char *const reflog_show_usage[] = {\n+\tBUILTIN_REFLOG_SHOW_USAGE,\n+\tNULL,\n+};\n+\n static const char *const reflog_expire_usage[] = {\n \tBUILTIN_REFLOG_EXPIRE_USAGE,\n \tNULL\n@@ -33,7 +41,7 @@ static const char *const reflog_exists_usage[] = {\n };\n \n static const char *const reflog_usage[] = {\n-\tN_(\"git reflog [show] [<log-options>] [<ref>]\"),\n+\tBUILTIN_REFLOG_SHOW_USAGE,\n \tBUILTIN_REFLOG_EXPIRE_USAGE,\n \tBUILTIN_REFLOG_DELETE_USAGE,\n \tBUILTIN_REFLOG_EXISTS_USAGE,\n@@ -207,6 +215,19 @@ static int expire_total_callback(const struct option *opt,\n \treturn 0;\n }\n \n+static int cmd_reflog_show(int argc, const char **argv, const char *prefix)\n+{\n+\tstruct option options[] = {\n+\t\tOPT_END()\n+\t};\n+\n+\tparse_options(argc, argv, prefix, options, reflog_show_usage,\n+\t\t      PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 |\n+\t\t      PARSE_OPT_KEEP_UNKNOWN);\n+\n+\treturn cmd_log_reflog(argc - 1, argv + 1, prefix);\n+}\n+\n static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n {\n \tstruct cmd_reflog_expire_cb cmd = { 0 };\n@@ -404,7 +425,7 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)\n \t\tgoto log_reflog;\n \n \tif (!strcmp(argv[1], \"show\"))\n-\t\treturn cmd_log_reflog(argc - 1, argv + 1, prefix);\n+\t\treturn cmd_reflog_show(argc, argv, prefix);\n \telse if (!strcmp(argv[1], \"expire\"))\n \t\treturn cmd_reflog_expire(argc - 1, argv + 1, prefix);\n \telse if (!strcmp(argv[1], \"delete\"))\ndiff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh\nindex 0dc36d842b0..3f469353ec7 100755\n--- a/t/t1410-reflog.sh\n+++ b/t/t1410-reflog.sh\n@@ -111,6 +111,11 @@ test_expect_success 'correct usage on sub-command -h' '\n \tgrep \"git reflog expire\" err\n '\n \n+test_expect_success 'correct usage on \"git reflog show -h\"' '\n+\ttest_expect_code 129 git reflog show -h >err &&\n+\tgrep -F \"git reflog [show]\" err\n+'\n+\n test_expect_success 'pass through -- to sub-command' '\n \ttest_when_finished \"rm -rf repo\" &&\n \tgit init repo &&\n-- \n2.35.1.1384.g7d2906948a1\n\n"},{"id":"451588","messageId":"99CF36A8-B9FD-4E05-A2DA-B4662C530738@gmail.com","threadId":"57578","inReplyTo":"patch-1.8-5069b3fd0ff-20220317T180439Z-avarab@gmail.com","subject":"Re: [PATCH 1/8] reflog.c: indent argument lists","fromName":"John Cai","fromEmail":"johncai86@gmail.com","sentAt":"2022-03-17T19:42:10Z","receivedAt":"2022-03-17T19:42:17Z","isPatch":true,"sender":{"key":"johncai86@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2354211?v=4"},"body":"Hi Ævar\n\nOn 17 Mar 2022, at 14:08, Ævar Arnfjörð Bjarmason wrote:\n\n> When reflog.c was lib-ified in 7d3d226e700 (reflog: libify delete\n> reflog function and helpers, 2022-03-02) these previously \"static\"\n> functions were made non-\"static\", but the argument lists were not\n> correspondingly indented according to our usual coding style. Let's do\n> that.\n>\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> ---\n>  reflog.c | 20 ++++++++++----------\n>  1 file changed, 10 insertions(+), 10 deletions(-)\n>\n> diff --git a/reflog.c b/reflog.c\n> index 333fd8708fe..82e5a935117 100644\n> --- a/reflog.c\n> +++ b/reflog.c\n> @@ -240,8 +240,8 @@ static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit\n>   * Return true iff the specified reflog entry should be expired.\n>   */\n>  int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid,\n> -\t\t\t\t    const char *email, timestamp_t timestamp, int tz,\n> -\t\t\t\t    const char *message, void *cb_data)\n> +\t\t\t     const char *email, timestamp_t timestamp, int tz,\n> +\t\t\t     const char *message, void *cb_data)\n>  {\n>  \tstruct expire_reflog_policy_cb *cb = cb_data;\n>  \tstruct commit *old_commit, *new_commit;\n> @@ -273,10 +273,10 @@ int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid,\n>  }\n>\n>  int should_expire_reflog_ent_verbose(struct object_id *ooid,\n> -\t\t\t\t\t    struct object_id *noid,\n> -\t\t\t\t\t    const char *email,\n> -\t\t\t\t\t    timestamp_t timestamp, int tz,\n> -\t\t\t\t\t    const char *message, void *cb_data)\n> +\t\t\t\t     struct object_id *noid,\n> +\t\t\t\t     const char *email,\n> +\t\t\t\t     timestamp_t timestamp, int tz,\n> +\t\t\t\t     const char *message, void *cb_data)\n>  {\n>  \tstruct expire_reflog_policy_cb *cb = cb_data;\n>  \tint expire;\n> @@ -323,8 +323,8 @@ static int is_head(const char *refname)\n>  }\n>\n>  void reflog_expiry_prepare(const char *refname,\n> -\t\t\t\t  const struct object_id *oid,\n> -\t\t\t\t  void *cb_data)\n> +\t\t\t   const struct object_id *oid,\n> +\t\t\t   void *cb_data)\n>  {\n>  \tstruct expire_reflog_policy_cb *cb = cb_data;\n>  \tstruct commit_list *elem;\n> @@ -377,8 +377,8 @@ void reflog_expiry_cleanup(void *cb_data)\n>  }\n>\n>  int count_reflog_ent(struct object_id *ooid, struct object_id *noid,\n> -\t\tconst char *email, timestamp_t timestamp, int tz,\n> -\t\tconst char *message, void *cb_data)\n> +\t\t     const char *email, timestamp_t timestamp, int tz,\n> +\t\t     const char *message, void *cb_data)\n>  {\n>  \tstruct cmd_reflog_expire_cb *cb = cb_data;\n>  \tif (!cb->expire_total || timestamp < cb->expire_total)\n\nJust wanted to say thanks for fixing these :)\n\n> -- \n> 2.35.1.1384.g7d2906948a1\n"},{"id":"451613","messageId":"xmqqczikcasz.fsf@gitster.g","threadId":"57578","inReplyTo":"patch-5.8-130e718722b-20220317T180439Z-avarab@gmail.com","subject":"Re: [PATCH 5/8] git reflog [expire|delete]: make -h output consistent with SYNOPSIS","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-03-18T01:24:28Z","receivedAt":"2022-03-18T01:24:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Make use of the guaranteed pretty alignment of \"-h\" output added in my\n> 4631cfc20bd (parse-options: properly align continued usage output,\n> 2021-09-21) and wrap and format the \"git reflog [expire|delete] -h\"\n\n\"(expire|delete) -h\", I think.  Does it matter who wrote an earlier\ncommit, by the way?  You do not name who did 33d7bdd6459 you refer\nto in the later part of the proposed log message, for example, and\nit feels simpler to consider all the past commits as just \"ours\".\n\n> usage output. Also add the missing \"--single-worktree\" option, as well\n> as adding other things that were in the SYNOPSIS output, but not in\n> the \"-h\" output.\n>\n> This was last touched in 33d7bdd6459 (builtin/reflog.c: use\n> parse-options api for expire, delete subcommands, 2022-01-06), but in\n> that commit the previous usage() output was faithfully\n> reproduced. Let's follow-up on that and make this even easier to read.\n>\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> ---\n>  builtin/reflog.c | 11 +++++------\n>  1 file changed, 5 insertions(+), 6 deletions(-)\n>\n> diff --git a/builtin/reflog.c b/builtin/reflog.c\n> index 25313d504a9..458764400b5 100644\n> --- a/builtin/reflog.c\n> +++ b/builtin/reflog.c\n> @@ -6,14 +6,13 @@\n>  #include \"reflog.h\"\n>  \n>  #define BUILTIN_REFLOG_EXPIRE_USAGE \\\n> -\tN_(\"git reflog expire [--expire=<time>] \" \\\n> -\t   \"[--expire-unreachable=<time>] \" \\\n> -\t   \"[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] \" \\\n> -\t   \"[--verbose] [--all] <refs>...\")\n> +\tN_(\"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\\n\" \\\n> +\t   \"                  [--rewrite] [--updateref] [--stale-fix]\\n\" \\\n> +\t   \"                  [--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>...]\")\n\nOK.  This makes the line folding match what we write in the synopsis\nsection of the documentation.\n\n>  #define BUILTIN_REFLOG_DELETE_USAGE \\\n> -\tN_(\"git reflog delete [--rewrite] [--updateref] \" \\\n> -\t   \"[--dry-run | -n] [--verbose] <refs>...\")\n> +\tN_(\"git reflog delete [--rewrite] [--updateref]\\n\" \\\n> +\t   \"                  [--dry-run | -n] [--verbose] <ref>@{<specifier>}...\")\n\nLikewise.  Looking good.\n\n\n>  #define BUILTIN_REFLOG_EXISTS_USAGE \\\n>  \tN_(\"git reflog exists <ref>\")\n"},{"id":"451614","messageId":"xmqq35jgcail.fsf@gitster.g","threadId":"57578","inReplyTo":"patch-6.8-f88acdc9702-20220317T180439Z-avarab@gmail.com","subject":"Re: [PATCH 6/8] reflog exists: use parse_options() API","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-03-18T01:30:42Z","receivedAt":"2022-03-18T01:30:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Change the \"reflog exists\" command added in afcb2e7a3b8 (git-reflog:\n> add exists command, 2015-07-21) to use parse_options() instead of its\n> own custom command-line parser. This continues work started in\n> 33d7bdd6459 (builtin/reflog.c: use parse-options api for expire,\n> delete subcommands, 2022-01-06).\n>\n> As a result we'll understand the --end-of-options synonym for \"--\", so\n> let's test for that.\n>\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> ---\n>  builtin/reflog.c         | 38 ++++++++++++++++----------------------\n>  t/t1418-reflog-exists.sh |  5 +++++\n>  2 files changed, 21 insertions(+), 22 deletions(-)\n>\n> diff --git a/builtin/reflog.c b/builtin/reflog.c\n> index 458764400b5..9847e9db3de 100644\n> --- a/builtin/reflog.c\n> +++ b/builtin/reflog.c\n> @@ -27,8 +27,10 @@ static const char *const reflog_delete_usage[] = {\n>  \tNULL\n>  };\n>  \n> -static const char reflog_exists_usage[] =\n> -\tBUILTIN_REFLOG_EXISTS_USAGE;\n> +static const char *const reflog_exists_usage[] = {\n> +\tBUILTIN_REFLOG_EXISTS_USAGE,\n> +\tNULL,\n> +};\n\nGood.\n\nThe discrepanthy in the postimage of [PATCH 4/8] bothered me a lot.\n\nThis would immediately help by making it possible to feed it to\nparse_options(), but the uniformity will also make it easier to\nconcatenate common and subcommand specific usage later, I would\npresume, if we wanted to.\n\n> +\tstruct option options[] = {\n> +\t\tOPT_END()\n> +\t};\n> +\tconst char *refname;\n>  \n> +\targc = parse_options(argc, argv, prefix, options, reflog_exists_usage,\n> +\t\t\t     0);\n> +\tif (!argc)\n> +\t\tusage_with_options(reflog_exists_usage, options);\n>  \n> +\trefname = argv[0];\n> +\tif (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))\n> +\t\tdie(_(\"invalid ref format: %s\"), refname);\n> +\treturn !reflog_exists(refname);\n>  }\n\nQuite straight-forward.  Looking good.\n"},{"id":"451615","messageId":"xmqqy218av2s.fsf@gitster.g","threadId":"57578","inReplyTo":"patch-7.8-19e1ff0c569-20220317T180439Z-avarab@gmail.com","subject":"Re: [PATCH 7/8] reflog: convert to parse_options() API","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-03-18T01:49:31Z","receivedAt":"2022-03-18T01:49:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n>  int cmd_reflog(int argc, const char **argv, const char *prefix)\n>  {\n> -\tif (argc > 1 && !strcmp(argv[1], \"-h\"))\n> -\t\tusage(_(reflog_usage));\n> +\tstruct option options[] = {\n> +\t\tOPT_END()\n> +\t};\n>  \n> -\t/* With no command, we default to showing it. */\n> -\tif (argc < 2 || *argv[1] == '-')\n> -\t\treturn cmd_log_reflog(argc, argv, prefix);\n> +\targc = parse_options(argc, argv, prefix, options, reflog_usage,\n> +\t\t\t     PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 |\n> +\t\t\t     PARSE_OPT_KEEP_UNKNOWN |\n> +\t\t\t     PARSE_OPT_NO_INTERNAL_HELP);\n> +\n> +\t/*\n> +\t  * With \"git reflog\" we default to showing it. !argc is\n> +\t  * impossible with PARSE_OPT_KEEP_ARGV0.\n> +\t  */\n\nFunny indentation?\n\n> +\tif (argc == 1)\n> +\t\tgoto log_reflog;\n> +\n> +\tif (!strcmp(argv[1], \"-h\"))\n> +\t\tusage_with_options(reflog_usage, options);\n> +\telse if (*argv[1] == '-')\n> +\t\tgoto log_reflog;\n\nUnfortunate.  KEEP_UNKNOWN is unwieldy, but it is no worse than the\noriginal.  We do not have options that are common to all \"git reflog\"\nsubcommands, so the first token after \"git reflog\" being anything\nthat begins with \"-\" is a sign that the default \"show\" command is\nbeing asked for.\n\n> diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh\n> index 0f439c99d61..1d004744589 100644\n> --- a/t/test-lib-functions.sh\n> +++ b/t/test-lib-functions.sh\n> @@ -329,7 +329,7 @@ test_commit () {\n>  \telse\n>  \t\t$echo \"${3-$1}\" >\"$indir$file\"\n>  \tfi &&\n> -\tgit ${indir:+ -C \"$indir\"} add \"$file\" &&\n> +\tgit ${indir:+ -C \"$indir\"} add -- \"$file\" &&\n\nOK.\n\nLooking good.\n"},{"id":"452515","messageId":"20220328212152.589491-1-szeder.dev@gmail.com","threadId":"57578","inReplyTo":"patch-8.8-618e975f8b2-20220317T180439Z-avarab@gmail.com","subject":"[PATCH] reflog: fix 'show' subcommand's argv","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2022-03-28T21:21:52Z","receivedAt":"2022-03-28T21:22:12Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"cmd_reflog() invokes parse_options() with PARSE_OPT_KEEP_ARGV0, but it\ndoesn't account for the retained argv[0] before invoking\ncmd_reflog_show() to handle the 'git reflog show' subcommand.\nConsequently, cmd_reflog_show() always gets an 'argv' array starting\nwith elements argv[0]=\"reflog\" and argv[1]=\"show\".\n\nStrip the name of the git command from the 'argv' array before passing\nit to the function handling the 'show' subcommand.\n\nThere is no user-visible bug here, because cmd_reflog_show() doesn't\nhave any options or parameters of its own.\n\nSigned-off-by: SZEDER Gábor <szeder.dev@gmail.com>\n---\n builtin/reflog.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex 6c4fe1af40..c943c2aabe 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -225,7 +225,7 @@ static int cmd_reflog_show(int argc, const char **argv, const char *prefix)\n \t\t      PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 |\n \t\t      PARSE_OPT_KEEP_UNKNOWN);\n \n-\treturn cmd_log_reflog(argc - 1, argv + 1, prefix);\n+\treturn cmd_log_reflog(argc, argv, prefix);\n }\n \n static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n@@ -425,7 +425,7 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)\n \t\tgoto log_reflog;\n \n \tif (!strcmp(argv[1], \"show\"))\n-\t\treturn cmd_reflog_show(argc, argv, prefix);\n+\t\treturn cmd_reflog_show(argc - 1, argv + 1, prefix);\n \telse if (!strcmp(argv[1], \"expire\"))\n \t\treturn cmd_reflog_expire(argc - 1, argv + 1, prefix);\n \telse if (!strcmp(argv[1], \"delete\"))\n-- \n2.35.1.1272.g0ee9eb8209\n\n"},{"id":"452523","messageId":"xmqqa6d9zogh.fsf@gitster.g","threadId":"57578","inReplyTo":"20220328212152.589491-1-szeder.dev@gmail.com","subject":"Re: [PATCH] reflog: fix 'show' subcommand's argv","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-03-28T22:45:02Z","receivedAt":"2022-03-28T22:45:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"SZEDER Gábor <szeder.dev@gmail.com> writes:\n\n> cmd_reflog() invokes parse_options() with PARSE_OPT_KEEP_ARGV0, but it\n> doesn't account for the retained argv[0] before invoking\n> cmd_reflog_show() to handle the 'git reflog show' subcommand.\n> Consequently, cmd_reflog_show() always gets an 'argv' array starting\n> with elements argv[0]=\"reflog\" and argv[1]=\"show\".\n>\n> Strip the name of the git command from the 'argv' array before passing\n> it to the function handling the 'show' subcommand.\n>\n> There is no user-visible bug here, because cmd_reflog_show() doesn't\n> have any options or parameters of its own.\n\nThese two changes cancel out as far as cmd_log_reflog() is concerned\nbut makes a difference inside cmd_reflog_show(), if that function\ncared.\n\nThere is parse_options() call that uses argc and argv supplied by\nthe caller, and it is not adjusted, so it is curious why there is no\nexternally observable behaviour change.  But argv[0] and argv[1] are\nnot dashed options and because we do not say STOP_AT_NON_OPTION,\nparse_options() will skip such an extra non-option argument, so is\nthat the reason why there is no behaviour change?\n\nAs this is an \"oops, that is not quite right\" fix for\nab/reflog-parse-options topic, let's queue it diretly on top of the\ntopic.\n\nThanks.\n\n> Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>\n> ---\n>  builtin/reflog.c | 4 ++--\n>  1 file changed, 2 insertions(+), 2 deletions(-)\n>\n> diff --git a/builtin/reflog.c b/builtin/reflog.c\n> index 6c4fe1af40..c943c2aabe 100644\n> --- a/builtin/reflog.c\n> +++ b/builtin/reflog.c\n> @@ -225,7 +225,7 @@ static int cmd_reflog_show(int argc, const char **argv, const char *prefix)\n>  \t\t      PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 |\n>  \t\t      PARSE_OPT_KEEP_UNKNOWN);\n>  \n> -\treturn cmd_log_reflog(argc - 1, argv + 1, prefix);\n> +\treturn cmd_log_reflog(argc, argv, prefix);\n>  }\n>  \n>  static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n> @@ -425,7 +425,7 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)\n>  \t\tgoto log_reflog;\n>  \n>  \tif (!strcmp(argv[1], \"show\"))\n> -\t\treturn cmd_reflog_show(argc, argv, prefix);\n> +\t\treturn cmd_reflog_show(argc - 1, argv + 1, prefix);\n>  \telse if (!strcmp(argv[1], \"expire\"))\n>  \t\treturn cmd_reflog_expire(argc - 1, argv + 1, prefix);\n>  \telse if (!strcmp(argv[1], \"delete\"))\n"}]}