diff --git a/hgitaly/service/ref.py b/hgitaly/service/ref.py index 7c9cb5c847d93ce5b2934679523ccbad4c4f8f8f_aGdpdGFseS9zZXJ2aWNlL3JlZi5weQ==..4917ed9df786dfbb8ed18d967a764720b38be3eb_aGdpdGFseS9zZXJ2aWNlL3JlZi5weQ== 100644 --- a/hgitaly/service/ref.py +++ b/hgitaly/service/ref.py @@ -6,5 +6,8 @@ # SPDX-License-Identifier: GPL-2.0-or-later import logging +from heptapod.gitlab.branch import ( + gitlab_branch_from_ref, +) from hgext3rd.heptapod.branch import get_default_gitlab_branch @@ -9,5 +12,8 @@ from hgext3rd.heptapod.branch import get_default_gitlab_branch +from ..stub.shared_pb2 import ( + Branch +) from ..stub.ref_pb2 import ( FindDefaultBranchNameRequest, FindDefaultBranchNameResponse, @@ -17,7 +23,11 @@ FindAllTagNamesResponse, FindRefNameRequest, FindRefNameResponse, + FindAllBranchesRequest, + FindAllBranchesResponse, + FindBranchRequest, + FindBranchResponse, ) from ..stub.ref_pb2_grpc import RefServiceServicer from ..branch import ( @@ -20,6 +30,7 @@ ) from ..stub.ref_pb2_grpc import RefServiceServicer from ..branch import ( + gitlab_branch_head, iter_gitlab_branches, ) @@ -24,5 +35,6 @@ iter_gitlab_branches, ) +from .commit import changectx_to_git_commit as git_commit from ..servicer import HGitalyServicer from ..util import chunked @@ -106,3 +118,29 @@ in the whole Rails application. """ raise NotImplementedError("Second round of implementation") + + def FindBranch(self, + request: FindBranchRequest, + context) -> FindBranchResponse: + repo = self.load_repo(request.repository) + name = request.name + if name.startswith(b'refs/'): + name = gitlab_branch_from_ref(request.name) + + if name is None: + # TODO SPEC check if we really must exclude other refs + return FindBranchResponse(branch=None) + + head = gitlab_branch_head(repo, name) + return FindBranchResponse( + branch=Branch(name=name, target_commit=git_commit(head))) + + def FindAllBranches(self, + request: FindAllBranchesRequest, + context) -> FindAllBranchesResponse: + Branch = FindAllBranchesResponse.Branch + repo = self.load_repo(request.repository) + for chunk in chunked(iter_gitlab_branches(repo)): + yield FindAllBranchesResponse( + branches=(Branch(name=name, target=git_commit(head)) + for name, head in chunk)) diff --git a/hgitaly/tests/test_ref.py b/hgitaly/tests/test_ref.py index 7c9cb5c847d93ce5b2934679523ccbad4c4f8f8f_aGdpdGFseS90ZXN0cy90ZXN0X3JlZi5weQ==..4917ed9df786dfbb8ed18d967a764720b38be3eb_aGdpdGFseS90ZXN0cy90ZXN0X3JlZi5weQ== 100644 --- a/hgitaly/tests/test_ref.py +++ b/hgitaly/tests/test_ref.py @@ -9,6 +9,8 @@ from ..stub.ref_pb2 import ( FindAllBranchNamesRequest, FindAllTagNamesRequest, + FindBranchRequest, + FindAllBranchesRequest, ) from ..stub.ref_pb2_grpc import RefServiceStub @@ -60,3 +62,38 @@ resp = ref_stub.FindAllTagNames(request) assert [chunk.names for chunk in resp] == [[b'v3.2.1']] + + +def test_find_branch(grpc_channel, server_repos_root): + ref_stub = RefServiceStub(grpc_channel) + wrapper, grpc_repo = make_empty_repo(server_repos_root, + relative_path='find_branch') + ctx = wrapper.write_commit('foo') + resp = ref_stub.FindBranch( + FindBranchRequest(repository=grpc_repo, + name=b'branch/default')) + branch = resp.branch + assert branch is not None + assert branch.name == b'branch/default' + assert branch.target_commit.id == ctx.hex().decode() + + resp = ref_stub.FindBranch( + FindBranchRequest(repository=grpc_repo, + name=b'refs/heads/branch/default')) + assert resp.branch == branch + + resp = ref_stub.FindBranch( + FindBranchRequest(repository=grpc_repo, + name=b'refs/keeparound/012ca34fe56')) + + # There is no None in gRPC, just cascading default content (empty string). + # We checked that Gitaly indeed uses the default `Branch(name=b'')` + # to represent the absence of results. + assert not resp.branch.name + + resp = ref_stub.FindAllBranches( + FindAllBranchesRequest(repository=grpc_repo)) + branches = [br for chunk in resp for br in chunk.branches] + assert len(branches) == 1 + assert branches[0].name == b'branch/default' + assert branches[0].target == branch.target_commit