1package gerrit
2
3import (
4	"fmt"
5	"net/url"
6)
7
8// EditInfo entity contains information about a change edit.
9type EditInfo struct {
10	Commit       CommitInfo           `json:"commit"`
11	BaseRevision string               `json:"baseRevision"`
12	Fetch        map[string]FetchInfo `json:"fetch"`
13	Files        map[string]FileInfo  `json:"files,omitempty"`
14}
15
16// EditFileInfo entity contains additional information of a file within a change edit.
17type EditFileInfo struct {
18	WebLinks []WebLinkInfo `json:"web_links,omitempty"`
19}
20
21// ChangeEditDetailOptions specifies the parameters to the ChangesService.GetChangeEditDetails.
22//
23// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-edit-detail
24type ChangeEditDetailOptions struct {
25	// When request parameter list is provided the response also includes the file list.
26	List bool `url:"list,omitempty"`
27	// When base request parameter is provided the file list is computed against this base revision.
28	Base bool `url:"base,omitempty"`
29	// When request parameter download-commands is provided fetch info map is also included.
30	DownloadCommands bool `url:"download-commands,omitempty"`
31}
32
33// GetChangeEditDetails retrieves a change edit details.
34// As response an EditInfo entity is returned that describes the change edit, or “204 No Content” when change edit doesn’t exist for this change.
35// Change edits are stored on special branches and there can be max one edit per user per change.
36// Edits aren’t tracked in the database.
37//
38// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-edit-detail
39func (s *ChangesService) GetChangeEditDetails(changeID string, opt *ChangeEditDetailOptions) (*EditInfo, *Response, error) {
40	u := fmt.Sprintf("changes/%s/edit", changeID)
41
42	u, err := addOptions(u, opt)
43	if err != nil {
44		return nil, nil, err
45	}
46
47	req, err := s.client.NewRequest("GET", u, nil)
48	if err != nil {
49		return nil, nil, err
50	}
51
52	v := new(EditInfo)
53	resp, err := s.client.Do(req, v)
54	if err != nil {
55		return nil, resp, err
56	}
57
58	return v, resp, err
59}
60
61// RetrieveMetaDataOfAFileFromChangeEdit retrieves meta data of a file from a change edit.
62// Currently only web links are returned.
63//
64// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-edit-meta-data
65func (s *ChangesService) RetrieveMetaDataOfAFileFromChangeEdit(changeID, filePath string) (*EditFileInfo, *Response, error) {
66	u := fmt.Sprintf("changes/%s/edit/%s/meta", changeID, filePath)
67
68	req, err := s.client.NewRequest("GET", u, nil)
69	if err != nil {
70		return nil, nil, err
71	}
72
73	v := new(EditFileInfo)
74	resp, err := s.client.Do(req, v)
75	if err != nil {
76		return nil, resp, err
77	}
78
79	return v, resp, err
80}
81
82// RetrieveCommitMessageFromChangeEdit retrieves commit message from change edit.
83// The commit message is returned as base64 encoded string.
84//
85// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-edit-message
86func (s *ChangesService) RetrieveCommitMessageFromChangeEdit(changeID string) (string, *Response, error) {
87	u := fmt.Sprintf("changes/%s/edit:message", changeID)
88	return getStringResponseWithoutOptions(s.client, u)
89}
90
91// ChangeFileContentInChangeEdit put content of a file to a change edit.
92//
93// When change edit doesn’t exist for this change yet it is created.
94// When file content isn’t provided, it is wiped out for that file.
95// As response “204 No Content” is returned.
96//
97// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#put-edit-file
98func (s *ChangesService) ChangeFileContentInChangeEdit(changeID, filePath, content string) (*Response, error) {
99	u := fmt.Sprintf("changes/%s/edit/%s", changeID, url.QueryEscape(filePath))
100
101	req, err := s.client.NewRawPutRequest(u, content)
102	if err != nil {
103		return nil, err
104	}
105
106	return s.client.Do(req, nil)
107}
108
109// ChangeCommitMessageInChangeEdit modify commit message.
110// The request body needs to include a ChangeEditMessageInput entity.
111//
112// If a change edit doesn’t exist for this change yet, it is created.
113// As response “204 No Content” is returned.
114//
115// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#put-change-edit-message
116func (s *ChangesService) ChangeCommitMessageInChangeEdit(changeID string, input *ChangeEditMessageInput) (*Response, error) {
117	u := fmt.Sprintf("changes/%s/edit:message", changeID)
118
119	req, err := s.client.NewRequest("PUT", u, input)
120	if err != nil {
121		return nil, err
122	}
123
124	return s.client.Do(req, nil)
125}
126
127// DeleteFileInChangeEdit deletes a file from a change edit.
128// This deletes the file from the repository completely.
129// This is not the same as reverting or restoring a file to its previous contents.
130//
131// When change edit doesn’t exist for this change yet it is created.
132//
133// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#delete-edit-file
134func (s *ChangesService) DeleteFileInChangeEdit(changeID, filePath string) (*Response, error) {
135	u := fmt.Sprintf("changes/%s/edit/%s", changeID, filePath)
136	return s.client.DeleteRequest(u, nil)
137}
138
139// DeleteChangeEdit deletes change edit.
140//
141// As response “204 No Content” is returned.
142//
143// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#delete-edit
144func (s *ChangesService) DeleteChangeEdit(changeID string) (*Response, error) {
145	u := fmt.Sprintf("changes/%s/edit", changeID)
146	return s.client.DeleteRequest(u, nil)
147}
148
149// PublishChangeEdit promotes change edit to a regular patch set.
150//
151// As response “204 No Content” is returned.
152//
153// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#publish-edit
154func (s *ChangesService) PublishChangeEdit(changeID, notify string) (*Response, error) {
155	u := fmt.Sprintf("changes/%s/edit:publish", changeID)
156
157	req, err := s.client.NewRequest("POST", u, map[string]string{
158		"notify": notify,
159	})
160	if err != nil {
161		return nil, err
162	}
163	return s.client.Do(req, nil)
164}
165
166// RebaseChangeEdit rebases change edit on top of latest patch set.
167//
168// When change was rebased on top of latest patch set, response “204 No Content” is returned.
169// When change edit is already based on top of the latest patch set, the response “409 Conflict” is returned.
170//
171// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#rebase-edit
172func (s *ChangesService) RebaseChangeEdit(changeID string) (*Response, error) {
173	u := fmt.Sprintf("changes/%s/edit:rebase", changeID)
174
175	req, err := s.client.NewRequest("POST", u, nil)
176	if err != nil {
177		return nil, err
178	}
179
180	return s.client.Do(req, nil)
181}
182
183// RetrieveFileContentFromChangeEdit retrieves content of a file from a change edit.
184//
185// The content of the file is returned as text encoded inside base64.
186// The Content-Type header will always be text/plain reflecting the outer base64 encoding.
187// A Gerrit-specific X-FYI-Content-Type header can be examined to find the server detected content type of the file.
188//
189// When the specified file was deleted in the change edit “204 No Content” is returned.
190// If only the content type is required, callers should use HEAD to avoid downloading the encoded file contents.
191//
192// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-edit-file
193func (s *ChangesService) RetrieveFileContentFromChangeEdit(changeID, filePath string) (*string, *Response, error) {
194	u := fmt.Sprintf("changes/%s/edit/%s", changeID, filePath)
195
196	req, err := s.client.NewRequest("GET", u, nil)
197	if err != nil {
198		return nil, nil, err
199	}
200
201	v := new(string)
202	resp, err := s.client.Do(req, v)
203	if err != nil {
204		return nil, resp, err
205	}
206
207	return v, resp, err
208}
209
210// RetrieveFileContentTypeFromChangeEdit retrieves content type of a file from a change edit.
211// This is nearly the same as RetrieveFileContentFromChangeEdit.
212// But if only the content type is required, callers should use HEAD to avoid downloading the encoded file contents.
213//
214// For further documentation please have a look at RetrieveFileContentFromChangeEdit.
215//
216// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-edit-file
217func (s *ChangesService) RetrieveFileContentTypeFromChangeEdit(changeID, filePath string) (*Response, error) {
218	u := fmt.Sprintf("changes/%s/edit/%s", changeID, filePath)
219
220	req, err := s.client.NewRequest("HEAD", u, nil)
221	if err != nil {
222		return nil, err
223	}
224
225	return s.client.Do(req, nil)
226}
227
228/*
229Missing Change Edit Endpoints
230	Restore file content or rename files in Change Edit
231*/
232