1//
2// Copyright 2018, 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
17package gitlab
18
19import (
20 "fmt"
21 "time"
22)
23
24// DiscussionsService handles communication with the discussions related
25// methods of the GitLab API.
26//
27// GitLab API docs: https://docs.gitlab.com/ce/api/discussions.html
28type DiscussionsService struct {
29 client *Client
30}
31
32// Discussion represents a GitLab discussion.
33//
34// GitLab API docs: https://docs.gitlab.com/ce/api/discussions.html
35type Discussion struct {
36 ID string `json:"id"`
37 IndividualNote bool `json:"individual_note"`
38 Notes []*Note `json:"notes"`
39}
40
41func (d Discussion) String() string {
42 return Stringify(d)
43}
44
45// ListIssueDiscussionsOptions represents the available ListIssueDiscussions()
46// options.
47//
48// GitLab API docs:
49// https://docs.gitlab.com/ce/api/discussions.html#list-project-issue-discussion-items
50type ListIssueDiscussionsOptions ListOptions
51
52// ListIssueDiscussions gets a list of all discussions for a single
53// issue.
54//
55// GitLab API docs:
56// https://docs.gitlab.com/ce/api/discussions.html#list-project-issue-discussion-items
57func (s *DiscussionsService) ListIssueDiscussions(pid interface{}, issue int, opt *ListIssueDiscussionsOptions, options ...OptionFunc) ([]*Discussion, *Response, error) {
58 project, err := parseID(pid)
59 if err != nil {
60 return nil, nil, err
61 }
62 u := fmt.Sprintf("projects/%s/issues/%d/discussions", pathEscape(project), issue)
63
64 req, err := s.client.NewRequest("GET", u, opt, options)
65 if err != nil {
66 return nil, nil, err
67 }
68
69 var ds []*Discussion
70 resp, err := s.client.Do(req, &ds)
71 if err != nil {
72 return nil, resp, err
73 }
74
75 return ds, resp, err
76}
77
78// GetIssueDiscussion returns a single discussion for a specific project issue.
79//
80// GitLab API docs:
81// https://docs.gitlab.com/ce/api/discussions.html#get-single-issue-discussion-item
82func (s *DiscussionsService) GetIssueDiscussion(pid interface{}, issue int, discussion string, options ...OptionFunc) (*Discussion, *Response, error) {
83 project, err := parseID(pid)
84 if err != nil {
85 return nil, nil, err
86 }
87 u := fmt.Sprintf("projects/%s/issues/%d/discussions/%s",
88 pathEscape(project),
89 issue,
90 discussion,
91 )
92
93 req, err := s.client.NewRequest("GET", u, nil, options)
94 if err != nil {
95 return nil, nil, err
96 }
97
98 d := new(Discussion)
99 resp, err := s.client.Do(req, d)
100 if err != nil {
101 return nil, resp, err
102 }
103
104 return d, resp, err
105}
106
107// CreateIssueDiscussionOptions represents the available CreateIssueDiscussion()
108// options.
109//
110// GitLab API docs:
111// https://docs.gitlab.com/ce/api/discussions.html#create-new-issue-thread
112type CreateIssueDiscussionOptions struct {
113 Body *string `url:"body,omitempty" json:"body,omitempty"`
114 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
115}
116
117// CreateIssueDiscussion creates a new discussion to a single project issue.
118//
119// GitLab API docs:
120// https://docs.gitlab.com/ce/api/discussions.html#create-new-issue-thread
121func (s *DiscussionsService) CreateIssueDiscussion(pid interface{}, issue int, opt *CreateIssueDiscussionOptions, options ...OptionFunc) (*Discussion, *Response, error) {
122 project, err := parseID(pid)
123 if err != nil {
124 return nil, nil, err
125 }
126 u := fmt.Sprintf("projects/%s/issues/%d/discussions", pathEscape(project), issue)
127
128 req, err := s.client.NewRequest("POST", u, opt, options)
129 if err != nil {
130 return nil, nil, err
131 }
132
133 d := new(Discussion)
134 resp, err := s.client.Do(req, d)
135 if err != nil {
136 return nil, resp, err
137 }
138
139 return d, resp, err
140}
141
142// AddIssueDiscussionNoteOptions represents the available AddIssueDiscussionNote()
143// options.
144//
145// GitLab API docs:
146// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-issue-thread
147type AddIssueDiscussionNoteOptions struct {
148 Body *string `url:"body,omitempty" json:"body,omitempty"`
149 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
150}
151
152// AddIssueDiscussionNote creates a new discussion to a single project issue.
153//
154// GitLab API docs:
155// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-issue-thread
156func (s *DiscussionsService) AddIssueDiscussionNote(pid interface{}, issue int, discussion string, opt *AddIssueDiscussionNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
157 project, err := parseID(pid)
158 if err != nil {
159 return nil, nil, err
160 }
161 u := fmt.Sprintf("projects/%s/issues/%d/discussions/%s/notes",
162 pathEscape(project),
163 issue,
164 discussion,
165 )
166
167 req, err := s.client.NewRequest("POST", u, opt, options)
168 if err != nil {
169 return nil, nil, err
170 }
171
172 n := new(Note)
173 resp, err := s.client.Do(req, n)
174 if err != nil {
175 return nil, resp, err
176 }
177
178 return n, resp, err
179}
180
181// UpdateIssueDiscussionNoteOptions represents the available
182// UpdateIssueDiscussion() options.
183//
184// GitLab API docs:
185// https://docs.gitlab.com/ce/api/discussions.html#modify-existing-issue-thread-note
186type UpdateIssueDiscussionNoteOptions struct {
187 Body *string `url:"body,omitempty" json:"body,omitempty"`
188 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
189}
190
191// UpdateIssueDiscussionNote modifies existing discussion of an issue.
192//
193// GitLab API docs:
194// https://docs.gitlab.com/ce/api/discussions.html#modify-existing-issue-thread-note
195func (s *DiscussionsService) UpdateIssueDiscussionNote(pid interface{}, issue int, discussion string, note int, opt *UpdateIssueDiscussionNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
196 project, err := parseID(pid)
197 if err != nil {
198 return nil, nil, err
199 }
200 u := fmt.Sprintf("projects/%s/issues/%d/discussions/%s/notes/%d",
201 pathEscape(project),
202 issue,
203 discussion,
204 note,
205 )
206
207 req, err := s.client.NewRequest("PUT", u, opt, options)
208 if err != nil {
209 return nil, nil, err
210 }
211
212 n := new(Note)
213 resp, err := s.client.Do(req, n)
214 if err != nil {
215 return nil, resp, err
216 }
217
218 return n, resp, err
219}
220
221// DeleteIssueDiscussionNote deletes an existing discussion of an issue.
222//
223// GitLab API docs:
224// https://docs.gitlab.com/ce/api/discussions.html#delete-an-issue-thread-note
225func (s *DiscussionsService) DeleteIssueDiscussionNote(pid interface{}, issue int, discussion string, note int, options ...OptionFunc) (*Response, error) {
226 project, err := parseID(pid)
227 if err != nil {
228 return nil, err
229 }
230 u := fmt.Sprintf("projects/%s/issues/%d/discussions/%s/notes/%d",
231 pathEscape(project),
232 issue,
233 discussion,
234 note,
235 )
236
237 req, err := s.client.NewRequest("DELETE", u, nil, options)
238 if err != nil {
239 return nil, err
240 }
241
242 return s.client.Do(req, nil)
243}
244
245// ListSnippetDiscussionsOptions represents the available ListSnippetDiscussions()
246// options.
247//
248// GitLab API docs:
249// https://docs.gitlab.com/ce/api/discussions.html#list-project-snippet-discussion-items
250type ListSnippetDiscussionsOptions ListOptions
251
252// ListSnippetDiscussions gets a list of all discussions for a single
253// snippet. Snippet discussions are comments users can post to a snippet.
254//
255// GitLab API docs:
256// https://docs.gitlab.com/ce/api/discussions.html#list-project-snippet-discussion-items
257func (s *DiscussionsService) ListSnippetDiscussions(pid interface{}, snippet int, opt *ListSnippetDiscussionsOptions, options ...OptionFunc) ([]*Discussion, *Response, error) {
258 project, err := parseID(pid)
259 if err != nil {
260 return nil, nil, err
261 }
262 u := fmt.Sprintf("projects/%s/snippets/%d/discussions", pathEscape(project), snippet)
263
264 req, err := s.client.NewRequest("GET", u, opt, options)
265 if err != nil {
266 return nil, nil, err
267 }
268
269 var ds []*Discussion
270 resp, err := s.client.Do(req, &ds)
271 if err != nil {
272 return nil, resp, err
273 }
274
275 return ds, resp, err
276}
277
278// GetSnippetDiscussion returns a single discussion for a given snippet.
279//
280// GitLab API docs:
281// https://docs.gitlab.com/ce/api/discussions.html#get-single-snippet-discussion-item
282func (s *DiscussionsService) GetSnippetDiscussion(pid interface{}, snippet int, discussion string, options ...OptionFunc) (*Discussion, *Response, error) {
283 project, err := parseID(pid)
284 if err != nil {
285 return nil, nil, err
286 }
287 u := fmt.Sprintf("projects/%s/snippets/%d/discussions/%s",
288 pathEscape(project),
289 snippet,
290 discussion,
291 )
292
293 req, err := s.client.NewRequest("GET", u, nil, options)
294 if err != nil {
295 return nil, nil, err
296 }
297
298 d := new(Discussion)
299 resp, err := s.client.Do(req, d)
300 if err != nil {
301 return nil, resp, err
302 }
303
304 return d, resp, err
305}
306
307// CreateSnippetDiscussionOptions represents the available
308// CreateSnippetDiscussion() options.
309//
310// GitLab API docs:
311// https://docs.gitlab.com/ce/api/discussions.html#create-new-snippet-thread
312type CreateSnippetDiscussionOptions struct {
313 Body *string `url:"body,omitempty" json:"body,omitempty"`
314 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
315}
316
317// CreateSnippetDiscussion creates a new discussion for a single snippet.
318// Snippet discussions are comments users can post to a snippet.
319//
320// GitLab API docs:
321// https://docs.gitlab.com/ce/api/discussions.html#create-new-snippet-thread
322func (s *DiscussionsService) CreateSnippetDiscussion(pid interface{}, snippet int, opt *CreateSnippetDiscussionOptions, options ...OptionFunc) (*Discussion, *Response, error) {
323 project, err := parseID(pid)
324 if err != nil {
325 return nil, nil, err
326 }
327 u := fmt.Sprintf("projects/%s/snippets/%d/discussions", pathEscape(project), snippet)
328
329 req, err := s.client.NewRequest("POST", u, opt, options)
330 if err != nil {
331 return nil, nil, err
332 }
333
334 d := new(Discussion)
335 resp, err := s.client.Do(req, d)
336 if err != nil {
337 return nil, resp, err
338 }
339
340 return d, resp, err
341}
342
343// AddSnippetDiscussionNoteOptions represents the available
344// AddSnippetDiscussionNote() options.
345//
346// GitLab API docs:
347// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-snippet-thread
348type AddSnippetDiscussionNoteOptions struct {
349 Body *string `url:"body,omitempty" json:"body,omitempty"`
350 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
351}
352
353// AddSnippetDiscussionNote creates a new discussion to a single project
354// snippet.
355//
356// GitLab API docs:
357// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-snippet-thread
358func (s *DiscussionsService) AddSnippetDiscussionNote(pid interface{}, snippet int, discussion string, opt *AddSnippetDiscussionNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
359 project, err := parseID(pid)
360 if err != nil {
361 return nil, nil, err
362 }
363 u := fmt.Sprintf("projects/%s/snippets/%d/discussions/%s/notes",
364 pathEscape(project),
365 snippet,
366 discussion,
367 )
368
369 req, err := s.client.NewRequest("POST", u, opt, options)
370 if err != nil {
371 return nil, nil, err
372 }
373
374 n := new(Note)
375 resp, err := s.client.Do(req, n)
376 if err != nil {
377 return nil, resp, err
378 }
379
380 return n, resp, err
381}
382
383// UpdateSnippetDiscussionNoteOptions represents the available
384// UpdateSnippetDiscussion() options.
385//
386// GitLab API docs:
387// https://docs.gitlab.com/ce/api/discussions.html#modify-existing-snippet-thread-note
388type UpdateSnippetDiscussionNoteOptions struct {
389 Body *string `url:"body,omitempty" json:"body,omitempty"`
390 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
391}
392
393// UpdateSnippetDiscussionNote modifies existing discussion of a snippet.
394//
395// GitLab API docs:
396// https://docs.gitlab.com/ce/api/discussions.html#modify-existing-snippet-thread-note
397func (s *DiscussionsService) UpdateSnippetDiscussionNote(pid interface{}, snippet int, discussion string, note int, opt *UpdateSnippetDiscussionNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
398 project, err := parseID(pid)
399 if err != nil {
400 return nil, nil, err
401 }
402 u := fmt.Sprintf("projects/%s/snippets/%d/discussions/%s/notes/%d",
403 pathEscape(project),
404 snippet,
405 discussion,
406 note,
407 )
408
409 req, err := s.client.NewRequest("PUT", u, opt, options)
410 if err != nil {
411 return nil, nil, err
412 }
413
414 n := new(Note)
415 resp, err := s.client.Do(req, n)
416 if err != nil {
417 return nil, resp, err
418 }
419
420 return n, resp, err
421}
422
423// DeleteSnippetDiscussionNote deletes an existing discussion of a snippet.
424//
425// GitLab API docs:
426// https://docs.gitlab.com/ce/api/discussions.html#delete-a-snippet-thread-note
427func (s *DiscussionsService) DeleteSnippetDiscussionNote(pid interface{}, snippet int, discussion string, note int, options ...OptionFunc) (*Response, error) {
428 project, err := parseID(pid)
429 if err != nil {
430 return nil, err
431 }
432 u := fmt.Sprintf("projects/%s/snippets/%d/discussions/%s/notes/%d",
433 pathEscape(project),
434 snippet,
435 discussion,
436 note,
437 )
438
439 req, err := s.client.NewRequest("DELETE", u, nil, options)
440 if err != nil {
441 return nil, err
442 }
443
444 return s.client.Do(req, nil)
445}
446
447// ListGroupEpicDiscussionsOptions represents the available
448// ListEpicDiscussions() options.
449//
450// GitLab API docs:
451// https://docs.gitlab.com/ce/api/discussions.html#list-group-epic-discussion-items
452type ListGroupEpicDiscussionsOptions ListOptions
453
454// ListGroupEpicDiscussions gets a list of all discussions for a single
455// epic. Epic discussions are comments users can post to a epic.
456//
457// GitLab API docs:
458// https://docs.gitlab.com/ce/api/discussions.html#list-group-epic-discussion-items
459func (s *DiscussionsService) ListGroupEpicDiscussions(gid interface{}, epic int, opt *ListGroupEpicDiscussionsOptions, options ...OptionFunc) ([]*Discussion, *Response, error) {
460 group, err := parseID(gid)
461 if err != nil {
462 return nil, nil, err
463 }
464 u := fmt.Sprintf("groups/%s/epics/%d/discussions",
465 pathEscape(group),
466 epic,
467 )
468
469 req, err := s.client.NewRequest("GET", u, opt, options)
470 if err != nil {
471 return nil, nil, err
472 }
473
474 var ds []*Discussion
475 resp, err := s.client.Do(req, &ds)
476 if err != nil {
477 return nil, resp, err
478 }
479
480 return ds, resp, err
481}
482
483// GetEpicDiscussion returns a single discussion for a given epic.
484//
485// GitLab API docs:
486// https://docs.gitlab.com/ce/api/discussions.html#get-single-epic-discussion-item
487func (s *DiscussionsService) GetEpicDiscussion(gid interface{}, epic int, discussion string, options ...OptionFunc) (*Discussion, *Response, error) {
488 group, err := parseID(gid)
489 if err != nil {
490 return nil, nil, err
491 }
492 u := fmt.Sprintf("groups/%s/epics/%d/discussions/%s",
493 pathEscape(group),
494 epic,
495 discussion,
496 )
497
498 req, err := s.client.NewRequest("GET", u, nil, options)
499 if err != nil {
500 return nil, nil, err
501 }
502
503 d := new(Discussion)
504 resp, err := s.client.Do(req, d)
505 if err != nil {
506 return nil, resp, err
507 }
508
509 return d, resp, err
510}
511
512// CreateEpicDiscussionOptions represents the available CreateEpicDiscussion()
513// options.
514//
515// GitLab API docs:
516// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-epic-thread
517type CreateEpicDiscussionOptions struct {
518 Body *string `url:"body,omitempty" json:"body,omitempty"`
519 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
520}
521
522// CreateEpicDiscussion creates a new discussion for a single epic. Epic
523// discussions are comments users can post to a epic.
524//
525// GitLab API docs:
526// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-epic-thread
527func (s *DiscussionsService) CreateEpicDiscussion(gid interface{}, epic int, opt *CreateEpicDiscussionOptions, options ...OptionFunc) (*Discussion, *Response, error) {
528 group, err := parseID(gid)
529 if err != nil {
530 return nil, nil, err
531 }
532 u := fmt.Sprintf("groups/%s/epics/%d/discussions",
533 pathEscape(group),
534 epic,
535 )
536
537 req, err := s.client.NewRequest("POST", u, opt, options)
538 if err != nil {
539 return nil, nil, err
540 }
541
542 d := new(Discussion)
543 resp, err := s.client.Do(req, d)
544 if err != nil {
545 return nil, resp, err
546 }
547
548 return d, resp, err
549}
550
551// AddEpicDiscussionNoteOptions represents the available
552// AddEpicDiscussionNote() options.
553//
554// GitLab API docs:
555// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-epic-thread
556type AddEpicDiscussionNoteOptions struct {
557 Body *string `url:"body,omitempty" json:"body,omitempty"`
558 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
559}
560
561// AddEpicDiscussionNote creates a new discussion to a single project epic.
562//
563// GitLab API docs:
564// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-epic-thread
565func (s *DiscussionsService) AddEpicDiscussionNote(gid interface{}, epic int, discussion string, opt *AddEpicDiscussionNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
566 group, err := parseID(gid)
567 if err != nil {
568 return nil, nil, err
569 }
570 u := fmt.Sprintf("groups/%s/epics/%d/discussions/%s/notes",
571 pathEscape(group),
572 epic,
573 discussion,
574 )
575
576 req, err := s.client.NewRequest("POST", u, opt, options)
577 if err != nil {
578 return nil, nil, err
579 }
580
581 n := new(Note)
582 resp, err := s.client.Do(req, n)
583 if err != nil {
584 return nil, resp, err
585 }
586
587 return n, resp, err
588}
589
590// UpdateEpicDiscussionNoteOptions represents the available UpdateEpicDiscussion()
591// options.
592//
593// GitLab API docs:
594// https://docs.gitlab.com/ce/api/discussions.html#modify-existing-epic-thread-note
595type UpdateEpicDiscussionNoteOptions struct {
596 Body *string `url:"body,omitempty" json:"body,omitempty"`
597 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
598}
599
600// UpdateEpicDiscussionNote modifies existing discussion of a epic.
601//
602// GitLab API docs:
603// https://docs.gitlab.com/ce/api/discussions.html#modify-existing-epic-thread-note
604func (s *DiscussionsService) UpdateEpicDiscussionNote(gid interface{}, epic int, discussion string, note int, opt *UpdateEpicDiscussionNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
605 group, err := parseID(gid)
606 if err != nil {
607 return nil, nil, err
608 }
609 u := fmt.Sprintf("groups/%s/epics/%d/discussions/%s/notes/%d",
610 pathEscape(group),
611 epic,
612 discussion,
613 note,
614 )
615
616 req, err := s.client.NewRequest("PUT", u, opt, options)
617 if err != nil {
618 return nil, nil, err
619 }
620
621 n := new(Note)
622 resp, err := s.client.Do(req, n)
623 if err != nil {
624 return nil, resp, err
625 }
626
627 return n, resp, err
628}
629
630// DeleteEpicDiscussionNote deletes an existing discussion of a epic.
631//
632// GitLab API docs:
633// https://docs.gitlab.com/ce/api/discussions.html#delete-an-epic-thread-note
634func (s *DiscussionsService) DeleteEpicDiscussionNote(gid interface{}, epic int, discussion string, note int, options ...OptionFunc) (*Response, error) {
635 group, err := parseID(gid)
636 if err != nil {
637 return nil, err
638 }
639 u := fmt.Sprintf("groups/%s/epics/%d/discussions/%s/notes/%d",
640 pathEscape(group),
641 epic,
642 discussion,
643 note,
644 )
645
646 req, err := s.client.NewRequest("DELETE", u, nil, options)
647 if err != nil {
648 return nil, err
649 }
650
651 return s.client.Do(req, nil)
652}
653
654// ListMergeRequestDiscussionsOptions represents the available
655// ListMergeRequestDiscussions() options.
656//
657// GitLab API docs:
658// https://docs.gitlab.com/ce/api/discussions.html#list-project-merge-request-discussion-items
659type ListMergeRequestDiscussionsOptions ListOptions
660
661// ListMergeRequestDiscussions gets a list of all discussions for a single
662// merge request.
663//
664// GitLab API docs:
665// https://docs.gitlab.com/ce/api/discussions.html#list-project-merge-request-discussion-items
666func (s *DiscussionsService) ListMergeRequestDiscussions(pid interface{}, mergeRequest int, opt *ListMergeRequestDiscussionsOptions, options ...OptionFunc) ([]*Discussion, *Response, error) {
667 project, err := parseID(pid)
668 if err != nil {
669 return nil, nil, err
670 }
671 u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions",
672 pathEscape(project),
673 mergeRequest,
674 )
675
676 req, err := s.client.NewRequest("GET", u, opt, options)
677 if err != nil {
678 return nil, nil, err
679 }
680
681 var ds []*Discussion
682 resp, err := s.client.Do(req, &ds)
683 if err != nil {
684 return nil, resp, err
685 }
686
687 return ds, resp, err
688}
689
690// GetMergeRequestDiscussion returns a single discussion for a given merge
691// request.
692//
693// GitLab API docs:
694// https://docs.gitlab.com/ce/api/discussions.html#get-single-merge-request-discussion-item
695func (s *DiscussionsService) GetMergeRequestDiscussion(pid interface{}, mergeRequest int, discussion string, options ...OptionFunc) (*Discussion, *Response, error) {
696 project, err := parseID(pid)
697 if err != nil {
698 return nil, nil, err
699 }
700 u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions/%s",
701 pathEscape(project),
702 mergeRequest,
703 discussion,
704 )
705
706 req, err := s.client.NewRequest("GET", u, nil, options)
707 if err != nil {
708 return nil, nil, err
709 }
710
711 d := new(Discussion)
712 resp, err := s.client.Do(req, d)
713 if err != nil {
714 return nil, resp, err
715 }
716
717 return d, resp, err
718}
719
720// CreateMergeRequestDiscussionOptions represents the available
721// CreateMergeRequestDiscussion() options.
722//
723// GitLab API docs:
724// https://docs.gitlab.com/ce/api/discussions.html#create-new-merge-request-thread
725type CreateMergeRequestDiscussionOptions struct {
726 Body *string `url:"body,omitempty" json:"body,omitempty"`
727 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
728 Position *NotePosition `url:"position,omitempty" json:"position,omitempty"`
729}
730
731// CreateMergeRequestDiscussion creates a new discussion for a single merge
732// request.
733//
734// GitLab API docs:
735// https://docs.gitlab.com/ce/api/discussions.html#create-new-merge-request-thread
736func (s *DiscussionsService) CreateMergeRequestDiscussion(pid interface{}, mergeRequest int, opt *CreateMergeRequestDiscussionOptions, options ...OptionFunc) (*Discussion, *Response, error) {
737 project, err := parseID(pid)
738 if err != nil {
739 return nil, nil, err
740 }
741 u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions",
742 pathEscape(project),
743 mergeRequest,
744 )
745
746 req, err := s.client.NewRequest("POST", u, opt, options)
747 if err != nil {
748 return nil, nil, err
749 }
750
751 d := new(Discussion)
752 resp, err := s.client.Do(req, d)
753 if err != nil {
754 return nil, resp, err
755 }
756
757 return d, resp, err
758}
759
760// ResolveMergeRequestDiscussionOptions represents the available
761// ResolveMergeRequestDiscussion() options.
762//
763// GitLab API docs:
764// https://docs.gitlab.com/ce/api/discussions.html#resolve-a-merge-request-thread
765type ResolveMergeRequestDiscussionOptions struct {
766 Resolved *bool `url:"resolved,omitempty" json:"resolved,omitempty"`
767}
768
769// ResolveMergeRequestDiscussion resolves/unresolves whole discussion of a merge
770// request.
771//
772// GitLab API docs:
773// https://docs.gitlab.com/ce/api/discussions.html#resolve-a-merge-request-thread
774func (s *DiscussionsService) ResolveMergeRequestDiscussion(pid interface{}, mergeRequest int, discussion string, opt *ResolveMergeRequestDiscussionOptions, options ...OptionFunc) (*Discussion, *Response, error) {
775 project, err := parseID(pid)
776 if err != nil {
777 return nil, nil, err
778 }
779 u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions/%s",
780 pathEscape(project),
781 mergeRequest,
782 discussion,
783 )
784
785 req, err := s.client.NewRequest("PUT", u, opt, options)
786 if err != nil {
787 return nil, nil, err
788 }
789
790 d := new(Discussion)
791 resp, err := s.client.Do(req, d)
792 if err != nil {
793 return nil, resp, err
794 }
795
796 return d, resp, err
797}
798
799// AddMergeRequestDiscussionNoteOptions represents the available
800// AddMergeRequestDiscussionNote() options.
801//
802// GitLab API docs:
803// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-merge-request-discussion
804type AddMergeRequestDiscussionNoteOptions struct {
805 Body *string `url:"body,omitempty" json:"body,omitempty"`
806 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
807}
808
809// AddMergeRequestDiscussionNote creates a new discussion to a single project
810// merge request.
811//
812// GitLab API docs:
813// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-merge-request-discussion
814func (s *DiscussionsService) AddMergeRequestDiscussionNote(pid interface{}, mergeRequest int, discussion string, opt *AddMergeRequestDiscussionNoteOptions, options ...OptionFunc) (*Note, *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/discussions/%s/notes",
820 pathEscape(project),
821 mergeRequest,
822 discussion,
823 )
824
825 req, err := s.client.NewRequest("POST", u, opt, options)
826 if err != nil {
827 return nil, nil, err
828 }
829
830 n := new(Note)
831 resp, err := s.client.Do(req, n)
832 if err != nil {
833 return nil, resp, err
834 }
835
836 return n, resp, err
837}
838
839// UpdateMergeRequestDiscussionNoteOptions represents the available
840// UpdateMergeRequestDiscussion() options.
841//
842// GitLab API docs:
843// https://docs.gitlab.com/ce/api/discussions.html#modify-existing-merge-request-discussion-note
844type UpdateMergeRequestDiscussionNoteOptions struct {
845 Body *string `url:"body,omitempty" json:"body,omitempty"`
846 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
847 Resolved *bool `url:"resolved,omitempty" json:"resolved,omitempty"`
848}
849
850// UpdateMergeRequestDiscussionNote modifies existing discussion of a merge
851// request.
852//
853// GitLab API docs:
854// https://docs.gitlab.com/ce/api/discussions.html#modify-existing-merge-request-discussion-note
855func (s *DiscussionsService) UpdateMergeRequestDiscussionNote(pid interface{}, mergeRequest int, discussion string, note int, opt *UpdateMergeRequestDiscussionNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
856 project, err := parseID(pid)
857 if err != nil {
858 return nil, nil, err
859 }
860 u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions/%s/notes/%d",
861 pathEscape(project),
862 mergeRequest,
863 discussion,
864 note,
865 )
866
867 req, err := s.client.NewRequest("PUT", u, opt, options)
868 if err != nil {
869 return nil, nil, err
870 }
871
872 n := new(Note)
873 resp, err := s.client.Do(req, n)
874 if err != nil {
875 return nil, resp, err
876 }
877
878 return n, resp, err
879}
880
881// DeleteMergeRequestDiscussionNote deletes an existing discussion of a merge
882// request.
883//
884// GitLab API docs:
885// https://docs.gitlab.com/ce/api/discussions.html#delete-a-merge-request-discussion-note
886func (s *DiscussionsService) DeleteMergeRequestDiscussionNote(pid interface{}, mergeRequest int, discussion string, note int, options ...OptionFunc) (*Response, error) {
887 project, err := parseID(pid)
888 if err != nil {
889 return nil, err
890 }
891 u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions/%s/notes/%d",
892 pathEscape(project),
893 mergeRequest,
894 discussion,
895 note,
896 )
897
898 req, err := s.client.NewRequest("DELETE", u, nil, options)
899 if err != nil {
900 return nil, err
901 }
902
903 return s.client.Do(req, nil)
904}
905
906// ListCommitDiscussionsOptions represents the available
907// ListCommitDiscussions() options.
908//
909// GitLab API docs:
910// https://docs.gitlab.com/ce/api/discussions.html#list-project-commit-discussion-items
911type ListCommitDiscussionsOptions ListOptions
912
913// ListCommitDiscussions gets a list of all discussions for a single
914// commit.
915//
916// GitLab API docs:
917// https://docs.gitlab.com/ce/api/discussions.html#list-project-commit-discussion-items
918func (s *DiscussionsService) ListCommitDiscussions(pid interface{}, commit string, opt *ListCommitDiscussionsOptions, options ...OptionFunc) ([]*Discussion, *Response, error) {
919 project, err := parseID(pid)
920 if err != nil {
921 return nil, nil, err
922 }
923 u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions",
924 pathEscape(project),
925 commit,
926 )
927
928 req, err := s.client.NewRequest("GET", u, opt, options)
929 if err != nil {
930 return nil, nil, err
931 }
932
933 var ds []*Discussion
934 resp, err := s.client.Do(req, &ds)
935 if err != nil {
936 return nil, resp, err
937 }
938
939 return ds, resp, err
940}
941
942// GetCommitDiscussion returns a single discussion for a specific project
943// commit.
944//
945// GitLab API docs:
946// https://docs.gitlab.com/ce/api/discussions.html#get-single-commit-discussion-item
947func (s *DiscussionsService) GetCommitDiscussion(pid interface{}, commit string, discussion string, options ...OptionFunc) (*Discussion, *Response, error) {
948 project, err := parseID(pid)
949 if err != nil {
950 return nil, nil, err
951 }
952 u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions/%s",
953 pathEscape(project),
954 commit,
955 discussion,
956 )
957
958 req, err := s.client.NewRequest("GET", u, nil, options)
959 if err != nil {
960 return nil, nil, err
961 }
962
963 d := new(Discussion)
964 resp, err := s.client.Do(req, d)
965 if err != nil {
966 return nil, resp, err
967 }
968
969 return d, resp, err
970}
971
972// CreateCommitDiscussionOptions represents the available
973// CreateCommitDiscussion() options.
974//
975// GitLab API docs:
976// https://docs.gitlab.com/ce/api/discussions.html#create-new-commit-thread
977type CreateCommitDiscussionOptions struct {
978 Body *string `url:"body,omitempty" json:"body,omitempty"`
979 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
980 Position *NotePosition `url:"position,omitempty" json:"position,omitempty"`
981}
982
983// CreateCommitDiscussion creates a new discussion to a single project commit.
984//
985// GitLab API docs:
986// https://docs.gitlab.com/ce/api/discussions.html#create-new-commit-thread
987func (s *DiscussionsService) CreateCommitDiscussion(pid interface{}, commit string, opt *CreateCommitDiscussionOptions, options ...OptionFunc) (*Discussion, *Response, error) {
988 project, err := parseID(pid)
989 if err != nil {
990 return nil, nil, err
991 }
992 u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions",
993 pathEscape(project),
994 commit,
995 )
996
997 req, err := s.client.NewRequest("POST", u, opt, options)
998 if err != nil {
999 return nil, nil, err
1000 }
1001
1002 d := new(Discussion)
1003 resp, err := s.client.Do(req, d)
1004 if err != nil {
1005 return nil, resp, err
1006 }
1007
1008 return d, resp, err
1009}
1010
1011// AddCommitDiscussionNoteOptions represents the available
1012// AddCommitDiscussionNote() options.
1013//
1014// GitLab API docs:
1015// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-commit-thread
1016type AddCommitDiscussionNoteOptions struct {
1017 Body *string `url:"body,omitempty" json:"body,omitempty"`
1018 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
1019}
1020
1021// AddCommitDiscussionNote creates a new discussion to a single project commit.
1022//
1023// GitLab API docs:
1024// https://docs.gitlab.com/ce/api/discussions.html#add-note-to-existing-commit-thread
1025func (s *DiscussionsService) AddCommitDiscussionNote(pid interface{}, commit string, discussion string, opt *AddCommitDiscussionNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
1026 project, err := parseID(pid)
1027 if err != nil {
1028 return nil, nil, err
1029 }
1030 u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions/%s/notes",
1031 pathEscape(project),
1032 commit,
1033 discussion,
1034 )
1035
1036 req, err := s.client.NewRequest("POST", u, opt, options)
1037 if err != nil {
1038 return nil, nil, err
1039 }
1040
1041 n := new(Note)
1042 resp, err := s.client.Do(req, n)
1043 if err != nil {
1044 return nil, resp, err
1045 }
1046
1047 return n, resp, err
1048}
1049
1050// UpdateCommitDiscussionNoteOptions represents the available
1051// UpdateCommitDiscussion() options.
1052//
1053// GitLab API docs:
1054// https://docs.gitlab.com/ce/api/discussions.html#modify-an-existing-commit-thread-note
1055type UpdateCommitDiscussionNoteOptions struct {
1056 Body *string `url:"body,omitempty" json:"body,omitempty"`
1057 CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
1058}
1059
1060// UpdateCommitDiscussionNote modifies existing discussion of an commit.
1061//
1062// GitLab API docs:
1063// https://docs.gitlab.com/ce/api/discussions.html#modify-an-existing-commit-thread-note
1064func (s *DiscussionsService) UpdateCommitDiscussionNote(pid interface{}, commit string, discussion string, note int, opt *UpdateCommitDiscussionNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
1065 project, err := parseID(pid)
1066 if err != nil {
1067 return nil, nil, err
1068 }
1069 u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions/%s/notes/%d",
1070 pathEscape(project),
1071 commit,
1072 discussion,
1073 note,
1074 )
1075
1076 req, err := s.client.NewRequest("PUT", u, opt, options)
1077 if err != nil {
1078 return nil, nil, err
1079 }
1080
1081 n := new(Note)
1082 resp, err := s.client.Do(req, n)
1083 if err != nil {
1084 return nil, resp, err
1085 }
1086
1087 return n, resp, err
1088}
1089
1090// DeleteCommitDiscussionNote deletes an existing discussion of an commit.
1091//
1092// GitLab API docs:
1093// https://docs.gitlab.com/ce/api/discussions.html#delete-a-commit-thread-note
1094func (s *DiscussionsService) DeleteCommitDiscussionNote(pid interface{}, commit string, discussion string, note int, options ...OptionFunc) (*Response, error) {
1095 project, err := parseID(pid)
1096 if err != nil {
1097 return nil, err
1098 }
1099 u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions/%s/notes/%d",
1100 pathEscape(project),
1101 commit,
1102 discussion,
1103 note,
1104 )
1105
1106 req, err := s.client.NewRequest("DELETE", u, nil, options)
1107 if err != nil {
1108 return nil, err
1109 }
1110
1111 return s.client.Do(req, nil)
1112}