* [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand
2025-08-21 8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
@ 2025-08-21 8:52 ` Meet Soni
2025-08-21 10:21 ` Patrick Steinhardt
2025-08-21 8:52 ` [GSoC][PATCH 2/2] t: add test for git refs exists subcommand Meet Soni
` (3 subsequent siblings)
4 siblings, 1 reply; 23+ messages in thread
From: Meet Soni @ 2025-08-21 8:52 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, Meet Soni
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 <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
Documentation/git-refs.adoc | 7 ++++++
builtin/refs.c | 48 +++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
index d462953fb5..bfa9b3ea2d 100644
--- a/Documentation/git-refs.adoc
+++ b/Documentation/git-refs.adoc
@@ -18,6 +18,7 @@ git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
[--contains[=<object>]] [--no-contains[=<object>]]
[(--exclude=<pattern>)...] [--start-after=<marker>]
[ --stdin | (<pattern>...)]
+git refs exists <ref>
DESCRIPTION
-----------
@@ -38,6 +39,12 @@ list::
formatting, and sorting. This subcommand is an alias for
linkgit:git-for-each-ref[1] and offers identical functionality.
+exists::
+ Check whether the given reference exists. Returns an exit code of 0 if
+ it does, 2 if it is missing, and 1 in case looking up the reference
+ failed with an error other than the reference being missing. This does
+ not verify whether the reference resolves to an actual object.
+
OPTIONS
-------
diff --git a/builtin/refs.c b/builtin/refs.c
index 76224feba4..617d8ab138 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -7,6 +7,7 @@
#include "strbuf.h"
#include "worktree.h"
#include "for-each-ref.h"
+#include "refs/refs-internal.h"
#define REFS_MIGRATE_USAGE \
N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]")
@@ -14,6 +15,9 @@
#define REFS_VERIFY_USAGE \
N_("git refs verify [--strict] [--verbose]")
+#define REFS_EXISTS_USAGE \
+ N_("git refs exists <ref>")
+
static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
struct repository *repo UNUSED)
{
@@ -113,6 +117,48 @@ static int cmd_refs_list(int argc, const char **argv, const char *prefix,
return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage);
}
+static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
+ struct repository *repo UNUSED)
+{
+ struct strbuf unused_referent = STRBUF_INIT;
+ struct object_id unused_oid;
+ unsigned int unused_type;
+ int failure_errno = 0;
+ const char *ref;
+
+ const char * const exists_usage[] = {
+ REFS_EXISTS_USAGE,
+ NULL,
+ };
+ struct option options[] = {
+ OPT_END(),
+ };
+
+ argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
+ if (!argc)
+ die("'git refs exists' requires a reference");
+
+ ref = *argv++;
+ if (*argv)
+ die("'git refs exists' requires exactly one reference");
+
+ if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
+ &unused_oid, &unused_referent, &unused_type,
+ &failure_errno)) {
+ if (failure_errno == ENOENT || failure_errno == EISDIR) {
+ error(_("reference does not exist"));
+ return 2;
+ } else {
+ errno = failure_errno;
+ error_errno(_("failed to look up reference"));
+ return 1;
+ }
+ }
+
+ strbuf_release(&unused_referent);
+ return 0;
+}
+
int cmd_refs(int argc,
const char **argv,
const char *prefix,
@@ -122,6 +168,7 @@ int cmd_refs(int argc,
REFS_MIGRATE_USAGE,
REFS_VERIFY_USAGE,
"git refs list " COMMON_USAGE_FOR_EACH_REF,
+ REFS_EXISTS_USAGE,
NULL,
};
parse_opt_subcommand_fn *fn = NULL;
@@ -129,6 +176,7 @@ int cmd_refs(int argc,
OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify),
OPT_SUBCOMMAND("list", &fn, cmd_refs_list),
+ OPT_SUBCOMMAND("exists", &fn, cmd_refs_exists),
OPT_END(),
};
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand
2025-08-21 8:52 ` [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand Meet Soni
@ 2025-08-21 10:21 ` Patrick Steinhardt
0 siblings, 0 replies; 23+ messages in thread
From: Patrick Steinhardt @ 2025-08-21 10:21 UTC (permalink / raw)
To: Meet Soni; +Cc: git, shejialuo
On Thu, Aug 21, 2025 at 02:22:45PM +0530, Meet Soni wrote:
> 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.
I agree with this decision. It doesn't really feel worth it to share
code for such trivial functionality.
> diff --git a/builtin/refs.c b/builtin/refs.c
> index 76224feba4..617d8ab138 100644
> --- a/builtin/refs.c
> +++ b/builtin/refs.c
> @@ -113,6 +117,48 @@ static int cmd_refs_list(int argc, const char **argv, const char *prefix,
> return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage);
> }
>
> +static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
> + struct repository *repo UNUSED)
> +{
> + struct strbuf unused_referent = STRBUF_INIT;
> + struct object_id unused_oid;
> + unsigned int unused_type;
> + int failure_errno = 0;
> + const char *ref;
> +
Let's drop this empty newline.
> + const char * const exists_usage[] = {
> + REFS_EXISTS_USAGE,
> + NULL,
> + };
> + struct option options[] = {
> + OPT_END(),
> + };
> +
> + argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
> + if (!argc)
> + die("'git refs exists' requires a reference");
> +
> + ref = *argv++;
> + if (*argv)
> + die("'git refs exists' requires exactly one reference");
We can combine these two error messages to just say `if (argc != 1)`.
Also, the strings should be marked for translation.
> + if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
> + &unused_oid, &unused_referent, &unused_type,
> + &failure_errno)) {
> + if (failure_errno == ENOENT || failure_errno == EISDIR) {
> + error(_("reference does not exist"));
> + return 2;
> + } else {
> + errno = failure_errno;
> + error_errno(_("failed to look up reference"));
> + return 1;
I'd personally prefer to se a common exit path and use `goto` so that
one doesn't have to worry about whether or not the `struct strbuf` needs
to be free'd in error cases. But I'll leave it up to you to decide
whether you want to do this change.
Patrick
^ permalink raw reply [flat|nested] 23+ messages in thread
* [GSoC][PATCH 2/2] t: add test for git refs exists subcommand
2025-08-21 8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
2025-08-21 8:52 ` [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand Meet Soni
@ 2025-08-21 8:52 ` Meet Soni
2025-08-21 10:21 ` Patrick Steinhardt
2025-08-21 10:21 ` [GSoC][PATCH 0/2] Add " Patrick Steinhardt
` (2 subsequent siblings)
4 siblings, 1 reply; 23+ messages in thread
From: Meet Soni @ 2025-08-21 8:52 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, Meet Soni
The new `git refs exists` subcommand must have identical behavior to its
predecessor, `git show-ref --exists`. To avoid duplicating the entire
test suite, refactor the existing tests into a shareable helper script.
Extract the tests for the `--exists` flag from `t1403-show-ref.sh` into
a new `show-ref-exists-tests.sh` helper. The command under test is
parameterized using the `$git_show_ref_exists` variable.
Source new helper to both `t1403-show-ref.sh` and the new test file,
`t1462-refs-exists.sh`, ensuring both commands are verified against the
same comprehensive test suite.
Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
t/meson.build | 3 +-
t/show-ref-exists-tests.sh | 66 ++++++++++++++++++++++++++++++++++++++
t/t1403-show-ref.sh | 66 +-------------------------------------
t/t1462-refs-exists.sh | 22 +++++++++++++
4 files changed, 91 insertions(+), 66 deletions(-)
create mode 100644 t/show-ref-exists-tests.sh
create mode 100755 t/t1462-refs-exists.sh
diff --git a/t/meson.build b/t/meson.build
index baeeba2ce6..eed812a9b9 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -211,6 +211,7 @@ integration_tests = [
't1451-fsck-buffer.sh',
't1460-refs-migrate.sh',
't1461-refs-list.sh',
+ 't1462-refs-exists.sh',
't1500-rev-parse.sh',
't1501-work-tree.sh',
't1502-rev-parse-parseopt.sh',
@@ -1219,4 +1220,4 @@ if perl.found() and time.found()
timeout: 0,
)
endforeach
-endif
\ No newline at end of file
+endif
diff --git a/t/show-ref-exists-tests.sh b/t/show-ref-exists-tests.sh
new file mode 100644
index 0000000000..23b941d386
--- /dev/null
+++ b/t/show-ref-exists-tests.sh
@@ -0,0 +1,66 @@
+git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
+
+test_expect_success '--exists with existing reference' '
+ ${git_show_ref_exists} refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+ test_expect_code 2 ${git_show_ref_exists} refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+ test_expect_code 2 ${git_show_ref_exists} $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+ grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+ ${git_show_ref_exists} HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+ test_when_finished "git update-ref -d refs/heads/bad...name" &&
+ new_oid=$(git rev-parse HEAD) &&
+ test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+ test_when_finished "git symbolic-ref -d refs/symref" &&
+ git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+ ${git_show_ref_exists} refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+ test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+ git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+ ${git_show_ref_exists} refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+ test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+ tree_oid=$(git rev-parse HEAD^{tree}) &&
+ test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+ cat >expect <<-EOF &&
+ error: reference does not exist
+ EOF
+ test_expect_code 2 ${git_show_ref_exists} refs/heads 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+ test_expect_code 2 ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+ test_when_finished "rm .git/FETCH_HEAD" &&
+ git rev-parse HEAD >.git/FETCH_HEAD &&
+ ${git_show_ref_exists} FETCH_HEAD
+'
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
index 9da3650e91..dbae82384b 100755
--- a/t/t1403-show-ref.sh
+++ b/t/t1403-show-ref.sh
@@ -228,69 +228,5 @@ test_expect_success 'show-ref sub-modes are mutually exclusive' '
grep "cannot be used together" err
'
-test_expect_success '--exists with existing reference' '
- git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
- test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
- test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
- grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
- git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
- test_when_finished "git update-ref -d refs/heads/bad...name" &&
- new_oid=$(git rev-parse HEAD) &&
- test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
- git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
- test_when_finished "git symbolic-ref -d refs/symref" &&
- git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
- git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
- test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
- git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
- git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
- test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
- tree_oid=$(git rev-parse HEAD^{tree}) &&
- test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
- cat >expect <<-EOF &&
- error: reference does not exist
- EOF
- test_expect_code 2 git show-ref --exists refs/heads 2>err &&
- test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
- test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
- test_when_finished "rm .git/FETCH_HEAD" &&
- git rev-parse HEAD >.git/FETCH_HEAD &&
- git show-ref --exists FETCH_HEAD
-'
-
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
test_done
diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
new file mode 100755
index 0000000000..c00d76cc9e
--- /dev/null
+++ b/t/t1462-refs-exists.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description='refs exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+git_show_ref_exists='git refs exists'
+
+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_DIRECTORY"/show-ref-exists-tests.sh
+
+test_done
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [GSoC][PATCH 2/2] t: add test for git refs exists subcommand
2025-08-21 8:52 ` [GSoC][PATCH 2/2] t: add test for git refs exists subcommand Meet Soni
@ 2025-08-21 10:21 ` Patrick Steinhardt
2025-08-22 4:59 ` Meet Soni
0 siblings, 1 reply; 23+ messages in thread
From: Patrick Steinhardt @ 2025-08-21 10:21 UTC (permalink / raw)
To: Meet Soni; +Cc: git, shejialuo
On Thu, Aug 21, 2025 at 02:22:46PM +0530, Meet Soni wrote:
> The new `git refs exists` subcommand must have identical behavior to its
> predecessor, `git show-ref --exists`. To avoid duplicating the entire
> test suite, refactor the existing tests into a shareable helper script.
>
> Extract the tests for the `--exists` flag from `t1403-show-ref.sh` into
> a new `show-ref-exists-tests.sh` helper. The command under test is
> parameterized using the `$git_show_ref_exists` variable.
>
> Source new helper to both `t1403-show-ref.sh` and the new test file,
s/new/this/, otherwise this reads grammatically wrong to me.
> test_done
> diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
> new file mode 100755
> index 0000000000..c00d76cc9e
> --- /dev/null
> +++ b/t/t1462-refs-exists.sh
> @@ -0,0 +1,22 @@
> +#!/bin/sh
> +
> +test_description='refs exists'
> +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
> +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> +
> +. ./test-lib.sh
> +
> +git_show_ref_exists='git refs exists'
> +
> +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
> +'
It's a bit weird that this setup needs to be replicated. I guess it
comes from the fact that t1403 also has a bunch of other tests for
git-show-ref(1) that are irrelevant to existence checks.
How about we instead split out the existence-checks in t1403 into a
separate test suite first and then pull out the whole logic from it in a
subsequent commit so that we can also share the setup?
Patrick
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [GSoC][PATCH 2/2] t: add test for git refs exists subcommand
2025-08-21 10:21 ` Patrick Steinhardt
@ 2025-08-22 4:59 ` Meet Soni
0 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-22 4:59 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, shejialuo
On Thu, 21 Aug 2025 at 15:51, Patrick Steinhardt <ps@pks.im> wrote:
>
> On Thu, Aug 21, 2025 at 02:22:46PM +0530, Meet Soni wrote:
> > The new `git refs exists` subcommand must have identical behavior to its
> > predecessor, `git show-ref --exists`. To avoid duplicating the entire
> > test suite, refactor the existing tests into a shareable helper script.
> >
> > Extract the tests for the `--exists` flag from `t1403-show-ref.sh` into
> > a new `show-ref-exists-tests.sh` helper. The command under test is
> > parameterized using the `$git_show_ref_exists` variable.
> >
> > Source new helper to both `t1403-show-ref.sh` and the new test file,
>
> s/new/this/, otherwise this reads grammatically wrong to me.
>
> > test_done
> > diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
> > new file mode 100755
> > index 0000000000..c00d76cc9e
> > --- /dev/null
> > +++ b/t/t1462-refs-exists.sh
> > @@ -0,0 +1,22 @@
> > +#!/bin/sh
> > +
> > +test_description='refs exists'
> > +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
> > +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> > +
> > +. ./test-lib.sh
> > +
> > +git_show_ref_exists='git refs exists'
> > +
> > +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
> > +'
>
> It's a bit weird that this setup needs to be replicated. I guess it
> comes from the fact that t1403 also has a bunch of other tests for
> git-show-ref(1) that are irrelevant to existence checks.
>
> How about we instead split out the existence-checks in t1403 into a
> separate test suite first and then pull out the whole logic from it in a
> subsequent commit so that we can also share the setup?
>
Thanks for the review. You're right, splitting the test commit into two is
cleaner. I'll make that change and send out a v2 shortly.
> Patrick
Thanks,
Meet.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [GSoC][PATCH 0/2] Add refs exists subcommand
2025-08-21 8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
2025-08-21 8:52 ` [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand Meet Soni
2025-08-21 8:52 ` [GSoC][PATCH 2/2] t: add test for git refs exists subcommand Meet Soni
@ 2025-08-21 10:21 ` Patrick Steinhardt
2025-08-21 16:01 ` Junio C Hamano
2025-08-23 6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
4 siblings, 0 replies; 23+ messages in thread
From: Patrick Steinhardt @ 2025-08-21 10:21 UTC (permalink / raw)
To: Meet Soni; +Cc: git, shejialuo
On Thu, Aug 21, 2025 at 02:22:44PM +0530, Meet Soni wrote:
> This series introduces `git refs exists` as a modern replacement for
> `git show-ref --exists`, continuing the effort to consolidate commands
> under the `git refs` namespace.
>
> The two patches are as follows:
>
> 1. The first implements the `exists` subcommand. The small amount of
> logic is duplicated from `show-ref` to avoid unnecessary abstraction.
>
> 2. The second adds tests by refactoring the `show-ref --exists` tests
> into a shareable helper, ensuring both commands are tested for
> identical behavior.
>
> Meet Soni (2):
> builtin/refs: add 'exists' subcommand
> t: add test for git refs exists subcommand
>
> Documentation/git-refs.adoc | 7 ++++
> builtin/refs.c | 48 +++++++++++++++++++++++++++
> t/meson.build | 3 +-
> t/show-ref-exists-tests.sh | 66 +++++++++++++++++++++++++++++++++++++
> t/t1403-show-ref.sh | 66 +------------------------------------
> t/t1462-refs-exists.sh | 22 +++++++++++++
> 6 files changed, 146 insertions(+), 66 deletions(-)
> create mode 100644 t/show-ref-exists-tests.sh
> create mode 100755 t/t1462-refs-exists.sh
>
>
> base-commit: c44beea485f0f2feaf460e2ac87fdd5608d63cf0
> prerequisite-patch-id: 235cc677f372e9571dade4313f8cfed4eab65f7f
> prerequisite-patch-id: d0cb9932dcf233b3a26e413514375191ede93c73
> prerequisite-patch-id: 9cb324ad34a786af110e9d3d47e4ca8aec240971
> prerequisite-patch-id: 0d74ac673c285c334adcc19b9ca2d4919563e804
> prerequisite-patch-id: 04c6d989f4130a063bc80f7dc9ce9a16d3459665
> prerequisite-patch-id: 95dafb2692da02d79c59cc2742258a915da25e88
> prerequisite-patch-id: f14c9a47038305eb3cfe8e9b649fa64065ada9cd
...
Feels like something went wrong here :)
What the cover letter doesn't mention explicitly is what the base of
this topic is. I assume it's probably v2.51.0 with ms/refs-list merged
into it?
Patrick
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [GSoC][PATCH 0/2] Add refs exists subcommand
2025-08-21 8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
` (2 preceding siblings ...)
2025-08-21 10:21 ` [GSoC][PATCH 0/2] Add " Patrick Steinhardt
@ 2025-08-21 16:01 ` Junio C Hamano
2025-08-22 4:27 ` Meet Soni
2025-08-23 6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
4 siblings, 1 reply; 23+ messages in thread
From: Junio C Hamano @ 2025-08-21 16:01 UTC (permalink / raw)
To: Meet Soni; +Cc: git, ps, shejialuo
Meet Soni <meetsoni3017@gmail.com> writes:
> base-commit: c44beea485f0f2feaf460e2ac87fdd5608d63cf0
> prerequisite-patch-id: 235cc677f372e9571dade4313f8cfed4eab65f7f
> ... (~100 lines of crap omitted)
> prerequisite-patch-id: 553adfe23223a427db3f93e23dfb603c55cc5aae
Please don't force others to go hunt to find so many patches before
being able to even recreate what you based your changes on.
Learn the way how it is usually done by looking at:
https://lore.kernel.org/git/20250106-b4-pks-object-file-racy-collision-check-v2-0-8b3984ecbb18@pks.im/
Basically you would want to say
This is built on top of <commit> with <topic*> merged into it.
where <commit> is a commit on 'master' (or 'maint' or an even older
maintenance track, if the topic is about fixing a bug in a released
version of Git), and <topic*> are topic branches in flight that can
be merged to the same integration target ('master', or an older
maintenance tracks you chose <commit> from). And keep the number of
<topic*> to an absolute minimum in order for your changes to work.
Thanks.
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [GSoC][PATCH 0/2] Add refs exists subcommand
2025-08-21 16:01 ` Junio C Hamano
@ 2025-08-22 4:27 ` Meet Soni
0 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-22 4:27 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, ps, shejialuo
On Thu, 21 Aug 2025 at 21:31, Junio C Hamano <gitster@pobox.com> wrote:
>
> Meet Soni <meetsoni3017@gmail.com> writes:
>
> > base-commit: c44beea485f0f2feaf460e2ac87fdd5608d63cf0
> > prerequisite-patch-id: 235cc677f372e9571dade4313f8cfed4eab65f7f
> > ... (~100 lines of crap omitted)
> > prerequisite-patch-id: 553adfe23223a427db3f93e23dfb603c55cc5aae
>
> Please don't force others to go hunt to find so many patches before
> being able to even recreate what you based your changes on.
>
I was a bit confused between cherry-picking and basing my series on next, and I
ended up doing the latter. I’ll fix it.
> Learn the way how it is usually done by looking at:
>
> https://lore.kernel.org/git/20250106-b4-pks-object-file-racy-collision-check-v2-0-8b3984ecbb18@pks.im/
>
> Basically you would want to say
>
> This is built on top of <commit> with <topic*> merged into it.
>
> where <commit> is a commit on 'master' (or 'maint' or an even older
> maintenance track, if the topic is about fixing a bug in a released
> version of Git), and <topic*> are topic branches in flight that can
> be merged to the same integration target ('master', or an older
> maintenance tracks you chose <commit> from). And keep the number of
> <topic*> to an absolute minimum in order for your changes to work.
>
> Thanks.
Thanks.
^ permalink raw reply [flat|nested] 23+ messages in thread
* [GSoC][PATCH v2 0/4] Add refs exists subcommand
2025-08-21 8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
` (3 preceding siblings ...)
2025-08-21 16:01 ` Junio C Hamano
@ 2025-08-23 6:00 ` Meet Soni
2025-08-23 6:00 ` [GSoC][PATCH v2 1/4] builtin/refs: add 'exists' subcommand Meet Soni
` (5 more replies)
4 siblings, 6 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-23 6:00 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, gitster, Meet Soni
This series introduces `git refs exists` as a modern replacement for
`git show-ref --exists`, continuing the effort to consolidate commands
under the `git refs` namespace.
Changes in v2:
- v1 was based on the "next" branch as this series required a couple
of commits merged in it, but as those commits are now completely
merged into the master branch, I've rebased the v2 onto master
branch.
- split the test commit to make the setup shareable.
Meet Soni (4):
builtin/refs: add 'exists' subcommand
t1403: split 'show-ref --exists' tests into a separate file
t1422: refactor tests to be shareable
t: add test for git refs exists subcommand
Documentation/git-refs.adoc | 7 ++++
builtin/refs.c | 48 +++++++++++++++++++++++
t/meson.build | 4 +-
t/show-ref-exists-tests.sh | 76 +++++++++++++++++++++++++++++++++++++
t/t1403-show-ref.sh | 65 -------------------------------
t/t1422-show-ref-exists.sh | 9 +++++
t/t1462-refs-exists.sh | 10 +++++
7 files changed, 153 insertions(+), 66 deletions(-)
create mode 100644 t/show-ref-exists-tests.sh
create mode 100755 t/t1422-show-ref-exists.sh
create mode 100755 t/t1462-refs-exists.sh
Range-diff against v1:
1: 3fe68ee250 < -: ---------- bloom: optimize multiple pathspec items in revision
2: 36554bf51a < -: ---------- commit: convert pop_most_recent_commit() to prio_queue
3: 304f06e0c0 < -: ---------- commit: use prio_queue_replace() in pop_most_recent_commit(),MIME-Version: 1.0
4: e436bc94f3 < -: ---------- prio-queue: add prio_queue_replace()
5: c7a5d9a13c < -: ---------- Revert "Merge branch 'rs/pop-recent-commit-with-prio-queue' into next"
6: d66d5bfc41 < -: ---------- archive: flush deflate stream until Z_STREAM_END
7: 5297b08916 < -: ---------- Revert "Merge branch 'jt/archive-zip-deflate-fix' into next"
8: 19623eb97e < -: ---------- doc: factor out common option
9: 69c207dc45 < -: ---------- builtin/for-each-ref: align usage string with the man page
10: 6eeb1c070a < -: ---------- builtin/for-each-ref: factor out core logic into a helper
11: eecccfe98b < -: ---------- builtin/refs: add list subcommand
12: aa91c5c570 < -: ---------- t6300: refactor tests to be shareable
13: fed66d91c0 < -: ---------- t: add test for git refs list subcommand
14: 9bb4abe6cd < -: ---------- combine-diff: zero memory used for callback filepairs
15: 2a43e0e550 < -: ---------- within_depth: fix return for empty path
16: a1dfa5448d < -: ---------- diff: teach tree-diff a max-depth parameter
17: b55e6d36eb < -: ---------- diff: ensure consistent diff behavior with ignore options
18: fe54b9ef02 < -: ---------- parse-options: refactor flags for usage_with_options_internal
19: 129b3632f3 < -: ---------- builtin: also setup gently for --help-all
20: e1d3d61a45 < -: ---------- diff: --no-index should ignore the worktree
21: 621ce9c1c6 < -: ---------- git-jump: make `diff` work with filenames containing spaces
22: 9a49aef8dc < -: ---------- environment: remove the global variable 'merge_log_config'
23: 22d421fed9 < -: ---------- builtin/fmt-merge-msg: stop depending on 'the_repository'
24: f81a574f59 < -: ---------- doc: test linkgit macros for well-formedness
25: 63d33eb7f6 < -: ---------- doc: check well-formedness of delimited sections
26: ed26022094 < -: ---------- doc: check for absence of multiple terms in each entry of desc list
27: 03a353bb97 < -: ---------- doc: check for absence of the form --[no-]parameter
28: 93203872d7 < -: ---------- doc:git-for-each-ref: fix styling and typos
29: 84f3d6e11e < -: ---------- doc lint: check that synopsis manpages have synopsis inlines
30: 741f36c7d9 < -: ---------- docs: remove stray bracket from git-clone synopsis
31: 83d64df8d5 < -: ---------- t7005: use modern test style
32: a9c4141abb < -: ---------- t7005: stop abusing --exec-path
33: a60203a015 < -: ---------- t7005: sanitize test environment for subsequent tests
34: 7d4a5fef7d < -: ---------- count-objects: document count-objects pack
35: 3481cb7dfd < -: ---------- commit-graph: stop using `the_hash_algo` via macros
36: e45402bb19 < -: ---------- commit-graph: store the hash algorithm instead of its length
37: f1141b4391 < -: ---------- commit-graph: refactor `parse_commit_graph()` to take a repository
38: 89cc9b9adf < -: ---------- commit-graph: stop using `the_hash_algo`
39: ddacfc7466 < -: ---------- commit-graph: stop using `the_repository`
40: 7be9e410b2 < -: ---------- commit-graph: stop passing in redundant repository
41: cab69db9c3 < -: ---------- t/t1517: mark tests that fail with GIT_TEST_INSTALLED
42: ab94bb8000 < -: ---------- repo: declare the repo command
43: 9adb8a7fd1 < -: ---------- repo: add the field references.format
44: acf2669b54 < -: ---------- repo: add the field layout.bare
45: e52cd654c9 < -: ---------- repo: add the field layout.shallow
46: a81224d128 < -: ---------- repo: add the --format flag
47: d59b2a3793 < -: ---------- Revert "Merge branch 'ad/t1517-short-help-tests-fix' into next"
48: 5643b59dea ! 1: d1fa4e927e builtin/refs: add 'exists' subcommand
@@ Commit message
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
+ introduce `exists` subcommand. This command provides the same
functionality and exit-code behavior as `git show-ref --exists`, serving
as its modern replacement.
@@ Commit message
`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)`
+ Documentation for this subcommand is also added to the `git-refs(1)`
man page.
Mentored-by: Patrick Steinhardt <ps@pks.im>
@@ Documentation/git-refs.adoc
@@ Documentation/git-refs.adoc: git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
[--contains[=<object>]] [--no-contains[=<object>]]
[(--exclude=<pattern>)...] [--start-after=<marker>]
- [ --stdin | (<pattern>...)]
+ [ --stdin | <pattern>... ]
+git refs exists <ref>
DESCRIPTION
@@ builtin/refs.c: static int cmd_refs_list(int argc, const char **argv, const char
+ unsigned int unused_type;
+ int failure_errno = 0;
+ const char *ref;
-+
++ int ret = 0;
+ const char * const exists_usage[] = {
+ REFS_EXISTS_USAGE,
+ NULL,
@@ builtin/refs.c: static int cmd_refs_list(int argc, const char **argv, const char
+ };
+
+ argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
-+ if (!argc)
-+ die("'git refs exists' requires a reference");
++ if (argc != 1)
++ die(_("'git refs exists' requires a reference"));
+
+ ref = *argv++;
-+ if (*argv)
-+ die("'git refs exists' requires exactly one reference");
-+
+ if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
+ &unused_oid, &unused_referent, &unused_type,
+ &failure_errno)) {
+ if (failure_errno == ENOENT || failure_errno == EISDIR) {
+ error(_("reference does not exist"));
-+ return 2;
++ ret = 2;
+ } else {
+ errno = failure_errno;
+ error_errno(_("failed to look up reference"));
-+ return 1;
++ ret = 1;
+ }
++
++ goto out;
+ }
+
++out:
+ strbuf_release(&unused_referent);
-+ return 0;
++ return ret;
+}
+
int cmd_refs(int argc,
-: ---------- > 2: f1dfafe6c9 t1403: split 'show-ref --exists' tests into a separate file
49: e14bd088bd ! 3: a2a65c428c t: add test for git refs exists subcommand
@@ Metadata
Author: Meet Soni <meetsoni3017@gmail.com>
## Commit message ##
- t: add test for git refs exists subcommand
+ t1422: refactor tests to be shareable
- The new `git refs exists` subcommand must have identical behavior to its
- predecessor, `git show-ref --exists`. To avoid duplicating the entire
- test suite, refactor the existing tests into a shareable helper script.
+ In preparation for adding tests for the `git refs exists` command,
+ refactor the existing t1422 test suite to make its logic shareable.
- Extract the tests for the `--exists` flag from `t1403-show-ref.sh` into
- a new `show-ref-exists-tests.sh` helper. The command under test is
- parameterized using the `$git_show_ref_exists` variable.
+ Move the core test logic from `t1422-show-ref-exists.sh` to
+ `show-ref-exists-tests.sh` file. Inside this script, replace hardcoded
+ calls to "git show-ref --exists" with the `$git_show_ref_exists`
+ variable.
- Source new helper to both `t1403-show-ref.sh` and the new test file,
- `t1462-refs-exists.sh`, ensuring both commands are verified against the
- same comprehensive test suite.
+ The original `t1422-show-ref-exists.sh` script now becomes a simple
+ "driver". It is responsible for setting the default value of the
+ variable and then sourcing the test library.
+
+ This structure follows an established pattern for sharing tests and
+ prepares the test suite for the `refs exists` tests to be added in a
+ subsequent commit.
Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
- ## t/meson.build ##
-@@ t/meson.build: integration_tests = [
- 't1451-fsck-buffer.sh',
- 't1460-refs-migrate.sh',
- 't1461-refs-list.sh',
-+ 't1462-refs-exists.sh',
- 't1500-rev-parse.sh',
- 't1501-work-tree.sh',
- 't1502-rev-parse-parseopt.sh',
-@@ t/meson.build: if perl.found() and time.found()
- timeout: 0,
- )
- endforeach
--endif
- \ No newline at end of file
-+endif
-
## t/show-ref-exists-tests.sh (new) ##
@@
+git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
++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 '--exists with existing reference' '
+ ${git_show_ref_exists} refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
@@ t/show-ref-exists-tests.sh (new)
+ git rev-parse HEAD >.git/FETCH_HEAD &&
+ ${git_show_ref_exists} FETCH_HEAD
+'
++
++test_done
- ## t/t1403-show-ref.sh ##
-@@ t/t1403-show-ref.sh: test_expect_success 'show-ref sub-modes are mutually exclusive' '
- grep "cannot be used together" err
- '
+ ## t/t1422-show-ref-exists.sh (mode change 100644 => 100755) ##
+@@ t/t1422-show-ref-exists.sh: 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 '--exists with existing reference' '
- git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
@@ t/t1403-show-ref.sh: test_expect_success 'show-ref sub-modes are mutually exclus
- git show-ref --exists FETCH_HEAD
-'
-
+-test_done
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
- test_done
-
- ## t/t1462-refs-exists.sh (new) ##
-@@
-+#!/bin/sh
-+
-+test_description='refs exists'
-+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
-+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-+
-+. ./test-lib.sh
-+
-+git_show_ref_exists='git refs exists'
-+
-+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_DIRECTORY"/show-ref-exists-tests.sh
-+
-+test_done
-: ---------- > 4: e92da499b5 t: add test for git refs exists subcommand
--
2.34.1
^ permalink raw reply [flat|nested] 23+ messages in thread* [GSoC][PATCH v2 1/4] builtin/refs: add 'exists' subcommand
2025-08-23 6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
@ 2025-08-23 6:00 ` Meet Soni
2025-08-23 6:00 ` [GSoC][PATCH v2 2/4] t1403: split 'show-ref --exists' tests into a separate file Meet Soni
` (4 subsequent siblings)
5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-23 6:00 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, gitster, Meet Soni
As part of the ongoing effort to consolidate reference handling,
introduce `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 this subcommand is also added to the `git-refs(1)`
man page.
Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
Documentation/git-refs.adoc | 7 ++++++
builtin/refs.c | 48 +++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
index e608980711..5d2032b318 100644
--- a/Documentation/git-refs.adoc
+++ b/Documentation/git-refs.adoc
@@ -18,6 +18,7 @@ git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
[--contains[=<object>]] [--no-contains[=<object>]]
[(--exclude=<pattern>)...] [--start-after=<marker>]
[ --stdin | <pattern>... ]
+git refs exists <ref>
DESCRIPTION
-----------
@@ -38,6 +39,12 @@ list::
formatting, and sorting. This subcommand is an alias for
linkgit:git-for-each-ref[1] and offers identical functionality.
+exists::
+ Check whether the given reference exists. Returns an exit code of 0 if
+ it does, 2 if it is missing, and 1 in case looking up the reference
+ failed with an error other than the reference being missing. This does
+ not verify whether the reference resolves to an actual object.
+
OPTIONS
-------
diff --git a/builtin/refs.c b/builtin/refs.c
index 76224feba4..91548783b7 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -7,6 +7,7 @@
#include "strbuf.h"
#include "worktree.h"
#include "for-each-ref.h"
+#include "refs/refs-internal.h"
#define REFS_MIGRATE_USAGE \
N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]")
@@ -14,6 +15,9 @@
#define REFS_VERIFY_USAGE \
N_("git refs verify [--strict] [--verbose]")
+#define REFS_EXISTS_USAGE \
+ N_("git refs exists <ref>")
+
static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
struct repository *repo UNUSED)
{
@@ -113,6 +117,48 @@ static int cmd_refs_list(int argc, const char **argv, const char *prefix,
return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage);
}
+static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
+ struct repository *repo UNUSED)
+{
+ struct strbuf unused_referent = STRBUF_INIT;
+ struct object_id unused_oid;
+ unsigned int unused_type;
+ int failure_errno = 0;
+ const char *ref;
+ int ret = 0;
+ const char * const exists_usage[] = {
+ REFS_EXISTS_USAGE,
+ NULL,
+ };
+ struct option options[] = {
+ OPT_END(),
+ };
+
+ argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
+ if (argc != 1)
+ die(_("'git refs exists' requires a reference"));
+
+ ref = *argv++;
+ if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
+ &unused_oid, &unused_referent, &unused_type,
+ &failure_errno)) {
+ if (failure_errno == ENOENT || failure_errno == EISDIR) {
+ error(_("reference does not exist"));
+ ret = 2;
+ } else {
+ errno = failure_errno;
+ error_errno(_("failed to look up reference"));
+ ret = 1;
+ }
+
+ goto out;
+ }
+
+out:
+ strbuf_release(&unused_referent);
+ return ret;
+}
+
int cmd_refs(int argc,
const char **argv,
const char *prefix,
@@ -122,6 +168,7 @@ int cmd_refs(int argc,
REFS_MIGRATE_USAGE,
REFS_VERIFY_USAGE,
"git refs list " COMMON_USAGE_FOR_EACH_REF,
+ REFS_EXISTS_USAGE,
NULL,
};
parse_opt_subcommand_fn *fn = NULL;
@@ -129,6 +176,7 @@ int cmd_refs(int argc,
OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify),
OPT_SUBCOMMAND("list", &fn, cmd_refs_list),
+ OPT_SUBCOMMAND("exists", &fn, cmd_refs_exists),
OPT_END(),
};
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [GSoC][PATCH v2 2/4] t1403: split 'show-ref --exists' tests into a separate file
2025-08-23 6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
2025-08-23 6:00 ` [GSoC][PATCH v2 1/4] builtin/refs: add 'exists' subcommand Meet Soni
@ 2025-08-23 6:00 ` Meet Soni
2025-08-23 6:00 ` [GSoC][PATCH v2 3/4] t1422: refactor tests to be shareable Meet Soni
` (3 subsequent siblings)
5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-23 6:00 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, gitster, Meet Soni
The test file for git-show-ref(1), `t1403-show-ref.sh`, contains a group
of tests for the '--exists' flag. To improve organization and to prepare
for refactoring these tests to be shareable, move the '--exists' tests
and their corresponding setup logic into a self-contained test suite,
`t1422-show-ref-exists.sh`.
This is a pure code-movement refactoring with no change in test coverage
or behavior.
Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
t/meson.build | 3 +-
t/t1403-show-ref.sh | 65 -----------------------------
t/t1422-show-ref-exists.sh | 83 ++++++++++++++++++++++++++++++++++++++
3 files changed, 85 insertions(+), 66 deletions(-)
create mode 100644 t/t1422-show-ref-exists.sh
diff --git a/t/meson.build b/t/meson.build
index daf01fb5d0..4d6bc3d38e 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -205,6 +205,7 @@ integration_tests = [
't1419-exclude-refs.sh',
't1420-lost-found.sh',
't1421-reflog-write.sh',
+ 't1422-show-ref-exists.sh',
't1430-bad-ref-name.sh',
't1450-fsck.sh',
't1451-fsck-buffer.sh',
@@ -1216,4 +1217,4 @@ if perl.found() and time.found()
timeout: 0,
)
endforeach
-endif
\ No newline at end of file
+endif
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
index 9da3650e91..36c903ca19 100755
--- a/t/t1403-show-ref.sh
+++ b/t/t1403-show-ref.sh
@@ -228,69 +228,4 @@ test_expect_success 'show-ref sub-modes are mutually exclusive' '
grep "cannot be used together" err
'
-test_expect_success '--exists with existing reference' '
- git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
- test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
- test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
- grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
- git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
- test_when_finished "git update-ref -d refs/heads/bad...name" &&
- new_oid=$(git rev-parse HEAD) &&
- test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
- git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
- test_when_finished "git symbolic-ref -d refs/symref" &&
- git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
- git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
- test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
- git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
- git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
- test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
- tree_oid=$(git rev-parse HEAD^{tree}) &&
- test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
- cat >expect <<-EOF &&
- error: reference does not exist
- EOF
- test_expect_code 2 git show-ref --exists refs/heads 2>err &&
- test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
- test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
- test_when_finished "rm .git/FETCH_HEAD" &&
- git rev-parse HEAD >.git/FETCH_HEAD &&
- git show-ref --exists FETCH_HEAD
-'
-
test_done
diff --git a/t/t1422-show-ref-exists.sh b/t/t1422-show-ref-exists.sh
new file mode 100644
index 0000000000..0eccb2dce1
--- /dev/null
+++ b/t/t1422-show-ref-exists.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+test_description='show-ref --exists'
+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 '--exists with existing reference' '
+ git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+ test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+ test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+ grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+ git show-ref --exists HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+ test_when_finished "git update-ref -d refs/heads/bad...name" &&
+ new_oid=$(git rev-parse HEAD) &&
+ test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+ git show-ref --exists refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+ test_when_finished "git symbolic-ref -d refs/symref" &&
+ git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+ git show-ref --exists refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+ test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+ git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+ git show-ref --exists refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+ test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ git show-ref --exists refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+ tree_oid=$(git rev-parse HEAD^{tree}) &&
+ test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ git show-ref --exists refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+ cat >expect <<-EOF &&
+ error: reference does not exist
+ EOF
+ test_expect_code 2 git show-ref --exists refs/heads 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+ test_expect_code 2 git show-ref --exists FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+ test_when_finished "rm .git/FETCH_HEAD" &&
+ git rev-parse HEAD >.git/FETCH_HEAD &&
+ git show-ref --exists FETCH_HEAD
+'
+
+test_done
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [GSoC][PATCH v2 3/4] t1422: refactor tests to be shareable
2025-08-23 6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
2025-08-23 6:00 ` [GSoC][PATCH v2 1/4] builtin/refs: add 'exists' subcommand Meet Soni
2025-08-23 6:00 ` [GSoC][PATCH v2 2/4] t1403: split 'show-ref --exists' tests into a separate file Meet Soni
@ 2025-08-23 6:00 ` Meet Soni
2025-08-24 16:58 ` Patrick Steinhardt
2025-08-23 6:00 ` [GSoC][PATCH v2 4/4] t: add test for git refs exists subcommand Meet Soni
` (2 subsequent siblings)
5 siblings, 1 reply; 23+ messages in thread
From: Meet Soni @ 2025-08-23 6:00 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, gitster, Meet Soni
In preparation for adding tests for the `git refs exists` command,
refactor the existing t1422 test suite to make its logic shareable.
Move the core test logic from `t1422-show-ref-exists.sh` to
`show-ref-exists-tests.sh` file. Inside this script, replace hardcoded
calls to "git show-ref --exists" with the `$git_show_ref_exists`
variable.
The original `t1422-show-ref-exists.sh` script now becomes a simple
"driver". It is responsible for setting the default value of the
variable and then sourcing the test library.
This structure follows an established pattern for sharing tests and
prepares the test suite for the `refs exists` tests to be added in a
subsequent commit.
Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
t/show-ref-exists-tests.sh | 76 ++++++++++++++++++++++++++++++++++++++
t/t1422-show-ref-exists.sh | 76 +-------------------------------------
2 files changed, 77 insertions(+), 75 deletions(-)
create mode 100644 t/show-ref-exists-tests.sh
mode change 100644 => 100755 t/t1422-show-ref-exists.sh
diff --git a/t/show-ref-exists-tests.sh b/t/show-ref-exists-tests.sh
new file mode 100644
index 0000000000..2c29643573
--- /dev/null
+++ b/t/show-ref-exists-tests.sh
@@ -0,0 +1,76 @@
+git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
+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 '--exists with existing reference' '
+ ${git_show_ref_exists} refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+ test_expect_code 2 ${git_show_ref_exists} refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+ test_expect_code 2 ${git_show_ref_exists} $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+ grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+ ${git_show_ref_exists} HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+ test_when_finished "git update-ref -d refs/heads/bad...name" &&
+ new_oid=$(git rev-parse HEAD) &&
+ test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+ test_when_finished "git symbolic-ref -d refs/symref" &&
+ git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+ ${git_show_ref_exists} refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+ test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+ git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+ ${git_show_ref_exists} refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+ test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+ tree_oid=$(git rev-parse HEAD^{tree}) &&
+ test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+ cat >expect <<-EOF &&
+ error: reference does not exist
+ EOF
+ test_expect_code 2 ${git_show_ref_exists} refs/heads 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+ test_expect_code 2 ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+ test_when_finished "rm .git/FETCH_HEAD" &&
+ git rev-parse HEAD >.git/FETCH_HEAD &&
+ ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_done
diff --git a/t/t1422-show-ref-exists.sh b/t/t1422-show-ref-exists.sh
old mode 100644
new mode 100755
index 0eccb2dce1..fdca3f16c8
--- a/t/t1422-show-ref-exists.sh
+++ b/t/t1422-show-ref-exists.sh
@@ -6,78 +6,4 @@ 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 '--exists with existing reference' '
- git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
- test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
- test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
- grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
- git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
- test_when_finished "git update-ref -d refs/heads/bad...name" &&
- new_oid=$(git rev-parse HEAD) &&
- test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
- git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
- test_when_finished "git symbolic-ref -d refs/symref" &&
- git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
- git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
- test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
- git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
- git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
- test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
- tree_oid=$(git rev-parse HEAD^{tree}) &&
- test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
- cat >expect <<-EOF &&
- error: reference does not exist
- EOF
- test_expect_code 2 git show-ref --exists refs/heads 2>err &&
- test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
- test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
- test_when_finished "rm .git/FETCH_HEAD" &&
- git rev-parse HEAD >.git/FETCH_HEAD &&
- git show-ref --exists FETCH_HEAD
-'
-
-test_done
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [GSoC][PATCH v2 4/4] t: add test for git refs exists subcommand
2025-08-23 6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
` (2 preceding siblings ...)
2025-08-23 6:00 ` [GSoC][PATCH v2 3/4] t1422: refactor tests to be shareable Meet Soni
@ 2025-08-23 6:00 ` Meet Soni
2025-08-24 16:58 ` [GSoC][PATCH v2 0/4] Add " Patrick Steinhardt
2025-08-26 6:41 ` [GSoC][PATCH v3 " Meet Soni
5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-23 6:00 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, gitster, Meet Soni
Add a test script, `t/t1462-refs-exists.sh`, for the `git refs exists`
command.
This script acts as a simple driver, leveraging the shared test library
created in the preceding commit. It works by overriding the
`$git_show_ref_exists` variable to "git refs exists" and then sourcing the
shared library (`t/show-ref-exists-tests.sh`).
This approach ensures that `git refs exists` is tested against the
entire comprehensive test suite of `git show-ref --exists`, verifying
that it acts as a compatible drop-in replacement.
Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
t/meson.build | 1 +
t/t1462-refs-exists.sh | 10 ++++++++++
2 files changed, 11 insertions(+)
create mode 100755 t/t1462-refs-exists.sh
diff --git a/t/meson.build b/t/meson.build
index 4d6bc3d38e..93e9773ec8 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -211,6 +211,7 @@ integration_tests = [
't1451-fsck-buffer.sh',
't1460-refs-migrate.sh',
't1461-refs-list.sh',
+ 't1462-refs-exists.sh',
't1500-rev-parse.sh',
't1501-work-tree.sh',
't1502-rev-parse-parseopt.sh',
diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
new file mode 100755
index 0000000000..349453c4ca
--- /dev/null
+++ b/t/t1462-refs-exists.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+test_description='refs exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+git_show_ref_exists='git refs exists'
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [GSoC][PATCH v2 0/4] Add refs exists subcommand
2025-08-23 6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
` (3 preceding siblings ...)
2025-08-23 6:00 ` [GSoC][PATCH v2 4/4] t: add test for git refs exists subcommand Meet Soni
@ 2025-08-24 16:58 ` Patrick Steinhardt
2025-08-26 6:41 ` [GSoC][PATCH v3 " Meet Soni
5 siblings, 0 replies; 23+ messages in thread
From: Patrick Steinhardt @ 2025-08-24 16:58 UTC (permalink / raw)
To: Meet Soni; +Cc: git, shejialuo, gitster
On Sat, Aug 23, 2025 at 11:30:08AM +0530, Meet Soni wrote:
> This series introduces `git refs exists` as a modern replacement for
> `git show-ref --exists`, continuing the effort to consolidate commands
> under the `git refs` namespace.
>
> Changes in v2:
> - v1 was based on the "next" branch as this series required a couple
> of commits merged in it, but as those commits are now completely
> merged into the master branch, I've rebased the v2 onto master
> branch.
Good.
> - split the test commit to make the setup shareable.
Good, as well.
> @@ Commit message
> 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
> + introduce `exists` subcommand. This command provides the same
> functionality and exit-code behavior as `git show-ref --exists`, serving
> as its modern replacement.
This reads a bit funny now -- I think the previous version was
preferable.
Patrick
^ permalink raw reply [flat|nested] 23+ messages in thread* [GSoC][PATCH v3 0/4] Add refs exists subcommand
2025-08-23 6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
` (4 preceding siblings ...)
2025-08-24 16:58 ` [GSoC][PATCH v2 0/4] Add " Patrick Steinhardt
@ 2025-08-26 6:41 ` Meet Soni
2025-08-26 6:41 ` [GSoC][PATCH v3 1/4] builtin/refs: add 'exists' subcommand Meet Soni
` (5 more replies)
5 siblings, 6 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-26 6:41 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, gitster, Meet Soni
This series introduces `git refs exists` as a modern replacement for
`git show-ref --exists`, continuing the effort to consolidate commands
under the `git refs` namespace.
changes in v3:
- Reverted commit message.
- nit: added empty line.
Meet Soni (4):
builtin/refs: add 'exists' subcommand
t1403: split 'show-ref --exists' tests into a separate file
t1422: refactor tests to be shareable
t: add test for git refs exists subcommand
Documentation/git-refs.adoc | 7 ++++
builtin/refs.c | 48 +++++++++++++++++++++++
t/meson.build | 4 +-
t/show-ref-exists-tests.sh | 77 +++++++++++++++++++++++++++++++++++++
t/t1403-show-ref.sh | 65 -------------------------------
t/t1422-show-ref-exists.sh | 9 +++++
t/t1462-refs-exists.sh | 10 +++++
7 files changed, 154 insertions(+), 66 deletions(-)
create mode 100644 t/show-ref-exists-tests.sh
create mode 100755 t/t1422-show-ref-exists.sh
create mode 100755 t/t1462-refs-exists.sh
Range-diff against v2:
1: 19623eb97e < -: ---------- doc: factor out common option
2: 69c207dc45 < -: ---------- builtin/for-each-ref: align usage string with the man page
3: 6eeb1c070a < -: ---------- builtin/for-each-ref: factor out core logic into a helper
4: eecccfe98b < -: ---------- builtin/refs: add list subcommand
5: aa91c5c570 < -: ---------- t6300: refactor tests to be shareable
6: fed66d91c0 < -: ---------- t: add test for git refs list subcommand
7: b55e6d36eb < -: ---------- diff: ensure consistent diff behavior with ignore options
8: e1d3d61a45 < -: ---------- diff: --no-index should ignore the worktree
9: 621ce9c1c6 < -: ---------- git-jump: make `diff` work with filenames containing spaces
10: 9a49aef8dc < -: ---------- environment: remove the global variable 'merge_log_config'
11: 22d421fed9 < -: ---------- builtin/fmt-merge-msg: stop depending on 'the_repository'
12: 741f36c7d9 < -: ---------- docs: remove stray bracket from git-clone synopsis
13: 1fa68948c3 < -: ---------- The second batch
14: d1fa4e927e ! 1: 0c9349fa74 builtin/refs: add 'exists' subcommand
@@ Commit message
builtin/refs: add 'exists' subcommand
As part of the ongoing effort to consolidate reference handling,
- introduce `exists` subcommand. This command provides the same
+ 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.
@@ Commit message
`git refs list`, where sharing the larger implementation of
`for-each-ref` was necessary.
- Documentation for this subcommand is also added to the `git-refs(1)`
+ Documentation for the new subcommand is also added to the `git-refs(1)`
man page.
Mentored-by: Patrick Steinhardt <ps@pks.im>
15: f1dfafe6c9 = 2: d32067af55 t1403: split 'show-ref --exists' tests into a separate file
16: a2a65c428c ! 3: fb7223ad07 t1422: refactor tests to be shareable
@@ Commit message
## t/show-ref-exists-tests.sh (new) ##
@@
+git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
++
+test_expect_success setup '
+ test_commit --annotate A &&
+ git checkout -b side &&
17: e92da499b5 = 4: 75b5ee4ede t: add test for git refs exists subcommand
--
2.34.1
^ permalink raw reply [flat|nested] 23+ messages in thread* [GSoC][PATCH v3 1/4] builtin/refs: add 'exists' subcommand
2025-08-26 6:41 ` [GSoC][PATCH v3 " Meet Soni
@ 2025-08-26 6:41 ` Meet Soni
2025-08-26 6:41 ` [GSoC][PATCH v3 2/4] t1403: split 'show-ref --exists' tests into a separate file Meet Soni
` (4 subsequent siblings)
5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-26 6:41 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, gitster, Meet Soni
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 <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
Documentation/git-refs.adoc | 7 ++++++
builtin/refs.c | 48 +++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
index e608980711..5d2032b318 100644
--- a/Documentation/git-refs.adoc
+++ b/Documentation/git-refs.adoc
@@ -18,6 +18,7 @@ git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
[--contains[=<object>]] [--no-contains[=<object>]]
[(--exclude=<pattern>)...] [--start-after=<marker>]
[ --stdin | <pattern>... ]
+git refs exists <ref>
DESCRIPTION
-----------
@@ -38,6 +39,12 @@ list::
formatting, and sorting. This subcommand is an alias for
linkgit:git-for-each-ref[1] and offers identical functionality.
+exists::
+ Check whether the given reference exists. Returns an exit code of 0 if
+ it does, 2 if it is missing, and 1 in case looking up the reference
+ failed with an error other than the reference being missing. This does
+ not verify whether the reference resolves to an actual object.
+
OPTIONS
-------
diff --git a/builtin/refs.c b/builtin/refs.c
index 76224feba4..91548783b7 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -7,6 +7,7 @@
#include "strbuf.h"
#include "worktree.h"
#include "for-each-ref.h"
+#include "refs/refs-internal.h"
#define REFS_MIGRATE_USAGE \
N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]")
@@ -14,6 +15,9 @@
#define REFS_VERIFY_USAGE \
N_("git refs verify [--strict] [--verbose]")
+#define REFS_EXISTS_USAGE \
+ N_("git refs exists <ref>")
+
static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
struct repository *repo UNUSED)
{
@@ -113,6 +117,48 @@ static int cmd_refs_list(int argc, const char **argv, const char *prefix,
return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage);
}
+static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
+ struct repository *repo UNUSED)
+{
+ struct strbuf unused_referent = STRBUF_INIT;
+ struct object_id unused_oid;
+ unsigned int unused_type;
+ int failure_errno = 0;
+ const char *ref;
+ int ret = 0;
+ const char * const exists_usage[] = {
+ REFS_EXISTS_USAGE,
+ NULL,
+ };
+ struct option options[] = {
+ OPT_END(),
+ };
+
+ argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
+ if (argc != 1)
+ die(_("'git refs exists' requires a reference"));
+
+ ref = *argv++;
+ if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
+ &unused_oid, &unused_referent, &unused_type,
+ &failure_errno)) {
+ if (failure_errno == ENOENT || failure_errno == EISDIR) {
+ error(_("reference does not exist"));
+ ret = 2;
+ } else {
+ errno = failure_errno;
+ error_errno(_("failed to look up reference"));
+ ret = 1;
+ }
+
+ goto out;
+ }
+
+out:
+ strbuf_release(&unused_referent);
+ return ret;
+}
+
int cmd_refs(int argc,
const char **argv,
const char *prefix,
@@ -122,6 +168,7 @@ int cmd_refs(int argc,
REFS_MIGRATE_USAGE,
REFS_VERIFY_USAGE,
"git refs list " COMMON_USAGE_FOR_EACH_REF,
+ REFS_EXISTS_USAGE,
NULL,
};
parse_opt_subcommand_fn *fn = NULL;
@@ -129,6 +176,7 @@ int cmd_refs(int argc,
OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify),
OPT_SUBCOMMAND("list", &fn, cmd_refs_list),
+ OPT_SUBCOMMAND("exists", &fn, cmd_refs_exists),
OPT_END(),
};
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [GSoC][PATCH v3 2/4] t1403: split 'show-ref --exists' tests into a separate file
2025-08-26 6:41 ` [GSoC][PATCH v3 " Meet Soni
2025-08-26 6:41 ` [GSoC][PATCH v3 1/4] builtin/refs: add 'exists' subcommand Meet Soni
@ 2025-08-26 6:41 ` Meet Soni
2025-08-26 6:41 ` [GSoC][PATCH v3 3/4] t1422: refactor tests to be shareable Meet Soni
` (3 subsequent siblings)
5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-26 6:41 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, gitster, Meet Soni
The test file for git-show-ref(1), `t1403-show-ref.sh`, contains a group
of tests for the '--exists' flag. To improve organization and to prepare
for refactoring these tests to be shareable, move the '--exists' tests
and their corresponding setup logic into a self-contained test suite,
`t1422-show-ref-exists.sh`.
This is a pure code-movement refactoring with no change in test coverage
or behavior.
Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
t/meson.build | 3 +-
t/t1403-show-ref.sh | 65 -----------------------------
t/t1422-show-ref-exists.sh | 83 ++++++++++++++++++++++++++++++++++++++
3 files changed, 85 insertions(+), 66 deletions(-)
create mode 100644 t/t1422-show-ref-exists.sh
diff --git a/t/meson.build b/t/meson.build
index daf01fb5d0..4d6bc3d38e 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -205,6 +205,7 @@ integration_tests = [
't1419-exclude-refs.sh',
't1420-lost-found.sh',
't1421-reflog-write.sh',
+ 't1422-show-ref-exists.sh',
't1430-bad-ref-name.sh',
't1450-fsck.sh',
't1451-fsck-buffer.sh',
@@ -1216,4 +1217,4 @@ if perl.found() and time.found()
timeout: 0,
)
endforeach
-endif
\ No newline at end of file
+endif
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
index 9da3650e91..36c903ca19 100755
--- a/t/t1403-show-ref.sh
+++ b/t/t1403-show-ref.sh
@@ -228,69 +228,4 @@ test_expect_success 'show-ref sub-modes are mutually exclusive' '
grep "cannot be used together" err
'
-test_expect_success '--exists with existing reference' '
- git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
- test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
- test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
- grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
- git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
- test_when_finished "git update-ref -d refs/heads/bad...name" &&
- new_oid=$(git rev-parse HEAD) &&
- test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
- git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
- test_when_finished "git symbolic-ref -d refs/symref" &&
- git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
- git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
- test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
- git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
- git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
- test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
- tree_oid=$(git rev-parse HEAD^{tree}) &&
- test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
- cat >expect <<-EOF &&
- error: reference does not exist
- EOF
- test_expect_code 2 git show-ref --exists refs/heads 2>err &&
- test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
- test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
- test_when_finished "rm .git/FETCH_HEAD" &&
- git rev-parse HEAD >.git/FETCH_HEAD &&
- git show-ref --exists FETCH_HEAD
-'
-
test_done
diff --git a/t/t1422-show-ref-exists.sh b/t/t1422-show-ref-exists.sh
new file mode 100644
index 0000000000..0eccb2dce1
--- /dev/null
+++ b/t/t1422-show-ref-exists.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+test_description='show-ref --exists'
+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 '--exists with existing reference' '
+ git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+ test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+ test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+ grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+ git show-ref --exists HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+ test_when_finished "git update-ref -d refs/heads/bad...name" &&
+ new_oid=$(git rev-parse HEAD) &&
+ test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+ git show-ref --exists refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+ test_when_finished "git symbolic-ref -d refs/symref" &&
+ git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+ git show-ref --exists refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+ test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+ git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+ git show-ref --exists refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+ test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ git show-ref --exists refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+ tree_oid=$(git rev-parse HEAD^{tree}) &&
+ test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ git show-ref --exists refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+ cat >expect <<-EOF &&
+ error: reference does not exist
+ EOF
+ test_expect_code 2 git show-ref --exists refs/heads 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+ test_expect_code 2 git show-ref --exists FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+ test_when_finished "rm .git/FETCH_HEAD" &&
+ git rev-parse HEAD >.git/FETCH_HEAD &&
+ git show-ref --exists FETCH_HEAD
+'
+
+test_done
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [GSoC][PATCH v3 3/4] t1422: refactor tests to be shareable
2025-08-26 6:41 ` [GSoC][PATCH v3 " Meet Soni
2025-08-26 6:41 ` [GSoC][PATCH v3 1/4] builtin/refs: add 'exists' subcommand Meet Soni
2025-08-26 6:41 ` [GSoC][PATCH v3 2/4] t1403: split 'show-ref --exists' tests into a separate file Meet Soni
@ 2025-08-26 6:41 ` Meet Soni
2025-08-26 6:41 ` [GSoC][PATCH v3 4/4] t: add test for git refs exists subcommand Meet Soni
` (2 subsequent siblings)
5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-26 6:41 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, gitster, Meet Soni
In preparation for adding tests for the `git refs exists` command,
refactor the existing t1422 test suite to make its logic shareable.
Move the core test logic from `t1422-show-ref-exists.sh` to
`show-ref-exists-tests.sh` file. Inside this script, replace hardcoded
calls to "git show-ref --exists" with the `$git_show_ref_exists`
variable.
The original `t1422-show-ref-exists.sh` script now becomes a simple
"driver". It is responsible for setting the default value of the
variable and then sourcing the test library.
This structure follows an established pattern for sharing tests and
prepares the test suite for the `refs exists` tests to be added in a
subsequent commit.
Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
t/show-ref-exists-tests.sh | 77 ++++++++++++++++++++++++++++++++++++++
t/t1422-show-ref-exists.sh | 76 +------------------------------------
2 files changed, 78 insertions(+), 75 deletions(-)
create mode 100644 t/show-ref-exists-tests.sh
mode change 100644 => 100755 t/t1422-show-ref-exists.sh
diff --git a/t/show-ref-exists-tests.sh b/t/show-ref-exists-tests.sh
new file mode 100644
index 0000000000..36e8e9df33
--- /dev/null
+++ b/t/show-ref-exists-tests.sh
@@ -0,0 +1,77 @@
+git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
+
+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 '--exists with existing reference' '
+ ${git_show_ref_exists} refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+ test_expect_code 2 ${git_show_ref_exists} refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+ test_expect_code 2 ${git_show_ref_exists} $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+ grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+ ${git_show_ref_exists} HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+ test_when_finished "git update-ref -d refs/heads/bad...name" &&
+ new_oid=$(git rev-parse HEAD) &&
+ test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+ test_when_finished "git symbolic-ref -d refs/symref" &&
+ git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+ ${git_show_ref_exists} refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+ test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+ git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+ ${git_show_ref_exists} refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+ test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+ tree_oid=$(git rev-parse HEAD^{tree}) &&
+ test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+ cat >expect <<-EOF &&
+ error: reference does not exist
+ EOF
+ test_expect_code 2 ${git_show_ref_exists} refs/heads 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+ test_expect_code 2 ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+ test_when_finished "rm .git/FETCH_HEAD" &&
+ git rev-parse HEAD >.git/FETCH_HEAD &&
+ ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_done
diff --git a/t/t1422-show-ref-exists.sh b/t/t1422-show-ref-exists.sh
old mode 100644
new mode 100755
index 0eccb2dce1..fdca3f16c8
--- a/t/t1422-show-ref-exists.sh
+++ b/t/t1422-show-ref-exists.sh
@@ -6,78 +6,4 @@ 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 '--exists with existing reference' '
- git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
- test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
- test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
- grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
- git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
- test_when_finished "git update-ref -d refs/heads/bad...name" &&
- new_oid=$(git rev-parse HEAD) &&
- test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
- git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
- test_when_finished "git symbolic-ref -d refs/symref" &&
- git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
- git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
- test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
- git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
- git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
- test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
- tree_oid=$(git rev-parse HEAD^{tree}) &&
- test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
- cat >expect <<-EOF &&
- error: reference does not exist
- EOF
- test_expect_code 2 git show-ref --exists refs/heads 2>err &&
- test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
- test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
- test_when_finished "rm .git/FETCH_HEAD" &&
- git rev-parse HEAD >.git/FETCH_HEAD &&
- git show-ref --exists FETCH_HEAD
-'
-
-test_done
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [GSoC][PATCH v3 4/4] t: add test for git refs exists subcommand
2025-08-26 6:41 ` [GSoC][PATCH v3 " Meet Soni
` (2 preceding siblings ...)
2025-08-26 6:41 ` [GSoC][PATCH v3 3/4] t1422: refactor tests to be shareable Meet Soni
@ 2025-08-26 6:41 ` Meet Soni
2025-09-02 11:52 ` [GSoC][PATCH v3 0/4] Add " Patrick Steinhardt
2025-09-02 16:57 ` Junio C Hamano
5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-26 6:41 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, gitster, Meet Soni
Add a test script, `t/t1462-refs-exists.sh`, for the `git refs exists`
command.
This script acts as a simple driver, leveraging the shared test library
created in the preceding commit. It works by overriding the
`$git_show_ref_exists` variable to "git refs exists" and then sourcing the
shared library (`t/show-ref-exists-tests.sh`).
This approach ensures that `git refs exists` is tested against the
entire comprehensive test suite of `git show-ref --exists`, verifying
that it acts as a compatible drop-in replacement.
Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
t/meson.build | 1 +
t/t1462-refs-exists.sh | 10 ++++++++++
2 files changed, 11 insertions(+)
create mode 100755 t/t1462-refs-exists.sh
diff --git a/t/meson.build b/t/meson.build
index 4d6bc3d38e..93e9773ec8 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -211,6 +211,7 @@ integration_tests = [
't1451-fsck-buffer.sh',
't1460-refs-migrate.sh',
't1461-refs-list.sh',
+ 't1462-refs-exists.sh',
't1500-rev-parse.sh',
't1501-work-tree.sh',
't1502-rev-parse-parseopt.sh',
diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
new file mode 100755
index 0000000000..349453c4ca
--- /dev/null
+++ b/t/t1462-refs-exists.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+test_description='refs exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+git_show_ref_exists='git refs exists'
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [GSoC][PATCH v3 0/4] Add refs exists subcommand
2025-08-26 6:41 ` [GSoC][PATCH v3 " Meet Soni
` (3 preceding siblings ...)
2025-08-26 6:41 ` [GSoC][PATCH v3 4/4] t: add test for git refs exists subcommand Meet Soni
@ 2025-09-02 11:52 ` Patrick Steinhardt
2025-09-02 16:57 ` Junio C Hamano
5 siblings, 0 replies; 23+ messages in thread
From: Patrick Steinhardt @ 2025-09-02 11:52 UTC (permalink / raw)
To: Meet Soni; +Cc: git, shejialuo, gitster
On Tue, Aug 26, 2025 at 12:11:06PM +0530, Meet Soni wrote:
> This series introduces `git refs exists` as a modern replacement for
> `git show-ref --exists`, continuing the effort to consolidate commands
> under the `git refs` namespace.
>
> changes in v3:
> - Reverted commit message.
> - nit: added empty line.
Thanks, this version looks good to me.
Patrick
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [GSoC][PATCH v3 0/4] Add refs exists subcommand
2025-08-26 6:41 ` [GSoC][PATCH v3 " Meet Soni
` (4 preceding siblings ...)
2025-09-02 11:52 ` [GSoC][PATCH v3 0/4] Add " Patrick Steinhardt
@ 2025-09-02 16:57 ` Junio C Hamano
5 siblings, 0 replies; 23+ messages in thread
From: Junio C Hamano @ 2025-09-02 16:57 UTC (permalink / raw)
To: Meet Soni; +Cc: git, ps, shejialuo
Meet Soni <meetsoni3017@gmail.com> writes:
> This series introduces `git refs exists` as a modern replacement for
> `git show-ref --exists`, continuing the effort to consolidate commands
> under the `git refs` namespace.
>
> changes in v3:
> - Reverted commit message.
> - nit: added empty line.
>
> Meet Soni (4):
> builtin/refs: add 'exists' subcommand
> t1403: split 'show-ref --exists' tests into a separate file
> t1422: refactor tests to be shareable
> t: add test for git refs exists subcommand
>
> Documentation/git-refs.adoc | 7 ++++
> builtin/refs.c | 48 +++++++++++++++++++++++
> t/meson.build | 4 +-
> t/show-ref-exists-tests.sh | 77 +++++++++++++++++++++++++++++++++++++
> t/t1403-show-ref.sh | 65 -------------------------------
> t/t1422-show-ref-exists.sh | 9 +++++
> t/t1462-refs-exists.sh | 10 +++++
> 7 files changed, 154 insertions(+), 66 deletions(-)
> create mode 100644 t/show-ref-exists-tests.sh
> create mode 100755 t/t1422-show-ref-exists.sh
> create mode 100755 t/t1462-refs-exists.sh
>
> Range-diff against v2:
> 1: 19623eb97e < -: ---------- doc: factor out common option
> 2: 69c207dc45 < -: ---------- builtin/for-each-ref: align usage string with the man page
> 3: 6eeb1c070a < -: ---------- builtin/for-each-ref: factor out core logic into a helper
> 4: eecccfe98b < -: ---------- builtin/refs: add list subcommand
> 5: aa91c5c570 < -: ---------- t6300: refactor tests to be shareable
> 6: fed66d91c0 < -: ---------- t: add test for git refs list subcommand
> 7: b55e6d36eb < -: ---------- diff: ensure consistent diff behavior with ignore options
> 8: e1d3d61a45 < -: ---------- diff: --no-index should ignore the worktree
> 9: 621ce9c1c6 < -: ---------- git-jump: make `diff` work with filenames containing spaces
> 10: 9a49aef8dc < -: ---------- environment: remove the global variable 'merge_log_config'
> 11: 22d421fed9 < -: ---------- builtin/fmt-merge-msg: stop depending on 'the_repository'
> 12: 741f36c7d9 < -: ---------- docs: remove stray bracket from git-clone synopsis
> 13: 1fa68948c3 < -: ---------- The second batch
GitGitGadget and/or range-diff somehow went berserk?
But thanks to it, I now know that the series is built on top of the
second batch ;-) I was wondering why the patches did not apply
cleanly to a more recent tip of 'master'.
Will queue. Thanks.
^ permalink raw reply [flat|nested] 23+ messages in thread