Skip to content

Commit e8f0921

Browse files
authored
Merge pull request #1020 from nejch/feat/revert-commit-api
feat: add support for commit revert API (#991)
2 parents 19242c3 + cb43695 commit e8f0921

File tree

6 files changed

+96
-0
lines changed

6 files changed

+96
-0
lines changed

docs/gl_objects/commits.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ Cherry-pick a commit into another branch::
7272

7373
commit.cherry_pick(branch='target_branch')
7474

75+
Revert a commit on a given branch::
76+
77+
commit.revert(branch='target_branch')
78+
7579
Get the references the commit has been pushed to (branches and tags)::
7680

7781
commit.refs() # all references

gitlab/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ class GitlabRepairError(GitlabOperationError):
245245
pass
246246

247247

248+
class GitlabRevertError(GitlabOperationError):
249+
pass
250+
251+
248252
class GitlabLicenseError(GitlabOperationError):
249253
pass
250254

gitlab/tests/test_gitlab.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,50 @@ def resp_deactivate(url, request):
794794
self.gl.users.get(1, lazy=True).activate()
795795
self.gl.users.get(1, lazy=True).deactivate()
796796

797+
def test_commit_revert(self):
798+
@urlmatch(
799+
scheme="http",
800+
netloc="localhost",
801+
path="/api/v4/projects/1/repository/commits/6b2257ea",
802+
method="get",
803+
)
804+
def resp_get_commit(url, request):
805+
headers = {"content-type": "application/json"}
806+
content = """{
807+
"id": "6b2257eabcec3db1f59dafbd84935e3caea04235",
808+
"short_id": "6b2257ea",
809+
"title": "Initial commit"
810+
}"""
811+
content = content.encode("utf-8")
812+
return response(200, content, headers, None, 5, request)
813+
814+
@urlmatch(
815+
scheme="http",
816+
netloc="localhost",
817+
path="/api/v4/projects/1/repository/commits/6b2257ea",
818+
method="post",
819+
)
820+
def resp_revert_commit(url, request):
821+
headers = {"content-type": "application/json"}
822+
content = """{
823+
"id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad",
824+
"short_id": "8b090c1b",
825+
"title":"Revert \\"Initial commit\\""
826+
}"""
827+
content = content.encode("utf-8")
828+
return response(200, content, headers, None, 5, request)
829+
830+
with HTTMock(resp_get_commit):
831+
project = self.gl.projects.get(1, lazy=True)
832+
commit = project.commits.get("6b2257ea")
833+
self.assertEqual(commit.short_id, "6b2257ea")
834+
self.assertEqual(commit.title, "Initial commit")
835+
836+
with HTTMock(resp_revert_commit):
837+
revert_commit = commit.revert(branch="master")
838+
self.assertEqual(revert_commit["short_id"], "8b090c1b")
839+
self.assertEqual(revert_commit["title"], 'Revert "Initial commit"')
840+
797841
def test_update_submodule(self):
798842
@urlmatch(
799843
scheme="http", netloc="localhost", path="/api/v4/projects/1$", method="get"

gitlab/v4/objects.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,6 +2136,26 @@ def merge_requests(self, **kwargs):
21362136
path = "%s/%s/merge_requests" % (self.manager.path, self.get_id())
21372137
return self.manager.gitlab.http_get(path, **kwargs)
21382138

2139+
@cli.register_custom_action("ProjectCommit", ("branch",))
2140+
@exc.on_http_error(exc.GitlabRevertError)
2141+
def revert(self, branch, **kwargs):
2142+
"""Revert a commit on a given branch.
2143+
2144+
Args:
2145+
branch (str): Name of target branch
2146+
**kwargs: Extra options to send to the server (e.g. sudo)
2147+
2148+
Raises:
2149+
GitlabAuthenticationError: If authentication is not correct
2150+
GitlabRevertError: If the revert could not be performed
2151+
2152+
Returns:
2153+
dict: The new commit data (*not* a RESTObject)
2154+
"""
2155+
path = "%s/%s/revert" % (self.manager.path, self.get_id())
2156+
post_data = {"branch": branch}
2157+
return self.manager.gitlab.http_post(path, post_data=post_data, **kwargs)
2158+
21392159

21402160
class ProjectCommitManager(RetrieveMixin, CreateMixin, RESTManager):
21412161
_path = "/projects/%(project_id)s/repository/commits"

tools/cli_test_v4.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ testcase "merge request validation" '
100100
--iid "$MR_ID" >/dev/null 2>&1
101101
'
102102

103+
# Test revert commit
104+
COMMITS=$(GITLAB -v project-commit list --project-id "${PROJECT_ID}")
105+
COMMIT_ID=$(pecho "${COMMITS}" | grep -m1 '^id:' | cut -d' ' -f2)
106+
107+
testcase "revert commit" '
108+
GITLAB project-commit revert --project-id "$PROJECT_ID" \
109+
--id "$COMMIT_ID" --branch master
110+
'
111+
103112
# Test project labels
104113
testcase "create project label" '
105114
OUTPUT=$(GITLAB -v project-label create --project-id $PROJECT_ID \

tools/python_test_v4.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,21 @@
462462
discussion = commit.discussions.get(discussion.id)
463463
# assert len(discussion.attributes["notes"]) == 1
464464

465+
# Revert commit
466+
revert_commit = commit.revert(branch="master")
467+
468+
expected_message = 'Revert "{}"\n\nThis reverts commit {}'.format(
469+
commit.message, commit.id
470+
)
471+
assert revert_commit["message"] == expected_message
472+
473+
try:
474+
commit.revert(branch="master")
475+
# Only here to really ensure expected error without a full test framework
476+
raise AssertionError("Two revert attempts should raise GitlabRevertError")
477+
except gitlab.GitlabRevertError:
478+
pass
479+
465480
# housekeeping
466481
admin_project.housekeeping()
467482

0 commit comments

Comments
 (0)