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// MilestonesService handles communication with the milestone related methods
25// of the GitLab API.
26//
27// GitLab API docs: https://docs.gitlab.com/ce/api/milestones.html
28type MilestonesService struct {
29	client *Client
30}
31
32// Milestone represents a GitLab milestone.
33//
34// GitLab API docs: https://docs.gitlab.com/ce/api/milestones.html
35type Milestone struct {
36	ID          int        `json:"id"`
37	IID         int        `json:"iid"`
38	ProjectID   int        `json:"project_id"`
39	Title       string     `json:"title"`
40	Description string     `json:"description"`
41	StartDate   *ISOTime   `json:"start_date"`
42	DueDate     *ISOTime   `json:"due_date"`
43	State       string     `json:"state"`
44	UpdatedAt   *time.Time `json:"updated_at"`
45	CreatedAt   *time.Time `json:"created_at"`
46}
47
48func (m Milestone) String() string {
49	return Stringify(m)
50}
51
52// ListMilestonesOptions represents the available ListMilestones() options.
53//
54// GitLab API docs:
55// https://docs.gitlab.com/ce/api/milestones.html#list-project-milestones
56type ListMilestonesOptions struct {
57	ListOptions
58	IIDs   []int  `url:"iids,omitempty" json:"iids,omitempty"`
59	State  string `url:"state,omitempty" json:"state,omitempty"`
60	Search string `url:"search,omitempty" json:"search,omitempty"`
61}
62
63// ListMilestones returns a list of project milestones.
64//
65// GitLab API docs:
66// https://docs.gitlab.com/ce/api/milestones.html#list-project-milestones
67func (s *MilestonesService) ListMilestones(pid interface{}, opt *ListMilestonesOptions, options ...OptionFunc) ([]*Milestone, *Response, error) {
68	project, err := parseID(pid)
69	if err != nil {
70		return nil, nil, err
71	}
72	u := fmt.Sprintf("projects/%s/milestones", pathEscape(project))
73
74	req, err := s.client.NewRequest("GET", u, opt, options)
75	if err != nil {
76		return nil, nil, err
77	}
78
79	var m []*Milestone
80	resp, err := s.client.Do(req, &m)
81	if err != nil {
82		return nil, resp, err
83	}
84
85	return m, resp, err
86}
87
88// GetMilestone gets a single project milestone.
89//
90// GitLab API docs:
91// https://docs.gitlab.com/ce/api/milestones.html#get-single-milestone
92func (s *MilestonesService) GetMilestone(pid interface{}, milestone int, options ...OptionFunc) (*Milestone, *Response, error) {
93	project, err := parseID(pid)
94	if err != nil {
95		return nil, nil, err
96	}
97	u := fmt.Sprintf("projects/%s/milestones/%d", pathEscape(project), milestone)
98
99	req, err := s.client.NewRequest("GET", u, nil, options)
100	if err != nil {
101		return nil, nil, err
102	}
103
104	m := new(Milestone)
105	resp, err := s.client.Do(req, m)
106	if err != nil {
107		return nil, resp, err
108	}
109
110	return m, resp, err
111}
112
113// CreateMilestoneOptions represents the available CreateMilestone() options.
114//
115// GitLab API docs:
116// https://docs.gitlab.com/ce/api/milestones.html#create-new-milestone
117type CreateMilestoneOptions struct {
118	Title       *string  `url:"title,omitempty" json:"title,omitempty"`
119	Description *string  `url:"description,omitempty" json:"description,omitempty"`
120	StartDate   *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"`
121	DueDate     *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"`
122}
123
124// CreateMilestone creates a new project milestone.
125//
126// GitLab API docs:
127// https://docs.gitlab.com/ce/api/milestones.html#create-new-milestone
128func (s *MilestonesService) CreateMilestone(pid interface{}, opt *CreateMilestoneOptions, options ...OptionFunc) (*Milestone, *Response, error) {
129	project, err := parseID(pid)
130	if err != nil {
131		return nil, nil, err
132	}
133	u := fmt.Sprintf("projects/%s/milestones", pathEscape(project))
134
135	req, err := s.client.NewRequest("POST", u, opt, options)
136	if err != nil {
137		return nil, nil, err
138	}
139
140	m := new(Milestone)
141	resp, err := s.client.Do(req, m)
142	if err != nil {
143		return nil, resp, err
144	}
145
146	return m, resp, err
147}
148
149// UpdateMilestoneOptions represents the available UpdateMilestone() options.
150//
151// GitLab API docs:
152// https://docs.gitlab.com/ce/api/milestones.html#edit-milestone
153type UpdateMilestoneOptions struct {
154	Title       *string  `url:"title,omitempty" json:"title,omitempty"`
155	Description *string  `url:"description,omitempty" json:"description,omitempty"`
156	StartDate   *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"`
157	DueDate     *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"`
158	StateEvent  *string  `url:"state_event,omitempty" json:"state_event,omitempty"`
159}
160
161// UpdateMilestone updates an existing project milestone.
162//
163// GitLab API docs:
164// https://docs.gitlab.com/ce/api/milestones.html#edit-milestone
165func (s *MilestonesService) UpdateMilestone(pid interface{}, milestone int, opt *UpdateMilestoneOptions, options ...OptionFunc) (*Milestone, *Response, error) {
166	project, err := parseID(pid)
167	if err != nil {
168		return nil, nil, err
169	}
170	u := fmt.Sprintf("projects/%s/milestones/%d", pathEscape(project), milestone)
171
172	req, err := s.client.NewRequest("PUT", u, opt, options)
173	if err != nil {
174		return nil, nil, err
175	}
176
177	m := new(Milestone)
178	resp, err := s.client.Do(req, m)
179	if err != nil {
180		return nil, resp, err
181	}
182
183	return m, resp, err
184}
185
186// DeleteMilestone deletes a specified project milestone.
187//
188// GitLab API docs:
189// https://docs.gitlab.com/ce/api/milestones.html#delete-project-milestone
190func (s *MilestonesService) DeleteMilestone(pid interface{}, milestone int, options ...OptionFunc) (*Response, error) {
191	project, err := parseID(pid)
192	if err != nil {
193		return nil, err
194	}
195	u := fmt.Sprintf("projects/%s/milestones/%d", pathEscape(project), milestone)
196
197	req, err := s.client.NewRequest("DELETE", u, nil, options)
198	if err != nil {
199		return nil, err
200	}
201	return s.client.Do(req, nil)
202}
203
204// GetMilestoneIssuesOptions represents the available GetMilestoneIssues() options.
205//
206// GitLab API docs:
207// https://docs.gitlab.com/ce/api/milestones.html#get-all-issues-assigned-to-a-single-milestone
208type GetMilestoneIssuesOptions ListOptions
209
210// GetMilestoneIssues gets all issues assigned to a single project milestone.
211//
212// GitLab API docs:
213// https://docs.gitlab.com/ce/api/milestones.html#get-all-issues-assigned-to-a-single-milestone
214func (s *MilestonesService) GetMilestoneIssues(pid interface{}, milestone int, opt *GetMilestoneIssuesOptions, options ...OptionFunc) ([]*Issue, *Response, error) {
215	project, err := parseID(pid)
216	if err != nil {
217		return nil, nil, err
218	}
219	u := fmt.Sprintf("projects/%s/milestones/%d/issues", pathEscape(project), milestone)
220
221	req, err := s.client.NewRequest("GET", u, opt, options)
222	if err != nil {
223		return nil, nil, err
224	}
225
226	var i []*Issue
227	resp, err := s.client.Do(req, &i)
228	if err != nil {
229		return nil, resp, err
230	}
231
232	return i, resp, err
233}
234
235// GetMilestoneMergeRequestsOptions represents the available
236// GetMilestoneMergeRequests() options.
237//
238// GitLab API docs:
239// https://docs.gitlab.com/ce/api/milestones.html#get-all-merge-requests-assigned-to-a-single-milestone
240type GetMilestoneMergeRequestsOptions ListOptions
241
242// GetMilestoneMergeRequests gets all merge requests assigned to a single
243// project milestone.
244//
245// GitLab API docs:
246// https://docs.gitlab.com/ce/api/milestones.html#get-all-merge-requests-assigned-to-a-single-milestone
247func (s *MilestonesService) GetMilestoneMergeRequests(pid interface{}, milestone int, opt *GetMilestoneMergeRequestsOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) {
248	project, err := parseID(pid)
249	if err != nil {
250		return nil, nil, err
251	}
252	u := fmt.Sprintf("projects/%s/milestones/%d/merge_requests", pathEscape(project), milestone)
253
254	req, err := s.client.NewRequest("GET", u, opt, options)
255	if err != nil {
256		return nil, nil, err
257	}
258
259	var mr []*MergeRequest
260	resp, err := s.client.Do(req, &mr)
261	if err != nil {
262		return nil, resp, err
263	}
264
265	return mr, resp, err
266}
267