2007-11-07 01:29:20 +00:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='git ls-remote'
|
|
|
|
|
2020-11-18 23:44:32 +00:00
|
|
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
tests: mark tests relying on the current default for `init.defaultBranch`
In addition to the manual adjustment to let the `linux-gcc` CI job run
the test suite with `master` and then with `main`, this patch makes sure
that GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME is set in all test scripts
that currently rely on the initial branch name being `master by default.
To determine which test scripts to mark up, the first step was to
force-set the default branch name to `master` in
- all test scripts that contain the keyword `master`,
- t4211, which expects `t/t4211/history.export` with a hard-coded ref to
initialize the default branch,
- t5560 because it sources `t/t556x_common` which uses `master`,
- t8002 and t8012 because both source `t/annotate-tests.sh` which also
uses `master`)
This trick was performed by this command:
$ sed -i '/^ *\. \.\/\(test-lib\|lib-\(bash\|cvs\|git-svn\)\|gitweb-lib\)\.sh$/i\
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master\
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\
' $(git grep -l master t/t[0-9]*.sh) \
t/t4211*.sh t/t5560*.sh t/t8002*.sh t/t8012*.sh
After that, careful, manual inspection revealed that some of the test
scripts containing the needle `master` do not actually rely on a
specific default branch name: either they mention `master` only in a
comment, or they initialize that branch specificially, or they do not
actually refer to the current default branch. Therefore, the
aforementioned modification was undone in those test scripts thusly:
$ git checkout HEAD -- \
t/t0027-auto-crlf.sh t/t0060-path-utils.sh \
t/t1011-read-tree-sparse-checkout.sh \
t/t1305-config-include.sh t/t1309-early-config.sh \
t/t1402-check-ref-format.sh t/t1450-fsck.sh \
t/t2024-checkout-dwim.sh \
t/t2106-update-index-assume-unchanged.sh \
t/t3040-subprojects-basic.sh t/t3301-notes.sh \
t/t3308-notes-merge.sh t/t3423-rebase-reword.sh \
t/t3436-rebase-more-options.sh \
t/t4015-diff-whitespace.sh t/t4257-am-interactive.sh \
t/t5323-pack-redundant.sh t/t5401-update-hooks.sh \
t/t5511-refspec.sh t/t5526-fetch-submodules.sh \
t/t5529-push-errors.sh t/t5530-upload-pack-error.sh \
t/t5548-push-porcelain.sh \
t/t5552-skipping-fetch-negotiator.sh \
t/t5572-pull-submodule.sh t/t5608-clone-2gb.sh \
t/t5614-clone-submodules-shallow.sh \
t/t7508-status.sh t/t7606-merge-custom.sh \
t/t9302-fast-import-unpack-limit.sh
We excluded one set of test scripts in these commands, though: the range
of `git p4` tests. The reason? `git p4` stores the (foreign) remote
branch in the branch called `p4/master`, which is obviously not the
default branch. Manual analysis revealed that only five of these tests
actually require a specific default branch name to pass; They were
modified thusly:
$ sed -i '/^ *\. \.\/lib-git-p4\.sh$/i\
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master\
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\
' t/t980[0167]*.sh t/t9811*.sh
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-18 23:44:19 +00:00
|
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
|
|
|
2007-11-07 01:29:20 +00:00
|
|
|
. ./test-lib.sh
|
|
|
|
|
2020-03-26 08:27:49 +00:00
|
|
|
generate_references () {
|
|
|
|
for ref
|
|
|
|
do
|
|
|
|
oid=$(git rev-parse "$ref") &&
|
|
|
|
printf '%s\t%s\n' "$oid" "$ref" || return 1
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
v0 protocol: fix infinite loop when parsing multi-valued capabilities
If Git's client-side parsing of an upload-pack response (so git-fetch or
ls-remote) sees multiple instances of a single capability, it can enter
an infinite loop due to a bug in advancing the "offset" parameter in the
parser.
This bug can't happen between a client and server of the same Git
version. The client bug is in parse_feature_value() when the caller
passes in an offset parameter. And that only happens when the v0
protocol is parsing "symref" and "object-format" capabilities, via
next_server_feature_value(). But Git has never produced multiple
object-format capabilities, and it stopped producing multiple symref
values in d007dbf7d6 (Revert "upload-pack: send non-HEAD symbolic refs",
2013-11-18).
However, upload-pack did produce multiple symref entries for a while,
and they are valid. Plus other implementations, such as Dulwich will
still do so. So we should handle them. And even if we do not expect it,
it is obviously a bug for the parser to enter an infinite loop.
The bug itself is pretty simple. Commit 2c6a403d96 (connect: add
function to parse multiple v1 capability values, 2020-05-25) added the
"offset" parameter, which is used as both an in- and out-parameter. When
parsing the first "symref" capability, *offset will be 0 on input, and
after parsing the capability, we set *offset to an index just past the
value by taking a pointer difference "(value + end) - feature_list".
But on the second call, now *offset is set to that larger index, which
lets us skip past the first "symref" capability. However, we do so by
incrementing feature_list. That means our pointer difference is now too
small; it is counting from where we resumed parsing, not from the start
of the original feature_list pointer. And because we incremented
feature_list only inside our function, and not the caller, that
increment is lost next time the function is called.
One solution would be to account for those skipped bytes by incrementing
*offset, rather than assigning to it. But wait, there's more!
We also increment feature_list if we have a near-miss. Say we are
looking for "symref" and find "almost-symref". In that case we'll point
feature_list to the "y" in "almost-symref" and restart our search. But
that again means our offset won't be correct, as it won't account for
the bytes between the start of the string and that "y".
So instead, let's just record the beginning of the feature_list string
in a separate pointer that we never touch. That offset we take in and
return is meant to be using that point as a base, and now we'll do so
consistently.
Since the bug can't be reproduced using the current version of
git-upload-pack, we'll instead hard-code an input which triggers the
problem. Before this patch it loops forever re-parsing the second symref
entry. Now we check both that it finishes, and that it parses both
entries correctly (a case we could not test at all before).
We don't need to worry about testing v2 here; it communicates the
capabilities in a completely different way, and doesn't use this code at
all. There are tests earlier in t5512 that are meant to cover this (they
don't, but we'll address that in a future patch).
Reported-by: Jonas Haag <jonas@lophus.org>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-04-14 21:24:16 +00:00
|
|
|
test_expect_success 'set up fake upload-pack' '
|
|
|
|
# This can be used to simulate an upload-pack that just shows the
|
|
|
|
# contents of the "input" file (prepared with the test-tool pkt-line
|
|
|
|
# helper), and does not do any negotiation (since ls-remote does not
|
|
|
|
# need it).
|
|
|
|
write_script cat-input <<-\EOF
|
|
|
|
# send our initial advertisement/response
|
|
|
|
cat input
|
|
|
|
# soak up the flush packet from the client
|
|
|
|
cat
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
push: default to single remote even when not named origin
With "push.default=current" configured, a simple "git push" will push to
the same-name branch on the current branch's branch.<name>.pushRemote, or
remote.pushDefault, or origin. If none of these are defined, the push will
fail with error "fatal: No configured push destination".
The same "default to origin if no config" behavior applies with
"push.default=matching".
Other commands use "origin" as a default when there are multiple options,
but default to the single remote when there is only one - for example,
"git checkout <something>". This "assume the single remote if there is
only one" behavior is more friendly/useful than a defaulting behavior
that only uses the name "origin" no matter what.
Update "git push" to also default to the single remote (and finally fall
back to "origin" as default if there are several), for
"push.default=current" and for other current and future remote-defaulting
push behaviors.
This change also modifies the behavior of ls-remote in a consistent way,
so defaulting not only supplies 'origin', but any single configured remote
also.
Document the change in behavior, correct incorrect assumptions in related
tests, and add test cases reflecting this new single-remote-defaulting
behavior.
Signed-off-by: Tao Klerks <tao@klerks.biz>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-29 09:56:45 +00:00
|
|
|
test_expect_success 'dies when no remote found' '
|
|
|
|
test_must_fail git ls-remote
|
|
|
|
'
|
|
|
|
|
2007-11-07 01:29:20 +00:00
|
|
|
test_expect_success setup '
|
|
|
|
>file &&
|
|
|
|
git add file &&
|
|
|
|
test_tick &&
|
|
|
|
git commit -m initial &&
|
|
|
|
git tag mark &&
|
2018-04-09 01:42:26 +00:00
|
|
|
git tag mark1.1 &&
|
|
|
|
git tag mark1.2 &&
|
|
|
|
git tag mark1.10 &&
|
2020-03-26 08:27:50 +00:00
|
|
|
git show-ref --tags -d >expected.tag.raw &&
|
|
|
|
sed -e "s/ / /" expected.tag.raw >expected.tag &&
|
|
|
|
generate_references HEAD >expected.all &&
|
|
|
|
git show-ref -d >refs &&
|
|
|
|
sed -e "s/ / /" refs >>expected.all &&
|
2007-11-07 01:29:20 +00:00
|
|
|
|
push: default to single remote even when not named origin
With "push.default=current" configured, a simple "git push" will push to
the same-name branch on the current branch's branch.<name>.pushRemote, or
remote.pushDefault, or origin. If none of these are defined, the push will
fail with error "fatal: No configured push destination".
The same "default to origin if no config" behavior applies with
"push.default=matching".
Other commands use "origin" as a default when there are multiple options,
but default to the single remote when there is only one - for example,
"git checkout <something>". This "assume the single remote if there is
only one" behavior is more friendly/useful than a defaulting behavior
that only uses the name "origin" no matter what.
Update "git push" to also default to the single remote (and finally fall
back to "origin" as default if there are several), for
"push.default=current" and for other current and future remote-defaulting
push behaviors.
This change also modifies the behavior of ls-remote in a consistent way,
so defaulting not only supplies 'origin', but any single configured remote
also.
Document the change in behavior, correct incorrect assumptions in related
tests, and add test cases reflecting this new single-remote-defaulting
behavior.
Signed-off-by: Tao Klerks <tao@klerks.biz>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-29 09:56:45 +00:00
|
|
|
git remote add self "$(pwd)/.git" &&
|
|
|
|
git remote add self2 "."
|
2007-11-07 01:29:20 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'ls-remote --tags .git' '
|
|
|
|
git ls-remote --tags .git >actual &&
|
2008-03-12 21:36:36 +00:00
|
|
|
test_cmp expected.tag actual
|
2007-11-07 01:29:20 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'ls-remote .git' '
|
|
|
|
git ls-remote .git >actual &&
|
2008-03-12 21:36:36 +00:00
|
|
|
test_cmp expected.all actual
|
2007-11-07 01:29:20 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'ls-remote --tags self' '
|
|
|
|
git ls-remote --tags self >actual &&
|
2008-03-12 21:36:36 +00:00
|
|
|
test_cmp expected.tag actual
|
2007-11-07 01:29:20 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'ls-remote self' '
|
|
|
|
git ls-remote self >actual &&
|
2008-03-12 21:36:36 +00:00
|
|
|
test_cmp expected.all actual
|
2007-11-07 01:29:20 +00:00
|
|
|
'
|
|
|
|
|
2018-04-09 01:42:26 +00:00
|
|
|
test_expect_success 'ls-remote --sort="version:refname" --tags self' '
|
2020-03-26 08:27:49 +00:00
|
|
|
generate_references \
|
|
|
|
refs/tags/mark \
|
|
|
|
refs/tags/mark1.1 \
|
|
|
|
refs/tags/mark1.2 \
|
|
|
|
refs/tags/mark1.10 >expect &&
|
2018-04-09 01:42:26 +00:00
|
|
|
git ls-remote --sort="version:refname" --tags self >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'ls-remote --sort="-version:refname" --tags self' '
|
2020-03-26 08:27:49 +00:00
|
|
|
generate_references \
|
|
|
|
refs/tags/mark1.10 \
|
|
|
|
refs/tags/mark1.2 \
|
|
|
|
refs/tags/mark1.1 \
|
|
|
|
refs/tags/mark >expect &&
|
2018-04-09 01:42:26 +00:00
|
|
|
git ls-remote --sort="-version:refname" --tags self >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'ls-remote --sort="-refname" --tags self' '
|
2020-03-26 08:27:49 +00:00
|
|
|
generate_references \
|
|
|
|
refs/tags/mark1.2 \
|
|
|
|
refs/tags/mark1.10 \
|
|
|
|
refs/tags/mark1.1 \
|
|
|
|
refs/tags/mark >expect &&
|
2018-04-09 01:42:26 +00:00
|
|
|
git ls-remote --sort="-refname" --tags self >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
push: default to single remote even when not named origin
With "push.default=current" configured, a simple "git push" will push to
the same-name branch on the current branch's branch.<name>.pushRemote, or
remote.pushDefault, or origin. If none of these are defined, the push will
fail with error "fatal: No configured push destination".
The same "default to origin if no config" behavior applies with
"push.default=matching".
Other commands use "origin" as a default when there are multiple options,
but default to the single remote when there is only one - for example,
"git checkout <something>". This "assume the single remote if there is
only one" behavior is more friendly/useful than a defaulting behavior
that only uses the name "origin" no matter what.
Update "git push" to also default to the single remote (and finally fall
back to "origin" as default if there are several), for
"push.default=current" and for other current and future remote-defaulting
push behaviors.
This change also modifies the behavior of ls-remote in a consistent way,
so defaulting not only supplies 'origin', but any single configured remote
also.
Document the change in behavior, correct incorrect assumptions in related
tests, and add test cases reflecting this new single-remote-defaulting
behavior.
Signed-off-by: Tao Klerks <tao@klerks.biz>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-29 09:56:45 +00:00
|
|
|
test_expect_success 'dies when no remote specified, multiple remotes found, and no default specified' '
|
ls-remote: fall-back to default remotes when no remote specified
Instead of breaking execution when no remote (as specified in the
variable dest) is specified when git-ls-remote is invoked, continue on
and let remote_get() handle it.
This way, we are able to use the default remotes (eg. "origin",
branch.<name>.remote), as git-fetch, git-push, and other users of
remote_get(), do.
If no suitable remote is found, exit with a message describing the
issue, instead of just the usage text, as we do previously.
Add several tests to check that git-ls-remote handles the
no-remote-specified situation.
Also add a test that "git ls-remote <pattern>" does not work; we are
unable to guess the remote in that situation, as are git-fetch and
git-push.
In that test, we are testing for messages coming from two separate
processes, but we should be OK, because the second message is triggered
by closing the fd which must happen after the first message is printed.
(analysis by Jeff King.)
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-08 17:21:13 +00:00
|
|
|
test_must_fail git ls-remote
|
|
|
|
'
|
|
|
|
|
push: default to single remote even when not named origin
With "push.default=current" configured, a simple "git push" will push to
the same-name branch on the current branch's branch.<name>.pushRemote, or
remote.pushDefault, or origin. If none of these are defined, the push will
fail with error "fatal: No configured push destination".
The same "default to origin if no config" behavior applies with
"push.default=matching".
Other commands use "origin" as a default when there are multiple options,
but default to the single remote when there is only one - for example,
"git checkout <something>". This "assume the single remote if there is
only one" behavior is more friendly/useful than a defaulting behavior
that only uses the name "origin" no matter what.
Update "git push" to also default to the single remote (and finally fall
back to "origin" as default if there are several), for
"push.default=current" and for other current and future remote-defaulting
push behaviors.
This change also modifies the behavior of ls-remote in a consistent way,
so defaulting not only supplies 'origin', but any single configured remote
also.
Document the change in behavior, correct incorrect assumptions in related
tests, and add test cases reflecting this new single-remote-defaulting
behavior.
Signed-off-by: Tao Klerks <tao@klerks.biz>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-29 09:56:45 +00:00
|
|
|
test_expect_success 'succeeds when no remote specified but only one found' '
|
|
|
|
test_when_finished git remote add self2 "." &&
|
|
|
|
git remote remove self2 &&
|
|
|
|
git ls-remote
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'use "origin" when no remote specified and multiple found' '
|
2010-05-11 17:20:23 +00:00
|
|
|
URL="$(pwd)/.git" &&
|
|
|
|
echo "From $URL" >exp_err &&
|
|
|
|
|
|
|
|
git remote add origin "$URL" &&
|
|
|
|
git ls-remote 2>actual_err >actual &&
|
|
|
|
|
|
|
|
test_cmp exp_err actual_err &&
|
ls-remote: fall-back to default remotes when no remote specified
Instead of breaking execution when no remote (as specified in the
variable dest) is specified when git-ls-remote is invoked, continue on
and let remote_get() handle it.
This way, we are able to use the default remotes (eg. "origin",
branch.<name>.remote), as git-fetch, git-push, and other users of
remote_get(), do.
If no suitable remote is found, exit with a message describing the
issue, instead of just the usage text, as we do previously.
Add several tests to check that git-ls-remote handles the
no-remote-specified situation.
Also add a test that "git ls-remote <pattern>" does not work; we are
unable to guess the remote in that situation, as are git-fetch and
git-push.
In that test, we are testing for messages coming from two separate
processes, but we should be OK, because the second message is triggered
by closing the fd which must happen after the first message is printed.
(analysis by Jeff King.)
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-08 17:21:13 +00:00
|
|
|
test_cmp expected.all actual
|
|
|
|
'
|
|
|
|
|
2010-05-11 17:20:23 +00:00
|
|
|
test_expect_success 'suppress "From <url>" with -q' '
|
|
|
|
git ls-remote -q 2>actual_err &&
|
2020-03-25 05:54:48 +00:00
|
|
|
! test_cmp exp_err actual_err
|
2010-05-11 17:20:23 +00:00
|
|
|
'
|
|
|
|
|
ls-remote: fall-back to default remotes when no remote specified
Instead of breaking execution when no remote (as specified in the
variable dest) is specified when git-ls-remote is invoked, continue on
and let remote_get() handle it.
This way, we are able to use the default remotes (eg. "origin",
branch.<name>.remote), as git-fetch, git-push, and other users of
remote_get(), do.
If no suitable remote is found, exit with a message describing the
issue, instead of just the usage text, as we do previously.
Add several tests to check that git-ls-remote handles the
no-remote-specified situation.
Also add a test that "git ls-remote <pattern>" does not work; we are
unable to guess the remote in that situation, as are git-fetch and
git-push.
In that test, we are testing for messages coming from two separate
processes, but we should be OK, because the second message is triggered
by closing the fd which must happen after the first message is printed.
(analysis by Jeff King.)
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-08 17:21:13 +00:00
|
|
|
test_expect_success 'use branch.<name>.remote if possible' '
|
|
|
|
#
|
|
|
|
# Test that we are indeed using branch.<name>.remote, not "origin", even
|
|
|
|
# though the "origin" remote has been set.
|
|
|
|
#
|
|
|
|
|
|
|
|
# setup a new remote to differentiate from "origin"
|
|
|
|
git clone . other.git &&
|
|
|
|
(
|
|
|
|
cd other.git &&
|
2018-07-02 00:24:01 +00:00
|
|
|
echo "$(git rev-parse HEAD) HEAD" &&
|
ls-remote: fall-back to default remotes when no remote specified
Instead of breaking execution when no remote (as specified in the
variable dest) is specified when git-ls-remote is invoked, continue on
and let remote_get() handle it.
This way, we are able to use the default remotes (eg. "origin",
branch.<name>.remote), as git-fetch, git-push, and other users of
remote_get(), do.
If no suitable remote is found, exit with a message describing the
issue, instead of just the usage text, as we do previously.
Add several tests to check that git-ls-remote handles the
no-remote-specified situation.
Also add a test that "git ls-remote <pattern>" does not work; we are
unable to guess the remote in that situation, as are git-fetch and
git-push.
In that test, we are testing for messages coming from two separate
processes, but we should be OK, because the second message is triggered
by closing the fd which must happen after the first message is printed.
(analysis by Jeff King.)
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-08 17:21:13 +00:00
|
|
|
git show-ref | sed -e "s/ / /"
|
|
|
|
) >exp &&
|
|
|
|
|
2010-05-11 17:20:23 +00:00
|
|
|
URL="other.git" &&
|
|
|
|
echo "From $URL" >exp_err &&
|
|
|
|
|
|
|
|
git remote add other $URL &&
|
2020-11-18 23:44:32 +00:00
|
|
|
git config branch.main.remote other &&
|
ls-remote: fall-back to default remotes when no remote specified
Instead of breaking execution when no remote (as specified in the
variable dest) is specified when git-ls-remote is invoked, continue on
and let remote_get() handle it.
This way, we are able to use the default remotes (eg. "origin",
branch.<name>.remote), as git-fetch, git-push, and other users of
remote_get(), do.
If no suitable remote is found, exit with a message describing the
issue, instead of just the usage text, as we do previously.
Add several tests to check that git-ls-remote handles the
no-remote-specified situation.
Also add a test that "git ls-remote <pattern>" does not work; we are
unable to guess the remote in that situation, as are git-fetch and
git-push.
In that test, we are testing for messages coming from two separate
processes, but we should be OK, because the second message is triggered
by closing the fd which must happen after the first message is printed.
(analysis by Jeff King.)
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-08 17:21:13 +00:00
|
|
|
|
2010-05-11 17:20:23 +00:00
|
|
|
git ls-remote 2>actual_err >actual &&
|
|
|
|
test_cmp exp_err actual_err &&
|
ls-remote: fall-back to default remotes when no remote specified
Instead of breaking execution when no remote (as specified in the
variable dest) is specified when git-ls-remote is invoked, continue on
and let remote_get() handle it.
This way, we are able to use the default remotes (eg. "origin",
branch.<name>.remote), as git-fetch, git-push, and other users of
remote_get(), do.
If no suitable remote is found, exit with a message describing the
issue, instead of just the usage text, as we do previously.
Add several tests to check that git-ls-remote handles the
no-remote-specified situation.
Also add a test that "git ls-remote <pattern>" does not work; we are
unable to guess the remote in that situation, as are git-fetch and
git-push.
In that test, we are testing for messages coming from two separate
processes, but we should be OK, because the second message is triggered
by closing the fd which must happen after the first message is printed.
(analysis by Jeff King.)
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-08 17:21:13 +00:00
|
|
|
test_cmp exp actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'confuses pattern as remote when no remote specified' '
|
2017-05-03 10:16:50 +00:00
|
|
|
if test_have_prereq MINGW
|
|
|
|
then
|
|
|
|
# Windows does not like asterisks in pathname
|
2020-11-18 23:44:32 +00:00
|
|
|
does_not_exist=main
|
2017-05-03 10:16:50 +00:00
|
|
|
else
|
2020-11-18 23:44:32 +00:00
|
|
|
does_not_exist="refs*main"
|
2017-05-03 10:16:50 +00:00
|
|
|
fi &&
|
|
|
|
cat >exp <<-EOF &&
|
|
|
|
fatal: '\''$does_not_exist'\'' does not appear to be a git repository
|
2012-07-05 06:40:11 +00:00
|
|
|
fatal: Could not read from remote repository.
|
|
|
|
|
|
|
|
Please make sure you have the correct access rights
|
|
|
|
and the repository exists.
|
2012-03-03 02:15:34 +00:00
|
|
|
EOF
|
ls-remote: fall-back to default remotes when no remote specified
Instead of breaking execution when no remote (as specified in the
variable dest) is specified when git-ls-remote is invoked, continue on
and let remote_get() handle it.
This way, we are able to use the default remotes (eg. "origin",
branch.<name>.remote), as git-fetch, git-push, and other users of
remote_get(), do.
If no suitable remote is found, exit with a message describing the
issue, instead of just the usage text, as we do previously.
Add several tests to check that git-ls-remote handles the
no-remote-specified situation.
Also add a test that "git ls-remote <pattern>" does not work; we are
unable to guess the remote in that situation, as are git-fetch and
git-push.
In that test, we are testing for messages coming from two separate
processes, but we should be OK, because the second message is triggered
by closing the fd which must happen after the first message is printed.
(analysis by Jeff King.)
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-08 17:21:13 +00:00
|
|
|
#
|
2012-06-19 18:24:50 +00:00
|
|
|
# Do not expect "git ls-remote <pattern>" to work; ls-remote needs
|
|
|
|
# <remote> if you want to feed <pattern>, just like you cannot say
|
|
|
|
# fetch <branch>.
|
2020-11-18 23:44:32 +00:00
|
|
|
# We could just as easily have used "main"; the "*" emphasizes its
|
ls-remote: fall-back to default remotes when no remote specified
Instead of breaking execution when no remote (as specified in the
variable dest) is specified when git-ls-remote is invoked, continue on
and let remote_get() handle it.
This way, we are able to use the default remotes (eg. "origin",
branch.<name>.remote), as git-fetch, git-push, and other users of
remote_get(), do.
If no suitable remote is found, exit with a message describing the
issue, instead of just the usage text, as we do previously.
Add several tests to check that git-ls-remote handles the
no-remote-specified situation.
Also add a test that "git ls-remote <pattern>" does not work; we are
unable to guess the remote in that situation, as are git-fetch and
git-push.
In that test, we are testing for messages coming from two separate
processes, but we should be OK, because the second message is triggered
by closing the fd which must happen after the first message is printed.
(analysis by Jeff King.)
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-08 17:21:13 +00:00
|
|
|
# role as a pattern.
|
2017-05-03 10:16:50 +00:00
|
|
|
test_must_fail git ls-remote "$does_not_exist" >actual 2>&1 &&
|
2021-02-11 01:53:53 +00:00
|
|
|
test_cmp exp actual
|
ls-remote: fall-back to default remotes when no remote specified
Instead of breaking execution when no remote (as specified in the
variable dest) is specified when git-ls-remote is invoked, continue on
and let remote_get() handle it.
This way, we are able to use the default remotes (eg. "origin",
branch.<name>.remote), as git-fetch, git-push, and other users of
remote_get(), do.
If no suitable remote is found, exit with a message describing the
issue, instead of just the usage text, as we do previously.
Add several tests to check that git-ls-remote handles the
no-remote-specified situation.
Also add a test that "git ls-remote <pattern>" does not work; we are
unable to guess the remote in that situation, as are git-fetch and
git-push.
In that test, we are testing for messages coming from two separate
processes, but we should be OK, because the second message is triggered
by closing the fd which must happen after the first message is printed.
(analysis by Jeff King.)
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-08 17:21:13 +00:00
|
|
|
'
|
|
|
|
|
2011-05-18 20:06:00 +00:00
|
|
|
test_expect_success 'die with non-2 for wrong repository even with --exit-code' '
|
2015-03-20 10:12:29 +00:00
|
|
|
{
|
|
|
|
git ls-remote --exit-code ./no-such-repository
|
|
|
|
status=$?
|
|
|
|
} &&
|
2011-05-18 20:06:00 +00:00
|
|
|
test $status != 2 && test $status != 0
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Report success even when nothing matches' '
|
|
|
|
git ls-remote other.git "refs/nsn/*" >actual &&
|
2018-07-27 17:48:11 +00:00
|
|
|
test_must_be_empty actual
|
2011-05-18 20:06:00 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Report no-match with --exit-code' '
|
|
|
|
test_expect_code 2 git ls-remote --exit-code other.git "refs/nsn/*" >actual &&
|
2018-07-27 17:48:11 +00:00
|
|
|
test_must_be_empty actual
|
2011-05-18 20:06:00 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Report match with --exit-code' '
|
|
|
|
git ls-remote --exit-code other.git "refs/tags/*" >actual &&
|
2018-04-09 01:42:26 +00:00
|
|
|
git ls-remote . tags/mark* >expect &&
|
2011-05-18 20:06:00 +00:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
refs: support negative transfer.hideRefs
If you hide a hierarchy of refs using the transfer.hideRefs
config, there is no way to later override that config to
"unhide" it. This patch implements a "negative" hide which
causes matches to immediately be marked as unhidden, even if
another match would hide it. We take care to apply the
matches in reverse-order from how they are fed to us by the
config machinery, as that lets our usual "last one wins"
config precedence work (and entries in .git/config, for
example, will override /etc/gitconfig).
So you can now do:
$ git config --system transfer.hideRefs refs/secret
$ git config transfer.hideRefs '!refs/secret/not-so-secret'
to hide refs/secret in all repos, except for one public bit
in one specific repo. Or you can even do:
$ git clone \
-u "git -c transfer.hiderefs="!refs/foo" upload-pack" \
remote:repo.git
to clone remote:repo.git, overriding any hiding it has
configured.
There are two alternatives that were considered and
rejected:
1. A generic config mechanism for removing an item from a
list. E.g.: (e.g., "[transfer] hideRefs -= refs/foo").
This is nice because it could apply to other
multi-valued config, as well. But it is not nearly as
flexible. There is no way to say:
[transfer]
hideRefs = refs/secret
hideRefs = refs/secret/not-so-secret
Having explicit negative specifications means we can
override previous entries, even if they are not the
same literal string.
2. Adding another variable to override some parts of
hideRefs (e.g., "exposeRefs").
This solves the problem from alternative (1), but it
cannot easily obey the normal config precedence,
because it would use two separate lists. For example:
[transfer]
hideRefs = refs/secret
exposeRefs = refs/secret/not-so-secret
hideRefs = refs/secret/not-so-secret/no-really-its-secret
With two lists, we have to apply the "expose" rules
first, and only then apply the "hide" rules. But that
does not match what the above config intends.
Of course we could internally parse that to a single
list, respecting the ordering, which saves us having to
invent the new "!" syntax. But using a single name
communicates to the user that the ordering _is_
important. And "!" is well-known for negation, and
should not appear at the beginning of a ref (it is
actually valid in a ref-name, but all entries here
should be fully-qualified, starting with "refs/").
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-07-28 20:23:26 +00:00
|
|
|
test_expect_success 'set up some extra tags for ref hiding' '
|
|
|
|
git tag magic/one &&
|
|
|
|
git tag magic/two
|
|
|
|
'
|
|
|
|
|
upload/receive-pack: allow hiding ref hierarchies
A repository may have refs that are only used for its internal
bookkeeping purposes that should not be exposed to the others that
come over the network.
Teach upload-pack to omit some refs from its initial advertisement
by paying attention to the uploadpack.hiderefs multi-valued
configuration variable. Do the same to receive-pack via the
receive.hiderefs variable. As a convenient short-hand, allow using
transfer.hiderefs to set the value to both of these variables.
Any ref that is under the hierarchies listed on the value of these
variable is excluded from responses to requests made by "ls-remote",
"fetch", etc. (for upload-pack) and "push" (for receive-pack).
Because these hidden refs do not count as OUR_REF, an attempt to
fetch objects at the tip of them will be rejected, and because these
refs do not get advertised, "git push :" will not see local branches
that have the same name as them as "matching" ones to be sent.
An attempt to update/delete these hidden refs with an explicit
refspec, e.g. "git push origin :refs/hidden/22", is rejected. This
is not a new restriction. To the pusher, it would appear that there
is no such ref, so its push request will conclude with "Now that I
sent you all the data, it is time for you to update the refs. I saw
that the ref did not exist when I started pushing, and I want the
result to point at this commit". The receiving end will apply the
compare-and-swap rule to this request and rejects the push with
"Well, your update request conflicts with somebody else; I see there
is such a ref.", which is the right thing to do. Otherwise a push to
a hidden ref will always be "the last one wins", which is not a good
default.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-01-19 00:08:30 +00:00
|
|
|
for configsection in transfer uploadpack
|
|
|
|
do
|
|
|
|
test_expect_success "Hide some refs with $configsection.hiderefs" '
|
|
|
|
test_config $configsection.hiderefs refs/tags &&
|
|
|
|
git ls-remote . >actual &&
|
|
|
|
test_unconfig $configsection.hiderefs &&
|
2020-03-26 08:27:50 +00:00
|
|
|
git ls-remote . >expect.raw &&
|
|
|
|
sed -e "/ refs\/tags\//d" expect.raw >expect &&
|
upload/receive-pack: allow hiding ref hierarchies
A repository may have refs that are only used for its internal
bookkeeping purposes that should not be exposed to the others that
come over the network.
Teach upload-pack to omit some refs from its initial advertisement
by paying attention to the uploadpack.hiderefs multi-valued
configuration variable. Do the same to receive-pack via the
receive.hiderefs variable. As a convenient short-hand, allow using
transfer.hiderefs to set the value to both of these variables.
Any ref that is under the hierarchies listed on the value of these
variable is excluded from responses to requests made by "ls-remote",
"fetch", etc. (for upload-pack) and "push" (for receive-pack).
Because these hidden refs do not count as OUR_REF, an attempt to
fetch objects at the tip of them will be rejected, and because these
refs do not get advertised, "git push :" will not see local branches
that have the same name as them as "matching" ones to be sent.
An attempt to update/delete these hidden refs with an explicit
refspec, e.g. "git push origin :refs/hidden/22", is rejected. This
is not a new restriction. To the pusher, it would appear that there
is no such ref, so its push request will conclude with "Now that I
sent you all the data, it is time for you to update the refs. I saw
that the ref did not exist when I started pushing, and I want the
result to point at this commit". The receiving end will apply the
compare-and-swap rule to this request and rejects the push with
"Well, your update request conflicts with somebody else; I see there
is such a ref.", which is the right thing to do. Otherwise a push to
a hidden ref will always be "the last one wins", which is not a good
default.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-01-19 00:08:30 +00:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
refs: support negative transfer.hideRefs
If you hide a hierarchy of refs using the transfer.hideRefs
config, there is no way to later override that config to
"unhide" it. This patch implements a "negative" hide which
causes matches to immediately be marked as unhidden, even if
another match would hide it. We take care to apply the
matches in reverse-order from how they are fed to us by the
config machinery, as that lets our usual "last one wins"
config precedence work (and entries in .git/config, for
example, will override /etc/gitconfig).
So you can now do:
$ git config --system transfer.hideRefs refs/secret
$ git config transfer.hideRefs '!refs/secret/not-so-secret'
to hide refs/secret in all repos, except for one public bit
in one specific repo. Or you can even do:
$ git clone \
-u "git -c transfer.hiderefs="!refs/foo" upload-pack" \
remote:repo.git
to clone remote:repo.git, overriding any hiding it has
configured.
There are two alternatives that were considered and
rejected:
1. A generic config mechanism for removing an item from a
list. E.g.: (e.g., "[transfer] hideRefs -= refs/foo").
This is nice because it could apply to other
multi-valued config, as well. But it is not nearly as
flexible. There is no way to say:
[transfer]
hideRefs = refs/secret
hideRefs = refs/secret/not-so-secret
Having explicit negative specifications means we can
override previous entries, even if they are not the
same literal string.
2. Adding another variable to override some parts of
hideRefs (e.g., "exposeRefs").
This solves the problem from alternative (1), but it
cannot easily obey the normal config precedence,
because it would use two separate lists. For example:
[transfer]
hideRefs = refs/secret
exposeRefs = refs/secret/not-so-secret
hideRefs = refs/secret/not-so-secret/no-really-its-secret
With two lists, we have to apply the "expose" rules
first, and only then apply the "hide" rules. But that
does not match what the above config intends.
Of course we could internally parse that to a single
list, respecting the ordering, which saves us having to
invent the new "!" syntax. But using a single name
communicates to the user that the ordering _is_
important. And "!" is well-known for negation, and
should not appear at the beginning of a ref (it is
actually valid in a ref-name, but all entries here
should be fully-qualified, starting with "refs/").
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-07-28 20:23:26 +00:00
|
|
|
|
|
|
|
test_expect_success "Override hiding of $configsection.hiderefs" '
|
|
|
|
test_when_finished "test_unconfig $configsection.hiderefs" &&
|
|
|
|
git config --add $configsection.hiderefs refs/tags &&
|
|
|
|
git config --add $configsection.hiderefs "!refs/tags/magic" &&
|
|
|
|
git config --add $configsection.hiderefs refs/tags/magic/one &&
|
|
|
|
git ls-remote . >actual &&
|
|
|
|
grep refs/tags/magic/two actual &&
|
|
|
|
! grep refs/tags/magic/one actual
|
|
|
|
'
|
|
|
|
|
upload/receive-pack: allow hiding ref hierarchies
A repository may have refs that are only used for its internal
bookkeeping purposes that should not be exposed to the others that
come over the network.
Teach upload-pack to omit some refs from its initial advertisement
by paying attention to the uploadpack.hiderefs multi-valued
configuration variable. Do the same to receive-pack via the
receive.hiderefs variable. As a convenient short-hand, allow using
transfer.hiderefs to set the value to both of these variables.
Any ref that is under the hierarchies listed on the value of these
variable is excluded from responses to requests made by "ls-remote",
"fetch", etc. (for upload-pack) and "push" (for receive-pack).
Because these hidden refs do not count as OUR_REF, an attempt to
fetch objects at the tip of them will be rejected, and because these
refs do not get advertised, "git push :" will not see local branches
that have the same name as them as "matching" ones to be sent.
An attempt to update/delete these hidden refs with an explicit
refspec, e.g. "git push origin :refs/hidden/22", is rejected. This
is not a new restriction. To the pusher, it would appear that there
is no such ref, so its push request will conclude with "Now that I
sent you all the data, it is time for you to update the refs. I saw
that the ref did not exist when I started pushing, and I want the
result to point at this commit". The receiving end will apply the
compare-and-swap rule to this request and rejects the push with
"Well, your update request conflicts with somebody else; I see there
is such a ref.", which is the right thing to do. Otherwise a push to
a hidden ref will always be "the last one wins", which is not a good
default.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-01-19 00:08:30 +00:00
|
|
|
done
|
|
|
|
|
refs: support negative transfer.hideRefs
If you hide a hierarchy of refs using the transfer.hideRefs
config, there is no way to later override that config to
"unhide" it. This patch implements a "negative" hide which
causes matches to immediately be marked as unhidden, even if
another match would hide it. We take care to apply the
matches in reverse-order from how they are fed to us by the
config machinery, as that lets our usual "last one wins"
config precedence work (and entries in .git/config, for
example, will override /etc/gitconfig).
So you can now do:
$ git config --system transfer.hideRefs refs/secret
$ git config transfer.hideRefs '!refs/secret/not-so-secret'
to hide refs/secret in all repos, except for one public bit
in one specific repo. Or you can even do:
$ git clone \
-u "git -c transfer.hiderefs="!refs/foo" upload-pack" \
remote:repo.git
to clone remote:repo.git, overriding any hiding it has
configured.
There are two alternatives that were considered and
rejected:
1. A generic config mechanism for removing an item from a
list. E.g.: (e.g., "[transfer] hideRefs -= refs/foo").
This is nice because it could apply to other
multi-valued config, as well. But it is not nearly as
flexible. There is no way to say:
[transfer]
hideRefs = refs/secret
hideRefs = refs/secret/not-so-secret
Having explicit negative specifications means we can
override previous entries, even if they are not the
same literal string.
2. Adding another variable to override some parts of
hideRefs (e.g., "exposeRefs").
This solves the problem from alternative (1), but it
cannot easily obey the normal config precedence,
because it would use two separate lists. For example:
[transfer]
hideRefs = refs/secret
exposeRefs = refs/secret/not-so-secret
hideRefs = refs/secret/not-so-secret/no-really-its-secret
With two lists, we have to apply the "expose" rules
first, and only then apply the "hide" rules. But that
does not match what the above config intends.
Of course we could internally parse that to a single
list, respecting the ordering, which saves us having to
invent the new "!" syntax. But using a single name
communicates to the user that the ordering _is_
important. And "!" is well-known for negation, and
should not appear at the beginning of a ref (it is
actually valid in a ref-name, but all entries here
should be fully-qualified, starting with "refs/").
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-07-28 20:23:26 +00:00
|
|
|
test_expect_success 'overrides work between mixed transfer/upload-pack hideRefs' '
|
|
|
|
test_config uploadpack.hiderefs refs/tags &&
|
|
|
|
test_config transfer.hiderefs "!refs/tags/magic" &&
|
|
|
|
git ls-remote . >actual &&
|
|
|
|
grep refs/tags/magic actual
|
|
|
|
'
|
|
|
|
|
2018-12-18 12:47:50 +00:00
|
|
|
test_expect_success 'protocol v2 supports hiderefs' '
|
|
|
|
test_config uploadpack.hiderefs refs/tags &&
|
|
|
|
git -c protocol.version=2 ls-remote . >actual &&
|
|
|
|
! grep refs/tags actual
|
|
|
|
'
|
|
|
|
|
2016-01-18 23:20:50 +00:00
|
|
|
test_expect_success 'ls-remote --symref' '
|
2018-05-12 08:45:23 +00:00
|
|
|
git fetch origin &&
|
2023-04-14 21:25:13 +00:00
|
|
|
echo "ref: refs/heads/main HEAD" >expect.v2 &&
|
2020-03-26 08:27:49 +00:00
|
|
|
generate_references \
|
|
|
|
HEAD \
|
2023-04-14 21:25:13 +00:00
|
|
|
refs/heads/main >>expect.v2 &&
|
|
|
|
echo "ref: refs/remotes/origin/main refs/remotes/origin/HEAD" >>expect.v2 &&
|
2020-03-26 08:27:49 +00:00
|
|
|
oid=$(git rev-parse HEAD) &&
|
2023-04-14 21:25:13 +00:00
|
|
|
echo "$oid refs/remotes/origin/HEAD" >>expect.v2 &&
|
2020-03-26 08:27:49 +00:00
|
|
|
generate_references \
|
2020-11-18 23:44:32 +00:00
|
|
|
refs/remotes/origin/main \
|
2020-03-26 08:27:49 +00:00
|
|
|
refs/tags/mark \
|
|
|
|
refs/tags/mark1.1 \
|
|
|
|
refs/tags/mark1.10 \
|
2023-04-14 21:25:13 +00:00
|
|
|
refs/tags/mark1.2 >>expect.v2 &&
|
|
|
|
# v0 does not show non-HEAD symrefs
|
|
|
|
grep -v "ref: refs/remotes" <expect.v2 >expect.v0 &&
|
|
|
|
git -c protocol.version=0 ls-remote --symref >actual.v0 &&
|
|
|
|
test_cmp expect.v0 actual.v0 &&
|
|
|
|
git -c protocol.version=2 ls-remote --symref >actual.v2 &&
|
|
|
|
test_cmp expect.v2 actual.v2
|
2016-01-18 23:20:50 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'ls-remote with filtered symref (refname)' '
|
2019-12-21 19:49:30 +00:00
|
|
|
rev=$(git rev-parse HEAD) &&
|
|
|
|
cat >expect <<-EOF &&
|
2020-11-18 23:44:32 +00:00
|
|
|
ref: refs/heads/main HEAD
|
2019-12-21 19:49:30 +00:00
|
|
|
$rev HEAD
|
2016-01-18 23:20:50 +00:00
|
|
|
EOF
|
t5512: allow any protocol version for filtered symref test
We have a test that checks that ls-remote, when asked only about HEAD,
will report the HEAD symref, and not others. This was marked to always
run with the v0 protocol by b2f73b70b2 (t5512: compensate for v0 only
sending HEAD symrefs, 2019-02-25).
But in v0 this test is doing nothing! For v0, upload-pack only reports
the HEAD symref anyway, so we'd never have any other symref to report.
For v2, it is useful; we learn about all symrefs (and the test repo has
multiple), so this demonstrates that we correctly avoid showing them.
We could perhaps mark this to test explicitly with v2, but since that is
the default these days, it's sufficient to just run ls-remote without
any protocol specification. It still passes if somebody does an explicit
GIT_TEST_PROTOCOL_VERSION=0; it's just testing less.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-04-14 21:25:16 +00:00
|
|
|
git ls-remote --symref . HEAD >actual &&
|
2016-01-18 23:20:50 +00:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
t5512: test "ls-remote --heads --symref" filtering with v0 and v2
We have two overlapping tests for checking the behavior of "ls-remote
--symref" when filtering output. The first test checks that using
"--heads" will omit the symref for HEAD (since we don't print anything
about HEAD at all), but still prints other symrefs.
This has been marked as expecting failure since it was added in
99c08d4eb2 (ls-remote: add support for showing symrefs, 2016-01-19).
That's because back then, we only had the v0 protocol, and it only
reported on the HEAD symref, not others. But these days we have v2,
which does exactly what the test wants. It would even have started
unexpectedly passing when we switched to v2 by default, except that
b2f73b70b2 (t5512: compensate for v0 only sending HEAD symrefs,
2019-02-25) over-zealously marked it to run only in v0 mode.
So let's run it with both protocol versions, and adjust the expected
output for each. It passes in v2 without modification. In v0 mode, we'll
drop the extra symref, but this is still testing something useful: it
ensures that we do omit HEAD.
The test after this checks "--heads" again, this time using the expected
v0 output. That's now redundant. It also checks that limiting with a
pattern like "refs/heads/*" works similarly, but that's redundant with a
test earlier in the script which limits by HEAD (again, back then the
"HEAD" test was less interesting because there were no other symrefs to
omit, but in a modern v2 world, there are). So we can just delete that
second test entirely.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-04-14 21:25:18 +00:00
|
|
|
test_expect_success 'ls-remote with filtered symref (--heads)' '
|
2016-01-18 23:20:50 +00:00
|
|
|
git symbolic-ref refs/heads/foo refs/tags/mark &&
|
t5512: test "ls-remote --heads --symref" filtering with v0 and v2
We have two overlapping tests for checking the behavior of "ls-remote
--symref" when filtering output. The first test checks that using
"--heads" will omit the symref for HEAD (since we don't print anything
about HEAD at all), but still prints other symrefs.
This has been marked as expecting failure since it was added in
99c08d4eb2 (ls-remote: add support for showing symrefs, 2016-01-19).
That's because back then, we only had the v0 protocol, and it only
reported on the HEAD symref, not others. But these days we have v2,
which does exactly what the test wants. It would even have started
unexpectedly passing when we switched to v2 by default, except that
b2f73b70b2 (t5512: compensate for v0 only sending HEAD symrefs,
2019-02-25) over-zealously marked it to run only in v0 mode.
So let's run it with both protocol versions, and adjust the expected
output for each. It passes in v2 without modification. In v0 mode, we'll
drop the extra symref, but this is still testing something useful: it
ensures that we do omit HEAD.
The test after this checks "--heads" again, this time using the expected
v0 output. That's now redundant. It also checks that limiting with a
pattern like "refs/heads/*" works similarly, but that's redundant with a
test earlier in the script which limits by HEAD (again, back then the
"HEAD" test was less interesting because there were no other symrefs to
omit, but in a modern v2 world, there are). So we can just delete that
second test entirely.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-04-14 21:25:18 +00:00
|
|
|
cat >expect.v2 <<-EOF &&
|
2016-01-18 23:20:50 +00:00
|
|
|
ref: refs/tags/mark refs/heads/foo
|
2019-12-21 19:49:30 +00:00
|
|
|
$rev refs/heads/foo
|
2020-11-18 23:44:32 +00:00
|
|
|
$rev refs/heads/main
|
2016-01-18 23:20:50 +00:00
|
|
|
EOF
|
t5512: test "ls-remote --heads --symref" filtering with v0 and v2
We have two overlapping tests for checking the behavior of "ls-remote
--symref" when filtering output. The first test checks that using
"--heads" will omit the symref for HEAD (since we don't print anything
about HEAD at all), but still prints other symrefs.
This has been marked as expecting failure since it was added in
99c08d4eb2 (ls-remote: add support for showing symrefs, 2016-01-19).
That's because back then, we only had the v0 protocol, and it only
reported on the HEAD symref, not others. But these days we have v2,
which does exactly what the test wants. It would even have started
unexpectedly passing when we switched to v2 by default, except that
b2f73b70b2 (t5512: compensate for v0 only sending HEAD symrefs,
2019-02-25) over-zealously marked it to run only in v0 mode.
So let's run it with both protocol versions, and adjust the expected
output for each. It passes in v2 without modification. In v0 mode, we'll
drop the extra symref, but this is still testing something useful: it
ensures that we do omit HEAD.
The test after this checks "--heads" again, this time using the expected
v0 output. That's now redundant. It also checks that limiting with a
pattern like "refs/heads/*" works similarly, but that's redundant with a
test earlier in the script which limits by HEAD (again, back then the
"HEAD" test was less interesting because there were no other symrefs to
omit, but in a modern v2 world, there are). So we can just delete that
second test entirely.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-04-14 21:25:18 +00:00
|
|
|
grep -v "^ref: refs/tags/" <expect.v2 >expect.v0 &&
|
|
|
|
git -c protocol.version=0 ls-remote --symref --heads . >actual.v0 &&
|
|
|
|
test_cmp expect.v0 actual.v0 &&
|
|
|
|
git -c protocol.version=2 ls-remote --symref --heads . >actual.v2 &&
|
|
|
|
test_cmp expect.v2 actual.v2
|
2016-01-18 23:20:50 +00:00
|
|
|
'
|
|
|
|
|
v0 protocol: fix sha1/sha256 confusion for capabilities^{}
Commit eb398797cd (connect: advertized capability is not a ref,
2016-09-09) added support for an upload-pack server responding with:
0000000000000000000000000000000000000000 capabilities^{}
followed by a NUL and the actual capabilities. We correctly parse the
oid using the packet_reader's hash_algo field, but then we compare it to
null_oid(), which will instead use our current repo's default algorithm.
If we're defaulting to sha256 locally but the other side is sha1, they
won't match and we'll fail to parse the line (and thus die()).
This can cause a test failure when the suite is run with
GIT_TEST_DEFAULT_HASH=sha256, and we even do so regularly via the
linux-sha256 CI job. But since the test requires JGit to run, it's
usually just skipped, and nobody noticed the problem.
The reason the original patch used JGit is that Git itself does not ever
produce such a line via upload-pack; the feature was added to fix a
real-world problem when interacting with JGit. That was good for
verifying that the incompatibility was fixed, but it's not a good
regression test:
- hardly anybody runs it, because you have to have jgit installed;
hence this bug going unnoticed
- we're depending on jgit's behavior for the test to do anything
useful. In particular, this behavior is only relevant to the v0
protocol, but these days we ask for the v2 protocol by default. So
for modern jgit, this is probably testing nothing.
- it's complicated and slow. We had to do some fifo trickery to handle
races, and this one test makes up 40% of the runtime of the total
script.
Instead, let's just hard-code the response that's of interest to us.
That will test exactly what we want for every run, and reveals the bug
when run in sha256 mode. And of course we'll fix the actual bug by using
the correct hash_algo struct.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-04-14 21:25:11 +00:00
|
|
|
test_expect_success 'indicate no refs in v0 standards-compliant empty remote' '
|
|
|
|
# Git does not produce an output like this, but it does match the
|
|
|
|
# standard and is produced by other implementations like JGit. So
|
|
|
|
# hard-code the case we care about.
|
|
|
|
#
|
|
|
|
# The actual capabilities do not matter; there are none that would
|
|
|
|
# change how ls-remote behaves.
|
|
|
|
oid=0000000000000000000000000000000000000000 &&
|
|
|
|
test-tool pkt-line pack >input.q <<-EOF &&
|
|
|
|
$oid capabilities^{}Qcaps-go-here
|
|
|
|
0000
|
|
|
|
EOF
|
|
|
|
q_to_nul <input.q >input &&
|
connect: advertized capability is not a ref
When cloning an empty repository served by standard git, "git clone" produces
the following reassuring message:
$ git clone git://localhost/tmp/empty
Cloning into 'empty'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.
Meanwhile when cloning an empty repository served by JGit, the output is more
haphazard:
$ git clone git://localhost/tmp/empty
Cloning into 'empty'...
Checking connectivity... done.
warning: remote HEAD refers to nonexistent ref, unable to checkout.
This is a common command to run immediately after creating a remote repository
as preparation for adding content to populate it and pushing. The warning is
confusing and needlessly worrying.
The cause is that, since v3.1.0.201309270735-rc1~22 (Advertise capabilities
with no refs in upload service., 2013-08-08), JGit's ref advertisement includes
a ref named capabilities^{} to advertise its capabilities on, while git's ref
advertisement is empty in this case. This allows the client to learn about the
server's capabilities and is needed, for example, for fetch-by-sha1 to work
when no refs are advertised.
This also affects "ls-remote". For example, against an empty repository served
by JGit:
$ git ls-remote git://localhost/tmp/empty
0000000000000000000000000000000000000000 capabilities^{}
Git advertises the same capabilities^{} ref in its ref advertisement for push
but since it never did so for fetch, the client didn't need to handle this
case. Handle it.
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Helped-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-09 17:36:30 +00:00
|
|
|
|
|
|
|
# --exit-code asks the command to exit with 2 when no
|
|
|
|
# matching refs are found.
|
v0 protocol: fix sha1/sha256 confusion for capabilities^{}
Commit eb398797cd (connect: advertized capability is not a ref,
2016-09-09) added support for an upload-pack server responding with:
0000000000000000000000000000000000000000 capabilities^{}
followed by a NUL and the actual capabilities. We correctly parse the
oid using the packet_reader's hash_algo field, but then we compare it to
null_oid(), which will instead use our current repo's default algorithm.
If we're defaulting to sha256 locally but the other side is sha1, they
won't match and we'll fail to parse the line (and thus die()).
This can cause a test failure when the suite is run with
GIT_TEST_DEFAULT_HASH=sha256, and we even do so regularly via the
linux-sha256 CI job. But since the test requires JGit to run, it's
usually just skipped, and nobody noticed the problem.
The reason the original patch used JGit is that Git itself does not ever
produce such a line via upload-pack; the feature was added to fix a
real-world problem when interacting with JGit. That was good for
verifying that the incompatibility was fixed, but it's not a good
regression test:
- hardly anybody runs it, because you have to have jgit installed;
hence this bug going unnoticed
- we're depending on jgit's behavior for the test to do anything
useful. In particular, this behavior is only relevant to the v0
protocol, but these days we ask for the v2 protocol by default. So
for modern jgit, this is probably testing nothing.
- it's complicated and slow. We had to do some fifo trickery to handle
races, and this one test makes up 40% of the runtime of the total
script.
Instead, let's just hard-code the response that's of interest to us.
That will test exactly what we want for every run, and reveals the bug
when run in sha256 mode. And of course we'll fix the actual bug by using
the correct hash_algo struct.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-04-14 21:25:11 +00:00
|
|
|
test_expect_code 2 git ls-remote --exit-code --upload-pack=./cat-input .
|
connect: advertized capability is not a ref
When cloning an empty repository served by standard git, "git clone" produces
the following reassuring message:
$ git clone git://localhost/tmp/empty
Cloning into 'empty'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.
Meanwhile when cloning an empty repository served by JGit, the output is more
haphazard:
$ git clone git://localhost/tmp/empty
Cloning into 'empty'...
Checking connectivity... done.
warning: remote HEAD refers to nonexistent ref, unable to checkout.
This is a common command to run immediately after creating a remote repository
as preparation for adding content to populate it and pushing. The warning is
confusing and needlessly worrying.
The cause is that, since v3.1.0.201309270735-rc1~22 (Advertise capabilities
with no refs in upload service., 2013-08-08), JGit's ref advertisement includes
a ref named capabilities^{} to advertise its capabilities on, while git's ref
advertisement is empty in this case. This allows the client to learn about the
server's capabilities and is needed, for example, for fetch-by-sha1 to work
when no refs are advertised.
This also affects "ls-remote". For example, against an empty repository served
by JGit:
$ git ls-remote git://localhost/tmp/empty
0000000000000000000000000000000000000000 capabilities^{}
Git advertises the same capabilities^{} ref in its ref advertisement for push
but since it never did so for fetch, the client didn't need to handle this
case. Handle it.
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Helped-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-09 17:36:30 +00:00
|
|
|
'
|
2016-01-18 23:20:50 +00:00
|
|
|
|
2017-02-14 20:33:28 +00:00
|
|
|
test_expect_success 'ls-remote works outside repository' '
|
|
|
|
# It is important for this repo to be inside the nongit
|
|
|
|
# area, as we want a repo name that does not include
|
|
|
|
# slashes (because those inhibit some of our configuration
|
|
|
|
# lookups).
|
|
|
|
nongit git init --bare dst.git &&
|
|
|
|
nongit git ls-remote dst.git
|
|
|
|
'
|
|
|
|
|
2018-11-14 12:27:25 +00:00
|
|
|
test_expect_success 'ls-remote --sort fails gracefully outside repository' '
|
|
|
|
# Use a sort key that requires access to the referenced objects.
|
|
|
|
nongit test_must_fail git ls-remote --sort=authordate "$TRASH_DIRECTORY" 2>err &&
|
|
|
|
test_i18ngrep "^fatal: not a git repository, but the field '\''authordate'\'' requires access to object data" err
|
|
|
|
'
|
|
|
|
|
2018-10-31 04:24:05 +00:00
|
|
|
test_expect_success 'ls-remote patterns work with all protocol versions' '
|
|
|
|
git for-each-ref --format="%(objectname) %(refname)" \
|
2020-11-18 23:44:32 +00:00
|
|
|
refs/heads/main refs/remotes/origin/main >expect &&
|
2023-04-14 21:24:19 +00:00
|
|
|
git -c protocol.version=0 ls-remote . main >actual.v0 &&
|
|
|
|
test_cmp expect actual.v0 &&
|
2020-11-18 23:44:32 +00:00
|
|
|
git -c protocol.version=2 ls-remote . main >actual.v2 &&
|
2018-10-31 04:24:05 +00:00
|
|
|
test_cmp expect actual.v2
|
|
|
|
'
|
|
|
|
|
2018-10-31 04:24:42 +00:00
|
|
|
test_expect_success 'ls-remote prefixes work with all protocol versions' '
|
|
|
|
git for-each-ref --format="%(objectname) %(refname)" \
|
|
|
|
refs/heads/ refs/tags/ >expect &&
|
2023-04-14 21:24:19 +00:00
|
|
|
git -c protocol.version=0 ls-remote --heads --tags . >actual.v0 &&
|
|
|
|
test_cmp expect actual.v0 &&
|
2018-10-31 04:24:42 +00:00
|
|
|
git -c protocol.version=2 ls-remote --heads --tags . >actual.v2 &&
|
|
|
|
test_cmp expect actual.v2
|
|
|
|
'
|
|
|
|
|
v0 protocol: fix infinite loop when parsing multi-valued capabilities
If Git's client-side parsing of an upload-pack response (so git-fetch or
ls-remote) sees multiple instances of a single capability, it can enter
an infinite loop due to a bug in advancing the "offset" parameter in the
parser.
This bug can't happen between a client and server of the same Git
version. The client bug is in parse_feature_value() when the caller
passes in an offset parameter. And that only happens when the v0
protocol is parsing "symref" and "object-format" capabilities, via
next_server_feature_value(). But Git has never produced multiple
object-format capabilities, and it stopped producing multiple symref
values in d007dbf7d6 (Revert "upload-pack: send non-HEAD symbolic refs",
2013-11-18).
However, upload-pack did produce multiple symref entries for a while,
and they are valid. Plus other implementations, such as Dulwich will
still do so. So we should handle them. And even if we do not expect it,
it is obviously a bug for the parser to enter an infinite loop.
The bug itself is pretty simple. Commit 2c6a403d96 (connect: add
function to parse multiple v1 capability values, 2020-05-25) added the
"offset" parameter, which is used as both an in- and out-parameter. When
parsing the first "symref" capability, *offset will be 0 on input, and
after parsing the capability, we set *offset to an index just past the
value by taking a pointer difference "(value + end) - feature_list".
But on the second call, now *offset is set to that larger index, which
lets us skip past the first "symref" capability. However, we do so by
incrementing feature_list. That means our pointer difference is now too
small; it is counting from where we resumed parsing, not from the start
of the original feature_list pointer. And because we incremented
feature_list only inside our function, and not the caller, that
increment is lost next time the function is called.
One solution would be to account for those skipped bytes by incrementing
*offset, rather than assigning to it. But wait, there's more!
We also increment feature_list if we have a near-miss. Say we are
looking for "symref" and find "almost-symref". In that case we'll point
feature_list to the "y" in "almost-symref" and restart our search. But
that again means our offset won't be correct, as it won't account for
the bytes between the start of the string and that "y".
So instead, let's just record the beginning of the feature_list string
in a separate pointer that we never touch. That offset we take in and
return is meant to be using that point as a base, and now we'll do so
consistently.
Since the bug can't be reproduced using the current version of
git-upload-pack, we'll instead hard-code an input which triggers the
problem. Before this patch it loops forever re-parsing the second symref
entry. Now we check both that it finishes, and that it parses both
entries correctly (a case we could not test at all before).
We don't need to worry about testing v2 here; it communicates the
capabilities in a completely different way, and doesn't use this code at
all. There are tests earlier in t5512 that are meant to cover this (they
don't, but we'll address that in a future patch).
Reported-by: Jonas Haag <jonas@lophus.org>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-04-14 21:24:16 +00:00
|
|
|
test_expect_success 'v0 clients can handle multiple symrefs' '
|
|
|
|
# Modern versions of Git will not return multiple symref capabilities
|
|
|
|
# for v0, so we have to hard-code the response. Note that we will
|
|
|
|
# always use both v0 and object-format=sha1 here, as the hard-coded
|
|
|
|
# response reflects a server that only supports those.
|
|
|
|
oid=1234567890123456789012345678901234567890 &&
|
|
|
|
symrefs="symref=refs/remotes/origin/HEAD:refs/remotes/origin/main" &&
|
|
|
|
symrefs="$symrefs symref=HEAD:refs/heads/main" &&
|
|
|
|
|
|
|
|
# Likewise we want to make sure our parser is not fooled by the string
|
|
|
|
# "symref" appearing as part of an earlier cap. But there is no way to
|
|
|
|
# do that via upload-pack, as arbitrary strings can appear only in a
|
|
|
|
# "symref" value itself (where we skip past the values as a whole)
|
|
|
|
# and "agent" (which always appears after "symref", so putting our
|
|
|
|
# parser in a confused state is less interesting).
|
|
|
|
caps="some other caps including a-fake-symref-cap" &&
|
|
|
|
|
|
|
|
test-tool pkt-line pack >input.q <<-EOF &&
|
|
|
|
$oid HEADQ$caps $symrefs
|
|
|
|
$oid refs/heads/main
|
|
|
|
$oid refs/remotes/origin/HEAD
|
|
|
|
$oid refs/remotes/origin/main
|
|
|
|
0000
|
|
|
|
EOF
|
|
|
|
q_to_nul <input.q >input &&
|
|
|
|
|
|
|
|
cat >expect <<-EOF &&
|
|
|
|
ref: refs/heads/main HEAD
|
|
|
|
$oid HEAD
|
|
|
|
$oid refs/heads/main
|
|
|
|
ref: refs/remotes/origin/main refs/remotes/origin/HEAD
|
|
|
|
$oid refs/remotes/origin/HEAD
|
|
|
|
$oid refs/remotes/origin/main
|
|
|
|
EOF
|
|
|
|
|
|
|
|
git ls-remote --symref --upload-pack=./cat-input . >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2007-11-07 01:29:20 +00:00
|
|
|
test_done
|