From e840a8a0e607ab479b7a1e3f7cea264f1b9d0f20 Mon Sep 17 00:00:00 2001 From: Kyle Kelley Date: Sun, 1 Jun 2014 16:54:10 -0500 Subject: [PATCH] Provide text match metadata --- github/issues.go | 4 +++ github/repos.go | 4 +++ github/search.go | 39 ++++++++++++++++++++++++---- github/search_test.go | 59 +++++++++++++++++++++++++++++++++++++++++++ github/users.go | 4 +++ 5 files changed, 105 insertions(+), 5 deletions(-) diff --git a/github/issues.go b/github/issues.go index 27fc8fc..5219040 100644 --- a/github/issues.go +++ b/github/issues.go @@ -34,6 +34,10 @@ type Issue struct { URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` Milestone *Milestone `json:"milestone,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://developer.github.com/v3/search/#text-match-metadata + TextMatches []TextMatch `json:"text_matches,omitempty"` } func (i Issue) String() string { diff --git a/github/repos.go b/github/repos.go index 8d122a8..5203f3e 100644 --- a/github/repos.go +++ b/github/repos.go @@ -91,6 +91,10 @@ type Repository struct { TagsURL *string `json:"tags_url,omitempty"` TreesURL *string `json:"trees_url,omitempty"` TeamsURL *string `json:"teams_url,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://developer.github.com/v3/search/#text-match-metadata + TextMatches []TextMatch `json:"text_matches,omitempty"` } func (r Repository) String() string { diff --git a/github/search.go b/github/search.go index c6438b6..d9e9b41 100644 --- a/github/search.go +++ b/github/search.go @@ -34,6 +34,9 @@ type SearchOptions struct { // desc. Default is desc. Order string `url:"order,omitempty"` + // Whether to retrieve text match metadata with a query + TextMatch bool `url:"-"` + ListOptions } @@ -82,6 +85,25 @@ func (s *SearchService) Users(query string, opt *SearchOptions) (*UsersSearchRes return result, resp, err } +// Match represents a single text match. +type Match struct { + Text *string `json:"text,omitempty"` + Indices []int `json:"indices,omitempty"` +} + +// TextMatch represents a text match for a SearchResult +type TextMatch struct { + ObjectURL *string `json:"object_url,omitempty"` + ObjectType *string `json:"object_type,omitempty"` + Property *string `json:"property,omitempty"` + Fragment *string `json:"fragment,omitempty"` + Matches []Match `json:"matches,omitempty"` +} + +func (tm TextMatch) String() string { + return Stringify(tm) +} + // CodeSearchResult represents the result of an code search. type CodeSearchResult struct { Total *int `json:"total_count,omitempty"` @@ -90,11 +112,12 @@ type CodeSearchResult struct { // CodeResult represents a single search result. type CodeResult struct { - Name *string `json:"name,omitempty"` - Path *string `json:"path,omitempty"` - SHA *string `json:"sha,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - Repository *Repository `json:"repository,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + SHA *string `json:"sha,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Repository *Repository `json:"repository,omitempty"` + TextMatches []TextMatch `json:"text_matches,omitempty"` } func (c CodeResult) String() string { @@ -125,5 +148,11 @@ func (s *SearchService) search(searchType string, query string, opt *SearchOptio return nil, err } + if 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") + } + return s.client.Do(req, result) } diff --git a/github/search_test.go b/github/search_test.go index ce1b622..225e818 100644 --- a/github/search_test.go +++ b/github/search_test.go @@ -135,3 +135,62 @@ func TestSearchService_Code(t *testing.T) { t.Errorf("Search.Code returned %+v, want %+v", result, want) } } + +func TestSearchService_CodeTextMatch(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/search/code", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + + textMatchResponse := ` + { + "total_count": 1, + "items": [ + { + "name":"gopher1", + "text_matches": [ + { + "fragment": "I'm afraid my friend what you have found\nIs a gopher who lives to feed", + "matches": [ + { + "text": "gopher", + "indices": [ + 14, + 21 + ] + } + ] + } + ] + } + ] + } + ` + + fmt.Fprint(w, textMatchResponse) + }) + + opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}, TextMatch: true} + result, _, err := client.Search.Code("blah", opts) + if err != nil { + t.Errorf("Search.Code returned error: %v", err) + } + + wantedCodeResult := CodeResult{ + Name: String("gopher1"), + TextMatches: []TextMatch{TextMatch{ + Fragment: String("I'm afraid my friend what you have found\nIs a gopher who lives to feed"), + Matches: []Match{Match{Text: String("gopher"), Indices: []int{14, 21}}}, + }, + }, + } + + want := &CodeSearchResult{ + Total: Int(1), + CodeResults: []CodeResult{wantedCodeResult}, + } + if !reflect.DeepEqual(result, want) { + t.Errorf("Search.Code returned %+v, want %+v", result, want) + } +} diff --git a/github/users.go b/github/users.go index 9163418..bd68ac2 100644 --- a/github/users.go +++ b/github/users.go @@ -55,6 +55,10 @@ type User struct { ReposURL *string `json:"repos_url,omitempty"` StarredURL *string `json:"starred_url,omitempty"` SubscriptionsURL *string `json:"subscriptions_url,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://developer.github.com/v3/search/#text-match-metadata + TextMatches []TextMatch `json:"text_matches,omitempty"` } func (u User) String() string {