summaryrefslogtreecommitdiff
path: root/gitlab/v4/objects/merge_requests.py
diff options
context:
space:
mode:
Diffstat (limited to 'gitlab/v4/objects/merge_requests.py')
-rw-r--r--gitlab/v4/objects/merge_requests.py375
1 files changed, 375 insertions, 0 deletions
diff --git a/gitlab/v4/objects/merge_requests.py b/gitlab/v4/objects/merge_requests.py
new file mode 100644
index 0000000..477ccc6
--- /dev/null
+++ b/gitlab/v4/objects/merge_requests.py
@@ -0,0 +1,375 @@
+from gitlab import cli, types
+from gitlab import exceptions as exc
+from gitlab.base import * # noqa
+from gitlab.mixins import * # noqa
+from .commits import ProjectCommit, ProjectCommitManager
+from .issues import ProjectIssue, ProjectIssueManager
+from .merge_request_approvals import (
+ ProjectMergeRequestApprovalManager,
+ ProjectMergeRequestApprovalRuleManager,
+)
+from .award_emojis import ProjectMergeRequestAwardEmojiManager
+from .discussions import ProjectMergeRequestDiscussionManager
+from .notes import ProjectMergeRequestNoteManager
+from .events import (
+ ProjectMergeRequestResourceLabelEventManager,
+ ProjectMergeRequestResourceMilestoneEventManager,
+)
+
+
+class MergeRequest(RESTObject):
+ pass
+
+
+class MergeRequestManager(ListMixin, RESTManager):
+ _path = "/merge_requests"
+ _obj_cls = MergeRequest
+ _from_parent_attrs = {"group_id": "id"}
+ _list_filters = (
+ "state",
+ "order_by",
+ "sort",
+ "milestone",
+ "view",
+ "labels",
+ "created_after",
+ "created_before",
+ "updated_after",
+ "updated_before",
+ "scope",
+ "author_id",
+ "assignee_id",
+ "my_reaction_emoji",
+ "source_branch",
+ "target_branch",
+ "search",
+ "wip",
+ )
+ _types = {"labels": types.ListAttribute}
+
+
+class GroupMergeRequest(RESTObject):
+ pass
+
+
+class GroupMergeRequestManager(ListMixin, RESTManager):
+ _path = "/groups/%(group_id)s/merge_requests"
+ _obj_cls = GroupMergeRequest
+ _from_parent_attrs = {"group_id": "id"}
+ _list_filters = (
+ "state",
+ "order_by",
+ "sort",
+ "milestone",
+ "view",
+ "labels",
+ "created_after",
+ "created_before",
+ "updated_after",
+ "updated_before",
+ "scope",
+ "author_id",
+ "assignee_id",
+ "my_reaction_emoji",
+ "source_branch",
+ "target_branch",
+ "search",
+ "wip",
+ )
+ _types = {"labels": types.ListAttribute}
+
+
+class ProjectMergeRequest(
+ SubscribableMixin,
+ TodoMixin,
+ TimeTrackingMixin,
+ ParticipantsMixin,
+ SaveMixin,
+ ObjectDeleteMixin,
+ RESTObject,
+):
+ _id_attr = "iid"
+
+ _managers = (
+ ("approvals", "ProjectMergeRequestApprovalManager"),
+ ("approval_rules", "ProjectMergeRequestApprovalRuleManager"),
+ ("awardemojis", "ProjectMergeRequestAwardEmojiManager"),
+ ("diffs", "ProjectMergeRequestDiffManager"),
+ ("discussions", "ProjectMergeRequestDiscussionManager"),
+ ("notes", "ProjectMergeRequestNoteManager"),
+ ("resourcelabelevents", "ProjectMergeRequestResourceLabelEventManager"),
+ ("resourcemilestoneevents", "ProjectMergeRequestResourceMilestoneEventManager"),
+ )
+
+ @cli.register_custom_action("ProjectMergeRequest")
+ @exc.on_http_error(exc.GitlabMROnBuildSuccessError)
+ def cancel_merge_when_pipeline_succeeds(self, **kwargs):
+ """Cancel merge when the pipeline succeeds.
+
+ Args:
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabMROnBuildSuccessError: If the server could not handle the
+ request
+ """
+
+ path = "%s/%s/cancel_merge_when_pipeline_succeeds" % (
+ self.manager.path,
+ self.get_id(),
+ )
+ server_data = self.manager.gitlab.http_put(path, **kwargs)
+ self._update_attrs(server_data)
+
+ @cli.register_custom_action("ProjectMergeRequest")
+ @exc.on_http_error(exc.GitlabListError)
+ def closes_issues(self, **kwargs):
+ """List issues that will close on merge."
+
+ Args:
+ all (bool): If True, return all the items, without pagination
+ per_page (int): Number of items to retrieve per request
+ page (int): ID of the page to return (starts with page 1)
+ as_list (bool): If set to False and no pagination option is
+ defined, return a generator instead of a list
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabListError: If the list could not be retrieved
+
+ Returns:
+ RESTObjectList: List of issues
+ """
+ path = "%s/%s/closes_issues" % (self.manager.path, self.get_id())
+ data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
+ manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)
+ return RESTObjectList(manager, ProjectIssue, data_list)
+
+ @cli.register_custom_action("ProjectMergeRequest")
+ @exc.on_http_error(exc.GitlabListError)
+ def commits(self, **kwargs):
+ """List the merge request commits.
+
+ Args:
+ all (bool): If True, return all the items, without pagination
+ per_page (int): Number of items to retrieve per request
+ page (int): ID of the page to return (starts with page 1)
+ as_list (bool): If set to False and no pagination option is
+ defined, return a generator instead of a list
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabListError: If the list could not be retrieved
+
+ Returns:
+ RESTObjectList: The list of commits
+ """
+
+ path = "%s/%s/commits" % (self.manager.path, self.get_id())
+ data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
+ manager = ProjectCommitManager(self.manager.gitlab, parent=self.manager._parent)
+ return RESTObjectList(manager, ProjectCommit, data_list)
+
+ @cli.register_custom_action("ProjectMergeRequest")
+ @exc.on_http_error(exc.GitlabListError)
+ def changes(self, **kwargs):
+ """List the merge request changes.
+
+ Args:
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabListError: If the list could not be retrieved
+
+ Returns:
+ RESTObjectList: List of changes
+ """
+ path = "%s/%s/changes" % (self.manager.path, self.get_id())
+ return self.manager.gitlab.http_get(path, **kwargs)
+
+ @cli.register_custom_action("ProjectMergeRequest")
+ @exc.on_http_error(exc.GitlabListError)
+ def pipelines(self, **kwargs):
+ """List the merge request pipelines.
+
+ Args:
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabListError: If the list could not be retrieved
+
+ Returns:
+ RESTObjectList: List of changes
+ """
+
+ path = "%s/%s/pipelines" % (self.manager.path, self.get_id())
+ return self.manager.gitlab.http_get(path, **kwargs)
+
+ @cli.register_custom_action("ProjectMergeRequest", tuple(), ("sha"))
+ @exc.on_http_error(exc.GitlabMRApprovalError)
+ def approve(self, sha=None, **kwargs):
+ """Approve the merge request.
+
+ Args:
+ sha (str): Head SHA of MR
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabMRApprovalError: If the approval failed
+ """
+ path = "%s/%s/approve" % (self.manager.path, self.get_id())
+ data = {}
+ if sha:
+ data["sha"] = sha
+
+ server_data = self.manager.gitlab.http_post(path, post_data=data, **kwargs)
+ self._update_attrs(server_data)
+
+ @cli.register_custom_action("ProjectMergeRequest")
+ @exc.on_http_error(exc.GitlabMRApprovalError)
+ def unapprove(self, **kwargs):
+ """Unapprove the merge request.
+
+ Args:
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabMRApprovalError: If the unapproval failed
+ """
+ path = "%s/%s/unapprove" % (self.manager.path, self.get_id())
+ data = {}
+
+ server_data = self.manager.gitlab.http_post(path, post_data=data, **kwargs)
+ self._update_attrs(server_data)
+
+ @cli.register_custom_action("ProjectMergeRequest")
+ @exc.on_http_error(exc.GitlabMRRebaseError)
+ def rebase(self, **kwargs):
+ """Attempt to rebase the source branch onto the target branch
+
+ Args:
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabMRRebaseError: If rebasing failed
+ """
+ path = "%s/%s/rebase" % (self.manager.path, self.get_id())
+ data = {}
+ return self.manager.gitlab.http_put(path, post_data=data, **kwargs)
+
+ @cli.register_custom_action(
+ "ProjectMergeRequest",
+ tuple(),
+ (
+ "merge_commit_message",
+ "should_remove_source_branch",
+ "merge_when_pipeline_succeeds",
+ ),
+ )
+ @exc.on_http_error(exc.GitlabMRClosedError)
+ def merge(
+ self,
+ merge_commit_message=None,
+ should_remove_source_branch=False,
+ merge_when_pipeline_succeeds=False,
+ **kwargs
+ ):
+ """Accept the merge request.
+
+ Args:
+ merge_commit_message (bool): Commit message
+ should_remove_source_branch (bool): If True, removes the source
+ branch
+ merge_when_pipeline_succeeds (bool): Wait for the build to succeed,
+ then merge
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabMRClosedError: If the merge failed
+ """
+ path = "%s/%s/merge" % (self.manager.path, self.get_id())
+ data = {}
+ if merge_commit_message:
+ data["merge_commit_message"] = merge_commit_message
+ if should_remove_source_branch:
+ data["should_remove_source_branch"] = True
+ if merge_when_pipeline_succeeds:
+ data["merge_when_pipeline_succeeds"] = True
+
+ server_data = self.manager.gitlab.http_put(path, query_data=data, **kwargs)
+ self._update_attrs(server_data)
+
+
+class ProjectMergeRequestManager(CRUDMixin, RESTManager):
+ _path = "/projects/%(project_id)s/merge_requests"
+ _obj_cls = ProjectMergeRequest
+ _from_parent_attrs = {"project_id": "id"}
+ _create_attrs = (
+ ("source_branch", "target_branch", "title"),
+ (
+ "assignee_id",
+ "description",
+ "target_project_id",
+ "labels",
+ "milestone_id",
+ "remove_source_branch",
+ "allow_maintainer_to_push",
+ "squash",
+ ),
+ )
+ _update_attrs = (
+ tuple(),
+ (
+ "target_branch",
+ "assignee_id",
+ "title",
+ "description",
+ "state_event",
+ "labels",
+ "milestone_id",
+ "remove_source_branch",
+ "discussion_locked",
+ "allow_maintainer_to_push",
+ "squash",
+ ),
+ )
+ _list_filters = (
+ "state",
+ "order_by",
+ "sort",
+ "milestone",
+ "view",
+ "labels",
+ "created_after",
+ "created_before",
+ "updated_after",
+ "updated_before",
+ "scope",
+ "author_id",
+ "assignee_id",
+ "my_reaction_emoji",
+ "source_branch",
+ "target_branch",
+ "search",
+ "wip",
+ )
+ _types = {"labels": types.ListAttribute}
+
+
+class ProjectMergeRequestDiff(RESTObject):
+ pass
+
+
+class ProjectMergeRequestDiffManager(RetrieveMixin, RESTManager):
+ _path = "/projects/%(project_id)s/merge_requests/%(mr_iid)s/versions"
+ _obj_cls = ProjectMergeRequestDiff
+ _from_parent_attrs = {"project_id": "project_id", "mr_iid": "iid"}