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