2017-03-26 04:42:39 +02:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='test main ref store api'
|
|
|
|
|
2020-11-19 00:44:21 +01: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-19 00:44:19 +01:00
|
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
|
|
|
2017-03-26 04:42:39 +02:00
|
|
|
. ./test-lib.sh
|
|
|
|
|
2018-03-24 08:44:52 +01:00
|
|
|
RUN="test-tool ref-store main"
|
2017-03-26 04:42:39 +02:00
|
|
|
|
2021-08-02 18:53:32 +02:00
|
|
|
|
|
|
|
test_expect_success 'setup' '
|
|
|
|
test_commit one
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success REFFILES 'pack_refs(PACK_REFS_ALL | PACK_REFS_PRUNE)' '
|
2017-03-26 04:42:39 +02:00
|
|
|
N=`find .git/refs -type f | wc -l` &&
|
|
|
|
test "$N" != 0 &&
|
2021-12-07 14:38:14 +01:00
|
|
|
$RUN pack-refs PACK_REFS_PRUNE,PACK_REFS_ALL &&
|
2021-08-02 18:53:32 +02:00
|
|
|
N=`find .git/refs -type f` &&
|
|
|
|
test -z "$N"
|
2017-03-26 04:42:39 +02:00
|
|
|
'
|
|
|
|
|
2020-11-19 00:44:21 +01:00
|
|
|
test_expect_success 'create_symref(FOO, refs/heads/main)' '
|
|
|
|
$RUN create-symref FOO refs/heads/main nothing &&
|
|
|
|
echo refs/heads/main >expected &&
|
2017-03-26 04:42:39 +02:00
|
|
|
git symbolic-ref FOO >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'delete_refs(FOO, refs/tags/new-tag)' '
|
refs: switch peel_ref() to peel_iterated_oid()
The peel_ref() interface is confusing and error-prone:
- it's typically used by ref iteration callbacks that have both a
refname and oid. But since they pass only the refname, we may load
the ref value from the filesystem again. This is inefficient, but
also means we are open to a race if somebody simultaneously updates
the ref. E.g., this:
int some_ref_cb(const char *refname, const struct object_id *oid, ...)
{
if (!peel_ref(refname, &peeled))
printf("%s peels to %s",
oid_to_hex(oid), oid_to_hex(&peeled);
}
could print nonsense. It is correct to say "refname peels to..."
(you may see the "before" value or the "after" value, either of
which is consistent), but mentioning both oids may be mixing
before/after values.
Worse, whether this is possible depends on whether the optimization
to read from the current iterator value kicks in. So it is actually
not possible with:
for_each_ref(some_ref_cb);
but it _is_ possible with:
head_ref(some_ref_cb);
which does not use the iterator mechanism (though in practice, HEAD
should never peel to anything, so this may not be triggerable).
- it must take a fully-qualified refname for the read_ref_full() code
path to work. Yet we routinely pass it partial refnames from
callbacks to for_each_tag_ref(), etc. This happens to work when
iterating because there we do not call read_ref_full() at all, and
only use the passed refname to check if it is the same as the
iterator. But the requirements for the function parameters are quite
unclear.
Instead of taking a refname, let's instead take an oid. That fixes both
problems. It's a little funny for a "ref" function not to involve refs
at all. The key thing is that it's optimizing under the hood based on
having access to the ref iterator. So let's change the name to make it
clear why you'd want this function versus just peel_object().
There are two other directions I considered but rejected:
- we could pass the peel information into the each_ref_fn callback.
However, we don't know if the caller actually wants it or not. For
packed-refs, providing it is essentially free. But for loose refs,
we actually have to peel the object, which would be wasteful in most
cases. We could likewise pass in a flag to the callback indicating
whether the peeled information is known, but that complicates those
callbacks, as they then have to decide whether to manually peel
themselves. Plus it requires changing the interface of every
callback, whether they care about peeling or not, and there are many
of them.
- we could make a function to return the peeled value of the current
iterated ref (computing it if necessary), and BUG() otherwise. I.e.:
int peel_current_iterated_ref(struct object_id *out);
Each of the current callers is an each_ref_fn callback, so they'd
mostly be happy. But:
- we use those callbacks with functions like head_ref(), which do
not use the iteration code. So we'd need to handle the fallback
case there, anyway.
- it's possible that a caller would want to call into generic code
that sometimes is used during iteration and sometimes not. This
encapsulates the logic to do the fast thing when possible, and
fallback when necessary.
The implementation is mostly obvious, but I want to call out a few
things in the patch:
- the test-tool coverage for peel_ref() is now meaningless, as it all
collapses to a single peel_object() call (arguably they were pretty
uninteresting before; the tricky part of that function is the
fast-path we see during iteration, but these calls didn't trigger
that). I've just dropped it entirely, though note that some other
tests relied on the tags we created; I've moved that creation to the
tests where it matters.
- we no longer need to take a ref_store parameter, since we'd never
look up a ref now. We do still rely on a global "current iterator"
variable which _could_ be kept per-ref-store. But in practice this
is only useful if there are multiple recursive iterations, at which
point the more appropriate solution is probably a stack of
iterators. No caller used the actual ref-store parameter anyway
(they all call the wrapper that passes the_repository).
- the original only kicked in the optimization when the "refname"
pointer matched (i.e., not string comparison). We do likewise with
the "oid" parameter here, but fall back to doing an actual oideq()
call. This in theory lets us kick in the optimization more often,
though in practice no current caller cares. It should never be
wrong, though (peeling is a property of an object, so two refs
pointing to the same object would peel identically).
- the original took care not to touch the peeled out-parameter unless
we found something to put in it. But no caller cares about this, and
anyway, it is enforced by peel_object() itself (and even in the
optimized iterator case, that's where we eventually end up). We can
shorten the code and avoid an extra copy by just passing the
out-parameter through the stack.
Signed-off-by: Jeff King <peff@peff.net>
Reviewed-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-01-20 20:44:43 +01:00
|
|
|
git tag -a -m new-tag new-tag HEAD &&
|
2017-03-26 04:42:39 +02:00
|
|
|
git rev-parse FOO -- &&
|
|
|
|
git rev-parse refs/tags/new-tag -- &&
|
2020-11-19 00:44:21 +01:00
|
|
|
m=$(git rev-parse main) &&
|
2021-12-07 14:38:13 +01:00
|
|
|
$RUN delete-refs REF_NO_DEREF nothing FOO refs/tags/new-tag &&
|
2020-07-27 18:25:46 +02:00
|
|
|
test_must_fail git rev-parse --symbolic-full-name FOO &&
|
2017-03-26 04:42:39 +02:00
|
|
|
test_must_fail git rev-parse FOO -- &&
|
|
|
|
test_must_fail git rev-parse refs/tags/new-tag --
|
|
|
|
'
|
|
|
|
|
2022-01-31 18:50:18 +01:00
|
|
|
# In reftable, we keep the reflogs around for deleted refs.
|
|
|
|
test_expect_success !REFFILES 'delete-reflog(FOO, refs/tags/new-tag)' '
|
|
|
|
$RUN delete-reflog FOO &&
|
|
|
|
$RUN delete-reflog refs/tags/new-tag
|
|
|
|
'
|
|
|
|
|
2020-11-19 00:44:21 +01:00
|
|
|
test_expect_success 'rename_refs(main, new-main)' '
|
|
|
|
git rev-parse main >expected &&
|
|
|
|
$RUN rename-ref refs/heads/main refs/heads/new-main &&
|
|
|
|
git rev-parse new-main >actual &&
|
2017-03-26 04:42:39 +02:00
|
|
|
test_cmp expected actual &&
|
2020-11-19 00:44:21 +01:00
|
|
|
test_commit recreate-main
|
2017-03-26 04:42:39 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'for_each_ref(refs/heads/)' '
|
2018-03-25 21:20:49 +02:00
|
|
|
$RUN for-each-ref refs/heads/ | cut -d" " -f 2- >actual &&
|
2017-03-26 04:42:39 +02:00
|
|
|
cat >expected <<-\EOF &&
|
2020-11-19 00:44:21 +01:00
|
|
|
main 0x0
|
|
|
|
new-main 0x0
|
2017-03-26 04:42:39 +02:00
|
|
|
EOF
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2017-03-26 04:42:41 +02:00
|
|
|
test_expect_success 'for_each_ref() is sorted' '
|
2018-09-13 07:17:39 +02:00
|
|
|
$RUN for-each-ref refs/heads/ | cut -d" " -f 2- >actual &&
|
2017-03-26 04:42:41 +02:00
|
|
|
sort actual > expected &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2020-11-19 00:44:21 +01:00
|
|
|
test_expect_success 'resolve_ref(new-main)' '
|
|
|
|
SHA1=`git rev-parse new-main` &&
|
|
|
|
echo "$SHA1 refs/heads/new-main 0x0" >expected &&
|
|
|
|
$RUN resolve-ref refs/heads/new-main 0 >actual &&
|
2017-03-26 04:42:39 +02:00
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2020-11-19 00:44:21 +01:00
|
|
|
test_expect_success 'verify_ref(new-main)' '
|
|
|
|
$RUN verify-ref refs/heads/new-main
|
2017-03-26 04:42:39 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'for_each_reflog()' '
|
2018-09-13 07:17:39 +02:00
|
|
|
$RUN for-each-reflog | sort -k2 | cut -d" " -f 2- >actual &&
|
2017-03-26 04:42:39 +02:00
|
|
|
cat >expected <<-\EOF &&
|
|
|
|
HEAD 0x1
|
2020-11-19 00:44:21 +01:00
|
|
|
refs/heads/main 0x0
|
|
|
|
refs/heads/new-main 0x0
|
2017-03-26 04:42:39 +02:00
|
|
|
EOF
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'for_each_reflog_ent()' '
|
|
|
|
$RUN for-each-reflog-ent HEAD >actual &&
|
|
|
|
head -n1 actual | grep one &&
|
2021-12-02 18:36:30 +01:00
|
|
|
tail -n1 actual | grep recreate-main
|
2017-03-26 04:42:39 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'for_each_reflog_ent_reverse()' '
|
|
|
|
$RUN for-each-reflog-ent-reverse HEAD >actual &&
|
2020-11-19 00:44:21 +01:00
|
|
|
head -n1 actual | grep recreate-main &&
|
2021-12-02 18:36:30 +01:00
|
|
|
tail -n1 actual | grep one
|
2017-03-26 04:42:39 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'reflog_exists(HEAD)' '
|
|
|
|
$RUN reflog-exists HEAD
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'delete_reflog(HEAD)' '
|
|
|
|
$RUN delete-reflog HEAD &&
|
2021-08-02 18:53:31 +02:00
|
|
|
test_must_fail git reflog exists HEAD
|
2017-03-26 04:42:39 +02:00
|
|
|
'
|
|
|
|
|
2022-01-31 18:50:19 +01:00
|
|
|
test_expect_success REFFILES 'create-reflog(HEAD)' '
|
2021-11-22 15:19:08 +01:00
|
|
|
$RUN create-reflog HEAD &&
|
2021-08-02 18:53:31 +02:00
|
|
|
git reflog exists HEAD
|
2017-03-26 04:42:39 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'delete_ref(refs/heads/foo)' '
|
|
|
|
git checkout -b foo &&
|
|
|
|
FOO_SHA1=`git rev-parse foo` &&
|
|
|
|
git checkout --detach &&
|
|
|
|
test_commit bar-commit &&
|
|
|
|
git checkout -b bar &&
|
|
|
|
BAR_SHA1=`git rev-parse bar` &&
|
|
|
|
$RUN update-ref updating refs/heads/foo $BAR_SHA1 $FOO_SHA1 0 &&
|
|
|
|
echo $BAR_SHA1 >expected &&
|
|
|
|
git rev-parse refs/heads/foo >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'delete_ref(refs/heads/foo)' '
|
|
|
|
SHA1=`git rev-parse foo` &&
|
|
|
|
git checkout --detach &&
|
|
|
|
$RUN delete-ref msg refs/heads/foo $SHA1 0 &&
|
|
|
|
test_must_fail git rev-parse refs/heads/foo --
|
|
|
|
'
|
|
|
|
|
|
|
|
test_done
|