Skip to content

Commit 0f0a8a1

Browse files
inosmeetgitster
authored andcommitted
builtin/refs: add 'exists' subcommand
As part of the ongoing effort to consolidate reference handling, introduce a new `exists` subcommand. This command provides the same functionality and exit-code behavior as `git show-ref --exists`, serving as its modern replacement. The logic for `show-ref --exists` is minimal. Rather than creating a shared helper function which would be overkill for ~20 lines of code, its implementation is intentionally duplicated here. This contrasts with `git refs list`, where sharing the larger implementation of `for-each-ref` was necessary. Documentation for the new subcommand is also added to the `git-refs(1)` man page. Mentored-by: Patrick Steinhardt <[email protected]> Mentored-by: shejialuo <[email protected]> Signed-off-by: Meet Soni <[email protected]> Acked-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1fa6894 commit 0f0a8a1

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

Documentation/git-refs.adoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
1818
[--contains[=<object>]] [--no-contains[=<object>]]
1919
[(--exclude=<pattern>)...] [--start-after=<marker>]
2020
[ --stdin | <pattern>... ]
21+
git refs exists <ref>
2122

2223
DESCRIPTION
2324
-----------
@@ -38,6 +39,12 @@ list::
3839
formatting, and sorting. This subcommand is an alias for
3940
linkgit:git-for-each-ref[1] and offers identical functionality.
4041

42+
exists::
43+
Check whether the given reference exists. Returns an exit code of 0 if
44+
it does, 2 if it is missing, and 1 in case looking up the reference
45+
failed with an error other than the reference being missing. This does
46+
not verify whether the reference resolves to an actual object.
47+
4148
OPTIONS
4249
-------
4350

builtin/refs.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77
#include "strbuf.h"
88
#include "worktree.h"
99
#include "for-each-ref.h"
10+
#include "refs/refs-internal.h"
1011

1112
#define REFS_MIGRATE_USAGE \
1213
N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]")
1314

1415
#define REFS_VERIFY_USAGE \
1516
N_("git refs verify [--strict] [--verbose]")
1617

18+
#define REFS_EXISTS_USAGE \
19+
N_("git refs exists <ref>")
20+
1721
static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
1822
struct repository *repo UNUSED)
1923
{
@@ -113,6 +117,48 @@ static int cmd_refs_list(int argc, const char **argv, const char *prefix,
113117
return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage);
114118
}
115119

120+
static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
121+
struct repository *repo UNUSED)
122+
{
123+
struct strbuf unused_referent = STRBUF_INIT;
124+
struct object_id unused_oid;
125+
unsigned int unused_type;
126+
int failure_errno = 0;
127+
const char *ref;
128+
int ret = 0;
129+
const char * const exists_usage[] = {
130+
REFS_EXISTS_USAGE,
131+
NULL,
132+
};
133+
struct option options[] = {
134+
OPT_END(),
135+
};
136+
137+
argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
138+
if (argc != 1)
139+
die(_("'git refs exists' requires a reference"));
140+
141+
ref = *argv++;
142+
if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
143+
&unused_oid, &unused_referent, &unused_type,
144+
&failure_errno)) {
145+
if (failure_errno == ENOENT || failure_errno == EISDIR) {
146+
error(_("reference does not exist"));
147+
ret = 2;
148+
} else {
149+
errno = failure_errno;
150+
error_errno(_("failed to look up reference"));
151+
ret = 1;
152+
}
153+
154+
goto out;
155+
}
156+
157+
out:
158+
strbuf_release(&unused_referent);
159+
return ret;
160+
}
161+
116162
int cmd_refs(int argc,
117163
const char **argv,
118164
const char *prefix,
@@ -122,13 +168,15 @@ int cmd_refs(int argc,
122168
REFS_MIGRATE_USAGE,
123169
REFS_VERIFY_USAGE,
124170
"git refs list " COMMON_USAGE_FOR_EACH_REF,
171+
REFS_EXISTS_USAGE,
125172
NULL,
126173
};
127174
parse_opt_subcommand_fn *fn = NULL;
128175
struct option opts[] = {
129176
OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
130177
OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify),
131178
OPT_SUBCOMMAND("list", &fn, cmd_refs_list),
179+
OPT_SUBCOMMAND("exists", &fn, cmd_refs_exists),
132180
OPT_END(),
133181
};
134182

0 commit comments

Comments
 (0)