Skip to content
Snippets Groups Projects
Commit adb5d49653d6 authored by Georges Racinet's avatar Georges Racinet :squid:
Browse files

Moved Git repos: fixup GitLab pools relative paths

Should solve heptapod#1984, especially given that the migration
to native Projects calls `hg move-hg-git-repo-out-of-gitaly-reach`.

Given that this is a one shot and we happen to have the same Python
dependencies in the default and stable series of Heptapod, we're hardcoding
the series in the CI configuration. Obviously to be reverted upon merge in
the default branch.
parent 216426df9b7f
No related branches found
No related tags found
1 merge request!112Fixup for Git pools relative paths
Pipeline #97457 failed
......@@ -4,7 +4,7 @@
- downstream
variables:
BASE_IMAGES_TAG: $CI_COMMIT_HG_BRANCH
BASE_IMAGES_TAG: default
BASE_IMAGES_COLLECTION: registry.heptapod.net:443/heptapod/ci-images
BASE_IMAGES_MERCURIAL: $BASE_IMAGES_COLLECTION/mercurial
......
......@@ -11,6 +11,7 @@
"""
from __future__ import absolute_import
from mercurial import error
try:
from hgext3rd.hggit.git_handler import GitHandler
except ImportError: # pragma: no cover (fallback for hg-git < 0.11)
......@@ -99,6 +100,41 @@
if os.path.exists(old_gitdir) and not os.path.exists(self.gitdir):
os.rename(old_gitdir, self.gitdir)
self.fixup_git_pool()
def fixup_git_pool(self):
alternates_path = os.path.join(self.gitdir,
b'objects/info/alternates')
if not os.path.exists(alternates_path):
return
with open(alternates_path, 'rb') as alternates:
lines = alternates.readlines()
new_lines = []
for line in lines:
line = line.strip()
tgt_path = os.path.join(self.gitdir, line)
if os.path.exists(tgt_path):
new_lines.append(line)
else:
repositories_root = self.repo.ui.config(b'heptapod',
b'repositories-root')
idx = tgt_path.find(b'@pools/')
if idx == -1:
raise error.Abort(
b"Unreachable Git alternates path that is not "
b"under the expected GitLab pools: %r" % tgt_path)
abs_tgt = os.path.join(repositories_root, tgt_path[idx:])
if not os.path.exists(abs_tgt):
raise error.Abort(
b"After fix, path to shared Git inside GitLab pools "
b"does not exist: %r" % abs_tgt)
new_lines.append(os.path.relpath(abs_tgt,
self.gitdir + b'/objects'))
with open(alternates_path, 'wb') as alternates:
alternates.write(b'\n'.join(new_lines))
@property
def gitlab_refs(self):
return self.git.refs
......
......@@ -15,6 +15,7 @@
from mercurial import (
error,
)
from pathlib import Path
import pytest
import re
......@@ -22,6 +23,7 @@
from heptapod.testhelpers import (
RepoWrapper,
)
from heptapod.testhelpers.git import GitRepo
from heptapod.gitlab import prune_reasons
from heptapod.gitlab.branch import gitlab_branch_ref as git_branch_ref
from heptapod.gitlab.change import GitLabRefChange as RefChange
......@@ -39,6 +41,8 @@
# TODO move to helper module
from .test_integration import patch_gitlab_hooks
parametrize = pytest.mark.parametrize
@pytest.fixture
def wrapper(tmpdir):
......@@ -449,3 +453,35 @@
fallback=REF_TARGET_UNKNOWN_RAISE)
)
assert exc_info.value.args == (unknown_git_sha, )
@parametrize('special',
('abspath-not-found', 'relpath-not-found', 'other-alt'))
def test_fixup_git_pool_special_cases(wrapper, special, tmpdir):
wrapper.repo.ui.setconfig(b'heptapod', b'native', True)
git_repo = GitRepo.init(wrapper.path / '../repo.git')
if special == 'abspath-not-found':
alt_path = b'/no/such/path'
elif special == 'relpath-not-found':
alt_path = b'../@pools/does/not/exist/either'
else:
alt_path = tmpdir / 'existing'
alt_path.mkdir()
alt_path = str(alt_path).encode('utf-8')
conf_relpath = 'objects/info/alternates'
(git_repo.path / conf_relpath).write_binary(alt_path)
if special == 'other-alt':
handler = HeptapodGitHandler(wrapper.repo, wrapper.repo.ui)
moved_path = Path(handler.gitdir.decode())
assert moved_path != git_repo.path
assert (moved_path / conf_relpath).read_bytes() == alt_path
return
with pytest.raises(error.Abort) as exc_info:
HeptapodGitHandler(wrapper.repo, wrapper.repo.ui)
if special == 'abspath-not-found':
expected_msg = b'Unreachable Git alternates'
else:
expected_msg = b'path to shared Git inside GitLab pools'
assert expected_msg in exc_info.value.args[0]
......@@ -16,6 +16,7 @@
import pytest
import re
import shutil
import subprocess
from heptapod.gitlab import hooks
from heptapod.gitlab.prune_reasons import (
......@@ -154,9 +155,11 @@
}
def test_moved_out_of_gitaly_reach(main_fixture):
@parametrize('pool', ('with-pool', 'without_pool'))
def test_moved_out_of_gitaly_reach(main_fixture, pool):
with_pool = pool == 'with-pool'
fixture = main_fixture
wrapper = fixture.hg_repo_wrapper
wrapper.command('gitlab-mirror')
orig_git_path = fixture.git_repo.path
assert fixture.git_repo.branch_titles() == {b'branch/default': b'default1'}
......@@ -158,10 +161,26 @@
fixture = main_fixture
wrapper = fixture.hg_repo_wrapper
wrapper.command('gitlab-mirror')
orig_git_path = fixture.git_repo.path
assert fixture.git_repo.branch_titles() == {b'branch/default': b'default1'}
alternates_relpath = 'objects/info/alternates'
if with_pool:
pools_path = orig_git_path / '../@pools'
pools_path.mkdir()
in_pool_path = pools_path / 'shared.git'
orig_git_path.rename(in_pool_path)
# git clone --shared normalizes the 'alternates' with absolute paths.
# There is now point trying to give it relative paths, we will
# edit the alternates later on to match what GitLab does
pool_rel_path = b'../../@pools/shared.git/objects'
subprocess.check_call(('git', 'clone', '--bare', '--shared',
in_pool_path, orig_git_path))
(orig_git_path / alternates_relpath).write_binary(pool_rel_path)
# we did not break it by setting up the alternate objects store.
assert fixture.git_repo.branch_titles() == {
b'branch/default': b'default1'}
wrapper.set_config('heptapod', 'native', True)
fixture.reload_git_repo()
assert fixture.git_repo.path != orig_git_path
......@@ -163,10 +182,11 @@
wrapper.set_config('heptapod', 'native', True)
fixture.reload_git_repo()
assert fixture.git_repo.path != orig_git_path
# this performs the move
wrapper.commit_file('foo',
content='foo2',
message="default2")
wrapper.command('gitlab-mirror')
assert fixture.git_repo.branch_titles() == {b'branch/default': b'default2'}
......@@ -168,8 +188,19 @@
wrapper.commit_file('foo',
content='foo2',
message="default2")
wrapper.command('gitlab-mirror')
assert fixture.git_repo.branch_titles() == {b'branch/default': b'default2'}
# subsequent updates (not going through the moving code) also work
wrapper.commit_file('foo',
content='foo3',
message="default3")
wrapper.command('gitlab-mirror')
assert fixture.git_repo.branch_titles() == {b'branch/default': b'default3'}
if with_pool:
# just to be sure
assert (fixture.git_repo.path / alternates_relpath
).read_binary() != pool_rel_path
@parametrize('pushvar', ('skip-ci', 'mr-create'))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment