From 39cca82126dccb7d9ec77d9a51b83f2248bdb67f Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Sun, 14 Aug 2022 18:59:54 +0200 Subject: [PATCH] feat: add support for merge_base API --- docs/cli-examples.rst | 6 ++++++ docs/gl_objects/projects.rst | 4 ++++ gitlab/v4/objects/repositories.py | 28 ++++++++++++++++++++++++- tests/functional/api/test_repository.py | 10 +++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/docs/cli-examples.rst b/docs/cli-examples.rst index 167c72637..7408d9bad 100644 --- a/docs/cli-examples.rst +++ b/docs/cli-examples.rst @@ -302,6 +302,12 @@ Define the status of a commit (as would be done from a CI tool for example): --target-url http://server/build/123 \ --description "Jenkins build succeeded" +Get the merge base for two or more branches, tags or commits: + +.. code-block:: console + + gitlab project repository-merge-base --id 1 --refs bd1324e2f,main,v1.0.0 + Artifacts --------- diff --git a/docs/gl_objects/projects.rst b/docs/gl_objects/projects.rst index fee55d188..e96f14c80 100644 --- a/docs/gl_objects/projects.rst +++ b/docs/gl_objects/projects.rst @@ -231,6 +231,10 @@ Compare two branches, tags or commits:: for file_diff in result['diffs']: print(file_diff) +Get the merge base for two or more branches, tags or commits:: + + commit = project.repository_merge_base(['main', 'v1.2.3', 'bd1324e2f']) + Get a list of contributors for the repository:: contributors = project.repository_contributors() diff --git a/gitlab/v4/objects/repositories.py b/gitlab/v4/objects/repositories.py index b340e80fb..9c0cd9a37 100644 --- a/gitlab/v4/objects/repositories.py +++ b/gitlab/v4/objects/repositories.py @@ -10,7 +10,7 @@ import gitlab from gitlab import cli from gitlab import exceptions as exc -from gitlab import utils +from gitlab import types, utils if TYPE_CHECKING: # When running mypy we use these as the base classes @@ -246,6 +246,32 @@ def repository_archive( result, streamed, action, chunk_size, iterator=iterator ) + @cli.register_custom_action("Project", ("refs",)) + @exc.on_http_error(exc.GitlabGetError) + def repository_merge_base( + self, refs: List[str], **kwargs: Any + ) -> Union[Dict[str, Any], requests.Response]: + """Return a diff between two branches/commits. + + Args: + refs: The refs to find the common ancestor of. Multiple refs can be passed. + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabGetError: If the server failed to perform the request + + Returns: + The common ancestor commit (*not* a RESTObject) + """ + path = f"/projects/{self.encoded_id}/repository/merge_base" + query_data, _ = utils._transform_types( + data={"refs": refs}, + custom_types={"refs": types.ArrayAttribute}, + transform_data=True, + ) + return self.manager.gitlab.http_get(path, query_data=query_data, **kwargs) + @cli.register_custom_action("Project") @exc.on_http_error(exc.GitlabDeleteError) def delete_merged_branches(self, **kwargs: Any) -> None: diff --git a/tests/functional/api/test_repository.py b/tests/functional/api/test_repository.py index dc3d3600a..dd70f10b1 100644 --- a/tests/functional/api/test_repository.py +++ b/tests/functional/api/test_repository.py @@ -174,3 +174,13 @@ def test_revert_commit(project): with pytest.raises(gitlab.GitlabRevertError): # Two revert attempts should raise GitlabRevertError commit.revert(branch="main") + + +def test_repository_merge_base(project): + refs = [commit.id for commit in project.commits.list(all=True)] + + commit = project.repository_merge_base(refs) + assert commit["id"] in refs + + with pytest.raises(gitlab.GitlabGetError, match="Provide at least 2 refs"): + commit = project.repository_merge_base(refs[0])