notes.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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. // NotesService handles communication with the notes related methods
  23. // of the GitLab API.
  24. //
  25. // GitLab API docs: https://docs.gitlab.com/ce/api/notes.html
  26. type NotesService struct {
  27. client *Client
  28. }
  29. // Note represents a GitLab note.
  30. //
  31. // GitLab API docs: https://docs.gitlab.com/ce/api/notes.html
  32. type Note struct {
  33. ID int `json:"id"`
  34. Body string `json:"body"`
  35. Attachment string `json:"attachment"`
  36. Title string `json:"title"`
  37. FileName string `json:"file_name"`
  38. Author struct {
  39. ID int `json:"id"`
  40. Username string `json:"username"`
  41. Email string `json:"email"`
  42. Name string `json:"name"`
  43. State string `json:"state"`
  44. AvatarURL string `json:"avatar_url"`
  45. WebURL string `json:"web_url"`
  46. } `json:"author"`
  47. System bool `json:"system"`
  48. ExpiresAt *time.Time `json:"expires_at"`
  49. UpdatedAt *time.Time `json:"updated_at"`
  50. CreatedAt *time.Time `json:"created_at"`
  51. NoteableID int `json:"noteable_id"`
  52. NoteableType string `json:"noteable_type"`
  53. Position *NotePosition `json:"position"`
  54. Resolvable bool `json:"resolvable"`
  55. Resolved bool `json:"resolved"`
  56. ResolvedBy struct {
  57. ID int `json:"id"`
  58. Username string `json:"username"`
  59. Email string `json:"email"`
  60. Name string `json:"name"`
  61. State string `json:"state"`
  62. AvatarURL string `json:"avatar_url"`
  63. WebURL string `json:"web_url"`
  64. } `json:"resolved_by"`
  65. NoteableIID int `json:"noteable_iid"`
  66. }
  67. // NotePosition represents the position attributes of a note.
  68. type NotePosition struct {
  69. BaseSHA string `json:"base_sha"`
  70. StartSHA string `json:"start_sha"`
  71. HeadSHA string `json:"head_sha"`
  72. PositionType string `json:"position_type"`
  73. NewPath string `json:"new_path,omitempty"`
  74. NewLine int `json:"new_line,omitempty"`
  75. OldPath string `json:"old_path,omitempty"`
  76. OldLine int `json:"old_line,omitempty"`
  77. Width int `json:"width,omitempty"`
  78. Height int `json:"height,omitempty"`
  79. X int `json:"x,omitempty"`
  80. Y int `json:"y,omitempty"`
  81. }
  82. func (n Note) String() string {
  83. return Stringify(n)
  84. }
  85. // ListIssueNotesOptions represents the available ListIssueNotes() options.
  86. //
  87. // GitLab API docs:
  88. // https://docs.gitlab.com/ce/api/notes.html#list-project-issue-notes
  89. type ListIssueNotesOptions struct {
  90. ListOptions
  91. OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
  92. Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
  93. }
  94. // ListIssueNotes gets a list of all notes for a single issue.
  95. //
  96. // GitLab API docs:
  97. // https://docs.gitlab.com/ce/api/notes.html#list-project-issue-notes
  98. func (s *NotesService) ListIssueNotes(pid interface{}, issue int, opt *ListIssueNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) {
  99. project, err := parseID(pid)
  100. if err != nil {
  101. return nil, nil, err
  102. }
  103. u := fmt.Sprintf("projects/%s/issues/%d/notes", url.QueryEscape(project), issue)
  104. req, err := s.client.NewRequest("GET", u, opt, options)
  105. if err != nil {
  106. return nil, nil, err
  107. }
  108. var n []*Note
  109. resp, err := s.client.Do(req, &n)
  110. if err != nil {
  111. return nil, resp, err
  112. }
  113. return n, resp, err
  114. }
  115. // GetIssueNote returns a single note for a specific project issue.
  116. //
  117. // GitLab API docs:
  118. // https://docs.gitlab.com/ce/api/notes.html#get-single-issue-note
  119. func (s *NotesService) GetIssueNote(pid interface{}, issue, note int, options ...OptionFunc) (*Note, *Response, error) {
  120. project, err := parseID(pid)
  121. if err != nil {
  122. return nil, nil, err
  123. }
  124. u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", url.QueryEscape(project), issue, note)
  125. req, err := s.client.NewRequest("GET", u, nil, options)
  126. if err != nil {
  127. return nil, nil, err
  128. }
  129. n := new(Note)
  130. resp, err := s.client.Do(req, n)
  131. if err != nil {
  132. return nil, resp, err
  133. }
  134. return n, resp, err
  135. }
  136. // CreateIssueNoteOptions represents the available CreateIssueNote()
  137. // options.
  138. //
  139. // GitLab API docs:
  140. // https://docs.gitlab.com/ce/api/notes.html#create-new-issue-note
  141. type CreateIssueNoteOptions struct {
  142. Body *string `url:"body,omitempty" json:"body,omitempty"`
  143. }
  144. // CreateIssueNote creates a new note to a single project issue.
  145. //
  146. // GitLab API docs:
  147. // https://docs.gitlab.com/ce/api/notes.html#create-new-issue-note
  148. func (s *NotesService) CreateIssueNote(pid interface{}, issue int, opt *CreateIssueNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
  149. project, err := parseID(pid)
  150. if err != nil {
  151. return nil, nil, err
  152. }
  153. u := fmt.Sprintf("projects/%s/issues/%d/notes", url.QueryEscape(project), issue)
  154. req, err := s.client.NewRequest("POST", u, opt, options)
  155. if err != nil {
  156. return nil, nil, err
  157. }
  158. n := new(Note)
  159. resp, err := s.client.Do(req, n)
  160. if err != nil {
  161. return nil, resp, err
  162. }
  163. return n, resp, err
  164. }
  165. // UpdateIssueNoteOptions represents the available UpdateIssueNote()
  166. // options.
  167. //
  168. // GitLab API docs:
  169. // https://docs.gitlab.com/ce/api/notes.html#modify-existing-issue-note
  170. type UpdateIssueNoteOptions struct {
  171. Body *string `url:"body,omitempty" json:"body,omitempty"`
  172. }
  173. // UpdateIssueNote modifies existing note of an issue.
  174. //
  175. // https://docs.gitlab.com/ce/api/notes.html#modify-existing-issue-note
  176. func (s *NotesService) UpdateIssueNote(pid interface{}, issue, note int, opt *UpdateIssueNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
  177. project, err := parseID(pid)
  178. if err != nil {
  179. return nil, nil, err
  180. }
  181. u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", url.QueryEscape(project), issue, note)
  182. req, err := s.client.NewRequest("PUT", u, opt, options)
  183. if err != nil {
  184. return nil, nil, err
  185. }
  186. n := new(Note)
  187. resp, err := s.client.Do(req, n)
  188. if err != nil {
  189. return nil, resp, err
  190. }
  191. return n, resp, err
  192. }
  193. // DeleteIssueNote deletes an existing note of an issue.
  194. //
  195. // https://docs.gitlab.com/ce/api/notes.html#delete-an-issue-note
  196. func (s *NotesService) DeleteIssueNote(pid interface{}, issue, note int, options ...OptionFunc) (*Response, error) {
  197. project, err := parseID(pid)
  198. if err != nil {
  199. return nil, err
  200. }
  201. u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", url.QueryEscape(project), issue, note)
  202. req, err := s.client.NewRequest("DELETE", u, nil, options)
  203. if err != nil {
  204. return nil, err
  205. }
  206. return s.client.Do(req, nil)
  207. }
  208. // ListSnippetNotesOptions represents the available ListSnippetNotes() options.
  209. //
  210. // GitLab API docs:
  211. // https://docs.gitlab.com/ce/api/notes.html#list-all-snippet-notes
  212. type ListSnippetNotesOptions ListOptions
  213. // ListSnippetNotes gets a list of all notes for a single snippet. Snippet
  214. // notes are comments users can post to a snippet.
  215. //
  216. // GitLab API docs:
  217. // https://docs.gitlab.com/ce/api/notes.html#list-all-snippet-notes
  218. func (s *NotesService) ListSnippetNotes(pid interface{}, snippet int, opt *ListSnippetNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) {
  219. project, err := parseID(pid)
  220. if err != nil {
  221. return nil, nil, err
  222. }
  223. u := fmt.Sprintf("projects/%s/snippets/%d/notes", url.QueryEscape(project), snippet)
  224. req, err := s.client.NewRequest("GET", u, opt, options)
  225. if err != nil {
  226. return nil, nil, err
  227. }
  228. var n []*Note
  229. resp, err := s.client.Do(req, &n)
  230. if err != nil {
  231. return nil, resp, err
  232. }
  233. return n, resp, err
  234. }
  235. // GetSnippetNote returns a single note for a given snippet.
  236. //
  237. // GitLab API docs:
  238. // https://docs.gitlab.com/ce/api/notes.html#get-single-snippet-note
  239. func (s *NotesService) GetSnippetNote(pid interface{}, snippet, note int, options ...OptionFunc) (*Note, *Response, error) {
  240. project, err := parseID(pid)
  241. if err != nil {
  242. return nil, nil, err
  243. }
  244. u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", url.QueryEscape(project), snippet, note)
  245. req, err := s.client.NewRequest("GET", u, nil, options)
  246. if err != nil {
  247. return nil, nil, err
  248. }
  249. n := new(Note)
  250. resp, err := s.client.Do(req, n)
  251. if err != nil {
  252. return nil, resp, err
  253. }
  254. return n, resp, err
  255. }
  256. // CreateSnippetNoteOptions represents the available CreateSnippetNote()
  257. // options.
  258. //
  259. // GitLab API docs:
  260. // https://docs.gitlab.com/ce/api/notes.html#create-new-snippet-note
  261. type CreateSnippetNoteOptions struct {
  262. Body *string `url:"body,omitempty" json:"body,omitempty"`
  263. }
  264. // CreateSnippetNote creates a new note for a single snippet. Snippet notes are
  265. // comments users can post to a snippet.
  266. //
  267. // GitLab API docs:
  268. // https://docs.gitlab.com/ce/api/notes.html#create-new-snippet-note
  269. func (s *NotesService) CreateSnippetNote(pid interface{}, snippet int, opt *CreateSnippetNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
  270. project, err := parseID(pid)
  271. if err != nil {
  272. return nil, nil, err
  273. }
  274. u := fmt.Sprintf("projects/%s/snippets/%d/notes", url.QueryEscape(project), snippet)
  275. req, err := s.client.NewRequest("POST", u, opt, options)
  276. if err != nil {
  277. return nil, nil, err
  278. }
  279. n := new(Note)
  280. resp, err := s.client.Do(req, n)
  281. if err != nil {
  282. return nil, resp, err
  283. }
  284. return n, resp, err
  285. }
  286. // UpdateSnippetNoteOptions represents the available UpdateSnippetNote()
  287. // options.
  288. //
  289. // GitLab API docs:
  290. // https://docs.gitlab.com/ce/api/notes.html#modify-existing-snippet-note
  291. type UpdateSnippetNoteOptions struct {
  292. Body *string `url:"body,omitempty" json:"body,omitempty"`
  293. }
  294. // UpdateSnippetNote modifies existing note of a snippet.
  295. //
  296. // https://docs.gitlab.com/ce/api/notes.html#modify-existing-snippet-note
  297. func (s *NotesService) UpdateSnippetNote(pid interface{}, snippet, note int, opt *UpdateSnippetNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
  298. project, err := parseID(pid)
  299. if err != nil {
  300. return nil, nil, err
  301. }
  302. u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", url.QueryEscape(project), snippet, note)
  303. req, err := s.client.NewRequest("PUT", u, opt, options)
  304. if err != nil {
  305. return nil, nil, err
  306. }
  307. n := new(Note)
  308. resp, err := s.client.Do(req, n)
  309. if err != nil {
  310. return nil, resp, err
  311. }
  312. return n, resp, err
  313. }
  314. // DeleteSnippetNote deletes an existing note of a snippet.
  315. //
  316. // https://docs.gitlab.com/ce/api/notes.html#delete-a-snippet-note
  317. func (s *NotesService) DeleteSnippetNote(pid interface{}, snippet, note int, options ...OptionFunc) (*Response, error) {
  318. project, err := parseID(pid)
  319. if err != nil {
  320. return nil, err
  321. }
  322. u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", url.QueryEscape(project), snippet, note)
  323. req, err := s.client.NewRequest("DELETE", u, nil, options)
  324. if err != nil {
  325. return nil, err
  326. }
  327. return s.client.Do(req, nil)
  328. }
  329. // ListMergeRequestNotesOptions represents the available ListMergeRequestNotes()
  330. // options.
  331. //
  332. // GitLab API docs:
  333. // https://docs.gitlab.com/ce/api/notes.html#list-all-merge-request-notes
  334. type ListMergeRequestNotesOptions ListOptions
  335. // ListMergeRequestNotes gets a list of all notes for a single merge request.
  336. //
  337. // GitLab API docs:
  338. // https://docs.gitlab.com/ce/api/notes.html#list-all-merge-request-notes
  339. func (s *NotesService) ListMergeRequestNotes(pid interface{}, mergeRequest int, opt *ListMergeRequestNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) {
  340. project, err := parseID(pid)
  341. if err != nil {
  342. return nil, nil, err
  343. }
  344. u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", url.QueryEscape(project), mergeRequest)
  345. req, err := s.client.NewRequest("GET", u, opt, options)
  346. if err != nil {
  347. return nil, nil, err
  348. }
  349. var n []*Note
  350. resp, err := s.client.Do(req, &n)
  351. if err != nil {
  352. return nil, resp, err
  353. }
  354. return n, resp, err
  355. }
  356. // GetMergeRequestNote returns a single note for a given merge request.
  357. //
  358. // GitLab API docs:
  359. // https://docs.gitlab.com/ce/api/notes.html#get-single-merge-request-note
  360. func (s *NotesService) GetMergeRequestNote(pid interface{}, mergeRequest, note int, options ...OptionFunc) (*Note, *Response, error) {
  361. project, err := parseID(pid)
  362. if err != nil {
  363. return nil, nil, err
  364. }
  365. u := fmt.Sprintf("projects/%s/merge_requests/%d/notes/%d", url.QueryEscape(project), mergeRequest, note)
  366. req, err := s.client.NewRequest("GET", u, nil, options)
  367. if err != nil {
  368. return nil, nil, err
  369. }
  370. n := new(Note)
  371. resp, err := s.client.Do(req, n)
  372. if err != nil {
  373. return nil, resp, err
  374. }
  375. return n, resp, err
  376. }
  377. // CreateMergeRequestNoteOptions represents the available
  378. // CreateMergeRequestNote() options.
  379. //
  380. // GitLab API docs:
  381. // https://docs.gitlab.com/ce/api/notes.html#create-new-merge-request-note
  382. type CreateMergeRequestNoteOptions struct {
  383. Body *string `url:"body,omitempty" json:"body,omitempty"`
  384. }
  385. // CreateMergeRequestNote creates a new note for a single merge request.
  386. //
  387. // GitLab API docs:
  388. // https://docs.gitlab.com/ce/api/notes.html#create-new-merge-request-note
  389. func (s *NotesService) CreateMergeRequestNote(pid interface{}, mergeRequest int, opt *CreateMergeRequestNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
  390. project, err := parseID(pid)
  391. if err != nil {
  392. return nil, nil, err
  393. }
  394. u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", url.QueryEscape(project), mergeRequest)
  395. req, err := s.client.NewRequest("POST", u, opt, options)
  396. if err != nil {
  397. return nil, nil, err
  398. }
  399. n := new(Note)
  400. resp, err := s.client.Do(req, n)
  401. if err != nil {
  402. return nil, resp, err
  403. }
  404. return n, resp, err
  405. }
  406. // UpdateMergeRequestNoteOptions represents the available
  407. // UpdateMergeRequestNote() options.
  408. //
  409. // GitLab API docs:
  410. // https://docs.gitlab.com/ce/api/notes.html#modify-existing-merge-request-note
  411. type UpdateMergeRequestNoteOptions struct {
  412. Body *string `url:"body,omitempty" json:"body,omitempty"`
  413. }
  414. // UpdateMergeRequestNote modifies existing note of a merge request.
  415. //
  416. // https://docs.gitlab.com/ce/api/notes.html#modify-existing-merge-request-note
  417. func (s *NotesService) UpdateMergeRequestNote(pid interface{}, mergeRequest, note int, opt *UpdateMergeRequestNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
  418. project, err := parseID(pid)
  419. if err != nil {
  420. return nil, nil, err
  421. }
  422. u := fmt.Sprintf(
  423. "projects/%s/merge_requests/%d/notes/%d", url.QueryEscape(project), mergeRequest, note)
  424. req, err := s.client.NewRequest("PUT", u, opt, options)
  425. if err != nil {
  426. return nil, nil, err
  427. }
  428. n := new(Note)
  429. resp, err := s.client.Do(req, n)
  430. if err != nil {
  431. return nil, resp, err
  432. }
  433. return n, resp, err
  434. }
  435. // DeleteMergeRequestNote deletes an existing note of a merge request.
  436. //
  437. // https://docs.gitlab.com/ce/api/notes.html#delete-a-merge-request-note
  438. func (s *NotesService) DeleteMergeRequestNote(pid interface{}, mergeRequest, note int, options ...OptionFunc) (*Response, error) {
  439. project, err := parseID(pid)
  440. if err != nil {
  441. return nil, err
  442. }
  443. u := fmt.Sprintf(
  444. "projects/%s/merge_requests/%d/notes/%d", url.QueryEscape(project), mergeRequest, note)
  445. req, err := s.client.NewRequest("DELETE", u, nil, options)
  446. if err != nil {
  447. return nil, err
  448. }
  449. return s.client.Do(req, nil)
  450. }