From 5298964ee7db8a610f23de2d69aad8467727ca97 Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Tue, 18 Feb 2020 17:15:57 +0100 Subject: [PATCH 1/6] feat: add support for commit revert API (#991) --- docs/gl_objects/commits.rst | 4 ++++ gitlab/exceptions.py | 4 ++++ gitlab/v4/objects.py | 16 ++++++++++++++++ tools/cli_test_v4.sh | 9 +++++++++ tools/python_test_v4.py | 15 +++++++++++++++ 5 files changed, 48 insertions(+) diff --git a/docs/gl_objects/commits.rst b/docs/gl_objects/commits.rst index 97cd1c48f..abfedc8a4 100644 --- a/docs/gl_objects/commits.rst +++ b/docs/gl_objects/commits.rst @@ -72,6 +72,10 @@ Cherry-pick a commit into another branch:: commit.cherry_pick(branch='target_branch') +Revert a commit on a given branch:: + + commit.revert(branch='target_branch') + Get the references the commit has been pushed to (branches and tags):: commit.refs() # all references diff --git a/gitlab/exceptions.py b/gitlab/exceptions.py index aff3c87d5..d6791f223 100644 --- a/gitlab/exceptions.py +++ b/gitlab/exceptions.py @@ -245,6 +245,10 @@ class GitlabRepairError(GitlabOperationError): pass +class GitlabRevertError(GitlabOperationError): + pass + + class GitlabLicenseError(GitlabOperationError): pass diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index b31870c2b..d2af890fd 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -2136,6 +2136,22 @@ def merge_requests(self, **kwargs): path = "%s/%s/merge_requests" % (self.manager.path, self.get_id()) return self.manager.gitlab.http_get(path, **kwargs) + @cli.register_custom_action("ProjectCommit", ("branch",)) + @exc.on_http_error(exc.GitlabRevertError) + def revert(self, branch, **kwargs): + """Revert a commit on a given branch. + + Args: + branch (str): Name of target branch + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabRevertError: If the revert could not be performed + """ + path = "%s/%s/revert" % (self.manager.path, self.get_id()) + post_data = {"branch": branch} + self.manager.gitlab.http_post(path, post_data=post_data, **kwargs) class ProjectCommitManager(RetrieveMixin, CreateMixin, RESTManager): _path = "/projects/%(project_id)s/repository/commits" diff --git a/tools/cli_test_v4.sh b/tools/cli_test_v4.sh index dc6e0b278..b7ed708ed 100755 --- a/tools/cli_test_v4.sh +++ b/tools/cli_test_v4.sh @@ -100,6 +100,15 @@ testcase "merge request validation" ' --iid "$MR_ID" >/dev/null 2>&1 ' +# Test revert commit +COMMITS=$(GITLAB -v project-commit list --project-id "${PROJECT_ID}") +COMMIT_ID=$(pecho "${COMMITS}" | grep -m1 '^id:' | cut -d' ' -f2) + +testcase "revert commit" ' + GITLAB project-commit revert --project-id "$PROJECT_ID" \ + --id "$COMMIT_ID" --branch master +' + # Test project labels testcase "create project label" ' OUTPUT=$(GITLAB -v project-label create --project-id $PROJECT_ID \ diff --git a/tools/python_test_v4.py b/tools/python_test_v4.py index bffdd2a17..7c97899c6 100644 --- a/tools/python_test_v4.py +++ b/tools/python_test_v4.py @@ -462,6 +462,21 @@ discussion = commit.discussions.get(discussion.id) # assert len(discussion.attributes["notes"]) == 1 +# Revert commit +commit.revert(branch="master") +revert_commit = admin_project.commits.list()[0] + +expected_message = "Revert \"{}\"\n\nThis reverts commit {}".format( + commit.message, commit.id) +assert revert_commit.message == expected_message + +try: + commit.revert(branch="master") + # Only here to really ensure expected error without a full test framework + raise AssertionError("Two revert attempts should raise GitlabRevertError") +except gitlab.GitlabRevertError: + pass + # housekeeping admin_project.housekeeping() From ad3e833671c49db194c86e23981215b13b96bb1d Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Tue, 18 Feb 2020 17:31:34 +0100 Subject: [PATCH 2/6] style: fix black violations --- gitlab/v4/objects.py | 1 + tools/python_test_v4.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index d2af890fd..8b94f073e 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -2153,6 +2153,7 @@ def revert(self, branch, **kwargs): post_data = {"branch": branch} self.manager.gitlab.http_post(path, post_data=post_data, **kwargs) + class ProjectCommitManager(RetrieveMixin, CreateMixin, RESTManager): _path = "/projects/%(project_id)s/repository/commits" _obj_cls = ProjectCommit diff --git a/tools/python_test_v4.py b/tools/python_test_v4.py index 7c97899c6..f5d5df0fd 100644 --- a/tools/python_test_v4.py +++ b/tools/python_test_v4.py @@ -466,8 +466,9 @@ commit.revert(branch="master") revert_commit = admin_project.commits.list()[0] -expected_message = "Revert \"{}\"\n\nThis reverts commit {}".format( - commit.message, commit.id) +expected_message = 'Revert "{}"\n\nThis reverts commit {}'.format( + commit.message, commit.id +) assert revert_commit.message == expected_message try: From b77b945c7e0000fad4c422a5331c7e905e619a33 Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Wed, 19 Feb 2020 00:30:48 +0100 Subject: [PATCH 3/6] fix: return response with commit data --- gitlab/v4/objects.py | 5 ++++- tools/python_test_v4.py | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 8b94f073e..83f77d365 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -2148,10 +2148,13 @@ def revert(self, branch, **kwargs): Raises: GitlabAuthenticationError: If authentication is not correct GitlabRevertError: If the revert could not be performed + + Returns: + dict: The new commit data (*not* a RESTObject) """ path = "%s/%s/revert" % (self.manager.path, self.get_id()) post_data = {"branch": branch} - self.manager.gitlab.http_post(path, post_data=post_data, **kwargs) + return self.manager.gitlab.http_post(path, post_data=post_data, **kwargs) class ProjectCommitManager(RetrieveMixin, CreateMixin, RESTManager): diff --git a/tools/python_test_v4.py b/tools/python_test_v4.py index f5d5df0fd..49f99e5ba 100644 --- a/tools/python_test_v4.py +++ b/tools/python_test_v4.py @@ -463,13 +463,12 @@ # assert len(discussion.attributes["notes"]) == 1 # Revert commit -commit.revert(branch="master") -revert_commit = admin_project.commits.list()[0] +revert_commit = commit.revert(branch="master") expected_message = 'Revert "{}"\n\nThis reverts commit {}'.format( commit.message, commit.id ) -assert revert_commit.message == expected_message +assert revert_commit["message"] == expected_message try: commit.revert(branch="master") From d7a3066e03164af7f441397eac9e8cfef17c8e0c Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Wed, 19 Feb 2020 00:34:27 +0100 Subject: [PATCH 4/6] test: add unit tests for revert commit API --- gitlab/tests/test_gitlab.py | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/gitlab/tests/test_gitlab.py b/gitlab/tests/test_gitlab.py index 3eccf6e7d..aed675ee1 100644 --- a/gitlab/tests/test_gitlab.py +++ b/gitlab/tests/test_gitlab.py @@ -794,6 +794,58 @@ def resp_deactivate(url, request): self.gl.users.get(1, lazy=True).activate() self.gl.users.get(1, lazy=True).deactivate() + def test_commit_revert(self): + @urlmatch( + scheme="http", netloc="localhost", path="/api/v4/projects/1$", method="get" + ) + def resp_get_project(url, request): + headers = {"content-type": "application/json"} + content = '{"name": "name", "id": 1}'.encode("utf-8") + return response(200, content, headers, None, 5, request) + + @urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/repository/commits/6b2257ea", + method="get", + ) + def resp_get_commit(url, request): + headers = {"content-type": "application/json"} + content = """{ + "id": "6b2257eabcec3db1f59dafbd84935e3caea04235", + "short_id": "6b2257ea", + "title": "Initial commit" + }""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + @urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/repository/commits/6b2257ea", + method="post", + ) + def resp_revert_commit(url, request): + headers = {"content-type": "application/json"} + content = """{ + "id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad", + "short_id": "8b090c1b", + "title":"Revert \\"Initial commit\\"" + }""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + with HTTMock(resp_get_project, resp_get_commit): + project = self.gl.projects.get(1) + commit = project.commits.get("6b2257ea") + self.assertEqual(commit.short_id, "6b2257ea") + self.assertEqual(commit.title, "Initial commit") + + with HTTMock(resp_revert_commit): + revert_commit = commit.revert(branch="master") + self.assertEqual(revert_commit["short_id"], "8b090c1b") + self.assertEqual(revert_commit["title"], 'Revert "Initial commit"') + def test_update_submodule(self): @urlmatch( scheme="http", netloc="localhost", path="/api/v4/projects/1$", method="get" From 31c65621ff592dda0ad3bf854db906beb8a48e9a Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Wed, 19 Feb 2020 20:35:43 +0100 Subject: [PATCH 5/6] test: use lazy object in unit tests --- gitlab/tests/test_gitlab.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitlab/tests/test_gitlab.py b/gitlab/tests/test_gitlab.py index aed675ee1..5e0f3c20a 100644 --- a/gitlab/tests/test_gitlab.py +++ b/gitlab/tests/test_gitlab.py @@ -836,7 +836,7 @@ def resp_revert_commit(url, request): return response(200, content, headers, None, 5, request) with HTTMock(resp_get_project, resp_get_commit): - project = self.gl.projects.get(1) + project = self.gl.projects.get(1, lazy=True) commit = project.commits.get("6b2257ea") self.assertEqual(commit.short_id, "6b2257ea") self.assertEqual(commit.title, "Initial commit") From cb436951b1fde9c010e966819c75d0d7adacf17d Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Wed, 19 Feb 2020 21:09:39 +0100 Subject: [PATCH 6/6] test: remove duplicate resp_get_project --- gitlab/tests/test_gitlab.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/gitlab/tests/test_gitlab.py b/gitlab/tests/test_gitlab.py index 5e0f3c20a..b56889a91 100644 --- a/gitlab/tests/test_gitlab.py +++ b/gitlab/tests/test_gitlab.py @@ -795,14 +795,6 @@ def resp_deactivate(url, request): self.gl.users.get(1, lazy=True).deactivate() def test_commit_revert(self): - @urlmatch( - scheme="http", netloc="localhost", path="/api/v4/projects/1$", method="get" - ) - def resp_get_project(url, request): - headers = {"content-type": "application/json"} - content = '{"name": "name", "id": 1}'.encode("utf-8") - return response(200, content, headers, None, 5, request) - @urlmatch( scheme="http", netloc="localhost", @@ -835,7 +827,7 @@ def resp_revert_commit(url, request): content = content.encode("utf-8") return response(200, content, headers, None, 5, request) - with HTTMock(resp_get_project, resp_get_commit): + with HTTMock(resp_get_commit): project = self.gl.projects.get(1, lazy=True) commit = project.commits.get("6b2257ea") self.assertEqual(commit.short_id, "6b2257ea")