1
2
3
4
5
6 package github
7
8 import (
9 "context"
10 "fmt"
11 "strconv"
12 "strings"
13
14 qs "github.com/google/go-querystring/query"
15 )
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 type SearchService service
37
38
39 type SearchOptions struct {
40
41
42
43
44
45
46
47
48 Sort string `url:"sort,omitempty"`
49
50
51
52 Order string `url:"order,omitempty"`
53
54
55 TextMatch bool `url:"-"`
56
57 ListOptions
58 }
59
60
61 type searchParameters struct {
62 Query string
63 RepositoryID *int64
64 }
65
66
67 type RepositoriesSearchResult struct {
68 Total *int `json:"total_count,omitempty"`
69 IncompleteResults *bool `json:"incomplete_results,omitempty"`
70 Repositories []*Repository `json:"items,omitempty"`
71 }
72
73
74
75
76 func (s *SearchService) Repositories(ctx context.Context, query string, opts *SearchOptions) (*RepositoriesSearchResult, *Response, error) {
77 result := new(RepositoriesSearchResult)
78 resp, err := s.search(ctx, "repositories", &searchParameters{Query: query}, opts, result)
79 if err != nil {
80 return nil, resp, err
81 }
82
83 return result, resp, nil
84 }
85
86
87 type TopicsSearchResult struct {
88 Total *int `json:"total_count,omitempty"`
89 IncompleteResults *bool `json:"incomplete_results,omitempty"`
90 Topics []*TopicResult `json:"items,omitempty"`
91 }
92
93 type TopicResult struct {
94 Name *string `json:"name,omitempty"`
95 DisplayName *string `json:"display_name,omitempty"`
96 ShortDescription *string `json:"short_description,omitempty"`
97 Description *string `json:"description,omitempty"`
98 CreatedBy *string `json:"created_by,omitempty"`
99 CreatedAt *Timestamp `json:"created_at,omitempty"`
100 UpdatedAt *string `json:"updated_at,omitempty"`
101 Featured *bool `json:"featured,omitempty"`
102 Curated *bool `json:"curated,omitempty"`
103 Score *float64 `json:"score,omitempty"`
104 }
105
106
107
108
109
110
111 func (s *SearchService) Topics(ctx context.Context, query string, opts *SearchOptions) (*TopicsSearchResult, *Response, error) {
112 result := new(TopicsSearchResult)
113 resp, err := s.search(ctx, "topics", &searchParameters{Query: query}, opts, result)
114 if err != nil {
115 return nil, resp, err
116 }
117
118 return result, resp, nil
119 }
120
121
122 type CommitsSearchResult struct {
123 Total *int `json:"total_count,omitempty"`
124 IncompleteResults *bool `json:"incomplete_results,omitempty"`
125 Commits []*CommitResult `json:"items,omitempty"`
126 }
127
128
129 type CommitResult struct {
130 SHA *string `json:"sha,omitempty"`
131 Commit *Commit `json:"commit,omitempty"`
132 Author *User `json:"author,omitempty"`
133 Committer *User `json:"committer,omitempty"`
134 Parents []*Commit `json:"parents,omitempty"`
135 HTMLURL *string `json:"html_url,omitempty"`
136 URL *string `json:"url,omitempty"`
137 CommentsURL *string `json:"comments_url,omitempty"`
138
139 Repository *Repository `json:"repository,omitempty"`
140 Score *float64 `json:"score,omitempty"`
141 }
142
143
144
145
146 func (s *SearchService) Commits(ctx context.Context, query string, opts *SearchOptions) (*CommitsSearchResult, *Response, error) {
147 result := new(CommitsSearchResult)
148 resp, err := s.search(ctx, "commits", &searchParameters{Query: query}, opts, result)
149 if err != nil {
150 return nil, resp, err
151 }
152
153 return result, resp, nil
154 }
155
156
157 type IssuesSearchResult struct {
158 Total *int `json:"total_count,omitempty"`
159 IncompleteResults *bool `json:"incomplete_results,omitempty"`
160 Issues []*Issue `json:"items,omitempty"`
161 }
162
163
164
165
166 func (s *SearchService) Issues(ctx context.Context, query string, opts *SearchOptions) (*IssuesSearchResult, *Response, error) {
167 result := new(IssuesSearchResult)
168 resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opts, result)
169 if err != nil {
170 return nil, resp, err
171 }
172
173 return result, resp, nil
174 }
175
176
177 type UsersSearchResult struct {
178 Total *int `json:"total_count,omitempty"`
179 IncompleteResults *bool `json:"incomplete_results,omitempty"`
180 Users []*User `json:"items,omitempty"`
181 }
182
183
184
185
186 func (s *SearchService) Users(ctx context.Context, query string, opts *SearchOptions) (*UsersSearchResult, *Response, error) {
187 result := new(UsersSearchResult)
188 resp, err := s.search(ctx, "users", &searchParameters{Query: query}, opts, result)
189 if err != nil {
190 return nil, resp, err
191 }
192
193 return result, resp, nil
194 }
195
196
197 type Match struct {
198 Text *string `json:"text,omitempty"`
199 Indices []int `json:"indices,omitempty"`
200 }
201
202
203 type TextMatch struct {
204 ObjectURL *string `json:"object_url,omitempty"`
205 ObjectType *string `json:"object_type,omitempty"`
206 Property *string `json:"property,omitempty"`
207 Fragment *string `json:"fragment,omitempty"`
208 Matches []*Match `json:"matches,omitempty"`
209 }
210
211 func (tm TextMatch) String() string {
212 return Stringify(tm)
213 }
214
215
216 type CodeSearchResult struct {
217 Total *int `json:"total_count,omitempty"`
218 IncompleteResults *bool `json:"incomplete_results,omitempty"`
219 CodeResults []*CodeResult `json:"items,omitempty"`
220 }
221
222
223 type CodeResult struct {
224 Name *string `json:"name,omitempty"`
225 Path *string `json:"path,omitempty"`
226 SHA *string `json:"sha,omitempty"`
227 HTMLURL *string `json:"html_url,omitempty"`
228 Repository *Repository `json:"repository,omitempty"`
229 TextMatches []*TextMatch `json:"text_matches,omitempty"`
230 }
231
232 func (c CodeResult) String() string {
233 return Stringify(c)
234 }
235
236
237
238
239 func (s *SearchService) Code(ctx context.Context, query string, opts *SearchOptions) (*CodeSearchResult, *Response, error) {
240 result := new(CodeSearchResult)
241 resp, err := s.search(ctx, "code", &searchParameters{Query: query}, opts, result)
242 if err != nil {
243 return nil, resp, err
244 }
245
246 return result, resp, nil
247 }
248
249
250 type LabelsSearchResult struct {
251 Total *int `json:"total_count,omitempty"`
252 IncompleteResults *bool `json:"incomplete_results,omitempty"`
253 Labels []*LabelResult `json:"items,omitempty"`
254 }
255
256
257 type LabelResult struct {
258 ID *int64 `json:"id,omitempty"`
259 URL *string `json:"url,omitempty"`
260 Name *string `json:"name,omitempty"`
261 Color *string `json:"color,omitempty"`
262 Default *bool `json:"default,omitempty"`
263 Description *string `json:"description,omitempty"`
264 Score *float64 `json:"score,omitempty"`
265 }
266
267 func (l LabelResult) String() string {
268 return Stringify(l)
269 }
270
271
272
273
274 func (s *SearchService) Labels(ctx context.Context, repoID int64, query string, opts *SearchOptions) (*LabelsSearchResult, *Response, error) {
275 result := new(LabelsSearchResult)
276 resp, err := s.search(ctx, "labels", &searchParameters{RepositoryID: &repoID, Query: query}, opts, result)
277 if err != nil {
278 return nil, resp, err
279 }
280
281 return result, resp, nil
282 }
283
284
285
286
287
288
289 func (s *SearchService) search(ctx context.Context, searchType string, parameters *searchParameters, opts *SearchOptions, result interface{}) (*Response, error) {
290 params, err := qs.Values(opts)
291 if err != nil {
292 return nil, err
293 }
294
295 if parameters.RepositoryID != nil {
296 params.Set("repository_id", strconv.FormatInt(*parameters.RepositoryID, 10))
297 }
298 params.Set("q", parameters.Query)
299 u := fmt.Sprintf("search/%s?%s", searchType, params.Encode())
300
301 req, err := s.client.NewRequest("GET", u, nil)
302 if err != nil {
303 return nil, err
304 }
305 var acceptHeaders []string
306 switch {
307 case searchType == "commits":
308
309
310 acceptHeaders = append(acceptHeaders, mediaTypeCommitSearchPreview)
311 case searchType == "topics":
312
313
314 acceptHeaders = append(acceptHeaders, mediaTypeTopicsPreview)
315 case searchType == "repositories":
316
317
318 acceptHeaders = append(acceptHeaders, mediaTypeTopicsPreview)
319 case searchType == "issues":
320
321
322 acceptHeaders = append(acceptHeaders, mediaTypeReactionsPreview)
323 }
324
325
326
327 if opts != nil && opts.TextMatch {
328 acceptHeaders = append(acceptHeaders, "application/vnd.github.v3.text-match+json")
329 }
330 req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
331
332 return s.client.Do(ctx, req, result)
333 }
334
View as plain text