Skip to content

Commit

Permalink
show-ref: add --symbolic-name option
Browse files Browse the repository at this point in the history
For reftable development, it would be handy to have a tool to provide
the direct value of any ref whether it be a symbolic ref or not.
Currently there is git-symbolic-ref, which only works for symbolic refs,
and git-rev-parse, which will resolve the ref. Let's teach show-ref a
--symbolic-name option that will cause git-show-ref(1) to print out the
value symbolic references points to.

Signed-off-by: John Cai <johncai86@gmail.com>
  • Loading branch information
john-cai committed Apr 8, 2024
1 parent 2e0a7ee commit 08c9834
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 13 deletions.
21 changes: 20 additions & 1 deletion Documentation/git-show-ref.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SYNOPSIS
[verse]
'git show-ref' [--head] [-d | --dereference]
[-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]
[--heads] [--] [<pattern>...]
[--heads] [--symbolic-name] [--] [<pattern>...]
'git show-ref' --verify [-q | --quiet] [-d | --dereference]
[-s | --hash[=<n>]] [--abbrev[=<n>]]
[--] [<ref>...]
Expand Down Expand Up @@ -58,6 +58,11 @@ OPTIONS
Dereference tags into object IDs as well. They will be shown with `^{}`
appended.

--symbolic-name::

Print out the value the reference points to without dereferencing. This
is useful to know the reference that a symbolic ref is pointing to.

-s::
--hash[=<n>]::

Expand Down Expand Up @@ -146,6 +151,20 @@ $ git show-ref --heads --hash
...
-----------------------------------------------------------------------------

When using `--symbolic-name`, the output is in the format:

-----------
<oid> SP <ref> SP <symbolic-name>
-----------

For example,

-----------------------------------------------------------------------------
$ git show-ref --symbolic-name
b75428bae1d090f60bdd4b67185f814bc8f0819d refs/heads/SYMBOLIC_REF ref:refs/heads/main
...
-----------------------------------------------------------------------------

EXAMPLES
--------

Expand Down
38 changes: 27 additions & 11 deletions builtin/show-ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
static const char * const show_ref_usage[] = {
N_("git show-ref [--head] [-d | --dereference]\n"
" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n"
" [--heads] [--] [<pattern>...]"),
" [--heads] [--symbolic-name] [--] [<pattern>...]"),
N_("git show-ref --verify [-q | --quiet] [-d | --dereference]\n"
" [-s | --hash[=<n>]] [--abbrev[=<n>]]\n"
" [--] [<ref>...]"),
Expand All @@ -26,10 +26,13 @@ struct show_one_options {
int hash_only;
int abbrev;
int deref_tags;
int symbolic_name;
};

static void show_one(const struct show_one_options *opts,
const char *refname, const struct object_id *oid)
const char *refname,
const char *referent,
const struct object_id *oid, const int is_symref)
{
const char *hex;
struct object_id peeled;
Expand All @@ -44,7 +47,9 @@ static void show_one(const struct show_one_options *opts,
hex = repo_find_unique_abbrev(the_repository, oid, opts->abbrev);
if (opts->hash_only)
printf("%s\n", hex);
else
else if (opts->symbolic_name & is_symref) {
printf("%s %s ref:%s\n", hex, refname, referent);
} else
printf("%s %s\n", hex, refname);

if (!opts->deref_tags)
Expand All @@ -63,8 +68,11 @@ struct show_ref_data {
int show_head;
};

static int show_ref(const char *refname, const struct object_id *oid,
int flag UNUSED, void *cbdata)
static int show_ref_referent(struct repository *repo UNUSED,
const char *refname,
const char *referent,
const struct object_id *oid,
int flag, void *cbdata)
{
struct show_ref_data *data = cbdata;

Expand All @@ -91,11 +99,17 @@ static int show_ref(const char *refname, const struct object_id *oid,
match:
data->found_match++;

show_one(data->show_one_opts, refname, oid);
show_one(data->show_one_opts, refname, referent, oid, flag & REF_ISSYMREF);

return 0;
}

static int show_ref(const char *refname, const struct object_id *oid,
int flag, void *cbdata)
{
return show_ref_referent(NULL, refname, NULL, oid, flag, cbdata);
}

static int add_existing(const char *refname,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cbdata)
Expand Down Expand Up @@ -171,10 +185,11 @@ static int cmd_show_ref__verify(const struct show_one_options *show_one_opts,

while (*refs) {
struct object_id oid;
int flags = 0;

if ((starts_with(*refs, "refs/") || refname_is_safe(*refs)) &&
!read_ref(*refs, &oid)) {
show_one(show_one_opts, *refs, &oid);
!read_ref_full(*refs, 0, &oid, &flags)) {
show_one(show_one_opts, *refs, NULL, &oid, flags & REF_ISSYMREF);
}
else if (!show_one_opts->quiet)
die("'%s' - not a valid ref", *refs);
Expand Down Expand Up @@ -208,11 +223,11 @@ static int cmd_show_ref__patterns(const struct patterns_options *opts,
head_ref(show_ref, &show_ref_data);
if (opts->heads_only || opts->tags_only) {
if (opts->heads_only)
for_each_fullref_in("refs/heads/", show_ref, &show_ref_data);
for_each_ref_all("refs/heads/", show_ref_referent, &show_ref_data);
if (opts->tags_only)
for_each_fullref_in("refs/tags/", show_ref, &show_ref_data);
for_each_ref_all("refs/tags/", show_ref_referent, &show_ref_data);
} else {
for_each_ref(show_ref, &show_ref_data);
for_each_ref_all("", show_ref_referent, &show_ref_data);
}
if (!show_ref_data.found_match)
return 1;
Expand Down Expand Up @@ -289,6 +304,7 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
OPT_BOOL(0, "tags", &patterns_opts.tags_only, N_("only show tags (can be combined with heads)")),
OPT_BOOL(0, "heads", &patterns_opts.heads_only, N_("only show heads (can be combined with tags)")),
OPT_BOOL(0, "exists", &exists, N_("check for reference existence without resolving")),
OPT_BOOL(0, "symbolic-name", &show_one_opts.symbolic_name, N_("print out symbolic reference values")),
OPT_BOOL(0, "verify", &verify, N_("stricter reference checking, "
"requires exact ref path")),
OPT_HIDDEN_BOOL('h', NULL, &patterns_opts.show_head,
Expand Down
6 changes: 6 additions & 0 deletions refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,12 @@ int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_dat
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
}

int for_each_ref_all(const char *prefix, each_repo_ref_fn fn, void *cb_data)
{
return do_for_each_repo_ref(the_repository, prefix, fn, 0,
0, cb_data);
}

int for_each_namespaced_ref(const char **exclude_patterns,
each_ref_fn fn, void *cb_data)
{
Expand Down
2 changes: 1 addition & 1 deletion refs.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ int refs_for_each_branch_ref(struct ref_store *refs,
each_ref_fn fn, void *cb_data);
int refs_for_each_remote_ref(struct ref_store *refs,
each_ref_fn fn, void *cb_data);

/* just iterates the head ref. */
int head_ref(each_ref_fn fn, void *cb_data);

Expand Down Expand Up @@ -381,6 +380,7 @@ int for_each_tag_ref(each_ref_fn fn, void *cb_data);
int for_each_branch_ref(each_ref_fn fn, void *cb_data);
int for_each_remote_ref(each_ref_fn fn, void *cb_data);
int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data);
int for_each_ref_all(const char *prefix, each_repo_ref_fn fn, void *cb_data);

/* iterates all refs that match the specified glob pattern. */
int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data);
Expand Down
20 changes: 20 additions & 0 deletions t/t1403-show-ref.sh
Original file line number Diff line number Diff line change
Expand Up @@ -286,4 +286,24 @@ test_expect_success '--exists with existing special ref' '
git show-ref --exists FETCH_HEAD
'

test_expect_success '--symbolic-name with a non symbolic ref' '
commit_oid=$(git rev-parse refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME) &&
cat >expect <<-EOF &&
$commit_oid refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
EOF
git show-ref --symbolic-name refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME >actual &&
test_cmp expect actual
'

test_expect_success '--symbolic-name with symbolic ref' '
test_when_finished "git symbolic-ref -d refs/heads/SYMBOLIC_REF_A" &&
commit_oid=$(git rev-parse refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME) &&
cat >expect <<-EOF &&
$commit_oid refs/heads/SYMBOLIC_REF_A ref:refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
EOF
git symbolic-ref refs/heads/SYMBOLIC_REF_A refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
git show-ref --symbolic-name SYMBOLIC_REF_A >actual &&
test_cmp expect actual
'

test_done

0 comments on commit 08c9834

Please sign in to comment.