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}
159
160// CreateIssueNote creates a new note to a single project issue.
161//
162// GitLab API docs:
163// https://docs.gitlab.com/ce/api/notes.html#create-new-issue-note
164func (s *NotesService) CreateIssueNote(pid interface{}, issue int, opt *CreateIssueNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
165	project, err := parseID(pid)
166	if err != nil {
167		return nil, nil, err
168	}
169	u := fmt.Sprintf("projects/%s/issues/%d/notes", pathEscape(project), issue)
170
171	req, err := s.client.NewRequest("POST", u, opt, options)
172	if err != nil {
173		return nil, nil, err
174	}
175
176	n := new(Note)
177	resp, err := s.client.Do(req, n)
178	if err != nil {
179		return nil, resp, err
180	}
181
182	return n, resp, err
183}
184
185// UpdateIssueNoteOptions represents the available UpdateIssueNote()
186// options.
187//
188// GitLab API docs:
189// https://docs.gitlab.com/ce/api/notes.html#modify-existing-issue-note
190type UpdateIssueNoteOptions struct {
191	Body *string `url:"body,omitempty" json:"body,omitempty"`
192}
193
194// UpdateIssueNote modifies existing note of an issue.
195//
196// GitLab API docs:
197// https://docs.gitlab.com/ce/api/notes.html#modify-existing-issue-note
198func (s *NotesService) UpdateIssueNote(pid interface{}, issue, note int, opt *UpdateIssueNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
199	project, err := parseID(pid)
200	if err != nil {
201		return nil, nil, err
202	}
203	u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", pathEscape(project), issue, note)
204
205	req, err := s.client.NewRequest("PUT", u, opt, options)
206	if err != nil {
207		return nil, nil, err
208	}
209
210	n := new(Note)
211	resp, err := s.client.Do(req, n)
212	if err != nil {
213		return nil, resp, err
214	}
215
216	return n, resp, err
217}
218
219// DeleteIssueNote deletes an existing note of an issue.
220//
221// GitLab API docs:
222// https://docs.gitlab.com/ce/api/notes.html#delete-an-issue-note
223func (s *NotesService) DeleteIssueNote(pid interface{}, issue, note int, options ...OptionFunc) (*Response, error) {
224	project, err := parseID(pid)
225	if err != nil {
226		return nil, err
227	}
228	u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", pathEscape(project), issue, note)
229
230	req, err := s.client.NewRequest("DELETE", u, nil, options)
231	if err != nil {
232		return nil, err
233	}
234
235	return s.client.Do(req, nil)
236}
237
238// ListSnippetNotesOptions represents the available ListSnippetNotes() options.
239//
240// GitLab API docs:
241// https://docs.gitlab.com/ce/api/notes.html#list-all-snippet-notes
242type ListSnippetNotesOptions struct {
243	ListOptions
244	OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
245	Sort    *string `url:"sort,omitempty" json:"sort,omitempty"`
246}
247
248// ListSnippetNotes gets a list of all notes for a single snippet. Snippet
249// notes are comments users can post to a snippet.
250//
251// GitLab API docs:
252// https://docs.gitlab.com/ce/api/notes.html#list-all-snippet-notes
253func (s *NotesService) ListSnippetNotes(pid interface{}, snippet int, opt *ListSnippetNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) {
254	project, err := parseID(pid)
255	if err != nil {
256		return nil, nil, err
257	}
258	u := fmt.Sprintf("projects/%s/snippets/%d/notes", pathEscape(project), snippet)
259
260	req, err := s.client.NewRequest("GET", u, opt, options)
261	if err != nil {
262		return nil, nil, err
263	}
264
265	var n []*Note
266	resp, err := s.client.Do(req, &n)
267	if err != nil {
268		return nil, resp, err
269	}
270
271	return n, resp, err
272}
273
274// GetSnippetNote returns a single note for a given snippet.
275//
276// GitLab API docs:
277// https://docs.gitlab.com/ce/api/notes.html#get-single-snippet-note
278func (s *NotesService) GetSnippetNote(pid interface{}, snippet, note int, options ...OptionFunc) (*Note, *Response, error) {
279	project, err := parseID(pid)
280	if err != nil {
281		return nil, nil, err
282	}
283	u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", pathEscape(project), snippet, note)
284
285	req, err := s.client.NewRequest("GET", u, nil, options)
286	if err != nil {
287		return nil, nil, err
288	}
289
290	n := new(Note)
291	resp, err := s.client.Do(req, n)
292	if err != nil {
293		return nil, resp, err
294	}
295
296	return n, resp, err
297}
298
299// CreateSnippetNoteOptions represents the available CreateSnippetNote()
300// options.
301//
302// GitLab API docs:
303// https://docs.gitlab.com/ce/api/notes.html#create-new-snippet-note
304type CreateSnippetNoteOptions struct {
305	Body *string `url:"body,omitempty" json:"body,omitempty"`
306}
307
308// CreateSnippetNote creates a new note for a single snippet. Snippet notes are
309// comments users can post to a snippet.
310//
311// GitLab API docs:
312// https://docs.gitlab.com/ce/api/notes.html#create-new-snippet-note
313func (s *NotesService) CreateSnippetNote(pid interface{}, snippet int, opt *CreateSnippetNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
314	project, err := parseID(pid)
315	if err != nil {
316		return nil, nil, err
317	}
318	u := fmt.Sprintf("projects/%s/snippets/%d/notes", pathEscape(project), snippet)
319
320	req, err := s.client.NewRequest("POST", u, opt, options)
321	if err != nil {
322		return nil, nil, err
323	}
324
325	n := new(Note)
326	resp, err := s.client.Do(req, n)
327	if err != nil {
328		return nil, resp, err
329	}
330
331	return n, resp, err
332}
333
334// UpdateSnippetNoteOptions represents the available UpdateSnippetNote()
335// options.
336//
337// GitLab API docs:
338// https://docs.gitlab.com/ce/api/notes.html#modify-existing-snippet-note
339type UpdateSnippetNoteOptions struct {
340	Body *string `url:"body,omitempty" json:"body,omitempty"`
341}
342
343// UpdateSnippetNote modifies existing note of a snippet.
344//
345// GitLab API docs:
346// https://docs.gitlab.com/ce/api/notes.html#modify-existing-snippet-note
347func (s *NotesService) UpdateSnippetNote(pid interface{}, snippet, note int, opt *UpdateSnippetNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
348	project, err := parseID(pid)
349	if err != nil {
350		return nil, nil, err
351	}
352	u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", pathEscape(project), snippet, note)
353
354	req, err := s.client.NewRequest("PUT", u, opt, options)
355	if err != nil {
356		return nil, nil, err
357	}
358
359	n := new(Note)
360	resp, err := s.client.Do(req, n)
361	if err != nil {
362		return nil, resp, err
363	}
364
365	return n, resp, err
366}
367
368// DeleteSnippetNote deletes an existing note of a snippet.
369//
370// GitLab API docs:
371// https://docs.gitlab.com/ce/api/notes.html#delete-a-snippet-note
372func (s *NotesService) DeleteSnippetNote(pid interface{}, snippet, note int, options ...OptionFunc) (*Response, error) {
373	project, err := parseID(pid)
374	if err != nil {
375		return nil, err
376	}
377	u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", pathEscape(project), snippet, note)
378
379	req, err := s.client.NewRequest("DELETE", u, nil, options)
380	if err != nil {
381		return nil, err
382	}
383
384	return s.client.Do(req, nil)
385}
386
387// ListMergeRequestNotesOptions represents the available ListMergeRequestNotes()
388// options.
389//
390// GitLab API docs:
391// https://docs.gitlab.com/ce/api/notes.html#list-all-merge-request-notes
392type ListMergeRequestNotesOptions struct {
393	ListOptions
394	OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
395	Sort    *string `url:"sort,omitempty" json:"sort,omitempty"`
396}
397
398// ListMergeRequestNotes gets a list of all notes for a single merge request.
399//
400// GitLab API docs:
401// https://docs.gitlab.com/ce/api/notes.html#list-all-merge-request-notes
402func (s *NotesService) ListMergeRequestNotes(pid interface{}, mergeRequest int, opt *ListMergeRequestNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) {
403	project, err := parseID(pid)
404	if err != nil {
405		return nil, nil, err
406	}
407	u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", pathEscape(project), mergeRequest)
408
409	req, err := s.client.NewRequest("GET", u, opt, options)
410	if err != nil {
411		return nil, nil, err
412	}
413
414	var n []*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// GetMergeRequestNote returns a single note for a given merge request.
424//
425// GitLab API docs:
426// https://docs.gitlab.com/ce/api/notes.html#get-single-merge-request-note
427func (s *NotesService) GetMergeRequestNote(pid interface{}, mergeRequest, note int, options ...OptionFunc) (*Note, *Response, error) {
428	project, err := parseID(pid)
429	if err != nil {
430		return nil, nil, err
431	}
432	u := fmt.Sprintf("projects/%s/merge_requests/%d/notes/%d", pathEscape(project), mergeRequest, note)
433
434	req, err := s.client.NewRequest("GET", u, nil, options)
435	if err != nil {
436		return nil, nil, err
437	}
438
439	n := new(Note)
440	resp, err := s.client.Do(req, n)
441	if err != nil {
442		return nil, resp, err
443	}
444
445	return n, resp, err
446}
447
448// CreateMergeRequestNoteOptions represents the available
449// CreateMergeRequestNote() options.
450//
451// GitLab API docs:
452// https://docs.gitlab.com/ce/api/notes.html#create-new-merge-request-note
453type CreateMergeRequestNoteOptions struct {
454	Body *string `url:"body,omitempty" json:"body,omitempty"`
455}
456
457// CreateMergeRequestNote creates a new note for a single merge request.
458//
459// GitLab API docs:
460// https://docs.gitlab.com/ce/api/notes.html#create-new-merge-request-note
461func (s *NotesService) CreateMergeRequestNote(pid interface{}, mergeRequest int, opt *CreateMergeRequestNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
462	project, err := parseID(pid)
463	if err != nil {
464		return nil, nil, err
465	}
466	u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", pathEscape(project), mergeRequest)
467
468	req, err := s.client.NewRequest("POST", u, opt, options)
469	if err != nil {
470		return nil, nil, err
471	}
472
473	n := new(Note)
474	resp, err := s.client.Do(req, n)
475	if err != nil {
476		return nil, resp, err
477	}
478
479	return n, resp, err
480}
481
482// UpdateMergeRequestNoteOptions represents the available
483// UpdateMergeRequestNote() options.
484//
485// GitLab API docs:
486// https://docs.gitlab.com/ce/api/notes.html#modify-existing-merge-request-note
487type UpdateMergeRequestNoteOptions struct {
488	Body *string `url:"body,omitempty" json:"body,omitempty"`
489}
490
491// UpdateMergeRequestNote modifies existing note of a merge request.
492//
493// GitLab API docs:
494// https://docs.gitlab.com/ce/api/notes.html#modify-existing-merge-request-note
495func (s *NotesService) UpdateMergeRequestNote(pid interface{}, mergeRequest, note int, opt *UpdateMergeRequestNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
496	project, err := parseID(pid)
497	if err != nil {
498		return nil, nil, err
499	}
500	u := fmt.Sprintf(
501		"projects/%s/merge_requests/%d/notes/%d", pathEscape(project), mergeRequest, note)
502	req, err := s.client.NewRequest("PUT", u, opt, options)
503	if err != nil {
504		return nil, nil, err
505	}
506
507	n := new(Note)
508	resp, err := s.client.Do(req, n)
509	if err != nil {
510		return nil, resp, err
511	}
512
513	return n, resp, err
514}
515
516// DeleteMergeRequestNote deletes an existing note of a merge request.
517//
518// GitLab API docs:
519// https://docs.gitlab.com/ce/api/notes.html#delete-a-merge-request-note
520func (s *NotesService) DeleteMergeRequestNote(pid interface{}, mergeRequest, note int, options ...OptionFunc) (*Response, error) {
521	project, err := parseID(pid)
522	if err != nil {
523		return nil, err
524	}
525	u := fmt.Sprintf(
526		"projects/%s/merge_requests/%d/notes/%d", pathEscape(project), mergeRequest, note)
527
528	req, err := s.client.NewRequest("DELETE", u, nil, options)
529	if err != nil {
530		return nil, err
531	}
532
533	return s.client.Do(req, nil)
534}
535
536// ListEpicNotesOptions represents the available ListEpicNotes() options.
537//
538// GitLab API docs:
539// https://docs.gitlab.com/ee/api/notes.html#list-all-epic-notes
540type ListEpicNotesOptions struct {
541	ListOptions
542	OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
543	Sort    *string `url:"sort,omitempty" json:"sort,omitempty"`
544}
545
546// ListEpicNotes gets a list of all notes for a single epic.
547//
548// GitLab API docs:
549// https://docs.gitlab.com/ee/api/notes.html#list-all-epic-notes
550func (s *NotesService) ListEpicNotes(gid interface{}, epic int, opt *ListEpicNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) {
551	group, err := parseID(gid)
552	if err != nil {
553		return nil, nil, err
554	}
555	u := fmt.Sprintf("groups/%s/epics/%d/notes", pathEscape(group), epic)
556
557	req, err := s.client.NewRequest("GET", u, opt, options)
558	if err != nil {
559		return nil, nil, err
560	}
561
562	var n []*Note
563	resp, err := s.client.Do(req, &n)
564	if err != nil {
565		return nil, resp, err
566	}
567
568	return n, resp, err
569}
570
571// GetEpicNote returns a single note for an epic.
572//
573// GitLab API docs:
574// https://docs.gitlab.com/ee/api/notes.html#get-single-epic-note
575func (s *NotesService) GetEpicNote(gid interface{}, epic, note int, options ...OptionFunc) (*Note, *Response, error) {
576	group, err := parseID(gid)
577	if err != nil {
578		return nil, nil, err
579	}
580	u := fmt.Sprintf("groups/%s/epics/%d/notes/%d", pathEscape(group), epic, note)
581
582	req, err := s.client.NewRequest("GET", u, nil, options)
583	if err != nil {
584		return nil, nil, err
585	}
586
587	n := new(Note)
588	resp, err := s.client.Do(req, n)
589	if err != nil {
590		return nil, resp, err
591	}
592
593	return n, resp, err
594}
595
596// CreateEpicNoteOptions represents the available CreateEpicNote() options.
597//
598// GitLab API docs:
599// https://docs.gitlab.com/ee/api/notes.html#create-new-epic-note
600type CreateEpicNoteOptions struct {
601	Body *string `url:"body,omitempty" json:"body,omitempty"`
602}
603
604// CreateEpicNote creates a new note for a single merge request.
605//
606// GitLab API docs:
607// https://docs.gitlab.com/ee/api/notes.html#create-new-epic-note
608func (s *NotesService) CreateEpicNote(gid interface{}, epic int, opt *CreateEpicNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
609	group, err := parseID(gid)
610	if err != nil {
611		return nil, nil, err
612	}
613	u := fmt.Sprintf("groups/%s/epics/%d/notes", pathEscape(group), epic)
614
615	req, err := s.client.NewRequest("POST", u, opt, options)
616	if err != nil {
617		return nil, nil, err
618	}
619
620	n := new(Note)
621	resp, err := s.client.Do(req, n)
622	if err != nil {
623		return nil, resp, err
624	}
625
626	return n, resp, err
627}
628
629// UpdateEpicNoteOptions represents the available UpdateEpicNote() options.
630//
631// GitLab API docs:
632// https://docs.gitlab.com/ee/api/notes.html#modify-existing-epic-note
633type UpdateEpicNoteOptions struct {
634	Body *string `url:"body,omitempty" json:"body,omitempty"`
635}
636
637// UpdateEpicNote modifies existing note of an epic.
638//
639// https://docs.gitlab.com/ee/api/notes.html#modify-existing-epic-note
640func (s *NotesService) UpdateEpicNote(gid interface{}, epic, note int, opt *UpdateEpicNoteOptions, options ...OptionFunc) (*Note, *Response, error) {
641	group, err := parseID(gid)
642	if err != nil {
643		return nil, nil, err
644	}
645	u := fmt.Sprintf("groups/%s/epics/%d/notes/%d", pathEscape(group), epic, note)
646
647	req, err := s.client.NewRequest("PUT", u, opt, options)
648	if err != nil {
649		return nil, nil, err
650	}
651
652	n := new(Note)
653	resp, err := s.client.Do(req, n)
654	if err != nil {
655		return nil, resp, err
656	}
657
658	return n, resp, err
659}
660
661// DeleteEpicNote deletes an existing note of a merge request.
662//
663// https://docs.gitlab.com/ee/api/notes.html#delete-an-epic-note
664func (s *NotesService) DeleteEpicNote(gid interface{}, epic, note int, options ...OptionFunc) (*Response, error) {
665	group, err := parseID(gid)
666	if err != nil {
667		return nil, err
668	}
669	u := fmt.Sprintf("groups/%s/epics/%d/notes/%d", pathEscape(group), epic, note)
670
671	req, err := s.client.NewRequest("DELETE", u, nil, options)
672	if err != nil {
673		return nil, err
674	}
675
676	return s.client.Do(req, nil)
677}