notes.go

  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
 17package gitlab
 18
 19import (
 20	"fmt"
 21	"time"
 22)
 23
 24// NotesService handles communication with the notes related methods
 25// of the GitLab API.
 26//
 27// GitLab API docs: https://docs.gitlab.com/ce/api/notes.html
 28type NotesService struct {
 29	client *Client
 30}
 31
 32// Note represents a GitLab note.
 33//
 34// GitLab API docs: https://docs.gitlab.com/ce/api/notes.html
 35type Note struct {
 36	ID         int    `json:"id"`
 37	Body       string `json:"body"`
 38	Attachment string `json:"attachment"`
 39	Title      string `json:"title"`
 40	FileName   string `json:"file_name"`
 41	Author     struct {
 42		ID        int    `json:"id"`
 43		Username  string `json:"username"`
 44		Email     string `json:"email"`
 45		Name      string `json:"name"`
 46		State     string `json:"state"`
 47		AvatarURL string `json:"avatar_url"`
 48		WebURL    string `json:"web_url"`
 49	} `json:"author"`
 50	System       bool          `json:"system"`
 51	ExpiresAt    *time.Time    `json:"expires_at"`
 52	UpdatedAt    *time.Time    `json:"updated_at"`
 53	CreatedAt    *time.Time    `json:"created_at"`
 54	NoteableID   int           `json:"noteable_id"`
 55	NoteableType string        `json:"noteable_type"`
 56	Position     *NotePosition `json:"position"`
 57	Resolvable   bool          `json:"resolvable"`
 58	Resolved     bool          `json:"resolved"`
 59	ResolvedBy   struct {
 60		ID        int    `json:"id"`
 61		Username  string `json:"username"`
 62		Email     string `json:"email"`
 63		Name      string `json:"name"`
 64		State     string `json:"state"`
 65		AvatarURL string `json:"avatar_url"`
 66		WebURL    string `json:"web_url"`
 67	} `json:"resolved_by"`
 68	NoteableIID int `json:"noteable_iid"`
 69}
 70
 71// NotePosition represents the position attributes of a note.
 72type NotePosition struct {
 73	BaseSHA      string `json:"base_sha"`
 74	StartSHA     string `json:"start_sha"`
 75	HeadSHA      string `json:"head_sha"`
 76	PositionType string `json:"position_type"`
 77	NewPath      string `json:"new_path,omitempty"`
 78	NewLine      int    `json:"new_line,omitempty"`
 79	OldPath      string `json:"old_path,omitempty"`
 80	OldLine      int    `json:"old_line,omitempty"`
 81	Width        int    `json:"width,omitempty"`
 82	Height       int    `json:"height,omitempty"`
 83	X            int    `json:"x,omitempty"`
 84	Y            int    `json:"y,omitempty"`
 85}
 86
 87func (n Note) String() string {
 88	return Stringify(n)
 89}
 90
 91// ListIssueNotesOptions represents the available ListIssueNotes() options.
 92//
 93// GitLab API docs:
 94// https://docs.gitlab.com/ce/api/notes.html#list-project-issue-notes
 95type ListIssueNotesOptions struct {
 96	ListOptions
 97	OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
 98	Sort    *string `url:"sort,omitempty" json:"sort,omitempty"`
 99}
100
101// ListIssueNotes gets a list of all notes for a single issue.
102//
103// GitLab API docs:
104// https://docs.gitlab.com/ce/api/notes.html#list-project-issue-notes
105func (s *NotesService) ListIssueNotes(pid interface{}, issue int, opt *ListIssueNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) {
106	project, err := parseID(pid)
107	if err != nil {
108		return nil, nil, err
109	}
110	u := fmt.Sprintf("projects/%s/issues/%d/notes", pathEscape(project), issue)
111
112	req, err := s.client.NewRequest("GET", u, opt, options)
113	if err != nil {
114		return nil, nil, err
115	}
116
117	var n []*Note
118	resp, err := s.client.Do(req, &n)
119	if err != nil {
120		return nil, resp, err
121	}
122
123	return n, resp, err
124}
125
126// GetIssueNote returns a single note for a specific project issue.
127//
128// GitLab API docs:
129// https://docs.gitlab.com/ce/api/notes.html#get-single-issue-note
130func (s *NotesService) GetIssueNote(pid interface{}, issue, note int, options ...OptionFunc) (*Note, *Response, error) {
131	project, err := parseID(pid)
132	if err != nil {
133		return nil, nil, err
134	}
135	u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", pathEscape(project), issue, note)
136
137	req, err := s.client.NewRequest("GET", u, nil, options)
138	if err != nil {
139		return nil, nil, err
140	}
141
142	n := new(Note)
143	resp, err := s.client.Do(req, n)
144	if err != nil {
145		return nil, resp, err
146	}
147
148	return n, resp, err
149}
150
151// CreateIssueNoteOptions represents the available CreateIssueNote()
152// options.
153//
154// GitLab API docs:
155// https://docs.gitlab.com/ce/api/notes.html#create-new-issue-note
156type CreateIssueNoteOptions struct {
157	Body      *string    `url:"body,omitempty" json:"body,omitempty"`
158	CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
159}
160
161// CreateIssueNote creates a new note to a single project issue.
162//
163// GitLab API docs:
164// https://docs.gitlab.com/ce/api/notes.html#create-new-issue-note
165func (s *NotesService) CreateIssueNote(pid interface{}, issue int, opt *CreateIssueNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
166	project, err := parseID(pid)
167	if err != nil {
168		return nil, nil, err
169	}
170	u := fmt.Sprintf("projects/%s/issues/%d/notes", pathEscape(project), issue)
171
172	req, err := s.client.NewRequest("POST", u, opt, options)
173	if err != nil {
174		return nil, nil, err
175	}
176
177	n := new(Note)
178	resp, err := s.client.Do(req, n)
179	if err != nil {
180		return nil, resp, err
181	}
182
183	return n, resp, err
184}
185
186// UpdateIssueNoteOptions represents the available UpdateIssueNote()
187// options.
188//
189// GitLab API docs:
190// https://docs.gitlab.com/ce/api/notes.html#modify-existing-issue-note
191type UpdateIssueNoteOptions struct {
192	Body *string `url:"body,omitempty" json:"body,omitempty"`
193}
194
195// UpdateIssueNote modifies existing note of an issue.
196//
197// GitLab API docs:
198// https://docs.gitlab.com/ce/api/notes.html#modify-existing-issue-note
199func (s *NotesService) UpdateIssueNote(pid interface{}, issue, note int, opt *UpdateIssueNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
200	project, err := parseID(pid)
201	if err != nil {
202		return nil, nil, err
203	}
204	u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", pathEscape(project), issue, note)
205
206	req, err := s.client.NewRequest("PUT", u, opt, options)
207	if err != nil {
208		return nil, nil, err
209	}
210
211	n := new(Note)
212	resp, err := s.client.Do(req, n)
213	if err != nil {
214		return nil, resp, err
215	}
216
217	return n, resp, err
218}
219
220// DeleteIssueNote deletes an existing note of an issue.
221//
222// GitLab API docs:
223// https://docs.gitlab.com/ce/api/notes.html#delete-an-issue-note
224func (s *NotesService) DeleteIssueNote(pid interface{}, issue, note int, options ...OptionFunc) (*Response, error) {
225	project, err := parseID(pid)
226	if err != nil {
227		return nil, err
228	}
229	u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", pathEscape(project), issue, note)
230
231	req, err := s.client.NewRequest("DELETE", u, nil, options)
232	if err != nil {
233		return nil, err
234	}
235
236	return s.client.Do(req, nil)
237}
238
239// ListSnippetNotesOptions represents the available ListSnippetNotes() options.
240//
241// GitLab API docs:
242// https://docs.gitlab.com/ce/api/notes.html#list-all-snippet-notes
243type ListSnippetNotesOptions struct {
244	ListOptions
245	OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
246	Sort    *string `url:"sort,omitempty" json:"sort,omitempty"`
247}
248
249// ListSnippetNotes gets a list of all notes for a single snippet. Snippet
250// notes are comments users can post to a snippet.
251//
252// GitLab API docs:
253// https://docs.gitlab.com/ce/api/notes.html#list-all-snippet-notes
254func (s *NotesService) ListSnippetNotes(pid interface{}, snippet int, opt *ListSnippetNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) {
255	project, err := parseID(pid)
256	if err != nil {
257		return nil, nil, err
258	}
259	u := fmt.Sprintf("projects/%s/snippets/%d/notes", pathEscape(project), snippet)
260
261	req, err := s.client.NewRequest("GET", u, opt, options)
262	if err != nil {
263		return nil, nil, err
264	}
265
266	var n []*Note
267	resp, err := s.client.Do(req, &n)
268	if err != nil {
269		return nil, resp, err
270	}
271
272	return n, resp, err
273}
274
275// GetSnippetNote returns a single note for a given snippet.
276//
277// GitLab API docs:
278// https://docs.gitlab.com/ce/api/notes.html#get-single-snippet-note
279func (s *NotesService) GetSnippetNote(pid interface{}, snippet, note int, options ...OptionFunc) (*Note, *Response, error) {
280	project, err := parseID(pid)
281	if err != nil {
282		return nil, nil, err
283	}
284	u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", pathEscape(project), snippet, note)
285
286	req, err := s.client.NewRequest("GET", u, nil, options)
287	if err != nil {
288		return nil, nil, err
289	}
290
291	n := new(Note)
292	resp, err := s.client.Do(req, n)
293	if err != nil {
294		return nil, resp, err
295	}
296
297	return n, resp, err
298}
299
300// CreateSnippetNoteOptions represents the available CreateSnippetNote()
301// options.
302//
303// GitLab API docs:
304// https://docs.gitlab.com/ce/api/notes.html#create-new-snippet-note
305type CreateSnippetNoteOptions struct {
306	Body *string `url:"body,omitempty" json:"body,omitempty"`
307}
308
309// CreateSnippetNote creates a new note for a single snippet. Snippet notes are
310// comments users can post to a snippet.
311//
312// GitLab API docs:
313// https://docs.gitlab.com/ce/api/notes.html#create-new-snippet-note
314func (s *NotesService) CreateSnippetNote(pid interface{}, snippet int, opt *CreateSnippetNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
315	project, err := parseID(pid)
316	if err != nil {
317		return nil, nil, err
318	}
319	u := fmt.Sprintf("projects/%s/snippets/%d/notes", pathEscape(project), snippet)
320
321	req, err := s.client.NewRequest("POST", u, opt, options)
322	if err != nil {
323		return nil, nil, err
324	}
325
326	n := new(Note)
327	resp, err := s.client.Do(req, n)
328	if err != nil {
329		return nil, resp, err
330	}
331
332	return n, resp, err
333}
334
335// UpdateSnippetNoteOptions represents the available UpdateSnippetNote()
336// options.
337//
338// GitLab API docs:
339// https://docs.gitlab.com/ce/api/notes.html#modify-existing-snippet-note
340type UpdateSnippetNoteOptions struct {
341	Body *string `url:"body,omitempty" json:"body,omitempty"`
342}
343
344// UpdateSnippetNote modifies existing note of a snippet.
345//
346// GitLab API docs:
347// https://docs.gitlab.com/ce/api/notes.html#modify-existing-snippet-note
348func (s *NotesService) UpdateSnippetNote(pid interface{}, snippet, note int, opt *UpdateSnippetNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
349	project, err := parseID(pid)
350	if err != nil {
351		return nil, nil, err
352	}
353	u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", pathEscape(project), snippet, note)
354
355	req, err := s.client.NewRequest("PUT", u, opt, options)
356	if err != nil {
357		return nil, nil, err
358	}
359
360	n := new(Note)
361	resp, err := s.client.Do(req, n)
362	if err != nil {
363		return nil, resp, err
364	}
365
366	return n, resp, err
367}
368
369// DeleteSnippetNote deletes an existing note of a snippet.
370//
371// GitLab API docs:
372// https://docs.gitlab.com/ce/api/notes.html#delete-a-snippet-note
373func (s *NotesService) DeleteSnippetNote(pid interface{}, snippet, note int, options ...OptionFunc) (*Response, error) {
374	project, err := parseID(pid)
375	if err != nil {
376		return nil, err
377	}
378	u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", pathEscape(project), snippet, note)
379
380	req, err := s.client.NewRequest("DELETE", u, nil, options)
381	if err != nil {
382		return nil, err
383	}
384
385	return s.client.Do(req, nil)
386}
387
388// ListMergeRequestNotesOptions represents the available ListMergeRequestNotes()
389// options.
390//
391// GitLab API docs:
392// https://docs.gitlab.com/ce/api/notes.html#list-all-merge-request-notes
393type ListMergeRequestNotesOptions struct {
394	ListOptions
395	OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
396	Sort    *string `url:"sort,omitempty" json:"sort,omitempty"`
397}
398
399// ListMergeRequestNotes gets a list of all notes for a single merge request.
400//
401// GitLab API docs:
402// https://docs.gitlab.com/ce/api/notes.html#list-all-merge-request-notes
403func (s *NotesService) ListMergeRequestNotes(pid interface{}, mergeRequest int, opt *ListMergeRequestNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) {
404	project, err := parseID(pid)
405	if err != nil {
406		return nil, nil, err
407	}
408	u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", pathEscape(project), mergeRequest)
409
410	req, err := s.client.NewRequest("GET", u, opt, options)
411	if err != nil {
412		return nil, nil, err
413	}
414
415	var n []*Note
416	resp, err := s.client.Do(req, &n)
417	if err != nil {
418		return nil, resp, err
419	}
420
421	return n, resp, err
422}
423
424// GetMergeRequestNote returns a single note for a given merge request.
425//
426// GitLab API docs:
427// https://docs.gitlab.com/ce/api/notes.html#get-single-merge-request-note
428func (s *NotesService) GetMergeRequestNote(pid interface{}, mergeRequest, note int, options ...OptionFunc) (*Note, *Response, error) {
429	project, err := parseID(pid)
430	if err != nil {
431		return nil, nil, err
432	}
433	u := fmt.Sprintf("projects/%s/merge_requests/%d/notes/%d", pathEscape(project), mergeRequest, note)
434
435	req, err := s.client.NewRequest("GET", u, nil, options)
436	if err != nil {
437		return nil, nil, err
438	}
439
440	n := new(Note)
441	resp, err := s.client.Do(req, n)
442	if err != nil {
443		return nil, resp, err
444	}
445
446	return n, resp, err
447}
448
449// CreateMergeRequestNoteOptions represents the available
450// CreateMergeRequestNote() options.
451//
452// GitLab API docs:
453// https://docs.gitlab.com/ce/api/notes.html#create-new-merge-request-note
454type CreateMergeRequestNoteOptions struct {
455	Body *string `url:"body,omitempty" json:"body,omitempty"`
456}
457
458// CreateMergeRequestNote creates a new note for a single merge request.
459//
460// GitLab API docs:
461// https://docs.gitlab.com/ce/api/notes.html#create-new-merge-request-note
462func (s *NotesService) CreateMergeRequestNote(pid interface{}, mergeRequest int, opt *CreateMergeRequestNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
463	project, err := parseID(pid)
464	if err != nil {
465		return nil, nil, err
466	}
467	u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", pathEscape(project), mergeRequest)
468
469	req, err := s.client.NewRequest("POST", u, opt, options)
470	if err != nil {
471		return nil, nil, err
472	}
473
474	n := new(Note)
475	resp, err := s.client.Do(req, n)
476	if err != nil {
477		return nil, resp, err
478	}
479
480	return n, resp, err
481}
482
483// UpdateMergeRequestNoteOptions represents the available
484// UpdateMergeRequestNote() options.
485//
486// GitLab API docs:
487// https://docs.gitlab.com/ce/api/notes.html#modify-existing-merge-request-note
488type UpdateMergeRequestNoteOptions struct {
489	Body *string `url:"body,omitempty" json:"body,omitempty"`
490}
491
492// UpdateMergeRequestNote modifies existing note of a merge request.
493//
494// GitLab API docs:
495// https://docs.gitlab.com/ce/api/notes.html#modify-existing-merge-request-note
496func (s *NotesService) UpdateMergeRequestNote(pid interface{}, mergeRequest, note int, opt *UpdateMergeRequestNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
497	project, err := parseID(pid)
498	if err != nil {
499		return nil, nil, err
500	}
501	u := fmt.Sprintf(
502		"projects/%s/merge_requests/%d/notes/%d", pathEscape(project), mergeRequest, note)
503	req, err := s.client.NewRequest("PUT", u, opt, options)
504	if err != nil {
505		return nil, nil, err
506	}
507
508	n := new(Note)
509	resp, err := s.client.Do(req, n)
510	if err != nil {
511		return nil, resp, err
512	}
513
514	return n, resp, err
515}
516
517// DeleteMergeRequestNote deletes an existing note of a merge request.
518//
519// GitLab API docs:
520// https://docs.gitlab.com/ce/api/notes.html#delete-a-merge-request-note
521func (s *NotesService) DeleteMergeRequestNote(pid interface{}, mergeRequest, note int, options ...OptionFunc) (*Response, error) {
522	project, err := parseID(pid)
523	if err != nil {
524		return nil, err
525	}
526	u := fmt.Sprintf(
527		"projects/%s/merge_requests/%d/notes/%d", pathEscape(project), mergeRequest, note)
528
529	req, err := s.client.NewRequest("DELETE", u, nil, options)
530	if err != nil {
531		return nil, err
532	}
533
534	return s.client.Do(req, nil)
535}
536
537// ListEpicNotesOptions represents the available ListEpicNotes() options.
538//
539// GitLab API docs:
540// https://docs.gitlab.com/ee/api/notes.html#list-all-epic-notes
541type ListEpicNotesOptions struct {
542	ListOptions
543	OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
544	Sort    *string `url:"sort,omitempty" json:"sort,omitempty"`
545}
546
547// ListEpicNotes gets a list of all notes for a single epic.
548//
549// GitLab API docs:
550// https://docs.gitlab.com/ee/api/notes.html#list-all-epic-notes
551func (s *NotesService) ListEpicNotes(gid interface{}, epic int, opt *ListEpicNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) {
552	group, err := parseID(gid)
553	if err != nil {
554		return nil, nil, err
555	}
556	u := fmt.Sprintf("groups/%s/epics/%d/notes", pathEscape(group), epic)
557
558	req, err := s.client.NewRequest("GET", u, opt, options)
559	if err != nil {
560		return nil, nil, err
561	}
562
563	var n []*Note
564	resp, err := s.client.Do(req, &n)
565	if err != nil {
566		return nil, resp, err
567	}
568
569	return n, resp, err
570}
571
572// GetEpicNote returns a single note for an epic.
573//
574// GitLab API docs:
575// https://docs.gitlab.com/ee/api/notes.html#get-single-epic-note
576func (s *NotesService) GetEpicNote(gid interface{}, epic, note int, options ...OptionFunc) (*Note, *Response, error) {
577	group, err := parseID(gid)
578	if err != nil {
579		return nil, nil, err
580	}
581	u := fmt.Sprintf("groups/%s/epics/%d/notes/%d", pathEscape(group), epic, note)
582
583	req, err := s.client.NewRequest("GET", u, nil, options)
584	if err != nil {
585		return nil, nil, err
586	}
587
588	n := new(Note)
589	resp, err := s.client.Do(req, n)
590	if err != nil {
591		return nil, resp, err
592	}
593
594	return n, resp, err
595}
596
597// CreateEpicNoteOptions represents the available CreateEpicNote() options.
598//
599// GitLab API docs:
600// https://docs.gitlab.com/ee/api/notes.html#create-new-epic-note
601type CreateEpicNoteOptions struct {
602	Body *string `url:"body,omitempty" json:"body,omitempty"`
603}
604
605// CreateEpicNote creates a new note for a single merge request.
606//
607// GitLab API docs:
608// https://docs.gitlab.com/ee/api/notes.html#create-new-epic-note
609func (s *NotesService) CreateEpicNote(gid interface{}, epic int, opt *CreateEpicNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
610	group, err := parseID(gid)
611	if err != nil {
612		return nil, nil, err
613	}
614	u := fmt.Sprintf("groups/%s/epics/%d/notes", pathEscape(group), epic)
615
616	req, err := s.client.NewRequest("POST", 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// UpdateEpicNoteOptions represents the available UpdateEpicNote() options.
631//
632// GitLab API docs:
633// https://docs.gitlab.com/ee/api/notes.html#modify-existing-epic-note
634type UpdateEpicNoteOptions struct {
635	Body *string `url:"body,omitempty" json:"body,omitempty"`
636}
637
638// UpdateEpicNote modifies existing note of an epic.
639//
640// https://docs.gitlab.com/ee/api/notes.html#modify-existing-epic-note
641func (s *NotesService) UpdateEpicNote(gid interface{}, epic, note int, opt *UpdateEpicNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
642	group, err := parseID(gid)
643	if err != nil {
644		return nil, nil, err
645	}
646	u := fmt.Sprintf("groups/%s/epics/%d/notes/%d", pathEscape(group), epic, note)
647
648	req, err := s.client.NewRequest("PUT", u, opt, options)
649	if err != nil {
650		return nil, nil, err
651	}
652
653	n := new(Note)
654	resp, err := s.client.Do(req, n)
655	if err != nil {
656		return nil, resp, err
657	}
658
659	return n, resp, err
660}
661
662// DeleteEpicNote deletes an existing note of a merge request.
663//
664// https://docs.gitlab.com/ee/api/notes.html#delete-an-epic-note
665func (s *NotesService) DeleteEpicNote(gid interface{}, epic, note int, options ...OptionFunc) (*Response, error) {
666	group, err := parseID(gid)
667	if err != nil {
668		return nil, err
669	}
670	u := fmt.Sprintf("groups/%s/epics/%d/notes/%d", pathEscape(group), epic, note)
671
672	req, err := s.client.NewRequest("DELETE", u, nil, options)
673	if err != nil {
674		return nil, err
675	}
676
677	return s.client.Do(req, nil)
678}