From 24738045603d3e348233ef1211c672ddd06f68f3 Mon Sep 17 00:00:00 2001 From: Meet Soni Date: Thu, 27 Mar 2025 12:42:36 +0530 Subject: [PATCH] refs: add list subcommand consolidate `git show-ref` command as `git refs list` along with some of the flags. Namely: - --branches | --heads(deprecated) - --head - --tags So, now new subcommands can replace old ones like: - `git show-ref [--head]` -> `git refs list [--head]` - `git show-ref [--branches | --heads]` -> `git refs list [-branches | --heads]` - `git show-ref [--tags]` -> `git refs list [--tags]` Also add tests for this subcommand along with their flags. Signed-off-by: Meet Soni --- Documentation/git-refs.adoc | 19 ++++++++++++ builtin/refs.c | 62 +++++++++++++++++++++++++++++++++++++ t/meson.build | 1 + t/t1461-refs-list.sh | 52 +++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100755 t/t1461-refs-list.sh diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc index 4d6dc994f92eb2..2b21d09ec7c9ac 100644 --- a/Documentation/git-refs.adoc +++ b/Documentation/git-refs.adoc @@ -11,6 +11,7 @@ SYNOPSIS [synopsis] git refs migrate --ref-format= [--no-reflog] [--dry-run] git refs verify [--strict] [--verbose] +git refs list [--head] [--branches] [--tag] DESCRIPTION ----------- @@ -25,6 +26,9 @@ migrate:: verify:: Verify reference database consistency. +list:: + Displays references available in a local repository along with the associated + commit IDs. OPTIONS ------- @@ -57,6 +61,21 @@ The following options are specific to 'git refs verify': --verbose:: When verifying the reference database consistency, be chatty. +The following options are specific to 'git refs verify': + +--head:: + + Show the HEAD reference, even if it would normally be filtered out. + +--branches:: +--tags:: + + Limit to local branches and local tags, respectively. These options + are not mutually exclusive; when given both, references stored in + "refs/heads" and "refs/tags" are displayed. Note that `--heads` + is a deprecated synonym for `--branches` and may be removed + in the future. + KNOWN LIMITATIONS ----------------- diff --git a/builtin/refs.c b/builtin/refs.c index 44d592a94cf381..66036ce2fc4f9e 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -6,6 +6,7 @@ #include "refs.h" #include "strbuf.h" #include "worktree.h" +#include "object-name.h" #define REFS_MIGRATE_USAGE \ N_("git refs migrate --ref-format= [--no-reflog] [--dry-run]") @@ -13,6 +14,9 @@ #define REFS_VERIFY_USAGE \ N_("git refs verify [--strict] [--verbose]") +#define REFS_LIST_USAGE \ + N_("git refs list [--head] [--branches] [--tag]") + static int cmd_refs_migrate(int argc, const char **argv, const char *prefix, struct repository *repo UNUSED) { @@ -101,6 +105,62 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix, return ret; } +struct patterns_options { + int show_head; + int branches_only; + int tags_only; +}; + +static int show_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, + int flag UNUSED, void *cbdata UNUSED) +{ + const char *hex; + + hex = repo_find_unique_abbrev(the_repository, oid, 0); + printf("%s %s\n", hex, refname); + + return 0; +} + +static int cmd_refs_list(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) +{ + struct patterns_options patterns_opts = {0}; + const char * const list_usage[] = { + REFS_LIST_USAGE, + NULL, + }; + struct option options[] = { + OPT_BOOL(0, "head", &patterns_opts.show_head, + N_("show the HEAD reference, even if it would be filtered out")), + OPT_BOOL(0, "tags", &patterns_opts.tags_only, N_("only show tags (can be combined with --branches)")), + OPT_BOOL(0, "branches", &patterns_opts.branches_only, N_("only show branches (can be combined with --tags)")), + OPT_HIDDEN_BOOL(0, "heads", &patterns_opts.branches_only, + N_("deprecated synonym for --branches")), + OPT_END(), + }; + + argc = parse_options(argc, argv, prefix, options, list_usage, 0); + if (argc) + usage(_("'git refs list' takes no arguments")); + + if (patterns_opts.show_head) + refs_head_ref(get_main_ref_store(the_repository), show_ref, + &patterns_opts); + if (patterns_opts.tags_only || patterns_opts.branches_only) { + if (patterns_opts.branches_only) + refs_for_each_fullref_in(get_main_ref_store(the_repository), + "refs/heads/", NULL, show_ref, &patterns_opts); + + if (patterns_opts.tags_only) + refs_for_each_fullref_in(get_main_ref_store(the_repository), + "refs/tags/", NULL, show_ref, &patterns_opts); + } + else refs_for_each_ref(get_main_ref_store(the_repository), show_ref, &patterns_opts); + + return 0; +} + int cmd_refs(int argc, const char **argv, const char *prefix, @@ -109,12 +169,14 @@ int cmd_refs(int argc, const char * const refs_usage[] = { REFS_MIGRATE_USAGE, REFS_VERIFY_USAGE, + REFS_LIST_USAGE, NULL, }; parse_opt_subcommand_fn *fn = NULL; struct option opts[] = { OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate), OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify), + OPT_SUBCOMMAND("list", &fn, cmd_refs_list), OPT_END(), }; diff --git a/t/meson.build b/t/meson.build index a59da26be3f471..602a9a9293ccf4 100644 --- a/t/meson.build +++ b/t/meson.build @@ -224,6 +224,7 @@ integration_tests = [ 't1450-fsck.sh', 't1451-fsck-buffer.sh', 't1460-refs-migrate.sh', + 't1461-refs-list.sh', 't1500-rev-parse.sh', 't1501-work-tree.sh', 't1502-rev-parse-parseopt.sh', diff --git a/t/t1461-refs-list.sh b/t/t1461-refs-list.sh new file mode 100755 index 00000000000000..62524c87efad75 --- /dev/null +++ b/t/t1461-refs-list.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +test_description='refs list' +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +. ./test-lib.sh + +test_expect_success setup ' + test_commit --annotate A && + git checkout -b side && + test_commit --annotate B && + git checkout main && + test_commit C && + git branch B A^0 +' +test_expect_success 'refs list --branches, --tags, --head' ' + for branch in B main side + do + echo $(git rev-parse refs/heads/$branch) refs/heads/$branch || return 1 + done >expect.branches && + git refs list --branches >actual && + test_cmp expect.branches actual && + + for tag in A B C + do + echo $(git rev-parse refs/tags/$tag) refs/tags/$tag || return 1 + done >expect.tags && + git refs list --tags >actual && + test_cmp expect.tags actual && + + cat expect.branches expect.tags >expect && + git refs list --branches --tags >actual && + test_cmp expect actual && + + { + echo $(git rev-parse HEAD) HEAD && + cat expect.branches expect.tags + } >expect && + git refs list --branches --tags --head >actual && + test_cmp expect actual +' + +test_expect_success 'refs list --heads is deprecated and hidden' ' + test_expect_code 129 git refs list -h >short-help && + test_grep ! -e --heads short-help && + git refs list --heads >actual 2>warning && + test_grep ! deprecated warning && + test_cmp expect.branches actual +' + +test_done