summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Wittig <max.wittig@siemens.com>2020-02-20 09:06:23 +0100
committerGitHub <noreply@github.com>2020-02-20 09:06:23 +0100
commite8f0921d164c4b7db78e2f62e75eb32094b4456e (patch)
treed603f98235d9bfb6b1968a4e3412bb0d8efe72ba
parent19242c398b9074e04e35cc687c31c543a10db280 (diff)
parentcb436951b1fde9c010e966819c75d0d7adacf17d (diff)
downloadgitlab-e8f0921d164c4b7db78e2f62e75eb32094b4456e.tar.gz
Merge pull request #1020 from nejch/feat/revert-commit-api
feat: add support for commit revert API (#991)
-rw-r--r--docs/gl_objects/commits.rst4
-rw-r--r--gitlab/exceptions.py4
-rw-r--r--gitlab/tests/test_gitlab.py44
-rw-r--r--gitlab/v4/objects.py20
-rwxr-xr-xtools/cli_test_v4.sh9
-rw-r--r--tools/python_test_v4.py15
6 files changed, 96 insertions, 0 deletions
diff --git a/docs/gl_objects/commits.rst b/docs/gl_objects/commits.rst
index 97cd1c4..abfedc8 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 aff3c87..d6791f2 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/tests/test_gitlab.py b/gitlab/tests/test_gitlab.py
index 3eccf6e..b56889a 100644
--- a/gitlab/tests/test_gitlab.py
+++ b/gitlab/tests/test_gitlab.py
@@ -794,6 +794,50 @@ class TestGitlab(unittest.TestCase):
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/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_commit):
+ 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")
+
+ 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"
diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py
index b31870c..83f77d3 100644
--- a/gitlab/v4/objects.py
+++ b/gitlab/v4/objects.py
@@ -2136,6 +2136,26 @@ class ProjectCommit(RESTObject):
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
+
+ Returns:
+ dict: The new commit data (*not* a RESTObject)
+ """
+ path = "%s/%s/revert" % (self.manager.path, self.get_id())
+ post_data = {"branch": branch}
+ return 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 dc6e0b2..b7ed708 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 bffdd2a..49f99e5 100644
--- a/tools/python_test_v4.py
+++ b/tools/python_test_v4.py
@@ -462,6 +462,21 @@ d_note_from_get.delete()
discussion = commit.discussions.get(discussion.id)
# assert len(discussion.attributes["notes"]) == 1
+# Revert commit
+revert_commit = commit.revert(branch="master")
+
+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()