diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 4252e4d..02ed6e7 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -15,10 +15,6 @@ "Comment": "v3.0.0", "Rev": "2f3112b6f8f18f9df8743cc75ed51da08094ef6a" }, - { - "ImportPath": "github.com/google/go-github/github", - "Rev": "7ea4ee6d222607c11ea86e99a6f6723beeae785d" - }, { "ImportPath": "github.com/google/go-querystring/query", "Rev": "d8840cbb2baa915f4836edda4750050a2c0b7aea" @@ -36,6 +32,10 @@ "ImportPath": "github.com/onsi/gomega", "Comment": "v1.0-28-g8adf9e1", "Rev": "8adf9e1730c55cdc590de7d49766cb2acc88d8f2" + }, + { + "ImportPath": "github.com/zachgersh/go-github/github", + "Rev": "f47a8b33261f10482dfede3cc839c4fcf34da04f" } ] } diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/activity.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/activity.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/activity_events.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_events.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/activity_events.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_events.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/activity_events_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_events_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/activity_events_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_events_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/activity_notifications.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_notifications.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/activity_notifications.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_notifications.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/activity_notifications_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_notifications_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/activity_notifications_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_notifications_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/activity_star.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_star.go similarity index 89% rename from Godeps/_workspace/src/github.com/google/go-github/github/activity_star.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_star.go index 982f24d..fac4f41 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/activity_star.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_star.go @@ -7,6 +7,12 @@ package github import "fmt" +// StarredRepository is returned by ListStarred. +type StarredRepository struct { + StarredAt *Timestamp `json:"starred_at,omitempty"` + Repository *Repository `json:"repo,omitempty"` +} + // ListStargazers lists people who have starred the specified repo. // // GitHub API Docs: https://developer.github.com/v3/activity/starring/#list-stargazers @@ -49,7 +55,7 @@ type ActivityListStarredOptions struct { // will list the starred repositories for the authenticated user. // // GitHub API docs: http://developer.github.com/v3/activity/starring/#list-repositories-being-starred -func (s *ActivityService) ListStarred(user string, opt *ActivityListStarredOptions) ([]Repository, *Response, error) { +func (s *ActivityService) ListStarred(user string, opt *ActivityListStarredOptions) ([]StarredRepository, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/starred", user) @@ -66,7 +72,10 @@ func (s *ActivityService) ListStarred(user string, opt *ActivityListStarredOptio return nil, nil, err } - repos := new([]Repository) + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeStarringPreview) + + repos := new([]StarredRepository) resp, err := s.client.Do(req, repos) if err != nil { return nil, resp, err diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/activity_star_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_star_test.go similarity index 87% rename from Godeps/_workspace/src/github.com/google/go-github/github/activity_star_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_star_test.go index ae33b93..eb2c405 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/activity_star_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_star_test.go @@ -10,6 +10,7 @@ import ( "net/http" "reflect" "testing" + "time" ) func TestActivityService_ListStargazers(t *testing.T) { @@ -42,7 +43,8 @@ func TestActivityService_ListStarred_authenticatedUser(t *testing.T) { mux.HandleFunc("/user/starred", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, `[{"id":1}]`) + testHeader(t, r, "Accept", mediaTypeStarringPreview) + fmt.Fprint(w, `[{"starred_at":"2002-02-10T15:30:00Z","repo":{"id":1}}]`) }) repos, _, err := client.Activity.ListStarred("", nil) @@ -50,7 +52,7 @@ func TestActivityService_ListStarred_authenticatedUser(t *testing.T) { t.Errorf("Activity.ListStarred returned error: %v", err) } - want := []Repository{{ID: Int(1)}} + want := []StarredRepository{{StarredAt: &Timestamp{time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)}, Repository: &Repository{ID: Int(1)}}} if !reflect.DeepEqual(repos, want) { t.Errorf("Activity.ListStarred returned %+v, want %+v", repos, want) } @@ -62,12 +64,13 @@ func TestActivityService_ListStarred_specifiedUser(t *testing.T) { mux.HandleFunc("/users/u/starred", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") + testHeader(t, r, "Accept", mediaTypeStarringPreview) testFormValues(t, r, values{ "sort": "created", "direction": "asc", "page": "2", }) - fmt.Fprint(w, `[{"id":2}]`) + fmt.Fprint(w, `[{"starred_at":"2002-02-10T15:30:00Z","repo":{"id":2}}]`) }) opt := &ActivityListStarredOptions{"created", "asc", ListOptions{Page: 2}} @@ -76,7 +79,7 @@ func TestActivityService_ListStarred_specifiedUser(t *testing.T) { t.Errorf("Activity.ListStarred returned error: %v", err) } - want := []Repository{{ID: Int(2)}} + want := []StarredRepository{{StarredAt: &Timestamp{time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)}, Repository: &Repository{ID: Int(2)}}} if !reflect.DeepEqual(repos, want) { t.Errorf("Activity.ListStarred returned %+v, want %+v", repos, want) } diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/activity_watching.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_watching.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/activity_watching.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_watching.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/activity_watching_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_watching_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/activity_watching_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/activity_watching_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/doc.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/doc.go similarity index 86% rename from Godeps/_workspace/src/github.com/google/go-github/github/doc.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/doc.go index 8dee026..b4ac8e6 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/doc.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/doc.go @@ -28,24 +28,25 @@ Authentication The go-github library does not directly handle authentication. Instead, when creating a new client, pass an http.Client that can handle authentication for -you. The easiest and recommended way to do this is using the goauth2 library, -but you can always use any other library that provides an http.Client. If you -have an OAuth2 access token (for example, a personal API token), you can use it -with the goauth2 using: +you. The easiest and recommended way to do this is using the golang.org/x/oauth2 +library, but you can always use any other library that provides an http.Client. +If you have an OAuth2 access token (for example, a personal API token), you can +use it with the oauth2 library using: - import "code.google.com/p/goauth2/oauth" + import "golang.org/x/oauth2" - // simple OAuth transport if you already have an access token; - // see goauth2 library for full usage - t := &oauth.Transport{ - Token: &oauth.Token{AccessToken: "..."}, + func main() { + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: "... your access token ..."}, + ) + tc := oauth2.NewClient(oauth2.NoContext, ts) + + client := github.NewClient(tc) + + // list all repositories for the authenticated user + repos, _, err := client.Repositories.List("", nil) } - client := github.NewClient(t.Client()) - - // list all repositories for the authenticated user - repos, _, err := client.Repositories.List("", nil) - Note that when using an authenticated Client, all calls made by the client will include the specified OAuth token. Therefore, authenticated clients should almost never be shared between different users. diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/gists.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/gists.go similarity index 93% rename from Godeps/_workspace/src/github.com/google/go-github/github/gists.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/gists.go index 20c3536..a662d35 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/gists.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/gists.go @@ -157,6 +157,24 @@ func (s *GistsService) Get(id string) (*Gist, *Response, error) { return gist, resp, err } +// GetRevision gets a specific revision of a gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/#get-a-specific-revision-of-a-gist +func (s *GistsService) GetRevision(id, sha string) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v/%v", id, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + gist := new(Gist) + resp, err := s.client.Do(req, gist) + if err != nil { + return nil, resp, err + } + + return gist, resp, err +} + // Create a gist for authenticated user. // // GitHub API docs: http://developer.github.com/v3/gists/#create-a-gist diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/gists_comments.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/gists_comments.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/gists_comments.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/gists_comments.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/gists_comments_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/gists_comments_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/gists_comments_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/gists_comments_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/gists_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/gists_test.go similarity index 93% rename from Godeps/_workspace/src/github.com/google/go-github/github/gists_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/gists_test.go index bd755da..5731201 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/gists_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/gists_test.go @@ -146,6 +146,32 @@ func TestGistsService_Get_invalidID(t *testing.T) { testURLParseError(t, err) } +func TestGistsService_GetRevision(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/gists/1/s", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"id": "1"}`) + }) + + gist, _, err := client.Gists.GetRevision("1", "s") + + if err != nil { + t.Errorf("Gists.Get returned error: %v", err) + } + + want := &Gist{ID: String("1")} + if !reflect.DeepEqual(gist, want) { + t.Errorf("Gists.Get returned %+v, want %+v", gist, want) + } +} + +func TestGistsService_GetRevision_invalidID(t *testing.T) { + _, _, err := client.Gists.GetRevision("%", "%") + testURLParseError(t, err) +} + func TestGistsService_Create(t *testing.T) { setup() defer teardown() diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git_blobs.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_blobs.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git_blobs.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_blobs.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git_blobs_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_blobs_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git_blobs_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_blobs_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git_commits.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_commits.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git_commits.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_commits.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git_commits_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_commits_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git_commits_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_commits_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git_refs.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_refs.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git_refs.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_refs.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git_refs_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_refs_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git_refs_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_refs_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git_tags.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_tags.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git_tags.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_tags.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git_tags_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_tags_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git_tags_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_tags_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git_trees.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_trees.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git_trees.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_trees.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/git_trees_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_trees_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/git_trees_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/git_trees_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/github.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/github.go similarity index 92% rename from Godeps/_workspace/src/github.com/google/go-github/github/github.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/github.go index fced107..737c17c 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/github.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/github.go @@ -37,11 +37,15 @@ const ( // Media Type values to access preview APIs - // https://developer.github.com/changes/2014-08-05-team-memberships-api/ - mediaTypeMembershipPreview = "application/vnd.github.the-wasp-preview+json" + // https://developer.github.com/changes/2015-03-09-licenses-api/ + mediaTypeLicensesPreview = "application/vnd.github.drax-preview+json" - // https://developer.github.com/changes/2014-01-09-preview-the-new-deployments-api/ - mediaTypeDeploymentPreview = "application/vnd.github.cannonball-preview+json" + // https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/ + mediaTypeStarringPreview = "application/vnd.github.v3.star+json" + + // https://developer.github.com/changes/2015-06-24-api-enhancements-for-working-with-organization-permissions/ + mediaTypeOrgPermissionPreview = "application/vnd.github.ironman-preview+json" + mediaTypeOrgPermissionRepoPreview = "application/vnd.github.ironman-preview.repository+json" ) // A Client manages communication with the GitHub API. @@ -77,6 +81,7 @@ type Client struct { Repositories *RepositoriesService Search *SearchService Users *UsersService + Licenses *LicensesService } // ListOptions specifies the optional parameters to various List methods that @@ -119,7 +124,7 @@ func addOptions(s string, opt interface{}) (string, error) { // NewClient returns a new GitHub API client. If a nil httpClient is // provided, http.DefaultClient will be used. To use API methods which require // authentication, provide an http.Client that will perform the authentication -// for you (such as that provided by the goauth2 library). +// for you (such as that provided by the golang.org/x/oauth2 library). func NewClient(httpClient *http.Client) *Client { if httpClient == nil { httpClient = http.DefaultClient @@ -138,6 +143,7 @@ func NewClient(httpClient *http.Client) *Client { c.Repositories = &RepositoriesService{client: c} c.Search = &SearchService{client: c} c.Users = &UsersService{client: c} + c.Licenses = &LicensesService{client: c} return c } @@ -219,7 +225,7 @@ type Response struct { Rate } -// newResponse creats a new Response for the provided http.Response. +// newResponse creates a new Response for the provided http.Response. func newResponse(r *http.Response) *Response { response := &Response{Response: r} response.populatePageValues() @@ -333,10 +339,24 @@ type ErrorResponse struct { func (r *ErrorResponse) Error() string { return fmt.Sprintf("%v %v: %d %v %+v", - r.Response.Request.Method, r.Response.Request.URL, + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), r.Response.StatusCode, r.Message, r.Errors) } +// sanitizeURL redacts the client_id and client_secret tokens from the URL which +// may be exposed to the user, specifically in the ErrorResponse error message. +func sanitizeURL(uri *url.URL) *url.URL { + if uri == nil { + return nil + } + params := uri.Query() + if len(params.Get("client_secret")) > 0 { + params.Set("client_secret", "REDACTED") + uri.RawQuery = params.Encode() + } + return uri +} + /* An Error reports more details on an individual error in an ErrorResponse. These are the possible validation error codes: diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/github_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/github_test.go similarity index 97% rename from Godeps/_workspace/src/github.com/google/go-github/github/github_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/github_test.go index 0fb2c18..05c817b 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/github_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/github_test.go @@ -430,6 +430,25 @@ func TestDo_rateLimit_errorResponse(t *testing.T) { } } +func TestSanitizeURL(t *testing.T) { + tests := []struct { + in, want string + }{ + {"/?a=b", "/?a=b"}, + {"/?a=b&client_secret=secret", "/?a=b&client_secret=REDACTED"}, + {"/?a=b&client_id=id&client_secret=secret", "/?a=b&client_id=id&client_secret=REDACTED"}, + } + + for _, tt := range tests { + inURL, _ := url.Parse(tt.in) + want, _ := url.Parse(tt.want) + + if got := sanitizeURL(inURL); !reflect.DeepEqual(got, want) { + t.Errorf("sanitizeURL(%v) returned %v, want %v", tt.in, got, want) + } + } +} + func TestCheckResponse(t *testing.T) { res := &http.Response{ Request: &http.Request{}, diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/gitignore.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/gitignore.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/gitignore.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/gitignore.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/gitignore_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/gitignore_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/gitignore_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/gitignore_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues.go similarity index 95% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues.go index f92df6b..05f5477 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/issues.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues.go @@ -49,12 +49,12 @@ func (i Issue) String() string { // It is separate from Issue above because otherwise Labels // and Assignee fail to serialize to the correct JSON. type IssueRequest struct { - Title *string `json:"title,omitempty"` - Body *string `json:"body,omitempty"` - Labels []string `json:"labels,omitempty"` - Assignee *string `json:"assignee,omitempty"` - State *string `json:"state,omitempty"` - Milestone *int `json:"milestone,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + Labels *[]string `json:"labels,omitempty"` + Assignee *string `json:"assignee,omitempty"` + State *string `json:"state,omitempty"` + Milestone *int `json:"milestone,omitempty"` } // IssueListOptions specifies the optional parameters to the IssuesService.List @@ -72,7 +72,7 @@ type IssueListOptions struct { Labels []string `url:"labels,comma,omitempty"` // Sort specifies how to sort issues. Possible values are: created, updated, - // and comments. Default value is "assigned". + // and comments. Default value is "created". Sort string `url:"sort,omitempty"` // Direction in which to sort issues. Possible values are: asc, desc. @@ -166,7 +166,7 @@ type IssueListByRepoOptions struct { Labels []string `url:"labels,omitempty,comma"` // Sort specifies how to sort issues. Possible values are: created, updated, - // and comments. Default value is "assigned". + // and comments. Default value is "created". Sort string `url:"sort,omitempty"` // Direction in which to sort issues. Possible values are: asc, desc. diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_assignees.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_assignees.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_assignees.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_assignees.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_assignees_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_assignees_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_assignees_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_assignees_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_comments.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_comments.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_comments.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_comments.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_comments_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_comments_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_comments_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_comments_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_events.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_events.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_events.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_events.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_events_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_events_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_events_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_events_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_labels.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_labels.go similarity index 99% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_labels.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_labels.go index 5ad25c1..88f9f3f 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/issues_labels.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_labels.go @@ -7,7 +7,7 @@ package github import "fmt" -// Label represents a GitHib label on an Issue +// Label represents a GitHub label on an Issue type Label struct { URL *string `json:"url,omitempty"` Name *string `json:"name,omitempty"` diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_labels_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_labels_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_labels_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_labels_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_milestones.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_milestones.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_milestones.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_milestones.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_milestones_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_milestones_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_milestones_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_milestones_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/issues_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_test.go similarity index 99% rename from Godeps/_workspace/src/github.com/google/go-github/github/issues_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_test.go index 090cf1b..f69efd3 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/issues_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/issues_test.go @@ -176,7 +176,7 @@ func TestIssuesService_Create(t *testing.T) { Title: String("t"), Body: String("b"), Assignee: String("a"), - Labels: []string{"l1", "l2"}, + Labels: &[]string{"l1", "l2"}, } mux.HandleFunc("/repos/o/r/issues", func(w http.ResponseWriter, r *http.Request) { diff --git a/Godeps/_workspace/src/github.com/zachgersh/go-github/github/licenses.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/licenses.go new file mode 100644 index 0000000..fb2fb5a --- /dev/null +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/licenses.go @@ -0,0 +1,81 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "fmt" + +// LicensesService handles communication with the license related +// methods of the GitHub API. +// +// GitHub API docs: http://developer.github.com/v3/pulls/ +type LicensesService struct { + client *Client +} + +// License represents an open source license. +type License struct { + Key *string `json:"key,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + + HTMLURL *string `json:"html_url,omitempty"` + Featured *bool `json:"featured,omitempty"` + Description *string `json:"description,omitempty"` + Category *string `json:"category,omitempty"` + Implementation *string `json:"implementation,omitempty"` + Required *[]string `json:"required,omitempty"` + Permitted *[]string `json:"permitted,omitempty"` + Forbidden *[]string `json:"forbidden,omitempty"` + Body *string `json:"body,omitempty"` +} + +func (l License) String() string { + return Stringify(l) +} + +// List popular open source licenses. +// +// GitHub API docs: https://developer.github.com/v3/licenses/#list-all-licenses +func (s *LicensesService) List() ([]License, *Response, error) { + req, err := s.client.NewRequest("GET", "licenses", nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeLicensesPreview) + + licenses := new([]License) + resp, err := s.client.Do(req, licenses) + if err != nil { + return nil, resp, err + } + + return *licenses, resp, err +} + +// Get extended metadata for one license. +// +// GitHub API docs: https://developer.github.com/v3/licenses/#get-an-individual-license +func (s *LicensesService) Get(licenseName string) (*License, *Response, error) { + u := fmt.Sprintf("licenses/%s", licenseName) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeLicensesPreview) + + license := new(License) + resp, err := s.client.Do(req, license) + if err != nil { + return nil, resp, err + } + + return license, resp, err +} diff --git a/Godeps/_workspace/src/github.com/zachgersh/go-github/github/licenses_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/licenses_test.go new file mode 100644 index 0000000..dfecfeb --- /dev/null +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/licenses_test.go @@ -0,0 +1,64 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "fmt" + "net/http" + "reflect" + "testing" +) + +func TestLicensesService_List(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/licenses", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testHeader(t, r, "Accept", mediaTypeLicensesPreview) + fmt.Fprint(w, `[{"key":"mit","name":"MIT","url":"https://api.github.com/licenses/mit"}]`) + }) + + licenses, _, err := client.Licenses.List() + if err != nil { + t.Errorf("Licenses.List returned error: %v", err) + } + + want := []License{{ + Key: String("mit"), + Name: String("MIT"), + URL: String("https://api.github.com/licenses/mit"), + }} + if !reflect.DeepEqual(licenses, want) { + t.Errorf("Licenses.List returned %+v, want %+v", licenses, want) + } +} + +func TestLicensesService_Get(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/licenses/mit", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testHeader(t, r, "Accept", mediaTypeLicensesPreview) + fmt.Fprint(w, `{"key":"mit","name":"MIT"}`) + }) + + license, _, err := client.Licenses.Get("mit") + if err != nil { + t.Errorf("Licenses.Get returned error: %v", err) + } + + want := &License{Key: String("mit"), Name: String("MIT")} + if !reflect.DeepEqual(license, want) { + t.Errorf("Licenses.Get returned %+v, want %+v", license, want) + } +} + +func TestLicensesService_Get_invalidTemplate(t *testing.T) { + _, _, err := client.Licenses.Get("%") + testURLParseError(t, err) +} diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/misc.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/misc.go similarity index 80% rename from Godeps/_workspace/src/github.com/google/go-github/github/misc.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/misc.go index 4a9bb99..66e7f52 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/misc.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/misc.go @@ -98,6 +98,10 @@ type APIMeta struct { // username and password, sudo mode, and two-factor authentication are // not supported on these servers.) VerifiablePasswordAuthentication *bool `json:"verifiable_password_authentication,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub Pages websites. + Pages []string `json:"pages,omitempty"` } // APIMeta returns information about GitHub.com, the service. Or, if you access @@ -159,3 +163,35 @@ func (c *Client) Zen() (string, *Response, error) { return buf.String(), resp, nil } + +// ServiceHook represents a hook that has configuration settings, a list of +// available events, and default events. +type ServiceHook struct { + Name *string `json:"name,omitempty"` + Events []string `json:"events,omitempty"` + SupportedEvents []string `json:"supported_events,omitempty"` + Schema [][]string `json:"schema,omitempty"` +} + +func (s *ServiceHook) String() string { + return Stringify(s) +} + +// ListServiceHooks lists all of the available service hooks. +// +// GitHub API docs: https://developer.github.com/webhooks/#services +func (c *Client) ListServiceHooks() ([]ServiceHook, *Response, error) { + u := "hooks" + req, err := c.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hooks := new([]ServiceHook) + resp, err := c.Do(req, hooks) + if err != nil { + return nil, resp, err + } + + return *hooks, resp, err +} diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/misc_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/misc_test.go similarity index 77% rename from Godeps/_workspace/src/github.com/google/go-github/github/misc_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/misc_test.go index 33c3db6..8ca58d2 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/misc_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/misc_test.go @@ -72,7 +72,7 @@ func TestAPIMeta(t *testing.T) { mux.HandleFunc("/meta", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, `{"hooks":["h"], "git":["g"], "verifiable_password_authentication": true}`) + fmt.Fprint(w, `{"hooks":["h"], "git":["g"], "pages":["p"], "verifiable_password_authentication": true}`) }) meta, _, err := client.APIMeta() @@ -83,6 +83,7 @@ func TestAPIMeta(t *testing.T) { want := &APIMeta{ Hooks: []string{"h"}, Git: []string{"g"}, + Pages: []string{"p"}, VerifiablePasswordAuthentication: Bool(true), } if !reflect.DeepEqual(want, meta) { @@ -135,3 +136,35 @@ func TestZen(t *testing.T) { t.Errorf("Zen returned %+v, want %+v", got, want) } } + +func TestRepositoriesService_ListServiceHooks(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/hooks", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[{ + "name":"n", + "events":["e"], + "supported_events":["s"], + "schema":[ + ["a", "b"] + ] + }]`) + }) + + hooks, _, err := client.Repositories.ListServiceHooks() + if err != nil { + t.Errorf("Repositories.ListHooks returned error: %v", err) + } + + want := []ServiceHook{{ + Name: String("n"), + Events: []string{"e"}, + SupportedEvents: []string{"s"}, + Schema: [][]string{{"a", "b"}}, + }} + if !reflect.DeepEqual(hooks, want) { + t.Errorf("Repositories.ListServiceHooks returned %+v, want %+v", hooks, want) + } +} diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/orgs.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/orgs.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs.go diff --git a/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_hooks.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_hooks.go new file mode 100644 index 0000000..3e7ad40 --- /dev/null +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_hooks.go @@ -0,0 +1,104 @@ +// Copyright 2015 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "fmt" + +// ListHooks lists all Hooks for the specified organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#list-hooks +func (s *OrganizationsService) ListHooks(org string, opt *ListOptions) ([]Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks", org) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hooks := new([]Hook) + resp, err := s.client.Do(req, hooks) + if err != nil { + return nil, resp, err + } + + return *hooks, resp, err +} + +// GetHook returns a single specified Hook. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#get-single-hook +func (s *OrganizationsService) GetHook(org string, id int) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + hook := new(Hook) + resp, err := s.client.Do(req, hook) + return hook, resp, err +} + +// CreateHook creates a Hook for the specified org. +// Name and Config are required fields. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#create-a-hook +func (s *OrganizationsService) CreateHook(org string, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks", org) + req, err := s.client.NewRequest("POST", u, hook) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, err +} + +// EditHook updates a specified Hook. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#edit-a-hook +func (s *OrganizationsService) EditHook(org string, id int, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, nil, err + } + h := new(Hook) + resp, err := s.client.Do(req, h) + return h, resp, err +} + +// PingHook triggers a 'ping' event to be sent to the Hook. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#ping-a-hook +func (s *OrganizationsService) PingHook(org string, id int) (*Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(req, nil) +} + +// DeleteHook deletes a specified Hook. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#delete-a-hook +func (s *OrganizationsService) DeleteHook(org string, id int) (*Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(req, nil) +} diff --git a/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_hooks_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_hooks_test.go new file mode 100644 index 0000000..1ebc07d --- /dev/null +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_hooks_test.go @@ -0,0 +1,134 @@ +// Copyright 2015 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "encoding/json" + "fmt" + "net/http" + "reflect" + "testing" +) + +func TestOrganizationsService_ListHooks(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/hooks", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testFormValues(t, r, values{"page": "2"}) + fmt.Fprint(w, `[{"id":1}, {"id":2}]`) + }) + + opt := &ListOptions{Page: 2} + + hooks, _, err := client.Organizations.ListHooks("o", opt) + if err != nil { + t.Errorf("Organizations.ListHooks returned error: %v", err) + } + + want := []Hook{{ID: Int(1)}, {ID: Int(2)}} + if !reflect.DeepEqual(hooks, want) { + t.Errorf("Organizations.ListHooks returned %+v, want %+v", hooks, want) + } +} + +func TestOrganizationsService_ListHooks_invalidOrg(t *testing.T) { + _, _, err := client.Organizations.ListHooks("%", nil) + testURLParseError(t, err) +} + +func TestOrganizationsService_GetHook(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/hooks/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"id":1}`) + }) + + hook, _, err := client.Organizations.GetHook("o", 1) + if err != nil { + t.Errorf("Organizations.GetHook returned error: %v", err) + } + + want := &Hook{ID: Int(1)} + if !reflect.DeepEqual(hook, want) { + t.Errorf("Organizations.GetHook returned %+v, want %+v", hook, want) + } +} + +func TestOrganizationsService_GetHook_invalidOrg(t *testing.T) { + _, _, err := client.Organizations.GetHook("%", 1) + testURLParseError(t, err) +} + +func TestOrganizationsService_EditHook(t *testing.T) { + setup() + defer teardown() + + input := &Hook{Name: String("t")} + + mux.HandleFunc("/orgs/o/hooks/1", func(w http.ResponseWriter, r *http.Request) { + v := new(Hook) + json.NewDecoder(r.Body).Decode(v) + + testMethod(t, r, "PATCH") + if !reflect.DeepEqual(v, input) { + t.Errorf("Request body = %+v, want %+v", v, input) + } + + fmt.Fprint(w, `{"id":1}`) + }) + + hook, _, err := client.Organizations.EditHook("o", 1, input) + if err != nil { + t.Errorf("Organizations.EditHook returned error: %v", err) + } + + want := &Hook{ID: Int(1)} + if !reflect.DeepEqual(hook, want) { + t.Errorf("Organizations.EditHook returned %+v, want %+v", hook, want) + } +} + +func TestOrganizationsService_EditHook_invalidOrg(t *testing.T) { + _, _, err := client.Organizations.EditHook("%", 1, nil) + testURLParseError(t, err) +} + +func TestOrganizationsService_PingHook(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/hooks/1/pings", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + }) + + _, err := client.Organizations.PingHook("o", 1) + if err != nil { + t.Errorf("Organizations.PingHook returned error: %v", err) + } +} + +func TestOrganizationsService_DeleteHook(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/hooks/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + }) + + _, err := client.Organizations.DeleteHook("o", 1) + if err != nil { + t.Errorf("Organizations.DeleteHook returned error: %v", err) + } +} + +func TestOrganizationsService_DeleteHook_invalidOrg(t *testing.T) { + _, err := client.Organizations.DeleteHook("%", 1) + testURLParseError(t, err) +} diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/orgs_members.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_members.go similarity index 70% rename from Godeps/_workspace/src/github.com/google/go-github/github/orgs_members.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_members.go index ae6f579..554cb1d 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/orgs_members.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_members.go @@ -15,7 +15,16 @@ type Membership struct { // Possible values are: "active", "pending" State *string `json:"state,omitempty"` - // TODO(willnorris): add docs + // Role identifies the user's role within the organization or team. + // Possible values for organization membership: + // member - non-owner organization member + // admin - organization owner + // + // Possible values for team membership are: + // member - a normal member of the team + // maintainer - a team maintainer. Able to add/remove other team + // members, promote other team members to team + // maintainer, and edit the team’s name and description Role *string `json:"role,omitempty"` // For organization membership, the API URL of the organization. @@ -43,6 +52,15 @@ type ListMembersOptions struct { // 2fa_disabled, all. Default is "all". Filter string `url:"filter,omitempty"` + // Role filters memebers returned by their role in the organization. + // Possible values are: + // all - all members of the organization, regardless of role + // admin - organization owners + // member - non-organization members + // + // Default is "all". + Role string `url:"role,omitempty"` + ListOptions } @@ -68,6 +86,10 @@ func (s *OrganizationsService) ListMembers(org string, opt *ListMembersOptions) return nil, nil, err } + if opt != nil && opt.Role != "" { + req.Header.Set("Accept", mediaTypeOrgPermissionPreview) + } + members := new([]User) resp, err := s.client.Do(req, members) if err != nil { @@ -120,7 +142,8 @@ func (s *OrganizationsService) RemoveMember(org, user string) (*Response, error) return s.client.Do(req, nil) } -// PublicizeMembership publicizes a user's membership in an organization. +// PublicizeMembership publicizes a user's membership in an organization. (A +// user cannot publicize the membership for another user.) // // GitHub API docs: http://developer.github.com/v3/orgs/members/#publicize-a-users-membership func (s *OrganizationsService) PublicizeMembership(org, user string) (*Response, error) { @@ -171,9 +194,6 @@ func (s *OrganizationsService) ListOrgMemberships(opt *ListOrgMembershipsOptions return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeMembershipPreview) - var memberships []Membership resp, err := s.client.Do(req, &memberships) if err != nil { @@ -183,20 +203,25 @@ func (s *OrganizationsService) ListOrgMemberships(opt *ListOrgMembershipsOptions return memberships, resp, err } -// GetOrgMembership gets the membership for the authenticated user for the -// specified organization. +// GetOrgMembership gets the membership for a user in a specified organization. +// Passing an empty string for user will get the membership for the +// authenticated user. // +// GitHub API docs: https://developer.github.com/v3/orgs/members/#get-organization-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#get-your-organization-membership -func (s *OrganizationsService) GetOrgMembership(org string) (*Membership, *Response, error) { - u := fmt.Sprintf("user/memberships/orgs/%v", org) +func (s *OrganizationsService) GetOrgMembership(user, org string) (*Membership, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("orgs/%v/memberships/%v", org, user) + } else { + u = fmt.Sprintf("user/memberships/orgs/%v", org) + } + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeMembershipPreview) - membership := new(Membership) resp, err := s.client.Do(req, membership) if err != nil { @@ -206,20 +231,25 @@ func (s *OrganizationsService) GetOrgMembership(org string) (*Membership, *Respo return membership, resp, err } -// EditOrgMembership edits the membership for the authenticated user for the -// specified organization. +// EditOrgMembership edits the membership for user in specified organization. +// Passing an empty string for user will edit the membership for the +// authenticated user. // +// GitHub API docs: https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#edit-your-organization-membership -func (s *OrganizationsService) EditOrgMembership(org string, membership *Membership) (*Membership, *Response, error) { - u := fmt.Sprintf("user/memberships/orgs/%v", org) +func (s *OrganizationsService) EditOrgMembership(user, org string, membership *Membership) (*Membership, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("orgs/%v/memberships/%v", org, user) + } else { + u = fmt.Sprintf("user/memberships/orgs/%v", org) + } + req, err := s.client.NewRequest("PATCH", u, membership) if err != nil { return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeMembershipPreview) - m := new(Membership) resp, err := s.client.Do(req, m) if err != nil { @@ -228,3 +258,17 @@ func (s *OrganizationsService) EditOrgMembership(org string, membership *Members return m, resp, err } + +// RemoveOrgMembership removes user from the specified organization. If the +// user has been invited to the organization, this will cancel their invitation. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-organization-membership +func (s *OrganizationsService) RemoveOrgMembership(user, org string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/memberships/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/orgs_members_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_members_test.go similarity index 77% rename from Godeps/_workspace/src/github.com/google/go-github/github/orgs_members_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_members_test.go index 85cb987..973e3aa 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/orgs_members_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_members_test.go @@ -19,8 +19,10 @@ func TestOrganizationsService_ListMembers(t *testing.T) { mux.HandleFunc("/orgs/o/members", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") + testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview) testFormValues(t, r, values{ "filter": "2fa_disabled", + "role": "admin", "page": "2", }) fmt.Fprint(w, `[{"id":1}]`) @@ -29,6 +31,7 @@ func TestOrganizationsService_ListMembers(t *testing.T) { opt := &ListMembersOptions{ PublicOnly: false, Filter: "2fa_disabled", + Role: "admin", ListOptions: ListOptions{Page: 2}, } members, _, err := client.Organizations.ListMembers("o", opt) @@ -217,7 +220,6 @@ func TestOrganizationsService_ListOrgMemberships(t *testing.T) { mux.HandleFunc("/user/memberships/orgs", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - testHeader(t, r, "Accept", mediaTypeMembershipPreview) testFormValues(t, r, values{ "state": "active", "page": "2", @@ -240,17 +242,16 @@ func TestOrganizationsService_ListOrgMemberships(t *testing.T) { } } -func TestOrganizationsService_GetOrgMembership(t *testing.T) { +func TestOrganizationsService_GetOrgMembership_AuthenticatedUser(t *testing.T) { setup() defer teardown() mux.HandleFunc("/user/memberships/orgs/o", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - testHeader(t, r, "Accept", mediaTypeMembershipPreview) fmt.Fprint(w, `{"url":"u"}`) }) - membership, _, err := client.Organizations.GetOrgMembership("o") + membership, _, err := client.Organizations.GetOrgMembership("", "o") if err != nil { t.Errorf("Organizations.GetOrgMembership returned error: %v", err) } @@ -261,7 +262,27 @@ func TestOrganizationsService_GetOrgMembership(t *testing.T) { } } -func TestOrganizationsService_EditOrgMembership(t *testing.T) { +func TestOrganizationsService_GetOrgMembership_SpecifiedUser(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"url":"u"}`) + }) + + membership, _, err := client.Organizations.GetOrgMembership("u", "o") + if err != nil { + t.Errorf("Organizations.GetOrgMembership returned error: %v", err) + } + + want := &Membership{URL: String("u")} + if !reflect.DeepEqual(membership, want) { + t.Errorf("Organizations.GetOrgMembership returned %+v, want %+v", membership, want) + } +} + +func TestOrganizationsService_EditOrgMembership_AuthenticatedUser(t *testing.T) { setup() defer teardown() @@ -272,7 +293,6 @@ func TestOrganizationsService_EditOrgMembership(t *testing.T) { json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") - testHeader(t, r, "Accept", mediaTypeMembershipPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } @@ -280,7 +300,7 @@ func TestOrganizationsService_EditOrgMembership(t *testing.T) { fmt.Fprint(w, `{"url":"u"}`) }) - membership, _, err := client.Organizations.EditOrgMembership("o", input) + membership, _, err := client.Organizations.EditOrgMembership("", "o", input) if err != nil { t.Errorf("Organizations.EditOrgMembership returned error: %v", err) } @@ -290,3 +310,47 @@ func TestOrganizationsService_EditOrgMembership(t *testing.T) { t.Errorf("Organizations.EditOrgMembership returned %+v, want %+v", membership, want) } } + +func TestOrganizationsService_EditOrgMembership_SpecifiedUser(t *testing.T) { + setup() + defer teardown() + + input := &Membership{State: String("active")} + + mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) { + v := new(Membership) + json.NewDecoder(r.Body).Decode(v) + + testMethod(t, r, "PATCH") + if !reflect.DeepEqual(v, input) { + t.Errorf("Request body = %+v, want %+v", v, input) + } + + fmt.Fprint(w, `{"url":"u"}`) + }) + + membership, _, err := client.Organizations.EditOrgMembership("u", "o", input) + if err != nil { + t.Errorf("Organizations.EditOrgMembership returned error: %v", err) + } + + want := &Membership{URL: String("u")} + if !reflect.DeepEqual(membership, want) { + t.Errorf("Organizations.EditOrgMembership returned %+v, want %+v", membership, want) + } +} + +func TestOrganizationsService_RemoveOrgMembership(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + w.WriteHeader(http.StatusNoContent) + }) + + _, err := client.Organizations.RemoveOrgMembership("u", "o") + if err != nil { + t.Errorf("Organizations.RemoveOrgMembership returned error: %v", err) + } +} diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/orgs_teams.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_teams.go similarity index 70% rename from Godeps/_workspace/src/github.com/google/go-github/github/orgs_teams.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_teams.go index 0c0f7db..858c545 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/orgs_teams.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_teams.go @@ -10,11 +10,25 @@ import "fmt" // Team represents a team within a GitHub organization. Teams are used to // manage access to an organization's repositories. type Team struct { - ID *int `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - URL *string `json:"url,omitempty"` - Slug *string `json:"slug,omitempty"` - Permission *string `json:"permission,omitempty"` + ID *int `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + Slug *string `json:"slug,omitempty"` + + // Permission is deprecated when creating or editing a team in an org + // using the new GitHub permission model. It no longer identifies the + // permission a team has on its repos, but only specifies the default + // permission a repo is initially added with. Avoid confusion by + // specifying a permission value when calling AddTeamRepo. + Permission *string `json:"permission,omitempty"` + + // Privacy identifies the level of privacy this team should have. + // Possible values are: + // secret - only visible to organization owners and members of this team + // closed - visible to all members of this organization + // Default is "secret". + Privacy *string `json:"privacy,omitempty"` + MembersCount *int `json:"members_count,omitempty"` ReposCount *int `json:"repos_count,omitempty"` Organization *Organization `json:"organization,omitempty"` @@ -77,6 +91,10 @@ func (s *OrganizationsService) CreateTeam(org string, team *Team) (*Team, *Respo return nil, nil, err } + if team.Privacy != nil { + req.Header.Set("Accept", mediaTypeOrgPermissionPreview) + } + t := new(Team) resp, err := s.client.Do(req, t) if err != nil { @@ -96,6 +114,10 @@ func (s *OrganizationsService) EditTeam(id int, team *Team) (*Team, *Response, e return nil, nil, err } + if team.Privacy != nil { + req.Header.Set("Accept", mediaTypeOrgPermissionPreview) + } + t := new(Team) resp, err := s.client.Do(req, t) if err != nil { @@ -118,11 +140,21 @@ func (s *OrganizationsService) DeleteTeam(team int) (*Response, error) { return s.client.Do(req, nil) } +// OrganizationListTeamMembersOptions specifies the optional parameters to the +// OrganizationsService.ListTeamMembers method. +type OrganizationListTeamMembersOptions struct { + // Role filters members returned by their role in the team. Possible + // values are "all", "member", "maintainer". Default is "all". + Role string `url:"role,omitempty"` + + ListOptions +} + // ListTeamMembers lists all of the users who are members of the specified // team. // // GitHub API docs: http://developer.github.com/v3/orgs/teams/#list-team-members -func (s *OrganizationsService) ListTeamMembers(team int, opt *ListOptions) ([]User, *Response, error) { +func (s *OrganizationsService) ListTeamMembers(team int, opt *OrganizationListTeamMembersOptions) ([]User, *Response, error) { u := fmt.Sprintf("teams/%v/members", team) u, err := addOptions(u, opt) if err != nil { @@ -134,6 +166,10 @@ func (s *OrganizationsService) ListTeamMembers(team int, opt *ListOptions) ([]Us return nil, nil, err } + if opt != nil && opt.Role != "" { + req.Header.Set("Accept", mediaTypeOrgPermissionPreview) + } + members := new([]User) resp, err := s.client.Do(req, members) if err != nil { @@ -158,32 +194,6 @@ func (s *OrganizationsService) IsTeamMember(team int, user string) (bool, *Respo return member, resp, err } -// AddTeamMember adds a user to a team. -// -// GitHub API docs: http://developer.github.com/v3/orgs/teams/#add-team-member -func (s *OrganizationsService) AddTeamMember(team int, user string) (*Response, error) { - u := fmt.Sprintf("teams/%v/members/%v", team, user) - req, err := s.client.NewRequest("PUT", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) -} - -// RemoveTeamMember removes a user from a team. -// -// GitHub API docs: http://developer.github.com/v3/orgs/teams/#remove-team-member -func (s *OrganizationsService) RemoveTeamMember(team int, user string) (*Response, error) { - u := fmt.Sprintf("teams/%v/members/%v", team, user) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) -} - // ListTeamRepos lists the repositories that the specified team has access to. // // GitHub API docs: http://developer.github.com/v3/orgs/teams/#list-team-repos @@ -208,19 +218,40 @@ func (s *OrganizationsService) ListTeamRepos(team int, opt *ListOptions) ([]Repo return *repos, resp, err } -// IsTeamRepo checks if a team manages the specified repository. +// IsTeamRepo checks if a team manages the specified repository. If the +// repository is managed by team, a Repository is returned which includes the +// permissions team has for that repo. // // GitHub API docs: http://developer.github.com/v3/orgs/teams/#get-team-repo -func (s *OrganizationsService) IsTeamRepo(team int, owner string, repo string) (bool, *Response, error) { +func (s *OrganizationsService) IsTeamRepo(team int, owner string, repo string) (*Repository, *Response, error) { u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { - return false, nil, err + return nil, nil, err } - resp, err := s.client.Do(req, nil) - manages, err := parseBoolResponse(err) - return manages, resp, err + req.Header.Set("Accept", mediaTypeOrgPermissionRepoPreview) + + repository := new(Repository) + resp, err := s.client.Do(req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, err +} + +// OrganizationAddTeamRepoOptions specifies the optional parameters to the +// OrganizationsService.AddTeamRepo method. +type OrganizationAddTeamRepoOptions struct { + // Permission specifies the permission to grant the team on this repository. + // Possible values are: + // pull - team members can pull, but not push to or administer this repository + // push - team members can pull and push, but not administer this repository + // admin - team members can pull, push and administer this repository + // + // If not specified, the team's permission attribute will be used. + Permission string `json:"permission,omitempty"` } // AddTeamRepo adds a repository to be managed by the specified team. The @@ -228,13 +259,17 @@ func (s *OrganizationsService) IsTeamRepo(team int, owner string, repo string) ( // belongs, or a direct fork of a repository owned by the organization. // // GitHub API docs: http://developer.github.com/v3/orgs/teams/#add-team-repo -func (s *OrganizationsService) AddTeamRepo(team int, owner string, repo string) (*Response, error) { +func (s *OrganizationsService) AddTeamRepo(team int, owner string, repo string, opt *OrganizationAddTeamRepoOptions) (*Response, error) { u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) - req, err := s.client.NewRequest("PUT", u, nil) + req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, err } + if opt != nil { + req.Header.Set("Accept", mediaTypeOrgPermissionPreview) + } + return s.client.Do(req, nil) } @@ -286,9 +321,6 @@ func (s *OrganizationsService) GetTeamMembership(team int, user string) (*Member return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeMembershipPreview) - t := new(Membership) resp, err := s.client.Do(req, t) if err != nil { @@ -298,6 +330,20 @@ func (s *OrganizationsService) GetTeamMembership(team int, user string) (*Member return t, resp, err } +// OrganizationAddTeamMembershipOptions does stuff specifies the optional +// parameters to the OrganizationsService.AddTeamMembership method. +type OrganizationAddTeamMembershipOptions struct { + // Role specifies the role the user should have in the team. Possible + // values are: + // member - a normal member of the team + // maintainer - a team maintainer. Able to add/remove other team + // members, promote other team members to team + // maintainer, and edit the team’s name and description + // + // Default value is "member". + Role string `json:"role,omitempty"` +} + // AddTeamMembership adds or invites a user to a team. // // In order to add a membership between a user and a team, the authenticated @@ -316,15 +362,16 @@ func (s *OrganizationsService) GetTeamMembership(team int, user string) (*Member // added as a member of the team. // // GitHub API docs: https://developer.github.com/v3/orgs/teams/#add-team-membership -func (s *OrganizationsService) AddTeamMembership(team int, user string) (*Membership, *Response, error) { +func (s *OrganizationsService) AddTeamMembership(team int, user string, opt *OrganizationAddTeamMembershipOptions) (*Membership, *Response, error) { u := fmt.Sprintf("teams/%v/memberships/%v", team, user) - req, err := s.client.NewRequest("PUT", u, nil) + req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeMembershipPreview) + if opt != nil { + req.Header.Set("Accept", mediaTypeOrgPermissionPreview) + } t := new(Membership) resp, err := s.client.Do(req, t) @@ -345,8 +392,5 @@ func (s *OrganizationsService) RemoveTeamMembership(team int, user string) (*Res return nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeMembershipPreview) - return s.client.Do(req, nil) } diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/orgs_teams_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_teams_test.go similarity index 84% rename from Godeps/_workspace/src/github.com/google/go-github/github/orgs_teams_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_teams_test.go index 1f45e8c..a258137 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/orgs_teams_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_teams_test.go @@ -64,13 +64,14 @@ func TestOrganizationsService_CreateTeam(t *testing.T) { setup() defer teardown() - input := &Team{Name: String("n")} + input := &Team{Name: String("n"), Privacy: String("closed")} mux.HandleFunc("/orgs/o/teams", func(w http.ResponseWriter, r *http.Request) { v := new(Team) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") + testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } @@ -98,13 +99,14 @@ func TestOrganizationsService_EditTeam(t *testing.T) { setup() defer teardown() - input := &Team{Name: String("n")} + input := &Team{Name: String("n"), Privacy: String("closed")} mux.HandleFunc("/teams/1", func(w http.ResponseWriter, r *http.Request) { v := new(Team) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") + testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } @@ -143,11 +145,12 @@ func TestOrganizationsService_ListTeamMembers(t *testing.T) { mux.HandleFunc("/teams/1/members", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - testFormValues(t, r, values{"page": "2"}) + testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview) + testFormValues(t, r, values{"role": "member", "page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) - opt := &ListOptions{Page: 2} + opt := &OrganizationListTeamMembersOptions{Role: "member", ListOptions: ListOptions{Page: 2}} members, _, err := client.Organizations.ListTeamMembers(1, opt) if err != nil { t.Errorf("Organizations.ListTeamMembers returned error: %v", err) @@ -220,46 +223,6 @@ func TestOrganizationsService_IsTeamMember_invalidUser(t *testing.T) { testURLParseError(t, err) } -func TestOrganizationsService_AddTeamMember(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/teams/1/members/u", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "PUT") - w.WriteHeader(http.StatusNoContent) - }) - - _, err := client.Organizations.AddTeamMember(1, "u") - if err != nil { - t.Errorf("Organizations.AddTeamMember returned error: %v", err) - } -} - -func TestOrganizationsService_AddTeamMember_invalidUser(t *testing.T) { - _, err := client.Organizations.AddTeamMember(1, "%") - testURLParseError(t, err) -} - -func TestOrganizationsService_RemoveTeamMember(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/teams/1/members/u", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "DELETE") - w.WriteHeader(http.StatusNoContent) - }) - - _, err := client.Organizations.RemoveTeamMember(1, "u") - if err != nil { - t.Errorf("Organizations.RemoveTeamMember returned error: %v", err) - } -} - -func TestOrganizationsService_RemoveTeamMember_invalidUser(t *testing.T) { - _, err := client.Organizations.RemoveTeamMember(1, "%") - testURLParseError(t, err) -} - func TestOrganizationsService_PublicizeMembership(t *testing.T) { setup() defer teardown() @@ -328,15 +291,18 @@ func TestOrganizationsService_IsTeamRepo_true(t *testing.T) { mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - w.WriteHeader(http.StatusNoContent) + testHeader(t, r, "Accept", mediaTypeOrgPermissionRepoPreview) + fmt.Fprint(w, `{"id":1}`) }) - managed, _, err := client.Organizations.IsTeamRepo(1, "o", "r") + repo, _, err := client.Organizations.IsTeamRepo(1, "o", "r") if err != nil { t.Errorf("Organizations.IsTeamRepo returned error: %v", err) } - if want := true; managed != want { - t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", managed, want) + + want := &Repository{ID: Int(1)} + if !reflect.DeepEqual(repo, want) { + t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", repo, want) } } @@ -349,12 +315,15 @@ func TestOrganizationsService_IsTeamRepo_false(t *testing.T) { w.WriteHeader(http.StatusNotFound) }) - managed, _, err := client.Organizations.IsTeamRepo(1, "o", "r") - if err != nil { - t.Errorf("Organizations.IsTeamRepo returned error: %v", err) + repo, resp, err := client.Organizations.IsTeamRepo(1, "o", "r") + if err == nil { + t.Errorf("Expected HTTP 404 response") } - if want := false; managed != want { - t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", managed, want) + if got, want := resp.Response.StatusCode, http.StatusNotFound; got != want { + t.Errorf("Organizations.IsTeamRepo returned status %d, want %d", got, want) + } + if repo != nil { + t.Errorf("Organizations.IsTeamRepo returned %+v, want nil", repo) } } @@ -367,12 +336,15 @@ func TestOrganizationsService_IsTeamRepo_error(t *testing.T) { http.Error(w, "BadRequest", http.StatusBadRequest) }) - managed, _, err := client.Organizations.IsTeamRepo(1, "o", "r") + repo, resp, err := client.Organizations.IsTeamRepo(1, "o", "r") if err == nil { t.Errorf("Expected HTTP 400 response") } - if want := false; managed != want { - t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", managed, want) + if got, want := resp.Response.StatusCode, http.StatusBadRequest; got != want { + t.Errorf("Organizations.IsTeamRepo returned status %d, want %d", got, want) + } + if repo != nil { + t.Errorf("Organizations.IsTeamRepo returned %+v, want nil", repo) } } @@ -385,12 +357,22 @@ func TestOrganizationsService_AddTeamRepo(t *testing.T) { setup() defer teardown() + opt := &OrganizationAddTeamRepoOptions{Permission: "admin"} + mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) { + v := new(OrganizationAddTeamRepoOptions) + json.NewDecoder(r.Body).Decode(v) + testMethod(t, r, "PUT") + testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview) + if !reflect.DeepEqual(v, opt) { + t.Errorf("Request body = %+v, want %+v", v, opt) + } + w.WriteHeader(http.StatusNoContent) }) - _, err := client.Organizations.AddTeamRepo(1, "o", "r") + _, err := client.Organizations.AddTeamRepo(1, "o", "r", opt) if err != nil { t.Errorf("Organizations.AddTeamRepo returned error: %v", err) } @@ -405,14 +387,14 @@ func TestOrganizationsService_AddTeamRepo_noAccess(t *testing.T) { w.WriteHeader(422) }) - _, err := client.Organizations.AddTeamRepo(1, "o", "r") + _, err := client.Organizations.AddTeamRepo(1, "o", "r", nil) if err == nil { t.Errorf("Expcted error to be returned") } } func TestOrganizationsService_AddTeamRepo_invalidOwner(t *testing.T) { - _, err := client.Organizations.AddTeamRepo(1, "%", "r") + _, err := client.Organizations.AddTeamRepo(1, "%", "r", nil) testURLParseError(t, err) } @@ -442,7 +424,6 @@ func TestOrganizationsService_GetTeamMembership(t *testing.T) { mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - testHeader(t, r, "Accept", mediaTypeMembershipPreview) fmt.Fprint(w, `{"url":"u", "state":"active"}`) }) @@ -461,13 +442,22 @@ func TestOrganizationsService_AddTeamMembership(t *testing.T) { setup() defer teardown() + opt := &OrganizationAddTeamMembershipOptions{Role: "maintainer"} + mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) { + v := new(OrganizationAddTeamMembershipOptions) + json.NewDecoder(r.Body).Decode(v) + testMethod(t, r, "PUT") - testHeader(t, r, "Accept", mediaTypeMembershipPreview) + testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview) + if !reflect.DeepEqual(v, opt) { + t.Errorf("Request body = %+v, want %+v", v, opt) + } + fmt.Fprint(w, `{"url":"u", "state":"pending"}`) }) - membership, _, err := client.Organizations.AddTeamMembership(1, "u") + membership, _, err := client.Organizations.AddTeamMembership(1, "u", opt) if err != nil { t.Errorf("Organizations.AddTeamMembership returned error: %v", err) } @@ -484,7 +474,6 @@ func TestOrganizationsService_RemoveTeamMembership(t *testing.T) { mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") - testHeader(t, r, "Accept", mediaTypeMembershipPreview) w.WriteHeader(http.StatusNoContent) }) diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/orgs_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/orgs_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/pulls.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls.go similarity index 94% rename from Godeps/_workspace/src/github.com/google/go-github/github/pulls.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls.go index 307562d..71cf2e2 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/pulls.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls.go @@ -41,6 +41,8 @@ type PullRequest struct { HTMLURL *string `json:"html_url,omitempty"` IssueURL *string `json:"issue_url,omitempty"` StatusesURL *string `json:"statuses_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` Head *PullRequestBranch `json:"head,omitempty"` Base *PullRequestBranch `json:"base,omitempty"` @@ -73,6 +75,15 @@ type PullRequestListOptions struct { // Base filters pull requests by base branch name. Base string `url:"base,omitempty"` + // Sort specifies how to sort pull requests. Possible values are: created, + // updated, popularity, long-running. Default is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort pull requests. Possible values are: asc, desc. + // If Sort is "created" or not specified, Default is "desc", otherwise Default + // is "asc" + Direction string `url:"direction,omitempty"` + ListOptions } diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/pulls_comments.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls_comments.go similarity index 99% rename from Godeps/_workspace/src/github.com/google/go-github/github/pulls_comments.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls_comments.go index bfbad9a..35c7241 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/pulls_comments.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls_comments.go @@ -93,7 +93,7 @@ func (s *PullRequestsService) GetComment(owner string, repo string, number int) // CreateComment creates a new comment on the specified pull request. // -// GitHub API docs: https://developer.github.com/v3/pulls/comments/#get-a-single-comment +// GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-comment func (s *PullRequestsService) CreateComment(owner string, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) req, err := s.client.NewRequest("POST", u, comment) diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/pulls_comments_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls_comments_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/pulls_comments_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls_comments_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/pulls_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls_test.go similarity index 88% rename from Godeps/_workspace/src/github.com/google/go-github/github/pulls_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls_test.go index d0e976b..6ac0ddb 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/pulls_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/pulls_test.go @@ -20,15 +20,17 @@ func TestPullRequestsService_List(t *testing.T) { mux.HandleFunc("/repos/o/r/pulls", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ - "state": "closed", - "head": "h", - "base": "b", - "page": "2", + "state": "closed", + "head": "h", + "base": "b", + "sort": "created", + "direction": "desc", + "page": "2", }) fmt.Fprint(w, `[{"number":1}]`) }) - opt := &PullRequestListOptions{"closed", "h", "b", ListOptions{Page: 2}} + opt := &PullRequestListOptions{"closed", "h", "b", "created", "desc", ListOptions{Page: 2}} pulls, _, err := client.PullRequests.List("o", "r", opt) if err != nil { @@ -98,6 +100,29 @@ func TestPullRequestsService_Get_headAndBase(t *testing.T) { } } +func TestPullRequestService_Get_DiffURLAndPatchURL(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"number":1, + "diff_url": "https://github.com/octocat/Hello-World/pull/1347.diff", + "patch_url": "https://github.com/octocat/Hello-World/pull/1347.patch"}`) + }) + + pull, _, err := client.PullRequests.Get("o", "r", 1) + + if err != nil { + t.Errorf("PullRequests.Get returned error: %v", err) + } + + want := &PullRequest{Number: Int(1), DiffURL: String("https://github.com/octocat/Hello-World/pull/1347.diff"), PatchURL: String("https://github.com/octocat/Hello-World/pull/1347.patch")} + if !reflect.DeepEqual(pull, want) { + t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want) + } +} + func TestPullRequestsService_Get_invalidOwner(t *testing.T) { _, _, err := client.PullRequests.Get("%", "r", 1) testURLParseError(t, err) diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos.go similarity index 98% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos.go index 8d8d40f..ed9052c 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos.go @@ -49,6 +49,9 @@ type Repository struct { Organization *Organization `json:"organization,omitempty"` Permissions *map[string]bool `json:"permissions,omitempty"` + // Only provided when using RepositoriesService.Get while in preview + License *License `json:"license,omitempty"` + // Additional mutable fields when creating and editing a repository Private *bool `json:"private"` HasIssues *bool `json:"has_issues"` @@ -255,6 +258,10 @@ func (s *RepositoriesService) Get(owner, repo string) (*Repository, *Response, e return nil, nil, err } + // TODO: remove custom Accept header when the license support fully launches + // https://developer.github.com/v3/licenses/#get-a-repositorys-license + req.Header.Set("Accept", mediaTypeLicensesPreview) + repository := new(Repository) resp, err := s.client.Do(req, repository) if err != nil { diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_collaborators.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_collaborators.go similarity index 72% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_collaborators.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_collaborators.go index 3ad6162..61dc4ef 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_collaborators.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_collaborators.go @@ -22,6 +22,8 @@ func (s *RepositoriesService) ListCollaborators(owner, repo string, opt *ListOpt return nil, nil, err } + req.Header.Set("Accept", mediaTypeOrgPermissionPreview) + users := new([]User) resp, err := s.client.Do(req, users) if err != nil { @@ -49,15 +51,33 @@ func (s *RepositoriesService) IsCollaborator(owner, repo, user string) (bool, *R return isCollab, resp, err } +// RepositoryAddCollaboratorOptions specifies the optional parameters to the +// RepositoriesService.AddCollaborator method. +type RepositoryAddCollaboratorOptions struct { + // Permission specifies the permission to grant the user on this repository. + // Possible values are: + // pull - team members can pull, but not push to or administer this repository + // push - team members can pull and push, but not administer this repository + // admin - team members can pull, push and administer this repository + // + // Default value is "pull". This option is only valid for organization-owned repositories. + Permission string `json:"permission,omitempty"` +} + // AddCollaborator adds the specified Github user as collaborator to the given repo. // // GitHub API docs: http://developer.github.com/v3/repos/collaborators/#add-collaborator -func (s *RepositoriesService) AddCollaborator(owner, repo, user string) (*Response, error) { +func (s *RepositoriesService) AddCollaborator(owner, repo, user string, opt *RepositoryAddCollaboratorOptions) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) - req, err := s.client.NewRequest("PUT", u, nil) + req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, err } + + if opt != nil { + req.Header.Set("Accept", mediaTypeOrgPermissionPreview) + } + return s.client.Do(req, nil) } diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_collaborators_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_collaborators_test.go similarity index 86% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_collaborators_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_collaborators_test.go index de26ba9..ee6c498 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_collaborators_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_collaborators_test.go @@ -6,6 +6,7 @@ package github import ( + "encoding/json" "fmt" "net/http" "reflect" @@ -18,6 +19,7 @@ func TestRepositoriesService_ListCollaborators(t *testing.T) { mux.HandleFunc("/repos/o/r/collaborators", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") + testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprintf(w, `[{"id":1}, {"id":2}]`) }) @@ -86,19 +88,29 @@ func TestRepositoriesService_AddCollaborator(t *testing.T) { setup() defer teardown() + opt := &RepositoryAddCollaboratorOptions{Permission: "admin"} + mux.HandleFunc("/repos/o/r/collaborators/u", func(w http.ResponseWriter, r *http.Request) { + v := new(RepositoryAddCollaboratorOptions) + json.NewDecoder(r.Body).Decode(v) + testMethod(t, r, "PUT") + testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview) + if !reflect.DeepEqual(v, opt) { + t.Errorf("Request body = %+v, want %+v", v, opt) + } + w.WriteHeader(http.StatusNoContent) }) - _, err := client.Repositories.AddCollaborator("o", "r", "u") + _, err := client.Repositories.AddCollaborator("o", "r", "u", opt) if err != nil { t.Errorf("Repositories.AddCollaborator returned error: %v", err) } } func TestRepositoriesService_AddCollaborator_invalidUser(t *testing.T) { - _, err := client.Repositories.AddCollaborator("%", "%", "%") + _, err := client.Repositories.AddCollaborator("%", "%", "%", nil) testURLParseError(t, err) } diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_comments.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_comments.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_comments.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_comments.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_comments_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_comments_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_comments_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_comments_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_commits.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_commits.go similarity index 97% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_commits.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_commits.go index 5a59146..6401cb4 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_commits.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_commits.go @@ -61,7 +61,8 @@ func (c CommitFile) String() string { // CommitsComparison is the result of comparing two commits. // See CompareCommits() for details. type CommitsComparison struct { - BaseCommit *RepositoryCommit `json:"base_commit,omitempty"` + BaseCommit *RepositoryCommit `json:"base_commit,omitempty"` + MergeBaseCommit *RepositoryCommit `json:"merge_base_commit,omitempty"` // Head can be 'behind' or 'ahead' Status *string `json:"status,omitempty"` diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_commits_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_commits_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_commits_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_commits_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_contents.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_contents.go similarity index 83% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_contents.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_contents.go index d17c63e..80776f2 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_contents.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_contents.go @@ -13,22 +13,25 @@ import ( "encoding/json" "errors" "fmt" + "io" "net/http" "net/url" + "path" ) // RepositoryContent represents a file or directory in a github repository. type RepositoryContent struct { - Type *string `json:"type,omitempty"` - Encoding *string `json:"encoding,omitempty"` - Size *int `json:"size,omitempty"` - Name *string `json:"name,omitempty"` - Path *string `json:"path,omitempty"` - Content *string `json:"content,omitempty"` - SHA *string `json:"sha,omitempty"` - URL *string `json:"url,omitempty"` - GitURL *string `json:"giturl,omitempty"` - HTMLURL *string `json:"htmlurl,omitempty"` + Type *string `json:"type,omitempty"` + Encoding *string `json:"encoding,omitempty"` + Size *int `json:"size,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + Content *string `json:"content,omitempty"` + SHA *string `json:"sha,omitempty"` + URL *string `json:"url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` } // RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile. @@ -90,6 +93,32 @@ func (s *RepositoriesService) GetReadme(owner, repo string, opt *RepositoryConte return readme, resp, err } +// DownloadContents returns an io.ReadCloser that reads the contents of the +// specified file. This function will work with files of any size, as opposed +// to GetContents which is limited to 1 Mb files. It is the caller's +// responsibility to close the ReadCloser. +func (s *RepositoriesService) DownloadContents(owner, repo, filepath string, opt *RepositoryContentGetOptions) (io.ReadCloser, error) { + dir := path.Dir(filepath) + filename := path.Base(filepath) + _, dirContents, _, err := s.GetContents(owner, repo, dir, opt) + if err != nil { + return nil, err + } + for _, contents := range dirContents { + if *contents.Name == filename { + if contents.DownloadURL == nil || *contents.DownloadURL == "" { + return nil, fmt.Errorf("No download link found for %s", filepath) + } + resp, err := s.client.client.Get(*contents.DownloadURL) + if err != nil { + return nil, err + } + return resp.Body, nil + } + } + return nil, fmt.Errorf("No file named %s found in %s", filename, dir) +} + // GetContents can return either the metadata and content of a single file // (when path references a file) or the metadata of all the files and/or // subdirectories of a directory (when path references a directory). To make it diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_contents_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_contents_test.go similarity index 77% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_contents_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_contents_test.go index 7376aea..8ab3ecd 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_contents_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_contents_test.go @@ -2,6 +2,7 @@ package github import ( "fmt" + "io/ioutil" "net/http" "reflect" "testing" @@ -54,7 +55,70 @@ func TestRepositoriesService_GetReadme(t *testing.T) { } } -func TestRepositoriesService_GetContent_File(t *testing.T) { +func TestRepositoriesService_DownloadContents_Success(t *testing.T) { + setup() + defer teardown() + mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[{ + "type": "file", + "name": "f", + "download_url": "`+server.URL+`/download/f" + }]`) + }) + mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, "foo") + }) + + r, err := client.Repositories.DownloadContents("o", "r", "d/f", nil) + if err != nil { + t.Errorf("Repositories.DownloadContents returned error: %v", err) + } + + bytes, err := ioutil.ReadAll(r) + if err != nil { + t.Errorf("Error reading response body: %v", err) + } + r.Close() + + if got, want := string(bytes), "foo"; got != want { + t.Errorf("Repositories.DownloadContents returned %v, want %v", got, want) + } +} + +func TestRepositoriesService_DownloadContents_NoDownloadURL(t *testing.T) { + setup() + defer teardown() + mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[{ + "type": "file", + "name": "f", + }]`) + }) + + _, err := client.Repositories.DownloadContents("o", "r", "d/f", nil) + if err == nil { + t.Errorf("Repositories.DownloadContents did not return expected error") + } +} + +func TestRepositoriesService_DownloadContents_NoFile(t *testing.T) { + setup() + defer teardown() + mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[]`) + }) + + _, err := client.Repositories.DownloadContents("o", "r", "d/f", nil) + if err == nil { + t.Errorf("Repositories.DownloadContents did not return expected error") + } +} + +func TestRepositoriesService_GetContents_File(t *testing.T) { setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { @@ -69,7 +133,7 @@ func TestRepositoriesService_GetContent_File(t *testing.T) { }) fileContents, _, _, err := client.Repositories.GetContents("o", "r", "p", &RepositoryContentGetOptions{}) if err != nil { - t.Errorf("Repositories.GetContents_File returned error: %v", err) + t.Errorf("Repositories.GetContents returned error: %v", err) } want := &RepositoryContent{Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Encoding: String("base64"), Path: String("LICENSE")} if !reflect.DeepEqual(fileContents, want) { @@ -77,7 +141,7 @@ func TestRepositoriesService_GetContent_File(t *testing.T) { } } -func TestRepositoriesService_GetContent_Directory(t *testing.T) { +func TestRepositoriesService_GetContents_Directory(t *testing.T) { setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { @@ -88,7 +152,7 @@ func TestRepositoriesService_GetContent_Directory(t *testing.T) { "path": "lib" }, { - "type": "file", + "type": "file", "size": 20678, "name": "LICENSE", "path": "LICENSE" @@ -96,7 +160,7 @@ func TestRepositoriesService_GetContent_Directory(t *testing.T) { }) _, directoryContents, _, err := client.Repositories.GetContents("o", "r", "p", &RepositoryContentGetOptions{}) if err != nil { - t.Errorf("Repositories.GetContents_Directory returned error: %v", err) + t.Errorf("Repositories.GetContents returned error: %v", err) } want := []*RepositoryContent{{Type: String("dir"), Name: String("lib"), Path: String("lib")}, {Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Path: String("LICENSE")}} diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_deployments.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_deployments.go similarity index 84% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_deployments.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_deployments.go index 2fdf15a..77c7949 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_deployments.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_deployments.go @@ -27,13 +27,13 @@ type Deployment struct { // DeploymentRequest represents a deployment request type DeploymentRequest struct { - Ref *string `json:"ref,omitempty"` - Task *string `json:"task,omitempty"` - AutoMerge *bool `json:"auto_merge,omitempty"` - RequiredContexts []string `json:"required_contexts,omitempty"` - Payload *string `json:"payload,omitempty"` - Environment *string `json:"environment,omitempty"` - Description *string `json:"description,omitempty"` + Ref *string `json:"ref,omitempty"` + Task *string `json:"task,omitempty"` + AutoMerge *bool `json:"auto_merge,omitempty"` + RequiredContexts *[]string `json:"required_contexts,omitempty"` + Payload *string `json:"payload,omitempty"` + Environment *string `json:"environment,omitempty"` + Description *string `json:"description,omitempty"` } // DeploymentsListOptions specifies the optional parameters to the @@ -69,9 +69,6 @@ func (s *RepositoriesService) ListDeployments(owner, repo string, opt *Deploymen return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeDeploymentPreview) - deployments := new([]Deployment) resp, err := s.client.Do(req, deployments) if err != nil { @@ -92,9 +89,6 @@ func (s *RepositoriesService) CreateDeployment(owner, repo string, request *Depl return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeDeploymentPreview) - d := new(Deployment) resp, err := s.client.Do(req, d) if err != nil { @@ -138,9 +132,6 @@ func (s *RepositoriesService) ListDeploymentStatuses(owner, repo string, deploym return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeDeploymentPreview) - statuses := new([]DeploymentStatus) resp, err := s.client.Do(req, statuses) if err != nil { @@ -161,9 +152,6 @@ func (s *RepositoriesService) CreateDeploymentStatus(owner, repo string, deploym return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeDeploymentPreview) - d := new(DeploymentStatus) resp, err := s.client.Do(req, d) if err != nil { diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_deployments_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_deployments_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_deployments_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_deployments_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_forks.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_forks.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_forks.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_forks.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_forks_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_forks_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_forks_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_forks_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_hooks.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_hooks.go similarity index 88% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_hooks.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_hooks.go index 8468672..bc4c8c5 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_hooks.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_hooks.go @@ -164,6 +164,18 @@ func (s *RepositoriesService) DeleteHook(owner, repo string, id int) (*Response, return s.client.Do(req, nil) } +// PingHook triggers a 'ping' event to be sent to the Hook. +// +// GitHub API docs: https://developer.github.com/v3/repos/hooks/#ping-a-hook +func (s *RepositoriesService) PingHook(owner, repo string, id int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(req, nil) +} + // TestHook triggers a test Hook by github. // // GitHub API docs: http://developer.github.com/v3/repos/hooks/#test-a-push-hook @@ -176,34 +188,7 @@ func (s *RepositoriesService) TestHook(owner, repo string, id int) (*Response, e return s.client.Do(req, nil) } -// ServiceHook represents a hook that has configuration settings, a list of -// available events, and default events. -type ServiceHook struct { - Name *string `json:"name,omitempty"` - Events []string `json:"events,omitempty"` - SupportedEvents []string `json:"supported_events,omitempty"` - Schema [][]string `json:"schema,omitempty"` -} - -func (s *ServiceHook) String() string { - return Stringify(s) -} - -// ListServiceHooks lists all of the available service hooks. -// -// GitHub API docs: https://developer.github.com/webhooks/#services +// ListServiceHooks is deprecated. Use Client.ListServiceHooks instead. func (s *RepositoriesService) ListServiceHooks() ([]ServiceHook, *Response, error) { - u := "hooks" - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - hooks := new([]ServiceHook) - resp, err := s.client.Do(req, hooks) - if err != nil { - return nil, resp, err - } - - return *hooks, resp, err + return s.client.ListServiceHooks() } diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_hooks_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_hooks_test.go similarity index 86% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_hooks_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_hooks_test.go index b322e17..c163a26 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_hooks_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_hooks_test.go @@ -153,6 +153,20 @@ func TestRepositoriesService_DeleteHook_invalidOwner(t *testing.T) { testURLParseError(t, err) } +func TestRepositoriesService_PingHook(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/hooks/1/pings", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + }) + + _, err := client.Repositories.PingHook("o", "r", 1) + if err != nil { + t.Errorf("Repositories.PingHook returned error: %v", err) + } +} + func TestRepositoriesService_TestHook(t *testing.T) { setup() defer teardown() @@ -171,35 +185,3 @@ func TestRepositoriesService_TestHook_invalidOwner(t *testing.T) { _, err := client.Repositories.TestHook("%", "%", 1) testURLParseError(t, err) } - -func TestRepositoriesService_ListServiceHooks(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/hooks", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "GET") - fmt.Fprint(w, `[{ - "name":"n", - "events":["e"], - "supported_events":["s"], - "schema":[ - ["a", "b"] - ] - }]`) - }) - - hooks, _, err := client.Repositories.ListServiceHooks() - if err != nil { - t.Errorf("Repositories.ListHooks returned error: %v", err) - } - - want := []ServiceHook{{ - Name: String("n"), - Events: []string{"e"}, - SupportedEvents: []string{"s"}, - Schema: [][]string{{"a", "b"}}, - }} - if !reflect.DeepEqual(hooks, want) { - t.Errorf("Repositories.ListServiceHooks returned %+v, want %+v", hooks, want) - } -} diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_keys.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_keys.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_keys.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_keys.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_keys_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_keys_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_keys_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_keys_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_merging.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_merging.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_merging.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_merging.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_merging_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_merging_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_merging_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_merging_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_pages.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_pages.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_pages.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_pages.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_pages_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_pages_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_pages_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_pages_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_releases.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_releases.go similarity index 78% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_releases.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_releases.go index 1400114..f685a28 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_releases.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_releases.go @@ -8,7 +8,9 @@ package github import ( "errors" "fmt" + "io" "mime" + "net/http" "os" "path/filepath" ) @@ -85,8 +87,27 @@ func (s *RepositoriesService) ListReleases(owner, repo string, opt *ListOptions) // GitHub API docs: http://developer.github.com/v3/repos/releases/#get-a-single-release func (s *RepositoriesService) GetRelease(owner, repo string, id int) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) + return s.getSingleRelease(u) +} - req, err := s.client.NewRequest("GET", u, nil) +// GetLatestRelease fetches the latest published release for the repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-the-latest-release +func (s *RepositoriesService) GetLatestRelease(owner, repo string) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/latest", owner, repo) + return s.getSingleRelease(u) +} + +// GetReleaseByTag fetches a release with the specified tag. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-release-by-tag-name +func (s *RepositoriesService) GetReleaseByTag(owner, repo, tag string) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/tags/%s", owner, repo, tag) + return s.getSingleRelease(u) +} + +func (s *RepositoriesService) getSingleRelease(url string) (*RepositoryRelease, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) if err != nil { return nil, nil, err } @@ -192,6 +213,54 @@ func (s *RepositoriesService) GetReleaseAsset(owner, repo string, id int) (*Rele return asset, resp, err } +// DowloadReleaseAsset downloads a release asset. +// +// DowloadReleaseAsset returns an io.ReadCloser that reads the contents of the +// specified release asset. It is the caller's responsibility to close the ReadCloser. +// +// GitHub API docs : http://developer.github.com/v3/repos/releases/#get-a-single-release-asset +func (s *RepositoriesService) DownloadReleaseAsset(owner, repo string, id int) (io.ReadCloser, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + req.Header.Set("Accept", defaultMediaType) + + var resp *http.Response + if s.client.client.Transport == nil { + resp, err = http.DefaultTransport.RoundTrip(req) + } else { + resp, err = s.client.client.Transport.RoundTrip(req) + } + if err != nil { + return nil, err + } + + // GitHub API streamed the asset directly + if resp.StatusCode == http.StatusOK { + return resp.Body, nil + } + + if resp.StatusCode != http.StatusFound { + return nil, fmt.Errorf("Expected status code 200 or 302, got %d", resp.StatusCode) + } + + // GitHub API redirected to pre-signed S3 URL + downloadURL, err := resp.Location() + if err != nil { + return nil, err + } + + resp, err = http.Get(downloadURL.String()) + if err != nil { + return nil, err + } + + return resp.Body, nil +} + // EditReleaseAsset edits a repository release asset. // // GitHub API docs : http://developer.github.com/v3/repos/releases/#edit-a-release-asset diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_releases_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_releases_test.go similarity index 67% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_releases_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_releases_test.go index 17c6702..719792b 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_releases_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_releases_test.go @@ -6,8 +6,10 @@ package github import ( + "bytes" "encoding/json" "fmt" + "io/ioutil" "net/http" "os" "reflect" @@ -55,6 +57,46 @@ func TestRepositoriesService_GetRelease(t *testing.T) { } } +func TestRepositoriesService_GetLatestRelease(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/releases/latest", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"id":3}`) + }) + + release, resp, err := client.Repositories.GetLatestRelease("o", "r") + if err != nil { + t.Errorf("Repositories.GetLatestRelease returned error: %v\n%v", err, resp.Body) + } + + want := &RepositoryRelease{ID: Int(3)} + if !reflect.DeepEqual(release, want) { + t.Errorf("Repositories.GetLatestRelease returned %+v, want %+v", release, want) + } +} + +func TestRepositoriesService_GetReleaseByTag(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/releases/tags/foo", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"id":13}`) + }) + + release, resp, err := client.Repositories.GetReleaseByTag("o", "r", "foo") + if err != nil { + t.Errorf("Repositories.GetReleaseByTag returned error: %v\n%v", err, resp.Body) + } + + want := &RepositoryRelease{ID: Int(13)} + if !reflect.DeepEqual(release, want) { + t.Errorf("Repositories.GetReleaseByTag returned %+v, want %+v", release, want) + } +} + func TestRepositoriesService_CreateRelease(t *testing.T) { setup() defer teardown() @@ -164,6 +206,64 @@ func TestRepositoriesService_GetReleaseAsset(t *testing.T) { } } +func TestRepositoriesService_DownloadReleaseAsset_Stream(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testHeader(t, r, "Accept", defaultMediaType) + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt") + fmt.Fprint(w, "Hello World") + }) + + reader, err := client.Repositories.DowloadReleaseAsset("o", "r", 1) + if err != nil { + t.Errorf("Repositories.DowloadReleaseAsset returned error: %v", err) + } + want := []byte("Hello World") + content, err := ioutil.ReadAll(reader) + if err != nil { + t.Errorf("Repositories.DowloadReleaseAsset returned bad reader: %v", err) + } + if !bytes.Equal(want, content) { + t.Errorf("Repositories.DowloadReleaseAsset returned %+v, want %+v", content, want) + } +} + +func TestRepositoriesService_DownloadReleaseAsset_Redirect(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testHeader(t, r, "Accept", defaultMediaType) + w.Header().Set("Location", server.URL+"/github-cloud/releases/1/hello-world.txt") + w.WriteHeader(http.StatusFound) + }) + + mux.HandleFunc("/github-cloud/releases/1/hello-world.txt", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt") + fmt.Fprint(w, "Hello World") + }) + + reader, err := client.Repositories.DowloadReleaseAsset("o", "r", 1) + if err != nil { + t.Errorf("Repositories.DowloadReleaseAsset returned error: %v", err) + } + want := []byte("Hello World") + content, err := ioutil.ReadAll(reader) + if err != nil { + t.Errorf("Repositories.DowloadReleaseAsset returned bad reader: %v", err) + } + if !bytes.Equal(want, content) { + t.Errorf("Repositories.DowloadReleaseAsset returned %+v, want %+v", content, want) + } +} + func TestRepositoriesService_EditReleaseAsset(t *testing.T) { setup() defer teardown() diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_stats.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_stats.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_stats.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_stats.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_stats_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_stats_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_stats_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_stats_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_statuses.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_statuses.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_statuses.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_statuses.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_statuses_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_statuses_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_statuses_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_statuses_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/repos_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_test.go similarity index 98% rename from Godeps/_workspace/src/github.com/google/go-github/github/repos_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_test.go index def2119..3a2c413 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/repos_test.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/repos_test.go @@ -45,7 +45,6 @@ func TestRepositoriesService_List_specifiedUser(t *testing.T) { "direction": "asc", "page": "2", }) - fmt.Fprint(w, `[{"id":1}]`) }) @@ -191,7 +190,8 @@ func TestRepositoriesService_Get(t *testing.T) { mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"}}`) + testHeader(t, r, "Accept", mediaTypeLicensesPreview) + fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`) }) repo, _, err := client.Repositories.Get("o", "r") @@ -199,7 +199,7 @@ func TestRepositoriesService_Get(t *testing.T) { t.Errorf("Repositories.Get returned error: %v", err) } - want := &Repository{ID: Int(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}} + want := &Repository{ID: Int(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}, License: &License{Key: String("mit")}} if !reflect.DeepEqual(repo, want) { t.Errorf("Repositories.Get returned %+v, want %+v", repo, want) } diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/search.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/search.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/search.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/search.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/search_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/search_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/search_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/search_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/strings.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/strings.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/strings.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/strings.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/strings_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/strings_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/strings_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/strings_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/timestamp.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/timestamp.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/timestamp.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/timestamp.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/timestamp_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/timestamp_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/timestamp_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/timestamp_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/users.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users.go similarity index 95% rename from Godeps/_workspace/src/github.com/google/go-github/github/users.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/users.go index bd68ac2..95cca6b 100644 --- a/Godeps/_workspace/src/github.com/google/go-github/github/users.go +++ b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users.go @@ -59,6 +59,10 @@ type User struct { // 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"` + + // Permissions identifies the permissions that a user has on a given + // repository. This is only populated when calling Repositories.ListCollaborators. + Permissions *map[string]bool `json:"permissions,omitempty"` } func (u User) String() string { diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/users_administration.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_administration.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/users_administration.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_administration.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/users_administration_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_administration_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/users_administration_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_administration_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/users_emails.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_emails.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/users_emails.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_emails.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/users_emails_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_emails_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/users_emails_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_emails_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/users_followers.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_followers.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/users_followers.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_followers.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/users_followers_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_followers_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/users_followers_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_followers_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/users_keys.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_keys.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/users_keys.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_keys.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/users_keys_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_keys_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/users_keys_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_keys_test.go diff --git a/Godeps/_workspace/src/github.com/google/go-github/github/users_test.go b/Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/google/go-github/github/users_test.go rename to Godeps/_workspace/src/github.com/zachgersh/go-github/github/users_test.go diff --git a/README.md b/README.md index dd3e844..56e0c98 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ Fetches and creates versioned GitHub resources. * `repository`: *Required.* The repository name that contains the releases. -* `access_token`: *Optional.* The GitHub access token that should be used to - access the API. Only required for publishing releases. +* `access_token`: *Optional.* Used for accessing a release in a private-repo + during an `in` and pushing a release to a repo during an `out`. * `github_api_url`: *Optional.* If you use a non-public GitHub deployment then you can set your API URL here. diff --git a/check_command.go b/check_command.go index 4731e93..89fc9ae 100644 --- a/check_command.go +++ b/check_command.go @@ -5,7 +5,7 @@ import ( "sort" "github.com/blang/semver" - "github.com/google/go-github/github" + "github.com/zachgersh/go-github/github" ) type CheckCommand struct { diff --git a/check_command_test.go b/check_command_test.go index 76c6969..a8722fe 100644 --- a/check_command_test.go +++ b/check_command_test.go @@ -4,7 +4,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/google/go-github/github" + "github.com/zachgersh/go-github/github" "github.com/concourse/github-release-resource" "github.com/concourse/github-release-resource/fakes" diff --git a/fakes/fake_git_hub.go b/fakes/fake_git_hub.go index e4e8723..1d7f67f 100644 --- a/fakes/fake_git_hub.go +++ b/fakes/fake_git_hub.go @@ -2,21 +2,38 @@ package fakes import ( + "io" "os" "sync" "github.com/concourse/github-release-resource" - "github.com/google/go-github/github" + "github.com/zachgersh/go-github/github" ) type FakeGitHub struct { ListReleasesStub func() ([]github.RepositoryRelease, error) listReleasesMutex sync.RWMutex listReleasesArgsForCall []struct{} - listReleasesReturns struct { + listReleasesReturns struct { result1 []github.RepositoryRelease result2 error } + LatestReleaseStub func() (*github.RepositoryRelease, error) + latestReleaseMutex sync.RWMutex + latestReleaseArgsForCall []struct{} + latestReleaseReturns struct { + result1 *github.RepositoryRelease + result2 error + } + GetReleaseByTagStub func(tag string) (*github.RepositoryRelease, error) + getReleaseByTagMutex sync.RWMutex + getReleaseByTagArgsForCall []struct { + tag string + } + getReleaseByTagReturns struct { + result1 *github.RepositoryRelease + result2 error + } CreateReleaseStub func(release *github.RepositoryRelease) (*github.RepositoryRelease, error) createReleaseMutex sync.RWMutex createReleaseArgsForCall []struct { @@ -35,10 +52,10 @@ type FakeGitHub struct { result1 *github.RepositoryRelease result2 error } - ListReleaseAssetsStub func(release *github.RepositoryRelease) ([]github.ReleaseAsset, error) + ListReleaseAssetsStub func(release github.RepositoryRelease) ([]github.ReleaseAsset, error) listReleaseAssetsMutex sync.RWMutex listReleaseAssetsArgsForCall []struct { - release *github.RepositoryRelease + release github.RepositoryRelease } listReleaseAssetsReturns struct { result1 []github.ReleaseAsset @@ -62,6 +79,15 @@ type FakeGitHub struct { deleteReleaseAssetReturns struct { result1 error } + DownloadReleaseAssetStub func(asset *github.ReleaseAsset) (io.ReadCloser, error) + downloadReleaseAssetMutex sync.RWMutex + downloadReleaseAssetArgsForCall []struct { + asset *github.ReleaseAsset + } + downloadReleaseAssetReturns struct { + result1 io.ReadCloser + result2 error + } } func (fake *FakeGitHub) ListReleases() ([]github.RepositoryRelease, error) { @@ -89,6 +115,64 @@ func (fake *FakeGitHub) ListReleasesReturns(result1 []github.RepositoryRelease, }{result1, result2} } +func (fake *FakeGitHub) LatestRelease() (*github.RepositoryRelease, error) { + fake.latestReleaseMutex.Lock() + fake.latestReleaseArgsForCall = append(fake.latestReleaseArgsForCall, struct{}{}) + fake.latestReleaseMutex.Unlock() + if fake.LatestReleaseStub != nil { + return fake.LatestReleaseStub() + } else { + return fake.latestReleaseReturns.result1, fake.latestReleaseReturns.result2 + } +} + +func (fake *FakeGitHub) LatestReleaseCallCount() int { + fake.latestReleaseMutex.RLock() + defer fake.latestReleaseMutex.RUnlock() + return len(fake.latestReleaseArgsForCall) +} + +func (fake *FakeGitHub) LatestReleaseReturns(result1 *github.RepositoryRelease, result2 error) { + fake.LatestReleaseStub = nil + fake.latestReleaseReturns = struct { + result1 *github.RepositoryRelease + result2 error + }{result1, result2} +} + +func (fake *FakeGitHub) GetReleaseByTag(tag string) (*github.RepositoryRelease, error) { + fake.getReleaseByTagMutex.Lock() + fake.getReleaseByTagArgsForCall = append(fake.getReleaseByTagArgsForCall, struct { + tag string + }{tag}) + fake.getReleaseByTagMutex.Unlock() + if fake.GetReleaseByTagStub != nil { + return fake.GetReleaseByTagStub(tag) + } else { + return fake.getReleaseByTagReturns.result1, fake.getReleaseByTagReturns.result2 + } +} + +func (fake *FakeGitHub) GetReleaseByTagCallCount() int { + fake.getReleaseByTagMutex.RLock() + defer fake.getReleaseByTagMutex.RUnlock() + return len(fake.getReleaseByTagArgsForCall) +} + +func (fake *FakeGitHub) GetReleaseByTagArgsForCall(i int) string { + fake.getReleaseByTagMutex.RLock() + defer fake.getReleaseByTagMutex.RUnlock() + return fake.getReleaseByTagArgsForCall[i].tag +} + +func (fake *FakeGitHub) GetReleaseByTagReturns(result1 *github.RepositoryRelease, result2 error) { + fake.GetReleaseByTagStub = nil + fake.getReleaseByTagReturns = struct { + result1 *github.RepositoryRelease + result2 error + }{result1, result2} +} + func (fake *FakeGitHub) CreateRelease(release *github.RepositoryRelease) (*github.RepositoryRelease, error) { fake.createReleaseMutex.Lock() fake.createReleaseArgsForCall = append(fake.createReleaseArgsForCall, struct { @@ -155,10 +239,10 @@ func (fake *FakeGitHub) UpdateReleaseReturns(result1 *github.RepositoryRelease, }{result1, result2} } -func (fake *FakeGitHub) ListReleaseAssets(release *github.RepositoryRelease) ([]github.ReleaseAsset, error) { +func (fake *FakeGitHub) ListReleaseAssets(release github.RepositoryRelease) ([]github.ReleaseAsset, error) { fake.listReleaseAssetsMutex.Lock() fake.listReleaseAssetsArgsForCall = append(fake.listReleaseAssetsArgsForCall, struct { - release *github.RepositoryRelease + release github.RepositoryRelease }{release}) fake.listReleaseAssetsMutex.Unlock() if fake.ListReleaseAssetsStub != nil { @@ -174,7 +258,7 @@ func (fake *FakeGitHub) ListReleaseAssetsCallCount() int { return len(fake.listReleaseAssetsArgsForCall) } -func (fake *FakeGitHub) ListReleaseAssetsArgsForCall(i int) *github.RepositoryRelease { +func (fake *FakeGitHub) ListReleaseAssetsArgsForCall(i int) github.RepositoryRelease { fake.listReleaseAssetsMutex.RLock() defer fake.listReleaseAssetsMutex.RUnlock() return fake.listReleaseAssetsArgsForCall[i].release @@ -254,4 +338,37 @@ func (fake *FakeGitHub) DeleteReleaseAssetReturns(result1 error) { }{result1} } +func (fake *FakeGitHub) DownloadReleaseAsset(asset *github.ReleaseAsset) (io.ReadCloser, error) { + fake.downloadReleaseAssetMutex.Lock() + fake.downloadReleaseAssetArgsForCall = append(fake.downloadReleaseAssetArgsForCall, struct { + asset *github.ReleaseAsset + }{asset}) + fake.downloadReleaseAssetMutex.Unlock() + if fake.DownloadReleaseAssetStub != nil { + return fake.DownloadReleaseAssetStub(asset) + } else { + return fake.downloadReleaseAssetReturns.result1, fake.downloadReleaseAssetReturns.result2 + } +} + +func (fake *FakeGitHub) DownloadReleaseAssetCallCount() int { + fake.downloadReleaseAssetMutex.RLock() + defer fake.downloadReleaseAssetMutex.RUnlock() + return len(fake.downloadReleaseAssetArgsForCall) +} + +func (fake *FakeGitHub) DownloadReleaseAssetArgsForCall(i int) *github.ReleaseAsset { + fake.downloadReleaseAssetMutex.RLock() + defer fake.downloadReleaseAssetMutex.RUnlock() + return fake.downloadReleaseAssetArgsForCall[i].asset +} + +func (fake *FakeGitHub) DownloadReleaseAssetReturns(result1 io.ReadCloser, result2 error) { + fake.DownloadReleaseAssetStub = nil + fake.downloadReleaseAssetReturns = struct { + result1 io.ReadCloser + result2 error + }{result1, result2} +} + var _ resource.GitHub = new(FakeGitHub) diff --git a/github.go b/github.go index 76994d2..ea9986b 100644 --- a/github.go +++ b/github.go @@ -2,24 +2,28 @@ package resource import ( "errors" + "io" "net/url" "os" "code.google.com/p/goauth2/oauth" - "github.com/google/go-github/github" + "github.com/zachgersh/go-github/github" ) //go:generate counterfeiter . GitHub type GitHub interface { ListReleases() ([]github.RepositoryRelease, error) + LatestRelease() (*github.RepositoryRelease, error) + GetReleaseByTag(tag string) (*github.RepositoryRelease, error) CreateRelease(release *github.RepositoryRelease) (*github.RepositoryRelease, error) UpdateRelease(release *github.RepositoryRelease) (*github.RepositoryRelease, error) - ListReleaseAssets(release *github.RepositoryRelease) ([]github.ReleaseAsset, error) + ListReleaseAssets(release github.RepositoryRelease) ([]github.ReleaseAsset, error) UploadReleaseAsset(release *github.RepositoryRelease, name string, file *os.File) error DeleteReleaseAsset(asset github.ReleaseAsset) error + DownloadReleaseAsset(asset *github.ReleaseAsset) (io.ReadCloser, error) } type GitHubClient struct { @@ -73,6 +77,34 @@ func (g *GitHubClient) ListReleases() ([]github.RepositoryRelease, error) { return releases, nil } +func (g *GitHubClient) LatestRelease() (*github.RepositoryRelease, error) { + latest, res, err := g.client.Repositories.GetLatestRelease(g.user, g.repository) + if err != nil { + return &github.RepositoryRelease{}, nil + } + + err = res.Body.Close() + if err != nil { + return nil, err + } + + return latest, nil +} + +func (g *GitHubClient) GetReleaseByTag(tag string) (*github.RepositoryRelease, error) { + release, res, err := g.client.Repositories.GetReleaseByTag(g.user, g.repository, tag) + if err != nil { + return &github.RepositoryRelease{}, nil + } + + err = res.Body.Close() + if err != nil { + return nil, err + } + + return release, nil +} + func (g *GitHubClient) CreateRelease(release *github.RepositoryRelease) (*github.RepositoryRelease, error) { createdRelease, res, err := g.client.Repositories.CreateRelease(g.user, g.repository, release) if err != nil { @@ -144,3 +176,12 @@ func (g *GitHubClient) DeleteReleaseAsset(asset github.ReleaseAsset) error { return res.Body.Close() } + +func (g *GitHubClient) DownloadReleaseAsset(asset github.ReleaseAsset) (io.ReadCloser, error) { + res, err := g.client.Repositories.DownloadReleaseAsset(g.user, g.repository, *asset.ID) + if err != nil { + return nil, err + } + + return res, err +} diff --git a/in_command.go b/in_command.go index 0d15631..17743f9 100644 --- a/in_command.go +++ b/in_command.go @@ -5,12 +5,10 @@ import ( "fmt" "io" "io/ioutil" - "net/http" "os" "path/filepath" - "sort" - "github.com/google/go-github/github" + "github.com/zachgersh/go-github/github" ) type InCommand struct { @@ -31,32 +29,26 @@ func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) { return InResponse{}, err } - releases, err := c.github.ListReleases() - if err != nil { - return InResponse{}, err - } - - sort.Sort(byVersion(releases)) - - if len(releases) == 0 { - return InResponse{}, errors.New("no releases") - } - var foundRelease *github.RepositoryRelease if request.Version == nil { - foundRelease = &releases[len(releases)-1] + var err error + + foundRelease, err = c.github.LatestRelease() + if err != nil { + return InResponse{}, err + } } else { - for _, release := range releases { - if *release.TagName == request.Version.Tag { - foundRelease = &release - break - } + var err error + + foundRelease, err = c.github.GetReleaseByTag(request.Version.Tag) + if err != nil { + return InResponse{}, err } } if foundRelease == nil { - return InResponse{}, fmt.Errorf("could not find release with tag: %s", request.Version.Tag) + return InResponse{}, errors.New("no releases") } tagPath := filepath.Join(destDir, "tag") @@ -72,13 +64,12 @@ func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) { return InResponse{}, err } - assets, err := c.github.ListReleaseAssets(foundRelease) + assets, err := c.github.ListReleaseAssets(*foundRelease) if err != nil { return InResponse{}, err } for _, asset := range assets { - url := *asset.BrowserDownloadURL path := filepath.Join(destDir, *asset.Name) var matchFound bool @@ -104,7 +95,8 @@ func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) { fmt.Fprintf(c.writer, "downloading asset: %s\n", *asset.Name) - err := c.downloadFile(url, path) + assetToDownload := asset + err := c.downloadFile(&assetToDownload, path) if err != nil { return InResponse{}, err } @@ -118,20 +110,20 @@ func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) { }, nil } -func (c *InCommand) downloadFile(url, destPath string) error { +func (c *InCommand) downloadFile(asset *github.ReleaseAsset, destPath string) error { out, err := os.Create(destPath) if err != nil { return err } defer out.Close() - resp, err := http.Get(url) + content, err := c.github.DownloadReleaseAsset(asset) if err != nil { return err } - defer resp.Body.Close() + defer content.Close() - _, err = io.Copy(out, resp.Body) + _, err = io.Copy(out, content) if err != nil { return err } diff --git a/in_command_test.go b/in_command_test.go index 668ace8..7d49b3f 100644 --- a/in_command_test.go +++ b/in_command_test.go @@ -1,15 +1,16 @@ package resource_test import ( + "bytes" "errors" "io/ioutil" "os" "path/filepath" - "github.com/google/go-github/github" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/onsi/gomega/ghttp" + + "github.com/zachgersh/go-github/github" "github.com/concourse/github-release-resource" "github.com/concourse/github-release-resource/fakes" @@ -19,7 +20,6 @@ var _ = Describe("In Command", func() { var ( command *resource.InCommand githubClient *fakes.FakeGitHub - server *ghttp.Server inRequest resource.InRequest @@ -41,28 +41,17 @@ var _ = Describe("In Command", func() { destDir = filepath.Join(tmpDir, "destination") - server = ghttp.NewServer() - server.RouteToHandler("GET", "/example.txt", ghttp.RespondWith(200, "example.txt")) - server.RouteToHandler("GET", "/example.rtf", ghttp.RespondWith(200, "example.rtf")) - server.RouteToHandler("GET", "/example.wtf", ghttp.RespondWith(200, "example.wtf")) + githubClient.DownloadReleaseAssetReturns(ioutil.NopCloser(bytes.NewBufferString("some-content")), nil) inRequest = resource.InRequest{} }) - JustBeforeEach(func() { - inResponse, inErr = command.Run(destDir, inRequest) - }) - AfterEach(func() { - if server != nil { - server.Close() - } - Ω(os.RemoveAll(tmpDir)).Should(Succeed()) }) - buildRelease := func(id int, tag string) github.RepositoryRelease { - return github.RepositoryRelease{ + buildRelease := func(id int, tag string) *github.RepositoryRelease { + return &github.RepositoryRelease{ ID: github.Int(id), TagName: github.String(tag), HTMLURL: github.String("http://google.com"), @@ -71,29 +60,24 @@ var _ = Describe("In Command", func() { } } - buildAsset := func(name string) github.ReleaseAsset { + buildAsset := func(id int, name string) github.ReleaseAsset { return github.ReleaseAsset{ - Name: &name, - BrowserDownloadURL: github.String(server.URL() + "/" + name), + ID: github.Int(id), + Name: &name, } } - Context("when there are releases", func() { - BeforeEach(func() { - githubClient.ListReleasesReturns([]github.RepositoryRelease{ - buildRelease(2, "v0.35.0"), - buildRelease(1, "v0.34.0"), - }, nil) - - githubClient.ListReleaseAssetsReturns([]github.ReleaseAsset{ - buildAsset("example.txt"), - buildAsset("example.rtf"), - buildAsset("example.wtf"), - }, nil) - }) - + Context("when there is a tagged release", func() { Context("when a present version is specified", func() { BeforeEach(func() { + githubClient.GetReleaseByTagReturns(buildRelease(1, "v0.35.0"), nil) + + githubClient.ListReleaseAssetsReturns([]github.ReleaseAsset{ + buildAsset(0, "example.txt"), + buildAsset(1, "example.rtf"), + buildAsset(2, "example.wtf"), + }, nil) + inRequest.Version = &resource.Version{ Tag: "v0.35.0", } @@ -104,6 +88,8 @@ var _ = Describe("In Command", func() { inRequest.Params = resource.InParams{ Globs: []string{"*.txt", "*.rtf"}, } + + inResponse, inErr = command.Run(destDir, inRequest) }) It("succeeds", func() { @@ -123,14 +109,8 @@ var _ = Describe("In Command", func() { }) It("downloads only the files that match the globs", func() { - _, err := os.Stat(filepath.Join(destDir, "example.txt")) - Ω(err).ShouldNot(HaveOccurred()) - - _, err = os.Stat(filepath.Join(destDir, "example.rtf")) - Ω(err).ShouldNot(HaveOccurred()) - - _, err = os.Stat(filepath.Join(destDir, "example.wtf")) - Ω(err).Should(HaveOccurred()) + Ω(*githubClient.DownloadReleaseAssetArgsForCall(0)).Should(Equal(buildAsset(0, "example.txt"))) + Ω(*githubClient.DownloadReleaseAssetArgsForCall(1)).Should(Equal(buildAsset(1, "example.rtf"))) }) }) @@ -139,6 +119,8 @@ var _ = Describe("In Command", func() { inRequest.Params = resource.InParams{ Globs: []string{`[`}, } + + inResponse, inErr = command.Run(destDir, inRequest) }) It("returns an error", func() { @@ -149,6 +131,7 @@ var _ = Describe("In Command", func() { Context("when no globs are specified", func() { BeforeEach(func() { inRequest.Source = resource.Source{} + inResponse, inErr = command.Run(destDir, inRequest) }) It("succeeds", func() { @@ -168,21 +151,16 @@ var _ = Describe("In Command", func() { }) It("downloads all of the files", func() { - _, err := os.Stat(filepath.Join(destDir, "example.txt")) - Ω(err).ShouldNot(HaveOccurred()) - - _, err = os.Stat(filepath.Join(destDir, "example.rtf")) - Ω(err).ShouldNot(HaveOccurred()) - - _, err = os.Stat(filepath.Join(destDir, "example.wtf")) - Ω(err).ShouldNot(HaveOccurred()) + Ω(*githubClient.DownloadReleaseAssetArgsForCall(0)).Should(Equal(buildAsset(0, "example.txt"))) + Ω(*githubClient.DownloadReleaseAssetArgsForCall(1)).Should(Equal(buildAsset(1, "example.rtf"))) + Ω(*githubClient.DownloadReleaseAssetArgsForCall(2)).Should(Equal(buildAsset(2, "example.wtf"))) }) }) Context("when downloading an asset fails", func() { BeforeEach(func() { - server.Close() - server = nil + githubClient.DownloadReleaseAssetReturns(nil, errors.New("not this time")) + inResponse, inErr = command.Run(destDir, inRequest) }) It("returns an error", func() { @@ -195,6 +173,7 @@ var _ = Describe("In Command", func() { BeforeEach(func() { githubClient.ListReleaseAssetsReturns(nil, disaster) + inResponse, inErr = command.Run(destDir, inRequest) }) It("returns the error", func() { @@ -203,29 +182,25 @@ var _ = Describe("In Command", func() { }) }) - Context("when the specified version is not available", func() { - BeforeEach(func() { - inRequest.Version = &resource.Version{ - Tag: "v0.36.0", - } - }) - - It("returns an error", func() { - Ω(inErr).Should(HaveOccurred()) - }) - }) - Context("when the version is not specified", func() { BeforeEach(func() { + githubClient.LatestReleaseReturns(buildRelease(1, "v0.37.0"), nil) + + githubClient.ListReleaseAssetsReturns([]github.ReleaseAsset{ + buildAsset(0, "something.tgz"), + }, nil) + inRequest.Version = nil + inResponse, inErr = command.Run(destDir, inRequest) }) It("succeeds", func() { Ω(inErr).ShouldNot(HaveOccurred()) + Ω(githubClient.GetReleaseByTagCallCount()).Should(Equal(0)) }) It("returns the fetched version", func() { - Ω(inResponse.Version).Should(Equal(resource.Version{Tag: "v0.35.0"})) + Ω(inResponse.Version).Should(Equal(resource.Version{Tag: "v0.37.0"})) }) It("has some sweet metadata", func() { @@ -243,7 +218,7 @@ var _ = Describe("In Command", func() { tag, err := ioutil.ReadFile(filepath.Join(destDir, "tag")) Ω(err).ShouldNot(HaveOccurred()) - Ω(string(tag)).Should(Equal("v0.35.0")) + Ω(string(tag)).Should(Equal("v0.37.0")) }) It("stores version in a file", func() { @@ -253,37 +228,65 @@ var _ = Describe("In Command", func() { version, err := ioutil.ReadFile(filepath.Join(destDir, "version")) Ω(err).ShouldNot(HaveOccurred()) - Ω(string(version)).Should(Equal("0.35.0")) + Ω(string(version)).Should(Equal("0.37.0")) }) It("fetches from the latest release", func() { - _, err := os.Stat(filepath.Join(destDir, "example.txt")) - Ω(err).ShouldNot(HaveOccurred()) - - _, err = os.Stat(filepath.Join(destDir, "example.rtf")) - Ω(err).ShouldNot(HaveOccurred()) - - _, err = os.Stat(filepath.Join(destDir, "example.wtf")) - Ω(err).ShouldNot(HaveOccurred()) + Ω(*githubClient.DownloadReleaseAssetArgsForCall(0)).Should(Equal(buildAsset(0, "something.tgz"))) }) }) }) - Context("when no releases are present", func() { + Context("when no tagged release is present", func() { BeforeEach(func() { - githubClient.ListReleasesReturns([]github.RepositoryRelease{}, nil) + githubClient.GetReleaseByTagReturns(nil, nil) + + inRequest.Version = &resource.Version{ + Tag: "v0.40.0", + } + + inResponse, inErr = command.Run(destDir, inRequest) }) It("returns an error", func() { - Ω(inErr).Should(HaveOccurred()) + Ω(inErr).Should(MatchError("no releases")) }) }) - Context("when listing releases fails", func() { + Context("when no latest release is present", func() { + BeforeEach(func() { + githubClient.LatestReleaseReturns(nil, nil) + inResponse, inErr = command.Run(destDir, inRequest) + }) + + It("returns an error", func() { + Ω(inErr).Should(MatchError("no releases")) + }) + }) + + Context("when getting a tagged release fails", func() { disaster := errors.New("nope") BeforeEach(func() { - githubClient.ListReleasesReturns(nil, disaster) + githubClient.GetReleaseByTagReturns(nil, disaster) + + inRequest.Version = &resource.Version{ + Tag: "some-tag", + } + inResponse, inErr = command.Run(destDir, inRequest) + }) + + It("returns the error", func() { + Ω(inErr).Should(Equal(disaster)) + }) + }) + + Context("when getting the latest release fails", func() { + disaster := errors.New("nope-again") + + BeforeEach(func() { + githubClient.LatestReleaseReturns(nil, disaster) + inResponse, inErr = command.Run(destDir, inRequest) }) It("returns the error", func() { diff --git a/metadata.go b/metadata.go index 5c0c828..1139f33 100644 --- a/metadata.go +++ b/metadata.go @@ -1,6 +1,6 @@ package resource -import "github.com/google/go-github/github" +import "github.com/zachgersh/go-github/github" func metadataFromRelease(release *github.RepositoryRelease) []MetadataPair { metadata := []MetadataPair{} diff --git a/out_command.go b/out_command.go index a86333a..d478de0 100644 --- a/out_command.go +++ b/out_command.go @@ -8,7 +8,7 @@ import ( "path/filepath" "strings" - "github.com/google/go-github/github" + "github.com/zachgersh/go-github/github" ) type OutCommand struct { diff --git a/out_command_test.go b/out_command_test.go index 6db7825..75f1dfd 100644 --- a/out_command_test.go +++ b/out_command_test.go @@ -11,7 +11,7 @@ import ( "github.com/concourse/github-release-resource" "github.com/concourse/github-release-resource/fakes" - "github.com/google/go-github/github" + "github.com/zachgersh/go-github/github" ) func file(path, contents string) {