1// Copyright 2016 The go-github AUTHORS. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6package github
7
8import (
9	"context"
10	"fmt"
11	"time"
12)
13
14// PullRequestReview represents a review of a pull request.
15type PullRequestReview struct {
16	ID             *int64     `json:"id,omitempty"`
17	User           *User      `json:"user,omitempty"`
18	Body           *string    `json:"body,omitempty"`
19	SubmittedAt    *time.Time `json:"submitted_at,omitempty"`
20	CommitID       *string    `json:"commit_id,omitempty"`
21	HTMLURL        *string    `json:"html_url,omitempty"`
22	PullRequestURL *string    `json:"pull_request_url,omitempty"`
23	State          *string    `json:"state,omitempty"`
24}
25
26func (p PullRequestReview) String() string {
27	return Stringify(p)
28}
29
30// DraftReviewComment represents a comment part of the review.
31type DraftReviewComment struct {
32	Path     *string `json:"path,omitempty"`
33	Position *int    `json:"position,omitempty"`
34	Body     *string `json:"body,omitempty"`
35}
36
37func (c DraftReviewComment) String() string {
38	return Stringify(c)
39}
40
41// PullRequestReviewRequest represents a request to create a review.
42type PullRequestReviewRequest struct {
43	CommitID *string               `json:"commit_id,omitempty"`
44	Body     *string               `json:"body,omitempty"`
45	Event    *string               `json:"event,omitempty"`
46	Comments []*DraftReviewComment `json:"comments,omitempty"`
47}
48
49func (r PullRequestReviewRequest) String() string {
50	return Stringify(r)
51}
52
53// PullRequestReviewDismissalRequest represents a request to dismiss a review.
54type PullRequestReviewDismissalRequest struct {
55	Message *string `json:"message,omitempty"`
56}
57
58func (r PullRequestReviewDismissalRequest) String() string {
59	return Stringify(r)
60}
61
62// ListReviews lists all reviews on the specified pull request.
63//
64// TODO: Follow up with GitHub support about an issue with this method's
65// returned error format and remove this comment once it's fixed.
66// Read more about it here - https://github.com/google/go-github/issues/540
67//
68// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request
69func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*PullRequestReview, *Response, error) {
70	u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)
71	u, err := addOptions(u, opt)
72	if err != nil {
73		return nil, nil, err
74	}
75
76	req, err := s.client.NewRequest("GET", u, nil)
77	if err != nil {
78		return nil, nil, err
79	}
80
81	var reviews []*PullRequestReview
82	resp, err := s.client.Do(ctx, req, &reviews)
83	if err != nil {
84		return nil, resp, err
85	}
86
87	return reviews, resp, nil
88}
89
90// GetReview fetches the specified pull request review.
91//
92// TODO: Follow up with GitHub support about an issue with this method's
93// returned error format and remove this comment once it's fixed.
94// Read more about it here - https://github.com/google/go-github/issues/540
95//
96// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-a-single-review
97func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) {
98	u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
99
100	req, err := s.client.NewRequest("GET", u, nil)
101	if err != nil {
102		return nil, nil, err
103	}
104
105	review := new(PullRequestReview)
106	resp, err := s.client.Do(ctx, req, review)
107	if err != nil {
108		return nil, resp, err
109	}
110
111	return review, resp, nil
112}
113
114// DeletePendingReview deletes the specified pull request pending review.
115//
116// TODO: Follow up with GitHub support about an issue with this method's
117// returned error format and remove this comment once it's fixed.
118// Read more about it here - https://github.com/google/go-github/issues/540
119//
120// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review
121func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) {
122	u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
123
124	req, err := s.client.NewRequest("DELETE", u, nil)
125	if err != nil {
126		return nil, nil, err
127	}
128
129	review := new(PullRequestReview)
130	resp, err := s.client.Do(ctx, req, review)
131	if err != nil {
132		return nil, resp, err
133	}
134
135	return review, resp, nil
136}
137
138// ListReviewComments lists all the comments for the specified review.
139//
140// TODO: Follow up with GitHub support about an issue with this method's
141// returned error format and remove this comment once it's fixed.
142// Read more about it here - https://github.com/google/go-github/issues/540
143//
144// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review
145func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opt *ListOptions) ([]*PullRequestComment, *Response, error) {
146	u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID)
147	u, err := addOptions(u, opt)
148	if err != nil {
149		return nil, nil, err
150	}
151
152	req, err := s.client.NewRequest("GET", u, nil)
153	if err != nil {
154		return nil, nil, err
155	}
156
157	var comments []*PullRequestComment
158	resp, err := s.client.Do(ctx, req, &comments)
159	if err != nil {
160		return nil, resp, err
161	}
162
163	return comments, resp, nil
164}
165
166// CreateReview creates a new review on the specified pull request.
167//
168// TODO: Follow up with GitHub support about an issue with this method's
169// returned error format and remove this comment once it's fixed.
170// Read more about it here - https://github.com/google/go-github/issues/540
171//
172// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review
173func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) {
174	u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)
175
176	req, err := s.client.NewRequest("POST", u, review)
177	if err != nil {
178		return nil, nil, err
179	}
180
181	r := new(PullRequestReview)
182	resp, err := s.client.Do(ctx, req, r)
183	if err != nil {
184		return nil, resp, err
185	}
186
187	return r, resp, nil
188}
189
190// SubmitReview submits a specified review on the specified pull request.
191//
192// TODO: Follow up with GitHub support about an issue with this method's
193// returned error format and remove this comment once it's fixed.
194// Read more about it here - https://github.com/google/go-github/issues/540
195//
196// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review
197func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) {
198	u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID)
199
200	req, err := s.client.NewRequest("POST", u, review)
201	if err != nil {
202		return nil, nil, err
203	}
204
205	r := new(PullRequestReview)
206	resp, err := s.client.Do(ctx, req, r)
207	if err != nil {
208		return nil, resp, err
209	}
210
211	return r, resp, nil
212}
213
214// DismissReview dismisses a specified review on the specified pull request.
215//
216// TODO: Follow up with GitHub support about an issue with this method's
217// returned error format and remove this comment once it's fixed.
218// Read more about it here - https://github.com/google/go-github/issues/540
219//
220// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review
221func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) {
222	u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID)
223
224	req, err := s.client.NewRequest("PUT", u, review)
225	if err != nil {
226		return nil, nil, err
227	}
228
229	r := new(PullRequestReview)
230	resp, err := s.client.Do(ctx, req, r)
231	if err != nil {
232		return nil, resp, err
233	}
234
235	return r, resp, nil
236}
237