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

Topics as Heptapod default branch: avoid some surprises

This fixes the scenario of heptapod#1716 in two different ways:

- we do not change the default Heptapod branch from one topic to another
  if not needed.
- we check if the topic of the existing default branch has become obsolete
  and force switching in that case.

Then we add some protections against the case where the changes prune
the default branch and provide no suitable replacement (such as in
pruning the whole topic), so that momentary persistence of the GitLab
branch does not shadow the fact that an obselete changeset is being
references (this the end cause of the HTTP error 500 anyway).
parent 1dae3eaa6837
No related branches found
No related tags found
1 merge request!107Edge cases with a topic as default Heptapod branch
......@@ -1106,6 +1106,14 @@
self.repo._afterlock(
lambda success: post_receive(push_opts=push_opts))
def is_filtered(self, sha):
hg_sha = self.hg_sha_from_gitlab_sha(sha)
try:
self.repo[hg_sha]
except error.FilteredRepoLookupError:
return True
return False
def update_default_gitlab_branch(self, changes):
"""Update GitLab default branch if needed
......@@ -1140,6 +1148,17 @@
new_named_branch_refs, fallback_new_refs))
candidate_refs = new_named_branch_refs or fallback_new_refs
if not candidate_refs:
if self.is_filtered(self.gitlab_refs[default_ref]):
raise error.Abort(
b"These changes would obsolete the current "
b"Heptapod default branch '%s' "
b"(given here as GitLab full ref path)."
b"and provide no new suitable replacement." % default_ref,
hint=b"To secure your repository for Heptapod, "
b"consider pushing a public changeset first, even if "
b"almost empty; `hg push -r` can help to avoid pushing "
b"unwanted ones at the same time."
)
return
branch_default_ref = gitlab_branch_ref(b'branch/default')
......@@ -1165,4 +1184,14 @@
b"as it is public. For example, "
b"an almost empty `.hgignore` would be be enough.\n" % topic
)
if default_exists:
if self.is_filtered(self.gitlab_refs[default_ref]):
self.ui.warn(b"Default ref %r still in `gitlab_refs` "
b"but is obsolete\n" % default_ref)
else:
# No need to further endanger the repo, by changing
# default branch to another topic or rewrite the
# same value. GitLab is not
# designed for default branch changing at each push
return
else:
......@@ -1168,4 +1197,6 @@
else:
# wild branches are already excluded above. The remaining
# possibilities are bookmarks and named branches.
branch = gitlab_branch_from_ref(new_default_ref)
self.ui.status(
b"Setting '%s' as Heptapod default branch.\n"
......
......@@ -26,6 +26,12 @@
)
from heptapod.testhelpers.gitlab import patch_gitlab_hooks
from heptapod.gitlab import prune_reasons
from heptapod.gitlab.branch import (
gitlab_branch_ref,
)
from ...branch import (
get_default_gitlab_branch,
)
from ...no_git import (
NoGitStateMaintainer,
RefsByType,
......@@ -33,7 +39,7 @@
from ..utils import common_config
def test_never_prune_default_branch(tmpdir, monkeypatch):
def test_never_prune_named_default_branch(tmpdir, monkeypatch):
notifs = []
patch_gitlab_hooks(monkeypatch, notifs)
......@@ -60,6 +66,36 @@
assert re.search(br'prune.*default branch', exc_info.value.args[0])
def test_topical_default_branch_is_pruned(tmpdir, monkeypatch):
notifs = []
patch_gitlab_hooks(monkeypatch, notifs)
config = common_config()
config['heptapod'] = dict(native=True)
wrapper = RepoWrapper.init(tmpdir.join('repo'), config=config)
ctx0 = wrapper.write_commit('foo', topic='top1')
wrapper.command('gitlab-mirror')
wrapper.command('topics', b'top2', rev=[b'.'])
ctx1 = wrapper.repo[b'.']
handler = NoGitStateMaintainer(wrapper.repo.ui,
wrapper.repo)
top1_ref = gitlab_branch_ref(b'topic/default/top1')
top2_branch = b'topic/default/top2'
top2_ref = gitlab_branch_ref(top2_branch)
handler.update_default_gitlab_branch({
top1_ref: GitLabRefChange(ref=top1_ref,
before=ctx0.hex(),
after=ZERO_SHA),
top2_ref: GitLabRefChange(ref=top2_ref,
before=ZERO_SHA,
after=ctx1.hex()),
})
assert get_default_gitlab_branch(wrapper.repo) == top2_branch
def test_log_None_in_ref_keys(tmpdir, monkeypatch):
notifs = []
patch_gitlab_hooks(monkeypatch, notifs)
......
......@@ -674,6 +674,57 @@
fixture.assert_default_gitlab_branch('topic/default/initial')
def test_topical_gitlab_default_branch_one_more_topic(empty_fixture):
fixture = empty_fixture
wrapper = fixture.hg_repo_wrapper
wrapper.write_commit('foo', message="other0",
branch='default',
topic='top1')
wrapper.command('gitlab-mirror')
fixture.assert_default_gitlab_branch('topic/default/top1')
wrapper.write_commit('foo', message="same gitlab branch", topic="top2")
wrapper.command('gitlab-mirror')
fixture.assert_default_gitlab_branch('topic/default/top1')
def test_topical_gitlab_default_branch_full_prune(empty_fixture):
fixture = empty_fixture
wrapper = fixture.hg_repo_wrapper
wrapper.write_commit('foo', message="other0",
branch='default',
topic='top1')
wrapper.command('gitlab-mirror')
fixture.assert_default_gitlab_branch('topic/default/top1')
wrapper.prune('.')
with pytest.raises(error.Abort) as exc_info:
wrapper.command('gitlab-mirror')
assert re.search(br'obsolet.*default branch', exc_info.value.args[0])
fixture.assert_default_gitlab_branch('topic/default/top1')
def test_topical_gitlab_default_branch_rename_topic(empty_fixture):
fixture = empty_fixture
wrapper = fixture.hg_repo_wrapper
wrapper.write_commit('foo', message="other0",
branch='default',
topic='top1')
wrapper.command('gitlab-mirror')
fixture.assert_default_gitlab_branch('topic/default/top1')
wrapper.command('topics', b'top2', rev=[b'.'])
wrapper.command('gitlab-mirror')
fixture.assert_default_gitlab_branch('topic/default/top2')
def test_closed_branch(main_fixture):
fixture = main_fixture
wrapper = fixture.hg_repo_wrapper
......
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