mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
![Jeff King](/assets/img/avatar_default.png)
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>
167 lines
4.2 KiB
Bash
Executable file
167 lines
4.2 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
test_description='git ls-remote'
|
|
|
|
. ./test-lib.sh
|
|
|
|
test_expect_success setup '
|
|
>file &&
|
|
git add file &&
|
|
test_tick &&
|
|
git commit -m initial &&
|
|
git tag mark &&
|
|
git show-ref --tags -d | sed -e "s/ / /" >expected.tag &&
|
|
(
|
|
echo "$(git rev-parse HEAD) HEAD"
|
|
git show-ref -d | sed -e "s/ / /"
|
|
) >expected.all &&
|
|
|
|
git remote add self "$(pwd)/.git"
|
|
'
|
|
|
|
test_expect_success 'ls-remote --tags .git' '
|
|
git ls-remote --tags .git >actual &&
|
|
test_cmp expected.tag actual
|
|
'
|
|
|
|
test_expect_success 'ls-remote .git' '
|
|
git ls-remote .git >actual &&
|
|
test_cmp expected.all actual
|
|
'
|
|
|
|
test_expect_success 'ls-remote --tags self' '
|
|
git ls-remote --tags self >actual &&
|
|
test_cmp expected.tag actual
|
|
'
|
|
|
|
test_expect_success 'ls-remote self' '
|
|
git ls-remote self >actual &&
|
|
test_cmp expected.all actual
|
|
'
|
|
|
|
test_expect_success 'dies when no remote specified and no default remotes found' '
|
|
test_must_fail git ls-remote
|
|
'
|
|
|
|
test_expect_success 'use "origin" when no remote specified' '
|
|
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 &&
|
|
test_cmp expected.all actual
|
|
'
|
|
|
|
test_expect_success 'suppress "From <url>" with -q' '
|
|
git ls-remote -q 2>actual_err &&
|
|
test_must_fail test_cmp exp_err actual_err
|
|
'
|
|
|
|
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 &&
|
|
echo "$(git rev-parse HEAD) HEAD"
|
|
git show-ref | sed -e "s/ / /"
|
|
) >exp &&
|
|
|
|
URL="other.git" &&
|
|
echo "From $URL" >exp_err &&
|
|
|
|
git remote add other $URL &&
|
|
git config branch.master.remote other &&
|
|
|
|
git ls-remote 2>actual_err >actual &&
|
|
test_cmp exp_err actual_err &&
|
|
test_cmp exp actual
|
|
'
|
|
|
|
test_expect_success 'confuses pattern as remote when no remote specified' '
|
|
cat >exp <<-\EOF &&
|
|
fatal: '\''refs*master'\'' does not appear to be a git repository
|
|
fatal: Could not read from remote repository.
|
|
|
|
Please make sure you have the correct access rights
|
|
and the repository exists.
|
|
EOF
|
|
#
|
|
# 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>.
|
|
# We could just as easily have used "master"; the "*" emphasizes its
|
|
# role as a pattern.
|
|
test_must_fail git ls-remote refs*master >actual 2>&1 &&
|
|
test_cmp exp actual
|
|
'
|
|
|
|
test_expect_success 'die with non-2 for wrong repository even with --exit-code' '
|
|
{
|
|
git ls-remote --exit-code ./no-such-repository
|
|
status=$?
|
|
} &&
|
|
test $status != 2 && test $status != 0
|
|
'
|
|
|
|
test_expect_success 'Report success even when nothing matches' '
|
|
git ls-remote other.git "refs/nsn/*" >actual &&
|
|
>expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'Report no-match with --exit-code' '
|
|
test_expect_code 2 git ls-remote --exit-code other.git "refs/nsn/*" >actual &&
|
|
>expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'Report match with --exit-code' '
|
|
git ls-remote --exit-code other.git "refs/tags/*" >actual &&
|
|
git ls-remote . tags/mark >expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'set up some extra tags for ref hiding' '
|
|
git tag magic/one &&
|
|
git tag magic/two
|
|
'
|
|
|
|
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 &&
|
|
git ls-remote . |
|
|
sed -e "/ refs\/tags\//d" >expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
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
|
|
'
|
|
|
|
done
|
|
|
|
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
|
|
'
|
|
|
|
test_done
|