1//
2// Copyright 2018, 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)
22
23// SearchService handles communication with the search related methods of the
24// GitLab API.
25//
26// GitLab API docs: https://docs.gitlab.com/ce/api/search.html
27type SearchService struct {
28 client *Client
29}
30
31// SearchOptions represents the available options for all search methods.
32//
33// GitLab API docs: https://docs.gitlab.com/ce/api/search.html
34type SearchOptions ListOptions
35
36type searchOptions struct {
37 SearchOptions
38 Scope string `url:"scope" json:"scope"`
39 Search string `url:"search" json:"search"`
40}
41
42// Projects searches the expression within projects
43//
44// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-projects
45func (s *SearchService) Projects(query string, opt *SearchOptions, options ...OptionFunc) ([]*Project, *Response, error) {
46 var ps []*Project
47 resp, err := s.search("projects", query, &ps, opt, options...)
48 return ps, resp, err
49}
50
51// ProjectsByGroup searches the expression within projects for
52// the specified group
53//
54// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#group-search-api
55func (s *SearchService) ProjectsByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Project, *Response, error) {
56 var ps []*Project
57 resp, err := s.searchByGroup(gid, "projects", query, &ps, opt, options...)
58 return ps, resp, err
59}
60
61// Issues searches the expression within issues
62//
63// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-issues
64func (s *SearchService) Issues(query string, opt *SearchOptions, options ...OptionFunc) ([]*Issue, *Response, error) {
65 var is []*Issue
66 resp, err := s.search("issues", query, &is, opt, options...)
67 return is, resp, err
68}
69
70// IssuesByGroup searches the expression within issues for
71// the specified group
72//
73// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-issues
74func (s *SearchService) IssuesByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Issue, *Response, error) {
75 var is []*Issue
76 resp, err := s.searchByGroup(gid, "issues", query, &is, opt, options...)
77 return is, resp, err
78}
79
80// IssuesByProject searches the expression within issues for
81// the specified project
82//
83// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-issues
84func (s *SearchService) IssuesByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Issue, *Response, error) {
85 var is []*Issue
86 resp, err := s.searchByProject(pid, "issues", query, &is, opt, options...)
87 return is, resp, err
88}
89
90// MergeRequests searches the expression within merge requests
91//
92// GitLab API docs:
93// https://docs.gitlab.com/ce/api/search.html#scope-merge_requests
94func (s *SearchService) MergeRequests(query string, opt *SearchOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) {
95 var ms []*MergeRequest
96 resp, err := s.search("merge_requests", query, &ms, opt, options...)
97 return ms, resp, err
98}
99
100// MergeRequestsByGroup searches the expression within merge requests for
101// the specified group
102//
103// GitLab API docs:
104// https://docs.gitlab.com/ce/api/search.html#scope-merge_requests
105func (s *SearchService) MergeRequestsByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) {
106 var ms []*MergeRequest
107 resp, err := s.searchByGroup(gid, "merge_requests", query, &ms, opt, options...)
108 return ms, resp, err
109}
110
111// MergeRequestsByProject searches the expression within merge requests for
112// the specified project
113//
114// GitLab API docs:
115// https://docs.gitlab.com/ce/api/search.html#scope-merge_requests
116func (s *SearchService) MergeRequestsByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) {
117 var ms []*MergeRequest
118 resp, err := s.searchByProject(pid, "merge_requests", query, &ms, opt, options...)
119 return ms, resp, err
120}
121
122// Milestones searches the expression within milestones
123//
124// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-milestones
125func (s *SearchService) Milestones(query string, opt *SearchOptions, options ...OptionFunc) ([]*Milestone, *Response, error) {
126 var ms []*Milestone
127 resp, err := s.search("milestones", query, &ms, opt, options...)
128 return ms, resp, err
129}
130
131// MilestonesByGroup searches the expression within milestones for
132// the specified group
133//
134// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-milestones
135func (s *SearchService) MilestonesByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Milestone, *Response, error) {
136 var ms []*Milestone
137 resp, err := s.searchByGroup(gid, "milestones", query, &ms, opt, options...)
138 return ms, resp, err
139}
140
141// MilestonesByProject searches the expression within milestones for
142// the specified project
143//
144// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-milestones
145func (s *SearchService) MilestonesByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Milestone, *Response, error) {
146 var ms []*Milestone
147 resp, err := s.searchByProject(pid, "milestones", query, &ms, opt, options...)
148 return ms, resp, err
149}
150
151// SnippetTitles searches the expression within snippet titles
152//
153// GitLab API docs:
154// https://docs.gitlab.com/ce/api/search.html#scope-snippet_titles
155func (s *SearchService) SnippetTitles(query string, opt *SearchOptions, options ...OptionFunc) ([]*Snippet, *Response, error) {
156 var ss []*Snippet
157 resp, err := s.search("snippet_titles", query, &ss, opt, options...)
158 return ss, resp, err
159}
160
161// SnippetBlobs searches the expression within snippet blobs
162//
163// GitLab API docs:
164// https://docs.gitlab.com/ce/api/search.html#scope-snippet_blobs
165func (s *SearchService) SnippetBlobs(query string, opt *SearchOptions, options ...OptionFunc) ([]*Snippet, *Response, error) {
166 var ss []*Snippet
167 resp, err := s.search("snippet_blobs", query, &ss, opt, options...)
168 return ss, resp, err
169}
170
171// NotesByProject searches the expression within notes for the specified
172// project
173//
174// GitLab API docs: // https://docs.gitlab.com/ce/api/search.html#scope-notes
175func (s *SearchService) NotesByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Note, *Response, error) {
176 var ns []*Note
177 resp, err := s.searchByProject(pid, "notes", query, &ns, opt, options...)
178 return ns, resp, err
179}
180
181// WikiBlobs searches the expression within all wiki blobs
182//
183// GitLab API docs:
184// https://docs.gitlab.com/ce/api/search.html#scope-wiki_blobs
185func (s *SearchService) WikiBlobs(query string, opt *SearchOptions, options ...OptionFunc) ([]*Wiki, *Response, error) {
186 var ws []*Wiki
187 resp, err := s.search("wiki_blobs", query, &ws, opt, options...)
188 return ws, resp, err
189}
190
191// WikiBlobsByGroup searches the expression within wiki blobs for
192// specified group
193//
194// GitLab API docs:
195// https://docs.gitlab.com/ce/api/search.html#scope-wiki_blobs
196func (s *SearchService) WikiBlobsByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Wiki, *Response, error) {
197 var ws []*Wiki
198 resp, err := s.searchByGroup(gid, "wiki_blobs", query, &ws, opt, options...)
199 return ws, resp, err
200}
201
202// WikiBlobsByProject searches the expression within wiki blobs for
203// the specified project
204//
205// GitLab API docs:
206// https://docs.gitlab.com/ce/api/search.html#scope-wiki_blobs
207func (s *SearchService) WikiBlobsByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Wiki, *Response, error) {
208 var ws []*Wiki
209 resp, err := s.searchByProject(pid, "wiki_blobs", query, &ws, opt, options...)
210 return ws, resp, err
211}
212
213// Commits searches the expression within all commits
214//
215// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-commits
216func (s *SearchService) Commits(query string, opt *SearchOptions, options ...OptionFunc) ([]*Commit, *Response, error) {
217 var cs []*Commit
218 resp, err := s.search("commits", query, &cs, opt, options...)
219 return cs, resp, err
220}
221
222// CommitsByGroup searches the expression within commits for the specified
223// group
224//
225// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-commits
226func (s *SearchService) CommitsByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Commit, *Response, error) {
227 var cs []*Commit
228 resp, err := s.searchByGroup(gid, "commits", query, &cs, opt, options...)
229 return cs, resp, err
230}
231
232// CommitsByProject searches the expression within commits for the
233// specified project
234//
235// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-commits
236func (s *SearchService) CommitsByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Commit, *Response, error) {
237 var cs []*Commit
238 resp, err := s.searchByProject(pid, "commits", query, &cs, opt, options...)
239 return cs, resp, err
240}
241
242// Blob represents a single blob.
243type Blob struct {
244 Basename string `json:"basename"`
245 Data string `json:"data"`
246 Filename string `json:"filename"`
247 ID int `json:"id"`
248 Ref string `json:"ref"`
249 Startline int `json:"startline"`
250 ProjectID int `json:"project_id"`
251}
252
253// Blobs searches the expression within all blobs
254//
255// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-blobs
256func (s *SearchService) Blobs(query string, opt *SearchOptions, options ...OptionFunc) ([]*Blob, *Response, error) {
257 var bs []*Blob
258 resp, err := s.search("blobs", query, &bs, opt, options...)
259 return bs, resp, err
260}
261
262// BlobsByGroup searches the expression within blobs for the specified
263// group
264//
265// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-blobs
266func (s *SearchService) BlobsByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Blob, *Response, error) {
267 var bs []*Blob
268 resp, err := s.searchByGroup(gid, "blobs", query, &bs, opt, options...)
269 return bs, resp, err
270}
271
272// BlobsByProject searches the expression within blobs for the specified
273// project
274//
275// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-blobs
276func (s *SearchService) BlobsByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Blob, *Response, error) {
277 var bs []*Blob
278 resp, err := s.searchByProject(pid, "blobs", query, &bs, opt, options...)
279 return bs, resp, err
280}
281
282// Users searches the expression within all users
283//
284// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-users
285func (s *SearchService) Users(query string, opt *SearchOptions, options ...OptionFunc) ([]*User, *Response, error) {
286 var ret []*User
287 resp, err := s.search("users", query, &ret, opt, options...)
288 return ret, resp, err
289}
290
291// UsersByGroup searches the expression within users for the specified
292// group
293//
294// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-users-1
295func (s *SearchService) UsersByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*User, *Response, error) {
296 var ret []*User
297 resp, err := s.searchByGroup(gid, "users", query, &ret, opt, options...)
298 return ret, resp, err
299}
300
301// UsersByProject searches the expression within users for the
302// specified project
303//
304// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-users-2
305func (s *SearchService) UsersByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*User, *Response, error) {
306 var ret []*User
307 resp, err := s.searchByProject(pid, "users", query, &ret, opt, options...)
308 return ret, resp, err
309}
310
311func (s *SearchService) search(scope, query string, result interface{}, opt *SearchOptions, options ...OptionFunc) (*Response, error) {
312 opts := &searchOptions{SearchOptions: *opt, Scope: scope, Search: query}
313
314 req, err := s.client.NewRequest("GET", "search", opts, options)
315 if err != nil {
316 return nil, err
317 }
318
319 return s.client.Do(req, result)
320}
321
322func (s *SearchService) searchByGroup(gid interface{}, scope, query string, result interface{}, opt *SearchOptions, options ...OptionFunc) (*Response, error) {
323 group, err := parseID(gid)
324 if err != nil {
325 return nil, err
326 }
327 u := fmt.Sprintf("groups/%s/-/search", pathEscape(group))
328
329 opts := &searchOptions{SearchOptions: *opt, Scope: scope, Search: query}
330
331 req, err := s.client.NewRequest("GET", u, opts, options)
332 if err != nil {
333 return nil, err
334 }
335
336 return s.client.Do(req, result)
337}
338
339func (s *SearchService) searchByProject(pid interface{}, scope, query string, result interface{}, opt *SearchOptions, options ...OptionFunc) (*Response, error) {
340 project, err := parseID(pid)
341 if err != nil {
342 return nil, err
343 }
344 u := fmt.Sprintf("projects/%s/-/search", pathEscape(project))
345
346 opts := &searchOptions{SearchOptions: *opt, Scope: scope, Search: query}
347
348 req, err := s.client.NewRequest("GET", u, opts, options)
349 if err != nil {
350 return nil, err
351 }
352
353 return s.client.Do(req, result)
354}