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

New branch module, to generate GitLab branches from repo

The functions in this module enforce the Heptapod rules to map
addressable Mercurial content to GitLab branch, in particular:

- named branches and topics to GitLab branches
- multiple heads conventions
- bookmarks
parent db2b4cd5
No related branches found
No related tags found
No related merge requests found
# Copyright 2020 Georges Racinet <georges.racinet@octobus.net>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
#
# SPDX-License-Identifier: GPL-2.0-or-later
from mercurial import (
node as nodemod,
pycompat,
)
from heptapod.gitlab.branch import (
branchmap_branch_from_gitlab_branch,
gitlab_branch_from_branchmap_branch,
parse_wild_gitlab_branch,
)
def _extract_branchmap_heads(repo, entry):
"""From the given branchmap entry, extract default head and list of heads.
The default head is what needs to be returned for a simple branchmap
branch lookup. It can be ``None`` if all heads are invisible to GitLab
(closed or bookmarked).
:return: (default head, all heads visible to GitLab), all given as
:class:`changectx` instances.
"""
# branchmap entries results are already sorted by increasing rev number
contexts = (repo[node] for node in entry)
visible = [c for c in contexts if not (c.closesbranch() or c.bookmarks())]
if not visible:
return None, visible
return visible[-1], visible
def gitlab_branch_head(repo, gl_branch):
"""Return the unique head of the given GitLab branch.
Does not resolve other types of "revisions".
:return: a :class:`changectx` or ``None`` if there's no changeset for
the given ``gl_branch``.
"""
wild_hex = parse_wild_gitlab_branch(gl_branch)
if wild_hex is not None:
return repo[nodemod.bin(wild_hex)]
branchmap_key = branchmap_branch_from_gitlab_branch(gl_branch)
if branchmap_key is not None:
try:
entry = repo.branchmap()[branchmap_key]
except KeyError:
return None
return _extract_branchmap_heads(repo, entry)[0]
# last chance: bookmarks
bookmark_node = repo._bookmarks.get(gl_branch)
if bookmark_node is None:
return None
return repo[bookmark_node]
def iter_gitlab_branches(repo):
"""Iterate on all visible GitLab branches
Each iteration yields a pair ``(gl_branch, head)`` where ``gl_branch``
is the name of the GitLab branch and ``head`` is a :class:`changectx`
instance.
"""
for key, entry in pycompat.iteritems(repo.branchmap()):
default, visible = _extract_branchmap_heads(repo, entry)
if not visible:
continue
yield gitlab_branch_from_branchmap_branch(key), default
if len(visible) > 1:
for head in visible:
yield b'wild/' + head.hex(), head
for key, node in pycompat.iteritems(repo._bookmarks):
yield key, repo[node]
# Copyright 2020 Georges Racinet <georges.racinet@octobus.net>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
#
# SPDX-License-Identifier: GPL-2.0-or-later
from heptapod.testhelpers import (
LocalRepoWrapper,
)
from ..branch import (
gitlab_branch_head,
iter_gitlab_branches,
)
def make_repo(path):
return LocalRepoWrapper.init(path,
config=dict(
extensions=dict(topic=''),
))
def test_named_branch_multiple_heads(tmpdir):
wrapper = make_repo(tmpdir)
repo = wrapper.repo
default_branch = b'branch/default'
# no head, no bookmark
assert gitlab_branch_head(repo, default_branch) is None
assert gitlab_branch_head(repo, b'zebook') is None
# one head
base = wrapper.write_commit('foo')
assert gitlab_branch_head(repo, default_branch) == base
assert list(iter_gitlab_branches(repo)) == [(default_branch, base)]
# two heads, no bookmark
head1 = wrapper.write_commit('foo')
head2 = wrapper.write_commit('foo', parent=base)
assert gitlab_branch_head(repo, default_branch) == head2
assert set(iter_gitlab_branches(repo)) == {
(default_branch, head2),
(b'wild/' + head1.hex(), head1),
(b'wild/' + head2.hex(), head2),
}
assert gitlab_branch_head(repo, b'wild/' + head1.hex()) == head1
# one bookmarked head and one not bookmarked
wrapper.command('bookmark', b'book2', rev=head2.hex())
assert gitlab_branch_head(repo, default_branch) == head1
assert set(iter_gitlab_branches(repo)) == {
(default_branch, head1),
(b'book2', head2),
}
assert gitlab_branch_head(repo, b'wild/' + head1.hex()) == head1
assert gitlab_branch_head(repo, b'book2') == head2
# all heads bookmarked
wrapper.command('bookmark', b'book1', rev=head1.hex())
assert gitlab_branch_head(repo, default_branch) is None
assert set(iter_gitlab_branches(repo)) == {
(b'book1', head1),
(b'book2', head2),
}
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