merge_requests.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. //
  2. // Copyright 2017, 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. package gitlab
  17. import (
  18. "fmt"
  19. "net/url"
  20. "time"
  21. )
  22. // MergeRequestsService handles communication with the merge requests related
  23. // methods of the GitLab API.
  24. //
  25. // GitLab API docs: https://docs.gitlab.com/ce/api/merge_requests.html
  26. type MergeRequestsService struct {
  27. client *Client
  28. timeStats *timeStatsService
  29. }
  30. // MergeRequest represents a GitLab merge request.
  31. //
  32. // GitLab API docs: https://docs.gitlab.com/ce/api/merge_requests.html
  33. type MergeRequest struct {
  34. ID int `json:"id"`
  35. IID int `json:"iid"`
  36. TargetBranch string `json:"target_branch"`
  37. SourceBranch string `json:"source_branch"`
  38. ProjectID int `json:"project_id"`
  39. Title string `json:"title"`
  40. State string `json:"state"`
  41. CreatedAt *time.Time `json:"created_at"`
  42. UpdatedAt *time.Time `json:"updated_at"`
  43. Upvotes int `json:"upvotes"`
  44. Downvotes int `json:"downvotes"`
  45. Author struct {
  46. ID int `json:"id"`
  47. Username string `json:"username"`
  48. Name string `json:"name"`
  49. State string `json:"state"`
  50. CreatedAt *time.Time `json:"created_at"`
  51. } `json:"author"`
  52. Assignee struct {
  53. ID int `json:"id"`
  54. Username string `json:"username"`
  55. Name string `json:"name"`
  56. State string `json:"state"`
  57. CreatedAt *time.Time `json:"created_at"`
  58. } `json:"assignee"`
  59. SourceProjectID int `json:"source_project_id"`
  60. TargetProjectID int `json:"target_project_id"`
  61. Labels []string `json:"labels"`
  62. Description string `json:"description"`
  63. WorkInProgress bool `json:"work_in_progress"`
  64. Milestone *Milestone `json:"milestone"`
  65. MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"`
  66. MergeStatus string `json:"merge_status"`
  67. MergedBy struct {
  68. ID int `json:"id"`
  69. Username string `json:"username"`
  70. Name string `json:"name"`
  71. State string `json:"state"`
  72. CreatedAt *time.Time `json:"created_at"`
  73. } `json:"merged_by"`
  74. MergedAt *time.Time `json:"merged_at"`
  75. ClosedBy struct {
  76. ID int `json:"id"`
  77. Username string `json:"username"`
  78. Name string `json:"name"`
  79. State string `json:"state"`
  80. CreatedAt *time.Time `json:"created_at"`
  81. } `json:"closed_by"`
  82. ClosedAt *time.Time `json:"closed_at"`
  83. Subscribed bool `json:"subscribed"`
  84. SHA string `json:"sha"`
  85. MergeCommitSHA string `json:"merge_commit_sha"`
  86. UserNotesCount int `json:"user_notes_count"`
  87. ChangesCount string `json:"changes_count"`
  88. ShouldRemoveSourceBranch bool `json:"should_remove_source_branch"`
  89. ForceRemoveSourceBranch bool `json:"force_remove_source_branch"`
  90. WebURL string `json:"web_url"`
  91. DiscussionLocked bool `json:"discussion_locked"`
  92. Changes []struct {
  93. OldPath string `json:"old_path"`
  94. NewPath string `json:"new_path"`
  95. AMode string `json:"a_mode"`
  96. BMode string `json:"b_mode"`
  97. Diff string `json:"diff"`
  98. NewFile bool `json:"new_file"`
  99. RenamedFile bool `json:"renamed_file"`
  100. DeletedFile bool `json:"deleted_file"`
  101. } `json:"changes"`
  102. TimeStats *TimeStats `json:"time_stats"`
  103. Squash bool `json:"squash"`
  104. Pipeline struct {
  105. ID int `json:"id"`
  106. Ref string `json:"ref"`
  107. SHA string `json:"sha"`
  108. Status string `json:"status"`
  109. } `json:"pipeline"`
  110. }
  111. func (m MergeRequest) String() string {
  112. return Stringify(m)
  113. }
  114. // MergeRequestDiffVersion represents Gitlab merge request version.
  115. //
  116. // Gitlab API docs:
  117. // https://docs.gitlab.com/ce/api/merge_requests.html#get-a-single-mr-diff-version
  118. type MergeRequestDiffVersion struct {
  119. ID int `json:"id"`
  120. HeadCommitSHA string `json:"head_commit_sha,omitempty"`
  121. BaseCommitSHA string `json:"base_commit_sha,omitempty"`
  122. StartCommitSHA string `json:"start_commit_sha,omitempty"`
  123. CreatedAt *time.Time `json:"created_at,omitempty"`
  124. MergeRequestID int `json:"merge_request_id,omitempty"`
  125. State string `json:"state,omitempty"`
  126. RealSize string `json:"real_size,omitempty"`
  127. Commits []*Commit `json:"commits,omitempty"`
  128. Diffs []*Diff `json:"diffs,omitempty"`
  129. }
  130. func (m MergeRequestDiffVersion) String() string {
  131. return Stringify(m)
  132. }
  133. // ListMergeRequestsOptions represents the available ListMergeRequests()
  134. // options.
  135. //
  136. // GitLab API docs:
  137. // https://docs.gitlab.com/ce/api/merge_requests.html#list-merge-requests
  138. type ListMergeRequestsOptions struct {
  139. ListOptions
  140. State *string `url:"state,omitempty" json:"state,omitempty"`
  141. OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
  142. Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
  143. Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"`
  144. View *string `url:"view,omitempty" json:"view,omitempty"`
  145. Labels Labels `url:"labels,omitempty" json:"labels,omitempty"`
  146. CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
  147. CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"`
  148. UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"`
  149. UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"`
  150. Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
  151. AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"`
  152. AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
  153. MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
  154. SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
  155. TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
  156. Search *string `url:"search,omitempty" json:"search,omitempty"`
  157. }
  158. // ListMergeRequests gets all merge requests. The state parameter can be used
  159. // to get only merge requests with a given state (opened, closed, or merged)
  160. // or all of them (all). The pagination parameters page and per_page can be
  161. // used to restrict the list of merge requests.
  162. //
  163. // GitLab API docs:
  164. // https://docs.gitlab.com/ce/api/merge_requests.html#list-merge-requests
  165. func (s *MergeRequestsService) ListMergeRequests(opt *ListMergeRequestsOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) {
  166. req, err := s.client.NewRequest("GET", "merge_requests", opt, options)
  167. if err != nil {
  168. return nil, nil, err
  169. }
  170. var m []*MergeRequest
  171. resp, err := s.client.Do(req, &m)
  172. if err != nil {
  173. return nil, resp, err
  174. }
  175. return m, resp, err
  176. }
  177. // ListGroupMergeRequestsOptions represents the available ListGroupMergeRequests()
  178. // options.
  179. //
  180. // GitLab API docs:
  181. // https://docs.gitlab.com/ce/api/merge_requests.html#list-group-merge-requests
  182. type ListGroupMergeRequestsOptions struct {
  183. ListOptions
  184. State *string `url:"state,omitempty" json:"state,omitempty"`
  185. OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
  186. Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
  187. Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"`
  188. View *string `url:"view,omitempty" json:"view,omitempty"`
  189. Labels Labels `url:"labels,omitempty" json:"labels,omitempty"`
  190. CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
  191. CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"`
  192. UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"`
  193. UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"`
  194. Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
  195. AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"`
  196. AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
  197. MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
  198. SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
  199. TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
  200. Search *string `url:"search,omitempty" json:"search,omitempty"`
  201. }
  202. // ListGroupMergeRequests gets all merge requests for this group.
  203. //
  204. // GitLab API docs:
  205. // https://docs.gitlab.com/ce/api/merge_requests.html#list-group-merge-requests
  206. func (s *MergeRequestsService) ListGroupMergeRequests(gid interface{}, opt *ListGroupMergeRequestsOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) {
  207. group, err := parseID(gid)
  208. if err != nil {
  209. return nil, nil, err
  210. }
  211. u := fmt.Sprintf("groups/%s/merge_requests", url.QueryEscape(group))
  212. req, err := s.client.NewRequest("GET", u, opt, options)
  213. if err != nil {
  214. return nil, nil, err
  215. }
  216. var m []*MergeRequest
  217. resp, err := s.client.Do(req, &m)
  218. if err != nil {
  219. return nil, resp, err
  220. }
  221. return m, resp, err
  222. }
  223. // ListProjectMergeRequestsOptions represents the available ListMergeRequests()
  224. // options.
  225. //
  226. // GitLab API docs:
  227. // https://docs.gitlab.com/ce/api/merge_requests.html#list-project-merge-requests
  228. type ListProjectMergeRequestsOptions struct {
  229. ListOptions
  230. IIDs []int `url:"iids[],omitempty" json:"iids,omitempty"`
  231. State *string `url:"state,omitempty" json:"state,omitempty"`
  232. OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
  233. Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
  234. Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"`
  235. View *string `url:"view,omitempty" json:"view,omitempty"`
  236. Labels Labels `url:"labels,omitempty" json:"labels,omitempty"`
  237. CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
  238. CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"`
  239. UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"`
  240. UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"`
  241. Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
  242. AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"`
  243. AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
  244. MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
  245. SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
  246. TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
  247. Search *string `url:"search,omitempty" json:"search,omitempty"`
  248. }
  249. // ListProjectMergeRequests gets all merge requests for this project.
  250. //
  251. // GitLab API docs:
  252. // https://docs.gitlab.com/ce/api/merge_requests.html#list-project-merge-requests
  253. func (s *MergeRequestsService) ListProjectMergeRequests(pid interface{}, opt *ListProjectMergeRequestsOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) {
  254. project, err := parseID(pid)
  255. if err != nil {
  256. return nil, nil, err
  257. }
  258. u := fmt.Sprintf("projects/%s/merge_requests", url.QueryEscape(project))
  259. req, err := s.client.NewRequest("GET", u, opt, options)
  260. if err != nil {
  261. return nil, nil, err
  262. }
  263. var m []*MergeRequest
  264. resp, err := s.client.Do(req, &m)
  265. if err != nil {
  266. return nil, resp, err
  267. }
  268. return m, resp, err
  269. }
  270. // GetMergeRequest shows information about a single merge request.
  271. //
  272. // GitLab API docs:
  273. // https://docs.gitlab.com/ce/api/merge_requests.html#get-single-mr
  274. func (s *MergeRequestsService) GetMergeRequest(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequest, *Response, error) {
  275. project, err := parseID(pid)
  276. if err != nil {
  277. return nil, nil, err
  278. }
  279. u := fmt.Sprintf("projects/%s/merge_requests/%d", url.QueryEscape(project), mergeRequest)
  280. req, err := s.client.NewRequest("GET", u, nil, options)
  281. if err != nil {
  282. return nil, nil, err
  283. }
  284. m := new(MergeRequest)
  285. resp, err := s.client.Do(req, m)
  286. if err != nil {
  287. return nil, resp, err
  288. }
  289. return m, resp, err
  290. }
  291. // GetMergeRequestApprovals gets information about a merge requests approvals
  292. //
  293. // GitLab API docs:
  294. // https://docs.gitlab.com/ee/api/merge_request_approvals.html#merge-request-level-mr-approvals
  295. func (s *MergeRequestsService) GetMergeRequestApprovals(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequestApprovals, *Response, error) {
  296. project, err := parseID(pid)
  297. if err != nil {
  298. return nil, nil, err
  299. }
  300. u := fmt.Sprintf("projects/%s/merge_requests/%d/approvals", url.QueryEscape(project), mergeRequest)
  301. req, err := s.client.NewRequest("GET", u, nil, options)
  302. if err != nil {
  303. return nil, nil, err
  304. }
  305. a := new(MergeRequestApprovals)
  306. resp, err := s.client.Do(req, a)
  307. if err != nil {
  308. return nil, resp, err
  309. }
  310. return a, resp, err
  311. }
  312. // GetMergeRequestCommitsOptions represents the available GetMergeRequestCommits()
  313. // options.
  314. //
  315. // GitLab API docs:
  316. // https://docs.gitlab.com/ce/api/merge_requests.html#get-single-mr-commits
  317. type GetMergeRequestCommitsOptions ListOptions
  318. // GetMergeRequestCommits gets a list of merge request commits.
  319. //
  320. // GitLab API docs:
  321. // https://docs.gitlab.com/ce/api/merge_requests.html#get-single-mr-commits
  322. func (s *MergeRequestsService) GetMergeRequestCommits(pid interface{}, mergeRequest int, opt *GetMergeRequestCommitsOptions, options ...OptionFunc) ([]*Commit, *Response, error) {
  323. project, err := parseID(pid)
  324. if err != nil {
  325. return nil, nil, err
  326. }
  327. u := fmt.Sprintf("projects/%s/merge_requests/%d/commits", url.QueryEscape(project), mergeRequest)
  328. req, err := s.client.NewRequest("GET", u, opt, options)
  329. if err != nil {
  330. return nil, nil, err
  331. }
  332. var c []*Commit
  333. resp, err := s.client.Do(req, &c)
  334. if err != nil {
  335. return nil, resp, err
  336. }
  337. return c, resp, err
  338. }
  339. // GetMergeRequestChanges shows information about the merge request including
  340. // its files and changes.
  341. //
  342. // GitLab API docs:
  343. // https://docs.gitlab.com/ce/api/merge_requests.html#get-single-mr-changes
  344. func (s *MergeRequestsService) GetMergeRequestChanges(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequest, *Response, error) {
  345. project, err := parseID(pid)
  346. if err != nil {
  347. return nil, nil, err
  348. }
  349. u := fmt.Sprintf("projects/%s/merge_requests/%d/changes", url.QueryEscape(project), mergeRequest)
  350. req, err := s.client.NewRequest("GET", u, nil, options)
  351. if err != nil {
  352. return nil, nil, err
  353. }
  354. m := new(MergeRequest)
  355. resp, err := s.client.Do(req, m)
  356. if err != nil {
  357. return nil, resp, err
  358. }
  359. return m, resp, err
  360. }
  361. // ListMergeRequestPipelines gets all pipelines for the provided merge request.
  362. //
  363. // GitLab API docs:
  364. // https://docs.gitlab.com/ce/api/merge_requests.html#list-mr-pipelines
  365. func (s *MergeRequestsService) ListMergeRequestPipelines(pid interface{}, mergeRequest int, options ...OptionFunc) (PipelineList, *Response, error) {
  366. project, err := parseID(pid)
  367. if err != nil {
  368. return nil, nil, err
  369. }
  370. u := fmt.Sprintf("projects/%s/merge_requests/%d/pipelines", url.QueryEscape(project), mergeRequest)
  371. req, err := s.client.NewRequest("GET", u, nil, options)
  372. if err != nil {
  373. return nil, nil, err
  374. }
  375. var p PipelineList
  376. resp, err := s.client.Do(req, &p)
  377. if err != nil {
  378. return nil, resp, err
  379. }
  380. return p, resp, err
  381. }
  382. // GetIssuesClosedOnMergeOptions represents the available GetIssuesClosedOnMerge()
  383. // options.
  384. //
  385. // GitLab API docs:
  386. // https://docs.gitlab.com/ce/api/merge_requests.html#list-issues-that-will-close-on-merge
  387. type GetIssuesClosedOnMergeOptions ListOptions
  388. // GetIssuesClosedOnMerge gets all the issues that would be closed by merging the
  389. // provided merge request.
  390. //
  391. // GitLab API docs:
  392. // https://docs.gitlab.com/ce/api/merge_requests.html#list-issues-that-will-close-on-merge
  393. func (s *MergeRequestsService) GetIssuesClosedOnMerge(pid interface{}, mergeRequest int, opt *GetIssuesClosedOnMergeOptions, options ...OptionFunc) ([]*Issue, *Response, error) {
  394. project, err := parseID(pid)
  395. if err != nil {
  396. return nil, nil, err
  397. }
  398. u := fmt.Sprintf("/projects/%s/merge_requests/%d/closes_issues", url.QueryEscape(project), mergeRequest)
  399. req, err := s.client.NewRequest("GET", u, opt, options)
  400. if err != nil {
  401. return nil, nil, err
  402. }
  403. var i []*Issue
  404. resp, err := s.client.Do(req, &i)
  405. if err != nil {
  406. return nil, resp, err
  407. }
  408. return i, resp, err
  409. }
  410. // CreateMergeRequestOptions represents the available CreateMergeRequest()
  411. // options.
  412. //
  413. // GitLab API docs:
  414. // https://docs.gitlab.com/ce/api/merge_requests.html#create-mr
  415. type CreateMergeRequestOptions struct {
  416. Title *string `url:"title,omitempty" json:"title,omitempty"`
  417. Description *string `url:"description,omitempty" json:"description,omitempty"`
  418. SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
  419. TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
  420. Labels Labels `url:"labels,comma,omitempty" json:"labels,omitempty"`
  421. AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
  422. TargetProjectID *int `url:"target_project_id,omitempty" json:"target_project_id,omitempty"`
  423. MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"`
  424. RemoveSourceBranch *bool `url:"remove_source_branch,omitempty" json:"remove_source_branch,omitempty"`
  425. Squash *bool `url:"squash,omitempty" json:"squash,omitempty"`
  426. AllowCollaboration *bool `url:"allow_collaboration,omitempty" json:"allow_collaboration,omitempty"`
  427. }
  428. // CreateMergeRequest creates a new merge request.
  429. //
  430. // GitLab API docs:
  431. // https://docs.gitlab.com/ce/api/merge_requests.html#create-mr
  432. func (s *MergeRequestsService) CreateMergeRequest(pid interface{}, opt *CreateMergeRequestOptions, options ...OptionFunc) (*MergeRequest, *Response, error) {
  433. project, err := parseID(pid)
  434. if err != nil {
  435. return nil, nil, err
  436. }
  437. u := fmt.Sprintf("projects/%s/merge_requests", url.QueryEscape(project))
  438. req, err := s.client.NewRequest("POST", u, opt, options)
  439. if err != nil {
  440. return nil, nil, err
  441. }
  442. m := new(MergeRequest)
  443. resp, err := s.client.Do(req, m)
  444. if err != nil {
  445. return nil, resp, err
  446. }
  447. return m, resp, err
  448. }
  449. // UpdateMergeRequestOptions represents the available UpdateMergeRequest()
  450. // options.
  451. //
  452. // GitLab API docs:
  453. // https://docs.gitlab.com/ce/api/merge_requests.html#update-mr
  454. type UpdateMergeRequestOptions struct {
  455. Title *string `url:"title,omitempty" json:"title,omitempty"`
  456. Description *string `url:"description,omitempty" json:"description,omitempty"`
  457. TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
  458. AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
  459. Labels Labels `url:"labels,comma,omitempty" json:"labels,omitempty"`
  460. MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"`
  461. StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"`
  462. RemoveSourceBranch *bool `url:"remove_source_branch,omitempty" json:"remove_source_branch,omitempty"`
  463. Squash *bool `url:"squash,omitempty" json:"squash,omitempty"`
  464. DiscussionLocked *bool `url:"discussion_locked,omitempty" json:"discussion_locked,omitempty"`
  465. AllowCollaboration *bool `url:"allow_collaboration,omitempty" json:"allow_collaboration,omitempty"`
  466. }
  467. // UpdateMergeRequest updates an existing project milestone.
  468. //
  469. // GitLab API docs:
  470. // https://docs.gitlab.com/ce/api/merge_requests.html#update-mr
  471. func (s *MergeRequestsService) UpdateMergeRequest(pid interface{}, mergeRequest int, opt *UpdateMergeRequestOptions, options ...OptionFunc) (*MergeRequest, *Response, error) {
  472. project, err := parseID(pid)
  473. if err != nil {
  474. return nil, nil, err
  475. }
  476. u := fmt.Sprintf("projects/%s/merge_requests/%d", url.QueryEscape(project), mergeRequest)
  477. req, err := s.client.NewRequest("PUT", u, opt, options)
  478. if err != nil {
  479. return nil, nil, err
  480. }
  481. m := new(MergeRequest)
  482. resp, err := s.client.Do(req, m)
  483. if err != nil {
  484. return nil, resp, err
  485. }
  486. return m, resp, err
  487. }
  488. // DeleteMergeRequest deletes a merge request.
  489. //
  490. // GitLab API docs:
  491. // https://docs.gitlab.com/ce/api/merge_requests.html#delete-a-merge-request
  492. func (s *MergeRequestsService) DeleteMergeRequest(pid interface{}, mergeRequest int, options ...OptionFunc) (*Response, error) {
  493. project, err := parseID(pid)
  494. if err != nil {
  495. return nil, err
  496. }
  497. u := fmt.Sprintf("projects/%s/merge_requests/%d", url.QueryEscape(project), mergeRequest)
  498. req, err := s.client.NewRequest("DELETE", u, nil, options)
  499. if err != nil {
  500. return nil, err
  501. }
  502. return s.client.Do(req, nil)
  503. }
  504. // AcceptMergeRequestOptions represents the available AcceptMergeRequest()
  505. // options.
  506. //
  507. // GitLab API docs:
  508. // https://docs.gitlab.com/ce/api/merge_requests.html#accept-mr
  509. type AcceptMergeRequestOptions struct {
  510. MergeCommitMessage *string `url:"merge_commit_message,omitempty" json:"merge_commit_message,omitempty"`
  511. ShouldRemoveSourceBranch *bool `url:"should_remove_source_branch,omitempty" json:"should_remove_source_branch,omitempty"`
  512. MergeWhenPipelineSucceeds *bool `url:"merge_when_pipeline_succeeds,omitempty" json:"merge_when_pipeline_succeeds,omitempty"`
  513. Sha *string `url:"sha,omitempty" json:"sha,omitempty"`
  514. }
  515. // AcceptMergeRequest merges changes submitted with MR using this API. If merge
  516. // success you get 200 OK. If it has some conflicts and can not be merged - you
  517. // get 405 and error message 'Branch cannot be merged'. If merge request is
  518. // already merged or closed - you get 405 and error message 'Method Not Allowed'
  519. //
  520. // GitLab API docs:
  521. // https://docs.gitlab.com/ce/api/merge_requests.html#accept-mr
  522. func (s *MergeRequestsService) AcceptMergeRequest(pid interface{}, mergeRequest int, opt *AcceptMergeRequestOptions, options ...OptionFunc) (*MergeRequest, *Response, error) {
  523. project, err := parseID(pid)
  524. if err != nil {
  525. return nil, nil, err
  526. }
  527. u := fmt.Sprintf("projects/%s/merge_requests/%d/merge", url.QueryEscape(project), mergeRequest)
  528. req, err := s.client.NewRequest("PUT", u, opt, options)
  529. if err != nil {
  530. return nil, nil, err
  531. }
  532. m := new(MergeRequest)
  533. resp, err := s.client.Do(req, m)
  534. if err != nil {
  535. return nil, resp, err
  536. }
  537. return m, resp, err
  538. }
  539. // CancelMergeWhenPipelineSucceeds cancels a merge when pipeline succeeds. If
  540. // you don't have permissions to accept this merge request - you'll get a 401.
  541. // If the merge request is already merged or closed - you get 405 and error
  542. // message 'Method Not Allowed'. In case the merge request is not set to be
  543. // merged when the pipeline succeeds, you'll also get a 406 error.
  544. //
  545. // GitLab API docs:
  546. // https://docs.gitlab.com/ce/api/merge_requests.html#cancel-merge-when-pipeline-succeeds
  547. func (s *MergeRequestsService) CancelMergeWhenPipelineSucceeds(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequest, *Response, error) {
  548. project, err := parseID(pid)
  549. if err != nil {
  550. return nil, nil, err
  551. }
  552. u := fmt.Sprintf("projects/%s/merge_requests/%d/cancel_merge_when_pipeline_succeeds", url.QueryEscape(project), mergeRequest)
  553. req, err := s.client.NewRequest("PUT", u, nil, options)
  554. if err != nil {
  555. return nil, nil, err
  556. }
  557. m := new(MergeRequest)
  558. resp, err := s.client.Do(req, m)
  559. if err != nil {
  560. return nil, resp, err
  561. }
  562. return m, resp, err
  563. }
  564. // GetMergeRequestDiffVersionsOptions represents the available
  565. // GetMergeRequestDiffVersions() options.
  566. //
  567. // GitLab API docs:
  568. // https://docs.gitlab.com/ce/api/merge_requests.html#get-mr-diff-versions
  569. type GetMergeRequestDiffVersionsOptions ListOptions
  570. // GetMergeRequestDiffVersions get a list of merge request diff versions.
  571. //
  572. // GitLab API docs:
  573. // https://docs.gitlab.com/ce/api/merge_requests.html#get-mr-diff-versions
  574. func (s *MergeRequestsService) GetMergeRequestDiffVersions(pid interface{}, mergeRequest int, opt *GetMergeRequestDiffVersionsOptions, options ...OptionFunc) ([]*MergeRequestDiffVersion, *Response, error) {
  575. project, err := parseID(pid)
  576. if err != nil {
  577. return nil, nil, err
  578. }
  579. u := fmt.Sprintf("projects/%s/merge_requests/%d/versions", url.QueryEscape(project), mergeRequest)
  580. req, err := s.client.NewRequest("GET", u, opt, options)
  581. if err != nil {
  582. return nil, nil, err
  583. }
  584. var v []*MergeRequestDiffVersion
  585. resp, err := s.client.Do(req, &v)
  586. if err != nil {
  587. return nil, resp, err
  588. }
  589. return v, resp, err
  590. }
  591. // GetSingleMergeRequestDiffVersion get a single MR diff version
  592. //
  593. // GitLab API docs:
  594. // https://docs.gitlab.com/ce/api/merge_requests.html#get-a-single-mr-diff-version
  595. func (s *MergeRequestsService) GetSingleMergeRequestDiffVersion(pid interface{}, mergeRequest, version int, options ...OptionFunc) (*MergeRequestDiffVersion, *Response, error) {
  596. project, err := parseID(pid)
  597. if err != nil {
  598. return nil, nil, err
  599. }
  600. u := fmt.Sprintf("projects/%s/merge_requests/%d/versions/%d", url.QueryEscape(project), mergeRequest, version)
  601. req, err := s.client.NewRequest("GET", u, nil, options)
  602. if err != nil {
  603. return nil, nil, err
  604. }
  605. var v = new(MergeRequestDiffVersion)
  606. resp, err := s.client.Do(req, v)
  607. if err != nil {
  608. return nil, resp, err
  609. }
  610. return v, resp, err
  611. }
  612. // SubscribeToMergeRequest subscribes the authenticated user to the given merge
  613. // request to receive notifications. If the user is already subscribed to the
  614. // merge request, the status code 304 is returned.
  615. //
  616. // GitLab API docs:
  617. // https://docs.gitlab.com/ce/api/merge_requests.html#subscribe-to-a-merge-request
  618. func (s *MergeRequestsService) SubscribeToMergeRequest(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequest, *Response, error) {
  619. project, err := parseID(pid)
  620. if err != nil {
  621. return nil, nil, err
  622. }
  623. u := fmt.Sprintf("projects/%s/merge_requests/%d/subscribe", url.QueryEscape(project), mergeRequest)
  624. req, err := s.client.NewRequest("POST", u, nil, options)
  625. if err != nil {
  626. return nil, nil, err
  627. }
  628. m := new(MergeRequest)
  629. resp, err := s.client.Do(req, m)
  630. if err != nil {
  631. return nil, resp, err
  632. }
  633. return m, resp, err
  634. }
  635. // UnsubscribeFromMergeRequest unsubscribes the authenticated user from the
  636. // given merge request to not receive notifications from that merge request.
  637. // If the user is not subscribed to the merge request, status code 304 is
  638. // returned.
  639. //
  640. // GitLab API docs:
  641. // https://docs.gitlab.com/ce/api/merge_requests.html#unsubscribe-from-a-merge-request
  642. func (s *MergeRequestsService) UnsubscribeFromMergeRequest(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequest, *Response, error) {
  643. project, err := parseID(pid)
  644. if err != nil {
  645. return nil, nil, err
  646. }
  647. u := fmt.Sprintf("projects/%s/merge_requests/%d/unsubscribe", url.QueryEscape(project), mergeRequest)
  648. req, err := s.client.NewRequest("POST", u, nil, options)
  649. if err != nil {
  650. return nil, nil, err
  651. }
  652. m := new(MergeRequest)
  653. resp, err := s.client.Do(req, m)
  654. if err != nil {
  655. return nil, resp, err
  656. }
  657. return m, resp, err
  658. }
  659. // CreateTodo manually creates a todo for the current user on a merge request.
  660. // If there already exists a todo for the user on that merge request,
  661. // status code 304 is returned.
  662. //
  663. // GitLab API docs:
  664. // https://docs.gitlab.com/ce/api/merge_requests.html#create-a-todo
  665. func (s *MergeRequestsService) CreateTodo(pid interface{}, mergeRequest int, options ...OptionFunc) (*Todo, *Response, error) {
  666. project, err := parseID(pid)
  667. if err != nil {
  668. return nil, nil, err
  669. }
  670. u := fmt.Sprintf("projects/%s/merge_requests/%d/todo", url.QueryEscape(project), mergeRequest)
  671. req, err := s.client.NewRequest("POST", u, nil, options)
  672. if err != nil {
  673. return nil, nil, err
  674. }
  675. t := new(Todo)
  676. resp, err := s.client.Do(req, t)
  677. if err != nil {
  678. return nil, resp, err
  679. }
  680. return t, resp, err
  681. }
  682. // SetTimeEstimate sets the time estimate for a single project merge request.
  683. //
  684. // GitLab API docs:
  685. // https://docs.gitlab.com/ce/api/merge_requests.html#set-a-time-estimate-for-a-merge-request
  686. func (s *MergeRequestsService) SetTimeEstimate(pid interface{}, mergeRequest int, opt *SetTimeEstimateOptions, options ...OptionFunc) (*TimeStats, *Response, error) {
  687. return s.timeStats.setTimeEstimate(pid, "merge_requests", mergeRequest, opt, options...)
  688. }
  689. // ResetTimeEstimate resets the time estimate for a single project merge request.
  690. //
  691. // GitLab API docs:
  692. // https://docs.gitlab.com/ce/api/merge_requests.html#reset-the-time-estimate-for-a-merge-request
  693. func (s *MergeRequestsService) ResetTimeEstimate(pid interface{}, mergeRequest int, options ...OptionFunc) (*TimeStats, *Response, error) {
  694. return s.timeStats.resetTimeEstimate(pid, "merge_requests", mergeRequest, options...)
  695. }
  696. // AddSpentTime adds spent time for a single project merge request.
  697. //
  698. // GitLab API docs:
  699. // https://docs.gitlab.com/ce/api/merge_requests.html#add-spent-time-for-a-merge-request
  700. func (s *MergeRequestsService) AddSpentTime(pid interface{}, mergeRequest int, opt *AddSpentTimeOptions, options ...OptionFunc) (*TimeStats, *Response, error) {
  701. return s.timeStats.addSpentTime(pid, "merge_requests", mergeRequest, opt, options...)
  702. }
  703. // ResetSpentTime resets the spent time for a single project merge request.
  704. //
  705. // GitLab API docs:
  706. // https://docs.gitlab.com/ce/api/merge_requests.html#reset-spent-time-for-a-merge-request
  707. func (s *MergeRequestsService) ResetSpentTime(pid interface{}, mergeRequest int, options ...OptionFunc) (*TimeStats, *Response, error) {
  708. return s.timeStats.resetSpentTime(pid, "merge_requests", mergeRequest, options...)
  709. }
  710. // GetTimeSpent gets the spent time for a single project merge request.
  711. //
  712. // GitLab API docs:
  713. // https://docs.gitlab.com/ce/api/merge_requests.html#get-time-tracking-stats
  714. func (s *MergeRequestsService) GetTimeSpent(pid interface{}, mergeRequest int, options ...OptionFunc) (*TimeStats, *Response, error) {
  715. return s.timeStats.getTimeSpent(pid, "merge_requests", mergeRequest, options...)
  716. }