summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2022-04-04 10:56:21 -0700
committerLibravatar Junio C Hamano <gitster@pobox.com>2022-04-04 10:56:21 -0700
commit3ff8cbfe8a333f55931fa9b588f106e060a67079 (patch)
treed4096bb40c2513a46d6dfd4ecbbbe219c158a683
parentThe 17th batch (diff)
parentreflog: fix 'show' subcommand's argv (diff)
downloadtgif-3ff8cbfe8a333f55931fa9b588f106e060a67079.tar.xz
Merge branch 'ab/reflog-parse-options'
"git reflog" command now uses parse-options API to parse its command line options. * ab/reflog-parse-options: reflog: fix 'show' subcommand's argv reflog [show]: display sensible -h output reflog: convert to parse_options() API reflog exists: use parse_options() API git reflog [expire|delete]: make -h output consistent with SYNOPSIS reflog: move "usage" variables and use macros reflog tests: add missing "git reflog exists" tests reflog: refactor cmd_reflog() to "if" branches reflog.c: indent argument lists
-rw-r--r--builtin/reflog.c146
-rw-r--r--reflog.c20
-rwxr-xr-xt/t1410-reflog.sh22
-rwxr-xr-xt/t1411-reflog-show.sh5
-rwxr-xr-xt/t1418-reflog-exists.sh37
-rw-r--r--t/test-lib-functions.sh2
6 files changed, 165 insertions, 67 deletions
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 9407f835cb..c943c2aabe 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -5,8 +5,48 @@
#include "worktree.h"
#include "reflog.h"
-static const char reflog_exists_usage[] =
-N_("git reflog exists <ref>");
+#define BUILTIN_REFLOG_SHOW_USAGE \
+ N_("git reflog [show] [<log-options>] [<ref>]")
+
+#define BUILTIN_REFLOG_EXPIRE_USAGE \
+ N_("git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" \
+ " [--rewrite] [--updateref] [--stale-fix]\n" \
+ " [--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>...]")
+
+#define BUILTIN_REFLOG_DELETE_USAGE \
+ N_("git reflog delete [--rewrite] [--updateref]\n" \
+ " [--dry-run | -n] [--verbose] <ref>@{<specifier>}...")
+
+#define BUILTIN_REFLOG_EXISTS_USAGE \
+ N_("git reflog exists <ref>")
+
+static const char *const reflog_show_usage[] = {
+ BUILTIN_REFLOG_SHOW_USAGE,
+ NULL,
+};
+
+static const char *const reflog_expire_usage[] = {
+ BUILTIN_REFLOG_EXPIRE_USAGE,
+ NULL
+};
+
+static const char *const reflog_delete_usage[] = {
+ BUILTIN_REFLOG_DELETE_USAGE,
+ NULL
+};
+
+static const char *const reflog_exists_usage[] = {
+ BUILTIN_REFLOG_EXISTS_USAGE,
+ NULL,
+};
+
+static const char *const reflog_usage[] = {
+ BUILTIN_REFLOG_SHOW_USAGE,
+ BUILTIN_REFLOG_EXPIRE_USAGE,
+ BUILTIN_REFLOG_DELETE_USAGE,
+ BUILTIN_REFLOG_EXISTS_USAGE,
+ NULL
+};
static timestamp_t default_reflog_expire;
static timestamp_t default_reflog_expire_unreachable;
@@ -147,14 +187,6 @@ static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, const char
cb->expire_unreachable = default_reflog_expire_unreachable;
}
-static const char * reflog_expire_usage[] = {
- N_("git reflog expire [--expire=<time>] "
- "[--expire-unreachable=<time>] "
- "[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] "
- "[--verbose] [--all] <refs>..."),
- NULL
-};
-
static int expire_unreachable_callback(const struct option *opt,
const char *arg,
int unset)
@@ -183,6 +215,19 @@ static int expire_total_callback(const struct option *opt,
return 0;
}
+static int cmd_reflog_show(int argc, const char **argv, const char *prefix)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+
+ parse_options(argc, argv, prefix, options, reflog_show_usage,
+ PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 |
+ PARSE_OPT_KEEP_UNKNOWN);
+
+ return cmd_log_reflog(argc, argv, prefix);
+}
+
static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
{
struct cmd_reflog_expire_cb cmd = { 0 };
@@ -304,12 +349,6 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
return status;
}
-static const char * reflog_delete_usage[] = {
- N_("git reflog delete [--rewrite] [--updateref] "
- "[--dry-run | -n] [--verbose] <refs>..."),
- NULL
-};
-
static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
{
int i, status = 0;
@@ -342,57 +381,62 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
{
- int i, start = 0;
-
- for (i = 1; i < argc; i++) {
- const char *arg = argv[i];
- if (!strcmp(arg, "--")) {
- i++;
- break;
- }
- else if (arg[0] == '-')
- usage(_(reflog_exists_usage));
- else
- break;
- }
-
- start = i;
+ struct option options[] = {
+ OPT_END()
+ };
+ const char *refname;
- if (argc - start != 1)
- usage(_(reflog_exists_usage));
+ argc = parse_options(argc, argv, prefix, options, reflog_exists_usage,
+ 0);
+ if (!argc)
+ usage_with_options(reflog_exists_usage, options);
- if (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL))
- die(_("invalid ref format: %s"), argv[start]);
- return !reflog_exists(argv[start]);
+ refname = argv[0];
+ if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))
+ die(_("invalid ref format: %s"), refname);
+ return !reflog_exists(refname);
}
/*
* main "reflog"
*/
-static const char reflog_usage[] =
-"git reflog [ show | expire | delete | exists ]";
-
int cmd_reflog(int argc, const char **argv, const char *prefix)
{
- if (argc > 1 && !strcmp(argv[1], "-h"))
- usage(_(reflog_usage));
+ struct option options[] = {
+ OPT_END()
+ };
- /* With no command, we default to showing it. */
- if (argc < 2 || *argv[1] == '-')
- return cmd_log_reflog(argc, argv, prefix);
+ argc = parse_options(argc, argv, prefix, options, reflog_usage,
+ PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 |
+ PARSE_OPT_KEEP_UNKNOWN |
+ PARSE_OPT_NO_INTERNAL_HELP);
- if (!strcmp(argv[1], "show"))
- return cmd_log_reflog(argc - 1, argv + 1, prefix);
+ /*
+ * With "git reflog" we default to showing it. !argc is
+ * impossible with PARSE_OPT_KEEP_ARGV0.
+ */
+ if (argc == 1)
+ goto log_reflog;
- if (!strcmp(argv[1], "expire"))
- return cmd_reflog_expire(argc - 1, argv + 1, prefix);
+ if (!strcmp(argv[1], "-h"))
+ usage_with_options(reflog_usage, options);
+ else if (*argv[1] == '-')
+ goto log_reflog;
- if (!strcmp(argv[1], "delete"))
+ if (!strcmp(argv[1], "show"))
+ return cmd_reflog_show(argc - 1, argv + 1, prefix);
+ else if (!strcmp(argv[1], "expire"))
+ return cmd_reflog_expire(argc - 1, argv + 1, prefix);
+ else if (!strcmp(argv[1], "delete"))
return cmd_reflog_delete(argc - 1, argv + 1, prefix);
-
- if (!strcmp(argv[1], "exists"))
+ else if (!strcmp(argv[1], "exists"))
return cmd_reflog_exists(argc - 1, argv + 1, prefix);
+ /*
+ * Fall-through for e.g. "git reflog -1", "git reflog master",
+ * as well as the plain "git reflog" above goto above.
+ */
+log_reflog:
return cmd_log_reflog(argc, argv, prefix);
}
diff --git a/reflog.c b/reflog.c
index 47ba8620c5..135a1a6e41 100644
--- a/reflog.c
+++ b/reflog.c
@@ -240,8 +240,8 @@ static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit
* Return true iff the specified reflog entry should be expired.
*/
int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid,
- const char *email, timestamp_t timestamp, int tz,
- const char *message, void *cb_data)
+ const char *email, timestamp_t timestamp, int tz,
+ const char *message, void *cb_data)
{
struct expire_reflog_policy_cb *cb = cb_data;
struct commit *old_commit, *new_commit;
@@ -273,10 +273,10 @@ int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid,
}
int should_expire_reflog_ent_verbose(struct object_id *ooid,
- struct object_id *noid,
- const char *email,
- timestamp_t timestamp, int tz,
- const char *message, void *cb_data)
+ struct object_id *noid,
+ const char *email,
+ timestamp_t timestamp, int tz,
+ const char *message, void *cb_data)
{
struct expire_reflog_policy_cb *cb = cb_data;
int expire;
@@ -323,8 +323,8 @@ static int is_head(const char *refname)
}
void reflog_expiry_prepare(const char *refname,
- const struct object_id *oid,
- void *cb_data)
+ const struct object_id *oid,
+ void *cb_data)
{
struct expire_reflog_policy_cb *cb = cb_data;
struct commit_list *elem;
@@ -379,8 +379,8 @@ void reflog_expiry_cleanup(void *cb_data)
}
int count_reflog_ent(struct object_id *ooid, struct object_id *noid,
- const char *email, timestamp_t timestamp, int tz,
- const char *message, void *cb_data)
+ const char *email, timestamp_t timestamp, int tz,
+ const char *message, void *cb_data)
{
struct cmd_reflog_expire_cb *cb = cb_data;
if (!cb->expire_total || timestamp < cb->expire_total)
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index ea8e6ac2a0..aa59954f6c 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -106,6 +106,28 @@ test_expect_success setup '
test_line_count = 4 output
'
+test_expect_success 'correct usage on sub-command -h' '
+ test_expect_code 129 git reflog expire -h >err &&
+ grep "git reflog expire" err
+'
+
+test_expect_success 'correct usage on "git reflog show -h"' '
+ test_expect_code 129 git reflog show -h >err &&
+ grep -F "git reflog [show]" err
+'
+
+test_expect_success 'pass through -- to sub-command' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo message --a-file contents dash-tag &&
+
+ git -C repo reflog show -- --does-not-exist >out &&
+ test_must_be_empty out &&
+ git -C repo reflog show >expect &&
+ git -C repo reflog show -- --a-file >actual &&
+ test_cmp expect actual
+'
+
test_expect_success rewind '
test_tick && git reset --hard HEAD~2 &&
test -f C &&
diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh
index 0bb319b944..975c4ea83a 100755
--- a/t/t1411-reflog-show.sh
+++ b/t/t1411-reflog-show.sh
@@ -169,9 +169,4 @@ test_expect_success 'git log -g -p shows diffs vs. parents' '
test_cmp expect actual
'
-test_expect_success 'reflog exists works' '
- git reflog exists refs/heads/main &&
- ! git reflog exists refs/heads/nonexistent
-'
-
test_done
diff --git a/t/t1418-reflog-exists.sh b/t/t1418-reflog-exists.sh
new file mode 100755
index 0000000000..d51ecd5e92
--- /dev/null
+++ b/t/t1418-reflog-exists.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+test_description='Test reflog display routines'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit A
+'
+
+test_expect_success 'usage' '
+ test_expect_code 129 git reflog exists &&
+ test_expect_code 129 git reflog exists -h
+'
+
+test_expect_success 'usage: unknown option' '
+ test_expect_code 129 git reflog exists --unknown-option
+'
+
+test_expect_success 'reflog exists works' '
+ git reflog exists refs/heads/main &&
+ test_must_fail git reflog exists refs/heads/nonexistent
+'
+
+test_expect_success 'reflog exists works with a "--" delimiter' '
+ git reflog exists -- refs/heads/main &&
+ test_must_fail git reflog exists -- refs/heads/nonexistent
+'
+
+test_expect_success 'reflog exists works with a "--end-of-options" delimiter' '
+ git reflog exists --end-of-options refs/heads/main &&
+ test_must_fail git reflog exists --end-of-options refs/heads/nonexistent
+'
+
+test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index a027f0c409..1c3d65e6ea 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -329,7 +329,7 @@ test_commit () {
else
$echo "${3-$1}" >"$indir$file"
fi &&
- git ${indir:+ -C "$indir"} add "$file" &&
+ git ${indir:+ -C "$indir"} add -- "$file" &&
if test -z "$notick"
then
test_tick