...

Source file src/github.com/xanzy/go-gitlab/merge_requests.go

Documentation: github.com/xanzy/go-gitlab

     1  //
     2  // Copyright 2021, Sander van Harmelen
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package gitlab
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"net/http"
    23  	"time"
    24  )
    25  
    26  // MergeRequestsService handles communication with the merge requests related
    27  // methods of the GitLab API.
    28  //
    29  // GitLab API docs: https://docs.gitlab.com/ee/api/merge_requests.html
    30  type MergeRequestsService struct {
    31  	client    *Client
    32  	timeStats *timeStatsService
    33  }
    34  
    35  // MergeRequest represents a GitLab merge request.
    36  //
    37  // GitLab API docs: https://docs.gitlab.com/ee/api/merge_requests.html
    38  type MergeRequest struct {
    39  	ID                        int                 `json:"id"`
    40  	IID                       int                 `json:"iid"`
    41  	TargetBranch              string              `json:"target_branch"`
    42  	SourceBranch              string              `json:"source_branch"`
    43  	ProjectID                 int                 `json:"project_id"`
    44  	Title                     string              `json:"title"`
    45  	State                     string              `json:"state"`
    46  	CreatedAt                 *time.Time          `json:"created_at"`
    47  	UpdatedAt                 *time.Time          `json:"updated_at"`
    48  	Upvotes                   int                 `json:"upvotes"`
    49  	Downvotes                 int                 `json:"downvotes"`
    50  	Author                    *BasicUser          `json:"author"`
    51  	Assignee                  *BasicUser          `json:"assignee"`
    52  	Assignees                 []*BasicUser        `json:"assignees"`
    53  	Reviewers                 []*BasicUser        `json:"reviewers"`
    54  	SourceProjectID           int                 `json:"source_project_id"`
    55  	TargetProjectID           int                 `json:"target_project_id"`
    56  	Labels                    Labels              `json:"labels"`
    57  	LabelDetails              []*LabelDetails     `json:"label_details"`
    58  	Description               string              `json:"description"`
    59  	Draft                     bool                `json:"draft"`
    60  	WorkInProgress            bool                `json:"work_in_progress"`
    61  	Milestone                 *Milestone          `json:"milestone"`
    62  	MergeWhenPipelineSucceeds bool                `json:"merge_when_pipeline_succeeds"`
    63  	DetailedMergeStatus       string              `json:"detailed_merge_status"`
    64  	MergeError                string              `json:"merge_error"`
    65  	MergedBy                  *BasicUser          `json:"merged_by"`
    66  	MergedAt                  *time.Time          `json:"merged_at"`
    67  	ClosedBy                  *BasicUser          `json:"closed_by"`
    68  	ClosedAt                  *time.Time          `json:"closed_at"`
    69  	Subscribed                bool                `json:"subscribed"`
    70  	SHA                       string              `json:"sha"`
    71  	MergeCommitSHA            string              `json:"merge_commit_sha"`
    72  	SquashCommitSHA           string              `json:"squash_commit_sha"`
    73  	UserNotesCount            int                 `json:"user_notes_count"`
    74  	ChangesCount              string              `json:"changes_count"`
    75  	ShouldRemoveSourceBranch  bool                `json:"should_remove_source_branch"`
    76  	ForceRemoveSourceBranch   bool                `json:"force_remove_source_branch"`
    77  	AllowCollaboration        bool                `json:"allow_collaboration"`
    78  	WebURL                    string              `json:"web_url"`
    79  	References                *IssueReferences    `json:"references"`
    80  	DiscussionLocked          bool                `json:"discussion_locked"`
    81  	Changes                   []*MergeRequestDiff `json:"changes"`
    82  	User                      struct {
    83  		CanMerge bool `json:"can_merge"`
    84  	} `json:"user"`
    85  	TimeStats    *TimeStats    `json:"time_stats"`
    86  	Squash       bool          `json:"squash"`
    87  	Pipeline     *PipelineInfo `json:"pipeline"`
    88  	HeadPipeline *Pipeline     `json:"head_pipeline"`
    89  	DiffRefs     struct {
    90  		BaseSha  string `json:"base_sha"`
    91  		HeadSha  string `json:"head_sha"`
    92  		StartSha string `json:"start_sha"`
    93  	} `json:"diff_refs"`
    94  	DivergedCommitsCount        int                    `json:"diverged_commits_count"`
    95  	RebaseInProgress            bool                   `json:"rebase_in_progress"`
    96  	ApprovalsBeforeMerge        int                    `json:"approvals_before_merge"`
    97  	Reference                   string                 `json:"reference"`
    98  	FirstContribution           bool                   `json:"first_contribution"`
    99  	TaskCompletionStatus        *TasksCompletionStatus `json:"task_completion_status"`
   100  	HasConflicts                bool                   `json:"has_conflicts"`
   101  	BlockingDiscussionsResolved bool                   `json:"blocking_discussions_resolved"`
   102  	Overflow                    bool                   `json:"overflow"`
   103  
   104  	// Deprecated: This parameter is replaced by DetailedMergeStatus in GitLab 15.6.
   105  	MergeStatus string `json:"merge_status"`
   106  }
   107  
   108  func (m MergeRequest) String() string {
   109  	return Stringify(m)
   110  }
   111  
   112  func (m *MergeRequest) UnmarshalJSON(data []byte) error {
   113  	type alias MergeRequest
   114  
   115  	raw := make(map[string]interface{})
   116  	err := json.Unmarshal(data, &raw)
   117  	if err != nil {
   118  		return err
   119  	}
   120  
   121  	labelDetails, ok := raw["labels"].([]interface{})
   122  	if ok && len(labelDetails) > 0 {
   123  		// We only want to change anything if we got label details.
   124  		if _, ok := labelDetails[0].(map[string]interface{}); !ok {
   125  			return json.Unmarshal(data, (*alias)(m))
   126  		}
   127  
   128  		labels := make([]interface{}, len(labelDetails))
   129  		for i, details := range labelDetails {
   130  			labels[i] = details.(map[string]interface{})["name"]
   131  		}
   132  
   133  		// Set the correct values
   134  		raw["labels"] = labels
   135  		raw["label_details"] = labelDetails
   136  
   137  		data, err = json.Marshal(raw)
   138  		if err != nil {
   139  			return err
   140  		}
   141  	}
   142  
   143  	return json.Unmarshal(data, (*alias)(m))
   144  }
   145  
   146  // MergeRequestDiff represents Gitlab merge request diff.
   147  //
   148  // Gitlab API docs:
   149  // https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-diffs
   150  type MergeRequestDiff struct {
   151  	OldPath     string `json:"old_path"`
   152  	NewPath     string `json:"new_path"`
   153  	AMode       string `json:"a_mode"`
   154  	BMode       string `json:"b_mode"`
   155  	Diff        string `json:"diff"`
   156  	NewFile     bool   `json:"new_file"`
   157  	RenamedFile bool   `json:"renamed_file"`
   158  	DeletedFile bool   `json:"deleted_file"`
   159  }
   160  
   161  // MergeRequestDiffVersion represents Gitlab merge request version.
   162  //
   163  // Gitlab API docs:
   164  // https://docs.gitlab.com/ee/api/merge_requests.html#get-merge-request-diff-versions
   165  type MergeRequestDiffVersion struct {
   166  	ID             int        `json:"id"`
   167  	HeadCommitSHA  string     `json:"head_commit_sha,omitempty"`
   168  	BaseCommitSHA  string     `json:"base_commit_sha,omitempty"`
   169  	StartCommitSHA string     `json:"start_commit_sha,omitempty"`
   170  	CreatedAt      *time.Time `json:"created_at,omitempty"`
   171  	MergeRequestID int        `json:"merge_request_id,omitempty"`
   172  	State          string     `json:"state,omitempty"`
   173  	RealSize       string     `json:"real_size,omitempty"`
   174  	Commits        []*Commit  `json:"commits,omitempty"`
   175  	Diffs          []*Diff    `json:"diffs,omitempty"`
   176  }
   177  
   178  func (m MergeRequestDiffVersion) String() string {
   179  	return Stringify(m)
   180  }
   181  
   182  // ListMergeRequestsOptions represents the available ListMergeRequests()
   183  // options.
   184  //
   185  // GitLab API docs:
   186  // https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests
   187  type ListMergeRequestsOptions struct {
   188  	ListOptions
   189  	Approved               *string           `url:"approved,omitempty" json:"approved,omitempty"`
   190  	State                  *string           `url:"state,omitempty" json:"state,omitempty"`
   191  	OrderBy                *string           `url:"order_by,omitempty" json:"order_by,omitempty"`
   192  	Sort                   *string           `url:"sort,omitempty" json:"sort,omitempty"`
   193  	Milestone              *string           `url:"milestone,omitempty" json:"milestone,omitempty"`
   194  	View                   *string           `url:"view,omitempty" json:"view,omitempty"`
   195  	Labels                 *LabelOptions     `url:"labels,comma,omitempty" json:"labels,omitempty"`
   196  	NotLabels              *LabelOptions     `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"`
   197  	WithLabelsDetails      *bool             `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"`
   198  	WithMergeStatusRecheck *bool             `url:"with_merge_status_recheck,omitempty" json:"with_merge_status_recheck,omitempty"`
   199  	CreatedAfter           *time.Time        `url:"created_after,omitempty" json:"created_after,omitempty"`
   200  	CreatedBefore          *time.Time        `url:"created_before,omitempty" json:"created_before,omitempty"`
   201  	UpdatedAfter           *time.Time        `url:"updated_after,omitempty" json:"updated_after,omitempty"`
   202  	UpdatedBefore          *time.Time        `url:"updated_before,omitempty" json:"updated_before,omitempty"`
   203  	Scope                  *string           `url:"scope,omitempty" json:"scope,omitempty"`
   204  	AuthorID               *int              `url:"author_id,omitempty" json:"author_id,omitempty"`
   205  	AuthorUsername         *string           `url:"author_username,omitempty" json:"author_username,omitempty"`
   206  	NotAuthorUsername      *string           `url:"not[author_username],omitempty" json:"not[author_username],omitempty"`
   207  	AssigneeID             *AssigneeIDValue  `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
   208  	ApproverIDs            *ApproverIDsValue `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
   209  	ApprovedByIDs          *ApproverIDsValue `url:"approved_by_ids,omitempty" json:"approved_by_ids,omitempty"`
   210  	ReviewerID             *ReviewerIDValue  `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
   211  	ReviewerUsername       *string           `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
   212  	MyReactionEmoji        *string           `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
   213  	SourceBranch           *string           `url:"source_branch,omitempty" json:"source_branch,omitempty"`
   214  	TargetBranch           *string           `url:"target_branch,omitempty" json:"target_branch,omitempty"`
   215  	Search                 *string           `url:"search,omitempty" json:"search,omitempty"`
   216  	In                     *string           `url:"in,omitempty" json:"in,omitempty"`
   217  	Draft                  *bool             `url:"draft,omitempty" json:"draft,omitempty"`
   218  	WIP                    *string           `url:"wip,omitempty" json:"wip,omitempty"`
   219  }
   220  
   221  // ListMergeRequests gets all merge requests. The state parameter can be used
   222  // to get only merge requests with a given state (opened, closed, or merged)
   223  // or all of them (all). The pagination parameters page and per_page can be
   224  // used to restrict the list of merge requests.
   225  //
   226  // GitLab API docs:
   227  // https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests
   228  func (s *MergeRequestsService) ListMergeRequests(opt *ListMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) {
   229  	req, err := s.client.NewRequest(http.MethodGet, "merge_requests", opt, options)
   230  	if err != nil {
   231  		return nil, nil, err
   232  	}
   233  
   234  	var m []*MergeRequest
   235  	resp, err := s.client.Do(req, &m)
   236  	if err != nil {
   237  		return nil, resp, err
   238  	}
   239  
   240  	return m, resp, nil
   241  }
   242  
   243  // ListProjectMergeRequestsOptions represents the available ListMergeRequests()
   244  // options.
   245  //
   246  // GitLab API docs:
   247  // https://docs.gitlab.com/ee/api/merge_requests.html#list-project-merge-requests
   248  type ListProjectMergeRequestsOptions struct {
   249  	ListOptions
   250  	IIDs                   *[]int            `url:"iids[],omitempty" json:"iids,omitempty"`
   251  	State                  *string           `url:"state,omitempty" json:"state,omitempty"`
   252  	OrderBy                *string           `url:"order_by,omitempty" json:"order_by,omitempty"`
   253  	Sort                   *string           `url:"sort,omitempty" json:"sort,omitempty"`
   254  	Milestone              *string           `url:"milestone,omitempty" json:"milestone,omitempty"`
   255  	View                   *string           `url:"view,omitempty" json:"view,omitempty"`
   256  	Labels                 *LabelOptions     `url:"labels,comma,omitempty" json:"labels,omitempty"`
   257  	NotLabels              *LabelOptions     `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"`
   258  	WithLabelsDetails      *bool             `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"`
   259  	WithMergeStatusRecheck *bool             `url:"with_merge_status_recheck,omitempty" json:"with_merge_status_recheck,omitempty"`
   260  	CreatedAfter           *time.Time        `url:"created_after,omitempty" json:"created_after,omitempty"`
   261  	CreatedBefore          *time.Time        `url:"created_before,omitempty" json:"created_before,omitempty"`
   262  	UpdatedAfter           *time.Time        `url:"updated_after,omitempty" json:"updated_after,omitempty"`
   263  	UpdatedBefore          *time.Time        `url:"updated_before,omitempty" json:"updated_before,omitempty"`
   264  	Scope                  *string           `url:"scope,omitempty" json:"scope,omitempty"`
   265  	AuthorID               *int              `url:"author_id,omitempty" json:"author_id,omitempty"`
   266  	AuthorUsername         *string           `url:"author_username,omitempty" json:"author_username,omitempty"`
   267  	NotAuthorUsername      *string           `url:"not[author_username],omitempty" json:"not[author_username],omitempty"`
   268  	AssigneeID             *AssigneeIDValue  `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
   269  	ApproverIDs            *ApproverIDsValue `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
   270  	ApprovedByIDs          *ApproverIDsValue `url:"approved_by_ids,omitempty" json:"approved_by_ids,omitempty"`
   271  	ReviewerID             *ReviewerIDValue  `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
   272  	ReviewerUsername       *string           `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
   273  	MyReactionEmoji        *string           `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
   274  	SourceBranch           *string           `url:"source_branch,omitempty" json:"source_branch,omitempty"`
   275  	TargetBranch           *string           `url:"target_branch,omitempty" json:"target_branch,omitempty"`
   276  	Search                 *string           `url:"search,omitempty" json:"search,omitempty"`
   277  	Draft                  *bool             `url:"draft,omitempty" json:"draft,omitempty"`
   278  	WIP                    *string           `url:"wip,omitempty" json:"wip,omitempty"`
   279  }
   280  
   281  // ListProjectMergeRequests gets all merge requests for this project.
   282  //
   283  // GitLab API docs:
   284  // https://docs.gitlab.com/ee/api/merge_requests.html#list-project-merge-requests
   285  func (s *MergeRequestsService) ListProjectMergeRequests(pid interface{}, opt *ListProjectMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) {
   286  	project, err := parseID(pid)
   287  	if err != nil {
   288  		return nil, nil, err
   289  	}
   290  	u := fmt.Sprintf("projects/%s/merge_requests", PathEscape(project))
   291  
   292  	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
   293  	if err != nil {
   294  		return nil, nil, err
   295  	}
   296  
   297  	var m []*MergeRequest
   298  	resp, err := s.client.Do(req, &m)
   299  	if err != nil {
   300  		return nil, resp, err
   301  	}
   302  
   303  	return m, resp, nil
   304  }
   305  
   306  // ListGroupMergeRequestsOptions represents the available ListGroupMergeRequests()
   307  // options.
   308  //
   309  // GitLab API docs:
   310  // https://docs.gitlab.com/ee/api/merge_requests.html#list-group-merge-requests
   311  type ListGroupMergeRequestsOptions struct {
   312  	ListOptions
   313  	State                  *string           `url:"state,omitempty" json:"state,omitempty"`
   314  	OrderBy                *string           `url:"order_by,omitempty" json:"order_by,omitempty"`
   315  	Sort                   *string           `url:"sort,omitempty" json:"sort,omitempty"`
   316  	Milestone              *string           `url:"milestone,omitempty" json:"milestone,omitempty"`
   317  	View                   *string           `url:"view,omitempty" json:"view,omitempty"`
   318  	Labels                 *LabelOptions     `url:"labels,comma,omitempty" json:"labels,omitempty"`
   319  	NotLabels              *LabelOptions     `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"`
   320  	WithLabelsDetails      *bool             `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"`
   321  	WithMergeStatusRecheck *bool             `url:"with_merge_status_recheck,omitempty" json:"with_merge_status_recheck,omitempty"`
   322  	CreatedAfter           *time.Time        `url:"created_after,omitempty" json:"created_after,omitempty"`
   323  	CreatedBefore          *time.Time        `url:"created_before,omitempty" json:"created_before,omitempty"`
   324  	UpdatedAfter           *time.Time        `url:"updated_after,omitempty" json:"updated_after,omitempty"`
   325  	UpdatedBefore          *time.Time        `url:"updated_before,omitempty" json:"updated_before,omitempty"`
   326  	Scope                  *string           `url:"scope,omitempty" json:"scope,omitempty"`
   327  	AuthorID               *int              `url:"author_id,omitempty" json:"author_id,omitempty"`
   328  	AuthorUsername         *string           `url:"author_username,omitempty" json:"author_username,omitempty"`
   329  	NotAuthorUsername      *string           `url:"not[author_username],omitempty" json:"not[author_username],omitempty"`
   330  	AssigneeID             *AssigneeIDValue  `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
   331  	ApproverIDs            *ApproverIDsValue `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
   332  	ApprovedByIDs          *ApproverIDsValue `url:"approved_by_ids,omitempty" json:"approved_by_ids,omitempty"`
   333  	ReviewerID             *ReviewerIDValue  `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
   334  	ReviewerUsername       *string           `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
   335  	MyReactionEmoji        *string           `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
   336  	SourceBranch           *string           `url:"source_branch,omitempty" json:"source_branch,omitempty"`
   337  	TargetBranch           *string           `url:"target_branch,omitempty" json:"target_branch,omitempty"`
   338  	Search                 *string           `url:"search,omitempty" json:"search,omitempty"`
   339  	In                     *string           `url:"in,omitempty" json:"in,omitempty"`
   340  	Draft                  *bool             `url:"draft,omitempty" json:"draft,omitempty"`
   341  	WIP                    *string           `url:"wip,omitempty" json:"wip,omitempty"`
   342  }
   343  
   344  // ListGroupMergeRequests gets all merge requests for this group.
   345  //
   346  // GitLab API docs:
   347  // https://docs.gitlab.com/ee/api/merge_requests.html#list-group-merge-requests
   348  func (s *MergeRequestsService) ListGroupMergeRequests(gid interface{}, opt *ListGroupMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) {
   349  	group, err := parseID(gid)
   350  	if err != nil {
   351  		return nil, nil, err
   352  	}
   353  	u := fmt.Sprintf("groups/%s/merge_requests", PathEscape(group))
   354  
   355  	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
   356  	if err != nil {
   357  		return nil, nil, err
   358  	}
   359  
   360  	var m []*MergeRequest
   361  	resp, err := s.client.Do(req, &m)
   362  	if err != nil {
   363  		return nil, resp, err
   364  	}
   365  
   366  	return m, resp, nil
   367  }
   368  
   369  // GetMergeRequestsOptions represents the available GetMergeRequests()
   370  // options.
   371  //
   372  // GitLab API docs:
   373  // https://docs.gitlab.com/ee/api/merge_requests.html#get-single-mr
   374  type GetMergeRequestsOptions struct {
   375  	RenderHTML                  *bool `url:"render_html,omitempty" json:"render_html,omitempty"`
   376  	IncludeDivergedCommitsCount *bool `url:"include_diverged_commits_count,omitempty" json:"include_diverged_commits_count,omitempty"`
   377  	IncludeRebaseInProgress     *bool `url:"include_rebase_in_progress,omitempty" json:"include_rebase_in_progress,omitempty"`
   378  }
   379  
   380  // GetMergeRequest shows information about a single merge request.
   381  //
   382  // GitLab API docs:
   383  // https://docs.gitlab.com/ee/api/merge_requests.html#get-single-mr
   384  func (s *MergeRequestsService) GetMergeRequest(pid interface{}, mergeRequest int, opt *GetMergeRequestsOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
   385  	project, err := parseID(pid)
   386  	if err != nil {
   387  		return nil, nil, err
   388  	}
   389  	u := fmt.Sprintf("projects/%s/merge_requests/%d", PathEscape(project), mergeRequest)
   390  
   391  	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
   392  	if err != nil {
   393  		return nil, nil, err
   394  	}
   395  
   396  	m := new(MergeRequest)
   397  	resp, err := s.client.Do(req, m)
   398  	if err != nil {
   399  		return nil, resp, err
   400  	}
   401  
   402  	return m, resp, nil
   403  }
   404  
   405  // GetMergeRequestApprovals gets information about a merge requests approvals
   406  //
   407  // GitLab API docs:
   408  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#merge-request-level-mr-approvals
   409  func (s *MergeRequestsService) GetMergeRequestApprovals(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) {
   410  	project, err := parseID(pid)
   411  	if err != nil {
   412  		return nil, nil, err
   413  	}
   414  	u := fmt.Sprintf("projects/%s/merge_requests/%d/approvals", PathEscape(project), mergeRequest)
   415  
   416  	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
   417  	if err != nil {
   418  		return nil, nil, err
   419  	}
   420  
   421  	a := new(MergeRequestApprovals)
   422  	resp, err := s.client.Do(req, a)
   423  	if err != nil {
   424  		return nil, resp, err
   425  	}
   426  
   427  	return a, resp, nil
   428  }
   429  
   430  // GetMergeRequestCommitsOptions represents the available GetMergeRequestCommits()
   431  // options.
   432  //
   433  // GitLab API docs:
   434  // https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-commits
   435  type GetMergeRequestCommitsOptions ListOptions
   436  
   437  // GetMergeRequestCommits gets a list of merge request commits.
   438  //
   439  // GitLab API docs:
   440  // https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-commits
   441  func (s *MergeRequestsService) GetMergeRequestCommits(pid interface{}, mergeRequest int, opt *GetMergeRequestCommitsOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) {
   442  	project, err := parseID(pid)
   443  	if err != nil {
   444  		return nil, nil, err
   445  	}
   446  	u := fmt.Sprintf("projects/%s/merge_requests/%d/commits", PathEscape(project), mergeRequest)
   447  
   448  	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
   449  	if err != nil {
   450  		return nil, nil, err
   451  	}
   452  
   453  	var c []*Commit
   454  	resp, err := s.client.Do(req, &c)
   455  	if err != nil {
   456  		return nil, resp, err
   457  	}
   458  
   459  	return c, resp, nil
   460  }
   461  
   462  // GetMergeRequestChangesOptions represents the available GetMergeRequestChanges()
   463  // options.
   464  //
   465  // GitLab API docs:
   466  // https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-changes
   467  type GetMergeRequestChangesOptions struct {
   468  	AccessRawDiffs *bool `url:"access_raw_diffs,omitempty" json:"access_raw_diffs,omitempty"`
   469  	Unidiff        *bool `url:"unidiff,omitempty" json:"unidiff,omitempty"`
   470  }
   471  
   472  // GetMergeRequestChanges shows information about the merge request including
   473  // its files and changes.
   474  //
   475  // Deprecated: This endpoint has been replaced by
   476  // MergeRequestsService.ListMergeRequestDiffs()
   477  //
   478  // GitLab API docs:
   479  // https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-changes
   480  func (s *MergeRequestsService) GetMergeRequestChanges(pid interface{}, mergeRequest int, opt *GetMergeRequestChangesOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
   481  	project, err := parseID(pid)
   482  	if err != nil {
   483  		return nil, nil, err
   484  	}
   485  	u := fmt.Sprintf("projects/%s/merge_requests/%d/changes", PathEscape(project), mergeRequest)
   486  
   487  	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
   488  	if err != nil {
   489  		return nil, nil, err
   490  	}
   491  
   492  	m := new(MergeRequest)
   493  	resp, err := s.client.Do(req, m)
   494  	if err != nil {
   495  		return nil, resp, err
   496  	}
   497  
   498  	return m, resp, nil
   499  }
   500  
   501  // ListMergeRequestDiffsOptions represents the available ListMergeRequestDiffs()
   502  // options.
   503  //
   504  // GitLab API docs:
   505  // https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-diffs
   506  type ListMergeRequestDiffsOptions struct {
   507  	ListOptions
   508  	Unidiff *bool `url:"unidiff,omitempty" json:"unidiff,omitempty"`
   509  }
   510  
   511  // ListMergeRequestDiffs List diffs of the files changed in a merge request
   512  //
   513  // GitLab API docs:
   514  // https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-diffs
   515  func (s *MergeRequestsService) ListMergeRequestDiffs(pid interface{}, mergeRequest int, opt *ListMergeRequestDiffsOptions, options ...RequestOptionFunc) ([]*MergeRequestDiff, *Response, error) {
   516  	project, err := parseID(pid)
   517  	if err != nil {
   518  		return nil, nil, err
   519  	}
   520  	u := fmt.Sprintf("projects/%s/merge_requests/%d/diffs", PathEscape(project), mergeRequest)
   521  
   522  	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
   523  	if err != nil {
   524  		return nil, nil, err
   525  	}
   526  
   527  	var m []*MergeRequestDiff
   528  	resp, err := s.client.Do(req, &m)
   529  	if err != nil {
   530  		return nil, resp, err
   531  	}
   532  
   533  	return m, resp, nil
   534  }
   535  
   536  // GetMergeRequestParticipants gets a list of merge request participants.
   537  //
   538  // GitLab API docs:
   539  // https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-participants
   540  func (s *MergeRequestsService) GetMergeRequestParticipants(pid interface{}, mergeRequest int, options ...RequestOptionFunc) ([]*BasicUser, *Response, error) {
   541  	project, err := parseID(pid)
   542  	if err != nil {
   543  		return nil, nil, err
   544  	}
   545  	u := fmt.Sprintf("projects/%s/merge_requests/%d/participants", PathEscape(project), mergeRequest)
   546  
   547  	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
   548  	if err != nil {
   549  		return nil, nil, err
   550  	}
   551  
   552  	var bu []*BasicUser
   553  	resp, err := s.client.Do(req, &bu)
   554  	if err != nil {
   555  		return nil, resp, err
   556  	}
   557  
   558  	return bu, resp, nil
   559  }
   560  
   561  // MergeRequestReviewer represents a GitLab merge request reviewer.
   562  //
   563  // GitLab API docs:
   564  // https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-reviewers
   565  type MergeRequestReviewer struct {
   566  	User      *BasicUser `json:"user"`
   567  	State     string     `json:"state"`
   568  	CreatedAt *time.Time `json:"created_at"`
   569  }
   570  
   571  // GetMergeRequestReviewers gets a list of merge request reviewers.
   572  //
   573  // GitLab API docs:
   574  // https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-reviewers
   575  func (s *MergeRequestsService) GetMergeRequestReviewers(pid interface{}, mergeRequest int, options ...RequestOptionFunc) ([]*MergeRequestReviewer, *Response, error) {
   576  	project, err := parseID(pid)
   577  	if err != nil {
   578  		return nil, nil, err
   579  	}
   580  	u := fmt.Sprintf("projects/%s/merge_requests/%d/reviewers", PathEscape(project), mergeRequest)
   581  
   582  	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
   583  	if err != nil {
   584  		return nil, nil, err
   585  	}
   586  
   587  	var mrr []*MergeRequestReviewer
   588  	resp, err := s.client.Do(req, &mrr)
   589  	if err != nil {
   590  		return nil, resp, err
   591  	}
   592  
   593  	return mrr, resp, nil
   594  }
   595  
   596  // ListMergeRequestPipelines gets all pipelines for the provided merge request.
   597  //
   598  // GitLab API docs:
   599  // https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-pipelines
   600  func (s *MergeRequestsService) ListMergeRequestPipelines(pid interface{}, mergeRequest int, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) {
   601  	project, err := parseID(pid)
   602  	if err != nil {
   603  		return nil, nil, err
   604  	}
   605  	u := fmt.Sprintf("projects/%s/merge_requests/%d/pipelines", PathEscape(project), mergeRequest)
   606  
   607  	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
   608  	if err != nil {
   609  		return nil, nil, err
   610  	}
   611  
   612  	var p []*PipelineInfo
   613  	resp, err := s.client.Do(req, &p)
   614  	if err != nil {
   615  		return nil, resp, err
   616  	}
   617  
   618  	return p, resp, nil
   619  }
   620  
   621  // CreateMergeRequestPipeline creates a new pipeline for a merge request.
   622  //
   623  // GitLab API docs:
   624  // https://docs.gitlab.com/ee/api/merge_requests.html#create-merge-request-pipeline
   625  func (s *MergeRequestsService) CreateMergeRequestPipeline(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*PipelineInfo, *Response, error) {
   626  	project, err := parseID(pid)
   627  	if err != nil {
   628  		return nil, nil, err
   629  	}
   630  	u := fmt.Sprintf("projects/%s/merge_requests/%d/pipelines", PathEscape(project), mergeRequest)
   631  
   632  	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
   633  	if err != nil {
   634  		return nil, nil, err
   635  	}
   636  
   637  	p := new(PipelineInfo)
   638  	resp, err := s.client.Do(req, p)
   639  	if err != nil {
   640  		return nil, resp, err
   641  	}
   642  
   643  	return p, resp, nil
   644  }
   645  
   646  // GetIssuesClosedOnMergeOptions represents the available GetIssuesClosedOnMerge()
   647  // options.
   648  //
   649  // GitLab API docs:
   650  // https://docs.gitlab.com/ee/api/merge_requests.html#list-issues-that-close-on-merge
   651  type GetIssuesClosedOnMergeOptions ListOptions
   652  
   653  // GetIssuesClosedOnMerge gets all the issues that would be closed by merging the
   654  // provided merge request.
   655  //
   656  // GitLab API docs:
   657  // https://docs.gitlab.com/ee/api/merge_requests.html#list-issues-that-close-on-merge
   658  func (s *MergeRequestsService) GetIssuesClosedOnMerge(pid interface{}, mergeRequest int, opt *GetIssuesClosedOnMergeOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) {
   659  	project, err := parseID(pid)
   660  	if err != nil {
   661  		return nil, nil, err
   662  	}
   663  	u := fmt.Sprintf("projects/%s/merge_requests/%d/closes_issues", PathEscape(project), mergeRequest)
   664  
   665  	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
   666  	if err != nil {
   667  		return nil, nil, err
   668  	}
   669  
   670  	var i []*Issue
   671  	resp, err := s.client.Do(req, &i)
   672  	if err != nil {
   673  		return nil, resp, err
   674  	}
   675  
   676  	return i, resp, nil
   677  }
   678  
   679  // CreateMergeRequestOptions represents the available CreateMergeRequest()
   680  // options.
   681  //
   682  // GitLab API docs:
   683  // https://docs.gitlab.com/ee/api/merge_requests.html#create-mr
   684  type CreateMergeRequestOptions struct {
   685  	Title                *string       `url:"title,omitempty" json:"title,omitempty"`
   686  	Description          *string       `url:"description,omitempty" json:"description,omitempty"`
   687  	SourceBranch         *string       `url:"source_branch,omitempty" json:"source_branch,omitempty"`
   688  	TargetBranch         *string       `url:"target_branch,omitempty" json:"target_branch,omitempty"`
   689  	Labels               *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"`
   690  	AssigneeID           *int          `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
   691  	AssigneeIDs          *[]int        `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"`
   692  	ReviewerIDs          *[]int        `url:"reviewer_ids,omitempty" json:"reviewer_ids,omitempty"`
   693  	TargetProjectID      *int          `url:"target_project_id,omitempty" json:"target_project_id,omitempty"`
   694  	MilestoneID          *int          `url:"milestone_id,omitempty" json:"milestone_id,omitempty"`
   695  	RemoveSourceBranch   *bool         `url:"remove_source_branch,omitempty" json:"remove_source_branch,omitempty"`
   696  	Squash               *bool         `url:"squash,omitempty" json:"squash,omitempty"`
   697  	AllowCollaboration   *bool         `url:"allow_collaboration,omitempty" json:"allow_collaboration,omitempty"`
   698  	ApprovalsBeforeMerge *int          `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"`
   699  }
   700  
   701  // CreateMergeRequest creates a new merge request.
   702  //
   703  // GitLab API docs:
   704  // https://docs.gitlab.com/ee/api/merge_requests.html#create-mr
   705  func (s *MergeRequestsService) CreateMergeRequest(pid interface{}, opt *CreateMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
   706  	project, err := parseID(pid)
   707  	if err != nil {
   708  		return nil, nil, err
   709  	}
   710  	u := fmt.Sprintf("projects/%s/merge_requests", PathEscape(project))
   711  
   712  	req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
   713  	if err != nil {
   714  		return nil, nil, err
   715  	}
   716  
   717  	m := new(MergeRequest)
   718  	resp, err := s.client.Do(req, m)
   719  	if err != nil {
   720  		return nil, resp, err
   721  	}
   722  
   723  	return m, resp, nil
   724  }
   725  
   726  // UpdateMergeRequestOptions represents the available UpdateMergeRequest()
   727  // options.
   728  //
   729  // GitLab API docs:
   730  // https://docs.gitlab.com/ee/api/merge_requests.html#update-mr
   731  type UpdateMergeRequestOptions struct {
   732  	Title              *string       `url:"title,omitempty" json:"title,omitempty"`
   733  	Description        *string       `url:"description,omitempty" json:"description,omitempty"`
   734  	TargetBranch       *string       `url:"target_branch,omitempty" json:"target_branch,omitempty"`
   735  	AssigneeID         *int          `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
   736  	AssigneeIDs        *[]int        `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"`
   737  	ReviewerIDs        *[]int        `url:"reviewer_ids,omitempty" json:"reviewer_ids,omitempty"`
   738  	Labels             *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"`
   739  	AddLabels          *LabelOptions `url:"add_labels,comma,omitempty" json:"add_labels,omitempty"`
   740  	RemoveLabels       *LabelOptions `url:"remove_labels,comma,omitempty" json:"remove_labels,omitempty"`
   741  	MilestoneID        *int          `url:"milestone_id,omitempty" json:"milestone_id,omitempty"`
   742  	StateEvent         *string       `url:"state_event,omitempty" json:"state_event,omitempty"`
   743  	RemoveSourceBranch *bool         `url:"remove_source_branch,omitempty" json:"remove_source_branch,omitempty"`
   744  	Squash             *bool         `url:"squash,omitempty" json:"squash,omitempty"`
   745  	DiscussionLocked   *bool         `url:"discussion_locked,omitempty" json:"discussion_locked,omitempty"`
   746  	AllowCollaboration *bool         `url:"allow_collaboration,omitempty" json:"allow_collaboration,omitempty"`
   747  }
   748  
   749  // UpdateMergeRequest updates an existing project milestone.
   750  //
   751  // GitLab API docs:
   752  // https://docs.gitlab.com/ee/api/merge_requests.html#update-mr
   753  func (s *MergeRequestsService) UpdateMergeRequest(pid interface{}, mergeRequest int, opt *UpdateMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
   754  	project, err := parseID(pid)
   755  	if err != nil {
   756  		return nil, nil, err
   757  	}
   758  	u := fmt.Sprintf("projects/%s/merge_requests/%d", PathEscape(project), mergeRequest)
   759  
   760  	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
   761  	if err != nil {
   762  		return nil, nil, err
   763  	}
   764  
   765  	m := new(MergeRequest)
   766  	resp, err := s.client.Do(req, m)
   767  	if err != nil {
   768  		return nil, resp, err
   769  	}
   770  
   771  	return m, resp, nil
   772  }
   773  
   774  // DeleteMergeRequest deletes a merge request.
   775  //
   776  // GitLab API docs:
   777  // https://docs.gitlab.com/ee/api/merge_requests.html#delete-a-merge-request
   778  func (s *MergeRequestsService) DeleteMergeRequest(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*Response, error) {
   779  	project, err := parseID(pid)
   780  	if err != nil {
   781  		return nil, err
   782  	}
   783  	u := fmt.Sprintf("projects/%s/merge_requests/%d", PathEscape(project), mergeRequest)
   784  
   785  	req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
   786  	if err != nil {
   787  		return nil, err
   788  	}
   789  
   790  	return s.client.Do(req, nil)
   791  }
   792  
   793  // AcceptMergeRequestOptions represents the available AcceptMergeRequest()
   794  // options.
   795  //
   796  // GitLab API docs:
   797  // https://docs.gitlab.com/ee/api/merge_requests.html#merge-a-merge-request
   798  type AcceptMergeRequestOptions struct {
   799  	MergeCommitMessage        *string `url:"merge_commit_message,omitempty" json:"merge_commit_message,omitempty"`
   800  	SquashCommitMessage       *string `url:"squash_commit_message,omitempty" json:"squash_commit_message,omitempty"`
   801  	Squash                    *bool   `url:"squash,omitempty" json:"squash,omitempty"`
   802  	ShouldRemoveSourceBranch  *bool   `url:"should_remove_source_branch,omitempty" json:"should_remove_source_branch,omitempty"`
   803  	MergeWhenPipelineSucceeds *bool   `url:"merge_when_pipeline_succeeds,omitempty" json:"merge_when_pipeline_succeeds,omitempty"`
   804  	SHA                       *string `url:"sha,omitempty" json:"sha,omitempty"`
   805  }
   806  
   807  // AcceptMergeRequest merges changes submitted with MR using this API. If merge
   808  // success you get 200 OK. If it has some conflicts and can not be merged - you
   809  // get 405 and error message 'Branch cannot be merged'. If merge request is
   810  // already merged or closed - you get 405 and error message 'Method Not Allowed'
   811  //
   812  // GitLab API docs:
   813  // https://docs.gitlab.com/ee/api/merge_requests.html#merge-a-merge-request
   814  func (s *MergeRequestsService) AcceptMergeRequest(pid interface{}, mergeRequest int, opt *AcceptMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
   815  	project, err := parseID(pid)
   816  	if err != nil {
   817  		return nil, nil, err
   818  	}
   819  	u := fmt.Sprintf("projects/%s/merge_requests/%d/merge", PathEscape(project), mergeRequest)
   820  
   821  	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
   822  	if err != nil {
   823  		return nil, nil, err
   824  	}
   825  
   826  	m := new(MergeRequest)
   827  	resp, err := s.client.Do(req, m)
   828  	if err != nil {
   829  		return nil, resp, err
   830  	}
   831  
   832  	return m, resp, nil
   833  }
   834  
   835  // CancelMergeWhenPipelineSucceeds cancels a merge when pipeline succeeds. If
   836  // you don't have permissions to accept this merge request - you'll get a 401.
   837  // If the merge request is already merged or closed - you get 405 and error
   838  // message 'Method Not Allowed'. In case the merge request is not set to be
   839  // merged when the pipeline succeeds, you'll also get a 406 error.
   840  //
   841  // GitLab API docs:
   842  // https://docs.gitlab.com/ee/api/merge_requests.html#cancel-merge-when-pipeline-succeeds
   843  func (s *MergeRequestsService) CancelMergeWhenPipelineSucceeds(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
   844  	project, err := parseID(pid)
   845  	if err != nil {
   846  		return nil, nil, err
   847  	}
   848  	u := fmt.Sprintf("projects/%s/merge_requests/%d/cancel_merge_when_pipeline_succeeds", PathEscape(project), mergeRequest)
   849  
   850  	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
   851  	if err != nil {
   852  		return nil, nil, err
   853  	}
   854  
   855  	m := new(MergeRequest)
   856  	resp, err := s.client.Do(req, m)
   857  	if err != nil {
   858  		return nil, resp, err
   859  	}
   860  
   861  	return m, resp, nil
   862  }
   863  
   864  // RebaseMergeRequestOptions represents the available RebaseMergeRequest()
   865  // options.
   866  //
   867  // GitLab API docs:
   868  // https://docs.gitlab.com/ee/api/merge_requests.html#rebase-a-merge-request
   869  type RebaseMergeRequestOptions struct {
   870  	SkipCI *bool `url:"skip_ci,omitempty" json:"skip_ci,omitempty"`
   871  }
   872  
   873  // RebaseMergeRequest automatically rebases the source_branch of the merge
   874  // request against its target_branch. If you don’t have permissions to push
   875  // to the merge request’s source branch, you’ll get a 403 Forbidden response.
   876  //
   877  // GitLab API docs:
   878  // https://docs.gitlab.com/ee/api/merge_requests.html#rebase-a-merge-request
   879  func (s *MergeRequestsService) RebaseMergeRequest(pid interface{}, mergeRequest int, opt *RebaseMergeRequestOptions, options ...RequestOptionFunc) (*Response, error) {
   880  	project, err := parseID(pid)
   881  	if err != nil {
   882  		return nil, err
   883  	}
   884  	u := fmt.Sprintf("projects/%s/merge_requests/%d/rebase", PathEscape(project), mergeRequest)
   885  
   886  	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
   887  	if err != nil {
   888  		return nil, err
   889  	}
   890  
   891  	return s.client.Do(req, nil)
   892  }
   893  
   894  // GetMergeRequestDiffVersionsOptions represents the available
   895  // GetMergeRequestDiffVersions() options.
   896  //
   897  // GitLab API docs:
   898  // https://docs.gitlab.com/ee/api/merge_requests.html#get-merge-request-diff-versions
   899  type GetMergeRequestDiffVersionsOptions ListOptions
   900  
   901  // GetMergeRequestDiffVersions get a list of merge request diff versions.
   902  //
   903  // GitLab API docs:
   904  // https://docs.gitlab.com/ee/api/merge_requests.html#get-merge-request-diff-versions
   905  func (s *MergeRequestsService) GetMergeRequestDiffVersions(pid interface{}, mergeRequest int, opt *GetMergeRequestDiffVersionsOptions, options ...RequestOptionFunc) ([]*MergeRequestDiffVersion, *Response, error) {
   906  	project, err := parseID(pid)
   907  	if err != nil {
   908  		return nil, nil, err
   909  	}
   910  	u := fmt.Sprintf("projects/%s/merge_requests/%d/versions", PathEscape(project), mergeRequest)
   911  
   912  	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
   913  	if err != nil {
   914  		return nil, nil, err
   915  	}
   916  
   917  	var v []*MergeRequestDiffVersion
   918  	resp, err := s.client.Do(req, &v)
   919  	if err != nil {
   920  		return nil, resp, err
   921  	}
   922  
   923  	return v, resp, nil
   924  }
   925  
   926  // GetSingleMergeRequestDiffVersionOptions represents the available
   927  // GetSingleMergeRequestDiffVersion() options.
   928  //
   929  // GitLab API docs:
   930  // https://docs.gitlab.com/ee/api/merge_requests.html#get-a-single-merge-request-diff-version
   931  type GetSingleMergeRequestDiffVersionOptions struct {
   932  	Unidiff *bool `url:"unidiff,omitempty" json:"unidiff,omitempty"`
   933  }
   934  
   935  // GetSingleMergeRequestDiffVersion get a single MR diff version
   936  //
   937  // GitLab API docs:
   938  // https://docs.gitlab.com/ee/api/merge_requests.html#get-a-single-merge-request-diff-version
   939  func (s *MergeRequestsService) GetSingleMergeRequestDiffVersion(pid interface{}, mergeRequest, version int, opt *GetSingleMergeRequestDiffVersionOptions, options ...RequestOptionFunc) (*MergeRequestDiffVersion, *Response, error) {
   940  	project, err := parseID(pid)
   941  	if err != nil {
   942  		return nil, nil, err
   943  	}
   944  	u := fmt.Sprintf("projects/%s/merge_requests/%d/versions/%d", PathEscape(project), mergeRequest, version)
   945  
   946  	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
   947  	if err != nil {
   948  		return nil, nil, err
   949  	}
   950  
   951  	v := new(MergeRequestDiffVersion)
   952  	resp, err := s.client.Do(req, v)
   953  	if err != nil {
   954  		return nil, resp, err
   955  	}
   956  
   957  	return v, resp, nil
   958  }
   959  
   960  // SubscribeToMergeRequest subscribes the authenticated user to the given merge
   961  // request to receive notifications. If the user is already subscribed to the
   962  // merge request, the status code 304 is returned.
   963  //
   964  // GitLab API docs:
   965  // https://docs.gitlab.com/ee/api/merge_requests.html#subscribe-to-a-merge-request
   966  func (s *MergeRequestsService) SubscribeToMergeRequest(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
   967  	project, err := parseID(pid)
   968  	if err != nil {
   969  		return nil, nil, err
   970  	}
   971  	u := fmt.Sprintf("projects/%s/merge_requests/%d/subscribe", PathEscape(project), mergeRequest)
   972  
   973  	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
   974  	if err != nil {
   975  		return nil, nil, err
   976  	}
   977  
   978  	m := new(MergeRequest)
   979  	resp, err := s.client.Do(req, m)
   980  	if err != nil {
   981  		return nil, resp, err
   982  	}
   983  
   984  	return m, resp, nil
   985  }
   986  
   987  // UnsubscribeFromMergeRequest unsubscribes the authenticated user from the
   988  // given merge request to not receive notifications from that merge request.
   989  // If the user is not subscribed to the merge request, status code 304 is
   990  // returned.
   991  //
   992  // GitLab API docs:
   993  // https://docs.gitlab.com/ee/api/merge_requests.html#unsubscribe-from-a-merge-request
   994  func (s *MergeRequestsService) UnsubscribeFromMergeRequest(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
   995  	project, err := parseID(pid)
   996  	if err != nil {
   997  		return nil, nil, err
   998  	}
   999  	u := fmt.Sprintf("projects/%s/merge_requests/%d/unsubscribe", PathEscape(project), mergeRequest)
  1000  
  1001  	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
  1002  	if err != nil {
  1003  		return nil, nil, err
  1004  	}
  1005  
  1006  	m := new(MergeRequest)
  1007  	resp, err := s.client.Do(req, m)
  1008  	if err != nil {
  1009  		return nil, resp, err
  1010  	}
  1011  
  1012  	return m, resp, nil
  1013  }
  1014  
  1015  // CreateTodo manually creates a todo for the current user on a merge request.
  1016  // If there already exists a todo for the user on that merge request,
  1017  // status code 304 is returned.
  1018  //
  1019  // GitLab API docs:
  1020  // https://docs.gitlab.com/ee/api/merge_requests.html#create-a-to-do-item
  1021  func (s *MergeRequestsService) CreateTodo(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*Todo, *Response, error) {
  1022  	project, err := parseID(pid)
  1023  	if err != nil {
  1024  		return nil, nil, err
  1025  	}
  1026  	u := fmt.Sprintf("projects/%s/merge_requests/%d/todo", PathEscape(project), mergeRequest)
  1027  
  1028  	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
  1029  	if err != nil {
  1030  		return nil, nil, err
  1031  	}
  1032  
  1033  	t := new(Todo)
  1034  	resp, err := s.client.Do(req, t)
  1035  	if err != nil {
  1036  		return nil, resp, err
  1037  	}
  1038  
  1039  	return t, resp, nil
  1040  }
  1041  
  1042  // SetTimeEstimate sets the time estimate for a single project merge request.
  1043  //
  1044  // GitLab API docs:
  1045  // https://docs.gitlab.com/ee/api/merge_requests.html#set-a-time-estimate-for-a-merge-request
  1046  func (s *MergeRequestsService) SetTimeEstimate(pid interface{}, mergeRequest int, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
  1047  	return s.timeStats.setTimeEstimate(pid, "merge_requests", mergeRequest, opt, options...)
  1048  }
  1049  
  1050  // ResetTimeEstimate resets the time estimate for a single project merge request.
  1051  //
  1052  // GitLab API docs:
  1053  // https://docs.gitlab.com/ee/api/merge_requests.html#reset-the-time-estimate-for-a-merge-request
  1054  func (s *MergeRequestsService) ResetTimeEstimate(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
  1055  	return s.timeStats.resetTimeEstimate(pid, "merge_requests", mergeRequest, options...)
  1056  }
  1057  
  1058  // AddSpentTime adds spent time for a single project merge request.
  1059  //
  1060  // GitLab API docs:
  1061  // https://docs.gitlab.com/ee/api/merge_requests.html#add-spent-time-for-a-merge-request
  1062  func (s *MergeRequestsService) AddSpentTime(pid interface{}, mergeRequest int, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
  1063  	return s.timeStats.addSpentTime(pid, "merge_requests", mergeRequest, opt, options...)
  1064  }
  1065  
  1066  // ResetSpentTime resets the spent time for a single project merge request.
  1067  //
  1068  // GitLab API docs:
  1069  // https://docs.gitlab.com/ee/api/merge_requests.html#reset-spent-time-for-a-merge-request
  1070  func (s *MergeRequestsService) ResetSpentTime(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
  1071  	return s.timeStats.resetSpentTime(pid, "merge_requests", mergeRequest, options...)
  1072  }
  1073  
  1074  // GetTimeSpent gets the spent time for a single project merge request.
  1075  //
  1076  // GitLab API docs:
  1077  // https://docs.gitlab.com/ee/api/merge_requests.html#get-time-tracking-stats
  1078  func (s *MergeRequestsService) GetTimeSpent(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
  1079  	return s.timeStats.getTimeSpent(pid, "merge_requests", mergeRequest, options...)
  1080  }
  1081  

View as plain text