Skip to content
Snippets Groups Projects
Commit 83f11149 authored by Georges Racinet's avatar Georges Racinet
Browse files

Setting the GitLab default branch

The source of truth for the default GitLab branch is the HEAD
of the Git repository. If we don't set it, then GitLab will,
using a random branch of first push (unless maybe 'master' is
among them).

Further, it's much simpler and clearer to change from here than
from the Rails application, because the latter is mostly meant to perform
things like protecting the branch, and isn't really meant to set
it to anything other that it's already seeing.

For the Rails app, it'll just boil down to clear some caches if the
situation looks like HEAD is prone to change (e.g the default branch
maps to a topic).
parent 80e5c477
Branches
Tags
No related merge requests found
Pipeline #6173 failed
......@@ -453,9 +453,7 @@
to Git SHAs
:returns: a mapping from Git refs to :class:`GitRefChange` objects
"""
# we're not writing HEAD but apparently GitLab does, with
# the ref for its default branch, and that's the best detection
# we have of that.
# HEAD is the source of truth for GitLab default branch
default_branch_ref = self.git.refs.get_symrefs().get('HEAD')
to_prune = exportable.pop(ZERO_SHA, {})
to_prune.pop(default_branch_ref, None)
......@@ -517,8 +515,21 @@
def heptapod_apply_changes(self, changes):
self.heptapod_notify_gitlab('pre-receive', changes)
git_refs = self.git.refs
# Right after repo creation, HEAD is typically initialized
# as refs/heads/master, which doesn't exist,
# and probably won't after our push. If we don't correct it
# quickly, something on the GitLab side, even
# before post-receive treatment actually begins will set it to
# a random value - we don't want it to select topics if possible
# and if it has, we want that to change.
default_branch_ref = self.git.refs.get_symrefs().get(b'HEAD')
update_default_branch = (
default_branch_ref not in git_refs
or default_branch_ref.startswith(git_branch_ref(b'topic/')))
new_named_branch_refs = []
for change in pycompat.itervalues(changes):
if change.after == ZERO_SHA:
del git_refs[change.ref]
else:
git_refs[change.ref] = change.after
......@@ -520,8 +531,20 @@
for change in pycompat.itervalues(changes):
if change.after == ZERO_SHA:
del git_refs[change.ref]
else:
git_refs[change.ref] = change.after
if (change.before == ZERO_SHA
and change.ref.startswith(git_branch_ref(b'branch/'))):
new_named_branch_refs.append(change.ref)
if update_default_branch and new_named_branch_refs:
branch_default = git_branch_ref(b'branch/default')
if branch_default in new_named_branch_refs:
new_head = branch_default
else:
new_head = new_named_branch_refs[0]
self.repo.ui.note(b"Setting Git HEAD to %s" % new_head)
git_refs.set_symbolic_ref(b'HEAD', new_head)
def post_receive(txn):
self.heptapod_notify_gitlab('post-receive', changes)
......
......@@ -30,6 +30,9 @@
from ..utils import common_config
parametrize = pytest.mark.parametrize
def recording_hook(records, action=None):
class Hook(object):
......@@ -81,6 +84,9 @@
cwd=str(self.path))
return out.strip().split('|')
def get_symref(self, name):
return self.path.join(name).read().strip().split(':', 1)[1].strip()
def set_symref(self, name, target_ref):
self.path.join(name).write('ref: %s\n' % target_ref)
......@@ -246,8 +252,11 @@
# just checking our assumptions
assert git_repo.branch_titles() == {'branch/default': 'default1'}
# we need to test the branch masking on a branch that's not the GitLab default
server.write_commit('foo', branch='other', message='other1')
activate_mirror(server)
set_allow_bookmarks(server, True)
head = server.repo['tip']
server.command('bookmark', 'zebook', rev=head.hex())
assert git_repo.branch_titles() == {
......@@ -249,9 +258,10 @@
activate_mirror(server)
set_allow_bookmarks(server, True)
head = server.repo['tip']
server.command('bookmark', 'zebook', rev=head.hex())
assert git_repo.branch_titles() == {
'zebook': 'default1'
'branch/default': 'default1',
'zebook': 'other1'
}
server.command('bookmark', 'zebook', delete=True)
......@@ -259,6 +269,7 @@
assert server.repo.nodebookmarks(head.node()) == []
assert git_repo.branch_titles() == {
'branch/default': 'default1',
'branch/other': 'other1',
}
......@@ -262,6 +273,26 @@
}
@parametrize('branch_name', ('default', 'other'))
def test_change_gitlab_default_branch(tmpdir, monkeypatch, branch_name):
notifs = []
monkeypatch.setattr(gitlab, 'Hook', recording_hook(notifs))
config = common_config()
config['extensions']['hggit'] = ''
config['phases'] = dict(publish=False)
wrapper = LocalRepoWrapper.init(tmpdir.join('repo.hg'), config=config)
git_repo = GitRepo.init(tmpdir.join('repo.git'))
wrapper.write_commit('foo', message="other0", branch=branch_name, topic='initial')
wrapper.command('gitlab-mirror')
# that's what something (maybe Gitaly) does on the GitLab side:
git_repo.set_symref('HEAD', 'refs/heads/topic/%s/initial' % branch_name)
wrapper.set_phase('public', ['.'])
wrapper.command('gitlab-mirror')
assert git_repo.get_symref('HEAD') == 'refs/heads/branch/' + branch_name
def test_closed_branch(tmpdir, monkeypatch):
notifs = []
monkeypatch.setattr(gitlab, 'Hook', recording_hook(notifs))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment