2011-07-21 20:10:54 +00:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='fetch/push involving ref namespaces'
|
2020-11-18 23:44:31 +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
|
|
|
|
|
2011-07-21 20:10:54 +00:00
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
test_expect_success setup '
|
2016-12-14 22:39:52 +00:00
|
|
|
git config --global protocol.ext.allow user &&
|
2011-07-21 20:10:54 +00:00
|
|
|
test_tick &&
|
|
|
|
git init original &&
|
|
|
|
(
|
|
|
|
cd original &&
|
|
|
|
echo 0 >count &&
|
|
|
|
git add count &&
|
|
|
|
test_commit 0 &&
|
|
|
|
echo 1 >count &&
|
|
|
|
git add count &&
|
|
|
|
test_commit 1 &&
|
|
|
|
git remote add pushee-namespaced "ext::git --namespace=namespace %s ../pushee" &&
|
|
|
|
git remote add pushee-unnamespaced ../pushee
|
|
|
|
) &&
|
|
|
|
commit0=$(cd original && git rev-parse HEAD^) &&
|
|
|
|
commit1=$(cd original && git rev-parse HEAD) &&
|
2020-02-23 18:57:09 +00:00
|
|
|
git init --bare pushee &&
|
2011-07-21 20:10:54 +00:00
|
|
|
git init puller
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'pushing into a repository using a ref namespace' '
|
|
|
|
(
|
|
|
|
cd original &&
|
2020-11-18 23:44:31 +00:00
|
|
|
git push pushee-namespaced main &&
|
2011-07-21 20:10:54 +00:00
|
|
|
git ls-remote pushee-namespaced >actual &&
|
2020-11-18 23:44:31 +00:00
|
|
|
printf "$commit1\trefs/heads/main\n" >expected &&
|
2011-07-21 20:10:54 +00:00
|
|
|
test_cmp expected actual &&
|
|
|
|
git push pushee-namespaced --tags &&
|
|
|
|
git ls-remote pushee-namespaced >actual &&
|
|
|
|
printf "$commit0\trefs/tags/0\n" >>expected &&
|
|
|
|
printf "$commit1\trefs/tags/1\n" >>expected &&
|
|
|
|
test_cmp expected actual &&
|
|
|
|
# Verify that the GIT_NAMESPACE environment variable works as well
|
|
|
|
GIT_NAMESPACE=namespace git ls-remote "ext::git %s ../pushee" >actual &&
|
|
|
|
test_cmp expected actual &&
|
|
|
|
# Verify that --namespace overrides GIT_NAMESPACE
|
|
|
|
GIT_NAMESPACE=garbage git ls-remote pushee-namespaced >actual &&
|
|
|
|
test_cmp expected actual &&
|
|
|
|
# Try a namespace with no content
|
|
|
|
git ls-remote "ext::git --namespace=garbage %s ../pushee" >actual &&
|
2018-08-19 21:57:24 +00:00
|
|
|
test_must_be_empty actual &&
|
2011-07-21 20:10:54 +00:00
|
|
|
git ls-remote pushee-unnamespaced >actual &&
|
|
|
|
sed -e "s|refs/|refs/namespaces/namespace/refs/|" expected >expected.unnamespaced &&
|
|
|
|
test_cmp expected.unnamespaced actual
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'pulling from a repository using a ref namespace' '
|
|
|
|
(
|
|
|
|
cd puller &&
|
|
|
|
git remote add -f pushee-namespaced "ext::git --namespace=namespace %s ../pushee" &&
|
|
|
|
git for-each-ref refs/ >actual &&
|
2020-11-18 23:44:31 +00:00
|
|
|
printf "$commit1 commit\trefs/remotes/pushee-namespaced/main\n" >expected &&
|
2011-07-21 20:10:54 +00:00
|
|
|
printf "$commit0 commit\trefs/tags/0\n" >>expected &&
|
|
|
|
printf "$commit1 commit\trefs/tags/1\n" >>expected &&
|
|
|
|
test_cmp expected actual
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
# This test with clone --mirror checks for possible regressions in clone
|
|
|
|
# or the machinery underneath it. It ensures that no future change
|
|
|
|
# causes clone to ignore refs in refs/namespaces/*. In particular, it
|
|
|
|
# protects against a regression caused by any future change to the refs
|
|
|
|
# machinery that might cause it to ignore refs outside of refs/heads/*
|
|
|
|
# or refs/tags/*. More generally, this test also checks the high-level
|
|
|
|
# functionality of using clone --mirror to back up a set of repos hosted
|
|
|
|
# in the namespaces of a single repo.
|
|
|
|
test_expect_success 'mirroring a repository using a ref namespace' '
|
|
|
|
git clone --mirror pushee mirror &&
|
|
|
|
(
|
|
|
|
cd mirror &&
|
|
|
|
git for-each-ref refs/ >actual &&
|
2020-11-18 23:44:31 +00:00
|
|
|
printf "$commit1 commit\trefs/namespaces/namespace/refs/heads/main\n" >expected &&
|
2011-07-21 20:10:54 +00:00
|
|
|
printf "$commit0 commit\trefs/namespaces/namespace/refs/tags/0\n" >>expected &&
|
|
|
|
printf "$commit1 commit\trefs/namespaces/namespace/refs/tags/1\n" >>expected &&
|
|
|
|
test_cmp expected actual
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2015-11-05 06:07:31 +00:00
|
|
|
test_expect_success 'hide namespaced refs with transfer.hideRefs' '
|
|
|
|
GIT_NAMESPACE=namespace \
|
|
|
|
git -C pushee -c transfer.hideRefs=refs/tags \
|
|
|
|
ls-remote "ext::git %s ." >actual &&
|
2020-11-18 23:44:31 +00:00
|
|
|
printf "$commit1\trefs/heads/main\n" >expected &&
|
2015-11-05 06:07:31 +00:00
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'check that transfer.hideRefs does not match unstripped refs' '
|
|
|
|
GIT_NAMESPACE=namespace \
|
|
|
|
git -C pushee -c transfer.hideRefs=refs/namespaces/namespace/refs/tags \
|
|
|
|
ls-remote "ext::git %s ." >actual &&
|
2020-11-18 23:44:31 +00:00
|
|
|
printf "$commit1\trefs/heads/main\n" >expected &&
|
2015-11-05 06:07:31 +00:00
|
|
|
printf "$commit0\trefs/tags/0\n" >>expected &&
|
|
|
|
printf "$commit1\trefs/tags/1\n" >>expected &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'hide full refs with transfer.hideRefs' '
|
|
|
|
GIT_NAMESPACE=namespace \
|
|
|
|
git -C pushee -c transfer.hideRefs="^refs/namespaces/namespace/refs/tags" \
|
|
|
|
ls-remote "ext::git %s ." >actual &&
|
2020-11-18 23:44:31 +00:00
|
|
|
printf "$commit1\trefs/heads/main\n" >expected &&
|
2015-11-05 06:07:31 +00:00
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'try to update a hidden ref' '
|
2020-11-18 23:44:31 +00:00
|
|
|
test_config -C pushee transfer.hideRefs refs/heads/main &&
|
|
|
|
test_must_fail git -C original push pushee-namespaced main
|
2015-11-05 06:07:31 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'try to update a ref that is not hidden' '
|
2020-11-18 23:44:31 +00:00
|
|
|
test_config -C pushee transfer.hideRefs refs/namespaces/namespace/refs/heads/main &&
|
|
|
|
git -C original push pushee-namespaced main
|
2015-11-05 06:07:31 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'try to update a hidden full ref' '
|
2020-11-18 23:44:31 +00:00
|
|
|
test_config -C pushee transfer.hideRefs "^refs/namespaces/namespace/refs/heads/main" &&
|
|
|
|
test_must_fail git -C original push pushee-namespaced main
|
2015-11-05 06:07:31 +00:00
|
|
|
'
|
|
|
|
|
upload-pack: strip namespace from symref data
Since 7171d8c15f (upload-pack: send symbolic ref information as
capability, 2013-09-17), we've sent cloning and fetching clients special
information about which branch HEAD is pointing to, so that they don't
have to guess based on matching up commit ids.
However, this feature has never worked properly with the GIT_NAMESPACE
feature. Because upload-pack uses head_ref_namespaced(find_symref), we
do find and report on refs/namespaces/foo/HEAD instead of the actual
HEAD of the repo. This makes sense, since the branch pointed to by the
top-level HEAD may not be advertised at all. But we do two things wrong:
1. We report the full name refs/namespaces/foo/HEAD, instead of just
HEAD. Meaning no client is going to bother doing anything with that
symref, since we're not otherwise advertising it.
2. We report the symref destination using its full name (e.g.,
refs/namespaces/foo/refs/heads/master). That's similarly useless to
the client, who only saw "refs/heads/master" in the advertisement.
We should be stripping the namespace prefix off of both places (which
this patch fixes).
Likely nobody noticed because we tend to do the right thing anyway. Bug
(1) means that we said nothing about HEAD (just refs/namespace/foo/HEAD).
And so the client half of the code, from a45b5f0552 (connect: annotate
refs with their symref information in get_remote_head(), 2013-09-17),
does not annotate HEAD, and we use the fallback in guess_remote_head(),
matching refs by object id. Which is usually right. It only falls down
in ambiguous cases, like the one laid out in the included test.
This also means that we don't have to worry about breaking anybody who
was putting pre-stripped names into their namespace symrefs when we fix
bug (2). Because of bug (1), nobody would have been using the symref we
advertised in the first place (not to mention that those symrefs would
have appeared broken for any non-namespaced access).
Note that we have separate fixes here for the v0 and v2 protocols. The
symref advertisement moved in v2 to be a part of the ls-refs command.
This actually gets part (1) right, since the symref annotation
piggy-backs on the existing ref advertisement, which is properly
stripped. But it still needs a fix for part (2). The included tests
cover both protocols.
Reported-by: Bryan Turner <bturner@atlassian.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-05-23 06:11:21 +00:00
|
|
|
test_expect_success 'set up ambiguous HEAD' '
|
|
|
|
git init ambiguous &&
|
|
|
|
(
|
|
|
|
cd ambiguous &&
|
|
|
|
git commit --allow-empty -m foo &&
|
|
|
|
git update-ref refs/namespaces/ns/refs/heads/one HEAD &&
|
|
|
|
git update-ref refs/namespaces/ns/refs/heads/two HEAD &&
|
|
|
|
git symbolic-ref refs/namespaces/ns/HEAD \
|
|
|
|
refs/namespaces/ns/refs/heads/two
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'clone chooses correct HEAD (v0)' '
|
|
|
|
GIT_NAMESPACE=ns git -c protocol.version=0 \
|
|
|
|
clone ambiguous ambiguous-v0 &&
|
|
|
|
echo refs/heads/two >expect &&
|
|
|
|
git -C ambiguous-v0 symbolic-ref HEAD >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'clone chooses correct HEAD (v2)' '
|
|
|
|
GIT_NAMESPACE=ns git -c protocol.version=2 \
|
|
|
|
clone ambiguous ambiguous-v2 &&
|
|
|
|
echo refs/heads/two >expect &&
|
|
|
|
git -C ambiguous-v2 symbolic-ref HEAD >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
receive.denyCurrentBranch: respect all worktrees
The receive.denyCurrentBranch config option controls what happens if
you push to a branch that is checked out into a non-bare repository.
By default, it rejects it. It can be disabled via `ignore` or `warn`.
Another yet trickier option is `updateInstead`.
However, this setting was forgotten when the git worktree command was
introduced: only the main worktree's current branch is respected.
With this change, all worktrees are respected.
That change also leads to revealing another bug,
i.e. `receive.denyCurrentBranch = true` was ignored when pushing into a
non-bare repository's unborn current branch using ref namespaces. As
`is_ref_checked_out()` returns 0 which means `receive-pack` does not get
into conditional statement to switch `deny_current_branch` accordingly
(ignore, warn, refuse, unconfigured, updateInstead).
receive.denyCurrentBranch uses the function `refs_resolve_ref_unsafe()`
(called via `resolve_refdup()`) to resolve the symbolic ref HEAD, but
that function fails when HEAD does not point at a valid commit.
As we replace the call to `refs_resolve_ref_unsafe()` with
`find_shared_symref()`, which has no problem finding the worktree for a
given branch even if it is unborn yet, this bug is fixed at the same
time: receive.denyCurrentBranch now also handles worktrees with unborn
branches as intended even while using ref namespaces.
Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Hariom Verma <hariom18599@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-23 18:57:10 +00:00
|
|
|
test_expect_success 'denyCurrentBranch and unborn branch with ref namespace' '
|
|
|
|
(
|
|
|
|
cd original &&
|
|
|
|
git init unborn &&
|
|
|
|
git remote add unborn-namespaced "ext::git --namespace=namespace %s unborn" &&
|
2020-11-18 23:44:31 +00:00
|
|
|
test_must_fail git push unborn-namespaced HEAD:main &&
|
receive.denyCurrentBranch: respect all worktrees
The receive.denyCurrentBranch config option controls what happens if
you push to a branch that is checked out into a non-bare repository.
By default, it rejects it. It can be disabled via `ignore` or `warn`.
Another yet trickier option is `updateInstead`.
However, this setting was forgotten when the git worktree command was
introduced: only the main worktree's current branch is respected.
With this change, all worktrees are respected.
That change also leads to revealing another bug,
i.e. `receive.denyCurrentBranch = true` was ignored when pushing into a
non-bare repository's unborn current branch using ref namespaces. As
`is_ref_checked_out()` returns 0 which means `receive-pack` does not get
into conditional statement to switch `deny_current_branch` accordingly
(ignore, warn, refuse, unconfigured, updateInstead).
receive.denyCurrentBranch uses the function `refs_resolve_ref_unsafe()`
(called via `resolve_refdup()`) to resolve the symbolic ref HEAD, but
that function fails when HEAD does not point at a valid commit.
As we replace the call to `refs_resolve_ref_unsafe()` with
`find_shared_symref()`, which has no problem finding the worktree for a
given branch even if it is unborn yet, this bug is fixed at the same
time: receive.denyCurrentBranch now also handles worktrees with unborn
branches as intended even while using ref namespaces.
Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Hariom Verma <hariom18599@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-23 18:57:10 +00:00
|
|
|
git -C unborn config receive.denyCurrentBranch updateInstead &&
|
2020-11-18 23:44:31 +00:00
|
|
|
git push unborn-namespaced HEAD:main
|
receive.denyCurrentBranch: respect all worktrees
The receive.denyCurrentBranch config option controls what happens if
you push to a branch that is checked out into a non-bare repository.
By default, it rejects it. It can be disabled via `ignore` or `warn`.
Another yet trickier option is `updateInstead`.
However, this setting was forgotten when the git worktree command was
introduced: only the main worktree's current branch is respected.
With this change, all worktrees are respected.
That change also leads to revealing another bug,
i.e. `receive.denyCurrentBranch = true` was ignored when pushing into a
non-bare repository's unborn current branch using ref namespaces. As
`is_ref_checked_out()` returns 0 which means `receive-pack` does not get
into conditional statement to switch `deny_current_branch` accordingly
(ignore, warn, refuse, unconfigured, updateInstead).
receive.denyCurrentBranch uses the function `refs_resolve_ref_unsafe()`
(called via `resolve_refdup()`) to resolve the symbolic ref HEAD, but
that function fails when HEAD does not point at a valid commit.
As we replace the call to `refs_resolve_ref_unsafe()` with
`find_shared_symref()`, which has no problem finding the worktree for a
given branch even if it is unborn yet, this bug is fixed at the same
time: receive.denyCurrentBranch now also handles worktrees with unborn
branches as intended even while using ref namespaces.
Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Hariom Verma <hariom18599@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-23 18:57:10 +00:00
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2011-07-21 20:10:54 +00:00
|
|
|
test_done
|