Commit a714e836 by Patrick Steinhardt

transports: local: fix assert when fetching into repo with symrefs

When fetching into a repository which has symbolic references via the
"local" transport we run into an assert. The assert is being triggered
while we negotiate the packfile between the two repositories. When
hiding known revisions from the packbuilder revwalk, we unconditionally
hide all references of the local refdb. In case one of these references
is a symbolic reference, though, this means we're trying to hide a
`NULL` OID, which triggers the assert.

Fix the issue by only hiding OID references from the revwalk. Add a test
to catch this issue in the future.
parent 59012bf4
...@@ -510,8 +510,12 @@ static int local_counting(int stage, unsigned int current, unsigned int total, v ...@@ -510,8 +510,12 @@ static int local_counting(int stage, unsigned int current, unsigned int total, v
static int foreach_reference_cb(git_reference *reference, void *payload) static int foreach_reference_cb(git_reference *reference, void *payload)
{ {
git_revwalk *walk = (git_revwalk *)payload; git_revwalk *walk = (git_revwalk *)payload;
int error;
if (git_reference_type(reference) != GIT_REF_OID)
return 0;
int error = git_revwalk_hide(walk, git_reference_target(reference)); error = git_revwalk_hide(walk, git_reference_target(reference));
/* The reference is in the local repository, so the target may not /* The reference is in the local repository, so the target may not
* exist on the remote. It also may not be a commit. */ * exist on the remote. It also may not be a commit. */
if (error == GIT_ENOTFOUND || error == GITERR_INVALID) { if (error == GIT_ENOTFOUND || error == GITERR_INVALID) {
......
...@@ -343,6 +343,29 @@ void test_fetchhead_nonetwork__unborn_with_upstream(void) ...@@ -343,6 +343,29 @@ void test_fetchhead_nonetwork__unborn_with_upstream(void)
cl_fixture_cleanup("./repowithunborn"); cl_fixture_cleanup("./repowithunborn");
} }
void test_fetchhead_nonetwork__fetch_into_repo_with_symrefs(void)
{
git_repository *repo;
git_remote *remote;
git_reference *symref;
repo = cl_git_sandbox_init("empty_standard_repo");
/*
* Testing for a specific constellation where the repository has at
* least one symbolic reference in its refdb.
*/
cl_git_pass(git_reference_symbolic_create(&symref, repo, "refs/heads/symref", "refs/heads/master", 0, NULL));
cl_git_pass(git_remote_set_url(repo, "origin", cl_fixture("testrepo.git")));
cl_git_pass(git_remote_lookup(&remote, repo, "origin"));
cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));
git_remote_free(remote);
git_reference_free(symref);
cl_git_sandbox_cleanup();
}
void test_fetchhead_nonetwork__quote_in_branch_name(void) void test_fetchhead_nonetwork__quote_in_branch_name(void)
{ {
cl_set_cleanup(&cleanup_repository, "./test1"); cl_set_cleanup(&cleanup_repository, "./test1");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment