Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ const (

// https://developer.github.com/changes/2016-11-28-preview-org-membership/
mediaTypeOrgMembershipPreview = "application/vnd.github.korra-preview+json"

// https://developer.github.com/changes/2017-01-05-commit-search-api/
mediaTypeCommitSearchPreview = "application/vnd.github.cloak-preview+json"
)

// A Client manages communication with the GitHub API.
Expand Down
41 changes: 39 additions & 2 deletions github/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type SearchService service
type SearchOptions struct {
// How to sort the search results. Possible values are:
// - for repositories: stars, fork, updated
// - for commits: author-date, committer-date
// - for code: indexed
// - for issues: comments, created, updated
// - for users: followers, repositories, joined
Expand Down Expand Up @@ -54,6 +55,37 @@ func (s *SearchService) Repositories(query string, opt *SearchOptions) (*Reposit
return result, resp, err
}

// CommitsSearchResult represents the result of a commits search.
type CommitsSearchResult struct {
Total *int `json:"total_count,omitempty"`
IncompleteResults *bool `json:"incomplete_results,omitempty"`
Commits []*CommitResult `json:"items,omitempty"`
}

// CommitResult represents a commit object as returned in commit search endpoint response.
type CommitResult struct {
Hash *string `json:"hash,omitempty"`
Message *string `json:"message,omitempty"`
AuthorID *int `json:"author_id,omitempty"`
AuthorName *string `json:"author_name,omitempty"`
AuthorEmail *string `json:"author_email,omitempty"`
AuthorDate *Timestamp `json:"author_date,omitempty"`
CommitterID *int `json:"committer_id,omitempty"`
CommitterName *string `json:"committer_name,omitempty"`
CommitterEmail *string `json:"committer_email,omitempty"`
CommitterDate *Timestamp `json:"committer_date,omitempty"`
Repository *Repository `json:"repository,omitempty"`
}

// Commits searches commits via various criteria.
//
// GitHub API Docs: https://developer.github.com/v3/search/#search-commits
func (s *SearchService) Commits(query string, opt *SearchOptions) (*CommitsSearchResult, *Response, error) {
result := new(CommitsSearchResult)
resp, err := s.search("commits", query, opt, result)
return result, resp, err
}

// IssuesSearchResult represents the result of an issues search.
type IssuesSearchResult struct {
Total *int `json:"total_count,omitempty"`
Expand Down Expand Up @@ -136,7 +168,7 @@ func (s *SearchService) Code(query string, opt *SearchOptions) (*CodeSearchResul
}

// Helper function that executes search queries against different
// GitHub search types (repositories, code, issues, users)
// GitHub search types (repositories, commits, code, issues, users)
func (s *SearchService) search(searchType string, query string, opt *SearchOptions, result interface{}) (*Response, error) {
params, err := qs.Values(opt)
if err != nil {
Expand All @@ -150,7 +182,12 @@ func (s *SearchService) search(searchType string, query string, opt *SearchOptio
return nil, err
Copy link
Member

@dmitshur dmitshur Jan 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update the documentation for this method. It currently says:

// ...
// GitHub search types (repositories, code, issues, users)

But that's no longer true after your change, there's one more.

}

if opt != nil && opt.TextMatch {
switch {
case searchType == "commits":
// Accept header for search commits preview endpoint
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeCommitSearchPreview)
case opt != nil && opt.TextMatch:
// Accept header defaults to "application/vnd.github.v3+json"
// We change it here to fetch back text-match metadata
req.Header.Set("Accept", "application/vnd.github.v3.text-match+json")
Expand Down
31 changes: 31 additions & 0 deletions github/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,37 @@ func TestSearchService_Repositories(t *testing.T) {
}
}

func TestSearchService_Commits(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/search/commits", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{
"q": "blah",
"sort": "author-date",
"order": "desc",
})

fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"hash":"random_hash1"},{"hash":"random_hash2"}]}`)
})

opts := &SearchOptions{Sort: "author-date", Order: "desc"}
result, _, err := client.Search.Commits("blah", opts)
if err != nil {
t.Errorf("Search.Commits returned error: %v", err)
}

want := &CommitsSearchResult{
Total: Int(4),
IncompleteResults: Bool(false),
Commits: []*CommitResult{{Hash: String("random_hash1")}, {Hash: String("random_hash2")}},
}
if !reflect.DeepEqual(result, want) {
t.Errorf("Search.Commits returned %+v, want %+v", result, want)
}
}

func TestSearchService_Issues(t *testing.T) {
setup()
defer teardown()
Expand Down