commits.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  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. // CommitsService handles communication with the commit related methods
  23. // of the GitLab API.
  24. //
  25. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html
  26. type CommitsService struct {
  27. client *Client
  28. }
  29. // Commit represents a GitLab commit.
  30. //
  31. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html
  32. type Commit struct {
  33. ID string `json:"id"`
  34. ShortID string `json:"short_id"`
  35. Title string `json:"title"`
  36. AuthorName string `json:"author_name"`
  37. AuthorEmail string `json:"author_email"`
  38. AuthoredDate *time.Time `json:"authored_date"`
  39. CommitterName string `json:"committer_name"`
  40. CommitterEmail string `json:"committer_email"`
  41. CommittedDate *time.Time `json:"committed_date"`
  42. CreatedAt *time.Time `json:"created_at"`
  43. Message string `json:"message"`
  44. ParentIDs []string `json:"parent_ids"`
  45. Stats *CommitStats `json:"stats"`
  46. Status *BuildStateValue `json:"status"`
  47. }
  48. // CommitStats represents the number of added and deleted files in a commit.
  49. //
  50. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html
  51. type CommitStats struct {
  52. Additions int `json:"additions"`
  53. Deletions int `json:"deletions"`
  54. Total int `json:"total"`
  55. }
  56. func (c Commit) String() string {
  57. return Stringify(c)
  58. }
  59. // ListCommitsOptions represents the available ListCommits() options.
  60. //
  61. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#list-repository-commits
  62. type ListCommitsOptions struct {
  63. ListOptions
  64. RefName *string `url:"ref_name,omitempty" json:"ref_name,omitempty"`
  65. Since *time.Time `url:"since,omitempty" json:"since,omitempty"`
  66. Until *time.Time `url:"until,omitempty" json:"until,omitempty"`
  67. Path *string `url:"path,omitempty" json:"path,omitempty"`
  68. All *bool `url:"all,omitempty" json:"all,omitempty"`
  69. WithStats *bool `url:"with_stats,omitempty" json:"with_stats,omitempty"`
  70. }
  71. // ListCommits gets a list of repository commits in a project.
  72. //
  73. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#list-commits
  74. func (s *CommitsService) ListCommits(pid interface{}, opt *ListCommitsOptions, options ...OptionFunc) ([]*Commit, *Response, error) {
  75. project, err := parseID(pid)
  76. if err != nil {
  77. return nil, nil, err
  78. }
  79. u := fmt.Sprintf("projects/%s/repository/commits", url.QueryEscape(project))
  80. req, err := s.client.NewRequest("GET", u, opt, options)
  81. if err != nil {
  82. return nil, nil, err
  83. }
  84. var c []*Commit
  85. resp, err := s.client.Do(req, &c)
  86. if err != nil {
  87. return nil, resp, err
  88. }
  89. return c, resp, err
  90. }
  91. // FileAction represents the available actions that can be performed on a file.
  92. //
  93. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
  94. type FileAction string
  95. // The available file actions.
  96. const (
  97. FileCreate FileAction = "create"
  98. FileDelete FileAction = "delete"
  99. FileMove FileAction = "move"
  100. FileUpdate FileAction = "update"
  101. )
  102. // CommitAction represents a single file action within a commit.
  103. type CommitAction struct {
  104. Action FileAction `url:"action" json:"action"`
  105. FilePath string `url:"file_path" json:"file_path"`
  106. PreviousPath string `url:"previous_path,omitempty" json:"previous_path,omitempty"`
  107. Content string `url:"content,omitempty" json:"content,omitempty"`
  108. Encoding string `url:"encoding,omitempty" json:"encoding,omitempty"`
  109. }
  110. // CommitRef represents the reference of branches/tags in a commit.
  111. //
  112. // GitLab API docs:
  113. // https://docs.gitlab.com/ce/api/commits.html#get-references-a-commit-is-pushed-to
  114. type CommitRef struct {
  115. Type string `json:"type"`
  116. Name string `json:"name"`
  117. }
  118. // GetCommitRefsOptions represents the available GetCommitRefs() options.
  119. //
  120. // GitLab API docs:
  121. // https://docs.gitlab.com/ce/api/commits.html#get-references-a-commit-is-pushed-to
  122. type GetCommitRefsOptions struct {
  123. ListOptions
  124. Type *string `url:"type,omitempty" json:"type,omitempty"`
  125. }
  126. // GetCommitRefs gets all references (from branches or tags) a commit is pushed to
  127. //
  128. // GitLab API docs:
  129. // https://docs.gitlab.com/ce/api/commits.html#get-references-a-commit-is-pushed-to
  130. func (s *CommitsService) GetCommitRefs(pid interface{}, sha string, opt *GetCommitRefsOptions, options ...OptionFunc) ([]CommitRef, *Response, error) {
  131. project, err := parseID(pid)
  132. if err != nil {
  133. return nil, nil, err
  134. }
  135. u := fmt.Sprintf("projects/%s/repository/commits/%s/refs", url.QueryEscape(project), sha)
  136. req, err := s.client.NewRequest("GET", u, opt, options)
  137. if err != nil {
  138. return nil, nil, err
  139. }
  140. var cs []CommitRef
  141. resp, err := s.client.Do(req, &cs)
  142. if err != nil {
  143. return nil, resp, err
  144. }
  145. return cs, resp, err
  146. }
  147. // GetCommit gets a specific commit identified by the commit hash or name of a
  148. // branch or tag.
  149. //
  150. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#get-a-single-commit
  151. func (s *CommitsService) GetCommit(pid interface{}, sha string, options ...OptionFunc) (*Commit, *Response, error) {
  152. project, err := parseID(pid)
  153. if err != nil {
  154. return nil, nil, err
  155. }
  156. u := fmt.Sprintf("projects/%s/repository/commits/%s", url.QueryEscape(project), sha)
  157. req, err := s.client.NewRequest("GET", u, nil, options)
  158. if err != nil {
  159. return nil, nil, err
  160. }
  161. c := new(Commit)
  162. resp, err := s.client.Do(req, c)
  163. if err != nil {
  164. return nil, resp, err
  165. }
  166. return c, resp, err
  167. }
  168. // CreateCommitOptions represents the available options for a new commit.
  169. //
  170. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
  171. type CreateCommitOptions struct {
  172. Branch *string `url:"branch" json:"branch"`
  173. CommitMessage *string `url:"commit_message" json:"commit_message"`
  174. StartBranch *string `url:"start_branch,omitempty" json:"start_branch,omitempty"`
  175. Actions []*CommitAction `url:"actions" json:"actions"`
  176. AuthorEmail *string `url:"author_email,omitempty" json:"author_email,omitempty"`
  177. AuthorName *string `url:"author_name,omitempty" json:"author_name,omitempty"`
  178. }
  179. // CreateCommit creates a commit with multiple files and actions.
  180. //
  181. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
  182. func (s *CommitsService) CreateCommit(pid interface{}, opt *CreateCommitOptions, options ...OptionFunc) (*Commit, *Response, error) {
  183. project, err := parseID(pid)
  184. if err != nil {
  185. return nil, nil, err
  186. }
  187. u := fmt.Sprintf("projects/%s/repository/commits", url.QueryEscape(project))
  188. req, err := s.client.NewRequest("POST", u, opt, options)
  189. if err != nil {
  190. return nil, nil, err
  191. }
  192. var c *Commit
  193. resp, err := s.client.Do(req, &c)
  194. if err != nil {
  195. return nil, resp, err
  196. }
  197. return c, resp, err
  198. }
  199. // Diff represents a GitLab diff.
  200. //
  201. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html
  202. type Diff struct {
  203. Diff string `json:"diff"`
  204. NewPath string `json:"new_path"`
  205. OldPath string `json:"old_path"`
  206. AMode string `json:"a_mode"`
  207. BMode string `json:"b_mode"`
  208. NewFile bool `json:"new_file"`
  209. RenamedFile bool `json:"renamed_file"`
  210. DeletedFile bool `json:"deleted_file"`
  211. }
  212. func (d Diff) String() string {
  213. return Stringify(d)
  214. }
  215. // GetCommitDiffOptions represents the available GetCommitDiff() options.
  216. //
  217. // GitLab API docs:
  218. // https://docs.gitlab.com/ce/api/commits.html#get-the-diff-of-a-commit
  219. type GetCommitDiffOptions ListOptions
  220. // GetCommitDiff gets the diff of a commit in a project..
  221. //
  222. // GitLab API docs:
  223. // https://docs.gitlab.com/ce/api/commits.html#get-the-diff-of-a-commit
  224. func (s *CommitsService) GetCommitDiff(pid interface{}, sha string, opt *GetCommitDiffOptions, options ...OptionFunc) ([]*Diff, *Response, error) {
  225. project, err := parseID(pid)
  226. if err != nil {
  227. return nil, nil, err
  228. }
  229. u := fmt.Sprintf("projects/%s/repository/commits/%s/diff", url.QueryEscape(project), sha)
  230. req, err := s.client.NewRequest("GET", u, opt, options)
  231. if err != nil {
  232. return nil, nil, err
  233. }
  234. var d []*Diff
  235. resp, err := s.client.Do(req, &d)
  236. if err != nil {
  237. return nil, resp, err
  238. }
  239. return d, resp, err
  240. }
  241. // CommitComment represents a GitLab commit comment.
  242. //
  243. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html
  244. type CommitComment struct {
  245. Note string `json:"note"`
  246. Path string `json:"path"`
  247. Line int `json:"line"`
  248. LineType string `json:"line_type"`
  249. Author Author `json:"author"`
  250. }
  251. // Author represents a GitLab commit author
  252. type Author struct {
  253. ID int `json:"id"`
  254. Username string `json:"username"`
  255. Email string `json:"email"`
  256. Name string `json:"name"`
  257. State string `json:"state"`
  258. Blocked bool `json:"blocked"`
  259. CreatedAt *time.Time `json:"created_at"`
  260. }
  261. func (c CommitComment) String() string {
  262. return Stringify(c)
  263. }
  264. // GetCommitCommentsOptions represents the available GetCommitComments() options.
  265. //
  266. // GitLab API docs:
  267. // https://docs.gitlab.com/ce/api/commits.html#get-the-comments-of-a-commit
  268. type GetCommitCommentsOptions ListOptions
  269. // GetCommitComments gets the comments of a commit in a project.
  270. //
  271. // GitLab API docs:
  272. // https://docs.gitlab.com/ce/api/commits.html#get-the-comments-of-a-commit
  273. func (s *CommitsService) GetCommitComments(pid interface{}, sha string, opt *GetCommitCommentsOptions, options ...OptionFunc) ([]*CommitComment, *Response, error) {
  274. project, err := parseID(pid)
  275. if err != nil {
  276. return nil, nil, err
  277. }
  278. u := fmt.Sprintf("projects/%s/repository/commits/%s/comments", url.QueryEscape(project), sha)
  279. req, err := s.client.NewRequest("GET", u, opt, options)
  280. if err != nil {
  281. return nil, nil, err
  282. }
  283. var c []*CommitComment
  284. resp, err := s.client.Do(req, &c)
  285. if err != nil {
  286. return nil, resp, err
  287. }
  288. return c, resp, err
  289. }
  290. // PostCommitCommentOptions represents the available PostCommitComment()
  291. // options.
  292. //
  293. // GitLab API docs:
  294. // https://docs.gitlab.com/ce/api/commits.html#post-comment-to-commit
  295. type PostCommitCommentOptions struct {
  296. Note *string `url:"note,omitempty" json:"note,omitempty"`
  297. Path *string `url:"path" json:"path"`
  298. Line *int `url:"line" json:"line"`
  299. LineType *string `url:"line_type" json:"line_type"`
  300. }
  301. // PostCommitComment adds a comment to a commit. Optionally you can post
  302. // comments on a specific line of a commit. Therefor both path, line_new and
  303. // line_old are required.
  304. //
  305. // GitLab API docs:
  306. // https://docs.gitlab.com/ce/api/commits.html#post-comment-to-commit
  307. func (s *CommitsService) PostCommitComment(pid interface{}, sha string, opt *PostCommitCommentOptions, options ...OptionFunc) (*CommitComment, *Response, error) {
  308. project, err := parseID(pid)
  309. if err != nil {
  310. return nil, nil, err
  311. }
  312. u := fmt.Sprintf("projects/%s/repository/commits/%s/comments", url.QueryEscape(project), sha)
  313. req, err := s.client.NewRequest("POST", u, opt, options)
  314. if err != nil {
  315. return nil, nil, err
  316. }
  317. c := new(CommitComment)
  318. resp, err := s.client.Do(req, c)
  319. if err != nil {
  320. return nil, resp, err
  321. }
  322. return c, resp, err
  323. }
  324. // GetCommitStatusesOptions represents the available GetCommitStatuses() options.
  325. //
  326. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#get-the-status-of-a-commit
  327. type GetCommitStatusesOptions struct {
  328. ListOptions
  329. Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
  330. Stage *string `url:"stage,omitempty" json:"stage,omitempty"`
  331. Name *string `url:"name,omitempty" json:"name,omitempty"`
  332. All *bool `url:"all,omitempty" json:"all,omitempty"`
  333. }
  334. // CommitStatus represents a GitLab commit status.
  335. //
  336. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#get-the-status-of-a-commit
  337. type CommitStatus struct {
  338. ID int `json:"id"`
  339. SHA string `json:"sha"`
  340. Ref string `json:"ref"`
  341. Status string `json:"status"`
  342. Name string `json:"name"`
  343. TargetURL string `json:"target_url"`
  344. Description string `json:"description"`
  345. CreatedAt *time.Time `json:"created_at"`
  346. StartedAt *time.Time `json:"started_at"`
  347. FinishedAt *time.Time `json:"finished_at"`
  348. Author Author `json:"author"`
  349. }
  350. // GetCommitStatuses gets the statuses of a commit in a project.
  351. //
  352. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#get-the-status-of-a-commit
  353. func (s *CommitsService) GetCommitStatuses(pid interface{}, sha string, opt *GetCommitStatusesOptions, options ...OptionFunc) ([]*CommitStatus, *Response, error) {
  354. project, err := parseID(pid)
  355. if err != nil {
  356. return nil, nil, err
  357. }
  358. u := fmt.Sprintf("projects/%s/repository/commits/%s/statuses", url.QueryEscape(project), sha)
  359. req, err := s.client.NewRequest("GET", u, opt, options)
  360. if err != nil {
  361. return nil, nil, err
  362. }
  363. var cs []*CommitStatus
  364. resp, err := s.client.Do(req, &cs)
  365. if err != nil {
  366. return nil, resp, err
  367. }
  368. return cs, resp, err
  369. }
  370. // SetCommitStatusOptions represents the available SetCommitStatus() options.
  371. //
  372. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#post-the-status-to-commit
  373. type SetCommitStatusOptions struct {
  374. State BuildStateValue `url:"state" json:"state"`
  375. Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
  376. Name *string `url:"name,omitempty" json:"name,omitempty"`
  377. Context *string `url:"context,omitempty" json:"context,omitempty"`
  378. TargetURL *string `url:"target_url,omitempty" json:"target_url,omitempty"`
  379. Description *string `url:"description,omitempty" json:"description,omitempty"`
  380. }
  381. // SetCommitStatus sets the status of a commit in a project.
  382. //
  383. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#post-the-status-to-commit
  384. func (s *CommitsService) SetCommitStatus(pid interface{}, sha string, opt *SetCommitStatusOptions, options ...OptionFunc) (*CommitStatus, *Response, error) {
  385. project, err := parseID(pid)
  386. if err != nil {
  387. return nil, nil, err
  388. }
  389. u := fmt.Sprintf("projects/%s/statuses/%s", url.QueryEscape(project), sha)
  390. req, err := s.client.NewRequest("POST", u, opt, options)
  391. if err != nil {
  392. return nil, nil, err
  393. }
  394. var cs *CommitStatus
  395. resp, err := s.client.Do(req, &cs)
  396. if err != nil {
  397. return nil, resp, err
  398. }
  399. return cs, resp, err
  400. }
  401. // GetMergeRequestsByCommit gets merge request associated with a commit.
  402. //
  403. // GitLab API docs:
  404. // https://docs.gitlab.com/ce/api/commits.html#list-merge-requests-associated-with-a-commit
  405. func (s *CommitsService) GetMergeRequestsByCommit(pid interface{}, sha string, options ...OptionFunc) ([]*MergeRequest, *Response, error) {
  406. project, err := parseID(pid)
  407. if err != nil {
  408. return nil, nil, err
  409. }
  410. u := fmt.Sprintf("projects/%s/repository/commits/%s/merge_requests",
  411. url.QueryEscape(project), url.QueryEscape(sha))
  412. req, err := s.client.NewRequest("GET", u, nil, options)
  413. if err != nil {
  414. return nil, nil, err
  415. }
  416. var mrs []*MergeRequest
  417. resp, err := s.client.Do(req, &mrs)
  418. if err != nil {
  419. return nil, resp, err
  420. }
  421. return mrs, resp, err
  422. }
  423. // CherryPickCommitOptions represents the available options for cherry-picking a commit.
  424. //
  425. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#cherry-pick-a-commit
  426. type CherryPickCommitOptions struct {
  427. TargetBranch *string `url:"branch" json:"branch,omitempty"`
  428. }
  429. // CherryPickCommit sherry picks a commit to a given branch.
  430. //
  431. // GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#cherry-pick-a-commit
  432. func (s *CommitsService) CherryPickCommit(pid interface{}, sha string, opt *CherryPickCommitOptions, options ...OptionFunc) (*Commit, *Response, error) {
  433. project, err := parseID(pid)
  434. if err != nil {
  435. return nil, nil, err
  436. }
  437. u := fmt.Sprintf("projects/%s/repository/commits/%s/cherry_pick",
  438. url.QueryEscape(project), url.QueryEscape(sha))
  439. req, err := s.client.NewRequest("POST", u, opt, options)
  440. if err != nil {
  441. return nil, nil, err
  442. }
  443. var c *Commit
  444. resp, err := s.client.Do(req, &c)
  445. if err != nil {
  446. return nil, resp, err
  447. }
  448. return c, resp, err
  449. }