+Gnahz
+Google Inc.
+griffin_stewie
+Guillaume Jacquet
+Guz Alexander
+Guðmundur Bjarni Ólafsson
+Hanno Hecker
+Hari haran
+haya14busa
+Huy Tr
+huydx
+i2bskn
+Isao Jonas
+isqua
+Jameel Haffejee
+Jan Kosecki
+Jeremy Morris
+Jesse Newland
+Jihoon Chung
+Jimmi Dyson
+Joan Saum
+Joe Tsai
+John Barton
+John Engelman
+jpbelanger-mtl
+Juan Basso
+Julien Garcia Gonzalez
+Julien Rostand
+Justin Abrahms
+Jusung Lee
+jzhoucliqr
+Katrina Owen
+Keita Urashima
+Kevin Burke
+Konrad Malawski
+Kookheon Kwon
+Krzysztof Kowalczyk
+Kshitij Saraogi
+kyokomi
+Lucas Alcantara
+Luke Evers
+Luke Kysow
+Luke Roberts
+Luke Young
+Maksim Zhylinski
+Martin-Louis Bright
+Marwan Sulaiman
+Mat Geist
+Matt
+Matt Brender
+Matt Landis
+Maxime Bury
+Michael Spiegel
+Michael Tiller
+Michał Glapa
+Nathan VanBenschoten
+Neil O'Toole
+Nick Miyake
+Nick Spragg
+Nikhita Raghunath
+Noah Zoschke
+ns-cweber
+Oleg Kovalov
+Ondřej Kupka
+Panagiotis Moustafellos
+Parham Alvani
+Parker Moore
+parkhyukjun89
+Pavel Shtanko
+Pete Wagner
+Petr Shevtsov
+Pierre Carrier
+Piotr Zurek
+Quinn Slack
+Rackspace US, Inc.
+Radek Simko
+Rajendra arora
+RaviTeja Pothana
+rc1140
+Red Hat, Inc.
+Rob Figueiredo
+Rohit Upadhyay
+Ronak Jain
+Ruben Vereecken
+Ryan Lower
+Sahil Dua
+saisi
+Sam Minnée
+Sandeep Sukhani
+Sander van Harmelen
+Sanket Payghan
+Sarasa Kisaragi
+Sean Wang
+Sebastian Mandrean
+Sebastian Mæland Pedersen
+Sevki
+Shagun Khemka
+Shawn Catanzarite
+Shawn Smith
+sona-tar
+SoundCloud, Ltd.
+Stian Eikeland
+Thomas Bruyelle
+Timothée Peignier
+Trey Tacon
+ttacon
+Varadarajan Aravamudhan
+Victor Castell
+Victor Vrantchan
+Vlad Ungureanu
+Will Maier
+William Bailey
+Yann Malet
+Yannick Utard
+Yicheng Qin
+Yumikiyo Osanai
+Zach Latta
diff --git a/vendor/github.com/google/go-github/CONTRIBUTING.md b/vendor/github.com/google/go-github/CONTRIBUTING.md
new file mode 100644
index 0000000..8da635a
--- /dev/null
+++ b/vendor/github.com/google/go-github/CONTRIBUTING.md
@@ -0,0 +1,114 @@
+# How to contribute #
+
+We'd love to accept your patches and contributions to this project. There are
+a just a few small guidelines you need to follow.
+
+
+## Contributor License Agreement ##
+
+Contributions to any Google project must be accompanied by a Contributor
+License Agreement. This is not a copyright **assignment**, it simply gives
+Google permission to use and redistribute your contributions as part of the
+project. Head over to to see your current
+agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+
+## Submitting a patch ##
+
+ 1. It's generally best to start by opening a new issue describing the bug or
+ feature you're intending to fix. Even if you think it's relatively minor,
+ it's helpful to know what people are working on. Mention in the initial
+ issue that you are planning to work on that bug or feature so that it can
+ be assigned to you.
+
+ 1. Follow the normal process of [forking][] the project, and setup a new
+ branch to work in. It's important that each group of changes be done in
+ separate branches in order to ensure that a pull request only includes the
+ commits related to that bug or feature.
+
+ 1. Go makes it very simple to ensure properly formatted code, so always run
+ `go fmt` on your code before committing it. You should also run
+ [golint][] over your code. As noted in the [golint readme][], it's not
+ strictly necessary that your code be completely "lint-free", but this will
+ help you find common style issues.
+
+ 1. Any significant changes should almost always be accompanied by tests. The
+ project already has good test coverage, so look at some of the existing
+ tests if you're unsure how to go about it. [gocov][] and [gocov-html][]
+ are invaluable tools for seeing which parts of your code aren't being
+ exercised by your tests.
+
+ 1. Please run:
+ * `go generate github.com/google/go-github/...`
+ * `go test github.com/google/go-github/...`
+ * `go vet github.com/google/go-github/...`
+
+ 1. Do your best to have [well-formed commit messages][] for each change.
+ This provides consistency throughout the project, and ensures that commit
+ messages are able to be formatted properly by various git tools.
+
+ 1. Finally, push the commits to your fork and submit a [pull request][].
+
+[forking]: https://help.github.com/articles/fork-a-repo
+[golint]: https://github.com/golang/lint
+[golint readme]: https://github.com/golang/lint/blob/master/README.md
+[gocov]: https://github.com/axw/gocov
+[gocov-html]: https://github.com/matm/gocov-html
+[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
+[squash]: http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
+[pull request]: https://help.github.com/articles/creating-a-pull-request
+
+
+## Other notes on code organization ##
+
+Currently, everything is defined in the main `github` package, with API methods
+broken into separate service objects. These services map directly to how
+the [GitHub API documentation][] is organized, so use that as your guide for
+where to put new methods.
+
+Code is organized in files also based pretty closely on the GitHub API
+documentation, following the format `{service}_{api}.go`. For example, methods
+defined at live in
+[repos_hooks.go][].
+
+[GitHub API documentation]: https://developer.github.com/v3/
+[repos_hooks.go]: https://github.com/google/go-github/blob/master/github/repos_hooks.go
+
+
+## Maintainer's Guide ##
+
+(These notes are mostly only for people merging in pull requests.)
+
+**Verify CLAs.** CLAs must be on file for the pull request submitter and commit
+author(s). Google's CLA verification system should handle this automatically
+and will set commit statuses as appropriate. If there's ever any question about
+a pull request, ask [willnorris](https://github.com/willnorris).
+
+**Always try to maintain a clean, linear git history.** With very few
+exceptions, running `git log` should not show a bunch of branching and merging.
+
+Never use the GitHub "merge" button, since it always creates a merge commit.
+Instead, check out the pull request locally ([these git aliases
+help][git-aliases]), then cherry-pick or rebase them onto master. If there are
+small cleanup commits, especially as a result of addressing code review
+comments, these should almost always be squashed down to a single commit. Don't
+bother squashing commits that really deserve to be separate though. If needed,
+feel free to amend additional small changes to the code or commit message that
+aren't worth going through code review for.
+
+If you made any changes like squashing commits, rebasing onto master, etc, then
+GitHub won't recognize that this is the same commit in order to mark the pull
+request as "merged". So instead, amend the commit message to include a line
+"Fixes #0", referencing the pull request number. This would be in addition to
+any other "Fixes" lines for closing related issues. If you forget to do this,
+you can also leave a comment on the pull request [like this][rebase-comment].
+If you made any other changes, it's worth noting that as well, [like
+this][modified-comment].
+
+[git-aliases]: https://github.com/willnorris/dotfiles/blob/d640d010c23b1116bdb3d4dc12088ed26120d87d/git/.gitconfig#L13-L15
+[rebase-comment]: https://github.com/google/go-github/pull/277#issuecomment-183035491
+[modified-comment]: https://github.com/google/go-github/pull/280#issuecomment-184859046
diff --git a/vendor/github.com/google/go-github/LICENSE b/vendor/github.com/google/go-github/LICENSE
new file mode 100644
index 0000000..28b6486
--- /dev/null
+++ b/vendor/github.com/google/go-github/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2013 The go-github AUTHORS. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/google/go-github/README.md b/vendor/github.com/google/go-github/README.md
new file mode 100644
index 0000000..3e2483d
--- /dev/null
+++ b/vendor/github.com/google/go-github/README.md
@@ -0,0 +1,262 @@
+# go-github #
+
+[](https://godoc.org/github.com/google/go-github/github) [](https://travis-ci.org/google/go-github) [](https://coveralls.io/r/google/go-github?branch=master) [](https://groups.google.com/group/go-github)
+
+go-github is a Go client library for accessing the [GitHub API v3][].
+
+go-github requires Go version 1.9 or greater.
+
+If you're interested in using the [GraphQL API v4][], the recommended library is
+[shurcooL/githubv4][].
+
+## Usage ##
+
+```go
+import "github.com/google/go-github/v18/github"
+```
+
+Construct a new GitHub client, then use the various services on the client to
+access different parts of the GitHub API. For example:
+
+```go
+client := github.NewClient(nil)
+
+// list all organizations for user "willnorris"
+orgs, _, err := client.Organizations.List(context.Background(), "willnorris", nil)
+```
+
+Some API methods have optional parameters that can be passed. For example:
+
+```go
+client := github.NewClient(nil)
+
+// list public repositories for org "github"
+opt := &github.RepositoryListByOrgOptions{Type: "public"}
+repos, _, err := client.Repositories.ListByOrg(context.Background(), "github", opt)
+```
+
+The services of a client divide the API into logical chunks and correspond to
+the structure of the GitHub API documentation at
+https://developer.github.com/v3/.
+
+NOTE: Using the [context](https://godoc.org/context) package, one can easily
+pass cancelation signals and deadlines to various services of the client for
+handling a request. In case there is no context available, then `context.Background()`
+can be used as a starting point.
+
+For more sample code snippets, head over to the
+[example](https://github.com/google/go-github/tree/master/example) directory.
+
+### 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 [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:
+
+```go
+import "golang.org/x/oauth2"
+
+func main() {
+ ctx := context.Background()
+ ts := oauth2.StaticTokenSource(
+ &oauth2.Token{AccessToken: "... your access token ..."},
+ )
+ tc := oauth2.NewClient(ctx, ts)
+
+ client := github.NewClient(tc)
+
+ // list all repositories for the authenticated user
+ repos, _, err := client.Repositories.List(ctx, "", 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.
+
+See the [oauth2 docs][] for complete instructions on using that library.
+
+For API methods that require HTTP Basic Authentication, use the
+[`BasicAuthTransport`](https://godoc.org/github.com/google/go-github/github#BasicAuthTransport).
+
+GitHub Apps authentication can be provided by the [ghinstallation](https://github.com/bradleyfalzon/ghinstallation)
+package.
+
+```go
+import "github.com/bradleyfalzon/ghinstallation"
+
+func main() {
+ // Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99.
+ itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "2016-10-19.private-key.pem")
+ if err != nil {
+ // Handle error.
+ }
+
+ // Use installation transport with client.
+ client := github.NewClient(&http.Client{Transport: itr})
+
+ // Use client...
+}
+```
+
+### Rate Limiting ###
+
+GitHub imposes a rate limit on all API clients. Unauthenticated clients are
+limited to 60 requests per hour, while authenticated clients can make up to
+5,000 requests per hour. The Search API has a custom rate limit. Unauthenticated
+clients are limited to 10 requests per minute, while authenticated clients
+can make up to 30 requests per minute. To receive the higher rate limit when
+making calls that are not issued on behalf of a user,
+use `UnauthenticatedRateLimitedTransport`.
+
+The returned `Response.Rate` value contains the rate limit information
+from the most recent API call. If a recent enough response isn't
+available, you can use `RateLimits` to fetch the most up-to-date rate
+limit data for the client.
+
+To detect an API rate limit error, you can check if its type is `*github.RateLimitError`:
+
+```go
+repos, _, err := client.Repositories.List(ctx, "", nil)
+if _, ok := err.(*github.RateLimitError); ok {
+ log.Println("hit rate limit")
+}
+```
+
+Learn more about GitHub rate limiting at
+https://developer.github.com/v3/#rate-limiting.
+
+### Accepted Status ###
+
+Some endpoints may return a 202 Accepted status code, meaning that the
+information required is not yet ready and was scheduled to be gathered on
+the GitHub side. Methods known to behave like this are documented specifying
+this behavior.
+
+To detect this condition of error, you can check if its type is
+`*github.AcceptedError`:
+
+```go
+stats, _, err := client.Repositories.ListContributorsStats(ctx, org, repo)
+if _, ok := err.(*github.AcceptedError); ok {
+ log.Println("scheduled on GitHub side")
+}
+```
+
+### Conditional Requests ###
+
+The GitHub API has good support for conditional requests which will help
+prevent you from burning through your rate limit, as well as help speed up your
+application. `go-github` does not handle conditional requests directly, but is
+instead designed to work with a caching `http.Transport`. We recommend using
+https://github.com/gregjones/httpcache for that.
+
+Learn more about GitHub conditional requests at
+https://developer.github.com/v3/#conditional-requests.
+
+### Creating and Updating Resources ###
+
+All structs for GitHub resources use pointer values for all non-repeated fields.
+This allows distinguishing between unset fields and those set to a zero-value.
+Helper functions have been provided to easily create these pointers for string,
+bool, and int values. For example:
+
+```go
+// create a new private repository named "foo"
+repo := &github.Repository{
+ Name: github.String("foo"),
+ Private: github.Bool(true),
+}
+client.Repositories.Create(ctx, "", repo)
+```
+
+Users who have worked with protocol buffers should find this pattern familiar.
+
+### Pagination ###
+
+All requests for resource collections (repos, pull requests, issues, etc.)
+support pagination. Pagination options are described in the
+`github.ListOptions` struct and passed to the list methods directly or as an
+embedded type of a more specific list options struct (for example
+`github.PullRequestListOptions`). Pages information is available via the
+`github.Response` struct.
+
+```go
+client := github.NewClient(nil)
+
+opt := &github.RepositoryListByOrgOptions{
+ ListOptions: github.ListOptions{PerPage: 10},
+}
+// get all pages of results
+var allRepos []*github.Repository
+for {
+ repos, resp, err := client.Repositories.ListByOrg(ctx, "github", opt)
+ if err != nil {
+ return err
+ }
+ allRepos = append(allRepos, repos...)
+ if resp.NextPage == 0 {
+ break
+ }
+ opt.Page = resp.NextPage
+}
+```
+
+For complete usage of go-github, see the full [package docs][].
+
+[GitHub API v3]: https://developer.github.com/v3/
+[oauth2]: https://github.com/golang/oauth2
+[oauth2 docs]: https://godoc.org/golang.org/x/oauth2
+[personal API token]: https://github.com/blog/1509-personal-api-tokens
+[package docs]: https://godoc.org/github.com/google/go-github/github
+[GraphQL API v4]: https://developer.github.com/v4/
+[shurcooL/githubv4]: https://github.com/shurcooL/githubv4
+
+### Integration Tests ###
+
+You can run integration tests from the `test` directory. See the integration tests [README](test/README.md).
+
+## Roadmap ##
+
+This library is being initially developed for an internal application at
+Google, so API methods will likely be implemented in the order that they are
+needed by that application. You can track the status of implementation in
+[this Google spreadsheet][roadmap].
+
+[roadmap]: https://docs.google.com/spreadsheet/ccc?key=0ApoVX4GOiXr-dGNKN1pObFh6ek1DR2FKUjBNZ1FmaEE&usp=sharing
+
+## Contributing ##
+I would like to cover the entire GitHub API and contributions are of course always welcome. The
+calling pattern is pretty well established, so adding new methods is relatively
+straightforward. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for details.
+
+## Versioning ##
+
+In general, go-github follows [semver](https://semver.org/) as closely as we
+can for tagging releases of the package. For self-contained libraries, the
+application of semantic versioning is relatively straightforward and generally
+understood. But because go-github is a client library for the GitHub API, which
+itself changes behavior, and because we are typically pretty aggressive about
+implementing preview features of the GitHub API, we've adopted the following
+versioning policy:
+
+* We increment the **major version** with any incompatible change to
+ non-preview functionality, including changes to the exported Go API surface
+ or behavior of the API.
+* We increment the **minor version** with any backwards-compatible changes to
+ functionality, as well as any changes to preview functionality in the GitHub
+ API. GitHub makes no guarantee about the stability of preview functionality,
+ so neither do we consider it a stable part of the go-github API.
+* We increment the **patch version** with any backwards-compatible bug fixes.
+
+Preview functionality may take the form of entire methods or simply additional
+data returned from an otherwise non-preview method. Refer to the GitHub API
+documentation for details on preview functionality.
+
+## License ##
+
+This library is distributed under the BSD-style license found in the [LICENSE](./LICENSE)
+file.
diff --git a/vendor/github.com/google/go-github/example/appengine/app.go b/vendor/github.com/google/go-github/example/appengine/app.go
new file mode 100644
index 0000000..38f24e4
--- /dev/null
+++ b/vendor/github.com/google/go-github/example/appengine/app.go
@@ -0,0 +1,49 @@
+// Copyright 2017 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 demo provides an app that shows how to use the github package on
+// Google App Engine.
+package demo
+
+import (
+ "fmt"
+ "net/http"
+ "os"
+
+ "github.com/google/go-github/v18/github"
+ "golang.org/x/oauth2"
+ "google.golang.org/appengine"
+ "google.golang.org/appengine/log"
+)
+
+func init() {
+ http.HandleFunc("/", handler)
+}
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path != "/" {
+ http.NotFound(w, r)
+ return
+ }
+
+ ctx := appengine.NewContext(r)
+ ts := oauth2.StaticTokenSource(
+ &oauth2.Token{AccessToken: os.Getenv("GITHUB_AUTH_TOKEN")},
+ )
+ tc := oauth2.NewClient(ctx, ts)
+ client := github.NewClient(tc)
+
+ commits, _, err := client.Repositories.ListCommits(ctx, "google", "go-github", nil)
+ if err != nil {
+ log.Errorf(ctx, "ListCommits: %v", err)
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+ for _, commit := range commits {
+ fmt.Fprintln(w, commit.GetHTMLURL())
+ }
+}
diff --git a/vendor/github.com/google/go-github/example/appengine/app.yaml b/vendor/github.com/google/go-github/example/appengine/app.yaml
new file mode 100644
index 0000000..dca235f
--- /dev/null
+++ b/vendor/github.com/google/go-github/example/appengine/app.yaml
@@ -0,0 +1,14 @@
+# Copyright 2017 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.
+
+runtime: go
+api_version: go1
+
+handlers:
+- url: /.*
+ script: _go_app
+
+env_variables:
+ GITHUB_AUTH_TOKEN: "-your-auth-token-here-"
diff --git a/vendor/github.com/google/go-github/example/basicauth/main.go b/vendor/github.com/google/go-github/example/basicauth/main.go
new file mode 100644
index 0000000..8dfd68a
--- /dev/null
+++ b/vendor/github.com/google/go-github/example/basicauth/main.go
@@ -0,0 +1,55 @@
+// 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.
+
+// The basicauth command demonstrates using the github.BasicAuthTransport,
+// including handling two-factor authentication. This won't currently work for
+// accounts that use SMS to receive one-time passwords.
+package main
+
+import (
+ "bufio"
+ "context"
+ "fmt"
+ "os"
+ "strings"
+ "syscall"
+
+ "github.com/google/go-github/v18/github"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+func main() {
+ r := bufio.NewReader(os.Stdin)
+ fmt.Print("GitHub Username: ")
+ username, _ := r.ReadString('\n')
+
+ fmt.Print("GitHub Password: ")
+ bytePassword, _ := terminal.ReadPassword(int(syscall.Stdin))
+ password := string(bytePassword)
+
+ tp := github.BasicAuthTransport{
+ Username: strings.TrimSpace(username),
+ Password: strings.TrimSpace(password),
+ }
+
+ client := github.NewClient(tp.Client())
+ ctx := context.Background()
+ user, _, err := client.Users.Get(ctx, "")
+
+ // Is this a two-factor auth error? If so, prompt for OTP and try again.
+ if _, ok := err.(*github.TwoFactorAuthError); ok {
+ fmt.Print("\nGitHub OTP: ")
+ otp, _ := r.ReadString('\n')
+ tp.OTP = strings.TrimSpace(otp)
+ user, _, err = client.Users.Get(ctx, "")
+ }
+
+ if err != nil {
+ fmt.Printf("\nerror: %v\n", err)
+ return
+ }
+
+ fmt.Printf("\n%v\n", github.Stringify(user))
+}
diff --git a/vendor/github.com/google/go-github/example/commitpr/main.go b/vendor/github.com/google/go-github/example/commitpr/main.go
new file mode 100644
index 0000000..80ac88e
--- /dev/null
+++ b/vendor/github.com/google/go-github/example/commitpr/main.go
@@ -0,0 +1,216 @@
+// Copyright 2018 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.
+
+// The commitpr command utilizes go-github as a CLI tool for
+// pushing files to a branch and creating a pull request from it.
+// It takes an auth token as an environment variable and creates
+// the commit and the PR under the account affiliated with that token.
+//
+// The purpose of this example is to show how to use refs, trees and commits to
+// create commits and pull requests.
+//
+// Note, if you want to push a single file, you probably prefer to use the
+// content API. An example is available here:
+// https://godoc.org/github.com/google/go-github/github#example-RepositoriesService-CreateFile
+//
+// Note, for this to work at least 1 commit is needed, so you if you use this
+// after creating a repository you might want to make sure you set `AutoInit` to
+// `true`.
+package main
+
+import (
+ "context"
+ "errors"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "strings"
+ "time"
+
+ "github.com/google/go-github/v18/github"
+ "golang.org/x/oauth2"
+)
+
+var (
+ sourceOwner = flag.String("source-owner", "", "Name of the owner (user or org) of the repo to create the commit in.")
+ sourceRepo = flag.String("source-repo", "", "Name of repo to create the commit in.")
+ commitMessage = flag.String("commit-message", "", "Content of the commit message.")
+ commitBranch = flag.String("commit-branch", "", "Name of branch to create the commit in. If it does not already exists, it will be created using the `base-branch` parameter")
+ baseBranch = flag.String("base-branch", "master", "Name of branch to create the `commit-branch` from.")
+ prRepoOwner = flag.String("merge-repo-owner", "", "Name of the owner (user or org) of the repo to create the PR against. If not specified, the value of the `-source-owner` flag will be used.")
+ prRepo = flag.String("merge-repo", "", "Name of repo to create the PR against. If not specified, the value of the `-source-repo` flag will be used.")
+ prBranch = flag.String("merge-branch", "master", "Name of branch to create the PR against (the one you want to merge your branch in via the PR).")
+ prSubject = flag.String("pr-title", "", "Title of the pull request. If not specified, no pull request will be created.")
+ prDescription = flag.String("pr-text", "", "Text to put in the description of the pull request.")
+ sourceFiles = flag.String("files", "", `Comma-separated list of files to commit and their location.
+The local file is separated by its target location by a semi-colon.
+If the file should be in the same location with the same name, you can just put the file name and omit the repetition.
+Example: README.md,main.go:github/examples/commitpr/main.go`)
+ authorName = flag.String("author-name", "", "Name of the author of the commit.")
+ authorEmail = flag.String("author-email", "", "Email of the author of the commit.")
+)
+
+var client *github.Client
+var ctx = context.Background()
+
+// getRef returns the commit branch reference object if it exists or creates it
+// from the base branch before returning it.
+func getRef() (ref *github.Reference, err error) {
+ if ref, _, err = client.Git.GetRef(ctx, *sourceOwner, *sourceRepo, "refs/heads/"+*commitBranch); err == nil {
+ return ref, nil
+ }
+
+ // We consider that an error means the branch has not been found and needs to
+ // be created.
+ if *commitBranch == *baseBranch {
+ return nil, errors.New("The commit branch does not exist but `-base-branch` is the same as `-commit-branch`")
+ }
+
+ if *baseBranch == "" {
+ return nil, errors.New("The `-base-branch` should not be set to an empty string when the branch specified by `-commit-branch` does not exists")
+ }
+
+ var baseRef *github.Reference
+ if baseRef, _, err = client.Git.GetRef(ctx, *sourceOwner, *sourceRepo, "refs/heads/"+*baseBranch); err != nil {
+ return nil, err
+ }
+ newRef := &github.Reference{Ref: github.String("refs/heads/" + *commitBranch), Object: &github.GitObject{SHA: baseRef.Object.SHA}}
+ ref, _, err = client.Git.CreateRef(ctx, *sourceOwner, *sourceRepo, newRef)
+ return ref, err
+}
+
+// getTree generates the tree to commit based on the given files and the commit
+// of the ref you got in getRef.
+func getTree(ref *github.Reference) (tree *github.Tree, err error) {
+ // Create a tree with what to commit.
+ entries := []github.TreeEntry{}
+
+ // Load each file into the tree.
+ for _, fileArg := range strings.Split(*sourceFiles, ",") {
+ file, content, err := getFileContent(fileArg)
+ if err != nil {
+ return nil, err
+ }
+ entries = append(entries, github.TreeEntry{Path: github.String(file), Type: github.String("blob"), Content: github.String(string(content)), Mode: github.String("100644")})
+ }
+
+ tree, _, err = client.Git.CreateTree(ctx, *sourceOwner, *sourceRepo, *ref.Object.SHA, entries)
+ return tree, err
+}
+
+// getFileContent loads the local content of a file and return the target name
+// of the file in the target repository and its contents.
+func getFileContent(fileArg string) (targetName string, b []byte, err error) {
+ var localFile string
+ files := strings.Split(fileArg, ":")
+ switch {
+ case len(files) < 1:
+ return "", nil, errors.New("empty `-files` parameter")
+ case len(files) == 1:
+ localFile = files[0]
+ targetName = files[0]
+ default:
+ localFile = files[0]
+ targetName = files[1]
+ }
+
+ b, err = ioutil.ReadFile(localFile)
+ return targetName, b, err
+}
+
+// createCommit creates the commit in the given reference using the given tree.
+func pushCommit(ref *github.Reference, tree *github.Tree) (err error) {
+ // Get the parent commit to attach the commit to.
+ parent, _, err := client.Repositories.GetCommit(ctx, *sourceOwner, *sourceRepo, *ref.Object.SHA)
+ if err != nil {
+ return err
+ }
+ // This is not always populated, but is needed.
+ parent.Commit.SHA = parent.SHA
+
+ // Create the commit using the tree.
+ date := time.Now()
+ author := &github.CommitAuthor{Date: &date, Name: authorName, Email: authorEmail}
+ commit := &github.Commit{Author: author, Message: commitMessage, Tree: tree, Parents: []github.Commit{*parent.Commit}}
+ newCommit, _, err := client.Git.CreateCommit(ctx, *sourceOwner, *sourceRepo, commit)
+ if err != nil {
+ return err
+ }
+
+ // Attach the commit to the master branch.
+ ref.Object.SHA = newCommit.SHA
+ _, _, err = client.Git.UpdateRef(ctx, *sourceOwner, *sourceRepo, ref, false)
+ return err
+}
+
+// createPR creates a pull requesit. Based on: https://godoc.org/github.com/google/go-github/github#example-PullRequestsService-Create
+func createPR() (err error) {
+ if *prSubject == "" {
+ return errors.New("missing `-pr-title` flag; skipping PR creation")
+ }
+
+ if *prRepoOwner != "" && *prRepoOwner != *sourceOwner {
+ *commitBranch = fmt.Sprintf("%s:%s", *sourceOwner, *commitBranch)
+ } else {
+ prRepoOwner = sourceOwner
+ }
+
+ if *prRepo == "" {
+ prRepo = sourceRepo
+ }
+
+ newPR := &github.NewPullRequest{
+ Title: prSubject,
+ Head: commitBranch,
+ Base: prBranch,
+ Body: prDescription,
+ MaintainerCanModify: github.Bool(true),
+ }
+
+ pr, _, err := client.PullRequests.Create(ctx, *prRepoOwner, *prRepo, newPR)
+ if err != nil {
+ return err
+ }
+
+ fmt.Printf("PR created: %s\n", pr.GetHTMLURL())
+ return nil
+}
+
+func main() {
+ flag.Parse()
+ token := os.Getenv("GITHUB_AUTH_TOKEN")
+ if token == "" {
+ log.Fatal("Unauthorized: No token present")
+ }
+ if *sourceOwner == "" || *sourceRepo == "" || *commitBranch == "" || *sourceFiles == "" || *authorName == "" || *authorEmail == "" {
+ log.Fatal("You need to specify a non-empty value for the flags `-source-owner`, `-source-repo`, `-commit-branch`, `-files`, `-author-name` and `-author-email`")
+ }
+ ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
+ tc := oauth2.NewClient(ctx, ts)
+ client = github.NewClient(tc)
+
+ ref, err := getRef()
+ if err != nil {
+ log.Fatalf("Unable to get/create the commit reference: %s\n", err)
+ }
+ if ref == nil {
+ log.Fatalf("No error where returned but the reference is nil")
+ }
+
+ tree, err := getTree(ref)
+ if err != nil {
+ log.Fatalf("Unable to create the tree based on the provided files: %s\n", err)
+ }
+
+ if err := pushCommit(ref, tree); err != nil {
+ log.Fatalf("Unable to create the commit: %s\n", err)
+ }
+
+ if err := createPR(); err != nil {
+ log.Fatalf("Error while creating the pull request: %s", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/example/migrations/main.go b/vendor/github.com/google/go-github/example/migrations/main.go
new file mode 100644
index 0000000..d826606
--- /dev/null
+++ b/vendor/github.com/google/go-github/example/migrations/main.go
@@ -0,0 +1,40 @@
+// Copyright 2018 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.
+
+// migrations demonstrates the functionality of
+// the user data migration API for the authenticated GitHub
+// user and lists all the user migrations.
+package main
+
+import (
+ "context"
+ "fmt"
+ "github.com/google/go-github/v18/github"
+ "golang.org/x/oauth2"
+)
+
+func fetchAllUserMigrations() ([]*github.UserMigration, error) {
+ ctx := context.Background()
+ ts := oauth2.StaticTokenSource(
+ &oauth2.Token{AccessToken: ""},
+ )
+ tc := oauth2.NewClient(ctx, ts)
+ client := github.NewClient(tc)
+
+ migrations, _, err := client.Migrations.ListUserMigrations(ctx)
+ return migrations, err
+}
+
+func main() {
+ migrations, err := fetchAllUserMigrations()
+ if err != nil {
+ fmt.Printf("Error %v\n", err)
+ return
+ }
+
+ for i, m := range migrations {
+ fmt.Printf("%v. %v", i+1, m.GetID())
+ }
+}
diff --git a/vendor/github.com/google/go-github/example/newrepo/main.go b/vendor/github.com/google/go-github/example/newrepo/main.go
new file mode 100644
index 0000000..49fba77
--- /dev/null
+++ b/vendor/github.com/google/go-github/example/newrepo/main.go
@@ -0,0 +1,49 @@
+// Copyright 2018 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.
+
+// The newrepo command utilizes go-github as a cli tool for
+// creating new repositories. It takes an auth token as
+// an enviroment variable and creates the new repo under
+// the account affiliated with that token.
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "log"
+ "os"
+
+ "github.com/google/go-github/v18/github"
+ "golang.org/x/oauth2"
+)
+
+var (
+ name = flag.String("name", "", "Name of repo to create in authenticated user's GitHub account.")
+ description = flag.String("description", "", "Description of created repo.")
+ private = flag.Bool("private", false, "Will created repo be private.")
+)
+
+func main() {
+ flag.Parse()
+ token := os.Getenv("GITHUB_AUTH_TOKEN")
+ if token == "" {
+ log.Fatal("Unauthorized: No token present")
+ }
+ if *name == "" {
+ log.Fatal("No name: New repos must be given a name")
+ }
+ ctx := context.Background()
+ ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
+ tc := oauth2.NewClient(ctx, ts)
+ client := github.NewClient(tc)
+
+ r := &github.Repository{Name: name, Private: private, Description: description}
+ repo, _, err := client.Repositories.Create(ctx, "", r)
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Printf("Successfully created new repo: %v\n", repo.GetName())
+}
diff --git a/vendor/github.com/google/go-github/example/simple/main.go b/vendor/github.com/google/go-github/example/simple/main.go
new file mode 100644
index 0000000..5f2ce20
--- /dev/null
+++ b/vendor/github.com/google/go-github/example/simple/main.go
@@ -0,0 +1,40 @@
+// Copyright 2017 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.
+
+// The simple command demonstrates a simple functionality which
+// prompts the user for a GitHub username and lists all the public
+// organization memberships of the specified username.
+package main
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/google/go-github/v18/github"
+)
+
+// Fetch all the public organizations' membership of a user.
+//
+func FetchOrganizations(username string) ([]*github.Organization, error) {
+ client := github.NewClient(nil)
+ orgs, _, err := client.Organizations.List(context.Background(), username, nil)
+ return orgs, err
+}
+
+func main() {
+ var username string
+ fmt.Print("Enter GitHub username: ")
+ fmt.Scanf("%s", &username)
+
+ organizations, err := FetchOrganizations(username)
+ if err != nil {
+ fmt.Printf("Error: %v\n", err)
+ return
+ }
+
+ for i, organization := range organizations {
+ fmt.Printf("%v. %v\n", i+1, organization.GetLogin())
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/activity.go b/vendor/github.com/google/go-github/github/activity.go
new file mode 100644
index 0000000..d6c992c
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/activity.go
@@ -0,0 +1,69 @@
+// 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 "context"
+
+// ActivityService handles communication with the activity related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/
+type ActivityService service
+
+// FeedLink represents a link to a related resource.
+type FeedLink struct {
+ HRef *string `json:"href,omitempty"`
+ Type *string `json:"type,omitempty"`
+}
+
+// Feeds represents timeline resources in Atom format.
+type Feeds struct {
+ TimelineURL *string `json:"timeline_url,omitempty"`
+ UserURL *string `json:"user_url,omitempty"`
+ CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"`
+ CurrentUserURL *string `json:"current_user_url,omitempty"`
+ CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"`
+ CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"`
+ CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"`
+ Links *struct {
+ Timeline *FeedLink `json:"timeline,omitempty"`
+ User *FeedLink `json:"user,omitempty"`
+ CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"`
+ CurrentUser *FeedLink `json:"current_user,omitempty"`
+ CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"`
+ CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"`
+ CurrentUserOrganizations []FeedLink `json:"current_user_organizations,omitempty"`
+ } `json:"_links,omitempty"`
+}
+
+// ListFeeds lists all the feeds available to the authenticated user.
+//
+// GitHub provides several timeline resources in Atom format:
+// Timeline: The GitHub global public timeline
+// User: The public timeline for any user, using URI template
+// Current user public: The public timeline for the authenticated user
+// Current user: The private timeline for the authenticated user
+// Current user actor: The private timeline for activity created by the
+// authenticated user
+// Current user organizations: The private timeline for the organizations
+// the authenticated user is a member of.
+//
+// Note: Private feeds are only returned when authenticating via Basic Auth
+// since current feed URIs use the older, non revocable auth tokens.
+func (s *ActivityService) ListFeeds(ctx context.Context) (*Feeds, *Response, error) {
+ req, err := s.client.NewRequest("GET", "feeds", nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ f := &Feeds{}
+ resp, err := s.client.Do(ctx, req, f)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return f, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/activity_events.go b/vendor/github.com/google/go-github/github/activity_events.go
new file mode 100644
index 0000000..a919b11
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/activity_events.go
@@ -0,0 +1,328 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+// Event represents a GitHub event.
+type Event struct {
+ Type *string `json:"type,omitempty"`
+ Public *bool `json:"public,omitempty"`
+ RawPayload *json.RawMessage `json:"payload,omitempty"`
+ Repo *Repository `json:"repo,omitempty"`
+ Actor *User `json:"actor,omitempty"`
+ Org *Organization `json:"org,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ ID *string `json:"id,omitempty"`
+}
+
+func (e Event) String() string {
+ return Stringify(e)
+}
+
+// ParsePayload parses the event payload. For recognized event types,
+// a value of the corresponding struct type will be returned.
+func (e *Event) ParsePayload() (payload interface{}, err error) {
+ switch *e.Type {
+ case "CheckRunEvent":
+ payload = &CheckRunEvent{}
+ case "CheckSuiteEvent":
+ payload = &CheckSuiteEvent{}
+ case "CommitCommentEvent":
+ payload = &CommitCommentEvent{}
+ case "CreateEvent":
+ payload = &CreateEvent{}
+ case "DeleteEvent":
+ payload = &DeleteEvent{}
+ case "DeploymentEvent":
+ payload = &DeploymentEvent{}
+ case "DeploymentStatusEvent":
+ payload = &DeploymentStatusEvent{}
+ case "ForkEvent":
+ payload = &ForkEvent{}
+ case "GollumEvent":
+ payload = &GollumEvent{}
+ case "InstallationEvent":
+ payload = &InstallationEvent{}
+ case "InstallationRepositoriesEvent":
+ payload = &InstallationRepositoriesEvent{}
+ case "IssueCommentEvent":
+ payload = &IssueCommentEvent{}
+ case "IssuesEvent":
+ payload = &IssuesEvent{}
+ case "LabelEvent":
+ payload = &LabelEvent{}
+ case "MarketplacePurchaseEvent":
+ payload = &MarketplacePurchaseEvent{}
+ case "MemberEvent":
+ payload = &MemberEvent{}
+ case "MembershipEvent":
+ payload = &MembershipEvent{}
+ case "MilestoneEvent":
+ payload = &MilestoneEvent{}
+ case "OrganizationEvent":
+ payload = &OrganizationEvent{}
+ case "OrgBlockEvent":
+ payload = &OrgBlockEvent{}
+ case "PageBuildEvent":
+ payload = &PageBuildEvent{}
+ case "PingEvent":
+ payload = &PingEvent{}
+ case "ProjectEvent":
+ payload = &ProjectEvent{}
+ case "ProjectCardEvent":
+ payload = &ProjectCardEvent{}
+ case "ProjectColumnEvent":
+ payload = &ProjectColumnEvent{}
+ case "PublicEvent":
+ payload = &PublicEvent{}
+ case "PullRequestEvent":
+ payload = &PullRequestEvent{}
+ case "PullRequestReviewEvent":
+ payload = &PullRequestReviewEvent{}
+ case "PullRequestReviewCommentEvent":
+ payload = &PullRequestReviewCommentEvent{}
+ case "PushEvent":
+ payload = &PushEvent{}
+ case "ReleaseEvent":
+ payload = &ReleaseEvent{}
+ case "RepositoryEvent":
+ payload = &RepositoryEvent{}
+ case "StatusEvent":
+ payload = &StatusEvent{}
+ case "TeamEvent":
+ payload = &TeamEvent{}
+ case "TeamAddEvent":
+ payload = &TeamAddEvent{}
+ case "WatchEvent":
+ payload = &WatchEvent{}
+ }
+ err = json.Unmarshal(*e.RawPayload, &payload)
+ return payload, err
+}
+
+// Payload returns the parsed event payload. For recognized event types,
+// a value of the corresponding struct type will be returned.
+//
+// Deprecated: Use ParsePayload instead, which returns an error
+// rather than panics if JSON unmarshaling raw payload fails.
+func (e *Event) Payload() (payload interface{}) {
+ var err error
+ payload, err = e.ParsePayload()
+ if err != nil {
+ panic(err)
+ }
+ return payload
+}
+
+// ListEvents drinks from the firehose of all public events across GitHub.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events
+func (s *ActivityService) ListEvents(ctx context.Context, opt *ListOptions) ([]*Event, *Response, error) {
+ u, err := addOptions("events", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var events []*Event
+ resp, err := s.client.Do(ctx, req, &events)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return events, resp, nil
+}
+
+// ListRepositoryEvents lists events for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/#list-repository-events
+func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Event, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/events", owner, repo)
+ 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
+ }
+
+ var events []*Event
+ resp, err := s.client.Do(ctx, req, &events)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return events, resp, nil
+}
+
+// ListIssueEventsForRepository lists issue events for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/#list-issue-events-for-a-repository
+func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo)
+ 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
+ }
+
+ var events []*IssueEvent
+ resp, err := s.client.Do(ctx, req, &events)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return events, resp, nil
+}
+
+// ListEventsForRepoNetwork lists public events for a network of repositories.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-a-network-of-repositories
+func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Event, *Response, error) {
+ u := fmt.Sprintf("networks/%v/%v/events", owner, repo)
+ 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
+ }
+
+ var events []*Event
+ resp, err := s.client.Do(ctx, req, &events)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return events, resp, nil
+}
+
+// ListEventsForOrganization lists public events for an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-an-organization
+func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opt *ListOptions) ([]*Event, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/events", 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
+ }
+
+ var events []*Event
+ resp, err := s.client.Do(ctx, req, &events)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return events, resp, nil
+}
+
+// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is
+// true, only public events will be returned.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-performed-by-a-user
+func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opt *ListOptions) ([]*Event, *Response, error) {
+ var u string
+ if publicOnly {
+ u = fmt.Sprintf("users/%v/events/public", user)
+ } else {
+ u = fmt.Sprintf("users/%v/events", user)
+ }
+ 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
+ }
+
+ var events []*Event
+ resp, err := s.client.Do(ctx, req, &events)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return events, resp, nil
+}
+
+// ListEventsReceivedByUser lists the events received by a user. If publicOnly is
+// true, only public events will be returned.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-that-a-user-has-received
+func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opt *ListOptions) ([]*Event, *Response, error) {
+ var u string
+ if publicOnly {
+ u = fmt.Sprintf("users/%v/received_events/public", user)
+ } else {
+ u = fmt.Sprintf("users/%v/received_events", user)
+ }
+ 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
+ }
+
+ var events []*Event
+ resp, err := s.client.Do(ctx, req, &events)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return events, resp, nil
+}
+
+// ListUserEventsForOrganization provides the user’s organization dashboard. You
+// must be authenticated as the user to view this.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-for-an-organization
+func (s *ActivityService) ListUserEventsForOrganization(ctx context.Context, org, user string, opt *ListOptions) ([]*Event, *Response, error) {
+ u := fmt.Sprintf("users/%v/events/orgs/%v", user, 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
+ }
+
+ var events []*Event
+ resp, err := s.client.Do(ctx, req, &events)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return events, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/activity_events_test.go b/vendor/github.com/google/go-github/github/activity_events_test.go
new file mode 100644
index 0000000..0b01c4a
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/activity_events_test.go
@@ -0,0 +1,349 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestActivityService_ListEvents(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/events", 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}
+ events, _, err := client.Activity.ListEvents(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Activities.ListEvents returned error: %v", err)
+ }
+
+ want := []*Event{{ID: String("1")}, {ID: String("2")}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Activities.ListEvents returned %+v, want %+v", events, want)
+ }
+}
+
+func TestActivityService_ListRepositoryEvents(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/events", 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}
+ events, _, err := client.Activity.ListRepositoryEvents(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Activities.ListRepositoryEvents returned error: %v", err)
+ }
+
+ want := []*Event{{ID: String("1")}, {ID: String("2")}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Activities.ListRepositoryEvents returned %+v, want %+v", events, want)
+ }
+}
+
+func TestActivityService_ListRepositoryEvents_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Activity.ListRepositoryEvents(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestActivityService_ListIssueEventsForRepository(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/events", 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}
+ events, _, err := client.Activity.ListIssueEventsForRepository(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Activities.ListIssueEventsForRepository returned error: %v", err)
+ }
+
+ want := []*IssueEvent{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Activities.ListIssueEventsForRepository returned %+v, want %+v", events, want)
+ }
+}
+
+func TestActivityService_ListIssueEventsForRepository_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Activity.ListIssueEventsForRepository(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestActivityService_ListEventsForRepoNetwork(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/networks/o/r/events", 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}
+ events, _, err := client.Activity.ListEventsForRepoNetwork(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Activities.ListEventsForRepoNetwork returned error: %v", err)
+ }
+
+ want := []*Event{{ID: String("1")}, {ID: String("2")}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Activities.ListEventsForRepoNetwork returned %+v, want %+v", events, want)
+ }
+}
+
+func TestActivityService_ListEventsForRepoNetwork_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Activity.ListEventsForRepoNetwork(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestActivityService_ListEventsForOrganization(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/events", 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}
+ events, _, err := client.Activity.ListEventsForOrganization(context.Background(), "o", opt)
+ if err != nil {
+ t.Errorf("Activities.ListEventsForOrganization returned error: %v", err)
+ }
+
+ want := []*Event{{ID: String("1")}, {ID: String("2")}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Activities.ListEventsForOrganization returned %+v, want %+v", events, want)
+ }
+}
+
+func TestActivityService_ListEventsForOrganization_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Activity.ListEventsForOrganization(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestActivityService_ListEventsPerformedByUser_all(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/events", 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}
+ events, _, err := client.Activity.ListEventsPerformedByUser(context.Background(), "u", false, opt)
+ if err != nil {
+ t.Errorf("Events.ListPerformedByUser returned error: %v", err)
+ }
+
+ want := []*Event{{ID: String("1")}, {ID: String("2")}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Events.ListPerformedByUser returned %+v, want %+v", events, want)
+ }
+}
+
+func TestActivityService_ListEventsPerformedByUser_publicOnly(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/events/public", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`)
+ })
+
+ events, _, err := client.Activity.ListEventsPerformedByUser(context.Background(), "u", true, nil)
+ if err != nil {
+ t.Errorf("Events.ListPerformedByUser returned error: %v", err)
+ }
+
+ want := []*Event{{ID: String("1")}, {ID: String("2")}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Events.ListPerformedByUser returned %+v, want %+v", events, want)
+ }
+}
+
+func TestActivityService_ListEventsPerformedByUser_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Activity.ListEventsPerformedByUser(context.Background(), "%", false, nil)
+ testURLParseError(t, err)
+}
+
+func TestActivityService_ListEventsReceivedByUser_all(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/received_events", 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}
+ events, _, err := client.Activity.ListEventsReceivedByUser(context.Background(), "u", false, opt)
+ if err != nil {
+ t.Errorf("Events.ListReceivedByUser returned error: %v", err)
+ }
+
+ want := []*Event{{ID: String("1")}, {ID: String("2")}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Events.ListReceivedUser returned %+v, want %+v", events, want)
+ }
+}
+
+func TestActivityService_ListEventsReceivedByUser_publicOnly(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/received_events/public", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`)
+ })
+
+ events, _, err := client.Activity.ListEventsReceivedByUser(context.Background(), "u", true, nil)
+ if err != nil {
+ t.Errorf("Events.ListReceivedByUser returned error: %v", err)
+ }
+
+ want := []*Event{{ID: String("1")}, {ID: String("2")}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Events.ListReceivedByUser returned %+v, want %+v", events, want)
+ }
+}
+
+func TestActivityService_ListEventsReceivedByUser_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Activity.ListEventsReceivedByUser(context.Background(), "%", false, nil)
+ testURLParseError(t, err)
+}
+
+func TestActivityService_ListUserEventsForOrganization(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/events/orgs/o", 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}
+ events, _, err := client.Activity.ListUserEventsForOrganization(context.Background(), "o", "u", opt)
+ if err != nil {
+ t.Errorf("Activities.ListUserEventsForOrganization returned error: %v", err)
+ }
+
+ want := []*Event{{ID: String("1")}, {ID: String("2")}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Activities.ListUserEventsForOrganization returned %+v, want %+v", events, want)
+ }
+}
+
+func TestActivityService_EventParsePayload_typed(t *testing.T) {
+ raw := []byte(`{"type": "PushEvent","payload":{"push_id": 1}}`)
+ var event *Event
+ if err := json.Unmarshal(raw, &event); err != nil {
+ t.Fatalf("Unmarshal Event returned error: %v", err)
+ }
+
+ want := &PushEvent{PushID: Int64(1)}
+ got, err := event.ParsePayload()
+ if err != nil {
+ t.Fatalf("ParsePayload returned unexpected error: %v", err)
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Event.ParsePayload returned %+v, want %+v", got, want)
+ }
+}
+
+// TestEvent_Payload_untyped checks that unrecognized events are parsed to an
+// interface{} value (instead of being discarded or throwing an error), for
+// forward compatibility with new event types.
+func TestActivityService_EventParsePayload_untyped(t *testing.T) {
+ raw := []byte(`{"type": "UnrecognizedEvent","payload":{"field": "val"}}`)
+ var event *Event
+ if err := json.Unmarshal(raw, &event); err != nil {
+ t.Fatalf("Unmarshal Event returned error: %v", err)
+ }
+
+ want := map[string]interface{}{"field": "val"}
+ got, err := event.ParsePayload()
+ if err != nil {
+ t.Fatalf("ParsePayload returned unexpected error: %v", err)
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Event.ParsePayload returned %+v, want %+v", got, want)
+ }
+}
+
+func TestActivityService_EventParsePayload_installation(t *testing.T) {
+ raw := []byte(`{"type": "PullRequestEvent","payload":{"installation":{"id":1}}}`)
+ var event *Event
+ if err := json.Unmarshal(raw, &event); err != nil {
+ t.Fatalf("Unmarshal Event returned error: %v", err)
+ }
+
+ want := &PullRequestEvent{Installation: &Installation{ID: Int64(1)}}
+ got, err := event.ParsePayload()
+ if err != nil {
+ t.Fatalf("ParsePayload returned unexpected error: %v", err)
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Event.ParsePayload returned %+v, want %+v", got, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/activity_notifications.go b/vendor/github.com/google/go-github/github/activity_notifications.go
new file mode 100644
index 0000000..45c8b2a
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/activity_notifications.go
@@ -0,0 +1,223 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// Notification identifies a GitHub notification for a user.
+type Notification struct {
+ ID *string `json:"id,omitempty"`
+ Repository *Repository `json:"repository,omitempty"`
+ Subject *NotificationSubject `json:"subject,omitempty"`
+
+ // Reason identifies the event that triggered the notification.
+ //
+ // GitHub API docs: https://developer.github.com/v3/activity/notifications/#notification-reasons
+ Reason *string `json:"reason,omitempty"`
+
+ Unread *bool `json:"unread,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+ LastReadAt *time.Time `json:"last_read_at,omitempty"`
+ URL *string `json:"url,omitempty"`
+}
+
+// NotificationSubject identifies the subject of a notification.
+type NotificationSubject struct {
+ Title *string `json:"title,omitempty"`
+ URL *string `json:"url,omitempty"`
+ LatestCommentURL *string `json:"latest_comment_url,omitempty"`
+ Type *string `json:"type,omitempty"`
+}
+
+// NotificationListOptions specifies the optional parameters to the
+// ActivityService.ListNotifications method.
+type NotificationListOptions struct {
+ All bool `url:"all,omitempty"`
+ Participating bool `url:"participating,omitempty"`
+ Since time.Time `url:"since,omitempty"`
+ Before time.Time `url:"before,omitempty"`
+
+ ListOptions
+}
+
+// ListNotifications lists all notifications for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications
+func (s *ActivityService) ListNotifications(ctx context.Context, opt *NotificationListOptions) ([]*Notification, *Response, error) {
+ u := fmt.Sprintf("notifications")
+ 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
+ }
+
+ var notifications []*Notification
+ resp, err := s.client.Do(ctx, req, ¬ifications)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return notifications, resp, nil
+}
+
+// ListRepositoryNotifications lists all notifications in a given repository
+// for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications-in-a-repository
+func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner, repo string, opt *NotificationListOptions) ([]*Notification, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo)
+ 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
+ }
+
+ var notifications []*Notification
+ resp, err := s.client.Do(ctx, req, ¬ifications)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return notifications, resp, nil
+}
+
+type markReadOptions struct {
+ LastReadAt time.Time `json:"last_read_at,omitempty"`
+}
+
+// MarkNotificationsRead marks all notifications up to lastRead as read.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-as-read
+func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead time.Time) (*Response, error) {
+ opts := &markReadOptions{
+ LastReadAt: lastRead,
+ }
+ req, err := s.client.NewRequest("PUT", "notifications", opts)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// MarkRepositoryNotificationsRead marks all notifications up to lastRead in
+// the specified repository as read.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-notifications-as-read-in-a-repository
+func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead time.Time) (*Response, error) {
+ opts := &markReadOptions{
+ LastReadAt: lastRead,
+ }
+ u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo)
+ req, err := s.client.NewRequest("PUT", u, opts)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// GetThread gets the specified notification thread.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/notifications/#view-a-single-thread
+func (s *ActivityService) GetThread(ctx context.Context, id string) (*Notification, *Response, error) {
+ u := fmt.Sprintf("notifications/threads/%v", id)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ notification := new(Notification)
+ resp, err := s.client.Do(ctx, req, notification)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return notification, resp, nil
+}
+
+// MarkThreadRead marks the specified thread as read.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-a-thread-as-read
+func (s *ActivityService) MarkThreadRead(ctx context.Context, id string) (*Response, error) {
+ u := fmt.Sprintf("notifications/threads/%v", id)
+
+ req, err := s.client.NewRequest("PATCH", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// GetThreadSubscription checks to see if the authenticated user is subscribed
+// to a thread.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/notifications/#get-a-thread-subscription
+func (s *ActivityService) GetThreadSubscription(ctx context.Context, id string) (*Subscription, *Response, error) {
+ u := fmt.Sprintf("notifications/threads/%v/subscription", id)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ sub := new(Subscription)
+ resp, err := s.client.Do(ctx, req, sub)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return sub, resp, nil
+}
+
+// SetThreadSubscription sets the subscription for the specified thread for the
+// authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/notifications/#set-a-thread-subscription
+func (s *ActivityService) SetThreadSubscription(ctx context.Context, id string, subscription *Subscription) (*Subscription, *Response, error) {
+ u := fmt.Sprintf("notifications/threads/%v/subscription", id)
+
+ req, err := s.client.NewRequest("PUT", u, subscription)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ sub := new(Subscription)
+ resp, err := s.client.Do(ctx, req, sub)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return sub, resp, nil
+}
+
+// DeleteThreadSubscription deletes the subscription for the specified thread
+// for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/notifications/#delete-a-thread-subscription
+func (s *ActivityService) DeleteThreadSubscription(ctx context.Context, id string) (*Response, error) {
+ u := fmt.Sprintf("notifications/threads/%v/subscription", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/activity_notifications_test.go b/vendor/github.com/google/go-github/github/activity_notifications_test.go
new file mode 100644
index 0000000..a36b253
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/activity_notifications_test.go
@@ -0,0 +1,204 @@
+// Copyright 2014 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestActivityService_ListNotification(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/notifications", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "all": "true",
+ "participating": "true",
+ "since": "2006-01-02T15:04:05Z",
+ "before": "2007-03-04T15:04:05Z",
+ })
+
+ fmt.Fprint(w, `[{"id":"1", "subject":{"title":"t"}}]`)
+ })
+
+ opt := &NotificationListOptions{
+ All: true,
+ Participating: true,
+ Since: time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC),
+ Before: time.Date(2007, time.March, 04, 15, 04, 05, 0, time.UTC),
+ }
+ notifications, _, err := client.Activity.ListNotifications(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Activity.ListNotifications returned error: %v", err)
+ }
+
+ want := []*Notification{{ID: String("1"), Subject: &NotificationSubject{Title: String("t")}}}
+ if !reflect.DeepEqual(notifications, want) {
+ t.Errorf("Activity.ListNotifications returned %+v, want %+v", notifications, want)
+ }
+}
+
+func TestActivityService_ListRepositoryNotification(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/notifications", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":"1"}]`)
+ })
+
+ notifications, _, err := client.Activity.ListRepositoryNotifications(context.Background(), "o", "r", nil)
+ if err != nil {
+ t.Errorf("Activity.ListRepositoryNotifications returned error: %v", err)
+ }
+
+ want := []*Notification{{ID: String("1")}}
+ if !reflect.DeepEqual(notifications, want) {
+ t.Errorf("Activity.ListRepositoryNotifications returned %+v, want %+v", notifications, want)
+ }
+}
+
+func TestActivityService_MarkNotificationsRead(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/notifications", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ testHeader(t, r, "Content-Type", "application/json")
+ testBody(t, r, `{"last_read_at":"2006-01-02T15:04:05Z"}`+"\n")
+
+ w.WriteHeader(http.StatusResetContent)
+ })
+
+ _, err := client.Activity.MarkNotificationsRead(context.Background(), time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC))
+ if err != nil {
+ t.Errorf("Activity.MarkNotificationsRead returned error: %v", err)
+ }
+}
+
+func TestActivityService_MarkRepositoryNotificationsRead(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/notifications", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ testHeader(t, r, "Content-Type", "application/json")
+ testBody(t, r, `{"last_read_at":"2006-01-02T15:04:05Z"}`+"\n")
+
+ w.WriteHeader(http.StatusResetContent)
+ })
+
+ _, err := client.Activity.MarkRepositoryNotificationsRead(context.Background(), "o", "r", time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC))
+ if err != nil {
+ t.Errorf("Activity.MarkRepositoryNotificationsRead returned error: %v", err)
+ }
+}
+
+func TestActivityService_GetThread(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/notifications/threads/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":"1"}`)
+ })
+
+ notification, _, err := client.Activity.GetThread(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Activity.GetThread returned error: %v", err)
+ }
+
+ want := &Notification{ID: String("1")}
+ if !reflect.DeepEqual(notification, want) {
+ t.Errorf("Activity.GetThread returned %+v, want %+v", notification, want)
+ }
+}
+
+func TestActivityService_MarkThreadRead(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/notifications/threads/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PATCH")
+ w.WriteHeader(http.StatusResetContent)
+ })
+
+ _, err := client.Activity.MarkThreadRead(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Activity.MarkThreadRead returned error: %v", err)
+ }
+}
+
+func TestActivityService_GetThreadSubscription(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/notifications/threads/1/subscription", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"subscribed":true}`)
+ })
+
+ sub, _, err := client.Activity.GetThreadSubscription(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Activity.GetThreadSubscription returned error: %v", err)
+ }
+
+ want := &Subscription{Subscribed: Bool(true)}
+ if !reflect.DeepEqual(sub, want) {
+ t.Errorf("Activity.GetThreadSubscription returned %+v, want %+v", sub, want)
+ }
+}
+
+func TestActivityService_SetThreadSubscription(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Subscription{Subscribed: Bool(true)}
+
+ mux.HandleFunc("/notifications/threads/1/subscription", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Subscription)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PUT")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"ignored":true}`)
+ })
+
+ sub, _, err := client.Activity.SetThreadSubscription(context.Background(), "1", input)
+ if err != nil {
+ t.Errorf("Activity.SetThreadSubscription returned error: %v", err)
+ }
+
+ want := &Subscription{Ignored: Bool(true)}
+ if !reflect.DeepEqual(sub, want) {
+ t.Errorf("Activity.SetThreadSubscription returned %+v, want %+v", sub, want)
+ }
+}
+
+func TestActivityService_DeleteThreadSubscription(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/notifications/threads/1/subscription", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Activity.DeleteThreadSubscription(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Activity.DeleteThreadSubscription returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/activity_star.go b/vendor/github.com/google/go-github/github/activity_star.go
new file mode 100644
index 0000000..5ae5c10
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/activity_star.go
@@ -0,0 +1,137 @@
+// 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 (
+ "context"
+ "fmt"
+ "strings"
+)
+
+// StarredRepository is returned by ListStarred.
+type StarredRepository struct {
+ StarredAt *Timestamp `json:"starred_at,omitempty"`
+ Repository *Repository `json:"repo,omitempty"`
+}
+
+// Stargazer represents a user that has starred a repository.
+type Stargazer struct {
+ StarredAt *Timestamp `json:"starred_at,omitempty"`
+ User *User `json:"user,omitempty"`
+}
+
+// ListStargazers lists people who have starred the specified repo.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-stargazers
+func (s *ActivityService) ListStargazers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Stargazer, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/stargazers", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeStarringPreview)
+
+ var stargazers []*Stargazer
+ resp, err := s.client.Do(ctx, req, &stargazers)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return stargazers, resp, nil
+}
+
+// ActivityListStarredOptions specifies the optional parameters to the
+// ActivityService.ListStarred method.
+type ActivityListStarredOptions struct {
+ // How to sort the repository list. Possible values are: created, updated,
+ // pushed, full_name. Default is "full_name".
+ Sort string `url:"sort,omitempty"`
+
+ // Direction in which to sort repositories. Possible values are: asc, desc.
+ // Default is "asc" when sort is "full_name", otherwise default is "desc".
+ Direction string `url:"direction,omitempty"`
+
+ ListOptions
+}
+
+// ListStarred lists all the repos starred by a user. Passing the empty string
+// will list the starred repositories for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-repositories-being-starred
+func (s *ActivityService) ListStarred(ctx context.Context, user string, opt *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v/starred", user)
+ } else {
+ u = "user/starred"
+ }
+ 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
+ }
+
+ // TODO: remove custom Accept header when APIs fully launch
+ acceptHeaders := []string{mediaTypeStarringPreview, mediaTypeTopicsPreview}
+ req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+ var repos []*StarredRepository
+ resp, err := s.client.Do(ctx, req, &repos)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return repos, resp, nil
+}
+
+// IsStarred checks if a repository is starred by authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/starring/#check-if-you-are-starring-a-repository
+func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bool, *Response, error) {
+ u := fmt.Sprintf("user/starred/%v/%v", owner, repo)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+ resp, err := s.client.Do(ctx, req, nil)
+ starred, err := parseBoolResponse(err)
+ return starred, resp, err
+}
+
+// Star a repository as the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/starring/#star-a-repository
+func (s *ActivityService) Star(ctx context.Context, owner, repo string) (*Response, error) {
+ u := fmt.Sprintf("user/starred/%v/%v", owner, repo)
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
+
+// Unstar a repository as the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/starring/#unstar-a-repository
+func (s *ActivityService) Unstar(ctx context.Context, owner, repo string) (*Response, error) {
+ u := fmt.Sprintf("user/starred/%v/%v", owner, repo)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/activity_star_test.go b/vendor/github.com/google/go-github/github/activity_star_test.go
new file mode 100644
index 0000000..8a12247
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/activity_star_test.go
@@ -0,0 +1,185 @@
+// 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+)
+
+func TestActivityService_ListStargazers(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/stargazers", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeStarringPreview)
+ testFormValues(t, r, values{
+ "page": "2",
+ })
+
+ fmt.Fprint(w, `[{"starred_at":"2002-02-10T15:30:00Z","user":{"id":1}}]`)
+ })
+
+ stargazers, _, err := client.Activity.ListStargazers(context.Background(), "o", "r", &ListOptions{Page: 2})
+ if err != nil {
+ t.Errorf("Activity.ListStargazers returned error: %v", err)
+ }
+
+ want := []*Stargazer{{StarredAt: &Timestamp{time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)}, User: &User{ID: Int64(1)}}}
+ if !reflect.DeepEqual(stargazers, want) {
+ t.Errorf("Activity.ListStargazers returned %+v, want %+v", stargazers, want)
+ }
+}
+
+func TestActivityService_ListStarred_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/starred", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join([]string{mediaTypeStarringPreview, mediaTypeTopicsPreview}, ", "))
+ fmt.Fprint(w, `[{"starred_at":"2002-02-10T15:30:00Z","repo":{"id":1}}]`)
+ })
+
+ repos, _, err := client.Activity.ListStarred(context.Background(), "", nil)
+ if err != nil {
+ t.Errorf("Activity.ListStarred returned error: %v", err)
+ }
+
+ want := []*StarredRepository{{StarredAt: &Timestamp{time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)}, Repository: &Repository{ID: Int64(1)}}}
+ if !reflect.DeepEqual(repos, want) {
+ t.Errorf("Activity.ListStarred returned %+v, want %+v", repos, want)
+ }
+}
+
+func TestActivityService_ListStarred_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/starred", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join([]string{mediaTypeStarringPreview, mediaTypeTopicsPreview}, ", "))
+ testFormValues(t, r, values{
+ "sort": "created",
+ "direction": "asc",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"starred_at":"2002-02-10T15:30:00Z","repo":{"id":2}}]`)
+ })
+
+ opt := &ActivityListStarredOptions{"created", "asc", ListOptions{Page: 2}}
+ repos, _, err := client.Activity.ListStarred(context.Background(), "u", opt)
+ if err != nil {
+ t.Errorf("Activity.ListStarred returned error: %v", err)
+ }
+
+ want := []*StarredRepository{{StarredAt: &Timestamp{time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)}, Repository: &Repository{ID: Int64(2)}}}
+ if !reflect.DeepEqual(repos, want) {
+ t.Errorf("Activity.ListStarred returned %+v, want %+v", repos, want)
+ }
+}
+
+func TestActivityService_ListStarred_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Activity.ListStarred(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestActivityService_IsStarred_hasStar(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/starred/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ star, _, err := client.Activity.IsStarred(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Activity.IsStarred returned error: %v", err)
+ }
+ if want := true; star != want {
+ t.Errorf("Activity.IsStarred returned %+v, want %+v", star, want)
+ }
+}
+
+func TestActivityService_IsStarred_noStar(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/starred/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNotFound)
+ })
+
+ star, _, err := client.Activity.IsStarred(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Activity.IsStarred returned error: %v", err)
+ }
+ if want := false; star != want {
+ t.Errorf("Activity.IsStarred returned %+v, want %+v", star, want)
+ }
+}
+
+func TestActivityService_IsStarred_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Activity.IsStarred(context.Background(), "%", "%")
+ testURLParseError(t, err)
+}
+
+func TestActivityService_Star(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/starred/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ })
+
+ _, err := client.Activity.Star(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Activity.Star returned error: %v", err)
+ }
+}
+
+func TestActivityService_Star_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Activity.Star(context.Background(), "%", "%")
+ testURLParseError(t, err)
+}
+
+func TestActivityService_Unstar(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/starred/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Activity.Unstar(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Activity.Unstar returned error: %v", err)
+ }
+}
+
+func TestActivityService_Unstar_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Activity.Unstar(context.Background(), "%", "%")
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/activity_test.go b/vendor/github.com/google/go-github/github/activity_test.go
new file mode 100644
index 0000000..92b42d3
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/activity_test.go
@@ -0,0 +1,129 @@
+// Copyright 2016 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 (
+ "context"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestActivityService_List(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/feeds", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ w.WriteHeader(http.StatusOK)
+ w.Write(feedsJSON)
+ })
+
+ got, _, err := client.Activity.ListFeeds(context.Background())
+ if err != nil {
+ t.Errorf("Activity.ListFeeds returned error: %v", err)
+ }
+ if want := wantFeeds; !reflect.DeepEqual(got, want) {
+ t.Errorf("Activity.ListFeeds = %+v, want %+v", got, want)
+ }
+}
+
+var feedsJSON = []byte(`{
+ "timeline_url": "https://github.com/timeline",
+ "user_url": "https://github.com/{user}",
+ "current_user_public_url": "https://github.com/defunkt",
+ "current_user_url": "https://github.com/defunkt.private?token=abc123",
+ "current_user_actor_url": "https://github.com/defunkt.private.actor?token=abc123",
+ "current_user_organization_url": "",
+ "current_user_organization_urls": [
+ "https://github.com/organizations/github/defunkt.private.atom?token=abc123"
+ ],
+ "_links": {
+ "timeline": {
+ "href": "https://github.com/timeline",
+ "type": "application/atom+xml"
+ },
+ "user": {
+ "href": "https://github.com/{user}",
+ "type": "application/atom+xml"
+ },
+ "current_user_public": {
+ "href": "https://github.com/defunkt",
+ "type": "application/atom+xml"
+ },
+ "current_user": {
+ "href": "https://github.com/defunkt.private?token=abc123",
+ "type": "application/atom+xml"
+ },
+ "current_user_actor": {
+ "href": "https://github.com/defunkt.private.actor?token=abc123",
+ "type": "application/atom+xml"
+ },
+ "current_user_organization": {
+ "href": "",
+ "type": ""
+ },
+ "current_user_organizations": [
+ {
+ "href": "https://github.com/organizations/github/defunkt.private.atom?token=abc123",
+ "type": "application/atom+xml"
+ }
+ ]
+ }
+}`)
+
+var wantFeeds = &Feeds{
+ TimelineURL: String("https://github.com/timeline"),
+ UserURL: String("https://github.com/{user}"),
+ CurrentUserPublicURL: String("https://github.com/defunkt"),
+ CurrentUserURL: String("https://github.com/defunkt.private?token=abc123"),
+ CurrentUserActorURL: String("https://github.com/defunkt.private.actor?token=abc123"),
+ CurrentUserOrganizationURL: String(""),
+ CurrentUserOrganizationURLs: []string{
+ "https://github.com/organizations/github/defunkt.private.atom?token=abc123",
+ },
+ Links: &struct {
+ Timeline *FeedLink `json:"timeline,omitempty"`
+ User *FeedLink `json:"user,omitempty"`
+ CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"`
+ CurrentUser *FeedLink `json:"current_user,omitempty"`
+ CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"`
+ CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"`
+ CurrentUserOrganizations []FeedLink `json:"current_user_organizations,omitempty"`
+ }{
+ Timeline: &FeedLink{
+ HRef: String("https://github.com/timeline"),
+ Type: String("application/atom+xml"),
+ },
+ User: &FeedLink{
+ HRef: String("https://github.com/{user}"),
+ Type: String("application/atom+xml"),
+ },
+ CurrentUserPublic: &FeedLink{
+ HRef: String("https://github.com/defunkt"),
+ Type: String("application/atom+xml"),
+ },
+ CurrentUser: &FeedLink{
+ HRef: String("https://github.com/defunkt.private?token=abc123"),
+ Type: String("application/atom+xml"),
+ },
+ CurrentUserActor: &FeedLink{
+ HRef: String("https://github.com/defunkt.private.actor?token=abc123"),
+ Type: String("application/atom+xml"),
+ },
+ CurrentUserOrganization: &FeedLink{
+ HRef: String(""),
+ Type: String(""),
+ },
+ CurrentUserOrganizations: []FeedLink{
+ {
+ HRef: String("https://github.com/organizations/github/defunkt.private.atom?token=abc123"),
+ Type: String("application/atom+xml"),
+ },
+ },
+ },
+}
diff --git a/vendor/github.com/google/go-github/github/activity_watching.go b/vendor/github.com/google/go-github/github/activity_watching.go
new file mode 100644
index 0000000..c749ca8
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/activity_watching.go
@@ -0,0 +1,146 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+)
+
+// Subscription identifies a repository or thread subscription.
+type Subscription struct {
+ Subscribed *bool `json:"subscribed,omitempty"`
+ Ignored *bool `json:"ignored,omitempty"`
+ Reason *string `json:"reason,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ URL *string `json:"url,omitempty"`
+
+ // only populated for repository subscriptions
+ RepositoryURL *string `json:"repository_url,omitempty"`
+
+ // only populated for thread subscriptions
+ ThreadURL *string `json:"thread_url,omitempty"`
+}
+
+// ListWatchers lists watchers of a particular repo.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-watchers
+func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo)
+ 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
+ }
+
+ var watchers []*User
+ resp, err := s.client.Do(ctx, req, &watchers)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return watchers, resp, nil
+}
+
+// ListWatched lists the repositories the specified user is watching. Passing
+// the empty string will fetch watched repos for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-being-watched
+func (s *ActivityService) ListWatched(ctx context.Context, user string, opt *ListOptions) ([]*Repository, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v/subscriptions", user)
+ } else {
+ u = "user/subscriptions"
+ }
+ 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
+ }
+
+ var watched []*Repository
+ resp, err := s.client.Do(ctx, req, &watched)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return watched, resp, nil
+}
+
+// GetRepositorySubscription returns the subscription for the specified
+// repository for the authenticated user. If the authenticated user is not
+// watching the repository, a nil Subscription is returned.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/watching/#get-a-repository-subscription
+func (s *ActivityService) GetRepositorySubscription(ctx context.Context, owner, repo string) (*Subscription, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ sub := new(Subscription)
+ resp, err := s.client.Do(ctx, req, sub)
+ if err != nil {
+ // if it's just a 404, don't return that as an error
+ _, err = parseBoolResponse(err)
+ return nil, resp, err
+ }
+
+ return sub, resp, nil
+}
+
+// SetRepositorySubscription sets the subscription for the specified repository
+// for the authenticated user.
+//
+// To watch a repository, set subscription.Subscribed to true.
+// To ignore notifications made within a repository, set subscription.Ignored to true.
+// To stop watching a repository, use DeleteRepositorySubscription.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/watching/#set-a-repository-subscription
+func (s *ActivityService) SetRepositorySubscription(ctx context.Context, owner, repo string, subscription *Subscription) (*Subscription, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
+
+ req, err := s.client.NewRequest("PUT", u, subscription)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ sub := new(Subscription)
+ resp, err := s.client.Do(ctx, req, sub)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return sub, resp, nil
+}
+
+// DeleteRepositorySubscription deletes the subscription for the specified
+// repository for the authenticated user.
+//
+// This is used to stop watching a repository. To control whether or not to
+// receive notifications from a repository, use SetRepositorySubscription.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription
+func (s *ActivityService) DeleteRepositorySubscription(ctx context.Context, owner, repo string) (*Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/activity_watching_test.go b/vendor/github.com/google/go-github/github/activity_watching_test.go
new file mode 100644
index 0000000..b017d8d
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/activity_watching_test.go
@@ -0,0 +1,184 @@
+// Copyright 2014 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestActivityService_ListWatchers(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/subscribers", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "2",
+ })
+
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ watchers, _, err := client.Activity.ListWatchers(context.Background(), "o", "r", &ListOptions{Page: 2})
+ if err != nil {
+ t.Errorf("Activity.ListWatchers returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}}
+ if !reflect.DeepEqual(watchers, want) {
+ t.Errorf("Activity.ListWatchers returned %+v, want %+v", watchers, want)
+ }
+}
+
+func TestActivityService_ListWatched_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/subscriptions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ watched, _, err := client.Activity.ListWatched(context.Background(), "", &ListOptions{Page: 2})
+ if err != nil {
+ t.Errorf("Activity.ListWatched returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}}
+ if !reflect.DeepEqual(watched, want) {
+ t.Errorf("Activity.ListWatched returned %+v, want %+v", watched, want)
+ }
+}
+
+func TestActivityService_ListWatched_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/subscriptions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ watched, _, err := client.Activity.ListWatched(context.Background(), "u", &ListOptions{Page: 2})
+ if err != nil {
+ t.Errorf("Activity.ListWatched returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}}
+ if !reflect.DeepEqual(watched, want) {
+ t.Errorf("Activity.ListWatched returned %+v, want %+v", watched, want)
+ }
+}
+
+func TestActivityService_GetRepositorySubscription_true(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"subscribed":true}`)
+ })
+
+ sub, _, err := client.Activity.GetRepositorySubscription(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Activity.GetRepositorySubscription returned error: %v", err)
+ }
+
+ want := &Subscription{Subscribed: Bool(true)}
+ if !reflect.DeepEqual(sub, want) {
+ t.Errorf("Activity.GetRepositorySubscription returned %+v, want %+v", sub, want)
+ }
+}
+
+func TestActivityService_GetRepositorySubscription_false(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNotFound)
+ })
+
+ sub, _, err := client.Activity.GetRepositorySubscription(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Activity.GetRepositorySubscription returned error: %v", err)
+ }
+
+ var want *Subscription
+ if !reflect.DeepEqual(sub, want) {
+ t.Errorf("Activity.GetRepositorySubscription returned %+v, want %+v", sub, want)
+ }
+}
+
+func TestActivityService_GetRepositorySubscription_error(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusBadRequest)
+ })
+
+ _, _, err := client.Activity.GetRepositorySubscription(context.Background(), "o", "r")
+ if err == nil {
+ t.Errorf("Expected HTTP 400 response")
+ }
+}
+
+func TestActivityService_SetRepositorySubscription(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Subscription{Subscribed: Bool(true)}
+
+ mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Subscription)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PUT")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"ignored":true}`)
+ })
+
+ sub, _, err := client.Activity.SetRepositorySubscription(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Activity.SetRepositorySubscription returned error: %v", err)
+ }
+
+ want := &Subscription{Ignored: Bool(true)}
+ if !reflect.DeepEqual(sub, want) {
+ t.Errorf("Activity.SetRepositorySubscription returned %+v, want %+v", sub, want)
+ }
+}
+
+func TestActivityService_DeleteRepositorySubscription(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Activity.DeleteRepositorySubscription(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Activity.DeleteRepositorySubscription returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/admin.go b/vendor/github.com/google/go-github/github/admin.go
new file mode 100644
index 0000000..2d96733
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/admin.go
@@ -0,0 +1,101 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+)
+
+// AdminService handles communication with the admin related methods of the
+// GitHub API. These API routes are normally only accessible for GitHub
+// Enterprise installations.
+//
+// GitHub API docs: https://developer.github.com/v3/enterprise/
+type AdminService service
+
+// TeamLDAPMapping represents the mapping between a GitHub team and an LDAP group.
+type TeamLDAPMapping struct {
+ ID *int64 `json:"id,omitempty"`
+ LDAPDN *string `json:"ldap_dn,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Slug *string `json:"slug,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Privacy *string `json:"privacy,omitempty"`
+ Permission *string `json:"permission,omitempty"`
+
+ MembersURL *string `json:"members_url,omitempty"`
+ RepositoriesURL *string `json:"repositories_url,omitempty"`
+}
+
+func (m TeamLDAPMapping) String() string {
+ return Stringify(m)
+}
+
+// UserLDAPMapping represents the mapping between a GitHub user and an LDAP user.
+type UserLDAPMapping struct {
+ ID *int64 `json:"id,omitempty"`
+ LDAPDN *string `json:"ldap_dn,omitempty"`
+ Login *string `json:"login,omitempty"`
+ AvatarURL *string `json:"avatar_url,omitempty"`
+ GravatarID *string `json:"gravatar_id,omitempty"`
+ Type *string `json:"type,omitempty"`
+ SiteAdmin *bool `json:"site_admin,omitempty"`
+
+ URL *string `json:"url,omitempty"`
+ EventsURL *string `json:"events_url,omitempty"`
+ FollowingURL *string `json:"following_url,omitempty"`
+ FollowersURL *string `json:"followers_url,omitempty"`
+ GistsURL *string `json:"gists_url,omitempty"`
+ OrganizationsURL *string `json:"organizations_url,omitempty"`
+ ReceivedEventsURL *string `json:"received_events_url,omitempty"`
+ ReposURL *string `json:"repos_url,omitempty"`
+ StarredURL *string `json:"starred_url,omitempty"`
+ SubscriptionsURL *string `json:"subscriptions_url,omitempty"`
+}
+
+func (m UserLDAPMapping) String() string {
+ return Stringify(m)
+}
+
+// UpdateUserLDAPMapping updates the mapping between a GitHub user and an LDAP user.
+//
+// GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-user
+func (s *AdminService) UpdateUserLDAPMapping(ctx context.Context, user string, mapping *UserLDAPMapping) (*UserLDAPMapping, *Response, error) {
+ u := fmt.Sprintf("admin/ldap/users/%v/mapping", user)
+ req, err := s.client.NewRequest("PATCH", u, mapping)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ m := new(UserLDAPMapping)
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// UpdateTeamLDAPMapping updates the mapping between a GitHub team and an LDAP group.
+//
+// GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-team
+func (s *AdminService) UpdateTeamLDAPMapping(ctx context.Context, team int64, mapping *TeamLDAPMapping) (*TeamLDAPMapping, *Response, error) {
+ u := fmt.Sprintf("admin/ldap/teams/%v/mapping", team)
+ req, err := s.client.NewRequest("PATCH", u, mapping)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ m := new(TeamLDAPMapping)
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/admin_stats.go b/vendor/github.com/google/go-github/github/admin_stats.go
new file mode 100644
index 0000000..b5645f8
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/admin_stats.go
@@ -0,0 +1,171 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+)
+
+// AdminStats represents a variety of stats of a Github Enterprise
+// installation.
+type AdminStats struct {
+ Issues *IssueStats `json:"issues,omitempty"`
+ Hooks *HookStats `json:"hooks,omitempty"`
+ Milestones *MilestoneStats `json:"milestones,omitempty"`
+ Orgs *OrgStats `json:"orgs,omitempty"`
+ Comments *CommentStats `json:"comments,omitempty"`
+ Pages *PageStats `json:"pages,omitempty"`
+ Users *UserStats `json:"users,omitempty"`
+ Gists *GistStats `json:"gists,omitempty"`
+ Pulls *PullStats `json:"pulls,omitempty"`
+ Repos *RepoStats `json:"repos,omitempty"`
+}
+
+func (s AdminStats) String() string {
+ return Stringify(s)
+}
+
+// IssueStats represents the number of total, open and closed issues.
+type IssueStats struct {
+ TotalIssues *int `json:"total_issues,omitempty"`
+ OpenIssues *int `json:"open_issues,omitempty"`
+ ClosedIssues *int `json:"closed_issues,omitempty"`
+}
+
+func (s IssueStats) String() string {
+ return Stringify(s)
+}
+
+// HookStats represents the number of total, active and inactive hooks.
+type HookStats struct {
+ TotalHooks *int `json:"total_hooks,omitempty"`
+ ActiveHooks *int `json:"active_hooks,omitempty"`
+ InactiveHooks *int `json:"inactive_hooks,omitempty"`
+}
+
+func (s HookStats) String() string {
+ return Stringify(s)
+}
+
+// MilestoneStats represents the number of total, open and close milestones.
+type MilestoneStats struct {
+ TotalMilestones *int `json:"total_milestones,omitempty"`
+ OpenMilestones *int `json:"open_milestones,omitempty"`
+ ClosedMilestones *int `json:"closed_milestones,omitempty"`
+}
+
+func (s MilestoneStats) String() string {
+ return Stringify(s)
+}
+
+// OrgStats represents the number of total, disabled organizations and the team
+// and team member count.
+type OrgStats struct {
+ TotalOrgs *int `json:"total_orgs,omitempty"`
+ DisabledOrgs *int `json:"disabled_orgs,omitempty"`
+ TotalTeams *int `json:"total_teams,omitempty"`
+ TotalTeamMembers *int `json:"total_team_members,omitempty"`
+}
+
+func (s OrgStats) String() string {
+ return Stringify(s)
+}
+
+// CommentStats represents the number of total comments on commits, gists, issues
+// and pull requests.
+type CommentStats struct {
+ TotalCommitComments *int `json:"total_commit_comments,omitempty"`
+ TotalGistComments *int `json:"total_gist_comments,omitempty"`
+ TotalIssueComments *int `json:"total_issue_comments,omitempty"`
+ TotalPullRequestComments *int `json:"total_pull_request_comments,omitempty"`
+}
+
+func (s CommentStats) String() string {
+ return Stringify(s)
+}
+
+// PageStats represents the total number of github pages.
+type PageStats struct {
+ TotalPages *int `json:"total_pages,omitempty"`
+}
+
+func (s PageStats) String() string {
+ return Stringify(s)
+}
+
+// UserStats represents the number of total, admin and suspended users.
+type UserStats struct {
+ TotalUsers *int `json:"total_users,omitempty"`
+ AdminUsers *int `json:"admin_users,omitempty"`
+ SuspendedUsers *int `json:"suspended_users,omitempty"`
+}
+
+func (s UserStats) String() string {
+ return Stringify(s)
+}
+
+// GistStats represents the number of total, private and public gists.
+type GistStats struct {
+ TotalGists *int `json:"total_gists,omitempty"`
+ PrivateGists *int `json:"private_gists,omitempty"`
+ PublicGists *int `json:"public_gists,omitempty"`
+}
+
+func (s GistStats) String() string {
+ return Stringify(s)
+}
+
+// PullStats represents the number of total, merged, mergable and unmergeable
+// pull-requests.
+type PullStats struct {
+ TotalPulls *int `json:"total_pulls,omitempty"`
+ MergedPulls *int `json:"merged_pulls,omitempty"`
+ MergablePulls *int `json:"mergeable_pulls,omitempty"`
+ UnmergablePulls *int `json:"unmergeable_pulls,omitempty"`
+}
+
+func (s PullStats) String() string {
+ return Stringify(s)
+}
+
+// RepoStats represents the number of total, root, fork, organization repositories
+// together with the total number of pushes and wikis.
+type RepoStats struct {
+ TotalRepos *int `json:"total_repos,omitempty"`
+ RootRepos *int `json:"root_repos,omitempty"`
+ ForkRepos *int `json:"fork_repos,omitempty"`
+ OrgRepos *int `json:"org_repos,omitempty"`
+ TotalPushes *int `json:"total_pushes,omitempty"`
+ TotalWikis *int `json:"total_wikis,omitempty"`
+}
+
+func (s RepoStats) String() string {
+ return Stringify(s)
+}
+
+// GetAdminStats returns a variety of metrics about a Github Enterprise
+// installation.
+//
+// Please note that this is only available to site administrators,
+// otherwise it will error with a 404 not found (instead of 401 or 403).
+//
+// GitHub API docs: https://developer.github.com/v3/enterprise-admin/admin_stats/
+func (s *AdminService) GetAdminStats(ctx context.Context) (*AdminStats, *Response, error) {
+ u := fmt.Sprintf("enterprise/stats/all")
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ m := new(AdminStats)
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/admin_stats_test.go b/vendor/github.com/google/go-github/github/admin_stats_test.go
new file mode 100644
index 0000000..9433adc
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/admin_stats_test.go
@@ -0,0 +1,142 @@
+package github
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestAdminService_GetAdminStats(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/enterprise/stats/all", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ fmt.Fprint(w, `
+{
+ "repos": {
+ "total_repos": 212,
+ "root_repos": 194,
+ "fork_repos": 18,
+ "org_repos": 51,
+ "total_pushes": 3082,
+ "total_wikis": 15
+ },
+ "hooks": {
+ "total_hooks": 27,
+ "active_hooks": 23,
+ "inactive_hooks": 4
+ },
+ "pages": {
+ "total_pages": 36
+ },
+ "orgs": {
+ "total_orgs": 33,
+ "disabled_orgs": 0,
+ "total_teams": 60,
+ "total_team_members": 314
+ },
+ "users": {
+ "total_users": 254,
+ "admin_users": 45,
+ "suspended_users": 21
+ },
+ "pulls": {
+ "total_pulls": 86,
+ "merged_pulls": 60,
+ "mergeable_pulls": 21,
+ "unmergeable_pulls": 3
+ },
+ "issues": {
+ "total_issues": 179,
+ "open_issues": 83,
+ "closed_issues": 96
+ },
+ "milestones": {
+ "total_milestones": 7,
+ "open_milestones": 6,
+ "closed_milestones": 1
+ },
+ "gists": {
+ "total_gists": 178,
+ "private_gists": 151,
+ "public_gists": 25
+ },
+ "comments": {
+ "total_commit_comments": 6,
+ "total_gist_comments": 28,
+ "total_issue_comments": 366,
+ "total_pull_request_comments": 30
+ }
+}
+`)
+ })
+
+ stats, _, err := client.Admin.GetAdminStats(context.Background())
+ if err != nil {
+ t.Errorf("AdminService.GetAdminStats returned error: %v", err)
+ }
+
+ want := &AdminStats{
+ Repos: &RepoStats{
+ TotalRepos: Int(212),
+ RootRepos: Int(194),
+ ForkRepos: Int(18),
+ OrgRepos: Int(51),
+ TotalPushes: Int(3082),
+ TotalWikis: Int(15),
+ },
+ Hooks: &HookStats{
+ TotalHooks: Int(27),
+ ActiveHooks: Int(23),
+ InactiveHooks: Int(4),
+ },
+ Pages: &PageStats{
+ TotalPages: Int(36),
+ },
+ Orgs: &OrgStats{
+ TotalOrgs: Int(33),
+ DisabledOrgs: Int(0),
+ TotalTeams: Int(60),
+ TotalTeamMembers: Int(314),
+ },
+ Users: &UserStats{
+ TotalUsers: Int(254),
+ AdminUsers: Int(45),
+ SuspendedUsers: Int(21),
+ },
+ Pulls: &PullStats{
+ TotalPulls: Int(86),
+ MergedPulls: Int(60),
+ MergablePulls: Int(21),
+ UnmergablePulls: Int(3),
+ },
+ Issues: &IssueStats{
+ TotalIssues: Int(179),
+ OpenIssues: Int(83),
+ ClosedIssues: Int(96),
+ },
+ Milestones: &MilestoneStats{
+ TotalMilestones: Int(7),
+ OpenMilestones: Int(6),
+ ClosedMilestones: Int(1),
+ },
+ Gists: &GistStats{
+ TotalGists: Int(178),
+ PrivateGists: Int(151),
+ PublicGists: Int(25),
+ },
+ Comments: &CommentStats{
+ TotalCommitComments: Int(6),
+ TotalGistComments: Int(28),
+ TotalIssueComments: Int(366),
+ TotalPullRequestComments: Int(30),
+ },
+ }
+ if !reflect.DeepEqual(stats, want) {
+ t.Errorf("AdminService.GetAdminStats returned %+v, want %+v", stats, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/admin_test.go b/vendor/github.com/google/go-github/github/admin_test.go
new file mode 100644
index 0000000..8979686
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/admin_test.go
@@ -0,0 +1,81 @@
+// Copyright 2016 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestAdminService_UpdateUserLDAPMapping(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &UserLDAPMapping{
+ LDAPDN: String("uid=asdf,ou=users,dc=github,dc=com"),
+ }
+
+ mux.HandleFunc("/admin/ldap/users/u/mapping", func(w http.ResponseWriter, r *http.Request) {
+ v := new(UserLDAPMapping)
+ 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,"ldap_dn":"uid=asdf,ou=users,dc=github,dc=com"}`)
+ })
+
+ mapping, _, err := client.Admin.UpdateUserLDAPMapping(context.Background(), "u", input)
+ if err != nil {
+ t.Errorf("Admin.UpdateUserLDAPMapping returned error: %v", err)
+ }
+
+ want := &UserLDAPMapping{
+ ID: Int64(1),
+ LDAPDN: String("uid=asdf,ou=users,dc=github,dc=com"),
+ }
+ if !reflect.DeepEqual(mapping, want) {
+ t.Errorf("Admin.UpdateUserLDAPMapping returned %+v, want %+v", mapping, want)
+ }
+}
+
+func TestAdminService_UpdateTeamLDAPMapping(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &TeamLDAPMapping{
+ LDAPDN: String("cn=Enterprise Ops,ou=teams,dc=github,dc=com"),
+ }
+
+ mux.HandleFunc("/admin/ldap/teams/1/mapping", func(w http.ResponseWriter, r *http.Request) {
+ v := new(TeamLDAPMapping)
+ 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,"ldap_dn":"cn=Enterprise Ops,ou=teams,dc=github,dc=com"}`)
+ })
+
+ mapping, _, err := client.Admin.UpdateTeamLDAPMapping(context.Background(), 1, input)
+ if err != nil {
+ t.Errorf("Admin.UpdateTeamLDAPMapping returned error: %v", err)
+ }
+
+ want := &TeamLDAPMapping{
+ ID: Int64(1),
+ LDAPDN: String("cn=Enterprise Ops,ou=teams,dc=github,dc=com"),
+ }
+ if !reflect.DeepEqual(mapping, want) {
+ t.Errorf("Admin.UpdateTeamLDAPMapping returned %+v, want %+v", mapping, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/apps.go b/vendor/github.com/google/go-github/github/apps.go
new file mode 100644
index 0000000..32d4f2f
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/apps.go
@@ -0,0 +1,230 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// AppsService provides access to the installation related functions
+// in the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/
+type AppsService service
+
+// App represents a GitHub App.
+type App struct {
+ ID *int64 `json:"id,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ Owner *User `json:"owner,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Description *string `json:"description,omitempty"`
+ ExternalURL *string `json:"external_url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+}
+
+// InstallationToken represents an installation token.
+type InstallationToken struct {
+ Token *string `json:"token,omitempty"`
+ ExpiresAt *time.Time `json:"expires_at,omitempty"`
+}
+
+// InstallationPermissions lists the permissions for metadata, contents, issues and single file for an installation.
+type InstallationPermissions struct {
+ Metadata *string `json:"metadata,omitempty"`
+ Contents *string `json:"contents,omitempty"`
+ Issues *string `json:"issues,omitempty"`
+ SingleFile *string `json:"single_file,omitempty"`
+}
+
+// Installation represents a GitHub Apps installation.
+type Installation struct {
+ ID *int64 `json:"id,omitempty"`
+ AppID *int64 `json:"app_id,omitempty"`
+ TargetID *int64 `json:"target_id,omitempty"`
+ Account *User `json:"account,omitempty"`
+ AccessTokensURL *string `json:"access_tokens_url,omitempty"`
+ RepositoriesURL *string `json:"repositories_url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ TargetType *string `json:"target_type,omitempty"`
+ SingleFileName *string `json:"single_file_name,omitempty"`
+ RepositorySelection *string `json:"repository_selection,omitempty"`
+ Events []string `json:"events,omitempty"`
+ Permissions *InstallationPermissions `json:"permissions,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+}
+
+func (i Installation) String() string {
+ return Stringify(i)
+}
+
+// Get a single GitHub App. Passing the empty string will get
+// the authenticated GitHub App.
+//
+// Note: appSlug is just the URL-friendly name of your GitHub App.
+// You can find this on the settings page for your GitHub App
+// (e.g., https://github.com/settings/apps/:app_slug).
+//
+// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-github-app
+func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) {
+ var u string
+ if appSlug != "" {
+ u = fmt.Sprintf("apps/%v", appSlug)
+ } else {
+ u = "app"
+ }
+
+ 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", mediaTypeIntegrationPreview)
+
+ app := new(App)
+ resp, err := s.client.Do(ctx, req, app)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return app, resp, nil
+}
+
+// ListInstallations lists the installations that the current GitHub App has.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/#find-installations
+func (s *AppsService) ListInstallations(ctx context.Context, opt *ListOptions) ([]*Installation, *Response, error) {
+ u, err := addOptions("app/installations", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ 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", mediaTypeIntegrationPreview)
+
+ var i []*Installation
+ resp, err := s.client.Do(ctx, req, &i)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return i, resp, nil
+}
+
+// GetInstallation returns the specified installation.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-installation
+func (s *AppsService) GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) {
+ return s.getInstallation(ctx, fmt.Sprintf("app/installations/%v", id))
+}
+
+// ListUserInstallations lists installations that are accessible to the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/#list-installations-for-user
+func (s *AppsService) ListUserInstallations(ctx context.Context, opt *ListOptions) ([]*Installation, *Response, error) {
+ u, err := addOptions("user/installations", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ 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", mediaTypeIntegrationPreview)
+
+ var i struct {
+ Installations []*Installation `json:"installations"`
+ }
+ resp, err := s.client.Do(ctx, req, &i)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return i.Installations, resp, nil
+}
+
+// CreateInstallationToken creates a new installation token.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/#create-a-new-installation-token
+func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64) (*InstallationToken, *Response, error) {
+ u := fmt.Sprintf("installations/%v/access_tokens", id)
+
+ req, err := s.client.NewRequest("POST", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeIntegrationPreview)
+
+ t := new(InstallationToken)
+ resp, err := s.client.Do(ctx, req, t)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return t, resp, nil
+}
+
+// FindOrganizationInstallation finds the organization's installation information.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/#find-organization-installation
+func (s *AppsService) FindOrganizationInstallation(ctx context.Context, org string) (*Installation, *Response, error) {
+ return s.getInstallation(ctx, fmt.Sprintf("orgs/%v/installation", org))
+}
+
+// FindRepositoryInstallation finds the repository's installation information.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/#find-repository-installation
+func (s *AppsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*Installation, *Response, error) {
+ return s.getInstallation(ctx, fmt.Sprintf("repos/%v/%v/installation", owner, repo))
+}
+
+// FindRepositoryInstallationByID finds the repository's installation information.
+//
+// Note: FindRepositoryInstallationByID uses the undocumented GitHub API endpoint /repositories/:id/installation.
+func (s *AppsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*Installation, *Response, error) {
+ return s.getInstallation(ctx, fmt.Sprintf("repositories/%d/installation", id))
+}
+
+// FindUserInstallation finds the user's installation information.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/#find-repository-installation
+func (s *AppsService) FindUserInstallation(ctx context.Context, user string) (*Installation, *Response, error) {
+ return s.getInstallation(ctx, fmt.Sprintf("users/%v/installation", user))
+}
+
+func (s *AppsService) getInstallation(ctx context.Context, url string) (*Installation, *Response, error) {
+ req, err := s.client.NewRequest("GET", url, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeIntegrationPreview)
+
+ i := new(Installation)
+ resp, err := s.client.Do(ctx, req, i)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return i, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/apps_installation.go b/vendor/github.com/google/go-github/github/apps_installation.go
new file mode 100644
index 0000000..ccfecb8
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/apps_installation.go
@@ -0,0 +1,101 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+)
+
+// ListRepos lists the repositories that are accessible to the authenticated installation.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories
+func (s *AppsService) ListRepos(ctx context.Context, opt *ListOptions) ([]*Repository, *Response, error) {
+ u, err := addOptions("installation/repositories", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ 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", mediaTypeIntegrationPreview)
+
+ var r struct {
+ Repositories []*Repository `json:"repositories"`
+ }
+ resp, err := s.client.Do(ctx, req, &r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r.Repositories, resp, nil
+}
+
+// ListUserRepos lists repositories that are accessible
+// to the authenticated user for an installation.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories-accessible-to-the-user-for-an-installation
+func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opt *ListOptions) ([]*Repository, *Response, error) {
+ u := fmt.Sprintf("user/installations/%v/repositories", id)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeIntegrationPreview)
+
+ var r struct {
+ Repositories []*Repository `json:"repositories"`
+ }
+ resp, err := s.client.Do(ctx, req, &r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r.Repositories, resp, nil
+}
+
+// AddRepository adds a single repository to an installation.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/installations/#add-repository-to-installation
+func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (*Repository, *Response, error) {
+ u := fmt.Sprintf("apps/installations/%v/repositories/%v", instID, repoID)
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(Repository)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// RemoveRepository removes a single repository from an installation.
+//
+// GitHub docs: https://developer.github.com/v3/apps/installations/#remove-repository-from-installation
+func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64) (*Response, error) {
+ u := fmt.Sprintf("apps/installations/%v/repositories/%v", instID, repoID)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/apps_installation_test.go b/vendor/github.com/google/go-github/github/apps_installation_test.go
new file mode 100644
index 0000000..01358c0
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/apps_installation_test.go
@@ -0,0 +1,101 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestAppsService_ListRepos(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/installation/repositories", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ testFormValues(t, r, values{
+ "page": "1",
+ "per_page": "2",
+ })
+ fmt.Fprint(w, `{"repositories": [{"id":1}]}`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ repositories, _, err := client.Apps.ListRepos(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Apps.ListRepos returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}}
+ if !reflect.DeepEqual(repositories, want) {
+ t.Errorf("Apps.ListRepos returned %+v, want %+v", repositories, want)
+ }
+}
+
+func TestAppsService_ListUserRepos(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/installations/1/repositories", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ testFormValues(t, r, values{
+ "page": "1",
+ "per_page": "2",
+ })
+ fmt.Fprint(w, `{"repositories": [{"id":1}]}`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ repositories, _, err := client.Apps.ListUserRepos(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Apps.ListUserRepos returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}}
+ if !reflect.DeepEqual(repositories, want) {
+ t.Errorf("Apps.ListUserRepos returned %+v, want %+v", repositories, want)
+ }
+}
+
+func TestAppsService_AddRepository(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/apps/installations/1/repositories/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`)
+ })
+
+ repo, _, err := client.Apps.AddRepository(context.Background(), 1, 1)
+ if err != nil {
+ t.Errorf("Apps.AddRepository returned error: %v", err)
+ }
+
+ want := &Repository{ID: Int64(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}, License: &License{Key: String("mit")}}
+ if !reflect.DeepEqual(repo, want) {
+ t.Errorf("AddRepository returned %+v, want %+v", repo, want)
+ }
+}
+
+func TestAppsService_RemoveRepository(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/apps/installations/1/repositories/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Apps.RemoveRepository(context.Background(), 1, 1)
+ if err != nil {
+ t.Errorf("Apps.RemoveRepository returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/apps_marketplace.go b/vendor/github.com/google/go-github/github/apps_marketplace.go
new file mode 100644
index 0000000..3f35b91
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/apps_marketplace.go
@@ -0,0 +1,168 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+)
+
+// MarketplaceService handles communication with the marketplace related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/marketplace/
+type MarketplaceService struct {
+ client *Client
+ // Stubbed controls whether endpoints that return stubbed data are used
+ // instead of production endpoints. Stubbed data is fake data that's useful
+ // for testing your GitHub Apps. Stubbed data is hard-coded and will not
+ // change based on actual subscriptions.
+ //
+ // GitHub API docs: https://developer.github.com/v3/apps/marketplace/
+ Stubbed bool
+}
+
+// MarketplacePlan represents a GitHub Apps Marketplace Listing Plan.
+type MarketplacePlan struct {
+ URL *string `json:"url,omitempty"`
+ AccountsURL *string `json:"accounts_url,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Description *string `json:"description,omitempty"`
+ MonthlyPriceInCents *int `json:"monthly_price_in_cents,omitempty"`
+ YearlyPriceInCents *int `json:"yearly_price_in_cents,omitempty"`
+ PriceModel *string `json:"price_model,omitempty"`
+ UnitName *string `json:"unit_name,omitempty"`
+ Bullets *[]string `json:"bullets,omitempty"`
+}
+
+// MarketplacePurchase represents a GitHub Apps Marketplace Purchase.
+type MarketplacePurchase struct {
+ BillingCycle *string `json:"billing_cycle,omitempty"`
+ NextBillingDate *string `json:"next_billing_date,omitempty"`
+ UnitCount *int `json:"unit_count,omitempty"`
+ Plan *MarketplacePlan `json:"plan,omitempty"`
+ Account *MarketplacePlanAccount `json:"account,omitempty"`
+}
+
+// MarketplacePlanAccount represents a GitHub Account (user or organization) on a specific plan.
+type MarketplacePlanAccount struct {
+ URL *string `json:"url,omitempty"`
+ Type *string `json:"type,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+ Login *string `json:"login,omitempty"`
+ Email *string `json:"email,omitempty"`
+ OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"`
+ MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"`
+}
+
+// ListPlans lists all plans for your Marketplace listing.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-plans-for-your-marketplace-listing
+func (s *MarketplaceService) ListPlans(ctx context.Context, opt *ListOptions) ([]*MarketplacePlan, *Response, error) {
+ uri := s.marketplaceURI("plans")
+ u, err := addOptions(uri, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var plans []*MarketplacePlan
+ resp, err := s.client.Do(ctx, req, &plans)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return plans, resp, nil
+}
+
+// ListPlanAccountsForPlan lists all GitHub accounts (user or organization) on a specific plan.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-github-accounts-user-or-organization-on-a-specific-plan
+func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID int64, opt *ListOptions) ([]*MarketplacePlanAccount, *Response, error) {
+ uri := s.marketplaceURI(fmt.Sprintf("plans/%v/accounts", planID))
+ u, err := addOptions(uri, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var accounts []*MarketplacePlanAccount
+ resp, err := s.client.Do(ctx, req, &accounts)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return accounts, resp, nil
+}
+
+// ListPlanAccountsForAccount lists all GitHub accounts (user or organization) associated with an account.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#check-if-a-github-account-is-associated-with-any-marketplace-listing
+func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, accountID int64, opt *ListOptions) ([]*MarketplacePlanAccount, *Response, error) {
+ uri := s.marketplaceURI(fmt.Sprintf("accounts/%v", accountID))
+ u, err := addOptions(uri, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var accounts []*MarketplacePlanAccount
+ resp, err := s.client.Do(ctx, req, &accounts)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return accounts, resp, nil
+}
+
+// ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#get-a-users-marketplace-purchases
+func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opt *ListOptions) ([]*MarketplacePurchase, *Response, error) {
+ uri := "user/marketplace_purchases"
+ if s.Stubbed {
+ uri = "user/marketplace_purchases/stubbed"
+ }
+
+ u, err := addOptions(uri, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var purchases []*MarketplacePurchase
+ resp, err := s.client.Do(ctx, req, &purchases)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return purchases, resp, nil
+}
+
+func (s *MarketplaceService) marketplaceURI(endpoint string) string {
+ url := "marketplace_listing"
+ if s.Stubbed {
+ url = "marketplace_listing/stubbed"
+ }
+ return url + "/" + endpoint
+}
diff --git a/vendor/github.com/google/go-github/github/apps_marketplace_test.go b/vendor/github.com/google/go-github/github/apps_marketplace_test.go
new file mode 100644
index 0000000..0c1f86c
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/apps_marketplace_test.go
@@ -0,0 +1,194 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestMarketplaceService_ListPlans(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/marketplace_listing/plans", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "1",
+ "per_page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ client.Marketplace.Stubbed = false
+ plans, _, err := client.Marketplace.ListPlans(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Marketplace.ListPlans returned error: %v", err)
+ }
+
+ want := []*MarketplacePlan{{ID: Int64(1)}}
+ if !reflect.DeepEqual(plans, want) {
+ t.Errorf("Marketplace.ListPlans returned %+v, want %+v", plans, want)
+ }
+}
+
+func TestMarketplaceService_Stubbed_ListPlans(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/marketplace_listing/stubbed/plans", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ client.Marketplace.Stubbed = true
+ plans, _, err := client.Marketplace.ListPlans(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Marketplace.ListPlans (Stubbed) returned error: %v", err)
+ }
+
+ want := []*MarketplacePlan{{ID: Int64(1)}}
+ if !reflect.DeepEqual(plans, want) {
+ t.Errorf("Marketplace.ListPlans (Stubbed) returned %+v, want %+v", plans, want)
+ }
+}
+
+func TestMarketplaceService_ListPlanAccountsForPlan(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/marketplace_listing/plans/1/accounts", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ client.Marketplace.Stubbed = false
+ accounts, _, err := client.Marketplace.ListPlanAccountsForPlan(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Marketplace.ListPlanAccountsForPlan returned error: %v", err)
+ }
+
+ want := []*MarketplacePlanAccount{{ID: Int64(1)}}
+ if !reflect.DeepEqual(accounts, want) {
+ t.Errorf("Marketplace.ListPlanAccountsForPlan returned %+v, want %+v", accounts, want)
+ }
+}
+
+func TestMarketplaceService_Stubbed_ListPlanAccountsForPlan(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/marketplace_listing/stubbed/plans/1/accounts", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ client.Marketplace.Stubbed = true
+ accounts, _, err := client.Marketplace.ListPlanAccountsForPlan(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Marketplace.ListPlanAccountsForPlan (Stubbed) returned error: %v", err)
+ }
+
+ want := []*MarketplacePlanAccount{{ID: Int64(1)}}
+ if !reflect.DeepEqual(accounts, want) {
+ t.Errorf("Marketplace.ListPlanAccountsForPlan (Stubbed) returned %+v, want %+v", accounts, want)
+ }
+}
+
+func TestMarketplaceService_ListPlanAccountsForAccount(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/marketplace_listing/accounts/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ client.Marketplace.Stubbed = false
+ accounts, _, err := client.Marketplace.ListPlanAccountsForAccount(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Marketplace.ListPlanAccountsForAccount returned error: %v", err)
+ }
+
+ want := []*MarketplacePlanAccount{{ID: Int64(1)}}
+ if !reflect.DeepEqual(accounts, want) {
+ t.Errorf("Marketplace.ListPlanAccountsForAccount returned %+v, want %+v", accounts, want)
+ }
+}
+
+func TestMarketplaceService_Stubbed_ListPlanAccountsForAccount(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/marketplace_listing/stubbed/accounts/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ client.Marketplace.Stubbed = true
+ accounts, _, err := client.Marketplace.ListPlanAccountsForAccount(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Marketplace.ListPlanAccountsForAccount (Stubbed) returned error: %v", err)
+ }
+
+ want := []*MarketplacePlanAccount{{ID: Int64(1)}}
+ if !reflect.DeepEqual(accounts, want) {
+ t.Errorf("Marketplace.ListPlanAccountsForAccount (Stubbed) returned %+v, want %+v", accounts, want)
+ }
+}
+
+func TestMarketplaceService_ListMarketplacePurchasesForUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/marketplace_purchases", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"billing_cycle":"monthly"}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ client.Marketplace.Stubbed = false
+ purchases, _, err := client.Marketplace.ListMarketplacePurchasesForUser(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Marketplace.ListMarketplacePurchasesForUser returned error: %v", err)
+ }
+
+ want := []*MarketplacePurchase{{BillingCycle: String("monthly")}}
+ if !reflect.DeepEqual(purchases, want) {
+ t.Errorf("Marketplace.ListMarketplacePurchasesForUser returned %+v, want %+v", purchases, want)
+ }
+}
+
+func TestMarketplaceService_Stubbed_ListMarketplacePurchasesForUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/marketplace_purchases/stubbed", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"billing_cycle":"monthly"}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ client.Marketplace.Stubbed = true
+ purchases, _, err := client.Marketplace.ListMarketplacePurchasesForUser(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Marketplace.ListMarketplacePurchasesForUser returned error: %v", err)
+ }
+
+ want := []*MarketplacePurchase{{BillingCycle: String("monthly")}}
+ if !reflect.DeepEqual(purchases, want) {
+ t.Errorf("Marketplace.ListMarketplacePurchasesForUser returned %+v, want %+v", purchases, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/apps_test.go b/vendor/github.com/google/go-github/github/apps_test.go
new file mode 100644
index 0000000..f56c1c4
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/apps_test.go
@@ -0,0 +1,270 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestAppsService_Get_authenticatedApp(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/app", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ app, _, err := client.Apps.Get(context.Background(), "")
+ if err != nil {
+ t.Errorf("Apps.Get returned error: %v", err)
+ }
+
+ want := &App{ID: Int64(1)}
+ if !reflect.DeepEqual(app, want) {
+ t.Errorf("Apps.Get returned %+v, want %+v", app, want)
+ }
+}
+
+func TestAppsService_Get_specifiedApp(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/apps/a", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ fmt.Fprint(w, `{"html_url":"https://github.com/apps/a"}`)
+ })
+
+ app, _, err := client.Apps.Get(context.Background(), "a")
+ if err != nil {
+ t.Errorf("Apps.Get returned error: %v", err)
+ }
+
+ want := &App{HTMLURL: String("https://github.com/apps/a")}
+ if !reflect.DeepEqual(app, want) {
+ t.Errorf("Apps.Get returned %+v, want %+v", *app.HTMLURL, *want.HTMLURL)
+ }
+}
+
+func TestAppsService_ListInstallations(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/app/installations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ testFormValues(t, r, values{
+ "page": "1",
+ "per_page": "2",
+ })
+ fmt.Fprint(w, `[{
+ "id":1,
+ "app_id":1,
+ "target_id":1,
+ "target_type": "Organization",
+ "permissions": {
+ "metadata": "read",
+ "contents": "read",
+ "issues": "write",
+ "single_file": "write"
+ },
+ "events": [
+ "push",
+ "pull_request"
+ ],
+ "single_file_name": "config.yml",
+ "repository_selection": "selected",
+ "created_at": "2018-01-01T00:00:00Z",
+ "updated_at": "2018-01-01T00:00:00Z"}]`,
+ )
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ installations, _, err := client.Apps.ListInstallations(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Apps.ListInstallations returned error: %v", err)
+ }
+
+ date := Timestamp{Time: time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)}
+ want := []*Installation{{
+ ID: Int64(1),
+ AppID: Int64(1),
+ TargetID: Int64(1),
+ TargetType: String("Organization"),
+ SingleFileName: String("config.yml"),
+ RepositorySelection: String("selected"),
+ Permissions: &InstallationPermissions{
+ Metadata: String("read"),
+ Contents: String("read"),
+ Issues: String("write"),
+ SingleFile: String("write")},
+ Events: []string{"push", "pull_request"},
+ CreatedAt: &date,
+ UpdatedAt: &date,
+ }}
+ if !reflect.DeepEqual(installations, want) {
+ t.Errorf("Apps.ListInstallations returned %+v, want %+v", installations, want)
+ }
+}
+
+func TestAppsService_GetInstallation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/app/installations/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`)
+ })
+
+ installation, _, err := client.Apps.GetInstallation(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Apps.GetInstallation returned error: %v", err)
+ }
+
+ want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}
+ if !reflect.DeepEqual(installation, want) {
+ t.Errorf("Apps.GetInstallation returned %+v, want %+v", installation, want)
+ }
+}
+
+func TestAppsService_ListUserInstallations(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/installations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ testFormValues(t, r, values{
+ "page": "1",
+ "per_page": "2",
+ })
+ fmt.Fprint(w, `{"installations":[{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}]}`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ installations, _, err := client.Apps.ListUserInstallations(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Apps.ListUserInstallations returned error: %v", err)
+ }
+
+ want := []*Installation{{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}}
+ if !reflect.DeepEqual(installations, want) {
+ t.Errorf("Apps.ListUserInstallations returned %+v, want %+v", installations, want)
+ }
+}
+
+func TestAppsService_CreateInstallationToken(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/installations/1/access_tokens", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ fmt.Fprint(w, `{"token":"t"}`)
+ })
+
+ token, _, err := client.Apps.CreateInstallationToken(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Apps.CreateInstallationToken returned error: %v", err)
+ }
+
+ want := &InstallationToken{Token: String("t")}
+ if !reflect.DeepEqual(token, want) {
+ t.Errorf("Apps.CreateInstallationToken returned %+v, want %+v", token, want)
+ }
+}
+
+func TestAppsService_FindOrganizationInstallation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/installation", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`)
+ })
+
+ installation, _, err := client.Apps.FindOrganizationInstallation(context.Background(), "o")
+ if err != nil {
+ t.Errorf("Apps.FindOrganizationInstallation returned error: %v", err)
+ }
+
+ want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}
+ if !reflect.DeepEqual(installation, want) {
+ t.Errorf("Apps.FindOrganizationInstallation returned %+v, want %+v", installation, want)
+ }
+}
+
+func TestAppsService_FindRepositoryInstallation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/installation", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`)
+ })
+
+ installation, _, err := client.Apps.FindRepositoryInstallation(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Apps.FindRepositoryInstallation returned error: %v", err)
+ }
+
+ want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}
+ if !reflect.DeepEqual(installation, want) {
+ t.Errorf("Apps.FindRepositoryInstallation returned %+v, want %+v", installation, want)
+ }
+}
+
+func TestAppsService_FindRepositoryInstallationByID(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repositories/1/installation", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`)
+ })
+
+ installation, _, err := client.Apps.FindRepositoryInstallationByID(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Apps.FindRepositoryInstallationByID returned error: %v", err)
+ }
+
+ want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}
+ if !reflect.DeepEqual(installation, want) {
+ t.Errorf("Apps.FindRepositoryInstallationByID returned %+v, want %+v", installation, want)
+ }
+}
+
+func TestAppsService_FindUserInstallation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/installation", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
+ fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "User"}`)
+ })
+
+ installation, _, err := client.Apps.FindUserInstallation(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Apps.FindUserInstallation returned error: %v", err)
+ }
+
+ want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("User")}
+ if !reflect.DeepEqual(installation, want) {
+ t.Errorf("Apps.FindUserInstallation returned %+v, want %+v", installation, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/authorizations.go b/vendor/github.com/google/go-github/github/authorizations.go
new file mode 100644
index 0000000..190205b
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/authorizations.go
@@ -0,0 +1,435 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// Scope models a GitHub authorization scope.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth/#scopes
+type Scope string
+
+// This is the set of scopes for GitHub API V3
+const (
+ ScopeNone Scope = "(no scope)" // REVISIT: is this actually returned, or just a documentation artifact?
+ ScopeUser Scope = "user"
+ ScopeUserEmail Scope = "user:email"
+ ScopeUserFollow Scope = "user:follow"
+ ScopePublicRepo Scope = "public_repo"
+ ScopeRepo Scope = "repo"
+ ScopeRepoDeployment Scope = "repo_deployment"
+ ScopeRepoStatus Scope = "repo:status"
+ ScopeDeleteRepo Scope = "delete_repo"
+ ScopeNotifications Scope = "notifications"
+ ScopeGist Scope = "gist"
+ ScopeReadRepoHook Scope = "read:repo_hook"
+ ScopeWriteRepoHook Scope = "write:repo_hook"
+ ScopeAdminRepoHook Scope = "admin:repo_hook"
+ ScopeAdminOrgHook Scope = "admin:org_hook"
+ ScopeReadOrg Scope = "read:org"
+ ScopeWriteOrg Scope = "write:org"
+ ScopeAdminOrg Scope = "admin:org"
+ ScopeReadPublicKey Scope = "read:public_key"
+ ScopeWritePublicKey Scope = "write:public_key"
+ ScopeAdminPublicKey Scope = "admin:public_key"
+ ScopeReadGPGKey Scope = "read:gpg_key"
+ ScopeWriteGPGKey Scope = "write:gpg_key"
+ ScopeAdminGPGKey Scope = "admin:gpg_key"
+)
+
+// AuthorizationsService handles communication with the authorization related
+// methods of the GitHub API.
+//
+// This service requires HTTP Basic Authentication; it cannot be accessed using
+// an OAuth token.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/
+type AuthorizationsService service
+
+// Authorization represents an individual GitHub authorization.
+type Authorization struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Scopes []Scope `json:"scopes,omitempty"`
+ Token *string `json:"token,omitempty"`
+ TokenLastEight *string `json:"token_last_eight,omitempty"`
+ HashedToken *string `json:"hashed_token,omitempty"`
+ App *AuthorizationApp `json:"app,omitempty"`
+ Note *string `json:"note,omitempty"`
+ NoteURL *string `json:"note_url,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ Fingerprint *string `json:"fingerprint,omitempty"`
+
+ // User is only populated by the Check and Reset methods.
+ User *User `json:"user,omitempty"`
+}
+
+func (a Authorization) String() string {
+ return Stringify(a)
+}
+
+// AuthorizationApp represents an individual GitHub app (in the context of authorization).
+type AuthorizationApp struct {
+ URL *string `json:"url,omitempty"`
+ Name *string `json:"name,omitempty"`
+ ClientID *string `json:"client_id,omitempty"`
+}
+
+func (a AuthorizationApp) String() string {
+ return Stringify(a)
+}
+
+// Grant represents an OAuth application that has been granted access to an account.
+type Grant struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ App *AuthorizationApp `json:"app,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ Scopes []string `json:"scopes,omitempty"`
+}
+
+func (g Grant) String() string {
+ return Stringify(g)
+}
+
+// AuthorizationRequest represents a request to create an authorization.
+type AuthorizationRequest struct {
+ Scopes []Scope `json:"scopes,omitempty"`
+ Note *string `json:"note,omitempty"`
+ NoteURL *string `json:"note_url,omitempty"`
+ ClientID *string `json:"client_id,omitempty"`
+ ClientSecret *string `json:"client_secret,omitempty"`
+ Fingerprint *string `json:"fingerprint,omitempty"`
+}
+
+func (a AuthorizationRequest) String() string {
+ return Stringify(a)
+}
+
+// AuthorizationUpdateRequest represents a request to update an authorization.
+//
+// Note that for any one update, you must only provide one of the "scopes"
+// fields. That is, you may provide only one of "Scopes", or "AddScopes", or
+// "RemoveScopes".
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization
+type AuthorizationUpdateRequest struct {
+ Scopes []string `json:"scopes,omitempty"`
+ AddScopes []string `json:"add_scopes,omitempty"`
+ RemoveScopes []string `json:"remove_scopes,omitempty"`
+ Note *string `json:"note,omitempty"`
+ NoteURL *string `json:"note_url,omitempty"`
+ Fingerprint *string `json:"fingerprint,omitempty"`
+}
+
+func (a AuthorizationUpdateRequest) String() string {
+ return Stringify(a)
+}
+
+// List the authorizations for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-authorizations
+func (s *AuthorizationsService) List(ctx context.Context, opt *ListOptions) ([]*Authorization, *Response, error) {
+ u := "authorizations"
+ 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
+ }
+
+ var auths []*Authorization
+ resp, err := s.client.Do(ctx, req, &auths)
+ if err != nil {
+ return nil, resp, err
+ }
+ return auths, resp, nil
+}
+
+// Get a single authorization.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-authorization
+func (s *AuthorizationsService) Get(ctx context.Context, id int64) (*Authorization, *Response, error) {
+ u := fmt.Sprintf("authorizations/%d", id)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ a := new(Authorization)
+ resp, err := s.client.Do(ctx, req, a)
+ if err != nil {
+ return nil, resp, err
+ }
+ return a, resp, nil
+}
+
+// Create a new authorization for the specified OAuth application.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#create-a-new-authorization
+func (s *AuthorizationsService) Create(ctx context.Context, auth *AuthorizationRequest) (*Authorization, *Response, error) {
+ u := "authorizations"
+
+ req, err := s.client.NewRequest("POST", u, auth)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ a := new(Authorization)
+ resp, err := s.client.Do(ctx, req, a)
+ if err != nil {
+ return nil, resp, err
+ }
+ return a, resp, nil
+}
+
+// GetOrCreateForApp creates a new authorization for the specified OAuth
+// application, only if an authorization for that application doesn’t already
+// exist for the user.
+//
+// If a new token is created, the HTTP status code will be "201 Created", and
+// the returned Authorization.Token field will be populated. If an existing
+// token is returned, the status code will be "200 OK" and the
+// Authorization.Token field will be empty.
+//
+// clientID is the OAuth Client ID with which to create the token.
+//
+// GitHub API docs:
+// https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app
+// https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app-and-fingerprint
+func (s *AuthorizationsService) GetOrCreateForApp(ctx context.Context, clientID string, auth *AuthorizationRequest) (*Authorization, *Response, error) {
+ var u string
+ if auth.Fingerprint == nil || *auth.Fingerprint == "" {
+ u = fmt.Sprintf("authorizations/clients/%v", clientID)
+ } else {
+ u = fmt.Sprintf("authorizations/clients/%v/%v", clientID, *auth.Fingerprint)
+ }
+
+ req, err := s.client.NewRequest("PUT", u, auth)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ a := new(Authorization)
+ resp, err := s.client.Do(ctx, req, a)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return a, resp, nil
+}
+
+// Edit a single authorization.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization
+func (s *AuthorizationsService) Edit(ctx context.Context, id int64, auth *AuthorizationUpdateRequest) (*Authorization, *Response, error) {
+ u := fmt.Sprintf("authorizations/%d", id)
+
+ req, err := s.client.NewRequest("PATCH", u, auth)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ a := new(Authorization)
+ resp, err := s.client.Do(ctx, req, a)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return a, resp, nil
+}
+
+// Delete a single authorization.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-an-authorization
+func (s *AuthorizationsService) Delete(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("authorizations/%d", id)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// Check if an OAuth token is valid for a specific app.
+//
+// Note that this operation requires the use of BasicAuth, but where the
+// username is the OAuth application clientID, and the password is its
+// clientSecret. Invalid tokens will return a 404 Not Found.
+//
+// The returned Authorization.User field will be populated.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#check-an-authorization
+func (s *AuthorizationsService) Check(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) {
+ u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ a := new(Authorization)
+ resp, err := s.client.Do(ctx, req, a)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return a, resp, nil
+}
+
+// Reset is used to reset a valid OAuth token without end user involvement.
+// Applications must save the "token" property in the response, because changes
+// take effect immediately.
+//
+// Note that this operation requires the use of BasicAuth, but where the
+// username is the OAuth application clientID, and the password is its
+// clientSecret. Invalid tokens will return a 404 Not Found.
+//
+// The returned Authorization.User field will be populated.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#reset-an-authorization
+func (s *AuthorizationsService) Reset(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) {
+ u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token)
+
+ req, err := s.client.NewRequest("POST", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ a := new(Authorization)
+ resp, err := s.client.Do(ctx, req, a)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return a, resp, nil
+}
+
+// Revoke an authorization for an application.
+//
+// Note that this operation requires the use of BasicAuth, but where the
+// username is the OAuth application clientID, and the password is its
+// clientSecret. Invalid tokens will return a 404 Not Found.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#revoke-an-authorization-for-an-application
+func (s *AuthorizationsService) Revoke(ctx context.Context, clientID string, token string) (*Response, error) {
+ u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ListGrants lists the set of OAuth applications that have been granted
+// access to a user's account. This will return one entry for each application
+// that has been granted access to the account, regardless of the number of
+// tokens an application has generated for the user.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-grants
+func (s *AuthorizationsService) ListGrants(ctx context.Context, opt *ListOptions) ([]*Grant, *Response, error) {
+ u, err := addOptions("applications/grants", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ grants := []*Grant{}
+ resp, err := s.client.Do(ctx, req, &grants)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return grants, resp, nil
+}
+
+// GetGrant gets a single OAuth application grant.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-grant
+func (s *AuthorizationsService) GetGrant(ctx context.Context, id int64) (*Grant, *Response, error) {
+ u := fmt.Sprintf("applications/grants/%d", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ grant := new(Grant)
+ resp, err := s.client.Do(ctx, req, grant)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return grant, resp, nil
+}
+
+// DeleteGrant deletes an OAuth application grant. Deleting an application's
+// grant will also delete all OAuth tokens associated with the application for
+// the user.
+//
+// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-a-grant
+func (s *AuthorizationsService) DeleteGrant(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("applications/grants/%d", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// CreateImpersonation creates an impersonation OAuth token.
+//
+// This requires admin permissions. With the returned Authorization.Token
+// you can e.g. create or delete a user's public SSH key. NOTE: creating a
+// new token automatically revokes an existing one.
+//
+// GitHub API docs: https://developer.github.com/enterprise/2.5/v3/users/administration/#create-an-impersonation-oauth-token
+func (s *AuthorizationsService) CreateImpersonation(ctx context.Context, username string, authReq *AuthorizationRequest) (*Authorization, *Response, error) {
+ u := fmt.Sprintf("admin/users/%v/authorizations", username)
+ req, err := s.client.NewRequest("POST", u, authReq)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ a := new(Authorization)
+ resp, err := s.client.Do(ctx, req, a)
+ if err != nil {
+ return nil, resp, err
+ }
+ return a, resp, nil
+}
+
+// DeleteImpersonation deletes an impersonation OAuth token.
+//
+// NOTE: there can be only one at a time.
+//
+// GitHub API docs: https://developer.github.com/enterprise/2.5/v3/users/administration/#delete-an-impersonation-oauth-token
+func (s *AuthorizationsService) DeleteImpersonation(ctx context.Context, username string) (*Response, error) {
+ u := fmt.Sprintf("admin/users/%v/authorizations", username)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/authorizations_test.go b/vendor/github.com/google/go-github/github/authorizations_test.go
new file mode 100644
index 0000000..faf2574
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/authorizations_test.go
@@ -0,0 +1,359 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestAuthorizationsService_List(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/authorizations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "1", "per_page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ got, _, err := client.Authorizations.List(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Authorizations.List returned error: %v", err)
+ }
+
+ want := []*Authorization{{ID: Int64(1)}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Authorizations.List returned %+v, want %+v", *got[0].ID, *want[0].ID)
+ }
+}
+
+func TestAuthorizationsService_Get(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/authorizations/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ got, _, err := client.Authorizations.Get(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Authorizations.Get returned error: %v", err)
+ }
+
+ want := &Authorization{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Authorizations.Get returned auth %+v, want %+v", got, want)
+ }
+}
+
+func TestAuthorizationsService_Create(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &AuthorizationRequest{
+ Note: String("test"),
+ }
+
+ mux.HandleFunc("/authorizations", func(w http.ResponseWriter, r *http.Request) {
+ v := new(AuthorizationRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"ID":1}`)
+ })
+
+ got, _, err := client.Authorizations.Create(context.Background(), input)
+ if err != nil {
+ t.Errorf("Authorizations.Create returned error: %v", err)
+ }
+
+ want := &Authorization{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Authorization.Create returned %+v, want %+v", got, want)
+ }
+}
+
+func TestAuthorizationsService_GetOrCreateForApp(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &AuthorizationRequest{
+ Note: String("test"),
+ }
+
+ mux.HandleFunc("/authorizations/clients/id", func(w http.ResponseWriter, r *http.Request) {
+ v := new(AuthorizationRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PUT")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"ID":1}`)
+ })
+
+ got, _, err := client.Authorizations.GetOrCreateForApp(context.Background(), "id", input)
+ if err != nil {
+ t.Errorf("Authorizations.GetOrCreateForApp returned error: %v", err)
+ }
+
+ want := &Authorization{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Authorization.GetOrCreateForApp returned %+v, want %+v", got, want)
+ }
+}
+
+func TestAuthorizationsService_GetOrCreateForApp_Fingerprint(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &AuthorizationRequest{
+ Note: String("test"),
+ Fingerprint: String("fp"),
+ }
+
+ mux.HandleFunc("/authorizations/clients/id/fp", func(w http.ResponseWriter, r *http.Request) {
+ v := new(AuthorizationRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PUT")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"ID":1}`)
+ })
+
+ got, _, err := client.Authorizations.GetOrCreateForApp(context.Background(), "id", input)
+ if err != nil {
+ t.Errorf("Authorizations.GetOrCreateForApp returned error: %v", err)
+ }
+
+ want := &Authorization{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Authorization.GetOrCreateForApp returned %+v, want %+v", got, want)
+ }
+}
+
+func TestAuthorizationsService_Edit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &AuthorizationUpdateRequest{
+ Note: String("test"),
+ }
+
+ mux.HandleFunc("/authorizations/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(AuthorizationUpdateRequest)
+ 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}`)
+ })
+
+ got, _, err := client.Authorizations.Edit(context.Background(), 1, input)
+ if err != nil {
+ t.Errorf("Authorizations.Edit returned error: %v", err)
+ }
+
+ want := &Authorization{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Authorization.Update returned %+v, want %+v", got, want)
+ }
+}
+
+func TestAuthorizationsService_Delete(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/authorizations/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Authorizations.Delete(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Authorizations.Delete returned error: %v", err)
+ }
+}
+
+func TestAuthorizationsService_Check(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/applications/id/tokens/t", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ got, _, err := client.Authorizations.Check(context.Background(), "id", "t")
+ if err != nil {
+ t.Errorf("Authorizations.Check returned error: %v", err)
+ }
+
+ want := &Authorization{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Authorizations.Check returned auth %+v, want %+v", got, want)
+ }
+}
+
+func TestAuthorizationsService_Reset(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/applications/id/tokens/t", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ fmt.Fprint(w, `{"ID":1}`)
+ })
+
+ got, _, err := client.Authorizations.Reset(context.Background(), "id", "t")
+ if err != nil {
+ t.Errorf("Authorizations.Reset returned error: %v", err)
+ }
+
+ want := &Authorization{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Authorizations.Reset returned auth %+v, want %+v", got, want)
+ }
+}
+
+func TestAuthorizationsService_Revoke(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/applications/id/tokens/t", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Authorizations.Revoke(context.Background(), "id", "t")
+ if err != nil {
+ t.Errorf("Authorizations.Revoke returned error: %v", err)
+ }
+}
+
+func TestListGrants(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/applications/grants", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id": 1}]`)
+ })
+
+ got, _, err := client.Authorizations.ListGrants(context.Background(), nil)
+ if err != nil {
+ t.Errorf("OAuthAuthorizations.ListGrants returned error: %v", err)
+ }
+
+ want := []*Grant{{ID: Int64(1)}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("OAuthAuthorizations.ListGrants = %+v, want %+v", got, want)
+ }
+}
+
+func TestListGrants_withOptions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/applications/grants", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"id": 1}]`)
+ })
+
+ _, _, err := client.Authorizations.ListGrants(context.Background(), &ListOptions{Page: 2})
+ if err != nil {
+ t.Errorf("OAuthAuthorizations.ListGrants returned error: %v", err)
+ }
+}
+
+func TestGetGrant(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/applications/grants/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id": 1}`)
+ })
+
+ got, _, err := client.Authorizations.GetGrant(context.Background(), 1)
+ if err != nil {
+ t.Errorf("OAuthAuthorizations.GetGrant returned error: %v", err)
+ }
+
+ want := &Grant{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("OAuthAuthorizations.GetGrant = %+v, want %+v", got, want)
+ }
+}
+
+func TestDeleteGrant(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/applications/grants/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Authorizations.DeleteGrant(context.Background(), 1)
+ if err != nil {
+ t.Errorf("OAuthAuthorizations.DeleteGrant returned error: %v", err)
+ }
+}
+
+func TestAuthorizationsService_CreateImpersonation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/admin/users/u/authorizations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ req := &AuthorizationRequest{Scopes: []Scope{ScopePublicRepo}}
+ got, _, err := client.Authorizations.CreateImpersonation(context.Background(), "u", req)
+ if err != nil {
+ t.Errorf("Authorizations.CreateImpersonation returned error: %+v", err)
+ }
+
+ want := &Authorization{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Authorizations.CreateImpersonation returned %+v, want %+v", *got.ID, *want.ID)
+ }
+}
+
+func TestAuthorizationsService_DeleteImpersonation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/admin/users/u/authorizations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Authorizations.DeleteImpersonation(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Authorizations.DeleteImpersonation returned error: %+v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/checks.go b/vendor/github.com/google/go-github/github/checks.go
new file mode 100644
index 0000000..2a6ce41
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/checks.go
@@ -0,0 +1,421 @@
+// Copyright 2018 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 (
+ "context"
+ "fmt"
+)
+
+// ChecksService provides access to the Checks API in the
+// GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/
+type ChecksService service
+
+// CheckRun represents a GitHub check run on a repository associated with a GitHub app.
+type CheckRun struct {
+ ID *int64 `json:"id,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ HeadSHA *string `json:"head_sha,omitempty"`
+ ExternalID *string `json:"external_id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ Status *string `json:"status,omitempty"`
+ Conclusion *string `json:"conclusion,omitempty"`
+ StartedAt *Timestamp `json:"started_at,omitempty"`
+ CompletedAt *Timestamp `json:"completed_at,omitempty"`
+ Output *CheckRunOutput `json:"output,omitempty"`
+ Name *string `json:"name,omitempty"`
+ CheckSuite *CheckSuite `json:"check_suite,omitempty"`
+ App *App `json:"app,omitempty"`
+ PullRequests []*PullRequest `json:"pull_requests,omitempty"`
+}
+
+// CheckRunOutput represents the output of a CheckRun.
+type CheckRunOutput struct {
+ Title *string `json:"title,omitempty"`
+ Summary *string `json:"summary,omitempty"`
+ Text *string `json:"text,omitempty"`
+ AnnotationsCount *int `json:"annotations_count,omitempty"`
+ AnnotationsURL *string `json:"annotations_url,omitempty"`
+ Annotations []*CheckRunAnnotation `json:"annotations,omitempty"`
+ Images []*CheckRunImage `json:"images,omitempty"`
+}
+
+// CheckRunAnnotation represents an annotation object for a CheckRun output.
+type CheckRunAnnotation struct {
+ Path *string `json:"path,omitempty"`
+ BlobHRef *string `json:"blob_href,omitempty"`
+ StartLine *int `json:"start_line,omitempty"`
+ EndLine *int `json:"end_line,omitempty"`
+ AnnotationLevel *string `json:"annotation_level,omitempty"`
+ Message *string `json:"message,omitempty"`
+ Title *string `json:"title,omitempty"`
+ RawDetails *string `json:"raw_details,omitempty"`
+}
+
+// CheckRunImage represents an image object for a CheckRun output.
+type CheckRunImage struct {
+ Alt *string `json:"alt,omitempty"`
+ ImageURL *string `json:"image_url,omitempty"`
+ Caption *string `json:"caption,omitempty"`
+}
+
+// CheckSuite represents a suite of check runs.
+type CheckSuite struct {
+ ID *int64 `json:"id,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ HeadBranch *string `json:"head_branch,omitempty"`
+ HeadSHA *string `json:"head_sha,omitempty"`
+ URL *string `json:"url,omitempty"`
+ BeforeSHA *string `json:"before,omitempty"`
+ AfterSHA *string `json:"after,omitempty"`
+ Status *string `json:"status,omitempty"`
+ Conclusion *string `json:"conclusion,omitempty"`
+ App *App `json:"app,omitempty"`
+ Repository *Repository `json:"repository,omitempty"`
+ PullRequests []*PullRequest `json:"pull_requests,omitempty"`
+}
+
+func (c CheckRun) String() string {
+ return Stringify(c)
+}
+
+func (c CheckSuite) String() string {
+ return Stringify(c)
+}
+
+// GetCheckRun gets a check-run for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/runs/#get-a-single-check-run
+func (s *ChecksService) GetCheckRun(ctx context.Context, owner, repo string, checkRunID int64) (*CheckRun, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ checkRun := new(CheckRun)
+ resp, err := s.client.Do(ctx, req, checkRun)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return checkRun, resp, nil
+}
+
+// GetCheckSuite gets a single check suite.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/suites/#get-a-single-check-suite
+func (s *ChecksService) GetCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*CheckSuite, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/check-suites/%v", owner, repo, checkSuiteID)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ checkSuite := new(CheckSuite)
+ resp, err := s.client.Do(ctx, req, checkSuite)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return checkSuite, resp, nil
+}
+
+// CreateCheckRunOptions sets up parameters needed to create a CheckRun.
+type CreateCheckRunOptions struct {
+ Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.)
+ HeadBranch string `json:"head_branch"` // The name of the branch to perform a check against. (Required.)
+ HeadSHA string `json:"head_sha"` // The SHA of the commit. (Required.)
+ DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.)
+ ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.)
+ Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.)
+ Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".)
+ StartedAt *Timestamp `json:"started_at,omitempty"` // The time that the check run began. (Optional.)
+ CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.)
+ Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional)
+}
+
+// CreateCheckRun creates a check run for repository.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/runs/#create-a-check-run
+func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string, opt CreateCheckRunOptions) (*CheckRun, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/check-runs", owner, repo)
+ req, err := s.client.NewRequest("POST", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ checkRun := new(CheckRun)
+ resp, err := s.client.Do(ctx, req, checkRun)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return checkRun, resp, nil
+}
+
+// UpdateCheckRunOptions sets up parameters needed to update a CheckRun.
+type UpdateCheckRunOptions struct {
+ Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.)
+ HeadBranch *string `json:"head_branch,omitempty"` // The name of the branch to perform a check against. (Optional.)
+ HeadSHA *string `json:"head_sha,omitempty"` // The SHA of the commit. (Optional.)
+ DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.)
+ ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.)
+ Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.)
+ Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".)
+ CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.)
+ Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional)
+}
+
+// UpdateCheckRun updates a check run for a specific commit in a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/runs/#update-a-check-run
+func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, checkRunID int64, opt UpdateCheckRunOptions) (*CheckRun, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID)
+ req, err := s.client.NewRequest("PATCH", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ checkRun := new(CheckRun)
+ resp, err := s.client.Do(ctx, req, checkRun)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return checkRun, resp, nil
+}
+
+// ListCheckRunAnnotations lists the annotations for a check run.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-annotations-for-a-check-run
+func (s *ChecksService) ListCheckRunAnnotations(ctx context.Context, owner, repo string, checkRunID int64, opt *ListOptions) ([]*CheckRunAnnotation, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/check-runs/%v/annotations", owner, repo, checkRunID)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ var checkRunAnnotations []*CheckRunAnnotation
+ resp, err := s.client.Do(ctx, req, &checkRunAnnotations)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return checkRunAnnotations, resp, nil
+}
+
+// ListCheckRunsOptions represents parameters to list check runs.
+type ListCheckRunsOptions struct {
+ CheckName *string `url:"check_name,omitempty"` // Returns check runs with the specified name.
+ Status *string `url:"status,omitempty"` // Returns check runs with the specified status. Can be one of "queued", "in_progress", or "completed".
+ Filter *string `url:"filter,omitempty"` // Filters check runs by their completed_at timestamp. Can be one of "latest" (returning the most recent check runs) or "all". Default: "latest"
+
+ ListOptions
+}
+
+// ListCheckRunsResults represents the result of a check run list.
+type ListCheckRunsResults struct {
+ Total *int `json:"total_count,omitempty"`
+ CheckRuns []*CheckRun `json:"check_runs,omitempty"`
+}
+
+// ListCheckRunsForRef lists check runs for a specific ref.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-for-a-specific-ref
+func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, ref string, opt *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/commits/%v/check-runs", owner, repo, ref)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ var checkRunResults *ListCheckRunsResults
+ resp, err := s.client.Do(ctx, req, &checkRunResults)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return checkRunResults, resp, nil
+}
+
+// ListCheckRunsCheckSuite lists check runs for a check suite.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-in-a-check-suite
+func (s *ChecksService) ListCheckRunsCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64, opt *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/check-suites/%v/check-runs", owner, repo, checkSuiteID)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ var checkRunResults *ListCheckRunsResults
+ resp, err := s.client.Do(ctx, req, &checkRunResults)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return checkRunResults, resp, nil
+}
+
+// ListCheckSuiteOptions represents parameters to list check suites.
+type ListCheckSuiteOptions struct {
+ CheckName *string `url:"check_name,omitempty"` // Filters checks suites by the name of the check run.
+ AppID *int `url:"app_id,omitempty"` // Filters check suites by GitHub App id.
+
+ ListOptions
+}
+
+// ListCheckSuiteResults represents the result of a check run list.
+type ListCheckSuiteResults struct {
+ Total *int `json:"total_count,omitempty"`
+ CheckSuites []*CheckSuite `json:"check_suites,omitempty"`
+}
+
+// ListCheckSuitesForRef lists check suite for a specific ref.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/suites/#list-check-suites-for-a-specific-ref
+func (s *ChecksService) ListCheckSuitesForRef(ctx context.Context, owner, repo, ref string, opt *ListCheckSuiteOptions) (*ListCheckSuiteResults, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/commits/%v/check-suites", owner, repo, ref)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ var checkSuiteResults *ListCheckSuiteResults
+ resp, err := s.client.Do(ctx, req, &checkSuiteResults)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return checkSuiteResults, resp, nil
+}
+
+// AutoTriggerCheck enables or disables automatic creation of CheckSuite events upon pushes to the repository.
+type AutoTriggerCheck struct {
+ AppID *int64 `json:"app_id,omitempty"` // The id of the GitHub App. (Required.)
+ Setting *bool `json:"setting,omitempty"` // Set to "true" to enable automatic creation of CheckSuite events upon pushes to the repository, or "false" to disable them. Default: "true" (Required.)
+}
+
+// CheckSuitePreferenceOptions set options for check suite preferences for a repository.
+type CheckSuitePreferenceOptions struct {
+ PreferenceList *PreferenceList `json:"auto_trigger_checks,omitempty"` // A list of auto trigger checks that can be set for a check suite in a repository.
+}
+
+// CheckSuitePreferenceResults represents the results of the preference set operation.
+type CheckSuitePreferenceResults struct {
+ Preferences *PreferenceList `json:"preferences,omitempty"`
+ Repository *Repository `json:"repository,omitempty"`
+}
+
+// PreferenceList represents a list of auto trigger checks for repository
+type PreferenceList struct {
+ AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository.
+}
+
+// SetCheckSuitePreferences changes the default automatic flow when creating check suites.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/suites/#set-preferences-for-check-suites-on-a-repository
+func (s *ChecksService) SetCheckSuitePreferences(ctx context.Context, owner, repo string, opt CheckSuitePreferenceOptions) (*CheckSuitePreferenceResults, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/check-suites/preferences", owner, repo)
+ req, err := s.client.NewRequest("PATCH", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ var checkSuitePrefResults *CheckSuitePreferenceResults
+ resp, err := s.client.Do(ctx, req, &checkSuitePrefResults)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return checkSuitePrefResults, resp, nil
+}
+
+// CreateCheckSuiteOptions sets up parameters to manually create a check suites
+type CreateCheckSuiteOptions struct {
+ HeadSHA string `json:"head_sha"` // The sha of the head commit. (Required.)
+ HeadBranch *string `json:"head_branch,omitempty"` // The name of the head branch where the code changes are implemented.
+}
+
+// CreateCheckSuite manually creates a check suite for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/suites/#create-a-check-suite
+func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string, opt CreateCheckSuiteOptions) (*CheckSuite, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/check-suites", owner, repo)
+ req, err := s.client.NewRequest("POST", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ checkSuite := new(CheckSuite)
+ resp, err := s.client.Do(ctx, req, checkSuite)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return checkSuite, resp, nil
+}
+
+// ReRequestCheckSuite triggers GitHub to rerequest an existing check suite, without pushing new code to a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/checks/suites/#rerequest-check-suite
+func (s *ChecksService) ReRequestCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/check-suites/%v/rerequest", owner, repo, checkSuiteID)
+
+ req, err := s.client.NewRequest("POST", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeCheckRunsPreview)
+
+ resp, err := s.client.Do(ctx, req, nil)
+ return resp, err
+}
diff --git a/vendor/github.com/google/go-github/github/checks_test.go b/vendor/github.com/google/go-github/github/checks_test.go
new file mode 100644
index 0000000..3170f70
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/checks_test.go
@@ -0,0 +1,479 @@
+// Copyright 2018 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestChecksService_GetCheckRun(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/check-runs/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ fmt.Fprint(w, `{
+ "id": 1,
+ "name":"testCheckRun",
+ "status": "completed",
+ "conclusion": "neutral",
+ "started_at": "2018-05-04T01:14:52Z",
+ "completed_at": "2018-05-04T01:14:52Z"}`)
+ })
+ checkRun, _, err := client.Checks.GetCheckRun(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Checks.GetCheckRun return error: %v", err)
+ }
+ startedAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z")
+ completeAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z")
+
+ want := &CheckRun{
+ ID: Int64(1),
+ Status: String("completed"),
+ Conclusion: String("neutral"),
+ StartedAt: &Timestamp{startedAt},
+ CompletedAt: &Timestamp{completeAt},
+ Name: String("testCheckRun"),
+ }
+ if !reflect.DeepEqual(checkRun, want) {
+ t.Errorf("Checks.GetCheckRun return %+v, want %+v", checkRun, want)
+ }
+}
+
+func TestChecksService_GetCheckSuite(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/check-suites/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ fmt.Fprint(w, `{
+ "id": 1,
+ "head_branch":"master",
+ "head_sha": "deadbeef",
+ "conclusion": "neutral",
+ "before": "deadbeefb",
+ "after": "deadbeefa",
+ "status": "completed"}`)
+ })
+ checkSuite, _, err := client.Checks.GetCheckSuite(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Checks.GetCheckSuite return error: %v", err)
+ }
+ want := &CheckSuite{
+ ID: Int64(1),
+ HeadBranch: String("master"),
+ HeadSHA: String("deadbeef"),
+ AfterSHA: String("deadbeefa"),
+ BeforeSHA: String("deadbeefb"),
+ Status: String("completed"),
+ Conclusion: String("neutral"),
+ }
+ if !reflect.DeepEqual(checkSuite, want) {
+ t.Errorf("Checks.GetCheckSuite return %+v, want %+v", checkSuite, want)
+ }
+}
+
+func TestChecksService_CreateCheckRun(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/check-runs", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ fmt.Fprint(w, `{
+ "id": 1,
+ "name":"testCreateCheckRun",
+ "head_sha":"deadbeef",
+ "status": "in_progress",
+ "conclusion": null,
+ "started_at": "2018-05-04T01:14:52Z",
+ "completed_at": null,
+ "output":{"title": "Mighty test report", "summary":"", "text":""}}`)
+ })
+ startedAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z")
+ checkRunOpt := CreateCheckRunOptions{
+ HeadBranch: "master",
+ Name: "testCreateCheckRun",
+ HeadSHA: "deadbeef",
+ Status: String("in_progress"),
+ StartedAt: &Timestamp{startedAt},
+ Output: &CheckRunOutput{
+ Title: String("Mighty test report"),
+ Summary: String(""),
+ Text: String(""),
+ },
+ }
+
+ checkRun, _, err := client.Checks.CreateCheckRun(context.Background(), "o", "r", checkRunOpt)
+ if err != nil {
+ t.Errorf("Checks.CreateCheckRun return error: %v", err)
+ }
+
+ want := &CheckRun{
+ ID: Int64(1),
+ Status: String("in_progress"),
+ StartedAt: &Timestamp{startedAt},
+ HeadSHA: String("deadbeef"),
+ Name: String("testCreateCheckRun"),
+ Output: &CheckRunOutput{
+ Title: String("Mighty test report"),
+ Summary: String(""),
+ Text: String(""),
+ },
+ }
+ if !reflect.DeepEqual(checkRun, want) {
+ t.Errorf("Checks.CreateCheckRun return %+v, want %+v", checkRun, want)
+ }
+}
+
+func TestChecksService_ListCheckRunAnnotations(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/check-runs/1/annotations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ testFormValues(t, r, values{
+ "page": "1",
+ })
+ fmt.Fprint(w, `[{
+ "path": "README.md",
+ "blob_href": "https://github.com/octocat/Hello-World/blob/837db83be4137ca555d9a5598d0a1ea2987ecfee/README.md",
+ "start_line": 2,
+ "end_line": 2,
+ "annotation_level": "warning",
+ "message": "Check your spelling for 'banaas'.",
+ "title": "Spell check",
+ "raw_details": "Do you mean 'bananas' or 'banana'?"}]`,
+ )
+ })
+
+ checkRunAnnotations, _, err := client.Checks.ListCheckRunAnnotations(context.Background(), "o", "r", 1, &ListOptions{Page: 1})
+ if err != nil {
+ t.Errorf("Checks.ListCheckRunAnnotations return error: %v", err)
+ }
+
+ want := []*CheckRunAnnotation{{
+ Path: String("README.md"),
+ BlobHRef: String("https://github.com/octocat/Hello-World/blob/837db83be4137ca555d9a5598d0a1ea2987ecfee/README.md"),
+ StartLine: Int(2),
+ EndLine: Int(2),
+ AnnotationLevel: String("warning"),
+ Message: String("Check your spelling for 'banaas'."),
+ RawDetails: String("Do you mean 'bananas' or 'banana'?"),
+ Title: String("Spell check"),
+ }}
+
+ if !reflect.DeepEqual(checkRunAnnotations, want) {
+ t.Errorf("Checks.ListCheckRunAnnotations returned %+v, want %+v", checkRunAnnotations, want)
+ }
+}
+
+func TestChecksService_UpdateCheckRun(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/check-runs/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ fmt.Fprint(w, `{
+ "id": 1,
+ "name":"testUpdateCheckRun",
+ "head_sha":"deadbeef",
+ "status": "completed",
+ "conclusion": "neutral",
+ "started_at": "2018-05-04T01:14:52Z",
+ "completed_at": "2018-05-04T01:14:52Z",
+ "output":{"title": "Mighty test report", "summary":"There are 0 failures, 2 warnings and 1 notice", "text":"You may have misspelled some words."}}`)
+ })
+ startedAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z")
+ updateCheckRunOpt := UpdateCheckRunOptions{
+ HeadBranch: String("master"),
+ Name: "testUpdateCheckRun",
+ HeadSHA: String("deadbeef"),
+ Status: String("completed"),
+ CompletedAt: &Timestamp{startedAt},
+ Output: &CheckRunOutput{
+ Title: String("Mighty test report"),
+ Summary: String("There are 0 failures, 2 warnings and 1 notice"),
+ Text: String("You may have misspelled some words."),
+ },
+ }
+
+ checkRun, _, err := client.Checks.UpdateCheckRun(context.Background(), "o", "r", 1, updateCheckRunOpt)
+ if err != nil {
+ t.Errorf("Checks.UpdateCheckRun return error: %v", err)
+ }
+
+ want := &CheckRun{
+ ID: Int64(1),
+ Status: String("completed"),
+ StartedAt: &Timestamp{startedAt},
+ CompletedAt: &Timestamp{startedAt},
+ Conclusion: String("neutral"),
+ HeadSHA: String("deadbeef"),
+ Name: String("testUpdateCheckRun"),
+ Output: &CheckRunOutput{
+ Title: String("Mighty test report"),
+ Summary: String("There are 0 failures, 2 warnings and 1 notice"),
+ Text: String("You may have misspelled some words."),
+ },
+ }
+ if !reflect.DeepEqual(checkRun, want) {
+ t.Errorf("Checks.UpdateCheckRun return %+v, want %+v", checkRun, want)
+ }
+}
+
+func TestChecksService_ListCheckRunsForRef(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/commits/master/check-runs", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ testFormValues(t, r, values{
+ "check_name": "testing",
+ "page": "1",
+ "status": "completed",
+ "filter": "all",
+ })
+ fmt.Fprint(w, `{"total_count":1,
+ "check_runs": [{
+ "id": 1,
+ "head_sha": "deadbeef",
+ "status": "completed",
+ "conclusion": "neutral",
+ "started_at": "2018-05-04T01:14:52Z",
+ "completed_at": "2018-05-04T01:14:52Z"}]}`,
+ )
+ })
+
+ opt := &ListCheckRunsOptions{
+ CheckName: String("testing"),
+ Status: String("completed"),
+ Filter: String("all"),
+ ListOptions: ListOptions{Page: 1},
+ }
+ checkRuns, _, err := client.Checks.ListCheckRunsForRef(context.Background(), "o", "r", "master", opt)
+ if err != nil {
+ t.Errorf("Checks.ListCheckRunsForRef return error: %v", err)
+ }
+ startedAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z")
+ want := &ListCheckRunsResults{
+ Total: Int(1),
+ CheckRuns: []*CheckRun{{
+ ID: Int64(1),
+ Status: String("completed"),
+ StartedAt: &Timestamp{startedAt},
+ CompletedAt: &Timestamp{startedAt},
+ Conclusion: String("neutral"),
+ HeadSHA: String("deadbeef"),
+ }},
+ }
+
+ if !reflect.DeepEqual(checkRuns, want) {
+ t.Errorf("Checks.ListCheckRunsForRef returned %+v, want %+v", checkRuns, want)
+ }
+}
+
+func TestChecksService_ListCheckRunsCheckSuite(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/check-suites/1/check-runs", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ testFormValues(t, r, values{
+ "check_name": "testing",
+ "page": "1",
+ "status": "completed",
+ "filter": "all",
+ })
+ fmt.Fprint(w, `{"total_count":1,
+ "check_runs": [{
+ "id": 1,
+ "head_sha": "deadbeef",
+ "status": "completed",
+ "conclusion": "neutral",
+ "started_at": "2018-05-04T01:14:52Z",
+ "completed_at": "2018-05-04T01:14:52Z"}]}`,
+ )
+ })
+
+ opt := &ListCheckRunsOptions{
+ CheckName: String("testing"),
+ Status: String("completed"),
+ Filter: String("all"),
+ ListOptions: ListOptions{Page: 1},
+ }
+ checkRuns, _, err := client.Checks.ListCheckRunsCheckSuite(context.Background(), "o", "r", 1, opt)
+ if err != nil {
+ t.Errorf("Checks.ListCheckRunsCheckSuite return error: %v", err)
+ }
+ startedAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z")
+ want := &ListCheckRunsResults{
+ Total: Int(1),
+ CheckRuns: []*CheckRun{{
+ ID: Int64(1),
+ Status: String("completed"),
+ StartedAt: &Timestamp{startedAt},
+ CompletedAt: &Timestamp{startedAt},
+ Conclusion: String("neutral"),
+ HeadSHA: String("deadbeef"),
+ }},
+ }
+
+ if !reflect.DeepEqual(checkRuns, want) {
+ t.Errorf("Checks.ListCheckRunsCheckSuite returned %+v, want %+v", checkRuns, want)
+ }
+}
+
+func TestChecksService_ListCheckSuiteForRef(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/commits/master/check-suites", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ testFormValues(t, r, values{
+ "check_name": "testing",
+ "page": "1",
+ "app_id": "2",
+ })
+ fmt.Fprint(w, `{"total_count":1,
+ "check_suites": [{
+ "id": 1,
+ "head_sha": "deadbeef",
+ "head_branch": "master",
+ "status": "completed",
+ "conclusion": "neutral",
+ "before": "deadbeefb",
+ "after": "deadbeefa"}]}`,
+ )
+ })
+
+ opt := &ListCheckSuiteOptions{
+ CheckName: String("testing"),
+ AppID: Int(2),
+ ListOptions: ListOptions{Page: 1},
+ }
+ checkSuites, _, err := client.Checks.ListCheckSuitesForRef(context.Background(), "o", "r", "master", opt)
+ if err != nil {
+ t.Errorf("Checks.ListCheckSuitesForRef return error: %v", err)
+ }
+ want := &ListCheckSuiteResults{
+ Total: Int(1),
+ CheckSuites: []*CheckSuite{{
+ ID: Int64(1),
+ Status: String("completed"),
+ Conclusion: String("neutral"),
+ HeadSHA: String("deadbeef"),
+ HeadBranch: String("master"),
+ BeforeSHA: String("deadbeefb"),
+ AfterSHA: String("deadbeefa"),
+ }},
+ }
+
+ if !reflect.DeepEqual(checkSuites, want) {
+ t.Errorf("Checks.ListCheckSuitesForRef returned %+v, want %+v", checkSuites, want)
+ }
+}
+
+func TestChecksService_SetCheckSuitePreferences(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/check-suites/preferences", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ fmt.Fprint(w, `{"preferences":{"auto_trigger_checks":[{"app_id": 2,"setting": false}]}}`)
+ })
+ p := &PreferenceList{
+ AutoTriggerChecks: []*AutoTriggerCheck{{
+ AppID: Int64(2),
+ Setting: Bool(false),
+ }},
+ }
+ opt := CheckSuitePreferenceOptions{PreferenceList: p}
+ prefResults, _, err := client.Checks.SetCheckSuitePreferences(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Checks.SetCheckSuitePreferences return error: %v", err)
+ }
+
+ want := &CheckSuitePreferenceResults{
+ Preferences: p,
+ }
+
+ if !reflect.DeepEqual(prefResults, want) {
+ t.Errorf("Checks.SetCheckSuitePreferences return %+v, want %+v", prefResults, want)
+ }
+}
+
+func TestChecksService_CreateCheckSuite(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/check-suites", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ fmt.Fprint(w, `{
+ "id": 2,
+ "head_branch":"master",
+ "head_sha":"deadbeef",
+ "status": "completed",
+ "conclusion": "neutral",
+ "before": "deadbeefb",
+ "after": "deadbeefa"}`)
+ })
+
+ checkSuiteOpt := CreateCheckSuiteOptions{
+ HeadSHA: "deadbeef",
+ HeadBranch: String("master"),
+ }
+
+ checkSuite, _, err := client.Checks.CreateCheckSuite(context.Background(), "o", "r", checkSuiteOpt)
+ if err != nil {
+ t.Errorf("Checks.CreateCheckSuite return error: %v", err)
+ }
+
+ want := &CheckSuite{
+ ID: Int64(2),
+ Status: String("completed"),
+ HeadSHA: String("deadbeef"),
+ HeadBranch: String("master"),
+ Conclusion: String("neutral"),
+ BeforeSHA: String("deadbeefb"),
+ AfterSHA: String("deadbeefa"),
+ }
+ if !reflect.DeepEqual(checkSuite, want) {
+ t.Errorf("Checks.CreateCheckSuite return %+v, want %+v", checkSuite, want)
+ }
+}
+
+func TestChecksService_ReRequestCheckSuite(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/check-suites/1/rerequest", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeCheckRunsPreview)
+ w.WriteHeader(http.StatusCreated)
+ })
+ resp, err := client.Checks.ReRequestCheckSuite(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Checks.ReRequestCheckSuite return error: %v", err)
+ }
+ if got, want := resp.StatusCode, http.StatusCreated; got != want {
+ t.Errorf("Checks.ReRequestCheckSuite = %v, want %v", got, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/doc.go b/vendor/github.com/google/go-github/github/doc.go
new file mode 100644
index 0000000..96445d2
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/doc.go
@@ -0,0 +1,187 @@
+// 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 provides a client for using the GitHub API.
+
+Usage:
+
+ import "github.com/google/go-github/github"
+
+Construct a new GitHub client, then use the various services on the client to
+access different parts of the GitHub API. For example:
+
+ client := github.NewClient(nil)
+
+ // list all organizations for user "willnorris"
+ orgs, _, err := client.Organizations.List(ctx, "willnorris", nil)
+
+Some API methods have optional parameters that can be passed. For example:
+
+ client := github.NewClient(nil)
+
+ // list public repositories for org "github"
+ opt := &github.RepositoryListByOrgOptions{Type: "public"}
+ repos, _, err := client.Repositories.ListByOrg(ctx, "github", opt)
+
+The services of a client divide the API into logical chunks and correspond to
+the structure of the GitHub API documentation at
+https://developer.github.com/v3/.
+
+NOTE: Using the https://godoc.org/context package, one can easily
+pass cancelation signals and deadlines to various services of the client for
+handling a request. In case there is no context available, then context.Background()
+can be used as a starting point.
+
+For more sample code snippets, head over to the https://github.com/google/go-github/tree/master/example directory.
+
+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 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 "golang.org/x/oauth2"
+
+ func main() {
+ ctx := context.Background()
+ ts := oauth2.StaticTokenSource(
+ &oauth2.Token{AccessToken: "... your access token ..."},
+ )
+ tc := oauth2.NewClient(ctx, ts)
+
+ client := github.NewClient(tc)
+
+ // list all repositories for the authenticated user
+ repos, _, err := client.Repositories.List(ctx, "", 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.
+
+See the oauth2 docs for complete instructions on using that library.
+
+For API methods that require HTTP Basic Authentication, use the
+BasicAuthTransport.
+
+GitHub Apps authentication can be provided by the
+https://github.com/bradleyfalzon/ghinstallation package.
+
+ import "github.com/bradleyfalzon/ghinstallation"
+
+ func main() {
+ // Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99.
+ itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "2016-10-19.private-key.pem")
+ if err != nil {
+ // Handle error.
+ }
+
+ // Use installation transport with client
+ client := github.NewClient(&http.Client{Transport: itr})
+
+ // Use client...
+ }
+
+Rate Limiting
+
+GitHub imposes a rate limit on all API clients. Unauthenticated clients are
+limited to 60 requests per hour, while authenticated clients can make up to
+5,000 requests per hour. The Search API has a custom rate limit. Unauthenticated
+clients are limited to 10 requests per minute, while authenticated clients
+can make up to 30 requests per minute. To receive the higher rate limit when
+making calls that are not issued on behalf of a user,
+use UnauthenticatedRateLimitedTransport.
+
+The returned Response.Rate value contains the rate limit information
+from the most recent API call. If a recent enough response isn't
+available, you can use RateLimits to fetch the most up-to-date rate
+limit data for the client.
+
+To detect an API rate limit error, you can check if its type is *github.RateLimitError:
+
+ repos, _, err := client.Repositories.List(ctx, "", nil)
+ if _, ok := err.(*github.RateLimitError); ok {
+ log.Println("hit rate limit")
+ }
+
+Learn more about GitHub rate limiting at
+https://developer.github.com/v3/#rate-limiting.
+
+Accepted Status
+
+Some endpoints may return a 202 Accepted status code, meaning that the
+information required is not yet ready and was scheduled to be gathered on
+the GitHub side. Methods known to behave like this are documented specifying
+this behavior.
+
+To detect this condition of error, you can check if its type is
+*github.AcceptedError:
+
+ stats, _, err := client.Repositories.ListContributorsStats(ctx, org, repo)
+ if _, ok := err.(*github.AcceptedError); ok {
+ log.Println("scheduled on GitHub side")
+ }
+
+Conditional Requests
+
+The GitHub API has good support for conditional requests which will help
+prevent you from burning through your rate limit, as well as help speed up your
+application. go-github does not handle conditional requests directly, but is
+instead designed to work with a caching http.Transport. We recommend using
+https://github.com/gregjones/httpcache for that.
+
+Learn more about GitHub conditional requests at
+https://developer.github.com/v3/#conditional-requests.
+
+Creating and Updating Resources
+
+All structs for GitHub resources use pointer values for all non-repeated fields.
+This allows distinguishing between unset fields and those set to a zero-value.
+Helper functions have been provided to easily create these pointers for string,
+bool, and int values. For example:
+
+ // create a new private repository named "foo"
+ repo := &github.Repository{
+ Name: github.String("foo"),
+ Private: github.Bool(true),
+ }
+ client.Repositories.Create(ctx, "", repo)
+
+Users who have worked with protocol buffers should find this pattern familiar.
+
+Pagination
+
+All requests for resource collections (repos, pull requests, issues, etc.)
+support pagination. Pagination options are described in the
+github.ListOptions struct and passed to the list methods directly or as an
+embedded type of a more specific list options struct (for example
+github.PullRequestListOptions). Pages information is available via the
+github.Response struct.
+
+ client := github.NewClient(nil)
+
+ opt := &github.RepositoryListByOrgOptions{
+ ListOptions: github.ListOptions{PerPage: 10},
+ }
+ // get all pages of results
+ var allRepos []*github.Repository
+ for {
+ repos, resp, err := client.Repositories.ListByOrg(ctx, "github", opt)
+ if err != nil {
+ return err
+ }
+ allRepos = append(allRepos, repos...)
+ if resp.NextPage == 0 {
+ break
+ }
+ opt.Page = resp.NextPage
+ }
+
+*/
+package github
diff --git a/vendor/github.com/google/go-github/github/event_types.go b/vendor/github.com/google/go-github/github/event_types.go
new file mode 100644
index 0000000..9f49b34
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/event_types.go
@@ -0,0 +1,791 @@
+// Copyright 2016 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.
+
+// These event types are shared between the Events API and used as Webhook payloads.
+
+package github
+
+// CheckRunEvent is triggered when a check run is "created", "updated", or "re-requested".
+// The Webhook event name is "check_run".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#checkrunevent
+type CheckRunEvent struct {
+ CheckRun *CheckRun `json:"check_run,omitempty"`
+ // The action performed. Can be "created", "updated" or "re-requested".
+ Action *string `json:"action,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Org *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// CheckSuiteEvent is triggered when a check suite is "completed", "requested", or "re-requested".
+// The Webhook event name is "check_suite".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#checksuiteevent
+type CheckSuiteEvent struct {
+ CheckSuite *CheckSuite `json:"check_suite,omitempty"`
+ // The action performed. Can be "completed", "requested" or "re-requested".
+ Action *string `json:"action,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Org *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// CommitCommentEvent is triggered when a commit comment is created.
+// The Webhook event name is "commit_comment".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#commitcommentevent
+type CommitCommentEvent struct {
+ Comment *RepositoryComment `json:"comment,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Action *string `json:"action,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// CreateEvent represents a created repository, branch, or tag.
+// The Webhook event name is "create".
+//
+// Note: webhooks will not receive this event for created repositories.
+// Additionally, webhooks will not receive this event for tags if more
+// than three tags are pushed at once.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#createevent
+type CreateEvent struct {
+ Ref *string `json:"ref,omitempty"`
+ // RefType is the object that was created. Possible values are: "repository", "branch", "tag".
+ RefType *string `json:"ref_type,omitempty"`
+ MasterBranch *string `json:"master_branch,omitempty"`
+ Description *string `json:"description,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ PusherType *string `json:"pusher_type,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// DeleteEvent represents a deleted branch or tag.
+// The Webhook event name is "delete".
+//
+// Note: webhooks will not receive this event for tags if more than three tags
+// are deleted at once.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deleteevent
+type DeleteEvent struct {
+ Ref *string `json:"ref,omitempty"`
+ // RefType is the object that was deleted. Possible values are: "branch", "tag".
+ RefType *string `json:"ref_type,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ PusherType *string `json:"pusher_type,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// DeploymentEvent represents a deployment.
+// The Webhook event name is "deployment".
+//
+// Events of this type are not visible in timelines, they are only used to trigger hooks.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploymentevent
+type DeploymentEvent struct {
+ Deployment *Deployment `json:"deployment,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// DeploymentStatusEvent represents a deployment status.
+// The Webhook event name is "deployment_status".
+//
+// Events of this type are not visible in timelines, they are only used to trigger hooks.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploymentstatusevent
+type DeploymentStatusEvent struct {
+ Deployment *Deployment `json:"deployment,omitempty"`
+ DeploymentStatus *DeploymentStatus `json:"deployment_status,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// ForkEvent is triggered when a user forks a repository.
+// The Webhook event name is "fork".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#forkevent
+type ForkEvent struct {
+ // Forkee is the created repository.
+ Forkee *Repository `json:"forkee,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// Page represents a single Wiki page.
+type Page struct {
+ PageName *string `json:"page_name,omitempty"`
+ Title *string `json:"title,omitempty"`
+ Summary *string `json:"summary,omitempty"`
+ Action *string `json:"action,omitempty"`
+ SHA *string `json:"sha,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+}
+
+// GollumEvent is triggered when a Wiki page is created or updated.
+// The Webhook event name is "gollum".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#gollumevent
+type GollumEvent struct {
+ Pages []*Page `json:"pages,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// EditChange represents the changes when an issue, pull request, or comment has
+// been edited.
+type EditChange struct {
+ Title *struct {
+ From *string `json:"from,omitempty"`
+ } `json:"title,omitempty"`
+ Body *struct {
+ From *string `json:"from,omitempty"`
+ } `json:"body,omitempty"`
+}
+
+// ProjectChange represents the changes when a project has been edited.
+type ProjectChange struct {
+ Name *struct {
+ From *string `json:"from,omitempty"`
+ } `json:"name,omitempty"`
+ Body *struct {
+ From *string `json:"from,omitempty"`
+ } `json:"body,omitempty"`
+}
+
+// ProjectCardChange represents the changes when a project card has been edited.
+type ProjectCardChange struct {
+ Note *struct {
+ From *string `json:"from,omitempty"`
+ } `json:"note,omitempty"`
+}
+
+// ProjectColumnChange represents the changes when a project column has been edited.
+type ProjectColumnChange struct {
+ Name *struct {
+ From *string `json:"from,omitempty"`
+ } `json:"name,omitempty"`
+}
+
+// TeamChange represents the changes when a team has been edited.
+type TeamChange struct {
+ Description *struct {
+ From *string `json:"from,omitempty"`
+ } `json:"description,omitempty"`
+ Name *struct {
+ From *string `json:"from,omitempty"`
+ } `json:"name,omitempty"`
+ Privacy *struct {
+ From *string `json:"from,omitempty"`
+ } `json:"privacy,omitempty"`
+ Repository *struct {
+ Permissions *struct {
+ From *struct {
+ Admin *bool `json:"admin,omitempty"`
+ Pull *bool `json:"pull,omitempty"`
+ Push *bool `json:"push,omitempty"`
+ } `json:"from,omitempty"`
+ } `json:"permissions,omitempty"`
+ } `json:"repository,omitempty"`
+}
+
+// InstallationEvent is triggered when a GitHub App has been installed or uninstalled.
+// The Webhook event name is "installation".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#installationevent
+type InstallationEvent struct {
+ // The action that was performed. Can be either "created" or "deleted".
+ Action *string `json:"action,omitempty"`
+ Repositories []*Repository `json:"repositories,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// InstallationRepositoriesEvent is triggered when a repository is added or
+// removed from an installation. The Webhook event name is "installation_repositories".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#installationrepositoriesevent
+type InstallationRepositoriesEvent struct {
+ // The action that was performed. Can be either "added" or "removed".
+ Action *string `json:"action,omitempty"`
+ RepositoriesAdded []*Repository `json:"repositories_added,omitempty"`
+ RepositoriesRemoved []*Repository `json:"repositories_removed,omitempty"`
+ RepositorySelection *string `json:"repository_selection,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// IssueCommentEvent is triggered when an issue comment is created on an issue
+// or pull request.
+// The Webhook event name is "issue_comment".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuecommentevent
+type IssueCommentEvent struct {
+ // Action is the action that was performed on the comment.
+ // Possible values are: "created", "edited", "deleted".
+ Action *string `json:"action,omitempty"`
+ Issue *Issue `json:"issue,omitempty"`
+ Comment *IssueComment `json:"comment,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Changes *EditChange `json:"changes,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// IssuesEvent is triggered when an issue is assigned, unassigned, labeled,
+// unlabeled, opened, closed, or reopened.
+// The Webhook event name is "issues".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuesevent
+type IssuesEvent struct {
+ // Action is the action that was performed. Possible values are: "assigned",
+ // "unassigned", "labeled", "unlabeled", "opened", "closed", "reopened", "edited".
+ Action *string `json:"action,omitempty"`
+ Issue *Issue `json:"issue,omitempty"`
+ Assignee *User `json:"assignee,omitempty"`
+ Label *Label `json:"label,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Changes *EditChange `json:"changes,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// LabelEvent is triggered when a repository's label is created, edited, or deleted.
+// The Webhook event name is "label"
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#labelevent
+type LabelEvent struct {
+ // Action is the action that was performed. Possible values are:
+ // "created", "edited", "deleted"
+ Action *string `json:"action,omitempty"`
+ Label *Label `json:"label,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Changes *EditChange `json:"changes,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Org *Organization `json:"organization,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// MarketplacePurchaseEvent is triggered when a user purchases, cancels, or changes
+// their GitHub Marketplace plan.
+// Webhook event name "marketplace_purchase".
+//
+// Github API docs: https://developer.github.com/v3/activity/events/types/#marketplacepurchaseevent
+type MarketplacePurchaseEvent struct {
+ // Action is the action that was performed. Possible values are:
+ // "purchased", "cancelled", "changed".
+ Action *string `json:"action,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ EffectiveDate *Timestamp `json:"effective_date,omitempty"`
+ MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"`
+ PreviousMarketplacePurchase *MarketplacePurchase `json:"previous_marketplace_purchase,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// MemberEvent is triggered when a user is added as a collaborator to a repository.
+// The Webhook event name is "member".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#memberevent
+type MemberEvent struct {
+ // Action is the action that was performed. Possible value is: "added".
+ Action *string `json:"action,omitempty"`
+ Member *User `json:"member,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// MembershipEvent is triggered when a user is added or removed from a team.
+// The Webhook event name is "membership".
+//
+// Events of this type are not visible in timelines, they are only used to
+// trigger organization webhooks.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#membershipevent
+type MembershipEvent struct {
+ // Action is the action that was performed. Possible values are: "added", "removed".
+ Action *string `json:"action,omitempty"`
+ // Scope is the scope of the membership. Possible value is: "team".
+ Scope *string `json:"scope,omitempty"`
+ Member *User `json:"member,omitempty"`
+ Team *Team `json:"team,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Org *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted.
+// The Webhook event name is "milestone".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#milestoneevent
+type MilestoneEvent struct {
+ // Action is the action that was performed. Possible values are:
+ // "created", "closed", "opened", "edited", "deleted"
+ Action *string `json:"action,omitempty"`
+ Milestone *Milestone `json:"milestone,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Changes *EditChange `json:"changes,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Org *Organization `json:"organization,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// OrganizationEvent is triggered when a user is added, removed, or invited to an organization.
+// Events of this type are not visible in timelines. These events are only used to trigger organization hooks.
+// Webhook event name is "organization".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#organizationevent
+type OrganizationEvent struct {
+ // Action is the action that was performed.
+ // Can be one of "member_added", "member_removed", or "member_invited".
+ Action *string `json:"action,omitempty"`
+
+ // Invitaion is the invitation for the user or email if the action is "member_invited".
+ Invitation *Invitation `json:"invitation,omitempty"`
+
+ // Membership is the membership between the user and the organization.
+ // Not present when the action is "member_invited".
+ Membership *Membership `json:"membership,omitempty"`
+
+ Organization *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// OrgBlockEvent is triggered when an organization blocks or unblocks a user.
+// The Webhook event name is "org_block".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#orgblockevent
+type OrgBlockEvent struct {
+ // Action is the action that was performed.
+ // Can be "blocked" or "unblocked".
+ Action *string `json:"action,omitempty"`
+ BlockedUser *User `json:"blocked_user,omitempty"`
+ Organization *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// PageBuildEvent represents an attempted build of a GitHub Pages site, whether
+// successful or not.
+// The Webhook event name is "page_build".
+//
+// This event is triggered on push to a GitHub Pages enabled branch (gh-pages
+// for project pages, master for user and organization pages).
+//
+// Events of this type are not visible in timelines, they are only used to trigger hooks.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pagebuildevent
+type PageBuildEvent struct {
+ Build *PagesBuild `json:"build,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ ID *int64 `json:"id,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// PingEvent is triggered when a Webhook is added to GitHub.
+//
+// GitHub API docs: https://developer.github.com/webhooks/#ping-event
+type PingEvent struct {
+ // Random string of GitHub zen.
+ Zen *string `json:"zen,omitempty"`
+ // The ID of the webhook that triggered the ping.
+ HookID *int64 `json:"hook_id,omitempty"`
+ // The webhook configuration.
+ Hook *Hook `json:"hook,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// ProjectEvent is triggered when project is created, modified or deleted.
+// The webhook event name is "project".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectevent
+type ProjectEvent struct {
+ Action *string `json:"action,omitempty"`
+ Changes *ProjectChange `json:"changes,omitempty"`
+ Project *Project `json:"project,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Org *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// ProjectCardEvent is triggered when a project card is created, updated, moved, converted to an issue, or deleted.
+// The webhook event name is "project_card".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectcardevent
+type ProjectCardEvent struct {
+ Action *string `json:"action,omitempty"`
+ Changes *ProjectCardChange `json:"changes,omitempty"`
+ AfterID *int64 `json:"after_id,omitempty"`
+ ProjectCard *ProjectCard `json:"project_card,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Org *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// ProjectColumnEvent is triggered when a project column is created, updated, moved, or deleted.
+// The webhook event name is "project_column".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectcolumnevent
+type ProjectColumnEvent struct {
+ Action *string `json:"action,omitempty"`
+ Changes *ProjectColumnChange `json:"changes,omitempty"`
+ AfterID *int64 `json:"after_id,omitempty"`
+ ProjectColumn *ProjectColumn `json:"project_column,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Org *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// PublicEvent is triggered when a private repository is open sourced.
+// According to GitHub: "Without a doubt: the best GitHub event."
+// The Webhook event name is "public".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#publicevent
+type PublicEvent struct {
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// PullRequestEvent is triggered when a pull request is assigned, unassigned,
+// labeled, unlabeled, opened, closed, reopened, or synchronized.
+// The Webhook event name is "pull_request".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestevent
+type PullRequestEvent struct {
+ // Action is the action that was performed. Possible values are:
+ // "assigned", "unassigned", "review_requested", "review_request_removed", "labeled", "unlabeled",
+ // "opened", "closed", "reopened", "synchronize", "edited".
+ // If the action is "closed" and the merged key is false,
+ // the pull request was closed with unmerged commits. If the action is "closed"
+ // and the merged key is true, the pull request was merged.
+ Action *string `json:"action,omitempty"`
+ Assignee *User `json:"assignee,omitempty"`
+ Number *int `json:"number,omitempty"`
+ PullRequest *PullRequest `json:"pull_request,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Changes *EditChange `json:"changes,omitempty"`
+ // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries.
+ // A request affecting multiple reviewers at once is split into multiple
+ // such event deliveries, each with a single, different RequestedReviewer.
+ RequestedReviewer *User `json:"requested_reviewer,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+ Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries.
+
+ // The following field is only present when the webhook is triggered on
+ // a repository belonging to an organization.
+ Organization *Organization `json:"organization,omitempty"`
+}
+
+// PullRequestReviewEvent is triggered when a review is submitted on a pull
+// request.
+// The Webhook event name is "pull_request_review".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestreviewevent
+type PullRequestReviewEvent struct {
+ // Action is always "submitted".
+ Action *string `json:"action,omitempty"`
+ Review *PullRequestReview `json:"review,omitempty"`
+ PullRequest *PullRequest `json:"pull_request,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+
+ // The following field is only present when the webhook is triggered on
+ // a repository belonging to an organization.
+ Organization *Organization `json:"organization,omitempty"`
+}
+
+// PullRequestReviewCommentEvent is triggered when a comment is created on a
+// portion of the unified diff of a pull request.
+// The Webhook event name is "pull_request_review_comment".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestreviewcommentevent
+type PullRequestReviewCommentEvent struct {
+ // Action is the action that was performed on the comment.
+ // Possible values are: "created", "edited", "deleted".
+ Action *string `json:"action,omitempty"`
+ PullRequest *PullRequest `json:"pull_request,omitempty"`
+ Comment *PullRequestComment `json:"comment,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Changes *EditChange `json:"changes,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// PushEvent represents a git push to a GitHub repository.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pushevent
+type PushEvent struct {
+ PushID *int64 `json:"push_id,omitempty"`
+ Head *string `json:"head,omitempty"`
+ Ref *string `json:"ref,omitempty"`
+ Size *int `json:"size,omitempty"`
+ Commits []PushEventCommit `json:"commits,omitempty"`
+ Before *string `json:"before,omitempty"`
+ DistinctSize *int `json:"distinct_size,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ After *string `json:"after,omitempty"`
+ Created *bool `json:"created,omitempty"`
+ Deleted *bool `json:"deleted,omitempty"`
+ Forced *bool `json:"forced,omitempty"`
+ BaseRef *string `json:"base_ref,omitempty"`
+ Compare *string `json:"compare,omitempty"`
+ Repo *PushEventRepository `json:"repository,omitempty"`
+ HeadCommit *PushEventCommit `json:"head_commit,omitempty"`
+ Pusher *User `json:"pusher,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+func (p PushEvent) String() string {
+ return Stringify(p)
+}
+
+// PushEventCommit represents a git commit in a GitHub PushEvent.
+type PushEventCommit struct {
+ Message *string `json:"message,omitempty"`
+ Author *CommitAuthor `json:"author,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Distinct *bool `json:"distinct,omitempty"`
+
+ // The following fields are only populated by Events API.
+ SHA *string `json:"sha,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ ID *string `json:"id,omitempty"`
+ TreeID *string `json:"tree_id,omitempty"`
+ Timestamp *Timestamp `json:"timestamp,omitempty"`
+ Committer *CommitAuthor `json:"committer,omitempty"`
+ Added []string `json:"added,omitempty"`
+ Removed []string `json:"removed,omitempty"`
+ Modified []string `json:"modified,omitempty"`
+}
+
+func (p PushEventCommit) String() string {
+ return Stringify(p)
+}
+
+// PushEventRepository represents the repo object in a PushEvent payload.
+type PushEventRepository struct {
+ ID *int64 `json:"id,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ FullName *string `json:"full_name,omitempty"`
+ Owner *User `json:"owner,omitempty"`
+ Private *bool `json:"private,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Fork *bool `json:"fork,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ PushedAt *Timestamp `json:"pushed_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ Homepage *string `json:"homepage,omitempty"`
+ Size *int `json:"size,omitempty"`
+ StargazersCount *int `json:"stargazers_count,omitempty"`
+ WatchersCount *int `json:"watchers_count,omitempty"`
+ Language *string `json:"language,omitempty"`
+ HasIssues *bool `json:"has_issues,omitempty"`
+ HasDownloads *bool `json:"has_downloads,omitempty"`
+ HasWiki *bool `json:"has_wiki,omitempty"`
+ HasPages *bool `json:"has_pages,omitempty"`
+ ForksCount *int `json:"forks_count,omitempty"`
+ OpenIssuesCount *int `json:"open_issues_count,omitempty"`
+ DefaultBranch *string `json:"default_branch,omitempty"`
+ MasterBranch *string `json:"master_branch,omitempty"`
+ Organization *string `json:"organization,omitempty"`
+ URL *string `json:"url,omitempty"`
+ ArchiveURL *string `json:"archive_url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ StatusesURL *string `json:"statuses_url,omitempty"`
+ GitURL *string `json:"git_url,omitempty"`
+ SSHURL *string `json:"ssh_url,omitempty"`
+ CloneURL *string `json:"clone_url,omitempty"`
+ SVNURL *string `json:"svn_url,omitempty"`
+}
+
+// PushEventRepoOwner is a basic representation of user/org in a PushEvent payload.
+type PushEventRepoOwner struct {
+ Name *string `json:"name,omitempty"`
+ Email *string `json:"email,omitempty"`
+}
+
+// ReleaseEvent is triggered when a release is published.
+// The Webhook event name is "release".
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#releaseevent
+type ReleaseEvent struct {
+ // Action is the action that was performed. Possible value is: "published".
+ Action *string `json:"action,omitempty"`
+ Release *RepositoryRelease `json:"release,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// RepositoryEvent is triggered when a repository is created.
+// The Webhook event name is "repository".
+//
+// Events of this type are not visible in timelines, they are only used to
+// trigger organization webhooks.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryevent
+type RepositoryEvent struct {
+ // Action is the action that was performed. Possible values are: "created", "deleted",
+ // "publicized", "privatized".
+ Action *string `json:"action,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Org *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// StatusEvent is triggered when the status of a Git commit changes.
+// The Webhook event name is "status".
+//
+// Events of this type are not visible in timelines, they are only used to
+// trigger hooks.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#statusevent
+type StatusEvent struct {
+ SHA *string `json:"sha,omitempty"`
+ // State is the new state. Possible values are: "pending", "success", "failure", "error".
+ State *string `json:"state,omitempty"`
+ Description *string `json:"description,omitempty"`
+ TargetURL *string `json:"target_url,omitempty"`
+ Branches []*Branch `json:"branches,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Context *string `json:"context,omitempty"`
+ Commit *RepositoryCommit `json:"commit,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// TeamEvent is triggered when an organization's team is created, modified or deleted.
+// The Webhook event name is "team".
+//
+// Events of this type are not visible in timelines. These events are only used
+// to trigger hooks.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#teamevent
+type TeamEvent struct {
+ Action *string `json:"action,omitempty"`
+ Team *Team `json:"team,omitempty"`
+ Changes *TeamChange `json:"changes,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Org *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// TeamAddEvent is triggered when a repository is added to a team.
+// The Webhook event name is "team_add".
+//
+// Events of this type are not visible in timelines. These events are only used
+// to trigger hooks.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#teamaddevent
+type TeamAddEvent struct {
+ Team *Team `json:"team,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Org *Organization `json:"organization,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
+
+// WatchEvent is related to starring a repository, not watching. See this API
+// blog post for an explanation: https://developer.github.com/changes/2012-09-05-watcher-api/
+//
+// The event’s actor is the user who starred a repository, and the event’s
+// repository is the repository that was starred.
+//
+// GitHub API docs: https://developer.github.com/v3/activity/events/types/#watchevent
+type WatchEvent struct {
+ // Action is the action that was performed. Possible value is: "started".
+ Action *string `json:"action,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+ Installation *Installation `json:"installation,omitempty"`
+}
diff --git a/vendor/github.com/google/go-github/github/examples_test.go b/vendor/github.com/google/go-github/github/examples_test.go
new file mode 100644
index 0000000..942b0b7
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/examples_test.go
@@ -0,0 +1,168 @@
+// Copyright 2016 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_test
+
+import (
+ "context"
+ "fmt"
+ "log"
+
+ "github.com/google/go-github/v18/github"
+)
+
+func ExampleClient_Markdown() {
+ client := github.NewClient(nil)
+
+ input := "# heading #\n\nLink to issue #1"
+ opt := &github.MarkdownOptions{Mode: "gfm", Context: "google/go-github"}
+
+ output, _, err := client.Markdown(context.Background(), input, opt)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ fmt.Println(output)
+}
+
+func ExampleRepositoriesService_GetReadme() {
+ client := github.NewClient(nil)
+
+ readme, _, err := client.Repositories.GetReadme(context.Background(), "google", "go-github", nil)
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+
+ content, err := readme.GetContent()
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+
+ fmt.Printf("google/go-github README:\n%v\n", content)
+}
+
+func ExampleRepositoriesService_List() {
+ client := github.NewClient(nil)
+
+ user := "willnorris"
+ opt := &github.RepositoryListOptions{Type: "owner", Sort: "updated", Direction: "desc"}
+
+ repos, _, err := client.Repositories.List(context.Background(), user, opt)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ fmt.Printf("Recently updated repositories by %q: %v", user, github.Stringify(repos))
+}
+
+func ExampleRepositoriesService_CreateFile() {
+ // In this example we're creating a new file in a repository using the
+ // Contents API. Only 1 file per commit can be managed through that API.
+
+ // Note that authentication is needed here as you are performing a modification
+ // so you will need to modify the example to provide an oauth client to
+ // github.NewClient() instead of nil. See the following documentation for more
+ // information on how to authenticate with the client:
+ // https://godoc.org/github.com/google/go-github/github#hdr-Authentication
+ client := github.NewClient(nil)
+
+ ctx := context.Background()
+ fileContent := []byte("This is the content of my file\nand the 2nd line of it")
+
+ // Note: the file needs to be absent from the repository as you are not
+ // specifying a SHA reference here.
+ opts := &github.RepositoryContentFileOptions{
+ Message: github.String("This is my commit message"),
+ Content: fileContent,
+ Branch: github.String("master"),
+ Committer: &github.CommitAuthor{Name: github.String("FirstName LastName"), Email: github.String("user@example.com")},
+ }
+ _, _, err := client.Repositories.CreateFile(ctx, "myOrganization", "myRepository", "myNewFile.md", opts)
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+}
+
+func ExampleUsersService_ListAll() {
+ client := github.NewClient(nil)
+ opts := &github.UserListOptions{}
+ for {
+ users, _, err := client.Users.ListAll(context.Background(), opts)
+ if err != nil {
+ log.Fatalf("error listing users: %v", err)
+ }
+ if len(users) == 0 {
+ break
+ }
+ opts.Since = *users[len(users)-1].ID
+ // Process users...
+ }
+}
+
+func ExamplePullRequestsService_Create() {
+ // In this example we're creating a PR and displaying the HTML url at the end.
+
+ // Note that authentication is needed here as you are performing a modification
+ // so you will need to modify the example to provide an oauth client to
+ // github.NewClient() instead of nil. See the following documentation for more
+ // information on how to authenticate with the client:
+ // https://godoc.org/github.com/google/go-github/github#hdr-Authentication
+ client := github.NewClient(nil)
+
+ newPR := &github.NewPullRequest{
+ Title: github.String("My awesome pull request"),
+ Head: github.String("branch_to_merge"),
+ Base: github.String("master"),
+ Body: github.String("This is the description of the PR created with the package `github.com/google/go-github/github`"),
+ MaintainerCanModify: github.Bool(true),
+ }
+
+ pr, _, err := client.PullRequests.Create(context.Background(), "myOrganization", "myRepository", newPR)
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+
+ fmt.Printf("PR created: %s\n", pr.GetHTMLURL())
+}
+
+func ExampleTeamsService_ListTeams() {
+ // This example shows how to get a team ID corresponding to a given team name.
+
+ // Note that authentication is needed here as you are performing a lookup on
+ // an organization's administrative configuration, so you will need to modify
+ // the example to provide an oauth client to github.NewClient() instead of nil.
+ // See the following documentation for more information on how to authenticate
+ // with the client:
+ // https://godoc.org/github.com/google/go-github/github#hdr-Authentication
+ client := github.NewClient(nil)
+
+ teamName := "Developers team"
+ ctx := context.Background()
+ opts := &github.ListOptions{}
+
+ for {
+ teams, resp, err := client.Teams.ListTeams(ctx, "myOrganization", opts)
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ for _, t := range teams {
+ if t.GetName() == teamName {
+ fmt.Printf("Team %q has ID %d\n", teamName, t.GetID())
+ return
+ }
+ }
+ if resp.NextPage == 0 {
+ break
+ }
+ opts.Page = resp.NextPage
+ }
+
+ fmt.Printf("Team %q was not found\n", teamName)
+}
diff --git a/vendor/github.com/google/go-github/github/gen-accessors.go b/vendor/github.com/google/go-github/github/gen-accessors.go
new file mode 100644
index 0000000..fe92206
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/gen-accessors.go
@@ -0,0 +1,332 @@
+// Copyright 2017 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.
+
+// +build ignore
+
+// gen-accessors generates accessor methods for structs with pointer fields.
+//
+// It is meant to be used by the go-github authors in conjunction with the
+// go generate tool before sending a commit to GitHub.
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/format"
+ "go/parser"
+ "go/token"
+ "io/ioutil"
+ "log"
+ "os"
+ "sort"
+ "strings"
+ "text/template"
+)
+
+const (
+ fileSuffix = "-accessors.go"
+)
+
+var (
+ verbose = flag.Bool("v", false, "Print verbose log messages")
+
+ sourceTmpl = template.Must(template.New("source").Parse(source))
+
+ // blacklistStructMethod lists "struct.method" combos to skip.
+ blacklistStructMethod = map[string]bool{
+ "RepositoryContent.GetContent": true,
+ "Client.GetBaseURL": true,
+ "Client.GetUploadURL": true,
+ "ErrorResponse.GetResponse": true,
+ "RateLimitError.GetResponse": true,
+ "AbuseRateLimitError.GetResponse": true,
+ }
+ // blacklistStruct lists structs to skip.
+ blacklistStruct = map[string]bool{
+ "Client": true,
+ }
+)
+
+func logf(fmt string, args ...interface{}) {
+ if *verbose {
+ log.Printf(fmt, args...)
+ }
+}
+
+func main() {
+ flag.Parse()
+ fset := token.NewFileSet()
+
+ pkgs, err := parser.ParseDir(fset, ".", sourceFilter, 0)
+ if err != nil {
+ log.Fatal(err)
+ return
+ }
+
+ for pkgName, pkg := range pkgs {
+ t := &templateData{
+ filename: pkgName + fileSuffix,
+ Year: 2017,
+ Package: pkgName,
+ Imports: map[string]string{},
+ }
+ for filename, f := range pkg.Files {
+ logf("Processing %v...", filename)
+ if err := t.processAST(f); err != nil {
+ log.Fatal(err)
+ }
+ }
+ if err := t.dump(); err != nil {
+ log.Fatal(err)
+ }
+ }
+ logf("Done.")
+}
+
+func (t *templateData) processAST(f *ast.File) error {
+ for _, decl := range f.Decls {
+ gd, ok := decl.(*ast.GenDecl)
+ if !ok {
+ continue
+ }
+ for _, spec := range gd.Specs {
+ ts, ok := spec.(*ast.TypeSpec)
+ if !ok {
+ continue
+ }
+ // Skip unexported identifiers.
+ if !ts.Name.IsExported() {
+ logf("Struct %v is unexported; skipping.", ts.Name)
+ continue
+ }
+ // Check if the struct is blacklisted.
+ if blacklistStruct[ts.Name.Name] {
+ logf("Struct %v is blacklisted; skipping.", ts.Name)
+ continue
+ }
+ st, ok := ts.Type.(*ast.StructType)
+ if !ok {
+ continue
+ }
+ for _, field := range st.Fields.List {
+ se, ok := field.Type.(*ast.StarExpr)
+ if len(field.Names) == 0 || !ok {
+ continue
+ }
+
+ fieldName := field.Names[0]
+ // Skip unexported identifiers.
+ if !fieldName.IsExported() {
+ logf("Field %v is unexported; skipping.", fieldName)
+ continue
+ }
+ // Check if "struct.method" is blacklisted.
+ if key := fmt.Sprintf("%v.Get%v", ts.Name, fieldName); blacklistStructMethod[key] {
+ logf("Method %v is blacklisted; skipping.", key)
+ continue
+ }
+
+ switch x := se.X.(type) {
+ case *ast.ArrayType:
+ t.addArrayType(x, ts.Name.String(), fieldName.String())
+ case *ast.Ident:
+ t.addIdent(x, ts.Name.String(), fieldName.String())
+ case *ast.MapType:
+ t.addMapType(x, ts.Name.String(), fieldName.String())
+ case *ast.SelectorExpr:
+ t.addSelectorExpr(x, ts.Name.String(), fieldName.String())
+ default:
+ logf("processAST: type %q, field %q, unknown %T: %+v", ts.Name, fieldName, x, x)
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func sourceFilter(fi os.FileInfo) bool {
+ return !strings.HasSuffix(fi.Name(), "_test.go") && !strings.HasSuffix(fi.Name(), fileSuffix)
+}
+
+func (t *templateData) dump() error {
+ if len(t.Getters) == 0 {
+ logf("No getters for %v; skipping.", t.filename)
+ return nil
+ }
+
+ // Sort getters by ReceiverType.FieldName.
+ sort.Sort(byName(t.Getters))
+
+ var buf bytes.Buffer
+ if err := sourceTmpl.Execute(&buf, t); err != nil {
+ return err
+ }
+ clean, err := format.Source(buf.Bytes())
+ if err != nil {
+ return err
+ }
+
+ logf("Writing %v...", t.filename)
+ return ioutil.WriteFile(t.filename, clean, 0644)
+}
+
+func newGetter(receiverType, fieldName, fieldType, zeroValue string, namedStruct bool) *getter {
+ return &getter{
+ sortVal: strings.ToLower(receiverType) + "." + strings.ToLower(fieldName),
+ ReceiverVar: strings.ToLower(receiverType[:1]),
+ ReceiverType: receiverType,
+ FieldName: fieldName,
+ FieldType: fieldType,
+ ZeroValue: zeroValue,
+ NamedStruct: namedStruct,
+ }
+}
+
+func (t *templateData) addArrayType(x *ast.ArrayType, receiverType, fieldName string) {
+ var eltType string
+ switch elt := x.Elt.(type) {
+ case *ast.Ident:
+ eltType = elt.String()
+ default:
+ logf("addArrayType: type %q, field %q: unknown elt type: %T %+v; skipping.", receiverType, fieldName, elt, elt)
+ return
+ }
+
+ t.Getters = append(t.Getters, newGetter(receiverType, fieldName, "[]"+eltType, "nil", false))
+}
+
+func (t *templateData) addIdent(x *ast.Ident, receiverType, fieldName string) {
+ var zeroValue string
+ var namedStruct = false
+ switch x.String() {
+ case "int", "int64":
+ zeroValue = "0"
+ case "string":
+ zeroValue = `""`
+ case "bool":
+ zeroValue = "false"
+ case "Timestamp":
+ zeroValue = "Timestamp{}"
+ default:
+ zeroValue = "nil"
+ namedStruct = true
+ }
+
+ t.Getters = append(t.Getters, newGetter(receiverType, fieldName, x.String(), zeroValue, namedStruct))
+}
+
+func (t *templateData) addMapType(x *ast.MapType, receiverType, fieldName string) {
+ var keyType string
+ switch key := x.Key.(type) {
+ case *ast.Ident:
+ keyType = key.String()
+ default:
+ logf("addMapType: type %q, field %q: unknown key type: %T %+v; skipping.", receiverType, fieldName, key, key)
+ return
+ }
+
+ var valueType string
+ switch value := x.Value.(type) {
+ case *ast.Ident:
+ valueType = value.String()
+ default:
+ logf("addMapType: type %q, field %q: unknown value type: %T %+v; skipping.", receiverType, fieldName, value, value)
+ return
+ }
+
+ fieldType := fmt.Sprintf("map[%v]%v", keyType, valueType)
+ zeroValue := fmt.Sprintf("map[%v]%v{}", keyType, valueType)
+ t.Getters = append(t.Getters, newGetter(receiverType, fieldName, fieldType, zeroValue, false))
+}
+
+func (t *templateData) addSelectorExpr(x *ast.SelectorExpr, receiverType, fieldName string) {
+ if strings.ToLower(fieldName[:1]) == fieldName[:1] { // Non-exported field.
+ return
+ }
+
+ var xX string
+ if xx, ok := x.X.(*ast.Ident); ok {
+ xX = xx.String()
+ }
+
+ switch xX {
+ case "time", "json":
+ if xX == "json" {
+ t.Imports["encoding/json"] = "encoding/json"
+ } else {
+ t.Imports[xX] = xX
+ }
+ fieldType := fmt.Sprintf("%v.%v", xX, x.Sel.Name)
+ zeroValue := fmt.Sprintf("%v.%v{}", xX, x.Sel.Name)
+ if xX == "time" && x.Sel.Name == "Duration" {
+ zeroValue = "0"
+ }
+ t.Getters = append(t.Getters, newGetter(receiverType, fieldName, fieldType, zeroValue, false))
+ default:
+ logf("addSelectorExpr: xX %q, type %q, field %q: unknown x=%+v; skipping.", xX, receiverType, fieldName, x)
+ }
+}
+
+type templateData struct {
+ filename string
+ Year int
+ Package string
+ Imports map[string]string
+ Getters []*getter
+}
+
+type getter struct {
+ sortVal string // Lower-case version of "ReceiverType.FieldName".
+ ReceiverVar string // The one-letter variable name to match the ReceiverType.
+ ReceiverType string
+ FieldName string
+ FieldType string
+ ZeroValue string
+ NamedStruct bool // Getter for named struct.
+}
+
+type byName []*getter
+
+func (b byName) Len() int { return len(b) }
+func (b byName) Less(i, j int) bool { return b[i].sortVal < b[j].sortVal }
+func (b byName) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+
+const source = `// Copyright {{.Year}} 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.
+
+// Code generated by gen-accessors; DO NOT EDIT.
+
+package {{.Package}}
+{{with .Imports}}
+import (
+ {{- range . -}}
+ "{{.}}"
+ {{end -}}
+)
+{{end}}
+{{range .Getters}}
+{{if .NamedStruct}}
+// Get{{.FieldName}} returns the {{.FieldName}} field.
+func ({{.ReceiverVar}} *{{.ReceiverType}}) Get{{.FieldName}}() *{{.FieldType}} {
+ if {{.ReceiverVar}} == nil {
+ return {{.ZeroValue}}
+ }
+ return {{.ReceiverVar}}.{{.FieldName}}
+}
+{{else}}
+// Get{{.FieldName}} returns the {{.FieldName}} field if it's non-nil, zero value otherwise.
+func ({{.ReceiverVar}} *{{.ReceiverType}}) Get{{.FieldName}}() {{.FieldType}} {
+ if {{.ReceiverVar}} == nil || {{.ReceiverVar}}.{{.FieldName}} == nil {
+ return {{.ZeroValue}}
+ }
+ return *{{.ReceiverVar}}.{{.FieldName}}
+}
+{{end}}
+{{end}}
+`
diff --git a/vendor/github.com/google/go-github/github/gists.go b/vendor/github.com/google/go-github/github/gists.go
new file mode 100644
index 0000000..15e0bc2
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/gists.go
@@ -0,0 +1,358 @@
+// Copyright 2013 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+ "context"
+ "fmt"
+ "time"
+)
+
+// GistsService handles communication with the Gist related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/
+type GistsService service
+
+// Gist represents a GitHub's gist.
+type Gist struct {
+ ID *string `json:"id,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Public *bool `json:"public,omitempty"`
+ Owner *User `json:"owner,omitempty"`
+ Files map[GistFilename]GistFile `json:"files,omitempty"`
+ Comments *int `json:"comments,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ GitPullURL *string `json:"git_pull_url,omitempty"`
+ GitPushURL *string `json:"git_push_url,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+func (g Gist) String() string {
+ return Stringify(g)
+}
+
+// GistFilename represents filename on a gist.
+type GistFilename string
+
+// GistFile represents a file on a gist.
+type GistFile struct {
+ Size *int `json:"size,omitempty"`
+ Filename *string `json:"filename,omitempty"`
+ Language *string `json:"language,omitempty"`
+ Type *string `json:"type,omitempty"`
+ RawURL *string `json:"raw_url,omitempty"`
+ Content *string `json:"content,omitempty"`
+}
+
+func (g GistFile) String() string {
+ return Stringify(g)
+}
+
+// GistCommit represents a commit on a gist.
+type GistCommit struct {
+ URL *string `json:"url,omitempty"`
+ Version *string `json:"version,omitempty"`
+ User *User `json:"user,omitempty"`
+ ChangeStatus *CommitStats `json:"change_status,omitempty"`
+ CommittedAt *Timestamp `json:"committed_at,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+func (gc GistCommit) String() string {
+ return Stringify(gc)
+}
+
+// GistFork represents a fork of a gist.
+type GistFork struct {
+ URL *string `json:"url,omitempty"`
+ User *User `json:"user,omitempty"`
+ ID *string `json:"id,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+func (gf GistFork) String() string {
+ return Stringify(gf)
+}
+
+// GistListOptions specifies the optional parameters to the
+// GistsService.List, GistsService.ListAll, and GistsService.ListStarred methods.
+type GistListOptions struct {
+ // Since filters Gists by time.
+ Since time.Time `url:"since,omitempty"`
+
+ ListOptions
+}
+
+// List gists for a user. Passing the empty string will list
+// all public gists if called anonymously. However, if the call
+// is authenticated, it will returns all gists for the authenticated
+// user.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#list-gists
+func (s *GistsService) List(ctx context.Context, user string, opt *GistListOptions) ([]*Gist, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v/gists", user)
+ } else {
+ u = "gists"
+ }
+ 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
+ }
+
+ var gists []*Gist
+ resp, err := s.client.Do(ctx, req, &gists)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return gists, resp, nil
+}
+
+// ListAll lists all public gists.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#list-gists
+func (s *GistsService) ListAll(ctx context.Context, opt *GistListOptions) ([]*Gist, *Response, error) {
+ u, err := addOptions("gists/public", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var gists []*Gist
+ resp, err := s.client.Do(ctx, req, &gists)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return gists, resp, nil
+}
+
+// ListStarred lists starred gists of authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#list-gists
+func (s *GistsService) ListStarred(ctx context.Context, opt *GistListOptions) ([]*Gist, *Response, error) {
+ u, err := addOptions("gists/starred", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var gists []*Gist
+ resp, err := s.client.Do(ctx, req, &gists)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return gists, resp, nil
+}
+
+// Get a single gist.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#get-a-single-gist
+func (s *GistsService) Get(ctx context.Context, id string) (*Gist, *Response, error) {
+ u := fmt.Sprintf("gists/%v", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ gist := new(Gist)
+ resp, err := s.client.Do(ctx, req, gist)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return gist, resp, nil
+}
+
+// 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(ctx context.Context, 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(ctx, req, gist)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return gist, resp, nil
+}
+
+// Create a gist for authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#create-a-gist
+func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response, error) {
+ u := "gists"
+ req, err := s.client.NewRequest("POST", u, gist)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ g := new(Gist)
+ resp, err := s.client.Do(ctx, req, g)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return g, resp, nil
+}
+
+// Edit a gist.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#edit-a-gist
+func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist, *Response, error) {
+ u := fmt.Sprintf("gists/%v", id)
+ req, err := s.client.NewRequest("PATCH", u, gist)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ g := new(Gist)
+ resp, err := s.client.Do(ctx, req, g)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return g, resp, nil
+}
+
+// ListCommits lists commits of a gist.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#list-gist-commits
+func (s *GistsService) ListCommits(ctx context.Context, id string, opt *ListOptions) ([]*GistCommit, *Response, error) {
+ u := fmt.Sprintf("gists/%v/commits", id)
+ 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
+ }
+
+ var gistCommits []*GistCommit
+ resp, err := s.client.Do(ctx, req, &gistCommits)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return gistCommits, resp, nil
+}
+
+// Delete a gist.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#delete-a-gist
+func (s *GistsService) Delete(ctx context.Context, id string) (*Response, error) {
+ u := fmt.Sprintf("gists/%v", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
+
+// Star a gist on behalf of authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#star-a-gist
+func (s *GistsService) Star(ctx context.Context, id string) (*Response, error) {
+ u := fmt.Sprintf("gists/%v/star", id)
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
+
+// Unstar a gist on a behalf of authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#unstar-a-gist
+func (s *GistsService) Unstar(ctx context.Context, id string) (*Response, error) {
+ u := fmt.Sprintf("gists/%v/star", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
+
+// IsStarred checks if a gist is starred by authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#check-if-a-gist-is-starred
+func (s *GistsService) IsStarred(ctx context.Context, id string) (bool, *Response, error) {
+ u := fmt.Sprintf("gists/%v/star", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+ resp, err := s.client.Do(ctx, req, nil)
+ starred, err := parseBoolResponse(err)
+ return starred, resp, err
+}
+
+// Fork a gist.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#fork-a-gist
+func (s *GistsService) Fork(ctx context.Context, id string) (*Gist, *Response, error) {
+ u := fmt.Sprintf("gists/%v/forks", id)
+ req, err := s.client.NewRequest("POST", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ g := new(Gist)
+ resp, err := s.client.Do(ctx, req, g)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return g, resp, nil
+}
+
+// ListForks lists forks of a gist.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/#list-gist-forks
+func (s *GistsService) ListForks(ctx context.Context, id string) ([]*GistFork, *Response, error) {
+ u := fmt.Sprintf("gists/%v/forks", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var gistForks []*GistFork
+ resp, err := s.client.Do(ctx, req, &gistForks)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return gistForks, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/gists_comments.go b/vendor/github.com/google/go-github/github/gists_comments.go
new file mode 100644
index 0000000..d5322e3
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/gists_comments.go
@@ -0,0 +1,119 @@
+// 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// GistComment represents a Gist comment.
+type GistComment struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Body *string `json:"body,omitempty"`
+ User *User `json:"user,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+}
+
+func (g GistComment) String() string {
+ return Stringify(g)
+}
+
+// ListComments lists all comments for a gist.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/comments/#list-comments-on-a-gist
+func (s *GistsService) ListComments(ctx context.Context, gistID string, opt *ListOptions) ([]*GistComment, *Response, error) {
+ u := fmt.Sprintf("gists/%v/comments", gistID)
+ 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
+ }
+
+ var comments []*GistComment
+ resp, err := s.client.Do(ctx, req, &comments)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return comments, resp, nil
+}
+
+// GetComment retrieves a single comment from a gist.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/comments/#get-a-single-comment
+func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID int64) (*GistComment, *Response, error) {
+ u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c := new(GistComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// CreateComment creates a comment for a gist.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/comments/#create-a-comment
+func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) {
+ u := fmt.Sprintf("gists/%v/comments", gistID)
+ req, err := s.client.NewRequest("POST", u, comment)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c := new(GistComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// EditComment edits an existing gist comment.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/comments/#edit-a-comment
+func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) {
+ u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID)
+ req, err := s.client.NewRequest("PATCH", u, comment)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c := new(GistComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// DeleteComment deletes a gist comment.
+//
+// GitHub API docs: https://developer.github.com/v3/gists/comments/#delete-a-comment
+func (s *GistsService) DeleteComment(ctx context.Context, gistID string, commentID int64) (*Response, error) {
+ u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/gists_comments_test.go b/vendor/github.com/google/go-github/github/gists_comments_test.go
new file mode 100644
index 0000000..d2f5a95
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/gists_comments_test.go
@@ -0,0 +1,169 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestGistsService_ListComments(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/comments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id": 1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ comments, _, err := client.Gists.ListComments(context.Background(), "1", opt)
+ if err != nil {
+ t.Errorf("Gists.Comments returned error: %v", err)
+ }
+
+ want := []*GistComment{{ID: Int64(1)}}
+ if !reflect.DeepEqual(comments, want) {
+ t.Errorf("Gists.ListComments returned %+v, want %+v", comments, want)
+ }
+}
+
+func TestGistsService_ListComments_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gists.ListComments(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestGistsService_GetComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/comments/2", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id": 1}`)
+ })
+
+ comment, _, err := client.Gists.GetComment(context.Background(), "1", 2)
+ if err != nil {
+ t.Errorf("Gists.GetComment returned error: %v", err)
+ }
+
+ want := &GistComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Gists.GetComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestGistsService_GetComment_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gists.GetComment(context.Background(), "%", 1)
+ testURLParseError(t, err)
+}
+
+func TestGistsService_CreateComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &GistComment{ID: Int64(1), Body: String("b")}
+
+ mux.HandleFunc("/gists/1/comments", func(w http.ResponseWriter, r *http.Request) {
+ v := new(GistComment)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ comment, _, err := client.Gists.CreateComment(context.Background(), "1", input)
+ if err != nil {
+ t.Errorf("Gists.CreateComment returned error: %v", err)
+ }
+
+ want := &GistComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Gists.CreateComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestGistsService_CreateComment_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gists.CreateComment(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestGistsService_EditComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &GistComment{ID: Int64(1), Body: String("b")}
+
+ mux.HandleFunc("/gists/1/comments/2", func(w http.ResponseWriter, r *http.Request) {
+ v := new(GistComment)
+ 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}`)
+ })
+
+ comment, _, err := client.Gists.EditComment(context.Background(), "1", 2, input)
+ if err != nil {
+ t.Errorf("Gists.EditComment returned error: %v", err)
+ }
+
+ want := &GistComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Gists.EditComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestGistsService_EditComment_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gists.EditComment(context.Background(), "%", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestGistsService_DeleteComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/comments/2", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Gists.DeleteComment(context.Background(), "1", 2)
+ if err != nil {
+ t.Errorf("Gists.Delete returned error: %v", err)
+ }
+}
+
+func TestGistsService_DeleteComment_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Gists.DeleteComment(context.Background(), "%", 1)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/gists_test.go b/vendor/github.com/google/go-github/github/gists_test.go
new file mode 100644
index 0000000..3d31c9a
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/gists_test.go
@@ -0,0 +1,534 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestGistsService_List_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ since := "2013-01-01T00:00:00Z"
+
+ mux.HandleFunc("/users/u/gists", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "since": since,
+ })
+ fmt.Fprint(w, `[{"id": "1"}]`)
+ })
+
+ opt := &GistListOptions{Since: time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC)}
+ gists, _, err := client.Gists.List(context.Background(), "u", opt)
+ if err != nil {
+ t.Errorf("Gists.List returned error: %v", err)
+ }
+
+ want := []*Gist{{ID: String("1")}}
+ if !reflect.DeepEqual(gists, want) {
+ t.Errorf("Gists.List returned %+v, want %+v", gists, want)
+ }
+}
+
+func TestGistsService_List_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id": "1"}]`)
+ })
+
+ gists, _, err := client.Gists.List(context.Background(), "", nil)
+ if err != nil {
+ t.Errorf("Gists.List returned error: %v", err)
+ }
+
+ want := []*Gist{{ID: String("1")}}
+ if !reflect.DeepEqual(gists, want) {
+ t.Errorf("Gists.List returned %+v, want %+v", gists, want)
+ }
+}
+
+func TestGistsService_List_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gists.List(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestGistsService_ListAll(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ since := "2013-01-01T00:00:00Z"
+
+ mux.HandleFunc("/gists/public", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "since": since,
+ })
+ fmt.Fprint(w, `[{"id": "1"}]`)
+ })
+
+ opt := &GistListOptions{Since: time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC)}
+ gists, _, err := client.Gists.ListAll(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Gists.ListAll returned error: %v", err)
+ }
+
+ want := []*Gist{{ID: String("1")}}
+ if !reflect.DeepEqual(gists, want) {
+ t.Errorf("Gists.ListAll returned %+v, want %+v", gists, want)
+ }
+}
+
+func TestGistsService_ListStarred(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ since := "2013-01-01T00:00:00Z"
+
+ mux.HandleFunc("/gists/starred", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "since": since,
+ })
+ fmt.Fprint(w, `[{"id": "1"}]`)
+ })
+
+ opt := &GistListOptions{Since: time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC)}
+ gists, _, err := client.Gists.ListStarred(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Gists.ListStarred returned error: %v", err)
+ }
+
+ want := []*Gist{{ID: String("1")}}
+ if !reflect.DeepEqual(gists, want) {
+ t.Errorf("Gists.ListStarred returned %+v, want %+v", gists, want)
+ }
+}
+
+func TestGistsService_Get(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id": "1"}`)
+ })
+
+ gist, _, err := client.Gists.Get(context.Background(), "1")
+ 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_Get_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gists.Get(context.Background(), "%")
+ testURLParseError(t, err)
+}
+
+func TestGistsService_GetRevision(t *testing.T) {
+ client, mux, _, teardown := 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(context.Background(), "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) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gists.GetRevision(context.Background(), "%", "%")
+ testURLParseError(t, err)
+}
+
+func TestGistsService_Create(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Gist{
+ Description: String("Gist description"),
+ Public: Bool(false),
+ Files: map[GistFilename]GistFile{
+ "test.txt": {Content: String("Gist file content")},
+ },
+ }
+
+ mux.HandleFunc("/gists", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Gist)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w,
+ `
+ {
+ "id": "1",
+ "description": "Gist description",
+ "public": false,
+ "files": {
+ "test.txt": {
+ "filename": "test.txt"
+ }
+ }
+ }`)
+ })
+
+ gist, _, err := client.Gists.Create(context.Background(), input)
+ if err != nil {
+ t.Errorf("Gists.Create returned error: %v", err)
+ }
+
+ want := &Gist{
+ ID: String("1"),
+ Description: String("Gist description"),
+ Public: Bool(false),
+ Files: map[GistFilename]GistFile{
+ "test.txt": {Filename: String("test.txt")},
+ },
+ }
+ if !reflect.DeepEqual(gist, want) {
+ t.Errorf("Gists.Create returned %+v, want %+v", gist, want)
+ }
+}
+
+func TestGistsService_Edit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Gist{
+ Description: String("New description"),
+ Files: map[GistFilename]GistFile{
+ "new.txt": {Content: String("new file content")},
+ },
+ }
+
+ mux.HandleFunc("/gists/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Gist)
+ 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",
+ "description": "new description",
+ "public": false,
+ "files": {
+ "test.txt": {
+ "filename": "test.txt"
+ },
+ "new.txt": {
+ "filename": "new.txt"
+ }
+ }
+ }`)
+ })
+
+ gist, _, err := client.Gists.Edit(context.Background(), "1", input)
+ if err != nil {
+ t.Errorf("Gists.Edit returned error: %v", err)
+ }
+
+ want := &Gist{
+ ID: String("1"),
+ Description: String("new description"),
+ Public: Bool(false),
+ Files: map[GistFilename]GistFile{
+ "test.txt": {Filename: String("test.txt")},
+ "new.txt": {Filename: String("new.txt")},
+ },
+ }
+ if !reflect.DeepEqual(gist, want) {
+ t.Errorf("Gists.Edit returned %+v, want %+v", gist, want)
+ }
+}
+
+func TestGistsService_Edit_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gists.Edit(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestGistsService_ListCommits(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/commits", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, nil)
+ fmt.Fprint(w, `
+ [
+ {
+ "url": "https://api.github.com/gists/1/1",
+ "version": "1",
+ "user": {
+ "id": 1
+ },
+ "change_status": {
+ "deletions": 0,
+ "additions": 180,
+ "total": 180
+ },
+ "committed_at": "2010-01-01T00:00:00Z"
+ }
+ ]
+ `)
+ })
+
+ gistCommits, _, err := client.Gists.ListCommits(context.Background(), "1", nil)
+ if err != nil {
+ t.Errorf("Gists.ListCommits returned error: %v", err)
+ }
+
+ want := []*GistCommit{{
+ URL: String("https://api.github.com/gists/1/1"),
+ Version: String("1"),
+ User: &User{ID: Int64(1)},
+ CommittedAt: &Timestamp{time.Date(2010, time.January, 1, 00, 00, 00, 0, time.UTC)},
+ ChangeStatus: &CommitStats{
+ Additions: Int(180),
+ Deletions: Int(0),
+ Total: Int(180),
+ }}}
+
+ if !reflect.DeepEqual(gistCommits, want) {
+ t.Errorf("Gists.ListCommits returned %+v, want %+v", gistCommits, want)
+ }
+}
+
+func TestGistsService_ListCommits_withOptions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/commits", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "2",
+ })
+ fmt.Fprint(w, `[]`)
+ })
+
+ _, _, err := client.Gists.ListCommits(context.Background(), "1", &ListOptions{Page: 2})
+ if err != nil {
+ t.Errorf("Gists.ListCommits returned error: %v", err)
+ }
+}
+
+func TestGistsService_Delete(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Gists.Delete(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Gists.Delete returned error: %v", err)
+ }
+}
+
+func TestGistsService_Delete_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Gists.Delete(context.Background(), "%")
+ testURLParseError(t, err)
+}
+
+func TestGistsService_Star(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ })
+
+ _, err := client.Gists.Star(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Gists.Star returned error: %v", err)
+ }
+}
+
+func TestGistsService_Star_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Gists.Star(context.Background(), "%")
+ testURLParseError(t, err)
+}
+
+func TestGistsService_Unstar(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Gists.Unstar(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Gists.Unstar returned error: %v", err)
+ }
+}
+
+func TestGistsService_Unstar_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Gists.Unstar(context.Background(), "%")
+ testURLParseError(t, err)
+}
+
+func TestGistsService_IsStarred_hasStar(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ star, _, err := client.Gists.IsStarred(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Gists.Starred returned error: %v", err)
+ }
+ if want := true; star != want {
+ t.Errorf("Gists.Starred returned %+v, want %+v", star, want)
+ }
+}
+
+func TestGistsService_IsStarred_noStar(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNotFound)
+ })
+
+ star, _, err := client.Gists.IsStarred(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Gists.Starred returned error: %v", err)
+ }
+ if want := false; star != want {
+ t.Errorf("Gists.Starred returned %+v, want %+v", star, want)
+ }
+}
+
+func TestGistsService_IsStarred_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gists.IsStarred(context.Background(), "%")
+ testURLParseError(t, err)
+}
+
+func TestGistsService_Fork(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/forks", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ fmt.Fprint(w, `{"id": "2"}`)
+ })
+
+ gist, _, err := client.Gists.Fork(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Gists.Fork returned error: %v", err)
+ }
+
+ want := &Gist{ID: String("2")}
+ if !reflect.DeepEqual(gist, want) {
+ t.Errorf("Gists.Fork returned %+v, want %+v", gist, want)
+ }
+}
+
+func TestGistsService_ListForks(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gists/1/forks", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, nil)
+ fmt.Fprint(w, `
+ [
+ {"url": "https://api.github.com/gists/1",
+ "user": {"id": 1},
+ "id": "1",
+ "created_at": "2010-01-01T00:00:00Z",
+ "updated_at": "2013-01-01T00:00:00Z"
+ }
+ ]
+ `)
+ })
+
+ gistForks, _, err := client.Gists.ListForks(context.Background(), "1")
+ if err != nil {
+ t.Errorf("Gists.ListForks returned error: %v", err)
+ }
+
+ want := []*GistFork{{
+ URL: String("https://api.github.com/gists/1"),
+ ID: String("1"),
+ User: &User{ID: Int64(1)},
+ CreatedAt: &Timestamp{time.Date(2010, time.January, 1, 00, 00, 00, 0, time.UTC)},
+ UpdatedAt: &Timestamp{time.Date(2013, time.January, 1, 00, 00, 00, 0, time.UTC)}}}
+
+ if !reflect.DeepEqual(gistForks, want) {
+ t.Errorf("Gists.ListForks returned %+v, want %+v", gistForks, want)
+ }
+}
+
+func TestGistsService_Fork_invalidID(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gists.Fork(context.Background(), "%")
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/git.go b/vendor/github.com/google/go-github/github/git.go
new file mode 100644
index 0000000..1ce4743
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git.go
@@ -0,0 +1,12 @@
+// 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
+
+// GitService handles communication with the git data related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/git/
+type GitService service
diff --git a/vendor/github.com/google/go-github/github/git_blobs.go b/vendor/github.com/google/go-github/github/git_blobs.go
new file mode 100644
index 0000000..70aee14
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git_blobs.go
@@ -0,0 +1,69 @@
+// 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 (
+ "bytes"
+ "context"
+ "fmt"
+)
+
+// Blob represents a blob object.
+type Blob struct {
+ Content *string `json:"content,omitempty"`
+ Encoding *string `json:"encoding,omitempty"`
+ SHA *string `json:"sha,omitempty"`
+ Size *int `json:"size,omitempty"`
+ URL *string `json:"url,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+// GetBlob fetches a blob from a repo given a SHA.
+//
+// GitHub API docs: https://developer.github.com/v3/git/blobs/#get-a-blob
+func (s *GitService) GetBlob(ctx context.Context, owner string, repo string, sha string) (*Blob, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ blob := new(Blob)
+ resp, err := s.client.Do(ctx, req, blob)
+ return blob, resp, err
+}
+
+// GetBlobRaw fetches a blob's contents from a repo.
+// Unlike GetBlob, it returns the raw bytes rather than the base64-encoded data.
+//
+// GitHub API docs: https://developer.github.com/v3/git/blobs/#get-a-blob
+func (s *GitService) GetBlobRaw(ctx context.Context, owner, repo, sha string) ([]byte, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+ req.Header.Set("Accept", "application/vnd.github.v3.raw")
+
+ var buf bytes.Buffer
+ resp, err := s.client.Do(ctx, req, &buf)
+ return buf.Bytes(), resp, err
+}
+
+// CreateBlob creates a blob object.
+//
+// GitHub API docs: https://developer.github.com/v3/git/blobs/#create-a-blob
+func (s *GitService) CreateBlob(ctx context.Context, owner string, repo string, blob *Blob) (*Blob, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/git/blobs", owner, repo)
+ req, err := s.client.NewRequest("POST", u, blob)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ t := new(Blob)
+ resp, err := s.client.Do(ctx, req, t)
+ return t, resp, err
+}
diff --git a/vendor/github.com/google/go-github/github/git_blobs_test.go b/vendor/github.com/google/go-github/github/git_blobs_test.go
new file mode 100644
index 0000000..9945d35
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git_blobs_test.go
@@ -0,0 +1,124 @@
+// Copyright 2014 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 (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestGitService_GetBlob(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/blobs/s", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ fmt.Fprint(w, `{
+ "sha": "s",
+ "content": "blob content"
+ }`)
+ })
+
+ blob, _, err := client.Git.GetBlob(context.Background(), "o", "r", "s")
+ if err != nil {
+ t.Errorf("Git.GetBlob returned error: %v", err)
+ }
+
+ want := Blob{
+ SHA: String("s"),
+ Content: String("blob content"),
+ }
+
+ if !reflect.DeepEqual(*blob, want) {
+ t.Errorf("Blob.Get returned %+v, want %+v", *blob, want)
+ }
+}
+
+func TestGitService_GetBlob_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Git.GetBlob(context.Background(), "%", "%", "%")
+ testURLParseError(t, err)
+}
+
+func TestGitService_GetBlobRaw(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/blobs/s", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", "application/vnd.github.v3.raw")
+
+ fmt.Fprint(w, `raw contents here`)
+ })
+
+ blob, _, err := client.Git.GetBlobRaw(context.Background(), "o", "r", "s")
+ if err != nil {
+ t.Errorf("Git.GetBlobRaw returned error: %v", err)
+ }
+
+ want := []byte("raw contents here")
+ if !bytes.Equal(blob, want) {
+ t.Errorf("GetBlobRaw returned %q, want %q", blob, want)
+ }
+}
+
+func TestGitService_CreateBlob(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Blob{
+ SHA: String("s"),
+ Content: String("blob content"),
+ Encoding: String("utf-8"),
+ Size: Int(12),
+ }
+
+ mux.HandleFunc("/repos/o/r/git/blobs", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Blob)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+
+ want := input
+ if !reflect.DeepEqual(v, want) {
+ t.Errorf("Git.CreateBlob request body: %+v, want %+v", v, want)
+ }
+
+ fmt.Fprint(w, `{
+ "sha": "s",
+ "content": "blob content",
+ "encoding": "utf-8",
+ "size": 12
+ }`)
+ })
+
+ blob, _, err := client.Git.CreateBlob(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Git.CreateBlob returned error: %v", err)
+ }
+
+ want := input
+
+ if !reflect.DeepEqual(*blob, *want) {
+ t.Errorf("Git.CreateBlob returned %+v, want %+v", *blob, *want)
+ }
+}
+
+func TestGitService_CreateBlob_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Git.CreateBlob(context.Background(), "%", "%", &Blob{})
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/git_commits.go b/vendor/github.com/google/go-github/github/git_commits.go
new file mode 100644
index 0000000..1eb48a8
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git_commits.go
@@ -0,0 +1,134 @@
+// 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// SignatureVerification represents GPG signature verification.
+type SignatureVerification struct {
+ Verified *bool `json:"verified,omitempty"`
+ Reason *string `json:"reason,omitempty"`
+ Signature *string `json:"signature,omitempty"`
+ Payload *string `json:"payload,omitempty"`
+}
+
+// Commit represents a GitHub commit.
+type Commit struct {
+ SHA *string `json:"sha,omitempty"`
+ Author *CommitAuthor `json:"author,omitempty"`
+ Committer *CommitAuthor `json:"committer,omitempty"`
+ Message *string `json:"message,omitempty"`
+ Tree *Tree `json:"tree,omitempty"`
+ Parents []Commit `json:"parents,omitempty"`
+ Stats *CommitStats `json:"stats,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Verification *SignatureVerification `json:"verification,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+
+ // CommentCount is the number of GitHub comments on the commit. This
+ // is only populated for requests that fetch GitHub data like
+ // Pulls.ListCommits, Repositories.ListCommits, etc.
+ CommentCount *int `json:"comment_count,omitempty"`
+}
+
+func (c Commit) String() string {
+ return Stringify(c)
+}
+
+// CommitAuthor represents the author or committer of a commit. The commit
+// author may not correspond to a GitHub User.
+type CommitAuthor struct {
+ Date *time.Time `json:"date,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Email *string `json:"email,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ Login *string `json:"username,omitempty"` // Renamed for go-github consistency.
+}
+
+func (c CommitAuthor) String() string {
+ return Stringify(c)
+}
+
+// GetCommit fetchs the Commit object for a given SHA.
+//
+// GitHub API docs: https://developer.github.com/v3/git/commits/#get-a-commit
+func (s *GitService) GetCommit(ctx context.Context, owner string, repo string, sha string) (*Commit, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/git/commits/%v", owner, repo, sha)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeGitSigningPreview)
+
+ c := new(Commit)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// createCommit represents the body of a CreateCommit request.
+type createCommit struct {
+ Author *CommitAuthor `json:"author,omitempty"`
+ Committer *CommitAuthor `json:"committer,omitempty"`
+ Message *string `json:"message,omitempty"`
+ Tree *string `json:"tree,omitempty"`
+ Parents []string `json:"parents,omitempty"`
+}
+
+// CreateCommit creates a new commit in a repository.
+// commit must not be nil.
+//
+// The commit.Committer is optional and will be filled with the commit.Author
+// data if omitted. If the commit.Author is omitted, it will be filled in with
+// the authenticated user’s information and the current date.
+//
+// GitHub API docs: https://developer.github.com/v3/git/commits/#create-a-commit
+func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string, commit *Commit) (*Commit, *Response, error) {
+ if commit == nil {
+ return nil, nil, fmt.Errorf("commit must be provided")
+ }
+
+ u := fmt.Sprintf("repos/%v/%v/git/commits", owner, repo)
+
+ parents := make([]string, len(commit.Parents))
+ for i, parent := range commit.Parents {
+ parents[i] = *parent.SHA
+ }
+
+ body := &createCommit{
+ Author: commit.Author,
+ Committer: commit.Committer,
+ Message: commit.Message,
+ Parents: parents,
+ }
+ if commit.Tree != nil {
+ body.Tree = commit.Tree.SHA
+ }
+
+ req, err := s.client.NewRequest("POST", u, body)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c := new(Commit)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/git_commits_test.go b/vendor/github.com/google/go-github/github/git_commits_test.go
new file mode 100644
index 0000000..ff8827f
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git_commits_test.go
@@ -0,0 +1,90 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestGitService_GetCommit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/commits/s", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeGitSigningPreview)
+ fmt.Fprint(w, `{"sha":"s","message":"m","author":{"name":"n"}}`)
+ })
+
+ commit, _, err := client.Git.GetCommit(context.Background(), "o", "r", "s")
+ if err != nil {
+ t.Errorf("Git.GetCommit returned error: %v", err)
+ }
+
+ want := &Commit{SHA: String("s"), Message: String("m"), Author: &CommitAuthor{Name: String("n")}}
+ if !reflect.DeepEqual(commit, want) {
+ t.Errorf("Git.GetCommit returned %+v, want %+v", commit, want)
+ }
+}
+
+func TestGitService_GetCommit_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Git.GetCommit(context.Background(), "%", "%", "%")
+ testURLParseError(t, err)
+}
+
+func TestGitService_CreateCommit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Commit{
+ Message: String("m"),
+ Tree: &Tree{SHA: String("t")},
+ Parents: []Commit{{SHA: String("p")}},
+ }
+
+ mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) {
+ v := new(createCommit)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+
+ want := &createCommit{
+ Message: input.Message,
+ Tree: String("t"),
+ Parents: []string{"p"},
+ }
+ if !reflect.DeepEqual(v, want) {
+ t.Errorf("Request body = %+v, want %+v", v, want)
+ }
+ fmt.Fprint(w, `{"sha":"s"}`)
+ })
+
+ commit, _, err := client.Git.CreateCommit(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Git.CreateCommit returned error: %v", err)
+ }
+
+ want := &Commit{SHA: String("s")}
+ if !reflect.DeepEqual(commit, want) {
+ t.Errorf("Git.CreateCommit returned %+v, want %+v", commit, want)
+ }
+}
+
+func TestGitService_CreateCommit_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Git.CreateCommit(context.Background(), "%", "%", &Commit{})
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/git_refs.go b/vendor/github.com/google/go-github/github/git_refs.go
new file mode 100644
index 0000000..3b2ced2
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git_refs.go
@@ -0,0 +1,218 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+)
+
+// Reference represents a GitHub reference.
+type Reference struct {
+ Ref *string `json:"ref"`
+ URL *string `json:"url"`
+ Object *GitObject `json:"object"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+func (r Reference) String() string {
+ return Stringify(r)
+}
+
+// GitObject represents a Git object.
+type GitObject struct {
+ Type *string `json:"type"`
+ SHA *string `json:"sha"`
+ URL *string `json:"url"`
+}
+
+func (o GitObject) String() string {
+ return Stringify(o)
+}
+
+// createRefRequest represents the payload for creating a reference.
+type createRefRequest struct {
+ Ref *string `json:"ref"`
+ SHA *string `json:"sha"`
+}
+
+// updateRefRequest represents the payload for updating a reference.
+type updateRefRequest struct {
+ SHA *string `json:"sha"`
+ Force *bool `json:"force"`
+}
+
+// GetRef fetches a single Reference object for a given Git ref.
+// If there is no exact match, GetRef will return an error.
+//
+// Note: The GitHub API can return multiple matches.
+// If you wish to use this functionality please use the GetRefs() method.
+//
+// GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference
+func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) {
+ ref = strings.TrimPrefix(ref, "refs/")
+ u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, ref)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(Reference)
+ resp, err := s.client.Do(ctx, req, r)
+ if _, ok := err.(*json.UnmarshalTypeError); ok {
+ // Multiple refs, means there wasn't an exact match.
+ return nil, resp, errors.New("no exact match found for this ref")
+ } else if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// GetRefs fetches a slice of Reference objects for a given Git ref.
+// If there is an exact match, only that ref is returned.
+// If there is no exact match, GitHub returns all refs that start with ref.
+// If returned error is nil, there will be at least 1 ref returned.
+// For example:
+//
+// "heads/featureA" -> ["refs/heads/featureA"] // Exact match, single ref is returned.
+// "heads/feature" -> ["refs/heads/featureA", "refs/heads/featureB"] // All refs that start with ref.
+// "heads/notexist" -> [] // Returns an error.
+//
+// GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference
+func (s *GitService) GetRefs(ctx context.Context, owner string, repo string, ref string) ([]*Reference, *Response, error) {
+ ref = strings.TrimPrefix(ref, "refs/")
+ u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, ref)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var rawJSON json.RawMessage
+ resp, err := s.client.Do(ctx, req, &rawJSON)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ // Prioritize the most common case: a single returned ref.
+ r := new(Reference)
+ singleUnmarshalError := json.Unmarshal(rawJSON, r)
+ if singleUnmarshalError == nil {
+ return []*Reference{r}, resp, nil
+ }
+
+ // Attempt to unmarshal multiple refs.
+ var rs []*Reference
+ multipleUnmarshalError := json.Unmarshal(rawJSON, &rs)
+ if multipleUnmarshalError == nil {
+ if len(rs) == 0 {
+ return nil, resp, fmt.Errorf("unexpected response from GitHub API: an array of refs with length 0")
+ }
+ return rs, resp, nil
+ }
+
+ return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", singleUnmarshalError, multipleUnmarshalError)
+}
+
+// ReferenceListOptions specifies optional parameters to the
+// GitService.ListRefs method.
+type ReferenceListOptions struct {
+ Type string `url:"-"`
+
+ ListOptions
+}
+
+// ListRefs lists all refs in a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/git/refs/#get-all-references
+func (s *GitService) ListRefs(ctx context.Context, owner, repo string, opt *ReferenceListOptions) ([]*Reference, *Response, error) {
+ var u string
+ if opt != nil && opt.Type != "" {
+ u = fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, opt.Type)
+ } else {
+ u = fmt.Sprintf("repos/%v/%v/git/refs", owner, repo)
+ }
+ 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
+ }
+
+ var rs []*Reference
+ resp, err := s.client.Do(ctx, req, &rs)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return rs, resp, nil
+}
+
+// CreateRef creates a new ref in a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/git/refs/#create-a-reference
+func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, ref *Reference) (*Reference, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/git/refs", owner, repo)
+ req, err := s.client.NewRequest("POST", u, &createRefRequest{
+ // back-compat with previous behavior that didn't require 'refs/' prefix
+ Ref: String("refs/" + strings.TrimPrefix(*ref.Ref, "refs/")),
+ SHA: ref.Object.SHA,
+ })
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(Reference)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// UpdateRef updates an existing ref in a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/git/refs/#update-a-reference
+func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) {
+ refPath := strings.TrimPrefix(*ref.Ref, "refs/")
+ u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refPath)
+ req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{
+ SHA: ref.Object.SHA,
+ Force: &force,
+ })
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(Reference)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// DeleteRef deletes a ref from a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/git/refs/#delete-a-reference
+func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) {
+ ref = strings.TrimPrefix(ref, "refs/")
+ u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, ref)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/git_refs_test.go b/vendor/github.com/google/go-github/github/git_refs_test.go
new file mode 100644
index 0000000..3cae3c0
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git_refs_test.go
@@ -0,0 +1,429 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestGitService_GetRef_singleRef(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `
+ {
+ "ref": "refs/heads/b",
+ "url": "https://api.github.com/repos/o/r/git/refs/heads/b",
+ "object": {
+ "type": "commit",
+ "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
+ "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
+ }
+ }`)
+ })
+
+ ref, _, err := client.Git.GetRef(context.Background(), "o", "r", "refs/heads/b")
+ if err != nil {
+ t.Fatalf("Git.GetRef returned error: %v", err)
+ }
+
+ want := &Reference{
+ Ref: String("refs/heads/b"),
+ URL: String("https://api.github.com/repos/o/r/git/refs/heads/b"),
+ Object: &GitObject{
+ Type: String("commit"),
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ },
+ }
+ if !reflect.DeepEqual(ref, want) {
+ t.Errorf("Git.GetRef returned %+v, want %+v", ref, want)
+ }
+
+ // without 'refs/' prefix
+ if _, _, err := client.Git.GetRef(context.Background(), "o", "r", "heads/b"); err != nil {
+ t.Errorf("Git.GetRef returned error: %v", err)
+ }
+}
+
+func TestGitService_GetRef_multipleRefs(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `
+ [
+ {
+ "ref": "refs/heads/booger",
+ "url": "https://api.github.com/repos/o/r/git/refs/heads/booger",
+ "object": {
+ "type": "commit",
+ "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
+ "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
+ }
+ },
+ {
+ "ref": "refs/heads/bandsaw",
+ "url": "https://api.github.com/repos/o/r/git/refs/heads/bandsaw",
+ "object": {
+ "type": "commit",
+ "sha": "612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac",
+ "url": "https://api.github.com/repos/o/r/git/commits/612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac"
+ }
+ }
+ ]
+ `)
+ })
+
+ _, _, err := client.Git.GetRef(context.Background(), "o", "r", "refs/heads/b")
+ want := "no exact match found for this ref"
+ if err.Error() != want {
+ t.Errorf("Git.GetRef returned %+v, want %+v", err, want)
+ }
+
+}
+
+func TestGitService_GetRefs_singleRef(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `
+ {
+ "ref": "refs/heads/b",
+ "url": "https://api.github.com/repos/o/r/git/refs/heads/b",
+ "object": {
+ "type": "commit",
+ "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
+ "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
+ }
+ }`)
+ })
+
+ refs, _, err := client.Git.GetRefs(context.Background(), "o", "r", "refs/heads/b")
+ if err != nil {
+ t.Fatalf("Git.GetRefs returned error: %v", err)
+ }
+
+ ref := refs[0]
+ want := &Reference{
+ Ref: String("refs/heads/b"),
+ URL: String("https://api.github.com/repos/o/r/git/refs/heads/b"),
+ Object: &GitObject{
+ Type: String("commit"),
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ },
+ }
+ if !reflect.DeepEqual(ref, want) {
+ t.Errorf("Git.GetRefs returned %+v, want %+v", ref, want)
+ }
+
+ // without 'refs/' prefix
+ if _, _, err := client.Git.GetRefs(context.Background(), "o", "r", "heads/b"); err != nil {
+ t.Errorf("Git.GetRefs returned error: %v", err)
+ }
+}
+
+func TestGitService_GetRefs_multipleRefs(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `
+ [
+ {
+ "ref": "refs/heads/booger",
+ "url": "https://api.github.com/repos/o/r/git/refs/heads/booger",
+ "object": {
+ "type": "commit",
+ "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
+ "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
+ }
+ },
+ {
+ "ref": "refs/heads/bandsaw",
+ "url": "https://api.github.com/repos/o/r/git/refs/heads/bandsaw",
+ "object": {
+ "type": "commit",
+ "sha": "612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac",
+ "url": "https://api.github.com/repos/o/r/git/commits/612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac"
+ }
+ }
+ ]
+ `)
+ })
+
+ refs, _, err := client.Git.GetRefs(context.Background(), "o", "r", "refs/heads/b")
+ if err != nil {
+ t.Errorf("Git.GetRefs returned error: %v", err)
+ }
+
+ want := &Reference{
+ Ref: String("refs/heads/booger"),
+ URL: String("https://api.github.com/repos/o/r/git/refs/heads/booger"),
+ Object: &GitObject{
+ Type: String("commit"),
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ },
+ }
+ if !reflect.DeepEqual(refs[0], want) {
+ t.Errorf("Git.GetRefs returned %+v, want %+v", refs[0], want)
+ }
+}
+
+// TestGitService_GetRefs_noRefs tests for behaviour resulting from an unexpected GH response. This should never actually happen.
+func TestGitService_GetRefs_noRefs(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, "[]")
+ })
+
+ _, _, err := client.Git.GetRefs(context.Background(), "o", "r", "refs/heads/b")
+ want := "unexpected response from GitHub API: an array of refs with length 0"
+ if err.Error() != want {
+ t.Errorf("Git.GetRefs returned %+v, want %+v", err, want)
+ }
+
+}
+
+func TestGitService_ListRefs(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/refs", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `
+ [
+ {
+ "ref": "refs/heads/branchA",
+ "url": "https://api.github.com/repos/o/r/git/refs/heads/branchA",
+ "object": {
+ "type": "commit",
+ "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
+ "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
+ }
+ },
+ {
+ "ref": "refs/heads/branchB",
+ "url": "https://api.github.com/repos/o/r/git/refs/heads/branchB",
+ "object": {
+ "type": "commit",
+ "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
+ "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
+ }
+ }
+ ]`)
+ })
+
+ refs, _, err := client.Git.ListRefs(context.Background(), "o", "r", nil)
+ if err != nil {
+ t.Errorf("Git.ListRefs returned error: %v", err)
+ }
+
+ want := []*Reference{
+ {
+ Ref: String("refs/heads/branchA"),
+ URL: String("https://api.github.com/repos/o/r/git/refs/heads/branchA"),
+ Object: &GitObject{
+ Type: String("commit"),
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ },
+ },
+ {
+ Ref: String("refs/heads/branchB"),
+ URL: String("https://api.github.com/repos/o/r/git/refs/heads/branchB"),
+ Object: &GitObject{
+ Type: String("commit"),
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ },
+ },
+ }
+ if !reflect.DeepEqual(refs, want) {
+ t.Errorf("Git.ListRefs returned %+v, want %+v", refs, want)
+ }
+}
+
+func TestGitService_ListRefs_options(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/refs/t", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"ref": "r"}]`)
+ })
+
+ opt := &ReferenceListOptions{Type: "t", ListOptions: ListOptions{Page: 2}}
+ refs, _, err := client.Git.ListRefs(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Git.ListRefs returned error: %v", err)
+ }
+
+ want := []*Reference{{Ref: String("r")}}
+ if !reflect.DeepEqual(refs, want) {
+ t.Errorf("Git.ListRefs returned %+v, want %+v", refs, want)
+ }
+}
+
+func TestGitService_CreateRef(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ args := &createRefRequest{
+ Ref: String("refs/heads/b"),
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ }
+
+ mux.HandleFunc("/repos/o/r/git/refs", func(w http.ResponseWriter, r *http.Request) {
+ v := new(createRefRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, args) {
+ t.Errorf("Request body = %+v, want %+v", v, args)
+ }
+ fmt.Fprint(w, `
+ {
+ "ref": "refs/heads/b",
+ "url": "https://api.github.com/repos/o/r/git/refs/heads/b",
+ "object": {
+ "type": "commit",
+ "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
+ "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
+ }
+ }`)
+ })
+
+ ref, _, err := client.Git.CreateRef(context.Background(), "o", "r", &Reference{
+ Ref: String("refs/heads/b"),
+ Object: &GitObject{
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ },
+ })
+ if err != nil {
+ t.Errorf("Git.CreateRef returned error: %v", err)
+ }
+
+ want := &Reference{
+ Ref: String("refs/heads/b"),
+ URL: String("https://api.github.com/repos/o/r/git/refs/heads/b"),
+ Object: &GitObject{
+ Type: String("commit"),
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ },
+ }
+ if !reflect.DeepEqual(ref, want) {
+ t.Errorf("Git.CreateRef returned %+v, want %+v", ref, want)
+ }
+
+ // without 'refs/' prefix
+ _, _, err = client.Git.CreateRef(context.Background(), "o", "r", &Reference{
+ Ref: String("heads/b"),
+ Object: &GitObject{
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ },
+ })
+ if err != nil {
+ t.Errorf("Git.CreateRef returned error: %v", err)
+ }
+}
+
+func TestGitService_UpdateRef(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ args := &updateRefRequest{
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ Force: Bool(true),
+ }
+
+ mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) {
+ v := new(updateRefRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ if !reflect.DeepEqual(v, args) {
+ t.Errorf("Request body = %+v, want %+v", v, args)
+ }
+ fmt.Fprint(w, `
+ {
+ "ref": "refs/heads/b",
+ "url": "https://api.github.com/repos/o/r/git/refs/heads/b",
+ "object": {
+ "type": "commit",
+ "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
+ "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
+ }
+ }`)
+ })
+
+ ref, _, err := client.Git.UpdateRef(context.Background(), "o", "r", &Reference{
+ Ref: String("refs/heads/b"),
+ Object: &GitObject{SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd")},
+ }, true)
+ if err != nil {
+ t.Errorf("Git.UpdateRef returned error: %v", err)
+ }
+
+ want := &Reference{
+ Ref: String("refs/heads/b"),
+ URL: String("https://api.github.com/repos/o/r/git/refs/heads/b"),
+ Object: &GitObject{
+ Type: String("commit"),
+ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"),
+ },
+ }
+ if !reflect.DeepEqual(ref, want) {
+ t.Errorf("Git.UpdateRef returned %+v, want %+v", ref, want)
+ }
+
+ // without 'refs/' prefix
+ _, _, err = client.Git.UpdateRef(context.Background(), "o", "r", &Reference{
+ Ref: String("heads/b"),
+ Object: &GitObject{SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd")},
+ }, true)
+ if err != nil {
+ t.Errorf("Git.UpdateRef returned error: %v", err)
+ }
+}
+
+func TestGitService_DeleteRef(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Git.DeleteRef(context.Background(), "o", "r", "refs/heads/b")
+ if err != nil {
+ t.Errorf("Git.DeleteRef returned error: %v", err)
+ }
+
+ // without 'refs/' prefix
+ if _, err := client.Git.DeleteRef(context.Background(), "o", "r", "heads/b"); err != nil {
+ t.Errorf("Git.DeleteRef returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/git_tags.go b/vendor/github.com/google/go-github/github/git_tags.go
new file mode 100644
index 0000000..90398b3
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git_tags.go
@@ -0,0 +1,79 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// Tag represents a tag object.
+type Tag struct {
+ Tag *string `json:"tag,omitempty"`
+ SHA *string `json:"sha,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Message *string `json:"message,omitempty"`
+ Tagger *CommitAuthor `json:"tagger,omitempty"`
+ Object *GitObject `json:"object,omitempty"`
+ Verification *SignatureVerification `json:"verification,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+// createTagRequest represents the body of a CreateTag request. This is mostly
+// identical to Tag with the exception that the object SHA and Type are
+// top-level fields, rather than being nested inside a JSON object.
+type createTagRequest struct {
+ Tag *string `json:"tag,omitempty"`
+ Message *string `json:"message,omitempty"`
+ Object *string `json:"object,omitempty"`
+ Type *string `json:"type,omitempty"`
+ Tagger *CommitAuthor `json:"tagger,omitempty"`
+}
+
+// GetTag fetchs a tag from a repo given a SHA.
+//
+// GitHub API docs: https://developer.github.com/v3/git/tags/#get-a-tag
+func (s *GitService) GetTag(ctx context.Context, owner string, repo string, sha string) (*Tag, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/git/tags/%v", owner, repo, sha)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeGitSigningPreview)
+
+ tag := new(Tag)
+ resp, err := s.client.Do(ctx, req, tag)
+ return tag, resp, err
+}
+
+// CreateTag creates a tag object.
+//
+// GitHub API docs: https://developer.github.com/v3/git/tags/#create-a-tag-object
+func (s *GitService) CreateTag(ctx context.Context, owner string, repo string, tag *Tag) (*Tag, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/git/tags", owner, repo)
+
+ // convert Tag into a createTagRequest
+ tagRequest := &createTagRequest{
+ Tag: tag.Tag,
+ Message: tag.Message,
+ Tagger: tag.Tagger,
+ }
+ if tag.Object != nil {
+ tagRequest.Object = tag.Object.SHA
+ tagRequest.Type = tag.Object.Type
+ }
+
+ req, err := s.client.NewRequest("POST", u, tagRequest)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ t := new(Tag)
+ resp, err := s.client.Do(ctx, req, t)
+ return t, resp, err
+}
diff --git a/vendor/github.com/google/go-github/github/git_tags_test.go b/vendor/github.com/google/go-github/github/git_tags_test.go
new file mode 100644
index 0000000..0b11c64
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git_tags_test.go
@@ -0,0 +1,68 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestGitService_GetTag(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/tags/s", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeGitSigningPreview)
+ fmt.Fprint(w, `{"tag": "t"}`)
+ })
+
+ tag, _, err := client.Git.GetTag(context.Background(), "o", "r", "s")
+ if err != nil {
+ t.Errorf("Git.GetTag returned error: %v", err)
+ }
+
+ want := &Tag{Tag: String("t")}
+ if !reflect.DeepEqual(tag, want) {
+ t.Errorf("Git.GetTag returned %+v, want %+v", tag, want)
+ }
+}
+
+func TestGitService_CreateTag(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &createTagRequest{Tag: String("t"), Object: String("s")}
+
+ mux.HandleFunc("/repos/o/r/git/tags", func(w http.ResponseWriter, r *http.Request) {
+ v := new(createTagRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"tag": "t"}`)
+ })
+
+ tag, _, err := client.Git.CreateTag(context.Background(), "o", "r", &Tag{
+ Tag: input.Tag,
+ Object: &GitObject{SHA: input.Object},
+ })
+ if err != nil {
+ t.Errorf("Git.CreateTag returned error: %v", err)
+ }
+
+ want := &Tag{Tag: String("t")}
+ if !reflect.DeepEqual(tag, want) {
+ t.Errorf("Git.GetTag returned %+v, want %+v", tag, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/git_trees.go b/vendor/github.com/google/go-github/github/git_trees.go
new file mode 100644
index 0000000..4bc2913
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git_trees.go
@@ -0,0 +1,99 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// Tree represents a GitHub tree.
+type Tree struct {
+ SHA *string `json:"sha,omitempty"`
+ Entries []TreeEntry `json:"tree,omitempty"`
+
+ // Truncated is true if the number of items in the tree
+ // exceeded GitHub's maximum limit and the Entries were truncated
+ // in the response. Only populated for requests that fetch
+ // trees like Git.GetTree.
+ Truncated *bool `json:"truncated,omitempty"`
+}
+
+func (t Tree) String() string {
+ return Stringify(t)
+}
+
+// TreeEntry represents the contents of a tree structure. TreeEntry can
+// represent either a blob, a commit (in the case of a submodule), or another
+// tree.
+type TreeEntry struct {
+ SHA *string `json:"sha,omitempty"`
+ Path *string `json:"path,omitempty"`
+ Mode *string `json:"mode,omitempty"`
+ Type *string `json:"type,omitempty"`
+ Size *int `json:"size,omitempty"`
+ Content *string `json:"content,omitempty"`
+ URL *string `json:"url,omitempty"`
+}
+
+func (t TreeEntry) String() string {
+ return Stringify(t)
+}
+
+// GetTree fetches the Tree object for a given sha hash from a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/git/trees/#get-a-tree
+func (s *GitService) GetTree(ctx context.Context, owner string, repo string, sha string, recursive bool) (*Tree, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/git/trees/%v", owner, repo, sha)
+ if recursive {
+ u += "?recursive=1"
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ t := new(Tree)
+ resp, err := s.client.Do(ctx, req, t)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return t, resp, nil
+}
+
+// createTree represents the body of a CreateTree request.
+type createTree struct {
+ BaseTree string `json:"base_tree,omitempty"`
+ Entries []TreeEntry `json:"tree"`
+}
+
+// CreateTree creates a new tree in a repository. If both a tree and a nested
+// path modifying that tree are specified, it will overwrite the contents of
+// that tree with the new path contents and write a new tree out.
+//
+// GitHub API docs: https://developer.github.com/v3/git/trees/#create-a-tree
+func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []TreeEntry) (*Tree, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo)
+
+ body := &createTree{
+ BaseTree: baseTree,
+ Entries: entries,
+ }
+ req, err := s.client.NewRequest("POST", u, body)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ t := new(Tree)
+ resp, err := s.client.Do(ctx, req, t)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return t, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/git_trees_test.go b/vendor/github.com/google/go-github/github/git_trees_test.go
new file mode 100644
index 0000000..1f7024f
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/git_trees_test.go
@@ -0,0 +1,195 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestGitService_GetTree(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/git/trees/s", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{
+ "sha": "s",
+ "tree": [ { "type": "blob" } ],
+ "truncated": true
+ }`)
+ })
+
+ tree, _, err := client.Git.GetTree(context.Background(), "o", "r", "s", true)
+ if err != nil {
+ t.Errorf("Git.GetTree returned error: %v", err)
+ }
+
+ want := Tree{
+ SHA: String("s"),
+ Entries: []TreeEntry{
+ {
+ Type: String("blob"),
+ },
+ },
+ Truncated: Bool(true),
+ }
+ if !reflect.DeepEqual(*tree, want) {
+ t.Errorf("Tree.Get returned %+v, want %+v", *tree, want)
+ }
+}
+
+func TestGitService_GetTree_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Git.GetTree(context.Background(), "%", "%", "%", false)
+ testURLParseError(t, err)
+}
+
+func TestGitService_CreateTree(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := []TreeEntry{
+ {
+ Path: String("file.rb"),
+ Mode: String("100644"),
+ Type: String("blob"),
+ SHA: String("7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b"),
+ },
+ }
+
+ mux.HandleFunc("/repos/o/r/git/trees", func(w http.ResponseWriter, r *http.Request) {
+ v := new(createTree)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+
+ want := &createTree{
+ BaseTree: "b",
+ Entries: input,
+ }
+ if !reflect.DeepEqual(v, want) {
+ t.Errorf("Git.CreateTree request body: %+v, want %+v", v, want)
+ }
+
+ fmt.Fprint(w, `{
+ "sha": "cd8274d15fa3ae2ab983129fb037999f264ba9a7",
+ "tree": [
+ {
+ "path": "file.rb",
+ "mode": "100644",
+ "type": "blob",
+ "size": 132,
+ "sha": "7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b"
+ }
+ ]
+ }`)
+ })
+
+ tree, _, err := client.Git.CreateTree(context.Background(), "o", "r", "b", input)
+ if err != nil {
+ t.Errorf("Git.CreateTree returned error: %v", err)
+ }
+
+ want := Tree{
+ String("cd8274d15fa3ae2ab983129fb037999f264ba9a7"),
+ []TreeEntry{
+ {
+ Path: String("file.rb"),
+ Mode: String("100644"),
+ Type: String("blob"),
+ Size: Int(132),
+ SHA: String("7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b"),
+ },
+ },
+ nil,
+ }
+
+ if !reflect.DeepEqual(*tree, want) {
+ t.Errorf("Git.CreateTree returned %+v, want %+v", *tree, want)
+ }
+}
+
+func TestGitService_CreateTree_Content(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := []TreeEntry{
+ {
+ Path: String("content.md"),
+ Mode: String("100644"),
+ Content: String("file content"),
+ },
+ }
+
+ mux.HandleFunc("/repos/o/r/git/trees", func(w http.ResponseWriter, r *http.Request) {
+ v := new(createTree)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+
+ want := &createTree{
+ BaseTree: "b",
+ Entries: input,
+ }
+ if !reflect.DeepEqual(v, want) {
+ t.Errorf("Git.CreateTree request body: %+v, want %+v", v, want)
+ }
+
+ fmt.Fprint(w, `{
+ "sha": "5c6780ad2c68743383b740fd1dab6f6a33202b11",
+ "url": "https://api.github.com/repos/o/r/git/trees/5c6780ad2c68743383b740fd1dab6f6a33202b11",
+ "tree": [
+ {
+ "mode": "100644",
+ "type": "blob",
+ "sha": "aad8feacf6f8063150476a7b2bd9770f2794c08b",
+ "path": "content.md",
+ "size": 12,
+ "url": "https://api.github.com/repos/o/r/git/blobs/aad8feacf6f8063150476a7b2bd9770f2794c08b"
+ }
+ ]
+ }`)
+ })
+
+ tree, _, err := client.Git.CreateTree(context.Background(), "o", "r", "b", input)
+ if err != nil {
+ t.Errorf("Git.CreateTree returned error: %v", err)
+ }
+
+ want := Tree{
+ String("5c6780ad2c68743383b740fd1dab6f6a33202b11"),
+ []TreeEntry{
+ {
+ Path: String("content.md"),
+ Mode: String("100644"),
+ Type: String("blob"),
+ Size: Int(12),
+ SHA: String("aad8feacf6f8063150476a7b2bd9770f2794c08b"),
+ URL: String("https://api.github.com/repos/o/r/git/blobs/aad8feacf6f8063150476a7b2bd9770f2794c08b"),
+ },
+ },
+ nil,
+ }
+
+ if !reflect.DeepEqual(*tree, want) {
+ t.Errorf("Git.CreateTree returned %+v, want %+v", *tree, want)
+ }
+}
+
+func TestGitService_CreateTree_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Git.CreateTree(context.Background(), "%", "%", "", nil)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/github-accessors.go b/vendor/github.com/google/go-github/github/github-accessors.go
new file mode 100644
index 0000000..adc94b5
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/github-accessors.go
@@ -0,0 +1,11997 @@
+// Copyright 2017 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.
+
+// Code generated by gen-accessors; DO NOT EDIT.
+
+package github
+
+import (
+ "encoding/json"
+ "time"
+)
+
+// GetRetryAfter returns the RetryAfter field if it's non-nil, zero value otherwise.
+func (a *AbuseRateLimitError) GetRetryAfter() time.Duration {
+ if a == nil || a.RetryAfter == nil {
+ return 0
+ }
+ return *a.RetryAfter
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (a *AdminEnforcement) GetURL() string {
+ if a == nil || a.URL == nil {
+ return ""
+ }
+ return *a.URL
+}
+
+// GetComments returns the Comments field.
+func (a *AdminStats) GetComments() *CommentStats {
+ if a == nil {
+ return nil
+ }
+ return a.Comments
+}
+
+// GetGists returns the Gists field.
+func (a *AdminStats) GetGists() *GistStats {
+ if a == nil {
+ return nil
+ }
+ return a.Gists
+}
+
+// GetHooks returns the Hooks field.
+func (a *AdminStats) GetHooks() *HookStats {
+ if a == nil {
+ return nil
+ }
+ return a.Hooks
+}
+
+// GetIssues returns the Issues field.
+func (a *AdminStats) GetIssues() *IssueStats {
+ if a == nil {
+ return nil
+ }
+ return a.Issues
+}
+
+// GetMilestones returns the Milestones field.
+func (a *AdminStats) GetMilestones() *MilestoneStats {
+ if a == nil {
+ return nil
+ }
+ return a.Milestones
+}
+
+// GetOrgs returns the Orgs field.
+func (a *AdminStats) GetOrgs() *OrgStats {
+ if a == nil {
+ return nil
+ }
+ return a.Orgs
+}
+
+// GetPages returns the Pages field.
+func (a *AdminStats) GetPages() *PageStats {
+ if a == nil {
+ return nil
+ }
+ return a.Pages
+}
+
+// GetPulls returns the Pulls field.
+func (a *AdminStats) GetPulls() *PullStats {
+ if a == nil {
+ return nil
+ }
+ return a.Pulls
+}
+
+// GetRepos returns the Repos field.
+func (a *AdminStats) GetRepos() *RepoStats {
+ if a == nil {
+ return nil
+ }
+ return a.Repos
+}
+
+// GetUsers returns the Users field.
+func (a *AdminStats) GetUsers() *UserStats {
+ if a == nil {
+ return nil
+ }
+ return a.Users
+}
+
+// GetVerifiablePasswordAuthentication returns the VerifiablePasswordAuthentication field if it's non-nil, zero value otherwise.
+func (a *APIMeta) GetVerifiablePasswordAuthentication() bool {
+ if a == nil || a.VerifiablePasswordAuthentication == nil {
+ return false
+ }
+ return *a.VerifiablePasswordAuthentication
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (a *App) GetCreatedAt() time.Time {
+ if a == nil || a.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *a.CreatedAt
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (a *App) GetDescription() string {
+ if a == nil || a.Description == nil {
+ return ""
+ }
+ return *a.Description
+}
+
+// GetExternalURL returns the ExternalURL field if it's non-nil, zero value otherwise.
+func (a *App) GetExternalURL() string {
+ if a == nil || a.ExternalURL == nil {
+ return ""
+ }
+ return *a.ExternalURL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (a *App) GetHTMLURL() string {
+ if a == nil || a.HTMLURL == nil {
+ return ""
+ }
+ return *a.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (a *App) GetID() int64 {
+ if a == nil || a.ID == nil {
+ return 0
+ }
+ return *a.ID
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (a *App) GetName() string {
+ if a == nil || a.Name == nil {
+ return ""
+ }
+ return *a.Name
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (a *App) GetNodeID() string {
+ if a == nil || a.NodeID == nil {
+ return ""
+ }
+ return *a.NodeID
+}
+
+// GetOwner returns the Owner field.
+func (a *App) GetOwner() *User {
+ if a == nil {
+ return nil
+ }
+ return a.Owner
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (a *App) GetUpdatedAt() time.Time {
+ if a == nil || a.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *a.UpdatedAt
+}
+
+// GetApp returns the App field.
+func (a *Authorization) GetApp() *AuthorizationApp {
+ if a == nil {
+ return nil
+ }
+ return a.App
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (a *Authorization) GetCreatedAt() Timestamp {
+ if a == nil || a.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *a.CreatedAt
+}
+
+// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise.
+func (a *Authorization) GetFingerprint() string {
+ if a == nil || a.Fingerprint == nil {
+ return ""
+ }
+ return *a.Fingerprint
+}
+
+// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise.
+func (a *Authorization) GetHashedToken() string {
+ if a == nil || a.HashedToken == nil {
+ return ""
+ }
+ return *a.HashedToken
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (a *Authorization) GetID() int64 {
+ if a == nil || a.ID == nil {
+ return 0
+ }
+ return *a.ID
+}
+
+// GetNote returns the Note field if it's non-nil, zero value otherwise.
+func (a *Authorization) GetNote() string {
+ if a == nil || a.Note == nil {
+ return ""
+ }
+ return *a.Note
+}
+
+// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise.
+func (a *Authorization) GetNoteURL() string {
+ if a == nil || a.NoteURL == nil {
+ return ""
+ }
+ return *a.NoteURL
+}
+
+// GetToken returns the Token field if it's non-nil, zero value otherwise.
+func (a *Authorization) GetToken() string {
+ if a == nil || a.Token == nil {
+ return ""
+ }
+ return *a.Token
+}
+
+// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise.
+func (a *Authorization) GetTokenLastEight() string {
+ if a == nil || a.TokenLastEight == nil {
+ return ""
+ }
+ return *a.TokenLastEight
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (a *Authorization) GetUpdatedAt() Timestamp {
+ if a == nil || a.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *a.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (a *Authorization) GetURL() string {
+ if a == nil || a.URL == nil {
+ return ""
+ }
+ return *a.URL
+}
+
+// GetUser returns the User field.
+func (a *Authorization) GetUser() *User {
+ if a == nil {
+ return nil
+ }
+ return a.User
+}
+
+// GetClientID returns the ClientID field if it's non-nil, zero value otherwise.
+func (a *AuthorizationApp) GetClientID() string {
+ if a == nil || a.ClientID == nil {
+ return ""
+ }
+ return *a.ClientID
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (a *AuthorizationApp) GetName() string {
+ if a == nil || a.Name == nil {
+ return ""
+ }
+ return *a.Name
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (a *AuthorizationApp) GetURL() string {
+ if a == nil || a.URL == nil {
+ return ""
+ }
+ return *a.URL
+}
+
+// GetClientID returns the ClientID field if it's non-nil, zero value otherwise.
+func (a *AuthorizationRequest) GetClientID() string {
+ if a == nil || a.ClientID == nil {
+ return ""
+ }
+ return *a.ClientID
+}
+
+// GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise.
+func (a *AuthorizationRequest) GetClientSecret() string {
+ if a == nil || a.ClientSecret == nil {
+ return ""
+ }
+ return *a.ClientSecret
+}
+
+// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise.
+func (a *AuthorizationRequest) GetFingerprint() string {
+ if a == nil || a.Fingerprint == nil {
+ return ""
+ }
+ return *a.Fingerprint
+}
+
+// GetNote returns the Note field if it's non-nil, zero value otherwise.
+func (a *AuthorizationRequest) GetNote() string {
+ if a == nil || a.Note == nil {
+ return ""
+ }
+ return *a.Note
+}
+
+// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise.
+func (a *AuthorizationRequest) GetNoteURL() string {
+ if a == nil || a.NoteURL == nil {
+ return ""
+ }
+ return *a.NoteURL
+}
+
+// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise.
+func (a *AuthorizationUpdateRequest) GetFingerprint() string {
+ if a == nil || a.Fingerprint == nil {
+ return ""
+ }
+ return *a.Fingerprint
+}
+
+// GetNote returns the Note field if it's non-nil, zero value otherwise.
+func (a *AuthorizationUpdateRequest) GetNote() string {
+ if a == nil || a.Note == nil {
+ return ""
+ }
+ return *a.Note
+}
+
+// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise.
+func (a *AuthorizationUpdateRequest) GetNoteURL() string {
+ if a == nil || a.NoteURL == nil {
+ return ""
+ }
+ return *a.NoteURL
+}
+
+// GetAppID returns the AppID field if it's non-nil, zero value otherwise.
+func (a *AutoTriggerCheck) GetAppID() int64 {
+ if a == nil || a.AppID == nil {
+ return 0
+ }
+ return *a.AppID
+}
+
+// GetSetting returns the Setting field if it's non-nil, zero value otherwise.
+func (a *AutoTriggerCheck) GetSetting() bool {
+ if a == nil || a.Setting == nil {
+ return false
+ }
+ return *a.Setting
+}
+
+// GetContent returns the Content field if it's non-nil, zero value otherwise.
+func (b *Blob) GetContent() string {
+ if b == nil || b.Content == nil {
+ return ""
+ }
+ return *b.Content
+}
+
+// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise.
+func (b *Blob) GetEncoding() string {
+ if b == nil || b.Encoding == nil {
+ return ""
+ }
+ return *b.Encoding
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (b *Blob) GetNodeID() string {
+ if b == nil || b.NodeID == nil {
+ return ""
+ }
+ return *b.NodeID
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (b *Blob) GetSHA() string {
+ if b == nil || b.SHA == nil {
+ return ""
+ }
+ return *b.SHA
+}
+
+// GetSize returns the Size field if it's non-nil, zero value otherwise.
+func (b *Blob) GetSize() int {
+ if b == nil || b.Size == nil {
+ return 0
+ }
+ return *b.Size
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (b *Blob) GetURL() string {
+ if b == nil || b.URL == nil {
+ return ""
+ }
+ return *b.URL
+}
+
+// GetCommit returns the Commit field.
+func (b *Branch) GetCommit() *RepositoryCommit {
+ if b == nil {
+ return nil
+ }
+ return b.Commit
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (b *Branch) GetName() string {
+ if b == nil || b.Name == nil {
+ return ""
+ }
+ return *b.Name
+}
+
+// GetProtected returns the Protected field if it's non-nil, zero value otherwise.
+func (b *Branch) GetProtected() bool {
+ if b == nil || b.Protected == nil {
+ return false
+ }
+ return *b.Protected
+}
+
+// GetApp returns the App field.
+func (c *CheckRun) GetApp() *App {
+ if c == nil {
+ return nil
+ }
+ return c.App
+}
+
+// GetCheckSuite returns the CheckSuite field.
+func (c *CheckRun) GetCheckSuite() *CheckSuite {
+ if c == nil {
+ return nil
+ }
+ return c.CheckSuite
+}
+
+// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetCompletedAt() Timestamp {
+ if c == nil || c.CompletedAt == nil {
+ return Timestamp{}
+ }
+ return *c.CompletedAt
+}
+
+// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetConclusion() string {
+ if c == nil || c.Conclusion == nil {
+ return ""
+ }
+ return *c.Conclusion
+}
+
+// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetExternalID() string {
+ if c == nil || c.ExternalID == nil {
+ return ""
+ }
+ return *c.ExternalID
+}
+
+// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetHeadSHA() string {
+ if c == nil || c.HeadSHA == nil {
+ return ""
+ }
+ return *c.HeadSHA
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetHTMLURL() string {
+ if c == nil || c.HTMLURL == nil {
+ return ""
+ }
+ return *c.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetID() int64 {
+ if c == nil || c.ID == nil {
+ return 0
+ }
+ return *c.ID
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetName() string {
+ if c == nil || c.Name == nil {
+ return ""
+ }
+ return *c.Name
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetNodeID() string {
+ if c == nil || c.NodeID == nil {
+ return ""
+ }
+ return *c.NodeID
+}
+
+// GetOutput returns the Output field.
+func (c *CheckRun) GetOutput() *CheckRunOutput {
+ if c == nil {
+ return nil
+ }
+ return c.Output
+}
+
+// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetStartedAt() Timestamp {
+ if c == nil || c.StartedAt == nil {
+ return Timestamp{}
+ }
+ return *c.StartedAt
+}
+
+// GetStatus returns the Status field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetStatus() string {
+ if c == nil || c.Status == nil {
+ return ""
+ }
+ return *c.Status
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (c *CheckRun) GetURL() string {
+ if c == nil || c.URL == nil {
+ return ""
+ }
+ return *c.URL
+}
+
+// GetAnnotationLevel returns the AnnotationLevel field if it's non-nil, zero value otherwise.
+func (c *CheckRunAnnotation) GetAnnotationLevel() string {
+ if c == nil || c.AnnotationLevel == nil {
+ return ""
+ }
+ return *c.AnnotationLevel
+}
+
+// GetBlobHRef returns the BlobHRef field if it's non-nil, zero value otherwise.
+func (c *CheckRunAnnotation) GetBlobHRef() string {
+ if c == nil || c.BlobHRef == nil {
+ return ""
+ }
+ return *c.BlobHRef
+}
+
+// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise.
+func (c *CheckRunAnnotation) GetEndLine() int {
+ if c == nil || c.EndLine == nil {
+ return 0
+ }
+ return *c.EndLine
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (c *CheckRunAnnotation) GetMessage() string {
+ if c == nil || c.Message == nil {
+ return ""
+ }
+ return *c.Message
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (c *CheckRunAnnotation) GetPath() string {
+ if c == nil || c.Path == nil {
+ return ""
+ }
+ return *c.Path
+}
+
+// GetRawDetails returns the RawDetails field if it's non-nil, zero value otherwise.
+func (c *CheckRunAnnotation) GetRawDetails() string {
+ if c == nil || c.RawDetails == nil {
+ return ""
+ }
+ return *c.RawDetails
+}
+
+// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise.
+func (c *CheckRunAnnotation) GetStartLine() int {
+ if c == nil || c.StartLine == nil {
+ return 0
+ }
+ return *c.StartLine
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (c *CheckRunAnnotation) GetTitle() string {
+ if c == nil || c.Title == nil {
+ return ""
+ }
+ return *c.Title
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (c *CheckRunEvent) GetAction() string {
+ if c == nil || c.Action == nil {
+ return ""
+ }
+ return *c.Action
+}
+
+// GetCheckRun returns the CheckRun field.
+func (c *CheckRunEvent) GetCheckRun() *CheckRun {
+ if c == nil {
+ return nil
+ }
+ return c.CheckRun
+}
+
+// GetInstallation returns the Installation field.
+func (c *CheckRunEvent) GetInstallation() *Installation {
+ if c == nil {
+ return nil
+ }
+ return c.Installation
+}
+
+// GetOrg returns the Org field.
+func (c *CheckRunEvent) GetOrg() *Organization {
+ if c == nil {
+ return nil
+ }
+ return c.Org
+}
+
+// GetRepo returns the Repo field.
+func (c *CheckRunEvent) GetRepo() *Repository {
+ if c == nil {
+ return nil
+ }
+ return c.Repo
+}
+
+// GetSender returns the Sender field.
+func (c *CheckRunEvent) GetSender() *User {
+ if c == nil {
+ return nil
+ }
+ return c.Sender
+}
+
+// GetAlt returns the Alt field if it's non-nil, zero value otherwise.
+func (c *CheckRunImage) GetAlt() string {
+ if c == nil || c.Alt == nil {
+ return ""
+ }
+ return *c.Alt
+}
+
+// GetCaption returns the Caption field if it's non-nil, zero value otherwise.
+func (c *CheckRunImage) GetCaption() string {
+ if c == nil || c.Caption == nil {
+ return ""
+ }
+ return *c.Caption
+}
+
+// GetImageURL returns the ImageURL field if it's non-nil, zero value otherwise.
+func (c *CheckRunImage) GetImageURL() string {
+ if c == nil || c.ImageURL == nil {
+ return ""
+ }
+ return *c.ImageURL
+}
+
+// GetAnnotationsCount returns the AnnotationsCount field if it's non-nil, zero value otherwise.
+func (c *CheckRunOutput) GetAnnotationsCount() int {
+ if c == nil || c.AnnotationsCount == nil {
+ return 0
+ }
+ return *c.AnnotationsCount
+}
+
+// GetAnnotationsURL returns the AnnotationsURL field if it's non-nil, zero value otherwise.
+func (c *CheckRunOutput) GetAnnotationsURL() string {
+ if c == nil || c.AnnotationsURL == nil {
+ return ""
+ }
+ return *c.AnnotationsURL
+}
+
+// GetSummary returns the Summary field if it's non-nil, zero value otherwise.
+func (c *CheckRunOutput) GetSummary() string {
+ if c == nil || c.Summary == nil {
+ return ""
+ }
+ return *c.Summary
+}
+
+// GetText returns the Text field if it's non-nil, zero value otherwise.
+func (c *CheckRunOutput) GetText() string {
+ if c == nil || c.Text == nil {
+ return ""
+ }
+ return *c.Text
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (c *CheckRunOutput) GetTitle() string {
+ if c == nil || c.Title == nil {
+ return ""
+ }
+ return *c.Title
+}
+
+// GetAfterSHA returns the AfterSHA field if it's non-nil, zero value otherwise.
+func (c *CheckSuite) GetAfterSHA() string {
+ if c == nil || c.AfterSHA == nil {
+ return ""
+ }
+ return *c.AfterSHA
+}
+
+// GetApp returns the App field.
+func (c *CheckSuite) GetApp() *App {
+ if c == nil {
+ return nil
+ }
+ return c.App
+}
+
+// GetBeforeSHA returns the BeforeSHA field if it's non-nil, zero value otherwise.
+func (c *CheckSuite) GetBeforeSHA() string {
+ if c == nil || c.BeforeSHA == nil {
+ return ""
+ }
+ return *c.BeforeSHA
+}
+
+// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise.
+func (c *CheckSuite) GetConclusion() string {
+ if c == nil || c.Conclusion == nil {
+ return ""
+ }
+ return *c.Conclusion
+}
+
+// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise.
+func (c *CheckSuite) GetHeadBranch() string {
+ if c == nil || c.HeadBranch == nil {
+ return ""
+ }
+ return *c.HeadBranch
+}
+
+// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise.
+func (c *CheckSuite) GetHeadSHA() string {
+ if c == nil || c.HeadSHA == nil {
+ return ""
+ }
+ return *c.HeadSHA
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (c *CheckSuite) GetID() int64 {
+ if c == nil || c.ID == nil {
+ return 0
+ }
+ return *c.ID
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (c *CheckSuite) GetNodeID() string {
+ if c == nil || c.NodeID == nil {
+ return ""
+ }
+ return *c.NodeID
+}
+
+// GetRepository returns the Repository field.
+func (c *CheckSuite) GetRepository() *Repository {
+ if c == nil {
+ return nil
+ }
+ return c.Repository
+}
+
+// GetStatus returns the Status field if it's non-nil, zero value otherwise.
+func (c *CheckSuite) GetStatus() string {
+ if c == nil || c.Status == nil {
+ return ""
+ }
+ return *c.Status
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (c *CheckSuite) GetURL() string {
+ if c == nil || c.URL == nil {
+ return ""
+ }
+ return *c.URL
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (c *CheckSuiteEvent) GetAction() string {
+ if c == nil || c.Action == nil {
+ return ""
+ }
+ return *c.Action
+}
+
+// GetCheckSuite returns the CheckSuite field.
+func (c *CheckSuiteEvent) GetCheckSuite() *CheckSuite {
+ if c == nil {
+ return nil
+ }
+ return c.CheckSuite
+}
+
+// GetInstallation returns the Installation field.
+func (c *CheckSuiteEvent) GetInstallation() *Installation {
+ if c == nil {
+ return nil
+ }
+ return c.Installation
+}
+
+// GetOrg returns the Org field.
+func (c *CheckSuiteEvent) GetOrg() *Organization {
+ if c == nil {
+ return nil
+ }
+ return c.Org
+}
+
+// GetRepo returns the Repo field.
+func (c *CheckSuiteEvent) GetRepo() *Repository {
+ if c == nil {
+ return nil
+ }
+ return c.Repo
+}
+
+// GetSender returns the Sender field.
+func (c *CheckSuiteEvent) GetSender() *User {
+ if c == nil {
+ return nil
+ }
+ return c.Sender
+}
+
+// GetPreferenceList returns the PreferenceList field.
+func (c *CheckSuitePreferenceOptions) GetPreferenceList() *PreferenceList {
+ if c == nil {
+ return nil
+ }
+ return c.PreferenceList
+}
+
+// GetPreferences returns the Preferences field.
+func (c *CheckSuitePreferenceResults) GetPreferences() *PreferenceList {
+ if c == nil {
+ return nil
+ }
+ return c.Preferences
+}
+
+// GetRepository returns the Repository field.
+func (c *CheckSuitePreferenceResults) GetRepository() *Repository {
+ if c == nil {
+ return nil
+ }
+ return c.Repository
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (c *CodeOfConduct) GetBody() string {
+ if c == nil || c.Body == nil {
+ return ""
+ }
+ return *c.Body
+}
+
+// GetKey returns the Key field if it's non-nil, zero value otherwise.
+func (c *CodeOfConduct) GetKey() string {
+ if c == nil || c.Key == nil {
+ return ""
+ }
+ return *c.Key
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (c *CodeOfConduct) GetName() string {
+ if c == nil || c.Name == nil {
+ return ""
+ }
+ return *c.Name
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (c *CodeOfConduct) GetURL() string {
+ if c == nil || c.URL == nil {
+ return ""
+ }
+ return *c.URL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (c *CodeResult) GetHTMLURL() string {
+ if c == nil || c.HTMLURL == nil {
+ return ""
+ }
+ return *c.HTMLURL
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (c *CodeResult) GetName() string {
+ if c == nil || c.Name == nil {
+ return ""
+ }
+ return *c.Name
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (c *CodeResult) GetPath() string {
+ if c == nil || c.Path == nil {
+ return ""
+ }
+ return *c.Path
+}
+
+// GetRepository returns the Repository field.
+func (c *CodeResult) GetRepository() *Repository {
+ if c == nil {
+ return nil
+ }
+ return c.Repository
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (c *CodeResult) GetSHA() string {
+ if c == nil || c.SHA == nil {
+ return ""
+ }
+ return *c.SHA
+}
+
+// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise.
+func (c *CodeSearchResult) GetIncompleteResults() bool {
+ if c == nil || c.IncompleteResults == nil {
+ return false
+ }
+ return *c.IncompleteResults
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (c *CodeSearchResult) GetTotal() int {
+ if c == nil || c.Total == nil {
+ return 0
+ }
+ return *c.Total
+}
+
+// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise.
+func (c *CombinedStatus) GetCommitURL() string {
+ if c == nil || c.CommitURL == nil {
+ return ""
+ }
+ return *c.CommitURL
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (c *CombinedStatus) GetName() string {
+ if c == nil || c.Name == nil {
+ return ""
+ }
+ return *c.Name
+}
+
+// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise.
+func (c *CombinedStatus) GetRepositoryURL() string {
+ if c == nil || c.RepositoryURL == nil {
+ return ""
+ }
+ return *c.RepositoryURL
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (c *CombinedStatus) GetSHA() string {
+ if c == nil || c.SHA == nil {
+ return ""
+ }
+ return *c.SHA
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (c *CombinedStatus) GetState() string {
+ if c == nil || c.State == nil {
+ return ""
+ }
+ return *c.State
+}
+
+// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise.
+func (c *CombinedStatus) GetTotalCount() int {
+ if c == nil || c.TotalCount == nil {
+ return 0
+ }
+ return *c.TotalCount
+}
+
+// GetTotalCommitComments returns the TotalCommitComments field if it's non-nil, zero value otherwise.
+func (c *CommentStats) GetTotalCommitComments() int {
+ if c == nil || c.TotalCommitComments == nil {
+ return 0
+ }
+ return *c.TotalCommitComments
+}
+
+// GetTotalGistComments returns the TotalGistComments field if it's non-nil, zero value otherwise.
+func (c *CommentStats) GetTotalGistComments() int {
+ if c == nil || c.TotalGistComments == nil {
+ return 0
+ }
+ return *c.TotalGistComments
+}
+
+// GetTotalIssueComments returns the TotalIssueComments field if it's non-nil, zero value otherwise.
+func (c *CommentStats) GetTotalIssueComments() int {
+ if c == nil || c.TotalIssueComments == nil {
+ return 0
+ }
+ return *c.TotalIssueComments
+}
+
+// GetTotalPullRequestComments returns the TotalPullRequestComments field if it's non-nil, zero value otherwise.
+func (c *CommentStats) GetTotalPullRequestComments() int {
+ if c == nil || c.TotalPullRequestComments == nil {
+ return 0
+ }
+ return *c.TotalPullRequestComments
+}
+
+// GetAuthor returns the Author field.
+func (c *Commit) GetAuthor() *CommitAuthor {
+ if c == nil {
+ return nil
+ }
+ return c.Author
+}
+
+// GetCommentCount returns the CommentCount field if it's non-nil, zero value otherwise.
+func (c *Commit) GetCommentCount() int {
+ if c == nil || c.CommentCount == nil {
+ return 0
+ }
+ return *c.CommentCount
+}
+
+// GetCommitter returns the Committer field.
+func (c *Commit) GetCommitter() *CommitAuthor {
+ if c == nil {
+ return nil
+ }
+ return c.Committer
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (c *Commit) GetHTMLURL() string {
+ if c == nil || c.HTMLURL == nil {
+ return ""
+ }
+ return *c.HTMLURL
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (c *Commit) GetMessage() string {
+ if c == nil || c.Message == nil {
+ return ""
+ }
+ return *c.Message
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (c *Commit) GetNodeID() string {
+ if c == nil || c.NodeID == nil {
+ return ""
+ }
+ return *c.NodeID
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (c *Commit) GetSHA() string {
+ if c == nil || c.SHA == nil {
+ return ""
+ }
+ return *c.SHA
+}
+
+// GetStats returns the Stats field.
+func (c *Commit) GetStats() *CommitStats {
+ if c == nil {
+ return nil
+ }
+ return c.Stats
+}
+
+// GetTree returns the Tree field.
+func (c *Commit) GetTree() *Tree {
+ if c == nil {
+ return nil
+ }
+ return c.Tree
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (c *Commit) GetURL() string {
+ if c == nil || c.URL == nil {
+ return ""
+ }
+ return *c.URL
+}
+
+// GetVerification returns the Verification field.
+func (c *Commit) GetVerification() *SignatureVerification {
+ if c == nil {
+ return nil
+ }
+ return c.Verification
+}
+
+// GetDate returns the Date field if it's non-nil, zero value otherwise.
+func (c *CommitAuthor) GetDate() time.Time {
+ if c == nil || c.Date == nil {
+ return time.Time{}
+ }
+ return *c.Date
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (c *CommitAuthor) GetEmail() string {
+ if c == nil || c.Email == nil {
+ return ""
+ }
+ return *c.Email
+}
+
+// GetLogin returns the Login field if it's non-nil, zero value otherwise.
+func (c *CommitAuthor) GetLogin() string {
+ if c == nil || c.Login == nil {
+ return ""
+ }
+ return *c.Login
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (c *CommitAuthor) GetName() string {
+ if c == nil || c.Name == nil {
+ return ""
+ }
+ return *c.Name
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (c *CommitCommentEvent) GetAction() string {
+ if c == nil || c.Action == nil {
+ return ""
+ }
+ return *c.Action
+}
+
+// GetComment returns the Comment field.
+func (c *CommitCommentEvent) GetComment() *RepositoryComment {
+ if c == nil {
+ return nil
+ }
+ return c.Comment
+}
+
+// GetInstallation returns the Installation field.
+func (c *CommitCommentEvent) GetInstallation() *Installation {
+ if c == nil {
+ return nil
+ }
+ return c.Installation
+}
+
+// GetRepo returns the Repo field.
+func (c *CommitCommentEvent) GetRepo() *Repository {
+ if c == nil {
+ return nil
+ }
+ return c.Repo
+}
+
+// GetSender returns the Sender field.
+func (c *CommitCommentEvent) GetSender() *User {
+ if c == nil {
+ return nil
+ }
+ return c.Sender
+}
+
+// GetAdditions returns the Additions field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetAdditions() int {
+ if c == nil || c.Additions == nil {
+ return 0
+ }
+ return *c.Additions
+}
+
+// GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetBlobURL() string {
+ if c == nil || c.BlobURL == nil {
+ return ""
+ }
+ return *c.BlobURL
+}
+
+// GetChanges returns the Changes field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetChanges() int {
+ if c == nil || c.Changes == nil {
+ return 0
+ }
+ return *c.Changes
+}
+
+// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetContentsURL() string {
+ if c == nil || c.ContentsURL == nil {
+ return ""
+ }
+ return *c.ContentsURL
+}
+
+// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetDeletions() int {
+ if c == nil || c.Deletions == nil {
+ return 0
+ }
+ return *c.Deletions
+}
+
+// GetFilename returns the Filename field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetFilename() string {
+ if c == nil || c.Filename == nil {
+ return ""
+ }
+ return *c.Filename
+}
+
+// GetPatch returns the Patch field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetPatch() string {
+ if c == nil || c.Patch == nil {
+ return ""
+ }
+ return *c.Patch
+}
+
+// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetRawURL() string {
+ if c == nil || c.RawURL == nil {
+ return ""
+ }
+ return *c.RawURL
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetSHA() string {
+ if c == nil || c.SHA == nil {
+ return ""
+ }
+ return *c.SHA
+}
+
+// GetStatus returns the Status field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetStatus() string {
+ if c == nil || c.Status == nil {
+ return ""
+ }
+ return *c.Status
+}
+
+// GetAuthor returns the Author field.
+func (c *CommitResult) GetAuthor() *User {
+ if c == nil {
+ return nil
+ }
+ return c.Author
+}
+
+// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise.
+func (c *CommitResult) GetCommentsURL() string {
+ if c == nil || c.CommentsURL == nil {
+ return ""
+ }
+ return *c.CommentsURL
+}
+
+// GetCommit returns the Commit field.
+func (c *CommitResult) GetCommit() *Commit {
+ if c == nil {
+ return nil
+ }
+ return c.Commit
+}
+
+// GetCommitter returns the Committer field.
+func (c *CommitResult) GetCommitter() *User {
+ if c == nil {
+ return nil
+ }
+ return c.Committer
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (c *CommitResult) GetHTMLURL() string {
+ if c == nil || c.HTMLURL == nil {
+ return ""
+ }
+ return *c.HTMLURL
+}
+
+// GetRepository returns the Repository field.
+func (c *CommitResult) GetRepository() *Repository {
+ if c == nil {
+ return nil
+ }
+ return c.Repository
+}
+
+// GetScore returns the Score field.
+func (c *CommitResult) GetScore() *float64 {
+ if c == nil {
+ return nil
+ }
+ return c.Score
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (c *CommitResult) GetSHA() string {
+ if c == nil || c.SHA == nil {
+ return ""
+ }
+ return *c.SHA
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (c *CommitResult) GetURL() string {
+ if c == nil || c.URL == nil {
+ return ""
+ }
+ return *c.URL
+}
+
+// GetAheadBy returns the AheadBy field if it's non-nil, zero value otherwise.
+func (c *CommitsComparison) GetAheadBy() int {
+ if c == nil || c.AheadBy == nil {
+ return 0
+ }
+ return *c.AheadBy
+}
+
+// GetBaseCommit returns the BaseCommit field.
+func (c *CommitsComparison) GetBaseCommit() *RepositoryCommit {
+ if c == nil {
+ return nil
+ }
+ return c.BaseCommit
+}
+
+// GetBehindBy returns the BehindBy field if it's non-nil, zero value otherwise.
+func (c *CommitsComparison) GetBehindBy() int {
+ if c == nil || c.BehindBy == nil {
+ return 0
+ }
+ return *c.BehindBy
+}
+
+// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise.
+func (c *CommitsComparison) GetDiffURL() string {
+ if c == nil || c.DiffURL == nil {
+ return ""
+ }
+ return *c.DiffURL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (c *CommitsComparison) GetHTMLURL() string {
+ if c == nil || c.HTMLURL == nil {
+ return ""
+ }
+ return *c.HTMLURL
+}
+
+// GetMergeBaseCommit returns the MergeBaseCommit field.
+func (c *CommitsComparison) GetMergeBaseCommit() *RepositoryCommit {
+ if c == nil {
+ return nil
+ }
+ return c.MergeBaseCommit
+}
+
+// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise.
+func (c *CommitsComparison) GetPatchURL() string {
+ if c == nil || c.PatchURL == nil {
+ return ""
+ }
+ return *c.PatchURL
+}
+
+// GetPermalinkURL returns the PermalinkURL field if it's non-nil, zero value otherwise.
+func (c *CommitsComparison) GetPermalinkURL() string {
+ if c == nil || c.PermalinkURL == nil {
+ return ""
+ }
+ return *c.PermalinkURL
+}
+
+// GetStatus returns the Status field if it's non-nil, zero value otherwise.
+func (c *CommitsComparison) GetStatus() string {
+ if c == nil || c.Status == nil {
+ return ""
+ }
+ return *c.Status
+}
+
+// GetTotalCommits returns the TotalCommits field if it's non-nil, zero value otherwise.
+func (c *CommitsComparison) GetTotalCommits() int {
+ if c == nil || c.TotalCommits == nil {
+ return 0
+ }
+ return *c.TotalCommits
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (c *CommitsComparison) GetURL() string {
+ if c == nil || c.URL == nil {
+ return ""
+ }
+ return *c.URL
+}
+
+// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise.
+func (c *CommitsSearchResult) GetIncompleteResults() bool {
+ if c == nil || c.IncompleteResults == nil {
+ return false
+ }
+ return *c.IncompleteResults
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (c *CommitsSearchResult) GetTotal() int {
+ if c == nil || c.Total == nil {
+ return 0
+ }
+ return *c.Total
+}
+
+// GetAdditions returns the Additions field if it's non-nil, zero value otherwise.
+func (c *CommitStats) GetAdditions() int {
+ if c == nil || c.Additions == nil {
+ return 0
+ }
+ return *c.Additions
+}
+
+// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise.
+func (c *CommitStats) GetDeletions() int {
+ if c == nil || c.Deletions == nil {
+ return 0
+ }
+ return *c.Deletions
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (c *CommitStats) GetTotal() int {
+ if c == nil || c.Total == nil {
+ return 0
+ }
+ return *c.Total
+}
+
+// GetCodeOfConduct returns the CodeOfConduct field.
+func (c *CommunityHealthFiles) GetCodeOfConduct() *Metric {
+ if c == nil {
+ return nil
+ }
+ return c.CodeOfConduct
+}
+
+// GetContributing returns the Contributing field.
+func (c *CommunityHealthFiles) GetContributing() *Metric {
+ if c == nil {
+ return nil
+ }
+ return c.Contributing
+}
+
+// GetIssueTemplate returns the IssueTemplate field.
+func (c *CommunityHealthFiles) GetIssueTemplate() *Metric {
+ if c == nil {
+ return nil
+ }
+ return c.IssueTemplate
+}
+
+// GetLicense returns the License field.
+func (c *CommunityHealthFiles) GetLicense() *Metric {
+ if c == nil {
+ return nil
+ }
+ return c.License
+}
+
+// GetPullRequestTemplate returns the PullRequestTemplate field.
+func (c *CommunityHealthFiles) GetPullRequestTemplate() *Metric {
+ if c == nil {
+ return nil
+ }
+ return c.PullRequestTemplate
+}
+
+// GetReadme returns the Readme field.
+func (c *CommunityHealthFiles) GetReadme() *Metric {
+ if c == nil {
+ return nil
+ }
+ return c.Readme
+}
+
+// GetFiles returns the Files field.
+func (c *CommunityHealthMetrics) GetFiles() *CommunityHealthFiles {
+ if c == nil {
+ return nil
+ }
+ return c.Files
+}
+
+// GetHealthPercentage returns the HealthPercentage field if it's non-nil, zero value otherwise.
+func (c *CommunityHealthMetrics) GetHealthPercentage() int {
+ if c == nil || c.HealthPercentage == nil {
+ return 0
+ }
+ return *c.HealthPercentage
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (c *CommunityHealthMetrics) GetUpdatedAt() time.Time {
+ if c == nil || c.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *c.UpdatedAt
+}
+
+// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetAvatarURL() string {
+ if c == nil || c.AvatarURL == nil {
+ return ""
+ }
+ return *c.AvatarURL
+}
+
+// GetContributions returns the Contributions field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetContributions() int {
+ if c == nil || c.Contributions == nil {
+ return 0
+ }
+ return *c.Contributions
+}
+
+// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetEventsURL() string {
+ if c == nil || c.EventsURL == nil {
+ return ""
+ }
+ return *c.EventsURL
+}
+
+// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetFollowersURL() string {
+ if c == nil || c.FollowersURL == nil {
+ return ""
+ }
+ return *c.FollowersURL
+}
+
+// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetFollowingURL() string {
+ if c == nil || c.FollowingURL == nil {
+ return ""
+ }
+ return *c.FollowingURL
+}
+
+// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetGistsURL() string {
+ if c == nil || c.GistsURL == nil {
+ return ""
+ }
+ return *c.GistsURL
+}
+
+// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetGravatarID() string {
+ if c == nil || c.GravatarID == nil {
+ return ""
+ }
+ return *c.GravatarID
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetHTMLURL() string {
+ if c == nil || c.HTMLURL == nil {
+ return ""
+ }
+ return *c.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetID() int64 {
+ if c == nil || c.ID == nil {
+ return 0
+ }
+ return *c.ID
+}
+
+// GetLogin returns the Login field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetLogin() string {
+ if c == nil || c.Login == nil {
+ return ""
+ }
+ return *c.Login
+}
+
+// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetOrganizationsURL() string {
+ if c == nil || c.OrganizationsURL == nil {
+ return ""
+ }
+ return *c.OrganizationsURL
+}
+
+// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetReceivedEventsURL() string {
+ if c == nil || c.ReceivedEventsURL == nil {
+ return ""
+ }
+ return *c.ReceivedEventsURL
+}
+
+// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetReposURL() string {
+ if c == nil || c.ReposURL == nil {
+ return ""
+ }
+ return *c.ReposURL
+}
+
+// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetSiteAdmin() bool {
+ if c == nil || c.SiteAdmin == nil {
+ return false
+ }
+ return *c.SiteAdmin
+}
+
+// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetStarredURL() string {
+ if c == nil || c.StarredURL == nil {
+ return ""
+ }
+ return *c.StarredURL
+}
+
+// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetSubscriptionsURL() string {
+ if c == nil || c.SubscriptionsURL == nil {
+ return ""
+ }
+ return *c.SubscriptionsURL
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetType() string {
+ if c == nil || c.Type == nil {
+ return ""
+ }
+ return *c.Type
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (c *Contributor) GetURL() string {
+ if c == nil || c.URL == nil {
+ return ""
+ }
+ return *c.URL
+}
+
+// GetAuthor returns the Author field.
+func (c *ContributorStats) GetAuthor() *Contributor {
+ if c == nil {
+ return nil
+ }
+ return c.Author
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (c *ContributorStats) GetTotal() int {
+ if c == nil || c.Total == nil {
+ return 0
+ }
+ return *c.Total
+}
+
+// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise.
+func (c *CreateCheckRunOptions) GetCompletedAt() Timestamp {
+ if c == nil || c.CompletedAt == nil {
+ return Timestamp{}
+ }
+ return *c.CompletedAt
+}
+
+// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise.
+func (c *CreateCheckRunOptions) GetConclusion() string {
+ if c == nil || c.Conclusion == nil {
+ return ""
+ }
+ return *c.Conclusion
+}
+
+// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise.
+func (c *CreateCheckRunOptions) GetDetailsURL() string {
+ if c == nil || c.DetailsURL == nil {
+ return ""
+ }
+ return *c.DetailsURL
+}
+
+// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise.
+func (c *CreateCheckRunOptions) GetExternalID() string {
+ if c == nil || c.ExternalID == nil {
+ return ""
+ }
+ return *c.ExternalID
+}
+
+// GetOutput returns the Output field.
+func (c *CreateCheckRunOptions) GetOutput() *CheckRunOutput {
+ if c == nil {
+ return nil
+ }
+ return c.Output
+}
+
+// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise.
+func (c *CreateCheckRunOptions) GetStartedAt() Timestamp {
+ if c == nil || c.StartedAt == nil {
+ return Timestamp{}
+ }
+ return *c.StartedAt
+}
+
+// GetStatus returns the Status field if it's non-nil, zero value otherwise.
+func (c *CreateCheckRunOptions) GetStatus() string {
+ if c == nil || c.Status == nil {
+ return ""
+ }
+ return *c.Status
+}
+
+// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise.
+func (c *CreateCheckSuiteOptions) GetHeadBranch() string {
+ if c == nil || c.HeadBranch == nil {
+ return ""
+ }
+ return *c.HeadBranch
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (c *CreateEvent) GetDescription() string {
+ if c == nil || c.Description == nil {
+ return ""
+ }
+ return *c.Description
+}
+
+// GetInstallation returns the Installation field.
+func (c *CreateEvent) GetInstallation() *Installation {
+ if c == nil {
+ return nil
+ }
+ return c.Installation
+}
+
+// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise.
+func (c *CreateEvent) GetMasterBranch() string {
+ if c == nil || c.MasterBranch == nil {
+ return ""
+ }
+ return *c.MasterBranch
+}
+
+// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise.
+func (c *CreateEvent) GetPusherType() string {
+ if c == nil || c.PusherType == nil {
+ return ""
+ }
+ return *c.PusherType
+}
+
+// GetRef returns the Ref field if it's non-nil, zero value otherwise.
+func (c *CreateEvent) GetRef() string {
+ if c == nil || c.Ref == nil {
+ return ""
+ }
+ return *c.Ref
+}
+
+// GetRefType returns the RefType field if it's non-nil, zero value otherwise.
+func (c *CreateEvent) GetRefType() string {
+ if c == nil || c.RefType == nil {
+ return ""
+ }
+ return *c.RefType
+}
+
+// GetRepo returns the Repo field.
+func (c *CreateEvent) GetRepo() *Repository {
+ if c == nil {
+ return nil
+ }
+ return c.Repo
+}
+
+// GetSender returns the Sender field.
+func (c *CreateEvent) GetSender() *User {
+ if c == nil {
+ return nil
+ }
+ return c.Sender
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (c *CreateOrgInvitationOptions) GetEmail() string {
+ if c == nil || c.Email == nil {
+ return ""
+ }
+ return *c.Email
+}
+
+// GetInviteeID returns the InviteeID field if it's non-nil, zero value otherwise.
+func (c *CreateOrgInvitationOptions) GetInviteeID() int64 {
+ if c == nil || c.InviteeID == nil {
+ return 0
+ }
+ return *c.InviteeID
+}
+
+// GetRole returns the Role field if it's non-nil, zero value otherwise.
+func (c *CreateOrgInvitationOptions) GetRole() string {
+ if c == nil || c.Role == nil {
+ return ""
+ }
+ return *c.Role
+}
+
+// GetInstallation returns the Installation field.
+func (d *DeleteEvent) GetInstallation() *Installation {
+ if d == nil {
+ return nil
+ }
+ return d.Installation
+}
+
+// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise.
+func (d *DeleteEvent) GetPusherType() string {
+ if d == nil || d.PusherType == nil {
+ return ""
+ }
+ return *d.PusherType
+}
+
+// GetRef returns the Ref field if it's non-nil, zero value otherwise.
+func (d *DeleteEvent) GetRef() string {
+ if d == nil || d.Ref == nil {
+ return ""
+ }
+ return *d.Ref
+}
+
+// GetRefType returns the RefType field if it's non-nil, zero value otherwise.
+func (d *DeleteEvent) GetRefType() string {
+ if d == nil || d.RefType == nil {
+ return ""
+ }
+ return *d.RefType
+}
+
+// GetRepo returns the Repo field.
+func (d *DeleteEvent) GetRepo() *Repository {
+ if d == nil {
+ return nil
+ }
+ return d.Repo
+}
+
+// GetSender returns the Sender field.
+func (d *DeleteEvent) GetSender() *User {
+ if d == nil {
+ return nil
+ }
+ return d.Sender
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetCreatedAt() Timestamp {
+ if d == nil || d.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *d.CreatedAt
+}
+
+// GetCreator returns the Creator field.
+func (d *Deployment) GetCreator() *User {
+ if d == nil {
+ return nil
+ }
+ return d.Creator
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetDescription() string {
+ if d == nil || d.Description == nil {
+ return ""
+ }
+ return *d.Description
+}
+
+// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetEnvironment() string {
+ if d == nil || d.Environment == nil {
+ return ""
+ }
+ return *d.Environment
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetID() int64 {
+ if d == nil || d.ID == nil {
+ return 0
+ }
+ return *d.ID
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetNodeID() string {
+ if d == nil || d.NodeID == nil {
+ return ""
+ }
+ return *d.NodeID
+}
+
+// GetRef returns the Ref field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetRef() string {
+ if d == nil || d.Ref == nil {
+ return ""
+ }
+ return *d.Ref
+}
+
+// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetRepositoryURL() string {
+ if d == nil || d.RepositoryURL == nil {
+ return ""
+ }
+ return *d.RepositoryURL
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetSHA() string {
+ if d == nil || d.SHA == nil {
+ return ""
+ }
+ return *d.SHA
+}
+
+// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetStatusesURL() string {
+ if d == nil || d.StatusesURL == nil {
+ return ""
+ }
+ return *d.StatusesURL
+}
+
+// GetTask returns the Task field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetTask() string {
+ if d == nil || d.Task == nil {
+ return ""
+ }
+ return *d.Task
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetUpdatedAt() Timestamp {
+ if d == nil || d.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *d.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (d *Deployment) GetURL() string {
+ if d == nil || d.URL == nil {
+ return ""
+ }
+ return *d.URL
+}
+
+// GetDeployment returns the Deployment field.
+func (d *DeploymentEvent) GetDeployment() *Deployment {
+ if d == nil {
+ return nil
+ }
+ return d.Deployment
+}
+
+// GetInstallation returns the Installation field.
+func (d *DeploymentEvent) GetInstallation() *Installation {
+ if d == nil {
+ return nil
+ }
+ return d.Installation
+}
+
+// GetRepo returns the Repo field.
+func (d *DeploymentEvent) GetRepo() *Repository {
+ if d == nil {
+ return nil
+ }
+ return d.Repo
+}
+
+// GetSender returns the Sender field.
+func (d *DeploymentEvent) GetSender() *User {
+ if d == nil {
+ return nil
+ }
+ return d.Sender
+}
+
+// GetAutoMerge returns the AutoMerge field if it's non-nil, zero value otherwise.
+func (d *DeploymentRequest) GetAutoMerge() bool {
+ if d == nil || d.AutoMerge == nil {
+ return false
+ }
+ return *d.AutoMerge
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (d *DeploymentRequest) GetDescription() string {
+ if d == nil || d.Description == nil {
+ return ""
+ }
+ return *d.Description
+}
+
+// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise.
+func (d *DeploymentRequest) GetEnvironment() string {
+ if d == nil || d.Environment == nil {
+ return ""
+ }
+ return *d.Environment
+}
+
+// GetPayload returns the Payload field if it's non-nil, zero value otherwise.
+func (d *DeploymentRequest) GetPayload() string {
+ if d == nil || d.Payload == nil {
+ return ""
+ }
+ return *d.Payload
+}
+
+// GetProductionEnvironment returns the ProductionEnvironment field if it's non-nil, zero value otherwise.
+func (d *DeploymentRequest) GetProductionEnvironment() bool {
+ if d == nil || d.ProductionEnvironment == nil {
+ return false
+ }
+ return *d.ProductionEnvironment
+}
+
+// GetRef returns the Ref field if it's non-nil, zero value otherwise.
+func (d *DeploymentRequest) GetRef() string {
+ if d == nil || d.Ref == nil {
+ return ""
+ }
+ return *d.Ref
+}
+
+// GetRequiredContexts returns the RequiredContexts field if it's non-nil, zero value otherwise.
+func (d *DeploymentRequest) GetRequiredContexts() []string {
+ if d == nil || d.RequiredContexts == nil {
+ return nil
+ }
+ return *d.RequiredContexts
+}
+
+// GetTask returns the Task field if it's non-nil, zero value otherwise.
+func (d *DeploymentRequest) GetTask() string {
+ if d == nil || d.Task == nil {
+ return ""
+ }
+ return *d.Task
+}
+
+// GetTransientEnvironment returns the TransientEnvironment field if it's non-nil, zero value otherwise.
+func (d *DeploymentRequest) GetTransientEnvironment() bool {
+ if d == nil || d.TransientEnvironment == nil {
+ return false
+ }
+ return *d.TransientEnvironment
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatus) GetCreatedAt() Timestamp {
+ if d == nil || d.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *d.CreatedAt
+}
+
+// GetCreator returns the Creator field.
+func (d *DeploymentStatus) GetCreator() *User {
+ if d == nil {
+ return nil
+ }
+ return d.Creator
+}
+
+// GetDeploymentURL returns the DeploymentURL field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatus) GetDeploymentURL() string {
+ if d == nil || d.DeploymentURL == nil {
+ return ""
+ }
+ return *d.DeploymentURL
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatus) GetDescription() string {
+ if d == nil || d.Description == nil {
+ return ""
+ }
+ return *d.Description
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatus) GetID() int64 {
+ if d == nil || d.ID == nil {
+ return 0
+ }
+ return *d.ID
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatus) GetNodeID() string {
+ if d == nil || d.NodeID == nil {
+ return ""
+ }
+ return *d.NodeID
+}
+
+// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatus) GetRepositoryURL() string {
+ if d == nil || d.RepositoryURL == nil {
+ return ""
+ }
+ return *d.RepositoryURL
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatus) GetState() string {
+ if d == nil || d.State == nil {
+ return ""
+ }
+ return *d.State
+}
+
+// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatus) GetTargetURL() string {
+ if d == nil || d.TargetURL == nil {
+ return ""
+ }
+ return *d.TargetURL
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatus) GetUpdatedAt() Timestamp {
+ if d == nil || d.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *d.UpdatedAt
+}
+
+// GetDeployment returns the Deployment field.
+func (d *DeploymentStatusEvent) GetDeployment() *Deployment {
+ if d == nil {
+ return nil
+ }
+ return d.Deployment
+}
+
+// GetDeploymentStatus returns the DeploymentStatus field.
+func (d *DeploymentStatusEvent) GetDeploymentStatus() *DeploymentStatus {
+ if d == nil {
+ return nil
+ }
+ return d.DeploymentStatus
+}
+
+// GetInstallation returns the Installation field.
+func (d *DeploymentStatusEvent) GetInstallation() *Installation {
+ if d == nil {
+ return nil
+ }
+ return d.Installation
+}
+
+// GetRepo returns the Repo field.
+func (d *DeploymentStatusEvent) GetRepo() *Repository {
+ if d == nil {
+ return nil
+ }
+ return d.Repo
+}
+
+// GetSender returns the Sender field.
+func (d *DeploymentStatusEvent) GetSender() *User {
+ if d == nil {
+ return nil
+ }
+ return d.Sender
+}
+
+// GetAutoInactive returns the AutoInactive field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatusRequest) GetAutoInactive() bool {
+ if d == nil || d.AutoInactive == nil {
+ return false
+ }
+ return *d.AutoInactive
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatusRequest) GetDescription() string {
+ if d == nil || d.Description == nil {
+ return ""
+ }
+ return *d.Description
+}
+
+// GetEnvironmentURL returns the EnvironmentURL field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatusRequest) GetEnvironmentURL() string {
+ if d == nil || d.EnvironmentURL == nil {
+ return ""
+ }
+ return *d.EnvironmentURL
+}
+
+// GetLogURL returns the LogURL field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatusRequest) GetLogURL() string {
+ if d == nil || d.LogURL == nil {
+ return ""
+ }
+ return *d.LogURL
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (d *DeploymentStatusRequest) GetState() string {
+ if d == nil || d.State == nil {
+ return ""
+ }
+ return *d.State
+}
+
+// GetAuthor returns the Author field.
+func (d *DiscussionComment) GetAuthor() *User {
+ if d == nil {
+ return nil
+ }
+ return d.Author
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetBody() string {
+ if d == nil || d.Body == nil {
+ return ""
+ }
+ return *d.Body
+}
+
+// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetBodyHTML() string {
+ if d == nil || d.BodyHTML == nil {
+ return ""
+ }
+ return *d.BodyHTML
+}
+
+// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetBodyVersion() string {
+ if d == nil || d.BodyVersion == nil {
+ return ""
+ }
+ return *d.BodyVersion
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetCreatedAt() Timestamp {
+ if d == nil || d.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *d.CreatedAt
+}
+
+// GetDiscussionURL returns the DiscussionURL field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetDiscussionURL() string {
+ if d == nil || d.DiscussionURL == nil {
+ return ""
+ }
+ return *d.DiscussionURL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetHTMLURL() string {
+ if d == nil || d.HTMLURL == nil {
+ return ""
+ }
+ return *d.HTMLURL
+}
+
+// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetLastEditedAt() Timestamp {
+ if d == nil || d.LastEditedAt == nil {
+ return Timestamp{}
+ }
+ return *d.LastEditedAt
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetNodeID() string {
+ if d == nil || d.NodeID == nil {
+ return ""
+ }
+ return *d.NodeID
+}
+
+// GetNumber returns the Number field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetNumber() int {
+ if d == nil || d.Number == nil {
+ return 0
+ }
+ return *d.Number
+}
+
+// GetReactions returns the Reactions field.
+func (d *DiscussionComment) GetReactions() *Reactions {
+ if d == nil {
+ return nil
+ }
+ return d.Reactions
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetUpdatedAt() Timestamp {
+ if d == nil || d.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *d.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (d *DiscussionComment) GetURL() string {
+ if d == nil || d.URL == nil {
+ return ""
+ }
+ return *d.URL
+}
+
+// GetTeams returns the Teams field if it's non-nil, zero value otherwise.
+func (d *DismissalRestrictionsRequest) GetTeams() []string {
+ if d == nil || d.Teams == nil {
+ return nil
+ }
+ return *d.Teams
+}
+
+// GetUsers returns the Users field if it's non-nil, zero value otherwise.
+func (d *DismissalRestrictionsRequest) GetUsers() []string {
+ if d == nil || d.Users == nil {
+ return nil
+ }
+ return *d.Users
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (d *DraftReviewComment) GetBody() string {
+ if d == nil || d.Body == nil {
+ return ""
+ }
+ return *d.Body
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (d *DraftReviewComment) GetPath() string {
+ if d == nil || d.Path == nil {
+ return ""
+ }
+ return *d.Path
+}
+
+// GetPosition returns the Position field if it's non-nil, zero value otherwise.
+func (d *DraftReviewComment) GetPosition() int {
+ if d == nil || d.Position == nil {
+ return 0
+ }
+ return *d.Position
+}
+
+// GetActor returns the Actor field.
+func (e *Event) GetActor() *User {
+ if e == nil {
+ return nil
+ }
+ return e.Actor
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (e *Event) GetCreatedAt() time.Time {
+ if e == nil || e.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *e.CreatedAt
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (e *Event) GetID() string {
+ if e == nil || e.ID == nil {
+ return ""
+ }
+ return *e.ID
+}
+
+// GetOrg returns the Org field.
+func (e *Event) GetOrg() *Organization {
+ if e == nil {
+ return nil
+ }
+ return e.Org
+}
+
+// GetPublic returns the Public field if it's non-nil, zero value otherwise.
+func (e *Event) GetPublic() bool {
+ if e == nil || e.Public == nil {
+ return false
+ }
+ return *e.Public
+}
+
+// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise.
+func (e *Event) GetRawPayload() json.RawMessage {
+ if e == nil || e.RawPayload == nil {
+ return json.RawMessage{}
+ }
+ return *e.RawPayload
+}
+
+// GetRepo returns the Repo field.
+func (e *Event) GetRepo() *Repository {
+ if e == nil {
+ return nil
+ }
+ return e.Repo
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (e *Event) GetType() string {
+ if e == nil || e.Type == nil {
+ return ""
+ }
+ return *e.Type
+}
+
+// GetHRef returns the HRef field if it's non-nil, zero value otherwise.
+func (f *FeedLink) GetHRef() string {
+ if f == nil || f.HRef == nil {
+ return ""
+ }
+ return *f.HRef
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (f *FeedLink) GetType() string {
+ if f == nil || f.Type == nil {
+ return ""
+ }
+ return *f.Type
+}
+
+// GetCurrentUserActorURL returns the CurrentUserActorURL field if it's non-nil, zero value otherwise.
+func (f *Feeds) GetCurrentUserActorURL() string {
+ if f == nil || f.CurrentUserActorURL == nil {
+ return ""
+ }
+ return *f.CurrentUserActorURL
+}
+
+// GetCurrentUserOrganizationURL returns the CurrentUserOrganizationURL field if it's non-nil, zero value otherwise.
+func (f *Feeds) GetCurrentUserOrganizationURL() string {
+ if f == nil || f.CurrentUserOrganizationURL == nil {
+ return ""
+ }
+ return *f.CurrentUserOrganizationURL
+}
+
+// GetCurrentUserPublicURL returns the CurrentUserPublicURL field if it's non-nil, zero value otherwise.
+func (f *Feeds) GetCurrentUserPublicURL() string {
+ if f == nil || f.CurrentUserPublicURL == nil {
+ return ""
+ }
+ return *f.CurrentUserPublicURL
+}
+
+// GetCurrentUserURL returns the CurrentUserURL field if it's non-nil, zero value otherwise.
+func (f *Feeds) GetCurrentUserURL() string {
+ if f == nil || f.CurrentUserURL == nil {
+ return ""
+ }
+ return *f.CurrentUserURL
+}
+
+// GetTimelineURL returns the TimelineURL field if it's non-nil, zero value otherwise.
+func (f *Feeds) GetTimelineURL() string {
+ if f == nil || f.TimelineURL == nil {
+ return ""
+ }
+ return *f.TimelineURL
+}
+
+// GetUserURL returns the UserURL field if it's non-nil, zero value otherwise.
+func (f *Feeds) GetUserURL() string {
+ if f == nil || f.UserURL == nil {
+ return ""
+ }
+ return *f.UserURL
+}
+
+// GetForkee returns the Forkee field.
+func (f *ForkEvent) GetForkee() *Repository {
+ if f == nil {
+ return nil
+ }
+ return f.Forkee
+}
+
+// GetInstallation returns the Installation field.
+func (f *ForkEvent) GetInstallation() *Installation {
+ if f == nil {
+ return nil
+ }
+ return f.Installation
+}
+
+// GetRepo returns the Repo field.
+func (f *ForkEvent) GetRepo() *Repository {
+ if f == nil {
+ return nil
+ }
+ return f.Repo
+}
+
+// GetSender returns the Sender field.
+func (f *ForkEvent) GetSender() *User {
+ if f == nil {
+ return nil
+ }
+ return f.Sender
+}
+
+// GetComments returns the Comments field if it's non-nil, zero value otherwise.
+func (g *Gist) GetComments() int {
+ if g == nil || g.Comments == nil {
+ return 0
+ }
+ return *g.Comments
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (g *Gist) GetCreatedAt() time.Time {
+ if g == nil || g.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *g.CreatedAt
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (g *Gist) GetDescription() string {
+ if g == nil || g.Description == nil {
+ return ""
+ }
+ return *g.Description
+}
+
+// GetGitPullURL returns the GitPullURL field if it's non-nil, zero value otherwise.
+func (g *Gist) GetGitPullURL() string {
+ if g == nil || g.GitPullURL == nil {
+ return ""
+ }
+ return *g.GitPullURL
+}
+
+// GetGitPushURL returns the GitPushURL field if it's non-nil, zero value otherwise.
+func (g *Gist) GetGitPushURL() string {
+ if g == nil || g.GitPushURL == nil {
+ return ""
+ }
+ return *g.GitPushURL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (g *Gist) GetHTMLURL() string {
+ if g == nil || g.HTMLURL == nil {
+ return ""
+ }
+ return *g.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (g *Gist) GetID() string {
+ if g == nil || g.ID == nil {
+ return ""
+ }
+ return *g.ID
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (g *Gist) GetNodeID() string {
+ if g == nil || g.NodeID == nil {
+ return ""
+ }
+ return *g.NodeID
+}
+
+// GetOwner returns the Owner field.
+func (g *Gist) GetOwner() *User {
+ if g == nil {
+ return nil
+ }
+ return g.Owner
+}
+
+// GetPublic returns the Public field if it's non-nil, zero value otherwise.
+func (g *Gist) GetPublic() bool {
+ if g == nil || g.Public == nil {
+ return false
+ }
+ return *g.Public
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (g *Gist) GetUpdatedAt() time.Time {
+ if g == nil || g.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *g.UpdatedAt
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (g *GistComment) GetBody() string {
+ if g == nil || g.Body == nil {
+ return ""
+ }
+ return *g.Body
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (g *GistComment) GetCreatedAt() time.Time {
+ if g == nil || g.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *g.CreatedAt
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (g *GistComment) GetID() int64 {
+ if g == nil || g.ID == nil {
+ return 0
+ }
+ return *g.ID
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (g *GistComment) GetURL() string {
+ if g == nil || g.URL == nil {
+ return ""
+ }
+ return *g.URL
+}
+
+// GetUser returns the User field.
+func (g *GistComment) GetUser() *User {
+ if g == nil {
+ return nil
+ }
+ return g.User
+}
+
+// GetChangeStatus returns the ChangeStatus field.
+func (g *GistCommit) GetChangeStatus() *CommitStats {
+ if g == nil {
+ return nil
+ }
+ return g.ChangeStatus
+}
+
+// GetCommittedAt returns the CommittedAt field if it's non-nil, zero value otherwise.
+func (g *GistCommit) GetCommittedAt() Timestamp {
+ if g == nil || g.CommittedAt == nil {
+ return Timestamp{}
+ }
+ return *g.CommittedAt
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (g *GistCommit) GetNodeID() string {
+ if g == nil || g.NodeID == nil {
+ return ""
+ }
+ return *g.NodeID
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (g *GistCommit) GetURL() string {
+ if g == nil || g.URL == nil {
+ return ""
+ }
+ return *g.URL
+}
+
+// GetUser returns the User field.
+func (g *GistCommit) GetUser() *User {
+ if g == nil {
+ return nil
+ }
+ return g.User
+}
+
+// GetVersion returns the Version field if it's non-nil, zero value otherwise.
+func (g *GistCommit) GetVersion() string {
+ if g == nil || g.Version == nil {
+ return ""
+ }
+ return *g.Version
+}
+
+// GetContent returns the Content field if it's non-nil, zero value otherwise.
+func (g *GistFile) GetContent() string {
+ if g == nil || g.Content == nil {
+ return ""
+ }
+ return *g.Content
+}
+
+// GetFilename returns the Filename field if it's non-nil, zero value otherwise.
+func (g *GistFile) GetFilename() string {
+ if g == nil || g.Filename == nil {
+ return ""
+ }
+ return *g.Filename
+}
+
+// GetLanguage returns the Language field if it's non-nil, zero value otherwise.
+func (g *GistFile) GetLanguage() string {
+ if g == nil || g.Language == nil {
+ return ""
+ }
+ return *g.Language
+}
+
+// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise.
+func (g *GistFile) GetRawURL() string {
+ if g == nil || g.RawURL == nil {
+ return ""
+ }
+ return *g.RawURL
+}
+
+// GetSize returns the Size field if it's non-nil, zero value otherwise.
+func (g *GistFile) GetSize() int {
+ if g == nil || g.Size == nil {
+ return 0
+ }
+ return *g.Size
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (g *GistFile) GetType() string {
+ if g == nil || g.Type == nil {
+ return ""
+ }
+ return *g.Type
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (g *GistFork) GetCreatedAt() Timestamp {
+ if g == nil || g.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *g.CreatedAt
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (g *GistFork) GetID() string {
+ if g == nil || g.ID == nil {
+ return ""
+ }
+ return *g.ID
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (g *GistFork) GetNodeID() string {
+ if g == nil || g.NodeID == nil {
+ return ""
+ }
+ return *g.NodeID
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (g *GistFork) GetUpdatedAt() Timestamp {
+ if g == nil || g.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *g.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (g *GistFork) GetURL() string {
+ if g == nil || g.URL == nil {
+ return ""
+ }
+ return *g.URL
+}
+
+// GetUser returns the User field.
+func (g *GistFork) GetUser() *User {
+ if g == nil {
+ return nil
+ }
+ return g.User
+}
+
+// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise.
+func (g *GistStats) GetPrivateGists() int {
+ if g == nil || g.PrivateGists == nil {
+ return 0
+ }
+ return *g.PrivateGists
+}
+
+// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise.
+func (g *GistStats) GetPublicGists() int {
+ if g == nil || g.PublicGists == nil {
+ return 0
+ }
+ return *g.PublicGists
+}
+
+// GetTotalGists returns the TotalGists field if it's non-nil, zero value otherwise.
+func (g *GistStats) GetTotalGists() int {
+ if g == nil || g.TotalGists == nil {
+ return 0
+ }
+ return *g.TotalGists
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (g *Gitignore) GetName() string {
+ if g == nil || g.Name == nil {
+ return ""
+ }
+ return *g.Name
+}
+
+// GetSource returns the Source field if it's non-nil, zero value otherwise.
+func (g *Gitignore) GetSource() string {
+ if g == nil || g.Source == nil {
+ return ""
+ }
+ return *g.Source
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (g *GitObject) GetSHA() string {
+ if g == nil || g.SHA == nil {
+ return ""
+ }
+ return *g.SHA
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (g *GitObject) GetType() string {
+ if g == nil || g.Type == nil {
+ return ""
+ }
+ return *g.Type
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (g *GitObject) GetURL() string {
+ if g == nil || g.URL == nil {
+ return ""
+ }
+ return *g.URL
+}
+
+// GetInstallation returns the Installation field.
+func (g *GollumEvent) GetInstallation() *Installation {
+ if g == nil {
+ return nil
+ }
+ return g.Installation
+}
+
+// GetRepo returns the Repo field.
+func (g *GollumEvent) GetRepo() *Repository {
+ if g == nil {
+ return nil
+ }
+ return g.Repo
+}
+
+// GetSender returns the Sender field.
+func (g *GollumEvent) GetSender() *User {
+ if g == nil {
+ return nil
+ }
+ return g.Sender
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (g *GPGEmail) GetEmail() string {
+ if g == nil || g.Email == nil {
+ return ""
+ }
+ return *g.Email
+}
+
+// GetVerified returns the Verified field if it's non-nil, zero value otherwise.
+func (g *GPGEmail) GetVerified() bool {
+ if g == nil || g.Verified == nil {
+ return false
+ }
+ return *g.Verified
+}
+
+// GetCanCertify returns the CanCertify field if it's non-nil, zero value otherwise.
+func (g *GPGKey) GetCanCertify() bool {
+ if g == nil || g.CanCertify == nil {
+ return false
+ }
+ return *g.CanCertify
+}
+
+// GetCanEncryptComms returns the CanEncryptComms field if it's non-nil, zero value otherwise.
+func (g *GPGKey) GetCanEncryptComms() bool {
+ if g == nil || g.CanEncryptComms == nil {
+ return false
+ }
+ return *g.CanEncryptComms
+}
+
+// GetCanEncryptStorage returns the CanEncryptStorage field if it's non-nil, zero value otherwise.
+func (g *GPGKey) GetCanEncryptStorage() bool {
+ if g == nil || g.CanEncryptStorage == nil {
+ return false
+ }
+ return *g.CanEncryptStorage
+}
+
+// GetCanSign returns the CanSign field if it's non-nil, zero value otherwise.
+func (g *GPGKey) GetCanSign() bool {
+ if g == nil || g.CanSign == nil {
+ return false
+ }
+ return *g.CanSign
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (g *GPGKey) GetCreatedAt() time.Time {
+ if g == nil || g.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *g.CreatedAt
+}
+
+// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise.
+func (g *GPGKey) GetExpiresAt() time.Time {
+ if g == nil || g.ExpiresAt == nil {
+ return time.Time{}
+ }
+ return *g.ExpiresAt
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (g *GPGKey) GetID() int64 {
+ if g == nil || g.ID == nil {
+ return 0
+ }
+ return *g.ID
+}
+
+// GetKeyID returns the KeyID field if it's non-nil, zero value otherwise.
+func (g *GPGKey) GetKeyID() string {
+ if g == nil || g.KeyID == nil {
+ return ""
+ }
+ return *g.KeyID
+}
+
+// GetPrimaryKeyID returns the PrimaryKeyID field if it's non-nil, zero value otherwise.
+func (g *GPGKey) GetPrimaryKeyID() int64 {
+ if g == nil || g.PrimaryKeyID == nil {
+ return 0
+ }
+ return *g.PrimaryKeyID
+}
+
+// GetPublicKey returns the PublicKey field if it's non-nil, zero value otherwise.
+func (g *GPGKey) GetPublicKey() string {
+ if g == nil || g.PublicKey == nil {
+ return ""
+ }
+ return *g.PublicKey
+}
+
+// GetApp returns the App field.
+func (g *Grant) GetApp() *AuthorizationApp {
+ if g == nil {
+ return nil
+ }
+ return g.App
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (g *Grant) GetCreatedAt() Timestamp {
+ if g == nil || g.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *g.CreatedAt
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (g *Grant) GetID() int64 {
+ if g == nil || g.ID == nil {
+ return 0
+ }
+ return *g.ID
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (g *Grant) GetUpdatedAt() Timestamp {
+ if g == nil || g.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *g.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (g *Grant) GetURL() string {
+ if g == nil || g.URL == nil {
+ return ""
+ }
+ return *g.URL
+}
+
+// GetActive returns the Active field if it's non-nil, zero value otherwise.
+func (h *Hook) GetActive() bool {
+ if h == nil || h.Active == nil {
+ return false
+ }
+ return *h.Active
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (h *Hook) GetCreatedAt() time.Time {
+ if h == nil || h.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *h.CreatedAt
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (h *Hook) GetID() int64 {
+ if h == nil || h.ID == nil {
+ return 0
+ }
+ return *h.ID
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (h *Hook) GetName() string {
+ if h == nil || h.Name == nil {
+ return ""
+ }
+ return *h.Name
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (h *Hook) GetUpdatedAt() time.Time {
+ if h == nil || h.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *h.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (h *Hook) GetURL() string {
+ if h == nil || h.URL == nil {
+ return ""
+ }
+ return *h.URL
+}
+
+// GetActiveHooks returns the ActiveHooks field if it's non-nil, zero value otherwise.
+func (h *HookStats) GetActiveHooks() int {
+ if h == nil || h.ActiveHooks == nil {
+ return 0
+ }
+ return *h.ActiveHooks
+}
+
+// GetInactiveHooks returns the InactiveHooks field if it's non-nil, zero value otherwise.
+func (h *HookStats) GetInactiveHooks() int {
+ if h == nil || h.InactiveHooks == nil {
+ return 0
+ }
+ return *h.InactiveHooks
+}
+
+// GetTotalHooks returns the TotalHooks field if it's non-nil, zero value otherwise.
+func (h *HookStats) GetTotalHooks() int {
+ if h == nil || h.TotalHooks == nil {
+ return 0
+ }
+ return *h.TotalHooks
+}
+
+// GetAuthorsCount returns the AuthorsCount field if it's non-nil, zero value otherwise.
+func (i *Import) GetAuthorsCount() int {
+ if i == nil || i.AuthorsCount == nil {
+ return 0
+ }
+ return *i.AuthorsCount
+}
+
+// GetAuthorsURL returns the AuthorsURL field if it's non-nil, zero value otherwise.
+func (i *Import) GetAuthorsURL() string {
+ if i == nil || i.AuthorsURL == nil {
+ return ""
+ }
+ return *i.AuthorsURL
+}
+
+// GetCommitCount returns the CommitCount field if it's non-nil, zero value otherwise.
+func (i *Import) GetCommitCount() int {
+ if i == nil || i.CommitCount == nil {
+ return 0
+ }
+ return *i.CommitCount
+}
+
+// GetFailedStep returns the FailedStep field if it's non-nil, zero value otherwise.
+func (i *Import) GetFailedStep() string {
+ if i == nil || i.FailedStep == nil {
+ return ""
+ }
+ return *i.FailedStep
+}
+
+// GetHasLargeFiles returns the HasLargeFiles field if it's non-nil, zero value otherwise.
+func (i *Import) GetHasLargeFiles() bool {
+ if i == nil || i.HasLargeFiles == nil {
+ return false
+ }
+ return *i.HasLargeFiles
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (i *Import) GetHTMLURL() string {
+ if i == nil || i.HTMLURL == nil {
+ return ""
+ }
+ return *i.HTMLURL
+}
+
+// GetHumanName returns the HumanName field if it's non-nil, zero value otherwise.
+func (i *Import) GetHumanName() string {
+ if i == nil || i.HumanName == nil {
+ return ""
+ }
+ return *i.HumanName
+}
+
+// GetLargeFilesCount returns the LargeFilesCount field if it's non-nil, zero value otherwise.
+func (i *Import) GetLargeFilesCount() int {
+ if i == nil || i.LargeFilesCount == nil {
+ return 0
+ }
+ return *i.LargeFilesCount
+}
+
+// GetLargeFilesSize returns the LargeFilesSize field if it's non-nil, zero value otherwise.
+func (i *Import) GetLargeFilesSize() int {
+ if i == nil || i.LargeFilesSize == nil {
+ return 0
+ }
+ return *i.LargeFilesSize
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (i *Import) GetMessage() string {
+ if i == nil || i.Message == nil {
+ return ""
+ }
+ return *i.Message
+}
+
+// GetPercent returns the Percent field if it's non-nil, zero value otherwise.
+func (i *Import) GetPercent() int {
+ if i == nil || i.Percent == nil {
+ return 0
+ }
+ return *i.Percent
+}
+
+// GetPushPercent returns the PushPercent field if it's non-nil, zero value otherwise.
+func (i *Import) GetPushPercent() int {
+ if i == nil || i.PushPercent == nil {
+ return 0
+ }
+ return *i.PushPercent
+}
+
+// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise.
+func (i *Import) GetRepositoryURL() string {
+ if i == nil || i.RepositoryURL == nil {
+ return ""
+ }
+ return *i.RepositoryURL
+}
+
+// GetStatus returns the Status field if it's non-nil, zero value otherwise.
+func (i *Import) GetStatus() string {
+ if i == nil || i.Status == nil {
+ return ""
+ }
+ return *i.Status
+}
+
+// GetStatusText returns the StatusText field if it's non-nil, zero value otherwise.
+func (i *Import) GetStatusText() string {
+ if i == nil || i.StatusText == nil {
+ return ""
+ }
+ return *i.StatusText
+}
+
+// GetTFVCProject returns the TFVCProject field if it's non-nil, zero value otherwise.
+func (i *Import) GetTFVCProject() string {
+ if i == nil || i.TFVCProject == nil {
+ return ""
+ }
+ return *i.TFVCProject
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (i *Import) GetURL() string {
+ if i == nil || i.URL == nil {
+ return ""
+ }
+ return *i.URL
+}
+
+// GetUseLFS returns the UseLFS field if it's non-nil, zero value otherwise.
+func (i *Import) GetUseLFS() string {
+ if i == nil || i.UseLFS == nil {
+ return ""
+ }
+ return *i.UseLFS
+}
+
+// GetVCS returns the VCS field if it's non-nil, zero value otherwise.
+func (i *Import) GetVCS() string {
+ if i == nil || i.VCS == nil {
+ return ""
+ }
+ return *i.VCS
+}
+
+// GetVCSPassword returns the VCSPassword field if it's non-nil, zero value otherwise.
+func (i *Import) GetVCSPassword() string {
+ if i == nil || i.VCSPassword == nil {
+ return ""
+ }
+ return *i.VCSPassword
+}
+
+// GetVCSURL returns the VCSURL field if it's non-nil, zero value otherwise.
+func (i *Import) GetVCSURL() string {
+ if i == nil || i.VCSURL == nil {
+ return ""
+ }
+ return *i.VCSURL
+}
+
+// GetVCSUsername returns the VCSUsername field if it's non-nil, zero value otherwise.
+func (i *Import) GetVCSUsername() string {
+ if i == nil || i.VCSUsername == nil {
+ return ""
+ }
+ return *i.VCSUsername
+}
+
+// GetAccessTokensURL returns the AccessTokensURL field if it's non-nil, zero value otherwise.
+func (i *Installation) GetAccessTokensURL() string {
+ if i == nil || i.AccessTokensURL == nil {
+ return ""
+ }
+ return *i.AccessTokensURL
+}
+
+// GetAccount returns the Account field.
+func (i *Installation) GetAccount() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Account
+}
+
+// GetAppID returns the AppID field if it's non-nil, zero value otherwise.
+func (i *Installation) GetAppID() int64 {
+ if i == nil || i.AppID == nil {
+ return 0
+ }
+ return *i.AppID
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (i *Installation) GetCreatedAt() Timestamp {
+ if i == nil || i.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *i.CreatedAt
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (i *Installation) GetHTMLURL() string {
+ if i == nil || i.HTMLURL == nil {
+ return ""
+ }
+ return *i.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (i *Installation) GetID() int64 {
+ if i == nil || i.ID == nil {
+ return 0
+ }
+ return *i.ID
+}
+
+// GetPermissions returns the Permissions field.
+func (i *Installation) GetPermissions() *InstallationPermissions {
+ if i == nil {
+ return nil
+ }
+ return i.Permissions
+}
+
+// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise.
+func (i *Installation) GetRepositoriesURL() string {
+ if i == nil || i.RepositoriesURL == nil {
+ return ""
+ }
+ return *i.RepositoriesURL
+}
+
+// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise.
+func (i *Installation) GetRepositorySelection() string {
+ if i == nil || i.RepositorySelection == nil {
+ return ""
+ }
+ return *i.RepositorySelection
+}
+
+// GetSingleFileName returns the SingleFileName field if it's non-nil, zero value otherwise.
+func (i *Installation) GetSingleFileName() string {
+ if i == nil || i.SingleFileName == nil {
+ return ""
+ }
+ return *i.SingleFileName
+}
+
+// GetTargetID returns the TargetID field if it's non-nil, zero value otherwise.
+func (i *Installation) GetTargetID() int64 {
+ if i == nil || i.TargetID == nil {
+ return 0
+ }
+ return *i.TargetID
+}
+
+// GetTargetType returns the TargetType field if it's non-nil, zero value otherwise.
+func (i *Installation) GetTargetType() string {
+ if i == nil || i.TargetType == nil {
+ return ""
+ }
+ return *i.TargetType
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (i *Installation) GetUpdatedAt() Timestamp {
+ if i == nil || i.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *i.UpdatedAt
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (i *InstallationEvent) GetAction() string {
+ if i == nil || i.Action == nil {
+ return ""
+ }
+ return *i.Action
+}
+
+// GetInstallation returns the Installation field.
+func (i *InstallationEvent) GetInstallation() *Installation {
+ if i == nil {
+ return nil
+ }
+ return i.Installation
+}
+
+// GetSender returns the Sender field.
+func (i *InstallationEvent) GetSender() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Sender
+}
+
+// GetContents returns the Contents field if it's non-nil, zero value otherwise.
+func (i *InstallationPermissions) GetContents() string {
+ if i == nil || i.Contents == nil {
+ return ""
+ }
+ return *i.Contents
+}
+
+// GetIssues returns the Issues field if it's non-nil, zero value otherwise.
+func (i *InstallationPermissions) GetIssues() string {
+ if i == nil || i.Issues == nil {
+ return ""
+ }
+ return *i.Issues
+}
+
+// GetMetadata returns the Metadata field if it's non-nil, zero value otherwise.
+func (i *InstallationPermissions) GetMetadata() string {
+ if i == nil || i.Metadata == nil {
+ return ""
+ }
+ return *i.Metadata
+}
+
+// GetSingleFile returns the SingleFile field if it's non-nil, zero value otherwise.
+func (i *InstallationPermissions) GetSingleFile() string {
+ if i == nil || i.SingleFile == nil {
+ return ""
+ }
+ return *i.SingleFile
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (i *InstallationRepositoriesEvent) GetAction() string {
+ if i == nil || i.Action == nil {
+ return ""
+ }
+ return *i.Action
+}
+
+// GetInstallation returns the Installation field.
+func (i *InstallationRepositoriesEvent) GetInstallation() *Installation {
+ if i == nil {
+ return nil
+ }
+ return i.Installation
+}
+
+// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise.
+func (i *InstallationRepositoriesEvent) GetRepositorySelection() string {
+ if i == nil || i.RepositorySelection == nil {
+ return ""
+ }
+ return *i.RepositorySelection
+}
+
+// GetSender returns the Sender field.
+func (i *InstallationRepositoriesEvent) GetSender() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Sender
+}
+
+// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise.
+func (i *InstallationToken) GetExpiresAt() time.Time {
+ if i == nil || i.ExpiresAt == nil {
+ return time.Time{}
+ }
+ return *i.ExpiresAt
+}
+
+// GetToken returns the Token field if it's non-nil, zero value otherwise.
+func (i *InstallationToken) GetToken() string {
+ if i == nil || i.Token == nil {
+ return ""
+ }
+ return *i.Token
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (i *Invitation) GetCreatedAt() time.Time {
+ if i == nil || i.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *i.CreatedAt
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (i *Invitation) GetEmail() string {
+ if i == nil || i.Email == nil {
+ return ""
+ }
+ return *i.Email
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (i *Invitation) GetID() int64 {
+ if i == nil || i.ID == nil {
+ return 0
+ }
+ return *i.ID
+}
+
+// GetInvitationTeamURL returns the InvitationTeamURL field if it's non-nil, zero value otherwise.
+func (i *Invitation) GetInvitationTeamURL() string {
+ if i == nil || i.InvitationTeamURL == nil {
+ return ""
+ }
+ return *i.InvitationTeamURL
+}
+
+// GetInviter returns the Inviter field.
+func (i *Invitation) GetInviter() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Inviter
+}
+
+// GetLogin returns the Login field if it's non-nil, zero value otherwise.
+func (i *Invitation) GetLogin() string {
+ if i == nil || i.Login == nil {
+ return ""
+ }
+ return *i.Login
+}
+
+// GetRole returns the Role field if it's non-nil, zero value otherwise.
+func (i *Invitation) GetRole() string {
+ if i == nil || i.Role == nil {
+ return ""
+ }
+ return *i.Role
+}
+
+// GetTeamCount returns the TeamCount field if it's non-nil, zero value otherwise.
+func (i *Invitation) GetTeamCount() int {
+ if i == nil || i.TeamCount == nil {
+ return 0
+ }
+ return *i.TeamCount
+}
+
+// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise.
+func (i *Issue) GetActiveLockReason() string {
+ if i == nil || i.ActiveLockReason == nil {
+ return ""
+ }
+ return *i.ActiveLockReason
+}
+
+// GetAssignee returns the Assignee field.
+func (i *Issue) GetAssignee() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Assignee
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (i *Issue) GetBody() string {
+ if i == nil || i.Body == nil {
+ return ""
+ }
+ return *i.Body
+}
+
+// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise.
+func (i *Issue) GetClosedAt() time.Time {
+ if i == nil || i.ClosedAt == nil {
+ return time.Time{}
+ }
+ return *i.ClosedAt
+}
+
+// GetClosedBy returns the ClosedBy field.
+func (i *Issue) GetClosedBy() *User {
+ if i == nil {
+ return nil
+ }
+ return i.ClosedBy
+}
+
+// GetComments returns the Comments field if it's non-nil, zero value otherwise.
+func (i *Issue) GetComments() int {
+ if i == nil || i.Comments == nil {
+ return 0
+ }
+ return *i.Comments
+}
+
+// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise.
+func (i *Issue) GetCommentsURL() string {
+ if i == nil || i.CommentsURL == nil {
+ return ""
+ }
+ return *i.CommentsURL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (i *Issue) GetCreatedAt() time.Time {
+ if i == nil || i.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *i.CreatedAt
+}
+
+// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise.
+func (i *Issue) GetEventsURL() string {
+ if i == nil || i.EventsURL == nil {
+ return ""
+ }
+ return *i.EventsURL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (i *Issue) GetHTMLURL() string {
+ if i == nil || i.HTMLURL == nil {
+ return ""
+ }
+ return *i.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (i *Issue) GetID() int64 {
+ if i == nil || i.ID == nil {
+ return 0
+ }
+ return *i.ID
+}
+
+// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise.
+func (i *Issue) GetLabelsURL() string {
+ if i == nil || i.LabelsURL == nil {
+ return ""
+ }
+ return *i.LabelsURL
+}
+
+// GetLocked returns the Locked field if it's non-nil, zero value otherwise.
+func (i *Issue) GetLocked() bool {
+ if i == nil || i.Locked == nil {
+ return false
+ }
+ return *i.Locked
+}
+
+// GetMilestone returns the Milestone field.
+func (i *Issue) GetMilestone() *Milestone {
+ if i == nil {
+ return nil
+ }
+ return i.Milestone
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (i *Issue) GetNodeID() string {
+ if i == nil || i.NodeID == nil {
+ return ""
+ }
+ return *i.NodeID
+}
+
+// GetNumber returns the Number field if it's non-nil, zero value otherwise.
+func (i *Issue) GetNumber() int {
+ if i == nil || i.Number == nil {
+ return 0
+ }
+ return *i.Number
+}
+
+// GetPullRequestLinks returns the PullRequestLinks field.
+func (i *Issue) GetPullRequestLinks() *PullRequestLinks {
+ if i == nil {
+ return nil
+ }
+ return i.PullRequestLinks
+}
+
+// GetReactions returns the Reactions field.
+func (i *Issue) GetReactions() *Reactions {
+ if i == nil {
+ return nil
+ }
+ return i.Reactions
+}
+
+// GetRepository returns the Repository field.
+func (i *Issue) GetRepository() *Repository {
+ if i == nil {
+ return nil
+ }
+ return i.Repository
+}
+
+// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise.
+func (i *Issue) GetRepositoryURL() string {
+ if i == nil || i.RepositoryURL == nil {
+ return ""
+ }
+ return *i.RepositoryURL
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (i *Issue) GetState() string {
+ if i == nil || i.State == nil {
+ return ""
+ }
+ return *i.State
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (i *Issue) GetTitle() string {
+ if i == nil || i.Title == nil {
+ return ""
+ }
+ return *i.Title
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (i *Issue) GetUpdatedAt() time.Time {
+ if i == nil || i.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *i.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (i *Issue) GetURL() string {
+ if i == nil || i.URL == nil {
+ return ""
+ }
+ return *i.URL
+}
+
+// GetUser returns the User field.
+func (i *Issue) GetUser() *User {
+ if i == nil {
+ return nil
+ }
+ return i.User
+}
+
+// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise.
+func (i *IssueComment) GetAuthorAssociation() string {
+ if i == nil || i.AuthorAssociation == nil {
+ return ""
+ }
+ return *i.AuthorAssociation
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (i *IssueComment) GetBody() string {
+ if i == nil || i.Body == nil {
+ return ""
+ }
+ return *i.Body
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (i *IssueComment) GetCreatedAt() time.Time {
+ if i == nil || i.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *i.CreatedAt
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (i *IssueComment) GetHTMLURL() string {
+ if i == nil || i.HTMLURL == nil {
+ return ""
+ }
+ return *i.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (i *IssueComment) GetID() int64 {
+ if i == nil || i.ID == nil {
+ return 0
+ }
+ return *i.ID
+}
+
+// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise.
+func (i *IssueComment) GetIssueURL() string {
+ if i == nil || i.IssueURL == nil {
+ return ""
+ }
+ return *i.IssueURL
+}
+
+// GetReactions returns the Reactions field.
+func (i *IssueComment) GetReactions() *Reactions {
+ if i == nil {
+ return nil
+ }
+ return i.Reactions
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (i *IssueComment) GetUpdatedAt() time.Time {
+ if i == nil || i.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *i.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (i *IssueComment) GetURL() string {
+ if i == nil || i.URL == nil {
+ return ""
+ }
+ return *i.URL
+}
+
+// GetUser returns the User field.
+func (i *IssueComment) GetUser() *User {
+ if i == nil {
+ return nil
+ }
+ return i.User
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (i *IssueCommentEvent) GetAction() string {
+ if i == nil || i.Action == nil {
+ return ""
+ }
+ return *i.Action
+}
+
+// GetChanges returns the Changes field.
+func (i *IssueCommentEvent) GetChanges() *EditChange {
+ if i == nil {
+ return nil
+ }
+ return i.Changes
+}
+
+// GetComment returns the Comment field.
+func (i *IssueCommentEvent) GetComment() *IssueComment {
+ if i == nil {
+ return nil
+ }
+ return i.Comment
+}
+
+// GetInstallation returns the Installation field.
+func (i *IssueCommentEvent) GetInstallation() *Installation {
+ if i == nil {
+ return nil
+ }
+ return i.Installation
+}
+
+// GetIssue returns the Issue field.
+func (i *IssueCommentEvent) GetIssue() *Issue {
+ if i == nil {
+ return nil
+ }
+ return i.Issue
+}
+
+// GetRepo returns the Repo field.
+func (i *IssueCommentEvent) GetRepo() *Repository {
+ if i == nil {
+ return nil
+ }
+ return i.Repo
+}
+
+// GetSender returns the Sender field.
+func (i *IssueCommentEvent) GetSender() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Sender
+}
+
+// GetActor returns the Actor field.
+func (i *IssueEvent) GetActor() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Actor
+}
+
+// GetAssignee returns the Assignee field.
+func (i *IssueEvent) GetAssignee() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Assignee
+}
+
+// GetAssigner returns the Assigner field.
+func (i *IssueEvent) GetAssigner() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Assigner
+}
+
+// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise.
+func (i *IssueEvent) GetCommitID() string {
+ if i == nil || i.CommitID == nil {
+ return ""
+ }
+ return *i.CommitID
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (i *IssueEvent) GetCreatedAt() time.Time {
+ if i == nil || i.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *i.CreatedAt
+}
+
+// GetEvent returns the Event field if it's non-nil, zero value otherwise.
+func (i *IssueEvent) GetEvent() string {
+ if i == nil || i.Event == nil {
+ return ""
+ }
+ return *i.Event
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (i *IssueEvent) GetID() int64 {
+ if i == nil || i.ID == nil {
+ return 0
+ }
+ return *i.ID
+}
+
+// GetIssue returns the Issue field.
+func (i *IssueEvent) GetIssue() *Issue {
+ if i == nil {
+ return nil
+ }
+ return i.Issue
+}
+
+// GetLabel returns the Label field.
+func (i *IssueEvent) GetLabel() *Label {
+ if i == nil {
+ return nil
+ }
+ return i.Label
+}
+
+// GetLockReason returns the LockReason field if it's non-nil, zero value otherwise.
+func (i *IssueEvent) GetLockReason() string {
+ if i == nil || i.LockReason == nil {
+ return ""
+ }
+ return *i.LockReason
+}
+
+// GetMilestone returns the Milestone field.
+func (i *IssueEvent) GetMilestone() *Milestone {
+ if i == nil {
+ return nil
+ }
+ return i.Milestone
+}
+
+// GetRename returns the Rename field.
+func (i *IssueEvent) GetRename() *Rename {
+ if i == nil {
+ return nil
+ }
+ return i.Rename
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (i *IssueEvent) GetURL() string {
+ if i == nil || i.URL == nil {
+ return ""
+ }
+ return *i.URL
+}
+
+// GetAssignee returns the Assignee field if it's non-nil, zero value otherwise.
+func (i *IssueRequest) GetAssignee() string {
+ if i == nil || i.Assignee == nil {
+ return ""
+ }
+ return *i.Assignee
+}
+
+// GetAssignees returns the Assignees field if it's non-nil, zero value otherwise.
+func (i *IssueRequest) GetAssignees() []string {
+ if i == nil || i.Assignees == nil {
+ return nil
+ }
+ return *i.Assignees
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (i *IssueRequest) GetBody() string {
+ if i == nil || i.Body == nil {
+ return ""
+ }
+ return *i.Body
+}
+
+// GetLabels returns the Labels field if it's non-nil, zero value otherwise.
+func (i *IssueRequest) GetLabels() []string {
+ if i == nil || i.Labels == nil {
+ return nil
+ }
+ return *i.Labels
+}
+
+// GetMilestone returns the Milestone field if it's non-nil, zero value otherwise.
+func (i *IssueRequest) GetMilestone() int {
+ if i == nil || i.Milestone == nil {
+ return 0
+ }
+ return *i.Milestone
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (i *IssueRequest) GetState() string {
+ if i == nil || i.State == nil {
+ return ""
+ }
+ return *i.State
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (i *IssueRequest) GetTitle() string {
+ if i == nil || i.Title == nil {
+ return ""
+ }
+ return *i.Title
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (i *IssuesEvent) GetAction() string {
+ if i == nil || i.Action == nil {
+ return ""
+ }
+ return *i.Action
+}
+
+// GetAssignee returns the Assignee field.
+func (i *IssuesEvent) GetAssignee() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Assignee
+}
+
+// GetChanges returns the Changes field.
+func (i *IssuesEvent) GetChanges() *EditChange {
+ if i == nil {
+ return nil
+ }
+ return i.Changes
+}
+
+// GetInstallation returns the Installation field.
+func (i *IssuesEvent) GetInstallation() *Installation {
+ if i == nil {
+ return nil
+ }
+ return i.Installation
+}
+
+// GetIssue returns the Issue field.
+func (i *IssuesEvent) GetIssue() *Issue {
+ if i == nil {
+ return nil
+ }
+ return i.Issue
+}
+
+// GetLabel returns the Label field.
+func (i *IssuesEvent) GetLabel() *Label {
+ if i == nil {
+ return nil
+ }
+ return i.Label
+}
+
+// GetRepo returns the Repo field.
+func (i *IssuesEvent) GetRepo() *Repository {
+ if i == nil {
+ return nil
+ }
+ return i.Repo
+}
+
+// GetSender returns the Sender field.
+func (i *IssuesEvent) GetSender() *User {
+ if i == nil {
+ return nil
+ }
+ return i.Sender
+}
+
+// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise.
+func (i *IssuesSearchResult) GetIncompleteResults() bool {
+ if i == nil || i.IncompleteResults == nil {
+ return false
+ }
+ return *i.IncompleteResults
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (i *IssuesSearchResult) GetTotal() int {
+ if i == nil || i.Total == nil {
+ return 0
+ }
+ return *i.Total
+}
+
+// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise.
+func (i *IssueStats) GetClosedIssues() int {
+ if i == nil || i.ClosedIssues == nil {
+ return 0
+ }
+ return *i.ClosedIssues
+}
+
+// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise.
+func (i *IssueStats) GetOpenIssues() int {
+ if i == nil || i.OpenIssues == nil {
+ return 0
+ }
+ return *i.OpenIssues
+}
+
+// GetTotalIssues returns the TotalIssues field if it's non-nil, zero value otherwise.
+func (i *IssueStats) GetTotalIssues() int {
+ if i == nil || i.TotalIssues == nil {
+ return 0
+ }
+ return *i.TotalIssues
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (k *Key) GetID() int64 {
+ if k == nil || k.ID == nil {
+ return 0
+ }
+ return *k.ID
+}
+
+// GetKey returns the Key field if it's non-nil, zero value otherwise.
+func (k *Key) GetKey() string {
+ if k == nil || k.Key == nil {
+ return ""
+ }
+ return *k.Key
+}
+
+// GetReadOnly returns the ReadOnly field if it's non-nil, zero value otherwise.
+func (k *Key) GetReadOnly() bool {
+ if k == nil || k.ReadOnly == nil {
+ return false
+ }
+ return *k.ReadOnly
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (k *Key) GetTitle() string {
+ if k == nil || k.Title == nil {
+ return ""
+ }
+ return *k.Title
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (k *Key) GetURL() string {
+ if k == nil || k.URL == nil {
+ return ""
+ }
+ return *k.URL
+}
+
+// GetColor returns the Color field if it's non-nil, zero value otherwise.
+func (l *Label) GetColor() string {
+ if l == nil || l.Color == nil {
+ return ""
+ }
+ return *l.Color
+}
+
+// GetDefault returns the Default field if it's non-nil, zero value otherwise.
+func (l *Label) GetDefault() bool {
+ if l == nil || l.Default == nil {
+ return false
+ }
+ return *l.Default
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (l *Label) GetDescription() string {
+ if l == nil || l.Description == nil {
+ return ""
+ }
+ return *l.Description
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (l *Label) GetID() int64 {
+ if l == nil || l.ID == nil {
+ return 0
+ }
+ return *l.ID
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (l *Label) GetName() string {
+ if l == nil || l.Name == nil {
+ return ""
+ }
+ return *l.Name
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (l *Label) GetNodeID() string {
+ if l == nil || l.NodeID == nil {
+ return ""
+ }
+ return *l.NodeID
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (l *Label) GetURL() string {
+ if l == nil || l.URL == nil {
+ return ""
+ }
+ return *l.URL
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (l *LabelEvent) GetAction() string {
+ if l == nil || l.Action == nil {
+ return ""
+ }
+ return *l.Action
+}
+
+// GetChanges returns the Changes field.
+func (l *LabelEvent) GetChanges() *EditChange {
+ if l == nil {
+ return nil
+ }
+ return l.Changes
+}
+
+// GetInstallation returns the Installation field.
+func (l *LabelEvent) GetInstallation() *Installation {
+ if l == nil {
+ return nil
+ }
+ return l.Installation
+}
+
+// GetLabel returns the Label field.
+func (l *LabelEvent) GetLabel() *Label {
+ if l == nil {
+ return nil
+ }
+ return l.Label
+}
+
+// GetOrg returns the Org field.
+func (l *LabelEvent) GetOrg() *Organization {
+ if l == nil {
+ return nil
+ }
+ return l.Org
+}
+
+// GetRepo returns the Repo field.
+func (l *LabelEvent) GetRepo() *Repository {
+ if l == nil {
+ return nil
+ }
+ return l.Repo
+}
+
+// GetColor returns the Color field if it's non-nil, zero value otherwise.
+func (l *LabelResult) GetColor() string {
+ if l == nil || l.Color == nil {
+ return ""
+ }
+ return *l.Color
+}
+
+// GetDefault returns the Default field if it's non-nil, zero value otherwise.
+func (l *LabelResult) GetDefault() bool {
+ if l == nil || l.Default == nil {
+ return false
+ }
+ return *l.Default
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (l *LabelResult) GetDescription() string {
+ if l == nil || l.Description == nil {
+ return ""
+ }
+ return *l.Description
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (l *LabelResult) GetID() int64 {
+ if l == nil || l.ID == nil {
+ return 0
+ }
+ return *l.ID
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (l *LabelResult) GetName() string {
+ if l == nil || l.Name == nil {
+ return ""
+ }
+ return *l.Name
+}
+
+// GetScore returns the Score field.
+func (l *LabelResult) GetScore() *float64 {
+ if l == nil {
+ return nil
+ }
+ return l.Score
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (l *LabelResult) GetURL() string {
+ if l == nil || l.URL == nil {
+ return ""
+ }
+ return *l.URL
+}
+
+// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise.
+func (l *LabelsSearchResult) GetIncompleteResults() bool {
+ if l == nil || l.IncompleteResults == nil {
+ return false
+ }
+ return *l.IncompleteResults
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (l *LabelsSearchResult) GetTotal() int {
+ if l == nil || l.Total == nil {
+ return 0
+ }
+ return *l.Total
+}
+
+// GetOID returns the OID field if it's non-nil, zero value otherwise.
+func (l *LargeFile) GetOID() string {
+ if l == nil || l.OID == nil {
+ return ""
+ }
+ return *l.OID
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (l *LargeFile) GetPath() string {
+ if l == nil || l.Path == nil {
+ return ""
+ }
+ return *l.Path
+}
+
+// GetRefName returns the RefName field if it's non-nil, zero value otherwise.
+func (l *LargeFile) GetRefName() string {
+ if l == nil || l.RefName == nil {
+ return ""
+ }
+ return *l.RefName
+}
+
+// GetSize returns the Size field if it's non-nil, zero value otherwise.
+func (l *LargeFile) GetSize() int {
+ if l == nil || l.Size == nil {
+ return 0
+ }
+ return *l.Size
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (l *License) GetBody() string {
+ if l == nil || l.Body == nil {
+ return ""
+ }
+ return *l.Body
+}
+
+// GetConditions returns the Conditions field if it's non-nil, zero value otherwise.
+func (l *License) GetConditions() []string {
+ if l == nil || l.Conditions == nil {
+ return nil
+ }
+ return *l.Conditions
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (l *License) GetDescription() string {
+ if l == nil || l.Description == nil {
+ return ""
+ }
+ return *l.Description
+}
+
+// GetFeatured returns the Featured field if it's non-nil, zero value otherwise.
+func (l *License) GetFeatured() bool {
+ if l == nil || l.Featured == nil {
+ return false
+ }
+ return *l.Featured
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (l *License) GetHTMLURL() string {
+ if l == nil || l.HTMLURL == nil {
+ return ""
+ }
+ return *l.HTMLURL
+}
+
+// GetImplementation returns the Implementation field if it's non-nil, zero value otherwise.
+func (l *License) GetImplementation() string {
+ if l == nil || l.Implementation == nil {
+ return ""
+ }
+ return *l.Implementation
+}
+
+// GetKey returns the Key field if it's non-nil, zero value otherwise.
+func (l *License) GetKey() string {
+ if l == nil || l.Key == nil {
+ return ""
+ }
+ return *l.Key
+}
+
+// GetLimitations returns the Limitations field if it's non-nil, zero value otherwise.
+func (l *License) GetLimitations() []string {
+ if l == nil || l.Limitations == nil {
+ return nil
+ }
+ return *l.Limitations
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (l *License) GetName() string {
+ if l == nil || l.Name == nil {
+ return ""
+ }
+ return *l.Name
+}
+
+// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise.
+func (l *License) GetPermissions() []string {
+ if l == nil || l.Permissions == nil {
+ return nil
+ }
+ return *l.Permissions
+}
+
+// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise.
+func (l *License) GetSPDXID() string {
+ if l == nil || l.SPDXID == nil {
+ return ""
+ }
+ return *l.SPDXID
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (l *License) GetURL() string {
+ if l == nil || l.URL == nil {
+ return ""
+ }
+ return *l.URL
+}
+
+// GetCheckName returns the CheckName field if it's non-nil, zero value otherwise.
+func (l *ListCheckRunsOptions) GetCheckName() string {
+ if l == nil || l.CheckName == nil {
+ return ""
+ }
+ return *l.CheckName
+}
+
+// GetFilter returns the Filter field if it's non-nil, zero value otherwise.
+func (l *ListCheckRunsOptions) GetFilter() string {
+ if l == nil || l.Filter == nil {
+ return ""
+ }
+ return *l.Filter
+}
+
+// GetStatus returns the Status field if it's non-nil, zero value otherwise.
+func (l *ListCheckRunsOptions) GetStatus() string {
+ if l == nil || l.Status == nil {
+ return ""
+ }
+ return *l.Status
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (l *ListCheckRunsResults) GetTotal() int {
+ if l == nil || l.Total == nil {
+ return 0
+ }
+ return *l.Total
+}
+
+// GetAppID returns the AppID field if it's non-nil, zero value otherwise.
+func (l *ListCheckSuiteOptions) GetAppID() int {
+ if l == nil || l.AppID == nil {
+ return 0
+ }
+ return *l.AppID
+}
+
+// GetCheckName returns the CheckName field if it's non-nil, zero value otherwise.
+func (l *ListCheckSuiteOptions) GetCheckName() string {
+ if l == nil || l.CheckName == nil {
+ return ""
+ }
+ return *l.CheckName
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (l *ListCheckSuiteResults) GetTotal() int {
+ if l == nil || l.Total == nil {
+ return 0
+ }
+ return *l.Total
+}
+
+// GetAccountsURL returns the AccountsURL field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetAccountsURL() string {
+ if m == nil || m.AccountsURL == nil {
+ return ""
+ }
+ return *m.AccountsURL
+}
+
+// GetBullets returns the Bullets field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetBullets() []string {
+ if m == nil || m.Bullets == nil {
+ return nil
+ }
+ return *m.Bullets
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetDescription() string {
+ if m == nil || m.Description == nil {
+ return ""
+ }
+ return *m.Description
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetID() int64 {
+ if m == nil || m.ID == nil {
+ return 0
+ }
+ return *m.ID
+}
+
+// GetMonthlyPriceInCents returns the MonthlyPriceInCents field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetMonthlyPriceInCents() int {
+ if m == nil || m.MonthlyPriceInCents == nil {
+ return 0
+ }
+ return *m.MonthlyPriceInCents
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetName() string {
+ if m == nil || m.Name == nil {
+ return ""
+ }
+ return *m.Name
+}
+
+// GetPriceModel returns the PriceModel field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetPriceModel() string {
+ if m == nil || m.PriceModel == nil {
+ return ""
+ }
+ return *m.PriceModel
+}
+
+// GetUnitName returns the UnitName field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetUnitName() string {
+ if m == nil || m.UnitName == nil {
+ return ""
+ }
+ return *m.UnitName
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetURL() string {
+ if m == nil || m.URL == nil {
+ return ""
+ }
+ return *m.URL
+}
+
+// GetYearlyPriceInCents returns the YearlyPriceInCents field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetYearlyPriceInCents() int {
+ if m == nil || m.YearlyPriceInCents == nil {
+ return 0
+ }
+ return *m.YearlyPriceInCents
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlanAccount) GetEmail() string {
+ if m == nil || m.Email == nil {
+ return ""
+ }
+ return *m.Email
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlanAccount) GetID() int64 {
+ if m == nil || m.ID == nil {
+ return 0
+ }
+ return *m.ID
+}
+
+// GetLogin returns the Login field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlanAccount) GetLogin() string {
+ if m == nil || m.Login == nil {
+ return ""
+ }
+ return *m.Login
+}
+
+// GetMarketplacePurchase returns the MarketplacePurchase field.
+func (m *MarketplacePlanAccount) GetMarketplacePurchase() *MarketplacePurchase {
+ if m == nil {
+ return nil
+ }
+ return m.MarketplacePurchase
+}
+
+// GetOrganizationBillingEmail returns the OrganizationBillingEmail field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlanAccount) GetOrganizationBillingEmail() string {
+ if m == nil || m.OrganizationBillingEmail == nil {
+ return ""
+ }
+ return *m.OrganizationBillingEmail
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlanAccount) GetType() string {
+ if m == nil || m.Type == nil {
+ return ""
+ }
+ return *m.Type
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlanAccount) GetURL() string {
+ if m == nil || m.URL == nil {
+ return ""
+ }
+ return *m.URL
+}
+
+// GetAccount returns the Account field.
+func (m *MarketplacePurchase) GetAccount() *MarketplacePlanAccount {
+ if m == nil {
+ return nil
+ }
+ return m.Account
+}
+
+// GetBillingCycle returns the BillingCycle field if it's non-nil, zero value otherwise.
+func (m *MarketplacePurchase) GetBillingCycle() string {
+ if m == nil || m.BillingCycle == nil {
+ return ""
+ }
+ return *m.BillingCycle
+}
+
+// GetNextBillingDate returns the NextBillingDate field if it's non-nil, zero value otherwise.
+func (m *MarketplacePurchase) GetNextBillingDate() string {
+ if m == nil || m.NextBillingDate == nil {
+ return ""
+ }
+ return *m.NextBillingDate
+}
+
+// GetPlan returns the Plan field.
+func (m *MarketplacePurchase) GetPlan() *MarketplacePlan {
+ if m == nil {
+ return nil
+ }
+ return m.Plan
+}
+
+// GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise.
+func (m *MarketplacePurchase) GetUnitCount() int {
+ if m == nil || m.UnitCount == nil {
+ return 0
+ }
+ return *m.UnitCount
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (m *MarketplacePurchaseEvent) GetAction() string {
+ if m == nil || m.Action == nil {
+ return ""
+ }
+ return *m.Action
+}
+
+// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise.
+func (m *MarketplacePurchaseEvent) GetEffectiveDate() Timestamp {
+ if m == nil || m.EffectiveDate == nil {
+ return Timestamp{}
+ }
+ return *m.EffectiveDate
+}
+
+// GetInstallation returns the Installation field.
+func (m *MarketplacePurchaseEvent) GetInstallation() *Installation {
+ if m == nil {
+ return nil
+ }
+ return m.Installation
+}
+
+// GetMarketplacePurchase returns the MarketplacePurchase field.
+func (m *MarketplacePurchaseEvent) GetMarketplacePurchase() *MarketplacePurchase {
+ if m == nil {
+ return nil
+ }
+ return m.MarketplacePurchase
+}
+
+// GetPreviousMarketplacePurchase returns the PreviousMarketplacePurchase field.
+func (m *MarketplacePurchaseEvent) GetPreviousMarketplacePurchase() *MarketplacePurchase {
+ if m == nil {
+ return nil
+ }
+ return m.PreviousMarketplacePurchase
+}
+
+// GetSender returns the Sender field.
+func (m *MarketplacePurchaseEvent) GetSender() *User {
+ if m == nil {
+ return nil
+ }
+ return m.Sender
+}
+
+// GetText returns the Text field if it's non-nil, zero value otherwise.
+func (m *Match) GetText() string {
+ if m == nil || m.Text == nil {
+ return ""
+ }
+ return *m.Text
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (m *MemberEvent) GetAction() string {
+ if m == nil || m.Action == nil {
+ return ""
+ }
+ return *m.Action
+}
+
+// GetInstallation returns the Installation field.
+func (m *MemberEvent) GetInstallation() *Installation {
+ if m == nil {
+ return nil
+ }
+ return m.Installation
+}
+
+// GetMember returns the Member field.
+func (m *MemberEvent) GetMember() *User {
+ if m == nil {
+ return nil
+ }
+ return m.Member
+}
+
+// GetRepo returns the Repo field.
+func (m *MemberEvent) GetRepo() *Repository {
+ if m == nil {
+ return nil
+ }
+ return m.Repo
+}
+
+// GetSender returns the Sender field.
+func (m *MemberEvent) GetSender() *User {
+ if m == nil {
+ return nil
+ }
+ return m.Sender
+}
+
+// GetOrganization returns the Organization field.
+func (m *Membership) GetOrganization() *Organization {
+ if m == nil {
+ return nil
+ }
+ return m.Organization
+}
+
+// GetOrganizationURL returns the OrganizationURL field if it's non-nil, zero value otherwise.
+func (m *Membership) GetOrganizationURL() string {
+ if m == nil || m.OrganizationURL == nil {
+ return ""
+ }
+ return *m.OrganizationURL
+}
+
+// GetRole returns the Role field if it's non-nil, zero value otherwise.
+func (m *Membership) GetRole() string {
+ if m == nil || m.Role == nil {
+ return ""
+ }
+ return *m.Role
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (m *Membership) GetState() string {
+ if m == nil || m.State == nil {
+ return ""
+ }
+ return *m.State
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (m *Membership) GetURL() string {
+ if m == nil || m.URL == nil {
+ return ""
+ }
+ return *m.URL
+}
+
+// GetUser returns the User field.
+func (m *Membership) GetUser() *User {
+ if m == nil {
+ return nil
+ }
+ return m.User
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (m *MembershipEvent) GetAction() string {
+ if m == nil || m.Action == nil {
+ return ""
+ }
+ return *m.Action
+}
+
+// GetInstallation returns the Installation field.
+func (m *MembershipEvent) GetInstallation() *Installation {
+ if m == nil {
+ return nil
+ }
+ return m.Installation
+}
+
+// GetMember returns the Member field.
+func (m *MembershipEvent) GetMember() *User {
+ if m == nil {
+ return nil
+ }
+ return m.Member
+}
+
+// GetOrg returns the Org field.
+func (m *MembershipEvent) GetOrg() *Organization {
+ if m == nil {
+ return nil
+ }
+ return m.Org
+}
+
+// GetScope returns the Scope field if it's non-nil, zero value otherwise.
+func (m *MembershipEvent) GetScope() string {
+ if m == nil || m.Scope == nil {
+ return ""
+ }
+ return *m.Scope
+}
+
+// GetSender returns the Sender field.
+func (m *MembershipEvent) GetSender() *User {
+ if m == nil {
+ return nil
+ }
+ return m.Sender
+}
+
+// GetTeam returns the Team field.
+func (m *MembershipEvent) GetTeam() *Team {
+ if m == nil {
+ return nil
+ }
+ return m.Team
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (m *Metric) GetHTMLURL() string {
+ if m == nil || m.HTMLURL == nil {
+ return ""
+ }
+ return *m.HTMLURL
+}
+
+// GetKey returns the Key field if it's non-nil, zero value otherwise.
+func (m *Metric) GetKey() string {
+ if m == nil || m.Key == nil {
+ return ""
+ }
+ return *m.Key
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (m *Metric) GetName() string {
+ if m == nil || m.Name == nil {
+ return ""
+ }
+ return *m.Name
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (m *Metric) GetURL() string {
+ if m == nil || m.URL == nil {
+ return ""
+ }
+ return *m.URL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (m *Migration) GetCreatedAt() string {
+ if m == nil || m.CreatedAt == nil {
+ return ""
+ }
+ return *m.CreatedAt
+}
+
+// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise.
+func (m *Migration) GetExcludeAttachments() bool {
+ if m == nil || m.ExcludeAttachments == nil {
+ return false
+ }
+ return *m.ExcludeAttachments
+}
+
+// GetGUID returns the GUID field if it's non-nil, zero value otherwise.
+func (m *Migration) GetGUID() string {
+ if m == nil || m.GUID == nil {
+ return ""
+ }
+ return *m.GUID
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (m *Migration) GetID() int64 {
+ if m == nil || m.ID == nil {
+ return 0
+ }
+ return *m.ID
+}
+
+// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise.
+func (m *Migration) GetLockRepositories() bool {
+ if m == nil || m.LockRepositories == nil {
+ return false
+ }
+ return *m.LockRepositories
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (m *Migration) GetState() string {
+ if m == nil || m.State == nil {
+ return ""
+ }
+ return *m.State
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (m *Migration) GetUpdatedAt() string {
+ if m == nil || m.UpdatedAt == nil {
+ return ""
+ }
+ return *m.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (m *Migration) GetURL() string {
+ if m == nil || m.URL == nil {
+ return ""
+ }
+ return *m.URL
+}
+
+// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetClosedAt() time.Time {
+ if m == nil || m.ClosedAt == nil {
+ return time.Time{}
+ }
+ return *m.ClosedAt
+}
+
+// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetClosedIssues() int {
+ if m == nil || m.ClosedIssues == nil {
+ return 0
+ }
+ return *m.ClosedIssues
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetCreatedAt() time.Time {
+ if m == nil || m.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *m.CreatedAt
+}
+
+// GetCreator returns the Creator field.
+func (m *Milestone) GetCreator() *User {
+ if m == nil {
+ return nil
+ }
+ return m.Creator
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetDescription() string {
+ if m == nil || m.Description == nil {
+ return ""
+ }
+ return *m.Description
+}
+
+// GetDueOn returns the DueOn field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetDueOn() time.Time {
+ if m == nil || m.DueOn == nil {
+ return time.Time{}
+ }
+ return *m.DueOn
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetHTMLURL() string {
+ if m == nil || m.HTMLURL == nil {
+ return ""
+ }
+ return *m.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetID() int64 {
+ if m == nil || m.ID == nil {
+ return 0
+ }
+ return *m.ID
+}
+
+// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetLabelsURL() string {
+ if m == nil || m.LabelsURL == nil {
+ return ""
+ }
+ return *m.LabelsURL
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetNodeID() string {
+ if m == nil || m.NodeID == nil {
+ return ""
+ }
+ return *m.NodeID
+}
+
+// GetNumber returns the Number field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetNumber() int {
+ if m == nil || m.Number == nil {
+ return 0
+ }
+ return *m.Number
+}
+
+// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetOpenIssues() int {
+ if m == nil || m.OpenIssues == nil {
+ return 0
+ }
+ return *m.OpenIssues
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetState() string {
+ if m == nil || m.State == nil {
+ return ""
+ }
+ return *m.State
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetTitle() string {
+ if m == nil || m.Title == nil {
+ return ""
+ }
+ return *m.Title
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetUpdatedAt() time.Time {
+ if m == nil || m.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *m.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (m *Milestone) GetURL() string {
+ if m == nil || m.URL == nil {
+ return ""
+ }
+ return *m.URL
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (m *MilestoneEvent) GetAction() string {
+ if m == nil || m.Action == nil {
+ return ""
+ }
+ return *m.Action
+}
+
+// GetChanges returns the Changes field.
+func (m *MilestoneEvent) GetChanges() *EditChange {
+ if m == nil {
+ return nil
+ }
+ return m.Changes
+}
+
+// GetInstallation returns the Installation field.
+func (m *MilestoneEvent) GetInstallation() *Installation {
+ if m == nil {
+ return nil
+ }
+ return m.Installation
+}
+
+// GetMilestone returns the Milestone field.
+func (m *MilestoneEvent) GetMilestone() *Milestone {
+ if m == nil {
+ return nil
+ }
+ return m.Milestone
+}
+
+// GetOrg returns the Org field.
+func (m *MilestoneEvent) GetOrg() *Organization {
+ if m == nil {
+ return nil
+ }
+ return m.Org
+}
+
+// GetRepo returns the Repo field.
+func (m *MilestoneEvent) GetRepo() *Repository {
+ if m == nil {
+ return nil
+ }
+ return m.Repo
+}
+
+// GetSender returns the Sender field.
+func (m *MilestoneEvent) GetSender() *User {
+ if m == nil {
+ return nil
+ }
+ return m.Sender
+}
+
+// GetClosedMilestones returns the ClosedMilestones field if it's non-nil, zero value otherwise.
+func (m *MilestoneStats) GetClosedMilestones() int {
+ if m == nil || m.ClosedMilestones == nil {
+ return 0
+ }
+ return *m.ClosedMilestones
+}
+
+// GetOpenMilestones returns the OpenMilestones field if it's non-nil, zero value otherwise.
+func (m *MilestoneStats) GetOpenMilestones() int {
+ if m == nil || m.OpenMilestones == nil {
+ return 0
+ }
+ return *m.OpenMilestones
+}
+
+// GetTotalMilestones returns the TotalMilestones field if it's non-nil, zero value otherwise.
+func (m *MilestoneStats) GetTotalMilestones() int {
+ if m == nil || m.TotalMilestones == nil {
+ return 0
+ }
+ return *m.TotalMilestones
+}
+
+// GetBase returns the Base field if it's non-nil, zero value otherwise.
+func (n *NewPullRequest) GetBase() string {
+ if n == nil || n.Base == nil {
+ return ""
+ }
+ return *n.Base
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (n *NewPullRequest) GetBody() string {
+ if n == nil || n.Body == nil {
+ return ""
+ }
+ return *n.Body
+}
+
+// GetHead returns the Head field if it's non-nil, zero value otherwise.
+func (n *NewPullRequest) GetHead() string {
+ if n == nil || n.Head == nil {
+ return ""
+ }
+ return *n.Head
+}
+
+// GetIssue returns the Issue field if it's non-nil, zero value otherwise.
+func (n *NewPullRequest) GetIssue() int {
+ if n == nil || n.Issue == nil {
+ return 0
+ }
+ return *n.Issue
+}
+
+// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise.
+func (n *NewPullRequest) GetMaintainerCanModify() bool {
+ if n == nil || n.MaintainerCanModify == nil {
+ return false
+ }
+ return *n.MaintainerCanModify
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (n *NewPullRequest) GetTitle() string {
+ if n == nil || n.Title == nil {
+ return ""
+ }
+ return *n.Title
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (n *NewTeam) GetDescription() string {
+ if n == nil || n.Description == nil {
+ return ""
+ }
+ return *n.Description
+}
+
+// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise.
+func (n *NewTeam) GetLDAPDN() string {
+ if n == nil || n.LDAPDN == nil {
+ return ""
+ }
+ return *n.LDAPDN
+}
+
+// GetParentTeamID returns the ParentTeamID field if it's non-nil, zero value otherwise.
+func (n *NewTeam) GetParentTeamID() int64 {
+ if n == nil || n.ParentTeamID == nil {
+ return 0
+ }
+ return *n.ParentTeamID
+}
+
+// GetPermission returns the Permission field if it's non-nil, zero value otherwise.
+func (n *NewTeam) GetPermission() string {
+ if n == nil || n.Permission == nil {
+ return ""
+ }
+ return *n.Permission
+}
+
+// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise.
+func (n *NewTeam) GetPrivacy() string {
+ if n == nil || n.Privacy == nil {
+ return ""
+ }
+ return *n.Privacy
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (n *Notification) GetID() string {
+ if n == nil || n.ID == nil {
+ return ""
+ }
+ return *n.ID
+}
+
+// GetLastReadAt returns the LastReadAt field if it's non-nil, zero value otherwise.
+func (n *Notification) GetLastReadAt() time.Time {
+ if n == nil || n.LastReadAt == nil {
+ return time.Time{}
+ }
+ return *n.LastReadAt
+}
+
+// GetReason returns the Reason field if it's non-nil, zero value otherwise.
+func (n *Notification) GetReason() string {
+ if n == nil || n.Reason == nil {
+ return ""
+ }
+ return *n.Reason
+}
+
+// GetRepository returns the Repository field.
+func (n *Notification) GetRepository() *Repository {
+ if n == nil {
+ return nil
+ }
+ return n.Repository
+}
+
+// GetSubject returns the Subject field.
+func (n *Notification) GetSubject() *NotificationSubject {
+ if n == nil {
+ return nil
+ }
+ return n.Subject
+}
+
+// GetUnread returns the Unread field if it's non-nil, zero value otherwise.
+func (n *Notification) GetUnread() bool {
+ if n == nil || n.Unread == nil {
+ return false
+ }
+ return *n.Unread
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (n *Notification) GetUpdatedAt() time.Time {
+ if n == nil || n.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *n.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (n *Notification) GetURL() string {
+ if n == nil || n.URL == nil {
+ return ""
+ }
+ return *n.URL
+}
+
+// GetLatestCommentURL returns the LatestCommentURL field if it's non-nil, zero value otherwise.
+func (n *NotificationSubject) GetLatestCommentURL() string {
+ if n == nil || n.LatestCommentURL == nil {
+ return ""
+ }
+ return *n.LatestCommentURL
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (n *NotificationSubject) GetTitle() string {
+ if n == nil || n.Title == nil {
+ return ""
+ }
+ return *n.Title
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (n *NotificationSubject) GetType() string {
+ if n == nil || n.Type == nil {
+ return ""
+ }
+ return *n.Type
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (n *NotificationSubject) GetURL() string {
+ if n == nil || n.URL == nil {
+ return ""
+ }
+ return *n.URL
+}
+
+// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise.
+func (o *Organization) GetAvatarURL() string {
+ if o == nil || o.AvatarURL == nil {
+ return ""
+ }
+ return *o.AvatarURL
+}
+
+// GetBillingEmail returns the BillingEmail field if it's non-nil, zero value otherwise.
+func (o *Organization) GetBillingEmail() string {
+ if o == nil || o.BillingEmail == nil {
+ return ""
+ }
+ return *o.BillingEmail
+}
+
+// GetBlog returns the Blog field if it's non-nil, zero value otherwise.
+func (o *Organization) GetBlog() string {
+ if o == nil || o.Blog == nil {
+ return ""
+ }
+ return *o.Blog
+}
+
+// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise.
+func (o *Organization) GetCollaborators() int {
+ if o == nil || o.Collaborators == nil {
+ return 0
+ }
+ return *o.Collaborators
+}
+
+// GetCompany returns the Company field if it's non-nil, zero value otherwise.
+func (o *Organization) GetCompany() string {
+ if o == nil || o.Company == nil {
+ return ""
+ }
+ return *o.Company
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (o *Organization) GetCreatedAt() time.Time {
+ if o == nil || o.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *o.CreatedAt
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (o *Organization) GetDescription() string {
+ if o == nil || o.Description == nil {
+ return ""
+ }
+ return *o.Description
+}
+
+// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise.
+func (o *Organization) GetDiskUsage() int {
+ if o == nil || o.DiskUsage == nil {
+ return 0
+ }
+ return *o.DiskUsage
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (o *Organization) GetEmail() string {
+ if o == nil || o.Email == nil {
+ return ""
+ }
+ return *o.Email
+}
+
+// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise.
+func (o *Organization) GetEventsURL() string {
+ if o == nil || o.EventsURL == nil {
+ return ""
+ }
+ return *o.EventsURL
+}
+
+// GetFollowers returns the Followers field if it's non-nil, zero value otherwise.
+func (o *Organization) GetFollowers() int {
+ if o == nil || o.Followers == nil {
+ return 0
+ }
+ return *o.Followers
+}
+
+// GetFollowing returns the Following field if it's non-nil, zero value otherwise.
+func (o *Organization) GetFollowing() int {
+ if o == nil || o.Following == nil {
+ return 0
+ }
+ return *o.Following
+}
+
+// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise.
+func (o *Organization) GetHooksURL() string {
+ if o == nil || o.HooksURL == nil {
+ return ""
+ }
+ return *o.HooksURL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (o *Organization) GetHTMLURL() string {
+ if o == nil || o.HTMLURL == nil {
+ return ""
+ }
+ return *o.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (o *Organization) GetID() int64 {
+ if o == nil || o.ID == nil {
+ return 0
+ }
+ return *o.ID
+}
+
+// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise.
+func (o *Organization) GetIssuesURL() string {
+ if o == nil || o.IssuesURL == nil {
+ return ""
+ }
+ return *o.IssuesURL
+}
+
+// GetLocation returns the Location field if it's non-nil, zero value otherwise.
+func (o *Organization) GetLocation() string {
+ if o == nil || o.Location == nil {
+ return ""
+ }
+ return *o.Location
+}
+
+// GetLogin returns the Login field if it's non-nil, zero value otherwise.
+func (o *Organization) GetLogin() string {
+ if o == nil || o.Login == nil {
+ return ""
+ }
+ return *o.Login
+}
+
+// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise.
+func (o *Organization) GetMembersURL() string {
+ if o == nil || o.MembersURL == nil {
+ return ""
+ }
+ return *o.MembersURL
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (o *Organization) GetName() string {
+ if o == nil || o.Name == nil {
+ return ""
+ }
+ return *o.Name
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (o *Organization) GetNodeID() string {
+ if o == nil || o.NodeID == nil {
+ return ""
+ }
+ return *o.NodeID
+}
+
+// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise.
+func (o *Organization) GetOwnedPrivateRepos() int {
+ if o == nil || o.OwnedPrivateRepos == nil {
+ return 0
+ }
+ return *o.OwnedPrivateRepos
+}
+
+// GetPlan returns the Plan field.
+func (o *Organization) GetPlan() *Plan {
+ if o == nil {
+ return nil
+ }
+ return o.Plan
+}
+
+// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise.
+func (o *Organization) GetPrivateGists() int {
+ if o == nil || o.PrivateGists == nil {
+ return 0
+ }
+ return *o.PrivateGists
+}
+
+// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise.
+func (o *Organization) GetPublicGists() int {
+ if o == nil || o.PublicGists == nil {
+ return 0
+ }
+ return *o.PublicGists
+}
+
+// GetPublicMembersURL returns the PublicMembersURL field if it's non-nil, zero value otherwise.
+func (o *Organization) GetPublicMembersURL() string {
+ if o == nil || o.PublicMembersURL == nil {
+ return ""
+ }
+ return *o.PublicMembersURL
+}
+
+// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise.
+func (o *Organization) GetPublicRepos() int {
+ if o == nil || o.PublicRepos == nil {
+ return 0
+ }
+ return *o.PublicRepos
+}
+
+// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise.
+func (o *Organization) GetReposURL() string {
+ if o == nil || o.ReposURL == nil {
+ return ""
+ }
+ return *o.ReposURL
+}
+
+// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise.
+func (o *Organization) GetTotalPrivateRepos() int {
+ if o == nil || o.TotalPrivateRepos == nil {
+ return 0
+ }
+ return *o.TotalPrivateRepos
+}
+
+// GetTwoFactorRequirementEnabled returns the TwoFactorRequirementEnabled field if it's non-nil, zero value otherwise.
+func (o *Organization) GetTwoFactorRequirementEnabled() bool {
+ if o == nil || o.TwoFactorRequirementEnabled == nil {
+ return false
+ }
+ return *o.TwoFactorRequirementEnabled
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (o *Organization) GetType() string {
+ if o == nil || o.Type == nil {
+ return ""
+ }
+ return *o.Type
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (o *Organization) GetUpdatedAt() time.Time {
+ if o == nil || o.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *o.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (o *Organization) GetURL() string {
+ if o == nil || o.URL == nil {
+ return ""
+ }
+ return *o.URL
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (o *OrganizationEvent) GetAction() string {
+ if o == nil || o.Action == nil {
+ return ""
+ }
+ return *o.Action
+}
+
+// GetInstallation returns the Installation field.
+func (o *OrganizationEvent) GetInstallation() *Installation {
+ if o == nil {
+ return nil
+ }
+ return o.Installation
+}
+
+// GetInvitation returns the Invitation field.
+func (o *OrganizationEvent) GetInvitation() *Invitation {
+ if o == nil {
+ return nil
+ }
+ return o.Invitation
+}
+
+// GetMembership returns the Membership field.
+func (o *OrganizationEvent) GetMembership() *Membership {
+ if o == nil {
+ return nil
+ }
+ return o.Membership
+}
+
+// GetOrganization returns the Organization field.
+func (o *OrganizationEvent) GetOrganization() *Organization {
+ if o == nil {
+ return nil
+ }
+ return o.Organization
+}
+
+// GetSender returns the Sender field.
+func (o *OrganizationEvent) GetSender() *User {
+ if o == nil {
+ return nil
+ }
+ return o.Sender
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (o *OrgBlockEvent) GetAction() string {
+ if o == nil || o.Action == nil {
+ return ""
+ }
+ return *o.Action
+}
+
+// GetBlockedUser returns the BlockedUser field.
+func (o *OrgBlockEvent) GetBlockedUser() *User {
+ if o == nil {
+ return nil
+ }
+ return o.BlockedUser
+}
+
+// GetInstallation returns the Installation field.
+func (o *OrgBlockEvent) GetInstallation() *Installation {
+ if o == nil {
+ return nil
+ }
+ return o.Installation
+}
+
+// GetOrganization returns the Organization field.
+func (o *OrgBlockEvent) GetOrganization() *Organization {
+ if o == nil {
+ return nil
+ }
+ return o.Organization
+}
+
+// GetSender returns the Sender field.
+func (o *OrgBlockEvent) GetSender() *User {
+ if o == nil {
+ return nil
+ }
+ return o.Sender
+}
+
+// GetDisabledOrgs returns the DisabledOrgs field if it's non-nil, zero value otherwise.
+func (o *OrgStats) GetDisabledOrgs() int {
+ if o == nil || o.DisabledOrgs == nil {
+ return 0
+ }
+ return *o.DisabledOrgs
+}
+
+// GetTotalOrgs returns the TotalOrgs field if it's non-nil, zero value otherwise.
+func (o *OrgStats) GetTotalOrgs() int {
+ if o == nil || o.TotalOrgs == nil {
+ return 0
+ }
+ return *o.TotalOrgs
+}
+
+// GetTotalTeamMembers returns the TotalTeamMembers field if it's non-nil, zero value otherwise.
+func (o *OrgStats) GetTotalTeamMembers() int {
+ if o == nil || o.TotalTeamMembers == nil {
+ return 0
+ }
+ return *o.TotalTeamMembers
+}
+
+// GetTotalTeams returns the TotalTeams field if it's non-nil, zero value otherwise.
+func (o *OrgStats) GetTotalTeams() int {
+ if o == nil || o.TotalTeams == nil {
+ return 0
+ }
+ return *o.TotalTeams
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (p *Page) GetAction() string {
+ if p == nil || p.Action == nil {
+ return ""
+ }
+ return *p.Action
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (p *Page) GetHTMLURL() string {
+ if p == nil || p.HTMLURL == nil {
+ return ""
+ }
+ return *p.HTMLURL
+}
+
+// GetPageName returns the PageName field if it's non-nil, zero value otherwise.
+func (p *Page) GetPageName() string {
+ if p == nil || p.PageName == nil {
+ return ""
+ }
+ return *p.PageName
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (p *Page) GetSHA() string {
+ if p == nil || p.SHA == nil {
+ return ""
+ }
+ return *p.SHA
+}
+
+// GetSummary returns the Summary field if it's non-nil, zero value otherwise.
+func (p *Page) GetSummary() string {
+ if p == nil || p.Summary == nil {
+ return ""
+ }
+ return *p.Summary
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (p *Page) GetTitle() string {
+ if p == nil || p.Title == nil {
+ return ""
+ }
+ return *p.Title
+}
+
+// GetBuild returns the Build field.
+func (p *PageBuildEvent) GetBuild() *PagesBuild {
+ if p == nil {
+ return nil
+ }
+ return p.Build
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *PageBuildEvent) GetID() int64 {
+ if p == nil || p.ID == nil {
+ return 0
+ }
+ return *p.ID
+}
+
+// GetInstallation returns the Installation field.
+func (p *PageBuildEvent) GetInstallation() *Installation {
+ if p == nil {
+ return nil
+ }
+ return p.Installation
+}
+
+// GetRepo returns the Repo field.
+func (p *PageBuildEvent) GetRepo() *Repository {
+ if p == nil {
+ return nil
+ }
+ return p.Repo
+}
+
+// GetSender returns the Sender field.
+func (p *PageBuildEvent) GetSender() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Sender
+}
+
+// GetCNAME returns the CNAME field if it's non-nil, zero value otherwise.
+func (p *Pages) GetCNAME() string {
+ if p == nil || p.CNAME == nil {
+ return ""
+ }
+ return *p.CNAME
+}
+
+// GetCustom404 returns the Custom404 field if it's non-nil, zero value otherwise.
+func (p *Pages) GetCustom404() bool {
+ if p == nil || p.Custom404 == nil {
+ return false
+ }
+ return *p.Custom404
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (p *Pages) GetHTMLURL() string {
+ if p == nil || p.HTMLURL == nil {
+ return ""
+ }
+ return *p.HTMLURL
+}
+
+// GetStatus returns the Status field if it's non-nil, zero value otherwise.
+func (p *Pages) GetStatus() string {
+ if p == nil || p.Status == nil {
+ return ""
+ }
+ return *p.Status
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *Pages) GetURL() string {
+ if p == nil || p.URL == nil {
+ return ""
+ }
+ return *p.URL
+}
+
+// GetCommit returns the Commit field if it's non-nil, zero value otherwise.
+func (p *PagesBuild) GetCommit() string {
+ if p == nil || p.Commit == nil {
+ return ""
+ }
+ return *p.Commit
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (p *PagesBuild) GetCreatedAt() Timestamp {
+ if p == nil || p.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *p.CreatedAt
+}
+
+// GetDuration returns the Duration field if it's non-nil, zero value otherwise.
+func (p *PagesBuild) GetDuration() int {
+ if p == nil || p.Duration == nil {
+ return 0
+ }
+ return *p.Duration
+}
+
+// GetError returns the Error field.
+func (p *PagesBuild) GetError() *PagesError {
+ if p == nil {
+ return nil
+ }
+ return p.Error
+}
+
+// GetPusher returns the Pusher field.
+func (p *PagesBuild) GetPusher() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Pusher
+}
+
+// GetStatus returns the Status field if it's non-nil, zero value otherwise.
+func (p *PagesBuild) GetStatus() string {
+ if p == nil || p.Status == nil {
+ return ""
+ }
+ return *p.Status
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (p *PagesBuild) GetUpdatedAt() Timestamp {
+ if p == nil || p.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *p.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *PagesBuild) GetURL() string {
+ if p == nil || p.URL == nil {
+ return ""
+ }
+ return *p.URL
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (p *PagesError) GetMessage() string {
+ if p == nil || p.Message == nil {
+ return ""
+ }
+ return *p.Message
+}
+
+// GetTotalPages returns the TotalPages field if it's non-nil, zero value otherwise.
+func (p *PageStats) GetTotalPages() int {
+ if p == nil || p.TotalPages == nil {
+ return 0
+ }
+ return *p.TotalPages
+}
+
+// GetHook returns the Hook field.
+func (p *PingEvent) GetHook() *Hook {
+ if p == nil {
+ return nil
+ }
+ return p.Hook
+}
+
+// GetHookID returns the HookID field if it's non-nil, zero value otherwise.
+func (p *PingEvent) GetHookID() int64 {
+ if p == nil || p.HookID == nil {
+ return 0
+ }
+ return *p.HookID
+}
+
+// GetInstallation returns the Installation field.
+func (p *PingEvent) GetInstallation() *Installation {
+ if p == nil {
+ return nil
+ }
+ return p.Installation
+}
+
+// GetZen returns the Zen field if it's non-nil, zero value otherwise.
+func (p *PingEvent) GetZen() string {
+ if p == nil || p.Zen == nil {
+ return ""
+ }
+ return *p.Zen
+}
+
+// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise.
+func (p *Plan) GetCollaborators() int {
+ if p == nil || p.Collaborators == nil {
+ return 0
+ }
+ return *p.Collaborators
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (p *Plan) GetName() string {
+ if p == nil || p.Name == nil {
+ return ""
+ }
+ return *p.Name
+}
+
+// GetPrivateRepos returns the PrivateRepos field if it's non-nil, zero value otherwise.
+func (p *Plan) GetPrivateRepos() int {
+ if p == nil || p.PrivateRepos == nil {
+ return 0
+ }
+ return *p.PrivateRepos
+}
+
+// GetSpace returns the Space field if it's non-nil, zero value otherwise.
+func (p *Plan) GetSpace() int {
+ if p == nil || p.Space == nil {
+ return 0
+ }
+ return *p.Space
+}
+
+// GetConfigURL returns the ConfigURL field if it's non-nil, zero value otherwise.
+func (p *PreReceiveHook) GetConfigURL() string {
+ if p == nil || p.ConfigURL == nil {
+ return ""
+ }
+ return *p.ConfigURL
+}
+
+// GetEnforcement returns the Enforcement field if it's non-nil, zero value otherwise.
+func (p *PreReceiveHook) GetEnforcement() string {
+ if p == nil || p.Enforcement == nil {
+ return ""
+ }
+ return *p.Enforcement
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *PreReceiveHook) GetID() int64 {
+ if p == nil || p.ID == nil {
+ return 0
+ }
+ return *p.ID
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (p *PreReceiveHook) GetName() string {
+ if p == nil || p.Name == nil {
+ return ""
+ }
+ return *p.Name
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (p *Project) GetBody() string {
+ if p == nil || p.Body == nil {
+ return ""
+ }
+ return *p.Body
+}
+
+// GetColumnsURL returns the ColumnsURL field if it's non-nil, zero value otherwise.
+func (p *Project) GetColumnsURL() string {
+ if p == nil || p.ColumnsURL == nil {
+ return ""
+ }
+ return *p.ColumnsURL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (p *Project) GetCreatedAt() Timestamp {
+ if p == nil || p.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *p.CreatedAt
+}
+
+// GetCreator returns the Creator field.
+func (p *Project) GetCreator() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Creator
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (p *Project) GetHTMLURL() string {
+ if p == nil || p.HTMLURL == nil {
+ return ""
+ }
+ return *p.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *Project) GetID() int64 {
+ if p == nil || p.ID == nil {
+ return 0
+ }
+ return *p.ID
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (p *Project) GetName() string {
+ if p == nil || p.Name == nil {
+ return ""
+ }
+ return *p.Name
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (p *Project) GetNodeID() string {
+ if p == nil || p.NodeID == nil {
+ return ""
+ }
+ return *p.NodeID
+}
+
+// GetNumber returns the Number field if it's non-nil, zero value otherwise.
+func (p *Project) GetNumber() int {
+ if p == nil || p.Number == nil {
+ return 0
+ }
+ return *p.Number
+}
+
+// GetOwnerURL returns the OwnerURL field if it's non-nil, zero value otherwise.
+func (p *Project) GetOwnerURL() string {
+ if p == nil || p.OwnerURL == nil {
+ return ""
+ }
+ return *p.OwnerURL
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (p *Project) GetState() string {
+ if p == nil || p.State == nil {
+ return ""
+ }
+ return *p.State
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (p *Project) GetUpdatedAt() Timestamp {
+ if p == nil || p.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *p.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *Project) GetURL() string {
+ if p == nil || p.URL == nil {
+ return ""
+ }
+ return *p.URL
+}
+
+// GetArchived returns the Archived field if it's non-nil, zero value otherwise.
+func (p *ProjectCard) GetArchived() bool {
+ if p == nil || p.Archived == nil {
+ return false
+ }
+ return *p.Archived
+}
+
+// GetColumnID returns the ColumnID field if it's non-nil, zero value otherwise.
+func (p *ProjectCard) GetColumnID() int64 {
+ if p == nil || p.ColumnID == nil {
+ return 0
+ }
+ return *p.ColumnID
+}
+
+// GetColumnURL returns the ColumnURL field if it's non-nil, zero value otherwise.
+func (p *ProjectCard) GetColumnURL() string {
+ if p == nil || p.ColumnURL == nil {
+ return ""
+ }
+ return *p.ColumnURL
+}
+
+// GetContentURL returns the ContentURL field if it's non-nil, zero value otherwise.
+func (p *ProjectCard) GetContentURL() string {
+ if p == nil || p.ContentURL == nil {
+ return ""
+ }
+ return *p.ContentURL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectCard) GetCreatedAt() Timestamp {
+ if p == nil || p.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *p.CreatedAt
+}
+
+// GetCreator returns the Creator field.
+func (p *ProjectCard) GetCreator() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Creator
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *ProjectCard) GetID() int64 {
+ if p == nil || p.ID == nil {
+ return 0
+ }
+ return *p.ID
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (p *ProjectCard) GetNodeID() string {
+ if p == nil || p.NodeID == nil {
+ return ""
+ }
+ return *p.NodeID
+}
+
+// GetNote returns the Note field if it's non-nil, zero value otherwise.
+func (p *ProjectCard) GetNote() string {
+ if p == nil || p.Note == nil {
+ return ""
+ }
+ return *p.Note
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectCard) GetUpdatedAt() Timestamp {
+ if p == nil || p.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *p.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *ProjectCard) GetURL() string {
+ if p == nil || p.URL == nil {
+ return ""
+ }
+ return *p.URL
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (p *ProjectCardEvent) GetAction() string {
+ if p == nil || p.Action == nil {
+ return ""
+ }
+ return *p.Action
+}
+
+// GetAfterID returns the AfterID field if it's non-nil, zero value otherwise.
+func (p *ProjectCardEvent) GetAfterID() int64 {
+ if p == nil || p.AfterID == nil {
+ return 0
+ }
+ return *p.AfterID
+}
+
+// GetChanges returns the Changes field.
+func (p *ProjectCardEvent) GetChanges() *ProjectCardChange {
+ if p == nil {
+ return nil
+ }
+ return p.Changes
+}
+
+// GetInstallation returns the Installation field.
+func (p *ProjectCardEvent) GetInstallation() *Installation {
+ if p == nil {
+ return nil
+ }
+ return p.Installation
+}
+
+// GetOrg returns the Org field.
+func (p *ProjectCardEvent) GetOrg() *Organization {
+ if p == nil {
+ return nil
+ }
+ return p.Org
+}
+
+// GetProjectCard returns the ProjectCard field.
+func (p *ProjectCardEvent) GetProjectCard() *ProjectCard {
+ if p == nil {
+ return nil
+ }
+ return p.ProjectCard
+}
+
+// GetRepo returns the Repo field.
+func (p *ProjectCardEvent) GetRepo() *Repository {
+ if p == nil {
+ return nil
+ }
+ return p.Repo
+}
+
+// GetSender returns the Sender field.
+func (p *ProjectCardEvent) GetSender() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Sender
+}
+
+// GetArchivedState returns the ArchivedState field if it's non-nil, zero value otherwise.
+func (p *ProjectCardListOptions) GetArchivedState() string {
+ if p == nil || p.ArchivedState == nil {
+ return ""
+ }
+ return *p.ArchivedState
+}
+
+// GetArchived returns the Archived field if it's non-nil, zero value otherwise.
+func (p *ProjectCardOptions) GetArchived() bool {
+ if p == nil || p.Archived == nil {
+ return false
+ }
+ return *p.Archived
+}
+
+// GetCardsURL returns the CardsURL field if it's non-nil, zero value otherwise.
+func (p *ProjectColumn) GetCardsURL() string {
+ if p == nil || p.CardsURL == nil {
+ return ""
+ }
+ return *p.CardsURL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectColumn) GetCreatedAt() Timestamp {
+ if p == nil || p.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *p.CreatedAt
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *ProjectColumn) GetID() int64 {
+ if p == nil || p.ID == nil {
+ return 0
+ }
+ return *p.ID
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (p *ProjectColumn) GetName() string {
+ if p == nil || p.Name == nil {
+ return ""
+ }
+ return *p.Name
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (p *ProjectColumn) GetNodeID() string {
+ if p == nil || p.NodeID == nil {
+ return ""
+ }
+ return *p.NodeID
+}
+
+// GetProjectURL returns the ProjectURL field if it's non-nil, zero value otherwise.
+func (p *ProjectColumn) GetProjectURL() string {
+ if p == nil || p.ProjectURL == nil {
+ return ""
+ }
+ return *p.ProjectURL
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectColumn) GetUpdatedAt() Timestamp {
+ if p == nil || p.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *p.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *ProjectColumn) GetURL() string {
+ if p == nil || p.URL == nil {
+ return ""
+ }
+ return *p.URL
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (p *ProjectColumnEvent) GetAction() string {
+ if p == nil || p.Action == nil {
+ return ""
+ }
+ return *p.Action
+}
+
+// GetAfterID returns the AfterID field if it's non-nil, zero value otherwise.
+func (p *ProjectColumnEvent) GetAfterID() int64 {
+ if p == nil || p.AfterID == nil {
+ return 0
+ }
+ return *p.AfterID
+}
+
+// GetChanges returns the Changes field.
+func (p *ProjectColumnEvent) GetChanges() *ProjectColumnChange {
+ if p == nil {
+ return nil
+ }
+ return p.Changes
+}
+
+// GetInstallation returns the Installation field.
+func (p *ProjectColumnEvent) GetInstallation() *Installation {
+ if p == nil {
+ return nil
+ }
+ return p.Installation
+}
+
+// GetOrg returns the Org field.
+func (p *ProjectColumnEvent) GetOrg() *Organization {
+ if p == nil {
+ return nil
+ }
+ return p.Org
+}
+
+// GetProjectColumn returns the ProjectColumn field.
+func (p *ProjectColumnEvent) GetProjectColumn() *ProjectColumn {
+ if p == nil {
+ return nil
+ }
+ return p.ProjectColumn
+}
+
+// GetRepo returns the Repo field.
+func (p *ProjectColumnEvent) GetRepo() *Repository {
+ if p == nil {
+ return nil
+ }
+ return p.Repo
+}
+
+// GetSender returns the Sender field.
+func (p *ProjectColumnEvent) GetSender() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Sender
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (p *ProjectEvent) GetAction() string {
+ if p == nil || p.Action == nil {
+ return ""
+ }
+ return *p.Action
+}
+
+// GetChanges returns the Changes field.
+func (p *ProjectEvent) GetChanges() *ProjectChange {
+ if p == nil {
+ return nil
+ }
+ return p.Changes
+}
+
+// GetInstallation returns the Installation field.
+func (p *ProjectEvent) GetInstallation() *Installation {
+ if p == nil {
+ return nil
+ }
+ return p.Installation
+}
+
+// GetOrg returns the Org field.
+func (p *ProjectEvent) GetOrg() *Organization {
+ if p == nil {
+ return nil
+ }
+ return p.Org
+}
+
+// GetProject returns the Project field.
+func (p *ProjectEvent) GetProject() *Project {
+ if p == nil {
+ return nil
+ }
+ return p.Project
+}
+
+// GetRepo returns the Repo field.
+func (p *ProjectEvent) GetRepo() *Repository {
+ if p == nil {
+ return nil
+ }
+ return p.Repo
+}
+
+// GetSender returns the Sender field.
+func (p *ProjectEvent) GetSender() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Sender
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (p *ProjectOptions) GetBody() string {
+ if p == nil || p.Body == nil {
+ return ""
+ }
+ return *p.Body
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (p *ProjectOptions) GetName() string {
+ if p == nil || p.Name == nil {
+ return ""
+ }
+ return *p.Name
+}
+
+// GetOrganizationPermission returns the OrganizationPermission field if it's non-nil, zero value otherwise.
+func (p *ProjectOptions) GetOrganizationPermission() string {
+ if p == nil || p.OrganizationPermission == nil {
+ return ""
+ }
+ return *p.OrganizationPermission
+}
+
+// GetPublic returns the Public field if it's non-nil, zero value otherwise.
+func (p *ProjectOptions) GetPublic() bool {
+ if p == nil || p.Public == nil {
+ return false
+ }
+ return *p.Public
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (p *ProjectOptions) GetState() string {
+ if p == nil || p.State == nil {
+ return ""
+ }
+ return *p.State
+}
+
+// GetEnforceAdmins returns the EnforceAdmins field.
+func (p *Protection) GetEnforceAdmins() *AdminEnforcement {
+ if p == nil {
+ return nil
+ }
+ return p.EnforceAdmins
+}
+
+// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field.
+func (p *Protection) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcement {
+ if p == nil {
+ return nil
+ }
+ return p.RequiredPullRequestReviews
+}
+
+// GetRequiredStatusChecks returns the RequiredStatusChecks field.
+func (p *Protection) GetRequiredStatusChecks() *RequiredStatusChecks {
+ if p == nil {
+ return nil
+ }
+ return p.RequiredStatusChecks
+}
+
+// GetRestrictions returns the Restrictions field.
+func (p *Protection) GetRestrictions() *BranchRestrictions {
+ if p == nil {
+ return nil
+ }
+ return p.Restrictions
+}
+
+// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field.
+func (p *ProtectionRequest) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcementRequest {
+ if p == nil {
+ return nil
+ }
+ return p.RequiredPullRequestReviews
+}
+
+// GetRequiredStatusChecks returns the RequiredStatusChecks field.
+func (p *ProtectionRequest) GetRequiredStatusChecks() *RequiredStatusChecks {
+ if p == nil {
+ return nil
+ }
+ return p.RequiredStatusChecks
+}
+
+// GetRestrictions returns the Restrictions field.
+func (p *ProtectionRequest) GetRestrictions() *BranchRestrictionsRequest {
+ if p == nil {
+ return nil
+ }
+ return p.Restrictions
+}
+
+// GetInstallation returns the Installation field.
+func (p *PublicEvent) GetInstallation() *Installation {
+ if p == nil {
+ return nil
+ }
+ return p.Installation
+}
+
+// GetRepo returns the Repo field.
+func (p *PublicEvent) GetRepo() *Repository {
+ if p == nil {
+ return nil
+ }
+ return p.Repo
+}
+
+// GetSender returns the Sender field.
+func (p *PublicEvent) GetSender() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Sender
+}
+
+// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetActiveLockReason() string {
+ if p == nil || p.ActiveLockReason == nil {
+ return ""
+ }
+ return *p.ActiveLockReason
+}
+
+// GetAdditions returns the Additions field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetAdditions() int {
+ if p == nil || p.Additions == nil {
+ return 0
+ }
+ return *p.Additions
+}
+
+// GetAssignee returns the Assignee field.
+func (p *PullRequest) GetAssignee() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Assignee
+}
+
+// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetAuthorAssociation() string {
+ if p == nil || p.AuthorAssociation == nil {
+ return ""
+ }
+ return *p.AuthorAssociation
+}
+
+// GetBase returns the Base field.
+func (p *PullRequest) GetBase() *PullRequestBranch {
+ if p == nil {
+ return nil
+ }
+ return p.Base
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetBody() string {
+ if p == nil || p.Body == nil {
+ return ""
+ }
+ return *p.Body
+}
+
+// GetChangedFiles returns the ChangedFiles field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetChangedFiles() int {
+ if p == nil || p.ChangedFiles == nil {
+ return 0
+ }
+ return *p.ChangedFiles
+}
+
+// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetClosedAt() time.Time {
+ if p == nil || p.ClosedAt == nil {
+ return time.Time{}
+ }
+ return *p.ClosedAt
+}
+
+// GetComments returns the Comments field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetComments() int {
+ if p == nil || p.Comments == nil {
+ return 0
+ }
+ return *p.Comments
+}
+
+// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetCommentsURL() string {
+ if p == nil || p.CommentsURL == nil {
+ return ""
+ }
+ return *p.CommentsURL
+}
+
+// GetCommits returns the Commits field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetCommits() int {
+ if p == nil || p.Commits == nil {
+ return 0
+ }
+ return *p.Commits
+}
+
+// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetCommitsURL() string {
+ if p == nil || p.CommitsURL == nil {
+ return ""
+ }
+ return *p.CommitsURL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetCreatedAt() time.Time {
+ if p == nil || p.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *p.CreatedAt
+}
+
+// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetDeletions() int {
+ if p == nil || p.Deletions == nil {
+ return 0
+ }
+ return *p.Deletions
+}
+
+// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetDiffURL() string {
+ if p == nil || p.DiffURL == nil {
+ return ""
+ }
+ return *p.DiffURL
+}
+
+// GetHead returns the Head field.
+func (p *PullRequest) GetHead() *PullRequestBranch {
+ if p == nil {
+ return nil
+ }
+ return p.Head
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetHTMLURL() string {
+ if p == nil || p.HTMLURL == nil {
+ return ""
+ }
+ return *p.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetID() int64 {
+ if p == nil || p.ID == nil {
+ return 0
+ }
+ return *p.ID
+}
+
+// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetIssueURL() string {
+ if p == nil || p.IssueURL == nil {
+ return ""
+ }
+ return *p.IssueURL
+}
+
+// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetMaintainerCanModify() bool {
+ if p == nil || p.MaintainerCanModify == nil {
+ return false
+ }
+ return *p.MaintainerCanModify
+}
+
+// GetMergeable returns the Mergeable field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetMergeable() bool {
+ if p == nil || p.Mergeable == nil {
+ return false
+ }
+ return *p.Mergeable
+}
+
+// GetMergeableState returns the MergeableState field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetMergeableState() string {
+ if p == nil || p.MergeableState == nil {
+ return ""
+ }
+ return *p.MergeableState
+}
+
+// GetMergeCommitSHA returns the MergeCommitSHA field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetMergeCommitSHA() string {
+ if p == nil || p.MergeCommitSHA == nil {
+ return ""
+ }
+ return *p.MergeCommitSHA
+}
+
+// GetMerged returns the Merged field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetMerged() bool {
+ if p == nil || p.Merged == nil {
+ return false
+ }
+ return *p.Merged
+}
+
+// GetMergedAt returns the MergedAt field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetMergedAt() time.Time {
+ if p == nil || p.MergedAt == nil {
+ return time.Time{}
+ }
+ return *p.MergedAt
+}
+
+// GetMergedBy returns the MergedBy field.
+func (p *PullRequest) GetMergedBy() *User {
+ if p == nil {
+ return nil
+ }
+ return p.MergedBy
+}
+
+// GetMilestone returns the Milestone field.
+func (p *PullRequest) GetMilestone() *Milestone {
+ if p == nil {
+ return nil
+ }
+ return p.Milestone
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetNodeID() string {
+ if p == nil || p.NodeID == nil {
+ return ""
+ }
+ return *p.NodeID
+}
+
+// GetNumber returns the Number field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetNumber() int {
+ if p == nil || p.Number == nil {
+ return 0
+ }
+ return *p.Number
+}
+
+// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetPatchURL() string {
+ if p == nil || p.PatchURL == nil {
+ return ""
+ }
+ return *p.PatchURL
+}
+
+// GetReviewCommentsURL returns the ReviewCommentsURL field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetReviewCommentsURL() string {
+ if p == nil || p.ReviewCommentsURL == nil {
+ return ""
+ }
+ return *p.ReviewCommentsURL
+}
+
+// GetReviewCommentURL returns the ReviewCommentURL field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetReviewCommentURL() string {
+ if p == nil || p.ReviewCommentURL == nil {
+ return ""
+ }
+ return *p.ReviewCommentURL
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetState() string {
+ if p == nil || p.State == nil {
+ return ""
+ }
+ return *p.State
+}
+
+// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetStatusesURL() string {
+ if p == nil || p.StatusesURL == nil {
+ return ""
+ }
+ return *p.StatusesURL
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetTitle() string {
+ if p == nil || p.Title == nil {
+ return ""
+ }
+ return *p.Title
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetUpdatedAt() time.Time {
+ if p == nil || p.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *p.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *PullRequest) GetURL() string {
+ if p == nil || p.URL == nil {
+ return ""
+ }
+ return *p.URL
+}
+
+// GetUser returns the User field.
+func (p *PullRequest) GetUser() *User {
+ if p == nil {
+ return nil
+ }
+ return p.User
+}
+
+// GetLabel returns the Label field if it's non-nil, zero value otherwise.
+func (p *PullRequestBranch) GetLabel() string {
+ if p == nil || p.Label == nil {
+ return ""
+ }
+ return *p.Label
+}
+
+// GetRef returns the Ref field if it's non-nil, zero value otherwise.
+func (p *PullRequestBranch) GetRef() string {
+ if p == nil || p.Ref == nil {
+ return ""
+ }
+ return *p.Ref
+}
+
+// GetRepo returns the Repo field.
+func (p *PullRequestBranch) GetRepo() *Repository {
+ if p == nil {
+ return nil
+ }
+ return p.Repo
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (p *PullRequestBranch) GetSHA() string {
+ if p == nil || p.SHA == nil {
+ return ""
+ }
+ return *p.SHA
+}
+
+// GetUser returns the User field.
+func (p *PullRequestBranch) GetUser() *User {
+ if p == nil {
+ return nil
+ }
+ return p.User
+}
+
+// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetAuthorAssociation() string {
+ if p == nil || p.AuthorAssociation == nil {
+ return ""
+ }
+ return *p.AuthorAssociation
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetBody() string {
+ if p == nil || p.Body == nil {
+ return ""
+ }
+ return *p.Body
+}
+
+// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetCommitID() string {
+ if p == nil || p.CommitID == nil {
+ return ""
+ }
+ return *p.CommitID
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetCreatedAt() time.Time {
+ if p == nil || p.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *p.CreatedAt
+}
+
+// GetDiffHunk returns the DiffHunk field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetDiffHunk() string {
+ if p == nil || p.DiffHunk == nil {
+ return ""
+ }
+ return *p.DiffHunk
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetHTMLURL() string {
+ if p == nil || p.HTMLURL == nil {
+ return ""
+ }
+ return *p.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetID() int64 {
+ if p == nil || p.ID == nil {
+ return 0
+ }
+ return *p.ID
+}
+
+// GetInReplyTo returns the InReplyTo field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetInReplyTo() int64 {
+ if p == nil || p.InReplyTo == nil {
+ return 0
+ }
+ return *p.InReplyTo
+}
+
+// GetOriginalCommitID returns the OriginalCommitID field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetOriginalCommitID() string {
+ if p == nil || p.OriginalCommitID == nil {
+ return ""
+ }
+ return *p.OriginalCommitID
+}
+
+// GetOriginalPosition returns the OriginalPosition field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetOriginalPosition() int {
+ if p == nil || p.OriginalPosition == nil {
+ return 0
+ }
+ return *p.OriginalPosition
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetPath() string {
+ if p == nil || p.Path == nil {
+ return ""
+ }
+ return *p.Path
+}
+
+// GetPosition returns the Position field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetPosition() int {
+ if p == nil || p.Position == nil {
+ return 0
+ }
+ return *p.Position
+}
+
+// GetPullRequestReviewID returns the PullRequestReviewID field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetPullRequestReviewID() int64 {
+ if p == nil || p.PullRequestReviewID == nil {
+ return 0
+ }
+ return *p.PullRequestReviewID
+}
+
+// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetPullRequestURL() string {
+ if p == nil || p.PullRequestURL == nil {
+ return ""
+ }
+ return *p.PullRequestURL
+}
+
+// GetReactions returns the Reactions field.
+func (p *PullRequestComment) GetReactions() *Reactions {
+ if p == nil {
+ return nil
+ }
+ return p.Reactions
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetUpdatedAt() time.Time {
+ if p == nil || p.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *p.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetURL() string {
+ if p == nil || p.URL == nil {
+ return ""
+ }
+ return *p.URL
+}
+
+// GetUser returns the User field.
+func (p *PullRequestComment) GetUser() *User {
+ if p == nil {
+ return nil
+ }
+ return p.User
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (p *PullRequestEvent) GetAction() string {
+ if p == nil || p.Action == nil {
+ return ""
+ }
+ return *p.Action
+}
+
+// GetAssignee returns the Assignee field.
+func (p *PullRequestEvent) GetAssignee() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Assignee
+}
+
+// GetChanges returns the Changes field.
+func (p *PullRequestEvent) GetChanges() *EditChange {
+ if p == nil {
+ return nil
+ }
+ return p.Changes
+}
+
+// GetInstallation returns the Installation field.
+func (p *PullRequestEvent) GetInstallation() *Installation {
+ if p == nil {
+ return nil
+ }
+ return p.Installation
+}
+
+// GetLabel returns the Label field.
+func (p *PullRequestEvent) GetLabel() *Label {
+ if p == nil {
+ return nil
+ }
+ return p.Label
+}
+
+// GetNumber returns the Number field if it's non-nil, zero value otherwise.
+func (p *PullRequestEvent) GetNumber() int {
+ if p == nil || p.Number == nil {
+ return 0
+ }
+ return *p.Number
+}
+
+// GetOrganization returns the Organization field.
+func (p *PullRequestEvent) GetOrganization() *Organization {
+ if p == nil {
+ return nil
+ }
+ return p.Organization
+}
+
+// GetPullRequest returns the PullRequest field.
+func (p *PullRequestEvent) GetPullRequest() *PullRequest {
+ if p == nil {
+ return nil
+ }
+ return p.PullRequest
+}
+
+// GetRepo returns the Repo field.
+func (p *PullRequestEvent) GetRepo() *Repository {
+ if p == nil {
+ return nil
+ }
+ return p.Repo
+}
+
+// GetRequestedReviewer returns the RequestedReviewer field.
+func (p *PullRequestEvent) GetRequestedReviewer() *User {
+ if p == nil {
+ return nil
+ }
+ return p.RequestedReviewer
+}
+
+// GetSender returns the Sender field.
+func (p *PullRequestEvent) GetSender() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Sender
+}
+
+// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise.
+func (p *PullRequestLinks) GetDiffURL() string {
+ if p == nil || p.DiffURL == nil {
+ return ""
+ }
+ return *p.DiffURL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (p *PullRequestLinks) GetHTMLURL() string {
+ if p == nil || p.HTMLURL == nil {
+ return ""
+ }
+ return *p.HTMLURL
+}
+
+// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise.
+func (p *PullRequestLinks) GetPatchURL() string {
+ if p == nil || p.PatchURL == nil {
+ return ""
+ }
+ return *p.PatchURL
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *PullRequestLinks) GetURL() string {
+ if p == nil || p.URL == nil {
+ return ""
+ }
+ return *p.URL
+}
+
+// GetMerged returns the Merged field if it's non-nil, zero value otherwise.
+func (p *PullRequestMergeResult) GetMerged() bool {
+ if p == nil || p.Merged == nil {
+ return false
+ }
+ return *p.Merged
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (p *PullRequestMergeResult) GetMessage() string {
+ if p == nil || p.Message == nil {
+ return ""
+ }
+ return *p.Message
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (p *PullRequestMergeResult) GetSHA() string {
+ if p == nil || p.SHA == nil {
+ return ""
+ }
+ return *p.SHA
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (p *PullRequestReview) GetBody() string {
+ if p == nil || p.Body == nil {
+ return ""
+ }
+ return *p.Body
+}
+
+// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise.
+func (p *PullRequestReview) GetCommitID() string {
+ if p == nil || p.CommitID == nil {
+ return ""
+ }
+ return *p.CommitID
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (p *PullRequestReview) GetHTMLURL() string {
+ if p == nil || p.HTMLURL == nil {
+ return ""
+ }
+ return *p.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *PullRequestReview) GetID() int64 {
+ if p == nil || p.ID == nil {
+ return 0
+ }
+ return *p.ID
+}
+
+// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise.
+func (p *PullRequestReview) GetPullRequestURL() string {
+ if p == nil || p.PullRequestURL == nil {
+ return ""
+ }
+ return *p.PullRequestURL
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (p *PullRequestReview) GetState() string {
+ if p == nil || p.State == nil {
+ return ""
+ }
+ return *p.State
+}
+
+// GetSubmittedAt returns the SubmittedAt field if it's non-nil, zero value otherwise.
+func (p *PullRequestReview) GetSubmittedAt() time.Time {
+ if p == nil || p.SubmittedAt == nil {
+ return time.Time{}
+ }
+ return *p.SubmittedAt
+}
+
+// GetUser returns the User field.
+func (p *PullRequestReview) GetUser() *User {
+ if p == nil {
+ return nil
+ }
+ return p.User
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (p *PullRequestReviewCommentEvent) GetAction() string {
+ if p == nil || p.Action == nil {
+ return ""
+ }
+ return *p.Action
+}
+
+// GetChanges returns the Changes field.
+func (p *PullRequestReviewCommentEvent) GetChanges() *EditChange {
+ if p == nil {
+ return nil
+ }
+ return p.Changes
+}
+
+// GetComment returns the Comment field.
+func (p *PullRequestReviewCommentEvent) GetComment() *PullRequestComment {
+ if p == nil {
+ return nil
+ }
+ return p.Comment
+}
+
+// GetInstallation returns the Installation field.
+func (p *PullRequestReviewCommentEvent) GetInstallation() *Installation {
+ if p == nil {
+ return nil
+ }
+ return p.Installation
+}
+
+// GetPullRequest returns the PullRequest field.
+func (p *PullRequestReviewCommentEvent) GetPullRequest() *PullRequest {
+ if p == nil {
+ return nil
+ }
+ return p.PullRequest
+}
+
+// GetRepo returns the Repo field.
+func (p *PullRequestReviewCommentEvent) GetRepo() *Repository {
+ if p == nil {
+ return nil
+ }
+ return p.Repo
+}
+
+// GetSender returns the Sender field.
+func (p *PullRequestReviewCommentEvent) GetSender() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Sender
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (p *PullRequestReviewDismissalRequest) GetMessage() string {
+ if p == nil || p.Message == nil {
+ return ""
+ }
+ return *p.Message
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (p *PullRequestReviewEvent) GetAction() string {
+ if p == nil || p.Action == nil {
+ return ""
+ }
+ return *p.Action
+}
+
+// GetInstallation returns the Installation field.
+func (p *PullRequestReviewEvent) GetInstallation() *Installation {
+ if p == nil {
+ return nil
+ }
+ return p.Installation
+}
+
+// GetOrganization returns the Organization field.
+func (p *PullRequestReviewEvent) GetOrganization() *Organization {
+ if p == nil {
+ return nil
+ }
+ return p.Organization
+}
+
+// GetPullRequest returns the PullRequest field.
+func (p *PullRequestReviewEvent) GetPullRequest() *PullRequest {
+ if p == nil {
+ return nil
+ }
+ return p.PullRequest
+}
+
+// GetRepo returns the Repo field.
+func (p *PullRequestReviewEvent) GetRepo() *Repository {
+ if p == nil {
+ return nil
+ }
+ return p.Repo
+}
+
+// GetReview returns the Review field.
+func (p *PullRequestReviewEvent) GetReview() *PullRequestReview {
+ if p == nil {
+ return nil
+ }
+ return p.Review
+}
+
+// GetSender returns the Sender field.
+func (p *PullRequestReviewEvent) GetSender() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Sender
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (p *PullRequestReviewRequest) GetBody() string {
+ if p == nil || p.Body == nil {
+ return ""
+ }
+ return *p.Body
+}
+
+// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise.
+func (p *PullRequestReviewRequest) GetCommitID() string {
+ if p == nil || p.CommitID == nil {
+ return ""
+ }
+ return *p.CommitID
+}
+
+// GetEvent returns the Event field if it's non-nil, zero value otherwise.
+func (p *PullRequestReviewRequest) GetEvent() string {
+ if p == nil || p.Event == nil {
+ return ""
+ }
+ return *p.Event
+}
+
+// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field.
+func (p *PullRequestReviewsEnforcementRequest) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest {
+ if p == nil {
+ return nil
+ }
+ return p.DismissalRestrictionsRequest
+}
+
+// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field.
+func (p *PullRequestReviewsEnforcementUpdate) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest {
+ if p == nil {
+ return nil
+ }
+ return p.DismissalRestrictionsRequest
+}
+
+// GetDismissStaleReviews returns the DismissStaleReviews field if it's non-nil, zero value otherwise.
+func (p *PullRequestReviewsEnforcementUpdate) GetDismissStaleReviews() bool {
+ if p == nil || p.DismissStaleReviews == nil {
+ return false
+ }
+ return *p.DismissStaleReviews
+}
+
+// GetMergablePulls returns the MergablePulls field if it's non-nil, zero value otherwise.
+func (p *PullStats) GetMergablePulls() int {
+ if p == nil || p.MergablePulls == nil {
+ return 0
+ }
+ return *p.MergablePulls
+}
+
+// GetMergedPulls returns the MergedPulls field if it's non-nil, zero value otherwise.
+func (p *PullStats) GetMergedPulls() int {
+ if p == nil || p.MergedPulls == nil {
+ return 0
+ }
+ return *p.MergedPulls
+}
+
+// GetTotalPulls returns the TotalPulls field if it's non-nil, zero value otherwise.
+func (p *PullStats) GetTotalPulls() int {
+ if p == nil || p.TotalPulls == nil {
+ return 0
+ }
+ return *p.TotalPulls
+}
+
+// GetUnmergablePulls returns the UnmergablePulls field if it's non-nil, zero value otherwise.
+func (p *PullStats) GetUnmergablePulls() int {
+ if p == nil || p.UnmergablePulls == nil {
+ return 0
+ }
+ return *p.UnmergablePulls
+}
+
+// GetCommits returns the Commits field if it's non-nil, zero value otherwise.
+func (p *PunchCard) GetCommits() int {
+ if p == nil || p.Commits == nil {
+ return 0
+ }
+ return *p.Commits
+}
+
+// GetDay returns the Day field if it's non-nil, zero value otherwise.
+func (p *PunchCard) GetDay() int {
+ if p == nil || p.Day == nil {
+ return 0
+ }
+ return *p.Day
+}
+
+// GetHour returns the Hour field if it's non-nil, zero value otherwise.
+func (p *PunchCard) GetHour() int {
+ if p == nil || p.Hour == nil {
+ return 0
+ }
+ return *p.Hour
+}
+
+// GetAfter returns the After field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetAfter() string {
+ if p == nil || p.After == nil {
+ return ""
+ }
+ return *p.After
+}
+
+// GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetBaseRef() string {
+ if p == nil || p.BaseRef == nil {
+ return ""
+ }
+ return *p.BaseRef
+}
+
+// GetBefore returns the Before field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetBefore() string {
+ if p == nil || p.Before == nil {
+ return ""
+ }
+ return *p.Before
+}
+
+// GetCompare returns the Compare field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetCompare() string {
+ if p == nil || p.Compare == nil {
+ return ""
+ }
+ return *p.Compare
+}
+
+// GetCreated returns the Created field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetCreated() bool {
+ if p == nil || p.Created == nil {
+ return false
+ }
+ return *p.Created
+}
+
+// GetDeleted returns the Deleted field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetDeleted() bool {
+ if p == nil || p.Deleted == nil {
+ return false
+ }
+ return *p.Deleted
+}
+
+// GetDistinctSize returns the DistinctSize field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetDistinctSize() int {
+ if p == nil || p.DistinctSize == nil {
+ return 0
+ }
+ return *p.DistinctSize
+}
+
+// GetForced returns the Forced field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetForced() bool {
+ if p == nil || p.Forced == nil {
+ return false
+ }
+ return *p.Forced
+}
+
+// GetHead returns the Head field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetHead() string {
+ if p == nil || p.Head == nil {
+ return ""
+ }
+ return *p.Head
+}
+
+// GetHeadCommit returns the HeadCommit field.
+func (p *PushEvent) GetHeadCommit() *PushEventCommit {
+ if p == nil {
+ return nil
+ }
+ return p.HeadCommit
+}
+
+// GetInstallation returns the Installation field.
+func (p *PushEvent) GetInstallation() *Installation {
+ if p == nil {
+ return nil
+ }
+ return p.Installation
+}
+
+// GetPusher returns the Pusher field.
+func (p *PushEvent) GetPusher() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Pusher
+}
+
+// GetPushID returns the PushID field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetPushID() int64 {
+ if p == nil || p.PushID == nil {
+ return 0
+ }
+ return *p.PushID
+}
+
+// GetRef returns the Ref field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetRef() string {
+ if p == nil || p.Ref == nil {
+ return ""
+ }
+ return *p.Ref
+}
+
+// GetRepo returns the Repo field.
+func (p *PushEvent) GetRepo() *PushEventRepository {
+ if p == nil {
+ return nil
+ }
+ return p.Repo
+}
+
+// GetSender returns the Sender field.
+func (p *PushEvent) GetSender() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Sender
+}
+
+// GetSize returns the Size field if it's non-nil, zero value otherwise.
+func (p *PushEvent) GetSize() int {
+ if p == nil || p.Size == nil {
+ return 0
+ }
+ return *p.Size
+}
+
+// GetAuthor returns the Author field.
+func (p *PushEventCommit) GetAuthor() *CommitAuthor {
+ if p == nil {
+ return nil
+ }
+ return p.Author
+}
+
+// GetCommitter returns the Committer field.
+func (p *PushEventCommit) GetCommitter() *CommitAuthor {
+ if p == nil {
+ return nil
+ }
+ return p.Committer
+}
+
+// GetDistinct returns the Distinct field if it's non-nil, zero value otherwise.
+func (p *PushEventCommit) GetDistinct() bool {
+ if p == nil || p.Distinct == nil {
+ return false
+ }
+ return *p.Distinct
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *PushEventCommit) GetID() string {
+ if p == nil || p.ID == nil {
+ return ""
+ }
+ return *p.ID
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (p *PushEventCommit) GetMessage() string {
+ if p == nil || p.Message == nil {
+ return ""
+ }
+ return *p.Message
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (p *PushEventCommit) GetSHA() string {
+ if p == nil || p.SHA == nil {
+ return ""
+ }
+ return *p.SHA
+}
+
+// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise.
+func (p *PushEventCommit) GetTimestamp() Timestamp {
+ if p == nil || p.Timestamp == nil {
+ return Timestamp{}
+ }
+ return *p.Timestamp
+}
+
+// GetTreeID returns the TreeID field if it's non-nil, zero value otherwise.
+func (p *PushEventCommit) GetTreeID() string {
+ if p == nil || p.TreeID == nil {
+ return ""
+ }
+ return *p.TreeID
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *PushEventCommit) GetURL() string {
+ if p == nil || p.URL == nil {
+ return ""
+ }
+ return *p.URL
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (p *PushEventRepoOwner) GetEmail() string {
+ if p == nil || p.Email == nil {
+ return ""
+ }
+ return *p.Email
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (p *PushEventRepoOwner) GetName() string {
+ if p == nil || p.Name == nil {
+ return ""
+ }
+ return *p.Name
+}
+
+// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetArchiveURL() string {
+ if p == nil || p.ArchiveURL == nil {
+ return ""
+ }
+ return *p.ArchiveURL
+}
+
+// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetCloneURL() string {
+ if p == nil || p.CloneURL == nil {
+ return ""
+ }
+ return *p.CloneURL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetCreatedAt() Timestamp {
+ if p == nil || p.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *p.CreatedAt
+}
+
+// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetDefaultBranch() string {
+ if p == nil || p.DefaultBranch == nil {
+ return ""
+ }
+ return *p.DefaultBranch
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetDescription() string {
+ if p == nil || p.Description == nil {
+ return ""
+ }
+ return *p.Description
+}
+
+// GetFork returns the Fork field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetFork() bool {
+ if p == nil || p.Fork == nil {
+ return false
+ }
+ return *p.Fork
+}
+
+// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetForksCount() int {
+ if p == nil || p.ForksCount == nil {
+ return 0
+ }
+ return *p.ForksCount
+}
+
+// GetFullName returns the FullName field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetFullName() string {
+ if p == nil || p.FullName == nil {
+ return ""
+ }
+ return *p.FullName
+}
+
+// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetGitURL() string {
+ if p == nil || p.GitURL == nil {
+ return ""
+ }
+ return *p.GitURL
+}
+
+// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetHasDownloads() bool {
+ if p == nil || p.HasDownloads == nil {
+ return false
+ }
+ return *p.HasDownloads
+}
+
+// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetHasIssues() bool {
+ if p == nil || p.HasIssues == nil {
+ return false
+ }
+ return *p.HasIssues
+}
+
+// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetHasPages() bool {
+ if p == nil || p.HasPages == nil {
+ return false
+ }
+ return *p.HasPages
+}
+
+// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetHasWiki() bool {
+ if p == nil || p.HasWiki == nil {
+ return false
+ }
+ return *p.HasWiki
+}
+
+// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetHomepage() string {
+ if p == nil || p.Homepage == nil {
+ return ""
+ }
+ return *p.Homepage
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetHTMLURL() string {
+ if p == nil || p.HTMLURL == nil {
+ return ""
+ }
+ return *p.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetID() int64 {
+ if p == nil || p.ID == nil {
+ return 0
+ }
+ return *p.ID
+}
+
+// GetLanguage returns the Language field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetLanguage() string {
+ if p == nil || p.Language == nil {
+ return ""
+ }
+ return *p.Language
+}
+
+// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetMasterBranch() string {
+ if p == nil || p.MasterBranch == nil {
+ return ""
+ }
+ return *p.MasterBranch
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetName() string {
+ if p == nil || p.Name == nil {
+ return ""
+ }
+ return *p.Name
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetNodeID() string {
+ if p == nil || p.NodeID == nil {
+ return ""
+ }
+ return *p.NodeID
+}
+
+// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetOpenIssuesCount() int {
+ if p == nil || p.OpenIssuesCount == nil {
+ return 0
+ }
+ return *p.OpenIssuesCount
+}
+
+// GetOrganization returns the Organization field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetOrganization() string {
+ if p == nil || p.Organization == nil {
+ return ""
+ }
+ return *p.Organization
+}
+
+// GetOwner returns the Owner field.
+func (p *PushEventRepository) GetOwner() *User {
+ if p == nil {
+ return nil
+ }
+ return p.Owner
+}
+
+// GetPrivate returns the Private field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetPrivate() bool {
+ if p == nil || p.Private == nil {
+ return false
+ }
+ return *p.Private
+}
+
+// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetPushedAt() Timestamp {
+ if p == nil || p.PushedAt == nil {
+ return Timestamp{}
+ }
+ return *p.PushedAt
+}
+
+// GetSize returns the Size field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetSize() int {
+ if p == nil || p.Size == nil {
+ return 0
+ }
+ return *p.Size
+}
+
+// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetSSHURL() string {
+ if p == nil || p.SSHURL == nil {
+ return ""
+ }
+ return *p.SSHURL
+}
+
+// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetStargazersCount() int {
+ if p == nil || p.StargazersCount == nil {
+ return 0
+ }
+ return *p.StargazersCount
+}
+
+// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetStatusesURL() string {
+ if p == nil || p.StatusesURL == nil {
+ return ""
+ }
+ return *p.StatusesURL
+}
+
+// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetSVNURL() string {
+ if p == nil || p.SVNURL == nil {
+ return ""
+ }
+ return *p.SVNURL
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetUpdatedAt() Timestamp {
+ if p == nil || p.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *p.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetURL() string {
+ if p == nil || p.URL == nil {
+ return ""
+ }
+ return *p.URL
+}
+
+// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise.
+func (p *PushEventRepository) GetWatchersCount() int {
+ if p == nil || p.WatchersCount == nil {
+ return 0
+ }
+ return *p.WatchersCount
+}
+
+// GetCore returns the Core field.
+func (r *RateLimits) GetCore() *Rate {
+ if r == nil {
+ return nil
+ }
+ return r.Core
+}
+
+// GetSearch returns the Search field.
+func (r *RateLimits) GetSearch() *Rate {
+ if r == nil {
+ return nil
+ }
+ return r.Search
+}
+
+// GetContent returns the Content field if it's non-nil, zero value otherwise.
+func (r *Reaction) GetContent() string {
+ if r == nil || r.Content == nil {
+ return ""
+ }
+ return *r.Content
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (r *Reaction) GetID() int64 {
+ if r == nil || r.ID == nil {
+ return 0
+ }
+ return *r.ID
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (r *Reaction) GetNodeID() string {
+ if r == nil || r.NodeID == nil {
+ return ""
+ }
+ return *r.NodeID
+}
+
+// GetUser returns the User field.
+func (r *Reaction) GetUser() *User {
+ if r == nil {
+ return nil
+ }
+ return r.User
+}
+
+// GetConfused returns the Confused field if it's non-nil, zero value otherwise.
+func (r *Reactions) GetConfused() int {
+ if r == nil || r.Confused == nil {
+ return 0
+ }
+ return *r.Confused
+}
+
+// GetHeart returns the Heart field if it's non-nil, zero value otherwise.
+func (r *Reactions) GetHeart() int {
+ if r == nil || r.Heart == nil {
+ return 0
+ }
+ return *r.Heart
+}
+
+// GetHooray returns the Hooray field if it's non-nil, zero value otherwise.
+func (r *Reactions) GetHooray() int {
+ if r == nil || r.Hooray == nil {
+ return 0
+ }
+ return *r.Hooray
+}
+
+// GetLaugh returns the Laugh field if it's non-nil, zero value otherwise.
+func (r *Reactions) GetLaugh() int {
+ if r == nil || r.Laugh == nil {
+ return 0
+ }
+ return *r.Laugh
+}
+
+// GetMinusOne returns the MinusOne field if it's non-nil, zero value otherwise.
+func (r *Reactions) GetMinusOne() int {
+ if r == nil || r.MinusOne == nil {
+ return 0
+ }
+ return *r.MinusOne
+}
+
+// GetPlusOne returns the PlusOne field if it's non-nil, zero value otherwise.
+func (r *Reactions) GetPlusOne() int {
+ if r == nil || r.PlusOne == nil {
+ return 0
+ }
+ return *r.PlusOne
+}
+
+// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise.
+func (r *Reactions) GetTotalCount() int {
+ if r == nil || r.TotalCount == nil {
+ return 0
+ }
+ return *r.TotalCount
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *Reactions) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (r *Reference) GetNodeID() string {
+ if r == nil || r.NodeID == nil {
+ return ""
+ }
+ return *r.NodeID
+}
+
+// GetObject returns the Object field.
+func (r *Reference) GetObject() *GitObject {
+ if r == nil {
+ return nil
+ }
+ return r.Object
+}
+
+// GetRef returns the Ref field if it's non-nil, zero value otherwise.
+func (r *Reference) GetRef() string {
+ if r == nil || r.Ref == nil {
+ return ""
+ }
+ return *r.Ref
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *Reference) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetBrowserDownloadURL returns the BrowserDownloadURL field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetBrowserDownloadURL() string {
+ if r == nil || r.BrowserDownloadURL == nil {
+ return ""
+ }
+ return *r.BrowserDownloadURL
+}
+
+// GetContentType returns the ContentType field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetContentType() string {
+ if r == nil || r.ContentType == nil {
+ return ""
+ }
+ return *r.ContentType
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetCreatedAt() Timestamp {
+ if r == nil || r.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *r.CreatedAt
+}
+
+// GetDownloadCount returns the DownloadCount field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetDownloadCount() int {
+ if r == nil || r.DownloadCount == nil {
+ return 0
+ }
+ return *r.DownloadCount
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetID() int64 {
+ if r == nil || r.ID == nil {
+ return 0
+ }
+ return *r.ID
+}
+
+// GetLabel returns the Label field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetLabel() string {
+ if r == nil || r.Label == nil {
+ return ""
+ }
+ return *r.Label
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetName() string {
+ if r == nil || r.Name == nil {
+ return ""
+ }
+ return *r.Name
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetNodeID() string {
+ if r == nil || r.NodeID == nil {
+ return ""
+ }
+ return *r.NodeID
+}
+
+// GetSize returns the Size field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetSize() int {
+ if r == nil || r.Size == nil {
+ return 0
+ }
+ return *r.Size
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetState() string {
+ if r == nil || r.State == nil {
+ return ""
+ }
+ return *r.State
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetUpdatedAt() Timestamp {
+ if r == nil || r.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *r.UpdatedAt
+}
+
+// GetUploader returns the Uploader field.
+func (r *ReleaseAsset) GetUploader() *User {
+ if r == nil {
+ return nil
+ }
+ return r.Uploader
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *ReleaseAsset) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (r *ReleaseEvent) GetAction() string {
+ if r == nil || r.Action == nil {
+ return ""
+ }
+ return *r.Action
+}
+
+// GetInstallation returns the Installation field.
+func (r *ReleaseEvent) GetInstallation() *Installation {
+ if r == nil {
+ return nil
+ }
+ return r.Installation
+}
+
+// GetRelease returns the Release field.
+func (r *ReleaseEvent) GetRelease() *RepositoryRelease {
+ if r == nil {
+ return nil
+ }
+ return r.Release
+}
+
+// GetRepo returns the Repo field.
+func (r *ReleaseEvent) GetRepo() *Repository {
+ if r == nil {
+ return nil
+ }
+ return r.Repo
+}
+
+// GetSender returns the Sender field.
+func (r *ReleaseEvent) GetSender() *User {
+ if r == nil {
+ return nil
+ }
+ return r.Sender
+}
+
+// GetFrom returns the From field if it's non-nil, zero value otherwise.
+func (r *Rename) GetFrom() string {
+ if r == nil || r.From == nil {
+ return ""
+ }
+ return *r.From
+}
+
+// GetTo returns the To field if it's non-nil, zero value otherwise.
+func (r *Rename) GetTo() string {
+ if r == nil || r.To == nil {
+ return ""
+ }
+ return *r.To
+}
+
+// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise.
+func (r *RepositoriesSearchResult) GetIncompleteResults() bool {
+ if r == nil || r.IncompleteResults == nil {
+ return false
+ }
+ return *r.IncompleteResults
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (r *RepositoriesSearchResult) GetTotal() int {
+ if r == nil || r.Total == nil {
+ return 0
+ }
+ return *r.Total
+}
+
+// GetAllowMergeCommit returns the AllowMergeCommit field if it's non-nil, zero value otherwise.
+func (r *Repository) GetAllowMergeCommit() bool {
+ if r == nil || r.AllowMergeCommit == nil {
+ return false
+ }
+ return *r.AllowMergeCommit
+}
+
+// GetAllowRebaseMerge returns the AllowRebaseMerge field if it's non-nil, zero value otherwise.
+func (r *Repository) GetAllowRebaseMerge() bool {
+ if r == nil || r.AllowRebaseMerge == nil {
+ return false
+ }
+ return *r.AllowRebaseMerge
+}
+
+// GetAllowSquashMerge returns the AllowSquashMerge field if it's non-nil, zero value otherwise.
+func (r *Repository) GetAllowSquashMerge() bool {
+ if r == nil || r.AllowSquashMerge == nil {
+ return false
+ }
+ return *r.AllowSquashMerge
+}
+
+// GetArchived returns the Archived field if it's non-nil, zero value otherwise.
+func (r *Repository) GetArchived() bool {
+ if r == nil || r.Archived == nil {
+ return false
+ }
+ return *r.Archived
+}
+
+// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetArchiveURL() string {
+ if r == nil || r.ArchiveURL == nil {
+ return ""
+ }
+ return *r.ArchiveURL
+}
+
+// GetAssigneesURL returns the AssigneesURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetAssigneesURL() string {
+ if r == nil || r.AssigneesURL == nil {
+ return ""
+ }
+ return *r.AssigneesURL
+}
+
+// GetAutoInit returns the AutoInit field if it's non-nil, zero value otherwise.
+func (r *Repository) GetAutoInit() bool {
+ if r == nil || r.AutoInit == nil {
+ return false
+ }
+ return *r.AutoInit
+}
+
+// GetBlobsURL returns the BlobsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetBlobsURL() string {
+ if r == nil || r.BlobsURL == nil {
+ return ""
+ }
+ return *r.BlobsURL
+}
+
+// GetBranchesURL returns the BranchesURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetBranchesURL() string {
+ if r == nil || r.BranchesURL == nil {
+ return ""
+ }
+ return *r.BranchesURL
+}
+
+// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetCloneURL() string {
+ if r == nil || r.CloneURL == nil {
+ return ""
+ }
+ return *r.CloneURL
+}
+
+// GetCodeOfConduct returns the CodeOfConduct field.
+func (r *Repository) GetCodeOfConduct() *CodeOfConduct {
+ if r == nil {
+ return nil
+ }
+ return r.CodeOfConduct
+}
+
+// GetCollaboratorsURL returns the CollaboratorsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetCollaboratorsURL() string {
+ if r == nil || r.CollaboratorsURL == nil {
+ return ""
+ }
+ return *r.CollaboratorsURL
+}
+
+// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetCommentsURL() string {
+ if r == nil || r.CommentsURL == nil {
+ return ""
+ }
+ return *r.CommentsURL
+}
+
+// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetCommitsURL() string {
+ if r == nil || r.CommitsURL == nil {
+ return ""
+ }
+ return *r.CommitsURL
+}
+
+// GetCompareURL returns the CompareURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetCompareURL() string {
+ if r == nil || r.CompareURL == nil {
+ return ""
+ }
+ return *r.CompareURL
+}
+
+// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetContentsURL() string {
+ if r == nil || r.ContentsURL == nil {
+ return ""
+ }
+ return *r.ContentsURL
+}
+
+// GetContributorsURL returns the ContributorsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetContributorsURL() string {
+ if r == nil || r.ContributorsURL == nil {
+ return ""
+ }
+ return *r.ContributorsURL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (r *Repository) GetCreatedAt() Timestamp {
+ if r == nil || r.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *r.CreatedAt
+}
+
+// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise.
+func (r *Repository) GetDefaultBranch() string {
+ if r == nil || r.DefaultBranch == nil {
+ return ""
+ }
+ return *r.DefaultBranch
+}
+
+// GetDeploymentsURL returns the DeploymentsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetDeploymentsURL() string {
+ if r == nil || r.DeploymentsURL == nil {
+ return ""
+ }
+ return *r.DeploymentsURL
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (r *Repository) GetDescription() string {
+ if r == nil || r.Description == nil {
+ return ""
+ }
+ return *r.Description
+}
+
+// GetDownloadsURL returns the DownloadsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetDownloadsURL() string {
+ if r == nil || r.DownloadsURL == nil {
+ return ""
+ }
+ return *r.DownloadsURL
+}
+
+// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetEventsURL() string {
+ if r == nil || r.EventsURL == nil {
+ return ""
+ }
+ return *r.EventsURL
+}
+
+// GetFork returns the Fork field if it's non-nil, zero value otherwise.
+func (r *Repository) GetFork() bool {
+ if r == nil || r.Fork == nil {
+ return false
+ }
+ return *r.Fork
+}
+
+// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise.
+func (r *Repository) GetForksCount() int {
+ if r == nil || r.ForksCount == nil {
+ return 0
+ }
+ return *r.ForksCount
+}
+
+// GetForksURL returns the ForksURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetForksURL() string {
+ if r == nil || r.ForksURL == nil {
+ return ""
+ }
+ return *r.ForksURL
+}
+
+// GetFullName returns the FullName field if it's non-nil, zero value otherwise.
+func (r *Repository) GetFullName() string {
+ if r == nil || r.FullName == nil {
+ return ""
+ }
+ return *r.FullName
+}
+
+// GetGitCommitsURL returns the GitCommitsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetGitCommitsURL() string {
+ if r == nil || r.GitCommitsURL == nil {
+ return ""
+ }
+ return *r.GitCommitsURL
+}
+
+// GetGitignoreTemplate returns the GitignoreTemplate field if it's non-nil, zero value otherwise.
+func (r *Repository) GetGitignoreTemplate() string {
+ if r == nil || r.GitignoreTemplate == nil {
+ return ""
+ }
+ return *r.GitignoreTemplate
+}
+
+// GetGitRefsURL returns the GitRefsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetGitRefsURL() string {
+ if r == nil || r.GitRefsURL == nil {
+ return ""
+ }
+ return *r.GitRefsURL
+}
+
+// GetGitTagsURL returns the GitTagsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetGitTagsURL() string {
+ if r == nil || r.GitTagsURL == nil {
+ return ""
+ }
+ return *r.GitTagsURL
+}
+
+// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetGitURL() string {
+ if r == nil || r.GitURL == nil {
+ return ""
+ }
+ return *r.GitURL
+}
+
+// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise.
+func (r *Repository) GetHasDownloads() bool {
+ if r == nil || r.HasDownloads == nil {
+ return false
+ }
+ return *r.HasDownloads
+}
+
+// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise.
+func (r *Repository) GetHasIssues() bool {
+ if r == nil || r.HasIssues == nil {
+ return false
+ }
+ return *r.HasIssues
+}
+
+// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise.
+func (r *Repository) GetHasPages() bool {
+ if r == nil || r.HasPages == nil {
+ return false
+ }
+ return *r.HasPages
+}
+
+// GetHasProjects returns the HasProjects field if it's non-nil, zero value otherwise.
+func (r *Repository) GetHasProjects() bool {
+ if r == nil || r.HasProjects == nil {
+ return false
+ }
+ return *r.HasProjects
+}
+
+// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise.
+func (r *Repository) GetHasWiki() bool {
+ if r == nil || r.HasWiki == nil {
+ return false
+ }
+ return *r.HasWiki
+}
+
+// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise.
+func (r *Repository) GetHomepage() string {
+ if r == nil || r.Homepage == nil {
+ return ""
+ }
+ return *r.Homepage
+}
+
+// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetHooksURL() string {
+ if r == nil || r.HooksURL == nil {
+ return ""
+ }
+ return *r.HooksURL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetHTMLURL() string {
+ if r == nil || r.HTMLURL == nil {
+ return ""
+ }
+ return *r.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (r *Repository) GetID() int64 {
+ if r == nil || r.ID == nil {
+ return 0
+ }
+ return *r.ID
+}
+
+// GetIssueCommentURL returns the IssueCommentURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetIssueCommentURL() string {
+ if r == nil || r.IssueCommentURL == nil {
+ return ""
+ }
+ return *r.IssueCommentURL
+}
+
+// GetIssueEventsURL returns the IssueEventsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetIssueEventsURL() string {
+ if r == nil || r.IssueEventsURL == nil {
+ return ""
+ }
+ return *r.IssueEventsURL
+}
+
+// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetIssuesURL() string {
+ if r == nil || r.IssuesURL == nil {
+ return ""
+ }
+ return *r.IssuesURL
+}
+
+// GetKeysURL returns the KeysURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetKeysURL() string {
+ if r == nil || r.KeysURL == nil {
+ return ""
+ }
+ return *r.KeysURL
+}
+
+// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetLabelsURL() string {
+ if r == nil || r.LabelsURL == nil {
+ return ""
+ }
+ return *r.LabelsURL
+}
+
+// GetLanguage returns the Language field if it's non-nil, zero value otherwise.
+func (r *Repository) GetLanguage() string {
+ if r == nil || r.Language == nil {
+ return ""
+ }
+ return *r.Language
+}
+
+// GetLanguagesURL returns the LanguagesURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetLanguagesURL() string {
+ if r == nil || r.LanguagesURL == nil {
+ return ""
+ }
+ return *r.LanguagesURL
+}
+
+// GetLicense returns the License field.
+func (r *Repository) GetLicense() *License {
+ if r == nil {
+ return nil
+ }
+ return r.License
+}
+
+// GetLicenseTemplate returns the LicenseTemplate field if it's non-nil, zero value otherwise.
+func (r *Repository) GetLicenseTemplate() string {
+ if r == nil || r.LicenseTemplate == nil {
+ return ""
+ }
+ return *r.LicenseTemplate
+}
+
+// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise.
+func (r *Repository) GetMasterBranch() string {
+ if r == nil || r.MasterBranch == nil {
+ return ""
+ }
+ return *r.MasterBranch
+}
+
+// GetMergesURL returns the MergesURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetMergesURL() string {
+ if r == nil || r.MergesURL == nil {
+ return ""
+ }
+ return *r.MergesURL
+}
+
+// GetMilestonesURL returns the MilestonesURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetMilestonesURL() string {
+ if r == nil || r.MilestonesURL == nil {
+ return ""
+ }
+ return *r.MilestonesURL
+}
+
+// GetMirrorURL returns the MirrorURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetMirrorURL() string {
+ if r == nil || r.MirrorURL == nil {
+ return ""
+ }
+ return *r.MirrorURL
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (r *Repository) GetName() string {
+ if r == nil || r.Name == nil {
+ return ""
+ }
+ return *r.Name
+}
+
+// GetNetworkCount returns the NetworkCount field if it's non-nil, zero value otherwise.
+func (r *Repository) GetNetworkCount() int {
+ if r == nil || r.NetworkCount == nil {
+ return 0
+ }
+ return *r.NetworkCount
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (r *Repository) GetNodeID() string {
+ if r == nil || r.NodeID == nil {
+ return ""
+ }
+ return *r.NodeID
+}
+
+// GetNotificationsURL returns the NotificationsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetNotificationsURL() string {
+ if r == nil || r.NotificationsURL == nil {
+ return ""
+ }
+ return *r.NotificationsURL
+}
+
+// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise.
+func (r *Repository) GetOpenIssuesCount() int {
+ if r == nil || r.OpenIssuesCount == nil {
+ return 0
+ }
+ return *r.OpenIssuesCount
+}
+
+// GetOrganization returns the Organization field.
+func (r *Repository) GetOrganization() *Organization {
+ if r == nil {
+ return nil
+ }
+ return r.Organization
+}
+
+// GetOwner returns the Owner field.
+func (r *Repository) GetOwner() *User {
+ if r == nil {
+ return nil
+ }
+ return r.Owner
+}
+
+// GetParent returns the Parent field.
+func (r *Repository) GetParent() *Repository {
+ if r == nil {
+ return nil
+ }
+ return r.Parent
+}
+
+// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise.
+func (r *Repository) GetPermissions() map[string]bool {
+ if r == nil || r.Permissions == nil {
+ return map[string]bool{}
+ }
+ return *r.Permissions
+}
+
+// GetPrivate returns the Private field if it's non-nil, zero value otherwise.
+func (r *Repository) GetPrivate() bool {
+ if r == nil || r.Private == nil {
+ return false
+ }
+ return *r.Private
+}
+
+// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetPullsURL() string {
+ if r == nil || r.PullsURL == nil {
+ return ""
+ }
+ return *r.PullsURL
+}
+
+// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise.
+func (r *Repository) GetPushedAt() Timestamp {
+ if r == nil || r.PushedAt == nil {
+ return Timestamp{}
+ }
+ return *r.PushedAt
+}
+
+// GetReleasesURL returns the ReleasesURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetReleasesURL() string {
+ if r == nil || r.ReleasesURL == nil {
+ return ""
+ }
+ return *r.ReleasesURL
+}
+
+// GetSize returns the Size field if it's non-nil, zero value otherwise.
+func (r *Repository) GetSize() int {
+ if r == nil || r.Size == nil {
+ return 0
+ }
+ return *r.Size
+}
+
+// GetSource returns the Source field.
+func (r *Repository) GetSource() *Repository {
+ if r == nil {
+ return nil
+ }
+ return r.Source
+}
+
+// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetSSHURL() string {
+ if r == nil || r.SSHURL == nil {
+ return ""
+ }
+ return *r.SSHURL
+}
+
+// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise.
+func (r *Repository) GetStargazersCount() int {
+ if r == nil || r.StargazersCount == nil {
+ return 0
+ }
+ return *r.StargazersCount
+}
+
+// GetStargazersURL returns the StargazersURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetStargazersURL() string {
+ if r == nil || r.StargazersURL == nil {
+ return ""
+ }
+ return *r.StargazersURL
+}
+
+// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetStatusesURL() string {
+ if r == nil || r.StatusesURL == nil {
+ return ""
+ }
+ return *r.StatusesURL
+}
+
+// GetSubscribersCount returns the SubscribersCount field if it's non-nil, zero value otherwise.
+func (r *Repository) GetSubscribersCount() int {
+ if r == nil || r.SubscribersCount == nil {
+ return 0
+ }
+ return *r.SubscribersCount
+}
+
+// GetSubscribersURL returns the SubscribersURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetSubscribersURL() string {
+ if r == nil || r.SubscribersURL == nil {
+ return ""
+ }
+ return *r.SubscribersURL
+}
+
+// GetSubscriptionURL returns the SubscriptionURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetSubscriptionURL() string {
+ if r == nil || r.SubscriptionURL == nil {
+ return ""
+ }
+ return *r.SubscriptionURL
+}
+
+// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetSVNURL() string {
+ if r == nil || r.SVNURL == nil {
+ return ""
+ }
+ return *r.SVNURL
+}
+
+// GetTagsURL returns the TagsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetTagsURL() string {
+ if r == nil || r.TagsURL == nil {
+ return ""
+ }
+ return *r.TagsURL
+}
+
+// GetTeamID returns the TeamID field if it's non-nil, zero value otherwise.
+func (r *Repository) GetTeamID() int64 {
+ if r == nil || r.TeamID == nil {
+ return 0
+ }
+ return *r.TeamID
+}
+
+// GetTeamsURL returns the TeamsURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetTeamsURL() string {
+ if r == nil || r.TeamsURL == nil {
+ return ""
+ }
+ return *r.TeamsURL
+}
+
+// GetTreesURL returns the TreesURL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetTreesURL() string {
+ if r == nil || r.TreesURL == nil {
+ return ""
+ }
+ return *r.TreesURL
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (r *Repository) GetUpdatedAt() Timestamp {
+ if r == nil || r.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *r.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *Repository) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise.
+func (r *Repository) GetWatchersCount() int {
+ if r == nil || r.WatchersCount == nil {
+ return 0
+ }
+ return *r.WatchersCount
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (r *RepositoryComment) GetBody() string {
+ if r == nil || r.Body == nil {
+ return ""
+ }
+ return *r.Body
+}
+
+// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise.
+func (r *RepositoryComment) GetCommitID() string {
+ if r == nil || r.CommitID == nil {
+ return ""
+ }
+ return *r.CommitID
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (r *RepositoryComment) GetCreatedAt() time.Time {
+ if r == nil || r.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *r.CreatedAt
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryComment) GetHTMLURL() string {
+ if r == nil || r.HTMLURL == nil {
+ return ""
+ }
+ return *r.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (r *RepositoryComment) GetID() int64 {
+ if r == nil || r.ID == nil {
+ return 0
+ }
+ return *r.ID
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (r *RepositoryComment) GetPath() string {
+ if r == nil || r.Path == nil {
+ return ""
+ }
+ return *r.Path
+}
+
+// GetPosition returns the Position field if it's non-nil, zero value otherwise.
+func (r *RepositoryComment) GetPosition() int {
+ if r == nil || r.Position == nil {
+ return 0
+ }
+ return *r.Position
+}
+
+// GetReactions returns the Reactions field.
+func (r *RepositoryComment) GetReactions() *Reactions {
+ if r == nil {
+ return nil
+ }
+ return r.Reactions
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (r *RepositoryComment) GetUpdatedAt() time.Time {
+ if r == nil || r.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *r.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *RepositoryComment) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetUser returns the User field.
+func (r *RepositoryComment) GetUser() *User {
+ if r == nil {
+ return nil
+ }
+ return r.User
+}
+
+// GetAuthor returns the Author field.
+func (r *RepositoryCommit) GetAuthor() *User {
+ if r == nil {
+ return nil
+ }
+ return r.Author
+}
+
+// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryCommit) GetCommentsURL() string {
+ if r == nil || r.CommentsURL == nil {
+ return ""
+ }
+ return *r.CommentsURL
+}
+
+// GetCommit returns the Commit field.
+func (r *RepositoryCommit) GetCommit() *Commit {
+ if r == nil {
+ return nil
+ }
+ return r.Commit
+}
+
+// GetCommitter returns the Committer field.
+func (r *RepositoryCommit) GetCommitter() *User {
+ if r == nil {
+ return nil
+ }
+ return r.Committer
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryCommit) GetHTMLURL() string {
+ if r == nil || r.HTMLURL == nil {
+ return ""
+ }
+ return *r.HTMLURL
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (r *RepositoryCommit) GetSHA() string {
+ if r == nil || r.SHA == nil {
+ return ""
+ }
+ return *r.SHA
+}
+
+// GetStats returns the Stats field.
+func (r *RepositoryCommit) GetStats() *CommitStats {
+ if r == nil {
+ return nil
+ }
+ return r.Stats
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *RepositoryCommit) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryContent) GetDownloadURL() string {
+ if r == nil || r.DownloadURL == nil {
+ return ""
+ }
+ return *r.DownloadURL
+}
+
+// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise.
+func (r *RepositoryContent) GetEncoding() string {
+ if r == nil || r.Encoding == nil {
+ return ""
+ }
+ return *r.Encoding
+}
+
+// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryContent) GetGitURL() string {
+ if r == nil || r.GitURL == nil {
+ return ""
+ }
+ return *r.GitURL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryContent) GetHTMLURL() string {
+ if r == nil || r.HTMLURL == nil {
+ return ""
+ }
+ return *r.HTMLURL
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (r *RepositoryContent) GetName() string {
+ if r == nil || r.Name == nil {
+ return ""
+ }
+ return *r.Name
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (r *RepositoryContent) GetPath() string {
+ if r == nil || r.Path == nil {
+ return ""
+ }
+ return *r.Path
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (r *RepositoryContent) GetSHA() string {
+ if r == nil || r.SHA == nil {
+ return ""
+ }
+ return *r.SHA
+}
+
+// GetSize returns the Size field if it's non-nil, zero value otherwise.
+func (r *RepositoryContent) GetSize() int {
+ if r == nil || r.Size == nil {
+ return 0
+ }
+ return *r.Size
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (r *RepositoryContent) GetType() string {
+ if r == nil || r.Type == nil {
+ return ""
+ }
+ return *r.Type
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *RepositoryContent) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetAuthor returns the Author field.
+func (r *RepositoryContentFileOptions) GetAuthor() *CommitAuthor {
+ if r == nil {
+ return nil
+ }
+ return r.Author
+}
+
+// GetBranch returns the Branch field if it's non-nil, zero value otherwise.
+func (r *RepositoryContentFileOptions) GetBranch() string {
+ if r == nil || r.Branch == nil {
+ return ""
+ }
+ return *r.Branch
+}
+
+// GetCommitter returns the Committer field.
+func (r *RepositoryContentFileOptions) GetCommitter() *CommitAuthor {
+ if r == nil {
+ return nil
+ }
+ return r.Committer
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (r *RepositoryContentFileOptions) GetMessage() string {
+ if r == nil || r.Message == nil {
+ return ""
+ }
+ return *r.Message
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (r *RepositoryContentFileOptions) GetSHA() string {
+ if r == nil || r.SHA == nil {
+ return ""
+ }
+ return *r.SHA
+}
+
+// GetContent returns the Content field.
+func (r *RepositoryContentResponse) GetContent() *RepositoryContent {
+ if r == nil {
+ return nil
+ }
+ return r.Content
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (r *RepositoryEvent) GetAction() string {
+ if r == nil || r.Action == nil {
+ return ""
+ }
+ return *r.Action
+}
+
+// GetInstallation returns the Installation field.
+func (r *RepositoryEvent) GetInstallation() *Installation {
+ if r == nil {
+ return nil
+ }
+ return r.Installation
+}
+
+// GetOrg returns the Org field.
+func (r *RepositoryEvent) GetOrg() *Organization {
+ if r == nil {
+ return nil
+ }
+ return r.Org
+}
+
+// GetRepo returns the Repo field.
+func (r *RepositoryEvent) GetRepo() *Repository {
+ if r == nil {
+ return nil
+ }
+ return r.Repo
+}
+
+// GetSender returns the Sender field.
+func (r *RepositoryEvent) GetSender() *User {
+ if r == nil {
+ return nil
+ }
+ return r.Sender
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (r *RepositoryInvitation) GetCreatedAt() Timestamp {
+ if r == nil || r.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *r.CreatedAt
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryInvitation) GetHTMLURL() string {
+ if r == nil || r.HTMLURL == nil {
+ return ""
+ }
+ return *r.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (r *RepositoryInvitation) GetID() int64 {
+ if r == nil || r.ID == nil {
+ return 0
+ }
+ return *r.ID
+}
+
+// GetInvitee returns the Invitee field.
+func (r *RepositoryInvitation) GetInvitee() *User {
+ if r == nil {
+ return nil
+ }
+ return r.Invitee
+}
+
+// GetInviter returns the Inviter field.
+func (r *RepositoryInvitation) GetInviter() *User {
+ if r == nil {
+ return nil
+ }
+ return r.Inviter
+}
+
+// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise.
+func (r *RepositoryInvitation) GetPermissions() string {
+ if r == nil || r.Permissions == nil {
+ return ""
+ }
+ return *r.Permissions
+}
+
+// GetRepo returns the Repo field.
+func (r *RepositoryInvitation) GetRepo() *Repository {
+ if r == nil {
+ return nil
+ }
+ return r.Repo
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *RepositoryInvitation) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetContent returns the Content field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetContent() string {
+ if r == nil || r.Content == nil {
+ return ""
+ }
+ return *r.Content
+}
+
+// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetDownloadURL() string {
+ if r == nil || r.DownloadURL == nil {
+ return ""
+ }
+ return *r.DownloadURL
+}
+
+// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetEncoding() string {
+ if r == nil || r.Encoding == nil {
+ return ""
+ }
+ return *r.Encoding
+}
+
+// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetGitURL() string {
+ if r == nil || r.GitURL == nil {
+ return ""
+ }
+ return *r.GitURL
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetHTMLURL() string {
+ if r == nil || r.HTMLURL == nil {
+ return ""
+ }
+ return *r.HTMLURL
+}
+
+// GetLicense returns the License field.
+func (r *RepositoryLicense) GetLicense() *License {
+ if r == nil {
+ return nil
+ }
+ return r.License
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetName() string {
+ if r == nil || r.Name == nil {
+ return ""
+ }
+ return *r.Name
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetPath() string {
+ if r == nil || r.Path == nil {
+ return ""
+ }
+ return *r.Path
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetSHA() string {
+ if r == nil || r.SHA == nil {
+ return ""
+ }
+ return *r.SHA
+}
+
+// GetSize returns the Size field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetSize() int {
+ if r == nil || r.Size == nil {
+ return 0
+ }
+ return *r.Size
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetType() string {
+ if r == nil || r.Type == nil {
+ return ""
+ }
+ return *r.Type
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *RepositoryLicense) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetBase returns the Base field if it's non-nil, zero value otherwise.
+func (r *RepositoryMergeRequest) GetBase() string {
+ if r == nil || r.Base == nil {
+ return ""
+ }
+ return *r.Base
+}
+
+// GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise.
+func (r *RepositoryMergeRequest) GetCommitMessage() string {
+ if r == nil || r.CommitMessage == nil {
+ return ""
+ }
+ return *r.CommitMessage
+}
+
+// GetHead returns the Head field if it's non-nil, zero value otherwise.
+func (r *RepositoryMergeRequest) GetHead() string {
+ if r == nil || r.Head == nil {
+ return ""
+ }
+ return *r.Head
+}
+
+// GetPermission returns the Permission field if it's non-nil, zero value otherwise.
+func (r *RepositoryPermissionLevel) GetPermission() string {
+ if r == nil || r.Permission == nil {
+ return ""
+ }
+ return *r.Permission
+}
+
+// GetUser returns the User field.
+func (r *RepositoryPermissionLevel) GetUser() *User {
+ if r == nil {
+ return nil
+ }
+ return r.User
+}
+
+// GetAssetsURL returns the AssetsURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetAssetsURL() string {
+ if r == nil || r.AssetsURL == nil {
+ return ""
+ }
+ return *r.AssetsURL
+}
+
+// GetAuthor returns the Author field.
+func (r *RepositoryRelease) GetAuthor() *User {
+ if r == nil {
+ return nil
+ }
+ return r.Author
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetBody() string {
+ if r == nil || r.Body == nil {
+ return ""
+ }
+ return *r.Body
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetCreatedAt() Timestamp {
+ if r == nil || r.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *r.CreatedAt
+}
+
+// GetDraft returns the Draft field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetDraft() bool {
+ if r == nil || r.Draft == nil {
+ return false
+ }
+ return *r.Draft
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetHTMLURL() string {
+ if r == nil || r.HTMLURL == nil {
+ return ""
+ }
+ return *r.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetID() int64 {
+ if r == nil || r.ID == nil {
+ return 0
+ }
+ return *r.ID
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetName() string {
+ if r == nil || r.Name == nil {
+ return ""
+ }
+ return *r.Name
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetNodeID() string {
+ if r == nil || r.NodeID == nil {
+ return ""
+ }
+ return *r.NodeID
+}
+
+// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetPrerelease() bool {
+ if r == nil || r.Prerelease == nil {
+ return false
+ }
+ return *r.Prerelease
+}
+
+// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetPublishedAt() Timestamp {
+ if r == nil || r.PublishedAt == nil {
+ return Timestamp{}
+ }
+ return *r.PublishedAt
+}
+
+// GetTagName returns the TagName field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetTagName() string {
+ if r == nil || r.TagName == nil {
+ return ""
+ }
+ return *r.TagName
+}
+
+// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetTarballURL() string {
+ if r == nil || r.TarballURL == nil {
+ return ""
+ }
+ return *r.TarballURL
+}
+
+// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetTargetCommitish() string {
+ if r == nil || r.TargetCommitish == nil {
+ return ""
+ }
+ return *r.TargetCommitish
+}
+
+// GetUploadURL returns the UploadURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetUploadURL() string {
+ if r == nil || r.UploadURL == nil {
+ return ""
+ }
+ return *r.UploadURL
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryRelease) GetZipballURL() string {
+ if r == nil || r.ZipballURL == nil {
+ return ""
+ }
+ return *r.ZipballURL
+}
+
+// GetCommit returns the Commit field.
+func (r *RepositoryTag) GetCommit() *Commit {
+ if r == nil {
+ return nil
+ }
+ return r.Commit
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (r *RepositoryTag) GetName() string {
+ if r == nil || r.Name == nil {
+ return ""
+ }
+ return *r.Name
+}
+
+// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryTag) GetTarballURL() string {
+ if r == nil || r.TarballURL == nil {
+ return ""
+ }
+ return *r.TarballURL
+}
+
+// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise.
+func (r *RepositoryTag) GetZipballURL() string {
+ if r == nil || r.ZipballURL == nil {
+ return ""
+ }
+ return *r.ZipballURL
+}
+
+// GetForkRepos returns the ForkRepos field if it's non-nil, zero value otherwise.
+func (r *RepoStats) GetForkRepos() int {
+ if r == nil || r.ForkRepos == nil {
+ return 0
+ }
+ return *r.ForkRepos
+}
+
+// GetOrgRepos returns the OrgRepos field if it's non-nil, zero value otherwise.
+func (r *RepoStats) GetOrgRepos() int {
+ if r == nil || r.OrgRepos == nil {
+ return 0
+ }
+ return *r.OrgRepos
+}
+
+// GetRootRepos returns the RootRepos field if it's non-nil, zero value otherwise.
+func (r *RepoStats) GetRootRepos() int {
+ if r == nil || r.RootRepos == nil {
+ return 0
+ }
+ return *r.RootRepos
+}
+
+// GetTotalPushes returns the TotalPushes field if it's non-nil, zero value otherwise.
+func (r *RepoStats) GetTotalPushes() int {
+ if r == nil || r.TotalPushes == nil {
+ return 0
+ }
+ return *r.TotalPushes
+}
+
+// GetTotalRepos returns the TotalRepos field if it's non-nil, zero value otherwise.
+func (r *RepoStats) GetTotalRepos() int {
+ if r == nil || r.TotalRepos == nil {
+ return 0
+ }
+ return *r.TotalRepos
+}
+
+// GetTotalWikis returns the TotalWikis field if it's non-nil, zero value otherwise.
+func (r *RepoStats) GetTotalWikis() int {
+ if r == nil || r.TotalWikis == nil {
+ return 0
+ }
+ return *r.TotalWikis
+}
+
+// GetContext returns the Context field if it's non-nil, zero value otherwise.
+func (r *RepoStatus) GetContext() string {
+ if r == nil || r.Context == nil {
+ return ""
+ }
+ return *r.Context
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (r *RepoStatus) GetCreatedAt() time.Time {
+ if r == nil || r.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *r.CreatedAt
+}
+
+// GetCreator returns the Creator field.
+func (r *RepoStatus) GetCreator() *User {
+ if r == nil {
+ return nil
+ }
+ return r.Creator
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (r *RepoStatus) GetDescription() string {
+ if r == nil || r.Description == nil {
+ return ""
+ }
+ return *r.Description
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (r *RepoStatus) GetID() int64 {
+ if r == nil || r.ID == nil {
+ return 0
+ }
+ return *r.ID
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (r *RepoStatus) GetState() string {
+ if r == nil || r.State == nil {
+ return ""
+ }
+ return *r.State
+}
+
+// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise.
+func (r *RepoStatus) GetTargetURL() string {
+ if r == nil || r.TargetURL == nil {
+ return ""
+ }
+ return *r.TargetURL
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (r *RepoStatus) GetUpdatedAt() time.Time {
+ if r == nil || r.UpdatedAt == nil {
+ return time.Time{}
+ }
+ return *r.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (r *RepoStatus) GetURL() string {
+ if r == nil || r.URL == nil {
+ return ""
+ }
+ return *r.URL
+}
+
+// GetStrict returns the Strict field if it's non-nil, zero value otherwise.
+func (r *RequiredStatusChecksRequest) GetStrict() bool {
+ if r == nil || r.Strict == nil {
+ return false
+ }
+ return *r.Strict
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (s *ServiceHook) GetName() string {
+ if s == nil || s.Name == nil {
+ return ""
+ }
+ return *s.Name
+}
+
+// GetPayload returns the Payload field if it's non-nil, zero value otherwise.
+func (s *SignatureVerification) GetPayload() string {
+ if s == nil || s.Payload == nil {
+ return ""
+ }
+ return *s.Payload
+}
+
+// GetReason returns the Reason field if it's non-nil, zero value otherwise.
+func (s *SignatureVerification) GetReason() string {
+ if s == nil || s.Reason == nil {
+ return ""
+ }
+ return *s.Reason
+}
+
+// GetSignature returns the Signature field if it's non-nil, zero value otherwise.
+func (s *SignatureVerification) GetSignature() string {
+ if s == nil || s.Signature == nil {
+ return ""
+ }
+ return *s.Signature
+}
+
+// GetVerified returns the Verified field if it's non-nil, zero value otherwise.
+func (s *SignatureVerification) GetVerified() bool {
+ if s == nil || s.Verified == nil {
+ return false
+ }
+ return *s.Verified
+}
+
+// GetActor returns the Actor field.
+func (s *Source) GetActor() *User {
+ if s == nil {
+ return nil
+ }
+ return s.Actor
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (s *Source) GetID() int64 {
+ if s == nil || s.ID == nil {
+ return 0
+ }
+ return *s.ID
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (s *Source) GetURL() string {
+ if s == nil || s.URL == nil {
+ return ""
+ }
+ return *s.URL
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (s *SourceImportAuthor) GetEmail() string {
+ if s == nil || s.Email == nil {
+ return ""
+ }
+ return *s.Email
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (s *SourceImportAuthor) GetID() int64 {
+ if s == nil || s.ID == nil {
+ return 0
+ }
+ return *s.ID
+}
+
+// GetImportURL returns the ImportURL field if it's non-nil, zero value otherwise.
+func (s *SourceImportAuthor) GetImportURL() string {
+ if s == nil || s.ImportURL == nil {
+ return ""
+ }
+ return *s.ImportURL
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (s *SourceImportAuthor) GetName() string {
+ if s == nil || s.Name == nil {
+ return ""
+ }
+ return *s.Name
+}
+
+// GetRemoteID returns the RemoteID field if it's non-nil, zero value otherwise.
+func (s *SourceImportAuthor) GetRemoteID() string {
+ if s == nil || s.RemoteID == nil {
+ return ""
+ }
+ return *s.RemoteID
+}
+
+// GetRemoteName returns the RemoteName field if it's non-nil, zero value otherwise.
+func (s *SourceImportAuthor) GetRemoteName() string {
+ if s == nil || s.RemoteName == nil {
+ return ""
+ }
+ return *s.RemoteName
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (s *SourceImportAuthor) GetURL() string {
+ if s == nil || s.URL == nil {
+ return ""
+ }
+ return *s.URL
+}
+
+// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise.
+func (s *Stargazer) GetStarredAt() Timestamp {
+ if s == nil || s.StarredAt == nil {
+ return Timestamp{}
+ }
+ return *s.StarredAt
+}
+
+// GetUser returns the User field.
+func (s *Stargazer) GetUser() *User {
+ if s == nil {
+ return nil
+ }
+ return s.User
+}
+
+// GetRepository returns the Repository field.
+func (s *StarredRepository) GetRepository() *Repository {
+ if s == nil {
+ return nil
+ }
+ return s.Repository
+}
+
+// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise.
+func (s *StarredRepository) GetStarredAt() Timestamp {
+ if s == nil || s.StarredAt == nil {
+ return Timestamp{}
+ }
+ return *s.StarredAt
+}
+
+// GetCommit returns the Commit field.
+func (s *StatusEvent) GetCommit() *RepositoryCommit {
+ if s == nil {
+ return nil
+ }
+ return s.Commit
+}
+
+// GetContext returns the Context field if it's non-nil, zero value otherwise.
+func (s *StatusEvent) GetContext() string {
+ if s == nil || s.Context == nil {
+ return ""
+ }
+ return *s.Context
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (s *StatusEvent) GetCreatedAt() Timestamp {
+ if s == nil || s.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *s.CreatedAt
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (s *StatusEvent) GetDescription() string {
+ if s == nil || s.Description == nil {
+ return ""
+ }
+ return *s.Description
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (s *StatusEvent) GetID() int64 {
+ if s == nil || s.ID == nil {
+ return 0
+ }
+ return *s.ID
+}
+
+// GetInstallation returns the Installation field.
+func (s *StatusEvent) GetInstallation() *Installation {
+ if s == nil {
+ return nil
+ }
+ return s.Installation
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (s *StatusEvent) GetName() string {
+ if s == nil || s.Name == nil {
+ return ""
+ }
+ return *s.Name
+}
+
+// GetRepo returns the Repo field.
+func (s *StatusEvent) GetRepo() *Repository {
+ if s == nil {
+ return nil
+ }
+ return s.Repo
+}
+
+// GetSender returns the Sender field.
+func (s *StatusEvent) GetSender() *User {
+ if s == nil {
+ return nil
+ }
+ return s.Sender
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (s *StatusEvent) GetSHA() string {
+ if s == nil || s.SHA == nil {
+ return ""
+ }
+ return *s.SHA
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (s *StatusEvent) GetState() string {
+ if s == nil || s.State == nil {
+ return ""
+ }
+ return *s.State
+}
+
+// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise.
+func (s *StatusEvent) GetTargetURL() string {
+ if s == nil || s.TargetURL == nil {
+ return ""
+ }
+ return *s.TargetURL
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (s *StatusEvent) GetUpdatedAt() Timestamp {
+ if s == nil || s.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *s.UpdatedAt
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (s *Subscription) GetCreatedAt() Timestamp {
+ if s == nil || s.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *s.CreatedAt
+}
+
+// GetIgnored returns the Ignored field if it's non-nil, zero value otherwise.
+func (s *Subscription) GetIgnored() bool {
+ if s == nil || s.Ignored == nil {
+ return false
+ }
+ return *s.Ignored
+}
+
+// GetReason returns the Reason field if it's non-nil, zero value otherwise.
+func (s *Subscription) GetReason() string {
+ if s == nil || s.Reason == nil {
+ return ""
+ }
+ return *s.Reason
+}
+
+// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise.
+func (s *Subscription) GetRepositoryURL() string {
+ if s == nil || s.RepositoryURL == nil {
+ return ""
+ }
+ return *s.RepositoryURL
+}
+
+// GetSubscribed returns the Subscribed field if it's non-nil, zero value otherwise.
+func (s *Subscription) GetSubscribed() bool {
+ if s == nil || s.Subscribed == nil {
+ return false
+ }
+ return *s.Subscribed
+}
+
+// GetThreadURL returns the ThreadURL field if it's non-nil, zero value otherwise.
+func (s *Subscription) GetThreadURL() string {
+ if s == nil || s.ThreadURL == nil {
+ return ""
+ }
+ return *s.ThreadURL
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (s *Subscription) GetURL() string {
+ if s == nil || s.URL == nil {
+ return ""
+ }
+ return *s.URL
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (t *Tag) GetMessage() string {
+ if t == nil || t.Message == nil {
+ return ""
+ }
+ return *t.Message
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (t *Tag) GetNodeID() string {
+ if t == nil || t.NodeID == nil {
+ return ""
+ }
+ return *t.NodeID
+}
+
+// GetObject returns the Object field.
+func (t *Tag) GetObject() *GitObject {
+ if t == nil {
+ return nil
+ }
+ return t.Object
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (t *Tag) GetSHA() string {
+ if t == nil || t.SHA == nil {
+ return ""
+ }
+ return *t.SHA
+}
+
+// GetTag returns the Tag field if it's non-nil, zero value otherwise.
+func (t *Tag) GetTag() string {
+ if t == nil || t.Tag == nil {
+ return ""
+ }
+ return *t.Tag
+}
+
+// GetTagger returns the Tagger field.
+func (t *Tag) GetTagger() *CommitAuthor {
+ if t == nil {
+ return nil
+ }
+ return t.Tagger
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (t *Tag) GetURL() string {
+ if t == nil || t.URL == nil {
+ return ""
+ }
+ return *t.URL
+}
+
+// GetVerification returns the Verification field.
+func (t *Tag) GetVerification() *SignatureVerification {
+ if t == nil {
+ return nil
+ }
+ return t.Verification
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (t *Team) GetDescription() string {
+ if t == nil || t.Description == nil {
+ return ""
+ }
+ return *t.Description
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (t *Team) GetID() int64 {
+ if t == nil || t.ID == nil {
+ return 0
+ }
+ return *t.ID
+}
+
+// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise.
+func (t *Team) GetLDAPDN() string {
+ if t == nil || t.LDAPDN == nil {
+ return ""
+ }
+ return *t.LDAPDN
+}
+
+// GetMembersCount returns the MembersCount field if it's non-nil, zero value otherwise.
+func (t *Team) GetMembersCount() int {
+ if t == nil || t.MembersCount == nil {
+ return 0
+ }
+ return *t.MembersCount
+}
+
+// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise.
+func (t *Team) GetMembersURL() string {
+ if t == nil || t.MembersURL == nil {
+ return ""
+ }
+ return *t.MembersURL
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (t *Team) GetName() string {
+ if t == nil || t.Name == nil {
+ return ""
+ }
+ return *t.Name
+}
+
+// GetOrganization returns the Organization field.
+func (t *Team) GetOrganization() *Organization {
+ if t == nil {
+ return nil
+ }
+ return t.Organization
+}
+
+// GetParent returns the Parent field.
+func (t *Team) GetParent() *Team {
+ if t == nil {
+ return nil
+ }
+ return t.Parent
+}
+
+// GetPermission returns the Permission field if it's non-nil, zero value otherwise.
+func (t *Team) GetPermission() string {
+ if t == nil || t.Permission == nil {
+ return ""
+ }
+ return *t.Permission
+}
+
+// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise.
+func (t *Team) GetPrivacy() string {
+ if t == nil || t.Privacy == nil {
+ return ""
+ }
+ return *t.Privacy
+}
+
+// GetReposCount returns the ReposCount field if it's non-nil, zero value otherwise.
+func (t *Team) GetReposCount() int {
+ if t == nil || t.ReposCount == nil {
+ return 0
+ }
+ return *t.ReposCount
+}
+
+// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise.
+func (t *Team) GetRepositoriesURL() string {
+ if t == nil || t.RepositoriesURL == nil {
+ return ""
+ }
+ return *t.RepositoriesURL
+}
+
+// GetSlug returns the Slug field if it's non-nil, zero value otherwise.
+func (t *Team) GetSlug() string {
+ if t == nil || t.Slug == nil {
+ return ""
+ }
+ return *t.Slug
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (t *Team) GetURL() string {
+ if t == nil || t.URL == nil {
+ return ""
+ }
+ return *t.URL
+}
+
+// GetInstallation returns the Installation field.
+func (t *TeamAddEvent) GetInstallation() *Installation {
+ if t == nil {
+ return nil
+ }
+ return t.Installation
+}
+
+// GetOrg returns the Org field.
+func (t *TeamAddEvent) GetOrg() *Organization {
+ if t == nil {
+ return nil
+ }
+ return t.Org
+}
+
+// GetRepo returns the Repo field.
+func (t *TeamAddEvent) GetRepo() *Repository {
+ if t == nil {
+ return nil
+ }
+ return t.Repo
+}
+
+// GetSender returns the Sender field.
+func (t *TeamAddEvent) GetSender() *User {
+ if t == nil {
+ return nil
+ }
+ return t.Sender
+}
+
+// GetTeam returns the Team field.
+func (t *TeamAddEvent) GetTeam() *Team {
+ if t == nil {
+ return nil
+ }
+ return t.Team
+}
+
+// GetAuthor returns the Author field.
+func (t *TeamDiscussion) GetAuthor() *User {
+ if t == nil {
+ return nil
+ }
+ return t.Author
+}
+
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetBody() string {
+ if t == nil || t.Body == nil {
+ return ""
+ }
+ return *t.Body
+}
+
+// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetBodyHTML() string {
+ if t == nil || t.BodyHTML == nil {
+ return ""
+ }
+ return *t.BodyHTML
+}
+
+// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetBodyVersion() string {
+ if t == nil || t.BodyVersion == nil {
+ return ""
+ }
+ return *t.BodyVersion
+}
+
+// GetCommentsCount returns the CommentsCount field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetCommentsCount() int {
+ if t == nil || t.CommentsCount == nil {
+ return 0
+ }
+ return *t.CommentsCount
+}
+
+// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetCommentsURL() string {
+ if t == nil || t.CommentsURL == nil {
+ return ""
+ }
+ return *t.CommentsURL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetCreatedAt() Timestamp {
+ if t == nil || t.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *t.CreatedAt
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetHTMLURL() string {
+ if t == nil || t.HTMLURL == nil {
+ return ""
+ }
+ return *t.HTMLURL
+}
+
+// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetLastEditedAt() Timestamp {
+ if t == nil || t.LastEditedAt == nil {
+ return Timestamp{}
+ }
+ return *t.LastEditedAt
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetNodeID() string {
+ if t == nil || t.NodeID == nil {
+ return ""
+ }
+ return *t.NodeID
+}
+
+// GetNumber returns the Number field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetNumber() int {
+ if t == nil || t.Number == nil {
+ return 0
+ }
+ return *t.Number
+}
+
+// GetPinned returns the Pinned field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetPinned() bool {
+ if t == nil || t.Pinned == nil {
+ return false
+ }
+ return *t.Pinned
+}
+
+// GetPrivate returns the Private field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetPrivate() bool {
+ if t == nil || t.Private == nil {
+ return false
+ }
+ return *t.Private
+}
+
+// GetReactions returns the Reactions field.
+func (t *TeamDiscussion) GetReactions() *Reactions {
+ if t == nil {
+ return nil
+ }
+ return t.Reactions
+}
+
+// GetTeamURL returns the TeamURL field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetTeamURL() string {
+ if t == nil || t.TeamURL == nil {
+ return ""
+ }
+ return *t.TeamURL
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetTitle() string {
+ if t == nil || t.Title == nil {
+ return ""
+ }
+ return *t.Title
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetUpdatedAt() Timestamp {
+ if t == nil || t.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *t.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (t *TeamDiscussion) GetURL() string {
+ if t == nil || t.URL == nil {
+ return ""
+ }
+ return *t.URL
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (t *TeamEvent) GetAction() string {
+ if t == nil || t.Action == nil {
+ return ""
+ }
+ return *t.Action
+}
+
+// GetChanges returns the Changes field.
+func (t *TeamEvent) GetChanges() *TeamChange {
+ if t == nil {
+ return nil
+ }
+ return t.Changes
+}
+
+// GetInstallation returns the Installation field.
+func (t *TeamEvent) GetInstallation() *Installation {
+ if t == nil {
+ return nil
+ }
+ return t.Installation
+}
+
+// GetOrg returns the Org field.
+func (t *TeamEvent) GetOrg() *Organization {
+ if t == nil {
+ return nil
+ }
+ return t.Org
+}
+
+// GetRepo returns the Repo field.
+func (t *TeamEvent) GetRepo() *Repository {
+ if t == nil {
+ return nil
+ }
+ return t.Repo
+}
+
+// GetSender returns the Sender field.
+func (t *TeamEvent) GetSender() *User {
+ if t == nil {
+ return nil
+ }
+ return t.Sender
+}
+
+// GetTeam returns the Team field.
+func (t *TeamEvent) GetTeam() *Team {
+ if t == nil {
+ return nil
+ }
+ return t.Team
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (t *TeamLDAPMapping) GetDescription() string {
+ if t == nil || t.Description == nil {
+ return ""
+ }
+ return *t.Description
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (t *TeamLDAPMapping) GetID() int64 {
+ if t == nil || t.ID == nil {
+ return 0
+ }
+ return *t.ID
+}
+
+// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise.
+func (t *TeamLDAPMapping) GetLDAPDN() string {
+ if t == nil || t.LDAPDN == nil {
+ return ""
+ }
+ return *t.LDAPDN
+}
+
+// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise.
+func (t *TeamLDAPMapping) GetMembersURL() string {
+ if t == nil || t.MembersURL == nil {
+ return ""
+ }
+ return *t.MembersURL
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (t *TeamLDAPMapping) GetName() string {
+ if t == nil || t.Name == nil {
+ return ""
+ }
+ return *t.Name
+}
+
+// GetPermission returns the Permission field if it's non-nil, zero value otherwise.
+func (t *TeamLDAPMapping) GetPermission() string {
+ if t == nil || t.Permission == nil {
+ return ""
+ }
+ return *t.Permission
+}
+
+// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise.
+func (t *TeamLDAPMapping) GetPrivacy() string {
+ if t == nil || t.Privacy == nil {
+ return ""
+ }
+ return *t.Privacy
+}
+
+// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise.
+func (t *TeamLDAPMapping) GetRepositoriesURL() string {
+ if t == nil || t.RepositoriesURL == nil {
+ return ""
+ }
+ return *t.RepositoriesURL
+}
+
+// GetSlug returns the Slug field if it's non-nil, zero value otherwise.
+func (t *TeamLDAPMapping) GetSlug() string {
+ if t == nil || t.Slug == nil {
+ return ""
+ }
+ return *t.Slug
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (t *TeamLDAPMapping) GetURL() string {
+ if t == nil || t.URL == nil {
+ return ""
+ }
+ return *t.URL
+}
+
+// GetFragment returns the Fragment field if it's non-nil, zero value otherwise.
+func (t *TextMatch) GetFragment() string {
+ if t == nil || t.Fragment == nil {
+ return ""
+ }
+ return *t.Fragment
+}
+
+// GetObjectType returns the ObjectType field if it's non-nil, zero value otherwise.
+func (t *TextMatch) GetObjectType() string {
+ if t == nil || t.ObjectType == nil {
+ return ""
+ }
+ return *t.ObjectType
+}
+
+// GetObjectURL returns the ObjectURL field if it's non-nil, zero value otherwise.
+func (t *TextMatch) GetObjectURL() string {
+ if t == nil || t.ObjectURL == nil {
+ return ""
+ }
+ return *t.ObjectURL
+}
+
+// GetProperty returns the Property field if it's non-nil, zero value otherwise.
+func (t *TextMatch) GetProperty() string {
+ if t == nil || t.Property == nil {
+ return ""
+ }
+ return *t.Property
+}
+
+// GetActor returns the Actor field.
+func (t *Timeline) GetActor() *User {
+ if t == nil {
+ return nil
+ }
+ return t.Actor
+}
+
+// GetAssignee returns the Assignee field.
+func (t *Timeline) GetAssignee() *User {
+ if t == nil {
+ return nil
+ }
+ return t.Assignee
+}
+
+// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise.
+func (t *Timeline) GetCommitID() string {
+ if t == nil || t.CommitID == nil {
+ return ""
+ }
+ return *t.CommitID
+}
+
+// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise.
+func (t *Timeline) GetCommitURL() string {
+ if t == nil || t.CommitURL == nil {
+ return ""
+ }
+ return *t.CommitURL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (t *Timeline) GetCreatedAt() time.Time {
+ if t == nil || t.CreatedAt == nil {
+ return time.Time{}
+ }
+ return *t.CreatedAt
+}
+
+// GetEvent returns the Event field if it's non-nil, zero value otherwise.
+func (t *Timeline) GetEvent() string {
+ if t == nil || t.Event == nil {
+ return ""
+ }
+ return *t.Event
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (t *Timeline) GetID() int64 {
+ if t == nil || t.ID == nil {
+ return 0
+ }
+ return *t.ID
+}
+
+// GetLabel returns the Label field.
+func (t *Timeline) GetLabel() *Label {
+ if t == nil {
+ return nil
+ }
+ return t.Label
+}
+
+// GetMilestone returns the Milestone field.
+func (t *Timeline) GetMilestone() *Milestone {
+ if t == nil {
+ return nil
+ }
+ return t.Milestone
+}
+
+// GetRename returns the Rename field.
+func (t *Timeline) GetRename() *Rename {
+ if t == nil {
+ return nil
+ }
+ return t.Rename
+}
+
+// GetSource returns the Source field.
+func (t *Timeline) GetSource() *Source {
+ if t == nil {
+ return nil
+ }
+ return t.Source
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (t *Timeline) GetURL() string {
+ if t == nil || t.URL == nil {
+ return ""
+ }
+ return *t.URL
+}
+
+// GetCount returns the Count field if it's non-nil, zero value otherwise.
+func (t *TrafficClones) GetCount() int {
+ if t == nil || t.Count == nil {
+ return 0
+ }
+ return *t.Count
+}
+
+// GetUniques returns the Uniques field if it's non-nil, zero value otherwise.
+func (t *TrafficClones) GetUniques() int {
+ if t == nil || t.Uniques == nil {
+ return 0
+ }
+ return *t.Uniques
+}
+
+// GetCount returns the Count field if it's non-nil, zero value otherwise.
+func (t *TrafficData) GetCount() int {
+ if t == nil || t.Count == nil {
+ return 0
+ }
+ return *t.Count
+}
+
+// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise.
+func (t *TrafficData) GetTimestamp() Timestamp {
+ if t == nil || t.Timestamp == nil {
+ return Timestamp{}
+ }
+ return *t.Timestamp
+}
+
+// GetUniques returns the Uniques field if it's non-nil, zero value otherwise.
+func (t *TrafficData) GetUniques() int {
+ if t == nil || t.Uniques == nil {
+ return 0
+ }
+ return *t.Uniques
+}
+
+// GetCount returns the Count field if it's non-nil, zero value otherwise.
+func (t *TrafficPath) GetCount() int {
+ if t == nil || t.Count == nil {
+ return 0
+ }
+ return *t.Count
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (t *TrafficPath) GetPath() string {
+ if t == nil || t.Path == nil {
+ return ""
+ }
+ return *t.Path
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (t *TrafficPath) GetTitle() string {
+ if t == nil || t.Title == nil {
+ return ""
+ }
+ return *t.Title
+}
+
+// GetUniques returns the Uniques field if it's non-nil, zero value otherwise.
+func (t *TrafficPath) GetUniques() int {
+ if t == nil || t.Uniques == nil {
+ return 0
+ }
+ return *t.Uniques
+}
+
+// GetCount returns the Count field if it's non-nil, zero value otherwise.
+func (t *TrafficReferrer) GetCount() int {
+ if t == nil || t.Count == nil {
+ return 0
+ }
+ return *t.Count
+}
+
+// GetReferrer returns the Referrer field if it's non-nil, zero value otherwise.
+func (t *TrafficReferrer) GetReferrer() string {
+ if t == nil || t.Referrer == nil {
+ return ""
+ }
+ return *t.Referrer
+}
+
+// GetUniques returns the Uniques field if it's non-nil, zero value otherwise.
+func (t *TrafficReferrer) GetUniques() int {
+ if t == nil || t.Uniques == nil {
+ return 0
+ }
+ return *t.Uniques
+}
+
+// GetCount returns the Count field if it's non-nil, zero value otherwise.
+func (t *TrafficViews) GetCount() int {
+ if t == nil || t.Count == nil {
+ return 0
+ }
+ return *t.Count
+}
+
+// GetUniques returns the Uniques field if it's non-nil, zero value otherwise.
+func (t *TrafficViews) GetUniques() int {
+ if t == nil || t.Uniques == nil {
+ return 0
+ }
+ return *t.Uniques
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (t *Tree) GetSHA() string {
+ if t == nil || t.SHA == nil {
+ return ""
+ }
+ return *t.SHA
+}
+
+// GetTruncated returns the Truncated field if it's non-nil, zero value otherwise.
+func (t *Tree) GetTruncated() bool {
+ if t == nil || t.Truncated == nil {
+ return false
+ }
+ return *t.Truncated
+}
+
+// GetContent returns the Content field if it's non-nil, zero value otherwise.
+func (t *TreeEntry) GetContent() string {
+ if t == nil || t.Content == nil {
+ return ""
+ }
+ return *t.Content
+}
+
+// GetMode returns the Mode field if it's non-nil, zero value otherwise.
+func (t *TreeEntry) GetMode() string {
+ if t == nil || t.Mode == nil {
+ return ""
+ }
+ return *t.Mode
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (t *TreeEntry) GetPath() string {
+ if t == nil || t.Path == nil {
+ return ""
+ }
+ return *t.Path
+}
+
+// GetSHA returns the SHA field if it's non-nil, zero value otherwise.
+func (t *TreeEntry) GetSHA() string {
+ if t == nil || t.SHA == nil {
+ return ""
+ }
+ return *t.SHA
+}
+
+// GetSize returns the Size field if it's non-nil, zero value otherwise.
+func (t *TreeEntry) GetSize() int {
+ if t == nil || t.Size == nil {
+ return 0
+ }
+ return *t.Size
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (t *TreeEntry) GetType() string {
+ if t == nil || t.Type == nil {
+ return ""
+ }
+ return *t.Type
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (t *TreeEntry) GetURL() string {
+ if t == nil || t.URL == nil {
+ return ""
+ }
+ return *t.URL
+}
+
+// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise.
+func (u *UpdateCheckRunOptions) GetCompletedAt() Timestamp {
+ if u == nil || u.CompletedAt == nil {
+ return Timestamp{}
+ }
+ return *u.CompletedAt
+}
+
+// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise.
+func (u *UpdateCheckRunOptions) GetConclusion() string {
+ if u == nil || u.Conclusion == nil {
+ return ""
+ }
+ return *u.Conclusion
+}
+
+// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise.
+func (u *UpdateCheckRunOptions) GetDetailsURL() string {
+ if u == nil || u.DetailsURL == nil {
+ return ""
+ }
+ return *u.DetailsURL
+}
+
+// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise.
+func (u *UpdateCheckRunOptions) GetExternalID() string {
+ if u == nil || u.ExternalID == nil {
+ return ""
+ }
+ return *u.ExternalID
+}
+
+// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise.
+func (u *UpdateCheckRunOptions) GetHeadBranch() string {
+ if u == nil || u.HeadBranch == nil {
+ return ""
+ }
+ return *u.HeadBranch
+}
+
+// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise.
+func (u *UpdateCheckRunOptions) GetHeadSHA() string {
+ if u == nil || u.HeadSHA == nil {
+ return ""
+ }
+ return *u.HeadSHA
+}
+
+// GetOutput returns the Output field.
+func (u *UpdateCheckRunOptions) GetOutput() *CheckRunOutput {
+ if u == nil {
+ return nil
+ }
+ return u.Output
+}
+
+// GetStatus returns the Status field if it's non-nil, zero value otherwise.
+func (u *UpdateCheckRunOptions) GetStatus() string {
+ if u == nil || u.Status == nil {
+ return ""
+ }
+ return *u.Status
+}
+
+// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise.
+func (u *User) GetAvatarURL() string {
+ if u == nil || u.AvatarURL == nil {
+ return ""
+ }
+ return *u.AvatarURL
+}
+
+// GetBio returns the Bio field if it's non-nil, zero value otherwise.
+func (u *User) GetBio() string {
+ if u == nil || u.Bio == nil {
+ return ""
+ }
+ return *u.Bio
+}
+
+// GetBlog returns the Blog field if it's non-nil, zero value otherwise.
+func (u *User) GetBlog() string {
+ if u == nil || u.Blog == nil {
+ return ""
+ }
+ return *u.Blog
+}
+
+// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise.
+func (u *User) GetCollaborators() int {
+ if u == nil || u.Collaborators == nil {
+ return 0
+ }
+ return *u.Collaborators
+}
+
+// GetCompany returns the Company field if it's non-nil, zero value otherwise.
+func (u *User) GetCompany() string {
+ if u == nil || u.Company == nil {
+ return ""
+ }
+ return *u.Company
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (u *User) GetCreatedAt() Timestamp {
+ if u == nil || u.CreatedAt == nil {
+ return Timestamp{}
+ }
+ return *u.CreatedAt
+}
+
+// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise.
+func (u *User) GetDiskUsage() int {
+ if u == nil || u.DiskUsage == nil {
+ return 0
+ }
+ return *u.DiskUsage
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (u *User) GetEmail() string {
+ if u == nil || u.Email == nil {
+ return ""
+ }
+ return *u.Email
+}
+
+// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise.
+func (u *User) GetEventsURL() string {
+ if u == nil || u.EventsURL == nil {
+ return ""
+ }
+ return *u.EventsURL
+}
+
+// GetFollowers returns the Followers field if it's non-nil, zero value otherwise.
+func (u *User) GetFollowers() int {
+ if u == nil || u.Followers == nil {
+ return 0
+ }
+ return *u.Followers
+}
+
+// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise.
+func (u *User) GetFollowersURL() string {
+ if u == nil || u.FollowersURL == nil {
+ return ""
+ }
+ return *u.FollowersURL
+}
+
+// GetFollowing returns the Following field if it's non-nil, zero value otherwise.
+func (u *User) GetFollowing() int {
+ if u == nil || u.Following == nil {
+ return 0
+ }
+ return *u.Following
+}
+
+// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise.
+func (u *User) GetFollowingURL() string {
+ if u == nil || u.FollowingURL == nil {
+ return ""
+ }
+ return *u.FollowingURL
+}
+
+// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise.
+func (u *User) GetGistsURL() string {
+ if u == nil || u.GistsURL == nil {
+ return ""
+ }
+ return *u.GistsURL
+}
+
+// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise.
+func (u *User) GetGravatarID() string {
+ if u == nil || u.GravatarID == nil {
+ return ""
+ }
+ return *u.GravatarID
+}
+
+// GetHireable returns the Hireable field if it's non-nil, zero value otherwise.
+func (u *User) GetHireable() bool {
+ if u == nil || u.Hireable == nil {
+ return false
+ }
+ return *u.Hireable
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (u *User) GetHTMLURL() string {
+ if u == nil || u.HTMLURL == nil {
+ return ""
+ }
+ return *u.HTMLURL
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (u *User) GetID() int64 {
+ if u == nil || u.ID == nil {
+ return 0
+ }
+ return *u.ID
+}
+
+// GetLocation returns the Location field if it's non-nil, zero value otherwise.
+func (u *User) GetLocation() string {
+ if u == nil || u.Location == nil {
+ return ""
+ }
+ return *u.Location
+}
+
+// GetLogin returns the Login field if it's non-nil, zero value otherwise.
+func (u *User) GetLogin() string {
+ if u == nil || u.Login == nil {
+ return ""
+ }
+ return *u.Login
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (u *User) GetName() string {
+ if u == nil || u.Name == nil {
+ return ""
+ }
+ return *u.Name
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (u *User) GetNodeID() string {
+ if u == nil || u.NodeID == nil {
+ return ""
+ }
+ return *u.NodeID
+}
+
+// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise.
+func (u *User) GetOrganizationsURL() string {
+ if u == nil || u.OrganizationsURL == nil {
+ return ""
+ }
+ return *u.OrganizationsURL
+}
+
+// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise.
+func (u *User) GetOwnedPrivateRepos() int {
+ if u == nil || u.OwnedPrivateRepos == nil {
+ return 0
+ }
+ return *u.OwnedPrivateRepos
+}
+
+// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise.
+func (u *User) GetPermissions() map[string]bool {
+ if u == nil || u.Permissions == nil {
+ return map[string]bool{}
+ }
+ return *u.Permissions
+}
+
+// GetPlan returns the Plan field.
+func (u *User) GetPlan() *Plan {
+ if u == nil {
+ return nil
+ }
+ return u.Plan
+}
+
+// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise.
+func (u *User) GetPrivateGists() int {
+ if u == nil || u.PrivateGists == nil {
+ return 0
+ }
+ return *u.PrivateGists
+}
+
+// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise.
+func (u *User) GetPublicGists() int {
+ if u == nil || u.PublicGists == nil {
+ return 0
+ }
+ return *u.PublicGists
+}
+
+// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise.
+func (u *User) GetPublicRepos() int {
+ if u == nil || u.PublicRepos == nil {
+ return 0
+ }
+ return *u.PublicRepos
+}
+
+// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise.
+func (u *User) GetReceivedEventsURL() string {
+ if u == nil || u.ReceivedEventsURL == nil {
+ return ""
+ }
+ return *u.ReceivedEventsURL
+}
+
+// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise.
+func (u *User) GetReposURL() string {
+ if u == nil || u.ReposURL == nil {
+ return ""
+ }
+ return *u.ReposURL
+}
+
+// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise.
+func (u *User) GetSiteAdmin() bool {
+ if u == nil || u.SiteAdmin == nil {
+ return false
+ }
+ return *u.SiteAdmin
+}
+
+// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise.
+func (u *User) GetStarredURL() string {
+ if u == nil || u.StarredURL == nil {
+ return ""
+ }
+ return *u.StarredURL
+}
+
+// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise.
+func (u *User) GetSubscriptionsURL() string {
+ if u == nil || u.SubscriptionsURL == nil {
+ return ""
+ }
+ return *u.SubscriptionsURL
+}
+
+// GetSuspendedAt returns the SuspendedAt field if it's non-nil, zero value otherwise.
+func (u *User) GetSuspendedAt() Timestamp {
+ if u == nil || u.SuspendedAt == nil {
+ return Timestamp{}
+ }
+ return *u.SuspendedAt
+}
+
+// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise.
+func (u *User) GetTotalPrivateRepos() int {
+ if u == nil || u.TotalPrivateRepos == nil {
+ return 0
+ }
+ return *u.TotalPrivateRepos
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (u *User) GetType() string {
+ if u == nil || u.Type == nil {
+ return ""
+ }
+ return *u.Type
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (u *User) GetUpdatedAt() Timestamp {
+ if u == nil || u.UpdatedAt == nil {
+ return Timestamp{}
+ }
+ return *u.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (u *User) GetURL() string {
+ if u == nil || u.URL == nil {
+ return ""
+ }
+ return *u.URL
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (u *UserContext) GetMessage() string {
+ if u == nil || u.Message == nil {
+ return ""
+ }
+ return *u.Message
+}
+
+// GetOcticon returns the Octicon field if it's non-nil, zero value otherwise.
+func (u *UserContext) GetOcticon() string {
+ if u == nil || u.Octicon == nil {
+ return ""
+ }
+ return *u.Octicon
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (u *UserEmail) GetEmail() string {
+ if u == nil || u.Email == nil {
+ return ""
+ }
+ return *u.Email
+}
+
+// GetPrimary returns the Primary field if it's non-nil, zero value otherwise.
+func (u *UserEmail) GetPrimary() bool {
+ if u == nil || u.Primary == nil {
+ return false
+ }
+ return *u.Primary
+}
+
+// GetVerified returns the Verified field if it's non-nil, zero value otherwise.
+func (u *UserEmail) GetVerified() bool {
+ if u == nil || u.Verified == nil {
+ return false
+ }
+ return *u.Verified
+}
+
+// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetAvatarURL() string {
+ if u == nil || u.AvatarURL == nil {
+ return ""
+ }
+ return *u.AvatarURL
+}
+
+// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetEventsURL() string {
+ if u == nil || u.EventsURL == nil {
+ return ""
+ }
+ return *u.EventsURL
+}
+
+// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetFollowersURL() string {
+ if u == nil || u.FollowersURL == nil {
+ return ""
+ }
+ return *u.FollowersURL
+}
+
+// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetFollowingURL() string {
+ if u == nil || u.FollowingURL == nil {
+ return ""
+ }
+ return *u.FollowingURL
+}
+
+// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetGistsURL() string {
+ if u == nil || u.GistsURL == nil {
+ return ""
+ }
+ return *u.GistsURL
+}
+
+// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetGravatarID() string {
+ if u == nil || u.GravatarID == nil {
+ return ""
+ }
+ return *u.GravatarID
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetID() int64 {
+ if u == nil || u.ID == nil {
+ return 0
+ }
+ return *u.ID
+}
+
+// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetLDAPDN() string {
+ if u == nil || u.LDAPDN == nil {
+ return ""
+ }
+ return *u.LDAPDN
+}
+
+// GetLogin returns the Login field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetLogin() string {
+ if u == nil || u.Login == nil {
+ return ""
+ }
+ return *u.Login
+}
+
+// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetOrganizationsURL() string {
+ if u == nil || u.OrganizationsURL == nil {
+ return ""
+ }
+ return *u.OrganizationsURL
+}
+
+// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetReceivedEventsURL() string {
+ if u == nil || u.ReceivedEventsURL == nil {
+ return ""
+ }
+ return *u.ReceivedEventsURL
+}
+
+// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetReposURL() string {
+ if u == nil || u.ReposURL == nil {
+ return ""
+ }
+ return *u.ReposURL
+}
+
+// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetSiteAdmin() bool {
+ if u == nil || u.SiteAdmin == nil {
+ return false
+ }
+ return *u.SiteAdmin
+}
+
+// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetStarredURL() string {
+ if u == nil || u.StarredURL == nil {
+ return ""
+ }
+ return *u.StarredURL
+}
+
+// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetSubscriptionsURL() string {
+ if u == nil || u.SubscriptionsURL == nil {
+ return ""
+ }
+ return *u.SubscriptionsURL
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetType() string {
+ if u == nil || u.Type == nil {
+ return ""
+ }
+ return *u.Type
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (u *UserLDAPMapping) GetURL() string {
+ if u == nil || u.URL == nil {
+ return ""
+ }
+ return *u.URL
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (u *UserMigration) GetCreatedAt() string {
+ if u == nil || u.CreatedAt == nil {
+ return ""
+ }
+ return *u.CreatedAt
+}
+
+// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise.
+func (u *UserMigration) GetExcludeAttachments() bool {
+ if u == nil || u.ExcludeAttachments == nil {
+ return false
+ }
+ return *u.ExcludeAttachments
+}
+
+// GetGUID returns the GUID field if it's non-nil, zero value otherwise.
+func (u *UserMigration) GetGUID() string {
+ if u == nil || u.GUID == nil {
+ return ""
+ }
+ return *u.GUID
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (u *UserMigration) GetID() int64 {
+ if u == nil || u.ID == nil {
+ return 0
+ }
+ return *u.ID
+}
+
+// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise.
+func (u *UserMigration) GetLockRepositories() bool {
+ if u == nil || u.LockRepositories == nil {
+ return false
+ }
+ return *u.LockRepositories
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (u *UserMigration) GetState() string {
+ if u == nil || u.State == nil {
+ return ""
+ }
+ return *u.State
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (u *UserMigration) GetUpdatedAt() string {
+ if u == nil || u.UpdatedAt == nil {
+ return ""
+ }
+ return *u.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (u *UserMigration) GetURL() string {
+ if u == nil || u.URL == nil {
+ return ""
+ }
+ return *u.URL
+}
+
+// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise.
+func (u *UsersSearchResult) GetIncompleteResults() bool {
+ if u == nil || u.IncompleteResults == nil {
+ return false
+ }
+ return *u.IncompleteResults
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (u *UsersSearchResult) GetTotal() int {
+ if u == nil || u.Total == nil {
+ return 0
+ }
+ return *u.Total
+}
+
+// GetAdminUsers returns the AdminUsers field if it's non-nil, zero value otherwise.
+func (u *UserStats) GetAdminUsers() int {
+ if u == nil || u.AdminUsers == nil {
+ return 0
+ }
+ return *u.AdminUsers
+}
+
+// GetSuspendedUsers returns the SuspendedUsers field if it's non-nil, zero value otherwise.
+func (u *UserStats) GetSuspendedUsers() int {
+ if u == nil || u.SuspendedUsers == nil {
+ return 0
+ }
+ return *u.SuspendedUsers
+}
+
+// GetTotalUsers returns the TotalUsers field if it's non-nil, zero value otherwise.
+func (u *UserStats) GetTotalUsers() int {
+ if u == nil || u.TotalUsers == nil {
+ return 0
+ }
+ return *u.TotalUsers
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (w *WatchEvent) GetAction() string {
+ if w == nil || w.Action == nil {
+ return ""
+ }
+ return *w.Action
+}
+
+// GetInstallation returns the Installation field.
+func (w *WatchEvent) GetInstallation() *Installation {
+ if w == nil {
+ return nil
+ }
+ return w.Installation
+}
+
+// GetRepo returns the Repo field.
+func (w *WatchEvent) GetRepo() *Repository {
+ if w == nil {
+ return nil
+ }
+ return w.Repo
+}
+
+// GetSender returns the Sender field.
+func (w *WatchEvent) GetSender() *User {
+ if w == nil {
+ return nil
+ }
+ return w.Sender
+}
+
+// GetEmail returns the Email field if it's non-nil, zero value otherwise.
+func (w *WebHookAuthor) GetEmail() string {
+ if w == nil || w.Email == nil {
+ return ""
+ }
+ return *w.Email
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (w *WebHookAuthor) GetName() string {
+ if w == nil || w.Name == nil {
+ return ""
+ }
+ return *w.Name
+}
+
+// GetUsername returns the Username field if it's non-nil, zero value otherwise.
+func (w *WebHookAuthor) GetUsername() string {
+ if w == nil || w.Username == nil {
+ return ""
+ }
+ return *w.Username
+}
+
+// GetAuthor returns the Author field.
+func (w *WebHookCommit) GetAuthor() *WebHookAuthor {
+ if w == nil {
+ return nil
+ }
+ return w.Author
+}
+
+// GetCommitter returns the Committer field.
+func (w *WebHookCommit) GetCommitter() *WebHookAuthor {
+ if w == nil {
+ return nil
+ }
+ return w.Committer
+}
+
+// GetDistinct returns the Distinct field if it's non-nil, zero value otherwise.
+func (w *WebHookCommit) GetDistinct() bool {
+ if w == nil || w.Distinct == nil {
+ return false
+ }
+ return *w.Distinct
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (w *WebHookCommit) GetID() string {
+ if w == nil || w.ID == nil {
+ return ""
+ }
+ return *w.ID
+}
+
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (w *WebHookCommit) GetMessage() string {
+ if w == nil || w.Message == nil {
+ return ""
+ }
+ return *w.Message
+}
+
+// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise.
+func (w *WebHookCommit) GetTimestamp() time.Time {
+ if w == nil || w.Timestamp == nil {
+ return time.Time{}
+ }
+ return *w.Timestamp
+}
+
+// GetAfter returns the After field if it's non-nil, zero value otherwise.
+func (w *WebHookPayload) GetAfter() string {
+ if w == nil || w.After == nil {
+ return ""
+ }
+ return *w.After
+}
+
+// GetBefore returns the Before field if it's non-nil, zero value otherwise.
+func (w *WebHookPayload) GetBefore() string {
+ if w == nil || w.Before == nil {
+ return ""
+ }
+ return *w.Before
+}
+
+// GetCompare returns the Compare field if it's non-nil, zero value otherwise.
+func (w *WebHookPayload) GetCompare() string {
+ if w == nil || w.Compare == nil {
+ return ""
+ }
+ return *w.Compare
+}
+
+// GetCreated returns the Created field if it's non-nil, zero value otherwise.
+func (w *WebHookPayload) GetCreated() bool {
+ if w == nil || w.Created == nil {
+ return false
+ }
+ return *w.Created
+}
+
+// GetDeleted returns the Deleted field if it's non-nil, zero value otherwise.
+func (w *WebHookPayload) GetDeleted() bool {
+ if w == nil || w.Deleted == nil {
+ return false
+ }
+ return *w.Deleted
+}
+
+// GetForced returns the Forced field if it's non-nil, zero value otherwise.
+func (w *WebHookPayload) GetForced() bool {
+ if w == nil || w.Forced == nil {
+ return false
+ }
+ return *w.Forced
+}
+
+// GetHeadCommit returns the HeadCommit field.
+func (w *WebHookPayload) GetHeadCommit() *WebHookCommit {
+ if w == nil {
+ return nil
+ }
+ return w.HeadCommit
+}
+
+// GetPusher returns the Pusher field.
+func (w *WebHookPayload) GetPusher() *User {
+ if w == nil {
+ return nil
+ }
+ return w.Pusher
+}
+
+// GetRef returns the Ref field if it's non-nil, zero value otherwise.
+func (w *WebHookPayload) GetRef() string {
+ if w == nil || w.Ref == nil {
+ return ""
+ }
+ return *w.Ref
+}
+
+// GetRepo returns the Repo field.
+func (w *WebHookPayload) GetRepo() *Repository {
+ if w == nil {
+ return nil
+ }
+ return w.Repo
+}
+
+// GetSender returns the Sender field.
+func (w *WebHookPayload) GetSender() *User {
+ if w == nil {
+ return nil
+ }
+ return w.Sender
+}
+
+// GetTotal returns the Total field if it's non-nil, zero value otherwise.
+func (w *WeeklyCommitActivity) GetTotal() int {
+ if w == nil || w.Total == nil {
+ return 0
+ }
+ return *w.Total
+}
+
+// GetWeek returns the Week field if it's non-nil, zero value otherwise.
+func (w *WeeklyCommitActivity) GetWeek() Timestamp {
+ if w == nil || w.Week == nil {
+ return Timestamp{}
+ }
+ return *w.Week
+}
+
+// GetAdditions returns the Additions field if it's non-nil, zero value otherwise.
+func (w *WeeklyStats) GetAdditions() int {
+ if w == nil || w.Additions == nil {
+ return 0
+ }
+ return *w.Additions
+}
+
+// GetCommits returns the Commits field if it's non-nil, zero value otherwise.
+func (w *WeeklyStats) GetCommits() int {
+ if w == nil || w.Commits == nil {
+ return 0
+ }
+ return *w.Commits
+}
+
+// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise.
+func (w *WeeklyStats) GetDeletions() int {
+ if w == nil || w.Deletions == nil {
+ return 0
+ }
+ return *w.Deletions
+}
+
+// GetWeek returns the Week field if it's non-nil, zero value otherwise.
+func (w *WeeklyStats) GetWeek() Timestamp {
+ if w == nil || w.Week == nil {
+ return Timestamp{}
+ }
+ return *w.Week
+}
diff --git a/vendor/github.com/google/go-github/github/github.go b/vendor/github.com/google/go-github/github/github.go
new file mode 100644
index 0000000..af1f1b2
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/github.go
@@ -0,0 +1,996 @@
+// 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.
+
+//go:generate go run gen-accessors.go
+
+package github
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/google/go-querystring/query"
+)
+
+const (
+ defaultBaseURL = "https://api.github.com/"
+ uploadBaseURL = "https://uploads.github.com/"
+ userAgent = "go-github"
+
+ headerRateLimit = "X-RateLimit-Limit"
+ headerRateRemaining = "X-RateLimit-Remaining"
+ headerRateReset = "X-RateLimit-Reset"
+ headerOTP = "X-GitHub-OTP"
+
+ mediaTypeV3 = "application/vnd.github.v3+json"
+ defaultMediaType = "application/octet-stream"
+ mediaTypeV3SHA = "application/vnd.github.v3.sha"
+ mediaTypeV3Diff = "application/vnd.github.v3.diff"
+ mediaTypeV3Patch = "application/vnd.github.v3.patch"
+ mediaTypeOrgPermissionRepo = "application/vnd.github.v3.repository+json"
+
+ // Media Type values to access preview APIs
+
+ // https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/
+ mediaTypeStarringPreview = "application/vnd.github.v3.star+json"
+
+ // https://help.github.com/enterprise/2.4/admin/guides/migrations/exporting-the-github-com-organization-s-repositories/
+ mediaTypeMigrationsPreview = "application/vnd.github.wyandotte-preview+json"
+
+ // https://developer.github.com/changes/2016-04-06-deployment-and-deployment-status-enhancements/
+ mediaTypeDeploymentStatusPreview = "application/vnd.github.ant-man-preview+json"
+
+ // https://developer.github.com/changes/2016-02-19-source-import-preview-api/
+ mediaTypeImportPreview = "application/vnd.github.barred-rock-preview"
+
+ // https://developer.github.com/changes/2016-05-12-reactions-api-preview/
+ mediaTypeReactionsPreview = "application/vnd.github.squirrel-girl-preview"
+
+ // https://developer.github.com/changes/2016-04-04-git-signing-api-preview/
+ mediaTypeGitSigningPreview = "application/vnd.github.cryptographer-preview+json"
+
+ // https://developer.github.com/changes/2016-05-23-timeline-preview-api/
+ mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json"
+
+ // https://developer.github.com/changes/2016-06-14-repository-invitations/
+ mediaTypeRepositoryInvitationsPreview = "application/vnd.github.swamp-thing-preview+json"
+
+ // https://developer.github.com/changes/2016-07-06-github-pages-preiew-api/
+ mediaTypePagesPreview = "application/vnd.github.mister-fantastic-preview+json"
+
+ // https://developer.github.com/changes/2016-09-14-projects-api/
+ mediaTypeProjectsPreview = "application/vnd.github.inertia-preview+json"
+
+ // https://developer.github.com/changes/2016-09-14-Integrations-Early-Access/
+ mediaTypeIntegrationPreview = "application/vnd.github.machine-man-preview+json"
+
+ // https://developer.github.com/changes/2017-01-05-commit-search-api/
+ mediaTypeCommitSearchPreview = "application/vnd.github.cloak-preview+json"
+
+ // https://developer.github.com/changes/2017-02-28-user-blocking-apis-and-webhook/
+ mediaTypeBlockUsersPreview = "application/vnd.github.giant-sentry-fist-preview+json"
+
+ // https://developer.github.com/changes/2017-02-09-community-health/
+ mediaTypeRepositoryCommunityHealthMetricsPreview = "application/vnd.github.black-panther-preview+json"
+
+ // https://developer.github.com/changes/2017-05-23-coc-api/
+ mediaTypeCodesOfConductPreview = "application/vnd.github.scarlet-witch-preview+json"
+
+ // https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/
+ mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json"
+
+ // https://developer.github.com/changes/2017-08-30-preview-nested-teams/
+ mediaTypeNestedTeamsPreview = "application/vnd.github.hellcat-preview+json"
+
+ // https://developer.github.com/changes/2017-11-09-repository-transfer-api-preview/
+ mediaTypeRepositoryTransferPreview = "application/vnd.github.nightshade-preview+json"
+
+ // https://developer.github.com/changes/2018-01-25-organization-invitation-api-preview/
+ mediaTypeOrganizationInvitationPreview = "application/vnd.github.dazzler-preview+json"
+
+ // https://developer.github.com/changes/2018-03-16-protected-branches-required-approving-reviews/
+ mediaTypeRequiredApprovingReviewsPreview = "application/vnd.github.luke-cage-preview+json"
+
+ // https://developer.github.com/changes/2018-02-22-label-description-search-preview/
+ mediaTypeLabelDescriptionSearchPreview = "application/vnd.github.symmetra-preview+json"
+
+ // https://developer.github.com/changes/2018-02-07-team-discussions-api/
+ mediaTypeTeamDiscussionsPreview = "application/vnd.github.echo-preview+json"
+
+ // https://developer.github.com/changes/2018-03-21-hovercard-api-preview/
+ mediaTypeHovercardPreview = "application/vnd.github.hagar-preview+json"
+
+ // https://developer.github.com/changes/2018-01-10-lock-reason-api-preview/
+ mediaTypeLockReasonPreview = "application/vnd.github.sailor-v-preview+json"
+
+ // https://developer.github.com/changes/2018-05-07-new-checks-api-public-beta/
+ mediaTypeCheckRunsPreview = "application/vnd.github.antiope-preview+json"
+
+ // https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/
+ mediaTypePreReceiveHooksPreview = "application/vnd.github.eye-scream-preview"
+)
+
+// A Client manages communication with the GitHub API.
+type Client struct {
+ clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func.
+ client *http.Client // HTTP client used to communicate with the API.
+
+ // Base URL for API requests. Defaults to the public GitHub API, but can be
+ // set to a domain endpoint to use with GitHub Enterprise. BaseURL should
+ // always be specified with a trailing slash.
+ BaseURL *url.URL
+
+ // Base URL for uploading files.
+ UploadURL *url.URL
+
+ // User agent used when communicating with the GitHub API.
+ UserAgent string
+
+ rateMu sync.Mutex
+ rateLimits [categories]Rate // Rate limits for the client as determined by the most recent API calls.
+
+ common service // Reuse a single struct instead of allocating one for each service on the heap.
+
+ // Services used for talking to different parts of the GitHub API.
+ Activity *ActivityService
+ Admin *AdminService
+ Apps *AppsService
+ Authorizations *AuthorizationsService
+ Checks *ChecksService
+ Gists *GistsService
+ Git *GitService
+ Gitignores *GitignoresService
+ Issues *IssuesService
+ Licenses *LicensesService
+ Marketplace *MarketplaceService
+ Migrations *MigrationService
+ Organizations *OrganizationsService
+ Projects *ProjectsService
+ PullRequests *PullRequestsService
+ Reactions *ReactionsService
+ Repositories *RepositoriesService
+ Search *SearchService
+ Teams *TeamsService
+ Users *UsersService
+}
+
+type service struct {
+ client *Client
+}
+
+// ListOptions specifies the optional parameters to various List methods that
+// support pagination.
+type ListOptions struct {
+ // For paginated result sets, page of results to retrieve.
+ Page int `url:"page,omitempty"`
+
+ // For paginated result sets, the number of results to include per page.
+ PerPage int `url:"per_page,omitempty"`
+}
+
+// UploadOptions specifies the parameters to methods that support uploads.
+type UploadOptions struct {
+ Name string `url:"name,omitempty"`
+}
+
+// RawType represents type of raw format of a request instead of JSON.
+type RawType uint8
+
+const (
+ // Diff format.
+ Diff RawType = 1 + iota
+ // Patch format.
+ Patch
+)
+
+// RawOptions specifies parameters when user wants to get raw format of
+// a response instead of JSON.
+type RawOptions struct {
+ Type RawType
+}
+
+// addOptions adds the parameters in opt as URL query parameters to s. opt
+// must be a struct whose fields may contain "url" tags.
+func addOptions(s string, opt interface{}) (string, error) {
+ v := reflect.ValueOf(opt)
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ return s, nil
+ }
+
+ u, err := url.Parse(s)
+ if err != nil {
+ return s, err
+ }
+
+ qs, err := query.Values(opt)
+ if err != nil {
+ return s, err
+ }
+
+ u.RawQuery = qs.Encode()
+ return u.String(), nil
+}
+
+// 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 golang.org/x/oauth2 library).
+func NewClient(httpClient *http.Client) *Client {
+ if httpClient == nil {
+ httpClient = http.DefaultClient
+ }
+ baseURL, _ := url.Parse(defaultBaseURL)
+ uploadURL, _ := url.Parse(uploadBaseURL)
+
+ c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent, UploadURL: uploadURL}
+ c.common.client = c
+ c.Activity = (*ActivityService)(&c.common)
+ c.Admin = (*AdminService)(&c.common)
+ c.Apps = (*AppsService)(&c.common)
+ c.Authorizations = (*AuthorizationsService)(&c.common)
+ c.Checks = (*ChecksService)(&c.common)
+ c.Gists = (*GistsService)(&c.common)
+ c.Git = (*GitService)(&c.common)
+ c.Gitignores = (*GitignoresService)(&c.common)
+ c.Issues = (*IssuesService)(&c.common)
+ c.Licenses = (*LicensesService)(&c.common)
+ c.Marketplace = &MarketplaceService{client: c}
+ c.Migrations = (*MigrationService)(&c.common)
+ c.Organizations = (*OrganizationsService)(&c.common)
+ c.Projects = (*ProjectsService)(&c.common)
+ c.PullRequests = (*PullRequestsService)(&c.common)
+ c.Reactions = (*ReactionsService)(&c.common)
+ c.Repositories = (*RepositoriesService)(&c.common)
+ c.Search = (*SearchService)(&c.common)
+ c.Teams = (*TeamsService)(&c.common)
+ c.Users = (*UsersService)(&c.common)
+ return c
+}
+
+// NewEnterpriseClient returns a new GitHub API client with provided
+// base URL and upload URL (often the same URL).
+// If either URL does not have a trailing slash, one is added automatically.
+// If a nil httpClient is provided, http.DefaultClient will be used.
+//
+// Note that NewEnterpriseClient is a convenience helper only;
+// its behavior is equivalent to using NewClient, followed by setting
+// the BaseURL and UploadURL fields.
+func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*Client, error) {
+ baseEndpoint, err := url.Parse(baseURL)
+ if err != nil {
+ return nil, err
+ }
+ if !strings.HasSuffix(baseEndpoint.Path, "/") {
+ baseEndpoint.Path += "/"
+ }
+
+ uploadEndpoint, err := url.Parse(uploadURL)
+ if err != nil {
+ return nil, err
+ }
+ if !strings.HasSuffix(uploadEndpoint.Path, "/") {
+ uploadEndpoint.Path += "/"
+ }
+
+ c := NewClient(httpClient)
+ c.BaseURL = baseEndpoint
+ c.UploadURL = uploadEndpoint
+ return c, nil
+}
+
+// NewRequest creates an API request. A relative URL can be provided in urlStr,
+// in which case it is resolved relative to the BaseURL of the Client.
+// Relative URLs should always be specified without a preceding slash. If
+// specified, the value pointed to by body is JSON encoded and included as the
+// request body.
+func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
+ if !strings.HasSuffix(c.BaseURL.Path, "/") {
+ return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL)
+ }
+ u, err := c.BaseURL.Parse(urlStr)
+ if err != nil {
+ return nil, err
+ }
+
+ var buf io.ReadWriter
+ if body != nil {
+ buf = new(bytes.Buffer)
+ enc := json.NewEncoder(buf)
+ enc.SetEscapeHTML(false)
+ err := enc.Encode(body)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ req, err := http.NewRequest(method, u.String(), buf)
+ if err != nil {
+ return nil, err
+ }
+
+ if body != nil {
+ req.Header.Set("Content-Type", "application/json")
+ }
+ req.Header.Set("Accept", mediaTypeV3)
+ if c.UserAgent != "" {
+ req.Header.Set("User-Agent", c.UserAgent)
+ }
+ return req, nil
+}
+
+// NewUploadRequest creates an upload request. A relative URL can be provided in
+// urlStr, in which case it is resolved relative to the UploadURL of the Client.
+// Relative URLs should always be specified without a preceding slash.
+func (c *Client) NewUploadRequest(urlStr string, reader io.Reader, size int64, mediaType string) (*http.Request, error) {
+ if !strings.HasSuffix(c.UploadURL.Path, "/") {
+ return nil, fmt.Errorf("UploadURL must have a trailing slash, but %q does not", c.UploadURL)
+ }
+ u, err := c.UploadURL.Parse(urlStr)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("POST", u.String(), reader)
+ if err != nil {
+ return nil, err
+ }
+ req.ContentLength = size
+
+ if mediaType == "" {
+ mediaType = defaultMediaType
+ }
+ req.Header.Set("Content-Type", mediaType)
+ req.Header.Set("Accept", mediaTypeV3)
+ req.Header.Set("User-Agent", c.UserAgent)
+ return req, nil
+}
+
+// Response is a GitHub API response. This wraps the standard http.Response
+// returned from GitHub and provides convenient access to things like
+// pagination links.
+type Response struct {
+ *http.Response
+
+ // These fields provide the page values for paginating through a set of
+ // results. Any or all of these may be set to the zero value for
+ // responses that are not part of a paginated set, or for which there
+ // are no additional pages.
+
+ NextPage int
+ PrevPage int
+ FirstPage int
+ LastPage int
+
+ // Explicitly specify the Rate type so Rate's String() receiver doesn't
+ // propagate to Response.
+ Rate Rate
+}
+
+// newResponse creates a new Response for the provided http.Response.
+// r must not be nil.
+func newResponse(r *http.Response) *Response {
+ response := &Response{Response: r}
+ response.populatePageValues()
+ response.Rate = parseRate(r)
+ return response
+}
+
+// populatePageValues parses the HTTP Link response headers and populates the
+// various pagination link values in the Response.
+func (r *Response) populatePageValues() {
+ if links, ok := r.Response.Header["Link"]; ok && len(links) > 0 {
+ for _, link := range strings.Split(links[0], ",") {
+ segments := strings.Split(strings.TrimSpace(link), ";")
+
+ // link must at least have href and rel
+ if len(segments) < 2 {
+ continue
+ }
+
+ // ensure href is properly formatted
+ if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") {
+ continue
+ }
+
+ // try to pull out page parameter
+ url, err := url.Parse(segments[0][1 : len(segments[0])-1])
+ if err != nil {
+ continue
+ }
+ page := url.Query().Get("page")
+ if page == "" {
+ continue
+ }
+
+ for _, segment := range segments[1:] {
+ switch strings.TrimSpace(segment) {
+ case `rel="next"`:
+ r.NextPage, _ = strconv.Atoi(page)
+ case `rel="prev"`:
+ r.PrevPage, _ = strconv.Atoi(page)
+ case `rel="first"`:
+ r.FirstPage, _ = strconv.Atoi(page)
+ case `rel="last"`:
+ r.LastPage, _ = strconv.Atoi(page)
+ }
+
+ }
+ }
+ }
+}
+
+// parseRate parses the rate related headers.
+func parseRate(r *http.Response) Rate {
+ var rate Rate
+ if limit := r.Header.Get(headerRateLimit); limit != "" {
+ rate.Limit, _ = strconv.Atoi(limit)
+ }
+ if remaining := r.Header.Get(headerRateRemaining); remaining != "" {
+ rate.Remaining, _ = strconv.Atoi(remaining)
+ }
+ if reset := r.Header.Get(headerRateReset); reset != "" {
+ if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 {
+ rate.Reset = Timestamp{time.Unix(v, 0)}
+ }
+ }
+ return rate
+}
+
+// Do sends an API request and returns the API response. The API response is
+// JSON decoded and stored in the value pointed to by v, or returned as an
+// error if an API error has occurred. If v implements the io.Writer
+// interface, the raw response body will be written to v, without attempting to
+// first decode it. If rate limit is exceeded and reset time is in the future,
+// Do returns *RateLimitError immediately without making a network API call.
+//
+// The provided ctx must be non-nil. If it is canceled or times out,
+// ctx.Err() will be returned.
+func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) {
+ req = withContext(ctx, req)
+
+ rateLimitCategory := category(req.URL.Path)
+
+ // If we've hit rate limit, don't make further requests before Reset time.
+ if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil {
+ return &Response{
+ Response: err.Response,
+ Rate: err.Rate,
+ }, err
+ }
+
+ resp, err := c.client.Do(req)
+ if err != nil {
+ // If we got an error, and the context has been canceled,
+ // the context's error is probably more useful.
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ default:
+ }
+
+ // If the error type is *url.Error, sanitize its URL before returning.
+ if e, ok := err.(*url.Error); ok {
+ if url, err := url.Parse(e.URL); err == nil {
+ e.URL = sanitizeURL(url).String()
+ return nil, e
+ }
+ }
+
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ response := newResponse(resp)
+
+ c.rateMu.Lock()
+ c.rateLimits[rateLimitCategory] = response.Rate
+ c.rateMu.Unlock()
+
+ err = CheckResponse(resp)
+ if err != nil {
+ // Even though there was an error, we still return the response
+ // in case the caller wants to inspect it further.
+ // However, if the error is AcceptedError, decode it below before
+ // returning from this function and closing the response body.
+ if _, ok := err.(*AcceptedError); !ok {
+ return response, err
+ }
+ }
+
+ if v != nil {
+ if w, ok := v.(io.Writer); ok {
+ io.Copy(w, resp.Body)
+ } else {
+ decErr := json.NewDecoder(resp.Body).Decode(v)
+ if decErr == io.EOF {
+ decErr = nil // ignore EOF errors caused by empty response body
+ }
+ if decErr != nil {
+ err = decErr
+ }
+ }
+ }
+
+ return response, err
+}
+
+// checkRateLimitBeforeDo does not make any network calls, but uses existing knowledge from
+// current client state in order to quickly check if *RateLimitError can be immediately returned
+// from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily.
+// Otherwise it returns nil, and Client.Do should proceed normally.
+func (c *Client) checkRateLimitBeforeDo(req *http.Request, rateLimitCategory rateLimitCategory) *RateLimitError {
+ c.rateMu.Lock()
+ rate := c.rateLimits[rateLimitCategory]
+ c.rateMu.Unlock()
+ if !rate.Reset.Time.IsZero() && rate.Remaining == 0 && time.Now().Before(rate.Reset.Time) {
+ // Create a fake response.
+ resp := &http.Response{
+ Status: http.StatusText(http.StatusForbidden),
+ StatusCode: http.StatusForbidden,
+ Request: req,
+ Header: make(http.Header),
+ Body: ioutil.NopCloser(strings.NewReader("")),
+ }
+ return &RateLimitError{
+ Rate: rate,
+ Response: resp,
+ Message: fmt.Sprintf("API rate limit of %v still exceeded until %v, not making remote request.", rate.Limit, rate.Reset.Time),
+ }
+ }
+
+ return nil
+}
+
+/*
+An ErrorResponse reports one or more errors caused by an API request.
+
+GitHub API docs: https://developer.github.com/v3/#client-errors
+*/
+type ErrorResponse struct {
+ Response *http.Response // HTTP response that caused this error
+ Message string `json:"message"` // error message
+ Errors []Error `json:"errors"` // more detail on individual errors
+ // Block is only populated on certain types of errors such as code 451.
+ // See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/
+ // for more information.
+ Block *struct {
+ Reason string `json:"reason,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ } `json:"block,omitempty"`
+ // Most errors will also include a documentation_url field pointing
+ // to some content that might help you resolve the error, see
+ // https://developer.github.com/v3/#client-errors
+ DocumentationURL string `json:"documentation_url,omitempty"`
+}
+
+func (r *ErrorResponse) Error() string {
+ return fmt.Sprintf("%v %v: %d %v %+v",
+ r.Response.Request.Method, sanitizeURL(r.Response.Request.URL),
+ r.Response.StatusCode, r.Message, r.Errors)
+}
+
+// TwoFactorAuthError occurs when using HTTP Basic Authentication for a user
+// that has two-factor authentication enabled. The request can be reattempted
+// by providing a one-time password in the request.
+type TwoFactorAuthError ErrorResponse
+
+func (r *TwoFactorAuthError) Error() string { return (*ErrorResponse)(r).Error() }
+
+// RateLimitError occurs when GitHub returns 403 Forbidden response with a rate limit
+// remaining value of 0, and error message starts with "API rate limit exceeded for ".
+type RateLimitError struct {
+ Rate Rate // Rate specifies last known rate limit for the client
+ Response *http.Response // HTTP response that caused this error
+ Message string `json:"message"` // error message
+}
+
+func (r *RateLimitError) Error() string {
+ return fmt.Sprintf("%v %v: %d %v %v",
+ r.Response.Request.Method, sanitizeURL(r.Response.Request.URL),
+ r.Response.StatusCode, r.Message, formatRateReset(r.Rate.Reset.Time.Sub(time.Now())))
+}
+
+// AcceptedError occurs when GitHub returns 202 Accepted response with an
+// empty body, which means a job was scheduled on the GitHub side to process
+// the information needed and cache it.
+// Technically, 202 Accepted is not a real error, it's just used to
+// indicate that results are not ready yet, but should be available soon.
+// The request can be repeated after some time.
+type AcceptedError struct{}
+
+func (*AcceptedError) Error() string {
+ return "job scheduled on GitHub side; try again later"
+}
+
+// AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the
+// "documentation_url" field value equal to "https://developer.github.com/v3/#abuse-rate-limits".
+type AbuseRateLimitError struct {
+ Response *http.Response // HTTP response that caused this error
+ Message string `json:"message"` // error message
+
+ // RetryAfter is provided with some abuse rate limit errors. If present,
+ // it is the amount of time that the client should wait before retrying.
+ // Otherwise, the client should try again later (after an unspecified amount of time).
+ RetryAfter *time.Duration
+}
+
+func (r *AbuseRateLimitError) Error() string {
+ return fmt.Sprintf("%v %v: %d %v",
+ r.Response.Request.Method, sanitizeURL(r.Response.Request.URL),
+ r.Response.StatusCode, r.Message)
+}
+
+// sanitizeURL redacts the client_secret parameter from the URL which may be
+// exposed to the user.
+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:
+
+ missing:
+ resource does not exist
+ missing_field:
+ a required field on a resource has not been set
+ invalid:
+ the formatting of a field is invalid
+ already_exists:
+ another resource has the same valid as this field
+ custom:
+ some resources return this (e.g. github.User.CreateKey()), additional
+ information is set in the Message field of the Error
+
+GitHub API docs: https://developer.github.com/v3/#client-errors
+*/
+type Error struct {
+ Resource string `json:"resource"` // resource on which the error occurred
+ Field string `json:"field"` // field on which the error occurred
+ Code string `json:"code"` // validation error code
+ Message string `json:"message"` // Message describing the error. Errors with Code == "custom" will always have this set.
+}
+
+func (e *Error) Error() string {
+ return fmt.Sprintf("%v error caused by %v field on %v resource",
+ e.Code, e.Field, e.Resource)
+}
+
+// CheckResponse checks the API response for errors, and returns them if
+// present. A response is considered an error if it has a status code outside
+// the 200 range or equal to 202 Accepted.
+// API error responses are expected to have either no response
+// body, or a JSON response body that maps to ErrorResponse. Any other
+// response body will be silently ignored.
+//
+// The error type will be *RateLimitError for rate limit exceeded errors,
+// *AcceptedError for 202 Accepted status codes,
+// and *TwoFactorAuthError for two-factor authentication errors.
+func CheckResponse(r *http.Response) error {
+ if r.StatusCode == http.StatusAccepted {
+ return &AcceptedError{}
+ }
+ if c := r.StatusCode; 200 <= c && c <= 299 {
+ return nil
+ }
+ errorResponse := &ErrorResponse{Response: r}
+ data, err := ioutil.ReadAll(r.Body)
+ if err == nil && data != nil {
+ json.Unmarshal(data, errorResponse)
+ }
+ switch {
+ case r.StatusCode == http.StatusUnauthorized && strings.HasPrefix(r.Header.Get(headerOTP), "required"):
+ return (*TwoFactorAuthError)(errorResponse)
+ case r.StatusCode == http.StatusForbidden && r.Header.Get(headerRateRemaining) == "0" && strings.HasPrefix(errorResponse.Message, "API rate limit exceeded for "):
+ return &RateLimitError{
+ Rate: parseRate(r),
+ Response: errorResponse.Response,
+ Message: errorResponse.Message,
+ }
+ case r.StatusCode == http.StatusForbidden && strings.HasSuffix(errorResponse.DocumentationURL, "/v3/#abuse-rate-limits"):
+ abuseRateLimitError := &AbuseRateLimitError{
+ Response: errorResponse.Response,
+ Message: errorResponse.Message,
+ }
+ if v := r.Header["Retry-After"]; len(v) > 0 {
+ // According to GitHub support, the "Retry-After" header value will be
+ // an integer which represents the number of seconds that one should
+ // wait before resuming making requests.
+ retryAfterSeconds, _ := strconv.ParseInt(v[0], 10, 64) // Error handling is noop.
+ retryAfter := time.Duration(retryAfterSeconds) * time.Second
+ abuseRateLimitError.RetryAfter = &retryAfter
+ }
+ return abuseRateLimitError
+ default:
+ return errorResponse
+ }
+}
+
+// parseBoolResponse determines the boolean result from a GitHub API response.
+// Several GitHub API methods return boolean responses indicated by the HTTP
+// status code in the response (true indicated by a 204, false indicated by a
+// 404). This helper function will determine that result and hide the 404
+// error if present. Any other error will be returned through as-is.
+func parseBoolResponse(err error) (bool, error) {
+ if err == nil {
+ return true, nil
+ }
+
+ if err, ok := err.(*ErrorResponse); ok && err.Response.StatusCode == http.StatusNotFound {
+ // Simply false. In this one case, we do not pass the error through.
+ return false, nil
+ }
+
+ // some other real error occurred
+ return false, err
+}
+
+// Rate represents the rate limit for the current client.
+type Rate struct {
+ // The number of requests per hour the client is currently limited to.
+ Limit int `json:"limit"`
+
+ // The number of remaining requests the client can make this hour.
+ Remaining int `json:"remaining"`
+
+ // The time at which the current rate limit will reset.
+ Reset Timestamp `json:"reset"`
+}
+
+func (r Rate) String() string {
+ return Stringify(r)
+}
+
+// RateLimits represents the rate limits for the current client.
+type RateLimits struct {
+ // The rate limit for non-search API requests. Unauthenticated
+ // requests are limited to 60 per hour. Authenticated requests are
+ // limited to 5,000 per hour.
+ //
+ // GitHub API docs: https://developer.github.com/v3/#rate-limiting
+ Core *Rate `json:"core"`
+
+ // The rate limit for search API requests. Unauthenticated requests
+ // are limited to 10 requests per minutes. Authenticated requests are
+ // limited to 30 per minute.
+ //
+ // GitHub API docs: https://developer.github.com/v3/search/#rate-limit
+ Search *Rate `json:"search"`
+}
+
+func (r RateLimits) String() string {
+ return Stringify(r)
+}
+
+type rateLimitCategory uint8
+
+const (
+ coreCategory rateLimitCategory = iota
+ searchCategory
+
+ categories // An array of this length will be able to contain all rate limit categories.
+)
+
+// category returns the rate limit category of the endpoint, determined by Request.URL.Path.
+func category(path string) rateLimitCategory {
+ switch {
+ default:
+ return coreCategory
+ case strings.HasPrefix(path, "/search/"):
+ return searchCategory
+ }
+}
+
+// RateLimits returns the rate limits for the current client.
+func (c *Client) RateLimits(ctx context.Context) (*RateLimits, *Response, error) {
+ req, err := c.NewRequest("GET", "rate_limit", nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ response := new(struct {
+ Resources *RateLimits `json:"resources"`
+ })
+ resp, err := c.Do(ctx, req, response)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if response.Resources != nil {
+ c.rateMu.Lock()
+ if response.Resources.Core != nil {
+ c.rateLimits[coreCategory] = *response.Resources.Core
+ }
+ if response.Resources.Search != nil {
+ c.rateLimits[searchCategory] = *response.Resources.Search
+ }
+ c.rateMu.Unlock()
+ }
+
+ return response.Resources, resp, nil
+}
+
+/*
+UnauthenticatedRateLimitedTransport allows you to make unauthenticated calls
+that need to use a higher rate limit associated with your OAuth application.
+
+ t := &github.UnauthenticatedRateLimitedTransport{
+ ClientID: "your app's client ID",
+ ClientSecret: "your app's client secret",
+ }
+ client := github.NewClient(t.Client())
+
+This will append the querystring params client_id=xxx&client_secret=yyy to all
+requests.
+
+See https://developer.github.com/v3/#unauthenticated-rate-limited-requests for
+more information.
+*/
+type UnauthenticatedRateLimitedTransport struct {
+ // ClientID is the GitHub OAuth client ID of the current application, which
+ // can be found by selecting its entry in the list at
+ // https://github.com/settings/applications.
+ ClientID string
+
+ // ClientSecret is the GitHub OAuth client secret of the current
+ // application.
+ ClientSecret string
+
+ // Transport is the underlying HTTP transport to use when making requests.
+ // It will default to http.DefaultTransport if nil.
+ Transport http.RoundTripper
+}
+
+// RoundTrip implements the RoundTripper interface.
+func (t *UnauthenticatedRateLimitedTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+ if t.ClientID == "" {
+ return nil, errors.New("t.ClientID is empty")
+ }
+ if t.ClientSecret == "" {
+ return nil, errors.New("t.ClientSecret is empty")
+ }
+
+ // To set extra querystring params, we must make a copy of the Request so
+ // that we don't modify the Request we were given. This is required by the
+ // specification of http.RoundTripper.
+ //
+ // Since we are going to modify only req.URL here, we only need a deep copy
+ // of req.URL.
+ req2 := new(http.Request)
+ *req2 = *req
+ req2.URL = new(url.URL)
+ *req2.URL = *req.URL
+
+ q := req2.URL.Query()
+ q.Set("client_id", t.ClientID)
+ q.Set("client_secret", t.ClientSecret)
+ req2.URL.RawQuery = q.Encode()
+
+ // Make the HTTP request.
+ return t.transport().RoundTrip(req2)
+}
+
+// Client returns an *http.Client that makes requests which are subject to the
+// rate limit of your OAuth application.
+func (t *UnauthenticatedRateLimitedTransport) Client() *http.Client {
+ return &http.Client{Transport: t}
+}
+
+func (t *UnauthenticatedRateLimitedTransport) transport() http.RoundTripper {
+ if t.Transport != nil {
+ return t.Transport
+ }
+ return http.DefaultTransport
+}
+
+// BasicAuthTransport is an http.RoundTripper that authenticates all requests
+// using HTTP Basic Authentication with the provided username and password. It
+// additionally supports users who have two-factor authentication enabled on
+// their GitHub account.
+type BasicAuthTransport struct {
+ Username string // GitHub username
+ Password string // GitHub password
+ OTP string // one-time password for users with two-factor auth enabled
+
+ // Transport is the underlying HTTP transport to use when making requests.
+ // It will default to http.DefaultTransport if nil.
+ Transport http.RoundTripper
+}
+
+// RoundTrip implements the RoundTripper interface.
+func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+ // To set extra headers, we must make a copy of the Request so
+ // that we don't modify the Request we were given. This is required by the
+ // specification of http.RoundTripper.
+ //
+ // Since we are going to modify only req.Header here, we only need a deep copy
+ // of req.Header.
+ req2 := new(http.Request)
+ *req2 = *req
+ req2.Header = make(http.Header, len(req.Header))
+ for k, s := range req.Header {
+ req2.Header[k] = append([]string(nil), s...)
+ }
+
+ req2.SetBasicAuth(t.Username, t.Password)
+ if t.OTP != "" {
+ req2.Header.Set(headerOTP, t.OTP)
+ }
+ return t.transport().RoundTrip(req2)
+}
+
+// Client returns an *http.Client that makes requests that are authenticated
+// using HTTP Basic Authentication.
+func (t *BasicAuthTransport) Client() *http.Client {
+ return &http.Client{Transport: t}
+}
+
+func (t *BasicAuthTransport) transport() http.RoundTripper {
+ if t.Transport != nil {
+ return t.Transport
+ }
+ return http.DefaultTransport
+}
+
+// formatRateReset formats d to look like "[rate reset in 2s]" or
+// "[rate reset in 87m02s]" for the positive durations. And like "[rate limit was reset 87m02s ago]"
+// for the negative cases.
+func formatRateReset(d time.Duration) string {
+ isNegative := d < 0
+ if isNegative {
+ d *= -1
+ }
+ secondsTotal := int(0.5 + d.Seconds())
+ minutes := secondsTotal / 60
+ seconds := secondsTotal - minutes*60
+
+ var timeString string
+ if minutes > 0 {
+ timeString = fmt.Sprintf("%dm%02ds", minutes, seconds)
+ } else {
+ timeString = fmt.Sprintf("%ds", seconds)
+ }
+
+ if isNegative {
+ return fmt.Sprintf("[rate limit was reset %v ago]", timeString)
+ }
+ return fmt.Sprintf("[rate reset in %v]", timeString)
+}
+
+// Bool is a helper routine that allocates a new bool value
+// to store v and returns a pointer to it.
+func Bool(v bool) *bool { return &v }
+
+// Int is a helper routine that allocates a new int value
+// to store v and returns a pointer to it.
+func Int(v int) *int { return &v }
+
+// Int64 is a helper routine that allocates a new int64 value
+// to store v and returns a pointer to it.
+func Int64(v int64) *int64 { return &v }
+
+// String is a helper routine that allocates a new string value
+// to store v and returns a pointer to it.
+func String(v string) *string { return &v }
diff --git a/vendor/github.com/google/go-github/github/github_test.go b/vendor/github.com/google/go-github/github/github_test.go
new file mode 100644
index 0000000..da29e1e
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/github_test.go
@@ -0,0 +1,1083 @@
+// 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 (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "os"
+ "path"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+)
+
+const (
+ // baseURLPath is a non-empty Client.BaseURL path to use during tests,
+ // to ensure relative URLs are used for all endpoints. See issue #752.
+ baseURLPath = "/api-v3"
+)
+
+// setup sets up a test HTTP server along with a github.Client that is
+// configured to talk to that test server. Tests should register handlers on
+// mux which provide mock responses for the API method being tested.
+func setup() (client *Client, mux *http.ServeMux, serverURL string, teardown func()) {
+ // mux is the HTTP request multiplexer used with the test server.
+ mux = http.NewServeMux()
+
+ // We want to ensure that tests catch mistakes where the endpoint URL is
+ // specified as absolute rather than relative. It only makes a difference
+ // when there's a non-empty base URL path. So, use that. See issue #752.
+ apiHandler := http.NewServeMux()
+ apiHandler.Handle(baseURLPath+"/", http.StripPrefix(baseURLPath, mux))
+ apiHandler.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
+ fmt.Fprintln(os.Stderr, "FAIL: Client.BaseURL path prefix is not preserved in the request URL:")
+ fmt.Fprintln(os.Stderr)
+ fmt.Fprintln(os.Stderr, "\t"+req.URL.String())
+ fmt.Fprintln(os.Stderr)
+ fmt.Fprintln(os.Stderr, "\tDid you accidentally use an absolute endpoint URL rather than relative?")
+ fmt.Fprintln(os.Stderr, "\tSee https://github.com/google/go-github/issues/752 for information.")
+ http.Error(w, "Client.BaseURL path prefix is not preserved in the request URL.", http.StatusInternalServerError)
+ })
+
+ // server is a test HTTP server used to provide mock API responses.
+ server := httptest.NewServer(apiHandler)
+
+ // client is the GitHub client being tested and is
+ // configured to use test server.
+ client = NewClient(nil)
+ url, _ := url.Parse(server.URL + baseURLPath + "/")
+ client.BaseURL = url
+ client.UploadURL = url
+
+ return client, mux, server.URL, server.Close
+}
+
+// openTestFile creates a new file with the given name and content for testing.
+// In order to ensure the exact file name, this function will create a new temp
+// directory, and create the file in that directory. It is the caller's
+// responsibility to remove the directory and its contents when no longer needed.
+func openTestFile(name, content string) (file *os.File, dir string, err error) {
+ dir, err = ioutil.TempDir("", "go-github")
+ if err != nil {
+ return nil, dir, err
+ }
+
+ file, err = os.OpenFile(path.Join(dir, name), os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
+ if err != nil {
+ return nil, dir, err
+ }
+
+ fmt.Fprint(file, content)
+
+ // close and re-open the file to keep file.Stat() happy
+ file.Close()
+ file, err = os.Open(file.Name())
+ if err != nil {
+ return nil, dir, err
+ }
+
+ return file, dir, err
+}
+
+func testMethod(t *testing.T, r *http.Request, want string) {
+ if got := r.Method; got != want {
+ t.Errorf("Request method: %v, want %v", got, want)
+ }
+}
+
+type values map[string]string
+
+func testFormValues(t *testing.T, r *http.Request, values values) {
+ want := url.Values{}
+ for k, v := range values {
+ want.Set(k, v)
+ }
+
+ r.ParseForm()
+ if got := r.Form; !reflect.DeepEqual(got, want) {
+ t.Errorf("Request parameters: %v, want %v", got, want)
+ }
+}
+
+func testHeader(t *testing.T, r *http.Request, header string, want string) {
+ if got := r.Header.Get(header); got != want {
+ t.Errorf("Header.Get(%q) returned %q, want %q", header, got, want)
+ }
+}
+
+func testURLParseError(t *testing.T, err error) {
+ if err == nil {
+ t.Errorf("Expected error to be returned")
+ }
+ if err, ok := err.(*url.Error); !ok || err.Op != "parse" {
+ t.Errorf("Expected URL parse error, got %+v", err)
+ }
+}
+
+func testBody(t *testing.T, r *http.Request, want string) {
+ b, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ t.Errorf("Error reading request body: %v", err)
+ }
+ if got := string(b); got != want {
+ t.Errorf("request Body is %s, want %s", got, want)
+ }
+}
+
+// Helper function to test that a value is marshalled to JSON as expected.
+func testJSONMarshal(t *testing.T, v interface{}, want string) {
+ j, err := json.Marshal(v)
+ if err != nil {
+ t.Errorf("Unable to marshal JSON for %v", v)
+ }
+
+ w := new(bytes.Buffer)
+ err = json.Compact(w, []byte(want))
+ if err != nil {
+ t.Errorf("String is not valid json: %s", want)
+ }
+
+ if w.String() != string(j) {
+ t.Errorf("json.Marshal(%q) returned %s, want %s", v, j, w)
+ }
+
+ // now go the other direction and make sure things unmarshal as expected
+ u := reflect.ValueOf(v).Interface()
+ if err := json.Unmarshal([]byte(want), u); err != nil {
+ t.Errorf("Unable to unmarshal JSON for %v", want)
+ }
+
+ if !reflect.DeepEqual(v, u) {
+ t.Errorf("json.Unmarshal(%q) returned %s, want %s", want, u, v)
+ }
+}
+
+func TestNewClient(t *testing.T) {
+ c := NewClient(nil)
+
+ if got, want := c.BaseURL.String(), defaultBaseURL; got != want {
+ t.Errorf("NewClient BaseURL is %v, want %v", got, want)
+ }
+ if got, want := c.UserAgent, userAgent; got != want {
+ t.Errorf("NewClient UserAgent is %v, want %v", got, want)
+ }
+}
+
+func TestNewEnterpriseClient(t *testing.T) {
+ baseURL := "https://custom-url/"
+ uploadURL := "https://custom-upload-url/"
+ c, err := NewEnterpriseClient(baseURL, uploadURL, nil)
+ if err != nil {
+ t.Fatalf("NewEnterpriseClient returned unexpected error: %v", err)
+ }
+
+ if got, want := c.BaseURL.String(), baseURL; got != want {
+ t.Errorf("NewClient BaseURL is %v, want %v", got, want)
+ }
+ if got, want := c.UploadURL.String(), uploadURL; got != want {
+ t.Errorf("NewClient UploadURL is %v, want %v", got, want)
+ }
+}
+
+func TestNewEnterpriseClient_addsTrailingSlashToURLs(t *testing.T) {
+ baseURL := "https://custom-url"
+ uploadURL := "https://custom-upload-url"
+ formattedBaseURL := baseURL + "/"
+ formattedUploadURL := uploadURL + "/"
+
+ c, err := NewEnterpriseClient(baseURL, uploadURL, nil)
+ if err != nil {
+ t.Fatalf("NewEnterpriseClient returned unexpected error: %v", err)
+ }
+
+ if got, want := c.BaseURL.String(), formattedBaseURL; got != want {
+ t.Errorf("NewClient BaseURL is %v, want %v", got, want)
+ }
+ if got, want := c.UploadURL.String(), formattedUploadURL; got != want {
+ t.Errorf("NewClient UploadURL is %v, want %v", got, want)
+ }
+}
+
+// Ensure that length of Client.rateLimits is the same as number of fields in RateLimits struct.
+func TestClient_rateLimits(t *testing.T) {
+ if got, want := len(Client{}.rateLimits), reflect.TypeOf(RateLimits{}).NumField(); got != want {
+ t.Errorf("len(Client{}.rateLimits) is %v, want %v", got, want)
+ }
+}
+
+func TestNewRequest(t *testing.T) {
+ c := NewClient(nil)
+
+ inURL, outURL := "/foo", defaultBaseURL+"foo"
+ inBody, outBody := &User{Login: String("l")}, `{"login":"l"}`+"\n"
+ req, _ := c.NewRequest("GET", inURL, inBody)
+
+ // test that relative URL was expanded
+ if got, want := req.URL.String(), outURL; got != want {
+ t.Errorf("NewRequest(%q) URL is %v, want %v", inURL, got, want)
+ }
+
+ // test that body was JSON encoded
+ body, _ := ioutil.ReadAll(req.Body)
+ if got, want := string(body), outBody; got != want {
+ t.Errorf("NewRequest(%q) Body is %v, want %v", inBody, got, want)
+ }
+
+ // test that default user-agent is attached to the request
+ if got, want := req.Header.Get("User-Agent"), c.UserAgent; got != want {
+ t.Errorf("NewRequest() User-Agent is %v, want %v", got, want)
+ }
+}
+
+func TestNewRequest_invalidJSON(t *testing.T) {
+ c := NewClient(nil)
+
+ type T struct {
+ A map[interface{}]interface{}
+ }
+ _, err := c.NewRequest("GET", ".", &T{})
+
+ if err == nil {
+ t.Error("Expected error to be returned.")
+ }
+ if err, ok := err.(*json.UnsupportedTypeError); !ok {
+ t.Errorf("Expected a JSON error; got %#v.", err)
+ }
+}
+
+func TestNewRequest_badURL(t *testing.T) {
+ c := NewClient(nil)
+ _, err := c.NewRequest("GET", ":", nil)
+ testURLParseError(t, err)
+}
+
+// ensure that no User-Agent header is set if the client's UserAgent is empty.
+// This caused a problem with Google's internal http client.
+func TestNewRequest_emptyUserAgent(t *testing.T) {
+ c := NewClient(nil)
+ c.UserAgent = ""
+ req, err := c.NewRequest("GET", ".", nil)
+ if err != nil {
+ t.Fatalf("NewRequest returned unexpected error: %v", err)
+ }
+ if _, ok := req.Header["User-Agent"]; ok {
+ t.Fatal("constructed request contains unexpected User-Agent header")
+ }
+}
+
+// If a nil body is passed to github.NewRequest, make sure that nil is also
+// passed to http.NewRequest. In most cases, passing an io.Reader that returns
+// no content is fine, since there is no difference between an HTTP request
+// body that is an empty string versus one that is not set at all. However in
+// certain cases, intermediate systems may treat these differently resulting in
+// subtle errors.
+func TestNewRequest_emptyBody(t *testing.T) {
+ c := NewClient(nil)
+ req, err := c.NewRequest("GET", ".", nil)
+ if err != nil {
+ t.Fatalf("NewRequest returned unexpected error: %v", err)
+ }
+ if req.Body != nil {
+ t.Fatalf("constructed request contains a non-nil Body")
+ }
+}
+
+func TestNewRequest_errorForNoTrailingSlash(t *testing.T) {
+ tests := []struct {
+ rawurl string
+ wantError bool
+ }{
+ {rawurl: "https://example.com/api/v3", wantError: true},
+ {rawurl: "https://example.com/api/v3/", wantError: false},
+ }
+ c := NewClient(nil)
+ for _, test := range tests {
+ u, err := url.Parse(test.rawurl)
+ if err != nil {
+ t.Fatalf("url.Parse returned unexpected error: %v.", err)
+ }
+ c.BaseURL = u
+ if _, err := c.NewRequest(http.MethodGet, "test", nil); test.wantError && err == nil {
+ t.Fatalf("Expected error to be returned.")
+ } else if !test.wantError && err != nil {
+ t.Fatalf("NewRequest returned unexpected error: %v.", err)
+ }
+ }
+}
+
+func TestNewUploadRequest_errorForNoTrailingSlash(t *testing.T) {
+ tests := []struct {
+ rawurl string
+ wantError bool
+ }{
+ {rawurl: "https://example.com/api/uploads", wantError: true},
+ {rawurl: "https://example.com/api/uploads/", wantError: false},
+ }
+ c := NewClient(nil)
+ for _, test := range tests {
+ u, err := url.Parse(test.rawurl)
+ if err != nil {
+ t.Fatalf("url.Parse returned unexpected error: %v.", err)
+ }
+ c.UploadURL = u
+ if _, err = c.NewUploadRequest("test", nil, 0, ""); test.wantError && err == nil {
+ t.Fatalf("Expected error to be returned.")
+ } else if !test.wantError && err != nil {
+ t.Fatalf("NewUploadRequest returned unexpected error: %v.", err)
+ }
+ }
+}
+
+func TestResponse_populatePageValues(t *testing.T) {
+ r := http.Response{
+ Header: http.Header{
+ "Link": {`; rel="first",` +
+ ` ; rel="prev",` +
+ ` ; rel="next",` +
+ ` ; rel="last"`,
+ },
+ },
+ }
+
+ response := newResponse(&r)
+ if got, want := response.FirstPage, 1; got != want {
+ t.Errorf("response.FirstPage: %v, want %v", got, want)
+ }
+ if got, want := response.PrevPage, 2; want != got {
+ t.Errorf("response.PrevPage: %v, want %v", got, want)
+ }
+ if got, want := response.NextPage, 4; want != got {
+ t.Errorf("response.NextPage: %v, want %v", got, want)
+ }
+ if got, want := response.LastPage, 5; want != got {
+ t.Errorf("response.LastPage: %v, want %v", got, want)
+ }
+}
+
+func TestResponse_populatePageValues_invalid(t *testing.T) {
+ r := http.Response{
+ Header: http.Header{
+ "Link": {`,` +
+ `; rel="first",` +
+ `https://api.github.com/?page=2; rel="prev",` +
+ `; rel="next",` +
+ `; rel="last"`,
+ },
+ },
+ }
+
+ response := newResponse(&r)
+ if got, want := response.FirstPage, 0; got != want {
+ t.Errorf("response.FirstPage: %v, want %v", got, want)
+ }
+ if got, want := response.PrevPage, 0; got != want {
+ t.Errorf("response.PrevPage: %v, want %v", got, want)
+ }
+ if got, want := response.NextPage, 0; got != want {
+ t.Errorf("response.NextPage: %v, want %v", got, want)
+ }
+ if got, want := response.LastPage, 0; got != want {
+ t.Errorf("response.LastPage: %v, want %v", got, want)
+ }
+
+ // more invalid URLs
+ r = http.Response{
+ Header: http.Header{
+ "Link": {`; rel="first"`},
+ },
+ }
+
+ response = newResponse(&r)
+ if got, want := response.FirstPage, 0; got != want {
+ t.Errorf("response.FirstPage: %v, want %v", got, want)
+ }
+}
+
+func TestDo(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ type foo struct {
+ A string
+ }
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"A":"a"}`)
+ })
+
+ req, _ := client.NewRequest("GET", ".", nil)
+ body := new(foo)
+ client.Do(context.Background(), req, body)
+
+ want := &foo{"a"}
+ if !reflect.DeepEqual(body, want) {
+ t.Errorf("Response body = %v, want %v", body, want)
+ }
+}
+
+func TestDo_httpError(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ http.Error(w, "Bad Request", 400)
+ })
+
+ req, _ := client.NewRequest("GET", ".", nil)
+ resp, err := client.Do(context.Background(), req, nil)
+
+ if err == nil {
+ t.Fatal("Expected HTTP 400 error, got no error.")
+ }
+ if resp.StatusCode != 400 {
+ t.Errorf("Expected HTTP 400 error, got %d status code.", resp.StatusCode)
+ }
+}
+
+// Test handling of an error caused by the internal http client's Do()
+// function. A redirect loop is pretty unlikely to occur within the GitHub
+// API, but does allow us to exercise the right code path.
+func TestDo_redirectLoop(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ http.Redirect(w, r, baseURLPath, http.StatusFound)
+ })
+
+ req, _ := client.NewRequest("GET", ".", nil)
+ _, err := client.Do(context.Background(), req, nil)
+
+ if err == nil {
+ t.Error("Expected error to be returned.")
+ }
+ if err, ok := err.(*url.Error); !ok {
+ t.Errorf("Expected a URL error; got %#v.", err)
+ }
+}
+
+// Test that an error caused by the internal http client's Do() function
+// does not leak the client secret.
+func TestDo_sanitizeURL(t *testing.T) {
+ tp := &UnauthenticatedRateLimitedTransport{
+ ClientID: "id",
+ ClientSecret: "secret",
+ }
+ unauthedClient := NewClient(tp.Client())
+ unauthedClient.BaseURL = &url.URL{Scheme: "http", Host: "127.0.0.1:0", Path: "/"} // Use port 0 on purpose to trigger a dial TCP error, expect to get "dial tcp 127.0.0.1:0: connect: can't assign requested address".
+ req, err := unauthedClient.NewRequest("GET", ".", nil)
+ if err != nil {
+ t.Fatalf("NewRequest returned unexpected error: %v", err)
+ }
+ _, err = unauthedClient.Do(context.Background(), req, nil)
+ if err == nil {
+ t.Fatal("Expected error to be returned.")
+ }
+ if strings.Contains(err.Error(), "client_secret=secret") {
+ t.Errorf("Do error contains secret, should be redacted:\n%q", err)
+ }
+}
+
+func TestDo_rateLimit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set(headerRateLimit, "60")
+ w.Header().Set(headerRateRemaining, "59")
+ w.Header().Set(headerRateReset, "1372700873")
+ })
+
+ req, _ := client.NewRequest("GET", ".", nil)
+ resp, err := client.Do(context.Background(), req, nil)
+ if err != nil {
+ t.Errorf("Do returned unexpected error: %v", err)
+ }
+ if got, want := resp.Rate.Limit, 60; got != want {
+ t.Errorf("Client rate limit = %v, want %v", got, want)
+ }
+ if got, want := resp.Rate.Remaining, 59; got != want {
+ t.Errorf("Client rate remaining = %v, want %v", got, want)
+ }
+ reset := time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC)
+ if resp.Rate.Reset.UTC() != reset {
+ t.Errorf("Client rate reset = %v, want %v", resp.Rate.Reset, reset)
+ }
+}
+
+// ensure rate limit is still parsed, even for error responses
+func TestDo_rateLimit_errorResponse(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set(headerRateLimit, "60")
+ w.Header().Set(headerRateRemaining, "59")
+ w.Header().Set(headerRateReset, "1372700873")
+ http.Error(w, "Bad Request", 400)
+ })
+
+ req, _ := client.NewRequest("GET", ".", nil)
+ resp, err := client.Do(context.Background(), req, nil)
+ if err == nil {
+ t.Error("Expected error to be returned.")
+ }
+ if _, ok := err.(*RateLimitError); ok {
+ t.Errorf("Did not expect a *RateLimitError error; got %#v.", err)
+ }
+ if got, want := resp.Rate.Limit, 60; got != want {
+ t.Errorf("Client rate limit = %v, want %v", got, want)
+ }
+ if got, want := resp.Rate.Remaining, 59; got != want {
+ t.Errorf("Client rate remaining = %v, want %v", got, want)
+ }
+ reset := time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC)
+ if resp.Rate.Reset.UTC() != reset {
+ t.Errorf("Client rate reset = %v, want %v", resp.Rate.Reset, reset)
+ }
+}
+
+// Ensure *RateLimitError is returned when API rate limit is exceeded.
+func TestDo_rateLimit_rateLimitError(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set(headerRateLimit, "60")
+ w.Header().Set(headerRateRemaining, "0")
+ w.Header().Set(headerRateReset, "1372700873")
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+ w.WriteHeader(http.StatusForbidden)
+ fmt.Fprintln(w, `{
+ "message": "API rate limit exceeded for xxx.xxx.xxx.xxx. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
+ "documentation_url": "https://developer.github.com/v3/#rate-limiting"
+}`)
+ })
+
+ req, _ := client.NewRequest("GET", ".", nil)
+ _, err := client.Do(context.Background(), req, nil)
+
+ if err == nil {
+ t.Error("Expected error to be returned.")
+ }
+ rateLimitErr, ok := err.(*RateLimitError)
+ if !ok {
+ t.Fatalf("Expected a *RateLimitError error; got %#v.", err)
+ }
+ if got, want := rateLimitErr.Rate.Limit, 60; got != want {
+ t.Errorf("rateLimitErr rate limit = %v, want %v", got, want)
+ }
+ if got, want := rateLimitErr.Rate.Remaining, 0; got != want {
+ t.Errorf("rateLimitErr rate remaining = %v, want %v", got, want)
+ }
+ reset := time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC)
+ if rateLimitErr.Rate.Reset.UTC() != reset {
+ t.Errorf("rateLimitErr rate reset = %v, want %v", rateLimitErr.Rate.Reset.UTC(), reset)
+ }
+}
+
+// Ensure a network call is not made when it's known that API rate limit is still exceeded.
+func TestDo_rateLimit_noNetworkCall(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ reset := time.Now().UTC().Add(time.Minute).Round(time.Second) // Rate reset is a minute from now, with 1 second precision.
+
+ mux.HandleFunc("/first", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set(headerRateLimit, "60")
+ w.Header().Set(headerRateRemaining, "0")
+ w.Header().Set(headerRateReset, fmt.Sprint(reset.Unix()))
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+ w.WriteHeader(http.StatusForbidden)
+ fmt.Fprintln(w, `{
+ "message": "API rate limit exceeded for xxx.xxx.xxx.xxx. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
+ "documentation_url": "https://developer.github.com/v3/#rate-limiting"
+}`)
+ })
+
+ madeNetworkCall := false
+ mux.HandleFunc("/second", func(w http.ResponseWriter, r *http.Request) {
+ madeNetworkCall = true
+ })
+
+ // First request is made, and it makes the client aware of rate reset time being in the future.
+ req, _ := client.NewRequest("GET", "first", nil)
+ client.Do(context.Background(), req, nil)
+
+ // Second request should not cause a network call to be made, since client can predict a rate limit error.
+ req, _ = client.NewRequest("GET", "second", nil)
+ _, err := client.Do(context.Background(), req, nil)
+
+ if madeNetworkCall {
+ t.Fatal("Network call was made, even though rate limit is known to still be exceeded.")
+ }
+
+ if err == nil {
+ t.Error("Expected error to be returned.")
+ }
+ rateLimitErr, ok := err.(*RateLimitError)
+ if !ok {
+ t.Fatalf("Expected a *RateLimitError error; got %#v.", err)
+ }
+ if got, want := rateLimitErr.Rate.Limit, 60; got != want {
+ t.Errorf("rateLimitErr rate limit = %v, want %v", got, want)
+ }
+ if got, want := rateLimitErr.Rate.Remaining, 0; got != want {
+ t.Errorf("rateLimitErr rate remaining = %v, want %v", got, want)
+ }
+ if rateLimitErr.Rate.Reset.UTC() != reset {
+ t.Errorf("rateLimitErr rate reset = %v, want %v", rateLimitErr.Rate.Reset.UTC(), reset)
+ }
+}
+
+// Ensure *AbuseRateLimitError is returned when the response indicates that
+// the client has triggered an abuse detection mechanism.
+func TestDo_rateLimit_abuseRateLimitError(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+ w.WriteHeader(http.StatusForbidden)
+ // When the abuse rate limit error is of the "temporarily blocked from content creation" type,
+ // there is no "Retry-After" header.
+ fmt.Fprintln(w, `{
+ "message": "You have triggered an abuse detection mechanism and have been temporarily blocked from content creation. Please retry your request again later.",
+ "documentation_url": "https://developer.github.com/v3/#abuse-rate-limits"
+}`)
+ })
+
+ req, _ := client.NewRequest("GET", ".", nil)
+ _, err := client.Do(context.Background(), req, nil)
+
+ if err == nil {
+ t.Error("Expected error to be returned.")
+ }
+ abuseRateLimitErr, ok := err.(*AbuseRateLimitError)
+ if !ok {
+ t.Fatalf("Expected a *AbuseRateLimitError error; got %#v.", err)
+ }
+ if got, want := abuseRateLimitErr.RetryAfter, (*time.Duration)(nil); got != want {
+ t.Errorf("abuseRateLimitErr RetryAfter = %v, want %v", got, want)
+ }
+}
+
+// Ensure *AbuseRateLimitError is returned when the response indicates that
+// the client has triggered an abuse detection mechanism on GitHub Enterprise.
+func TestDo_rateLimit_abuseRateLimitErrorEnterprise(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+ w.WriteHeader(http.StatusForbidden)
+ // When the abuse rate limit error is of the "temporarily blocked from content creation" type,
+ // there is no "Retry-After" header.
+ // This response returns a documentation url like the one returned for GitHub Enterprise, this
+ // url changes between versions but follows roughly the same format.
+ fmt.Fprintln(w, `{
+ "message": "You have triggered an abuse detection mechanism and have been temporarily blocked from content creation. Please retry your request again later.",
+ "documentation_url": "https://developer.github.com/enterprise/2.12/v3/#abuse-rate-limits"
+}`)
+ })
+
+ req, _ := client.NewRequest("GET", ".", nil)
+ _, err := client.Do(context.Background(), req, nil)
+
+ if err == nil {
+ t.Error("Expected error to be returned.")
+ }
+ abuseRateLimitErr, ok := err.(*AbuseRateLimitError)
+ if !ok {
+ t.Fatalf("Expected a *AbuseRateLimitError error; got %#v.", err)
+ }
+ if got, want := abuseRateLimitErr.RetryAfter, (*time.Duration)(nil); got != want {
+ t.Errorf("abuseRateLimitErr RetryAfter = %v, want %v", got, want)
+ }
+}
+
+// Ensure *AbuseRateLimitError.RetryAfter is parsed correctly.
+func TestDo_rateLimit_abuseRateLimitError_retryAfter(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+ w.Header().Set("Retry-After", "123") // Retry after value of 123 seconds.
+ w.WriteHeader(http.StatusForbidden)
+ fmt.Fprintln(w, `{
+ "message": "You have triggered an abuse detection mechanism ...",
+ "documentation_url": "https://developer.github.com/v3/#abuse-rate-limits"
+}`)
+ })
+
+ req, _ := client.NewRequest("GET", ".", nil)
+ _, err := client.Do(context.Background(), req, nil)
+
+ if err == nil {
+ t.Error("Expected error to be returned.")
+ }
+ abuseRateLimitErr, ok := err.(*AbuseRateLimitError)
+ if !ok {
+ t.Fatalf("Expected a *AbuseRateLimitError error; got %#v.", err)
+ }
+ if abuseRateLimitErr.RetryAfter == nil {
+ t.Fatalf("abuseRateLimitErr RetryAfter is nil, expected not-nil")
+ }
+ if got, want := *abuseRateLimitErr.RetryAfter, 123*time.Second; got != want {
+ t.Errorf("abuseRateLimitErr RetryAfter = %v, want %v", got, want)
+ }
+}
+
+func TestDo_noContent(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ var body json.RawMessage
+
+ req, _ := client.NewRequest("GET", ".", nil)
+ _, err := client.Do(context.Background(), req, &body)
+ if err != nil {
+ t.Fatalf("Do returned unexpected error: %v", err)
+ }
+}
+
+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{},
+ StatusCode: http.StatusBadRequest,
+ Body: ioutil.NopCloser(strings.NewReader(`{"message":"m",
+ "errors": [{"resource": "r", "field": "f", "code": "c"}],
+ "block": {"reason": "dmca", "created_at": "2016-03-17T15:39:46Z"}}`)),
+ }
+ err := CheckResponse(res).(*ErrorResponse)
+
+ if err == nil {
+ t.Errorf("Expected error response.")
+ }
+
+ want := &ErrorResponse{
+ Response: res,
+ Message: "m",
+ Errors: []Error{{Resource: "r", Field: "f", Code: "c"}},
+ Block: &struct {
+ Reason string `json:"reason,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ }{
+ Reason: "dmca",
+ CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)},
+ },
+ }
+ if !reflect.DeepEqual(err, want) {
+ t.Errorf("Error = %#v, want %#v", err, want)
+ }
+}
+
+// ensure that we properly handle API errors that do not contain a response body
+func TestCheckResponse_noBody(t *testing.T) {
+ res := &http.Response{
+ Request: &http.Request{},
+ StatusCode: http.StatusBadRequest,
+ Body: ioutil.NopCloser(strings.NewReader("")),
+ }
+ err := CheckResponse(res).(*ErrorResponse)
+
+ if err == nil {
+ t.Errorf("Expected error response.")
+ }
+
+ want := &ErrorResponse{
+ Response: res,
+ }
+ if !reflect.DeepEqual(err, want) {
+ t.Errorf("Error = %#v, want %#v", err, want)
+ }
+}
+
+func TestParseBooleanResponse_true(t *testing.T) {
+ result, err := parseBoolResponse(nil)
+ if err != nil {
+ t.Errorf("parseBoolResponse returned error: %+v", err)
+ }
+
+ if want := true; result != want {
+ t.Errorf("parseBoolResponse returned %+v, want: %+v", result, want)
+ }
+}
+
+func TestParseBooleanResponse_false(t *testing.T) {
+ v := &ErrorResponse{Response: &http.Response{StatusCode: http.StatusNotFound}}
+ result, err := parseBoolResponse(v)
+ if err != nil {
+ t.Errorf("parseBoolResponse returned error: %+v", err)
+ }
+
+ if want := false; result != want {
+ t.Errorf("parseBoolResponse returned %+v, want: %+v", result, want)
+ }
+}
+
+func TestParseBooleanResponse_error(t *testing.T) {
+ v := &ErrorResponse{Response: &http.Response{StatusCode: http.StatusBadRequest}}
+ result, err := parseBoolResponse(v)
+
+ if err == nil {
+ t.Errorf("Expected error to be returned.")
+ }
+
+ if want := false; result != want {
+ t.Errorf("parseBoolResponse returned %+v, want: %+v", result, want)
+ }
+}
+
+func TestErrorResponse_Error(t *testing.T) {
+ res := &http.Response{Request: &http.Request{}}
+ err := ErrorResponse{Message: "m", Response: res}
+ if err.Error() == "" {
+ t.Errorf("Expected non-empty ErrorResponse.Error()")
+ }
+}
+
+func TestError_Error(t *testing.T) {
+ err := Error{}
+ if err.Error() == "" {
+ t.Errorf("Expected non-empty Error.Error()")
+ }
+}
+
+func TestRateLimits(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/rate_limit", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"resources":{
+ "core": {"limit":2,"remaining":1,"reset":1372700873},
+ "search": {"limit":3,"remaining":2,"reset":1372700874}
+ }}`)
+ })
+
+ rate, _, err := client.RateLimits(context.Background())
+ if err != nil {
+ t.Errorf("RateLimits returned error: %v", err)
+ }
+
+ want := &RateLimits{
+ Core: &Rate{
+ Limit: 2,
+ Remaining: 1,
+ Reset: Timestamp{time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC).Local()},
+ },
+ Search: &Rate{
+ Limit: 3,
+ Remaining: 2,
+ Reset: Timestamp{time.Date(2013, time.July, 1, 17, 47, 54, 0, time.UTC).Local()},
+ },
+ }
+ if !reflect.DeepEqual(rate, want) {
+ t.Errorf("RateLimits returned %+v, want %+v", rate, want)
+ }
+
+ if got, want := client.rateLimits[coreCategory], *want.Core; got != want {
+ t.Errorf("client.rateLimits[coreCategory] is %+v, want %+v", got, want)
+ }
+ if got, want := client.rateLimits[searchCategory], *want.Search; got != want {
+ t.Errorf("client.rateLimits[searchCategory] is %+v, want %+v", got, want)
+ }
+}
+
+func TestUnauthenticatedRateLimitedTransport(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ var v, want string
+ q := r.URL.Query()
+ if v, want = q.Get("client_id"), "id"; v != want {
+ t.Errorf("OAuth Client ID = %v, want %v", v, want)
+ }
+ if v, want = q.Get("client_secret"), "secret"; v != want {
+ t.Errorf("OAuth Client Secret = %v, want %v", v, want)
+ }
+ })
+
+ tp := &UnauthenticatedRateLimitedTransport{
+ ClientID: "id",
+ ClientSecret: "secret",
+ }
+ unauthedClient := NewClient(tp.Client())
+ unauthedClient.BaseURL = client.BaseURL
+ req, _ := unauthedClient.NewRequest("GET", ".", nil)
+ unauthedClient.Do(context.Background(), req, nil)
+}
+
+func TestUnauthenticatedRateLimitedTransport_missingFields(t *testing.T) {
+ // missing ClientID
+ tp := &UnauthenticatedRateLimitedTransport{
+ ClientSecret: "secret",
+ }
+ _, err := tp.RoundTrip(nil)
+ if err == nil {
+ t.Errorf("Expected error to be returned")
+ }
+
+ // missing ClientSecret
+ tp = &UnauthenticatedRateLimitedTransport{
+ ClientID: "id",
+ }
+ _, err = tp.RoundTrip(nil)
+ if err == nil {
+ t.Errorf("Expected error to be returned")
+ }
+}
+
+func TestUnauthenticatedRateLimitedTransport_transport(t *testing.T) {
+ // default transport
+ tp := &UnauthenticatedRateLimitedTransport{
+ ClientID: "id",
+ ClientSecret: "secret",
+ }
+ if tp.transport() != http.DefaultTransport {
+ t.Errorf("Expected http.DefaultTransport to be used.")
+ }
+
+ // custom transport
+ tp = &UnauthenticatedRateLimitedTransport{
+ ClientID: "id",
+ ClientSecret: "secret",
+ Transport: &http.Transport{},
+ }
+ if tp.transport() == http.DefaultTransport {
+ t.Errorf("Expected custom transport to be used.")
+ }
+}
+
+func TestBasicAuthTransport(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ username, password, otp := "u", "p", "123456"
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ u, p, ok := r.BasicAuth()
+ if !ok {
+ t.Errorf("request does not contain basic auth credentials")
+ }
+ if u != username {
+ t.Errorf("request contained basic auth username %q, want %q", u, username)
+ }
+ if p != password {
+ t.Errorf("request contained basic auth password %q, want %q", p, password)
+ }
+ if got, want := r.Header.Get(headerOTP), otp; got != want {
+ t.Errorf("request contained OTP %q, want %q", got, want)
+ }
+ })
+
+ tp := &BasicAuthTransport{
+ Username: username,
+ Password: password,
+ OTP: otp,
+ }
+ basicAuthClient := NewClient(tp.Client())
+ basicAuthClient.BaseURL = client.BaseURL
+ req, _ := basicAuthClient.NewRequest("GET", ".", nil)
+ basicAuthClient.Do(context.Background(), req, nil)
+}
+
+func TestBasicAuthTransport_transport(t *testing.T) {
+ // default transport
+ tp := &BasicAuthTransport{}
+ if tp.transport() != http.DefaultTransport {
+ t.Errorf("Expected http.DefaultTransport to be used.")
+ }
+
+ // custom transport
+ tp = &BasicAuthTransport{
+ Transport: &http.Transport{},
+ }
+ if tp.transport() == http.DefaultTransport {
+ t.Errorf("Expected custom transport to be used.")
+ }
+}
+
+func TestFormatRateReset(t *testing.T) {
+ d := 120*time.Minute + 12*time.Second
+ got := formatRateReset(d)
+ want := "[rate reset in 120m12s]"
+ if got != want {
+ t.Errorf("Format is wrong. got: %v, want: %v", got, want)
+ }
+
+ d = 14*time.Minute + 2*time.Second
+ got = formatRateReset(d)
+ want = "[rate reset in 14m02s]"
+ if got != want {
+ t.Errorf("Format is wrong. got: %v, want: %v", got, want)
+ }
+
+ d = 2*time.Minute + 2*time.Second
+ got = formatRateReset(d)
+ want = "[rate reset in 2m02s]"
+ if got != want {
+ t.Errorf("Format is wrong. got: %v, want: %v", got, want)
+ }
+
+ d = 12 * time.Second
+ got = formatRateReset(d)
+ want = "[rate reset in 12s]"
+ if got != want {
+ t.Errorf("Format is wrong. got: %v, want: %v", got, want)
+ }
+
+ d = -1 * (2*time.Hour + 2*time.Second)
+ got = formatRateReset(d)
+ want = "[rate limit was reset 120m02s ago]"
+ if got != want {
+ t.Errorf("Format is wrong. got: %v, want: %v", got, want)
+ }
+}
+
+func TestNestedStructAccessorNoPanic(t *testing.T) {
+ issue := &Issue{User: nil}
+ got := issue.GetUser().GetPlan().GetName()
+ want := ""
+ if got != want {
+ t.Errorf("Issues.Get.GetUser().GetPlan().GetName() returned %+v, want %+v", got, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/gitignore.go b/vendor/github.com/google/go-github/github/gitignore.go
new file mode 100644
index 0000000..2f691bc
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/gitignore.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 (
+ "context"
+ "fmt"
+)
+
+// GitignoresService provides access to the gitignore related functions in the
+// GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/gitignore/
+type GitignoresService service
+
+// Gitignore represents a .gitignore file as returned by the GitHub API.
+type Gitignore struct {
+ Name *string `json:"name,omitempty"`
+ Source *string `json:"source,omitempty"`
+}
+
+func (g Gitignore) String() string {
+ return Stringify(g)
+}
+
+// List all available Gitignore templates.
+//
+// GitHub API docs: https://developer.github.com/v3/gitignore/#listing-available-templates
+func (s GitignoresService) List(ctx context.Context) ([]string, *Response, error) {
+ req, err := s.client.NewRequest("GET", "gitignore/templates", nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var availableTemplates []string
+ resp, err := s.client.Do(ctx, req, &availableTemplates)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return availableTemplates, resp, nil
+}
+
+// Get a Gitignore by name.
+//
+// GitHub API docs: https://developer.github.com/v3/gitignore/#get-a-single-template
+func (s GitignoresService) Get(ctx context.Context, name string) (*Gitignore, *Response, error) {
+ u := fmt.Sprintf("gitignore/templates/%v", name)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ gitignore := new(Gitignore)
+ resp, err := s.client.Do(ctx, req, gitignore)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return gitignore, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/gitignore_test.go b/vendor/github.com/google/go-github/github/gitignore_test.go
new file mode 100644
index 0000000..cdb8223
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/gitignore_test.go
@@ -0,0 +1,62 @@
+// 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestGitignoresService_List(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gitignore/templates", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `["C", "Go"]`)
+ })
+
+ available, _, err := client.Gitignores.List(context.Background())
+ if err != nil {
+ t.Errorf("Gitignores.List returned error: %v", err)
+ }
+
+ want := []string{"C", "Go"}
+ if !reflect.DeepEqual(available, want) {
+ t.Errorf("Gitignores.List returned %+v, want %+v", available, want)
+ }
+}
+
+func TestGitignoresService_Get(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/gitignore/templates/name", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"name":"Name","source":"template source"}`)
+ })
+
+ gitignore, _, err := client.Gitignores.Get(context.Background(), "name")
+ if err != nil {
+ t.Errorf("Gitignores.List returned error: %v", err)
+ }
+
+ want := &Gitignore{Name: String("Name"), Source: String("template source")}
+ if !reflect.DeepEqual(gitignore, want) {
+ t.Errorf("Gitignores.Get returned %+v, want %+v", gitignore, want)
+ }
+}
+
+func TestGitignoresService_Get_invalidTemplate(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Gitignores.Get(context.Background(), "%")
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/issues.go b/vendor/github.com/google/go-github/github/issues.go
new file mode 100644
index 0000000..1e0991c
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues.go
@@ -0,0 +1,347 @@
+// 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 (
+ "context"
+ "fmt"
+ "strings"
+ "time"
+)
+
+// IssuesService handles communication with the issue related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/
+type IssuesService service
+
+// Issue represents a GitHub issue on a repository.
+//
+// Note: As far as the GitHub API is concerned, every pull request is an issue,
+// but not every issue is a pull request. Some endpoints, events, and webhooks
+// may also return pull requests via this struct. If PullRequestLinks is nil,
+// this is an issue, and if PullRequestLinks is not nil, this is a pull request.
+// The IsPullRequest helper method can be used to check that.
+type Issue struct {
+ ID *int64 `json:"id,omitempty"`
+ Number *int `json:"number,omitempty"`
+ State *string `json:"state,omitempty"`
+ Locked *bool `json:"locked,omitempty"`
+ Title *string `json:"title,omitempty"`
+ Body *string `json:"body,omitempty"`
+ User *User `json:"user,omitempty"`
+ Labels []Label `json:"labels,omitempty"`
+ Assignee *User `json:"assignee,omitempty"`
+ Comments *int `json:"comments,omitempty"`
+ ClosedAt *time.Time `json:"closed_at,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+ ClosedBy *User `json:"closed_by,omitempty"`
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ CommentsURL *string `json:"comments_url,omitempty"`
+ EventsURL *string `json:"events_url,omitempty"`
+ LabelsURL *string `json:"labels_url,omitempty"`
+ RepositoryURL *string `json:"repository_url,omitempty"`
+ Milestone *Milestone `json:"milestone,omitempty"`
+ PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"`
+ Repository *Repository `json:"repository,omitempty"`
+ Reactions *Reactions `json:"reactions,omitempty"`
+ Assignees []*User `json:"assignees,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+
+ // TextMatches is only populated from search results that request text matches
+ // See: search.go and https://developer.github.com/v3/search/#text-match-metadata
+ TextMatches []TextMatch `json:"text_matches,omitempty"`
+
+ // ActiveLockReason is populated only when LockReason is provided while locking the issue.
+ // Possible values are: "off-topic", "too heated", "resolved", and "spam".
+ ActiveLockReason *string `json:"active_lock_reason,omitempty"`
+}
+
+func (i Issue) String() string {
+ return Stringify(i)
+}
+
+// IsPullRequest reports whether the issue is also a pull request. It uses the
+// method recommended by GitHub's API documentation, which is to check whether
+// PullRequestLinks is non-nil.
+func (i Issue) IsPullRequest() bool {
+ return i.PullRequestLinks != nil
+}
+
+// IssueRequest represents a request to create/edit an issue.
+// 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"`
+ Assignees *[]string `json:"assignees,omitempty"`
+}
+
+// IssueListOptions specifies the optional parameters to the IssuesService.List
+// and IssuesService.ListByOrg methods.
+type IssueListOptions struct {
+ // Filter specifies which issues to list. Possible values are: assigned,
+ // created, mentioned, subscribed, all. Default is "assigned".
+ Filter string `url:"filter,omitempty"`
+
+ // State filters issues based on their state. Possible values are: open,
+ // closed, all. Default is "open".
+ State string `url:"state,omitempty"`
+
+ // Labels filters issues based on their label.
+ Labels []string `url:"labels,comma,omitempty"`
+
+ // Sort specifies how to sort issues. Possible values are: created, updated,
+ // and comments. Default value is "created".
+ Sort string `url:"sort,omitempty"`
+
+ // Direction in which to sort issues. Possible values are: asc, desc.
+ // Default is "desc".
+ Direction string `url:"direction,omitempty"`
+
+ // Since filters issues by time.
+ Since time.Time `url:"since,omitempty"`
+
+ ListOptions
+}
+
+// PullRequestLinks object is added to the Issue object when it's an issue included
+// in the IssueCommentEvent webhook payload, if the webhook is fired by a comment on a PR.
+type PullRequestLinks struct {
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ DiffURL *string `json:"diff_url,omitempty"`
+ PatchURL *string `json:"patch_url,omitempty"`
+}
+
+// List the issues for the authenticated user. If all is true, list issues
+// across all the user's visible repositories including owned, member, and
+// organization repositories; if false, list only owned and member
+// repositories.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/#list-issues
+func (s *IssuesService) List(ctx context.Context, all bool, opt *IssueListOptions) ([]*Issue, *Response, error) {
+ var u string
+ if all {
+ u = "issues"
+ } else {
+ u = "user/issues"
+ }
+ return s.listIssues(ctx, u, opt)
+}
+
+// ListByOrg fetches the issues in the specified organization for the
+// authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/#list-issues
+func (s *IssuesService) ListByOrg(ctx context.Context, org string, opt *IssueListOptions) ([]*Issue, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/issues", org)
+ return s.listIssues(ctx, u, opt)
+}
+
+func (s *IssuesService) listIssues(ctx context.Context, u string, opt *IssueListOptions) ([]*Issue, *Response, error) {
+ 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+ var issues []*Issue
+ resp, err := s.client.Do(ctx, req, &issues)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return issues, resp, nil
+}
+
+// IssueListByRepoOptions specifies the optional parameters to the
+// IssuesService.ListByRepo method.
+type IssueListByRepoOptions struct {
+ // Milestone limits issues for the specified milestone. Possible values are
+ // a milestone number, "none" for issues with no milestone, "*" for issues
+ // with any milestone.
+ Milestone string `url:"milestone,omitempty"`
+
+ // State filters issues based on their state. Possible values are: open,
+ // closed, all. Default is "open".
+ State string `url:"state,omitempty"`
+
+ // Assignee filters issues based on their assignee. Possible values are a
+ // user name, "none" for issues that are not assigned, "*" for issues with
+ // any assigned user.
+ Assignee string `url:"assignee,omitempty"`
+
+ // Creator filters issues based on their creator.
+ Creator string `url:"creator,omitempty"`
+
+ // Mentioned filters issues to those mentioned a specific user.
+ Mentioned string `url:"mentioned,omitempty"`
+
+ // Labels filters issues based on their label.
+ Labels []string `url:"labels,omitempty,comma"`
+
+ // Sort specifies how to sort issues. Possible values are: created, updated,
+ // and comments. Default value is "created".
+ Sort string `url:"sort,omitempty"`
+
+ // Direction in which to sort issues. Possible values are: asc, desc.
+ // Default is "desc".
+ Direction string `url:"direction,omitempty"`
+
+ // Since filters issues by time.
+ Since time.Time `url:"since,omitempty"`
+
+ ListOptions
+}
+
+// ListByRepo lists the issues for the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/#list-issues-for-a-repository
+func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo string, opt *IssueListByRepoOptions) ([]*Issue, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeIntegrationPreview}
+ req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+ var issues []*Issue
+ resp, err := s.client.Do(ctx, req, &issues)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return issues, resp, nil
+}
+
+// Get a single issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/#get-a-single-issue
+func (s *IssuesService) Get(ctx context.Context, owner string, repo string, number int) (*Issue, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+ issue := new(Issue)
+ resp, err := s.client.Do(ctx, req, issue)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return issue, resp, nil
+}
+
+// Create a new issue on the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/#create-an-issue
+func (s *IssuesService) Create(ctx context.Context, owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
+ req, err := s.client.NewRequest("POST", u, issue)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ i := new(Issue)
+ resp, err := s.client.Do(ctx, req, i)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return i, resp, nil
+}
+
+// Edit an issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/#edit-an-issue
+func (s *IssuesService) Edit(ctx context.Context, owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
+ req, err := s.client.NewRequest("PATCH", u, issue)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ i := new(Issue)
+ resp, err := s.client.Do(ctx, req, i)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return i, resp, nil
+}
+
+// LockIssueOptions specifies the optional parameters to the
+// IssuesService.Lock method.
+type LockIssueOptions struct {
+ // LockReason specifies the reason to lock this issue.
+ // Providing a lock reason can help make it clearer to contributors why an issue
+ // was locked. Possible values are: "off-topic", "too heated", "resolved", and "spam".
+ LockReason string `json:"lock_reason,omitempty"`
+}
+
+// Lock an issue's conversation.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/#lock-an-issue
+func (s *IssuesService) Lock(ctx context.Context, owner string, repo string, number int, opt *LockIssueOptions) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number)
+ req, err := s.client.NewRequest("PUT", u, opt)
+ if err != nil {
+ return nil, err
+ }
+
+ if opt != nil {
+ req.Header.Set("Accept", mediaTypeLockReasonPreview)
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// Unlock an issue's conversation.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/#unlock-an-issue
+func (s *IssuesService) Unlock(ctx context.Context, owner string, repo string, number int) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/issues_assignees.go b/vendor/github.com/google/go-github/github/issues_assignees.go
new file mode 100644
index 0000000..9cb366f
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_assignees.go
@@ -0,0 +1,85 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// ListAssignees fetches all available assignees (owners and collaborators) to
+// which issues may be assigned.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/assignees/#list-assignees
+func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/assignees", owner, repo)
+ 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
+ }
+ var assignees []*User
+ resp, err := s.client.Do(ctx, req, &assignees)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return assignees, resp, nil
+}
+
+// IsAssignee checks if a user is an assignee for the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/assignees/#check-assignee
+func (s *IssuesService) IsAssignee(ctx context.Context, owner, repo, user string) (bool, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/assignees/%v", owner, repo, user)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+ resp, err := s.client.Do(ctx, req, nil)
+ assignee, err := parseBoolResponse(err)
+ return assignee, resp, err
+}
+
+// AddAssignees adds the provided GitHub users as assignees to the issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/assignees/#add-assignees-to-an-issue
+func (s *IssuesService) AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) {
+ users := &struct {
+ Assignees []string `json:"assignees,omitempty"`
+ }{Assignees: assignees}
+ u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number)
+ req, err := s.client.NewRequest("POST", u, users)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ issue := &Issue{}
+ resp, err := s.client.Do(ctx, req, issue)
+ return issue, resp, err
+}
+
+// RemoveAssignees removes the provided GitHub users as assignees from the issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/assignees/#remove-assignees-from-an-issue
+func (s *IssuesService) RemoveAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) {
+ users := &struct {
+ Assignees []string `json:"assignees,omitempty"`
+ }{Assignees: assignees}
+ u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number)
+ req, err := s.client.NewRequest("DELETE", u, users)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ issue := &Issue{}
+ resp, err := s.client.Do(ctx, req, issue)
+ return issue, resp, err
+}
diff --git a/vendor/github.com/google/go-github/github/issues_assignees_test.go b/vendor/github.com/google/go-github/github/issues_assignees_test.go
new file mode 100644
index 0000000..bb2bf4f
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_assignees_test.go
@@ -0,0 +1,164 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestIssuesService_ListAssignees(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/assignees", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ assignees, _, err := client.Issues.ListAssignees(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Issues.ListAssignees returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}}
+ if !reflect.DeepEqual(assignees, want) {
+ t.Errorf("Issues.ListAssignees returned %+v, want %+v", assignees, want)
+ }
+}
+
+func TestIssuesService_ListAssignees_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.ListAssignees(context.Background(), "%", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_IsAssignee_true(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/assignees/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ })
+
+ assignee, _, err := client.Issues.IsAssignee(context.Background(), "o", "r", "u")
+ if err != nil {
+ t.Errorf("Issues.IsAssignee returned error: %v", err)
+ }
+ if want := true; assignee != want {
+ t.Errorf("Issues.IsAssignee returned %+v, want %+v", assignee, want)
+ }
+}
+
+func TestIssuesService_IsAssignee_false(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/assignees/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNotFound)
+ })
+
+ assignee, _, err := client.Issues.IsAssignee(context.Background(), "o", "r", "u")
+ if err != nil {
+ t.Errorf("Issues.IsAssignee returned error: %v", err)
+ }
+ if want := false; assignee != want {
+ t.Errorf("Issues.IsAssignee returned %+v, want %+v", assignee, want)
+ }
+}
+
+func TestIssuesService_IsAssignee_error(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/assignees/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ http.Error(w, "BadRequest", http.StatusBadRequest)
+ })
+
+ assignee, _, err := client.Issues.IsAssignee(context.Background(), "o", "r", "u")
+ if err == nil {
+ t.Errorf("Expected HTTP 400 response")
+ }
+ if want := false; assignee != want {
+ t.Errorf("Issues.IsAssignee returned %+v, want %+v", assignee, want)
+ }
+}
+
+func TestIssuesService_IsAssignee_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.IsAssignee(context.Background(), "%", "r", "u")
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_AddAssignees(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/assignees", func(w http.ResponseWriter, r *http.Request) {
+ var assignees struct {
+ Assignees []string `json:"assignees,omitempty"`
+ }
+ json.NewDecoder(r.Body).Decode(&assignees)
+
+ testMethod(t, r, "POST")
+ want := []string{"user1", "user2"}
+ if !reflect.DeepEqual(assignees.Assignees, want) {
+ t.Errorf("assignees = %+v, want %+v", assignees, want)
+ }
+ fmt.Fprint(w, `{"number":1,"assignees":[{"login":"user1"},{"login":"user2"}]}`)
+ })
+
+ got, _, err := client.Issues.AddAssignees(context.Background(), "o", "r", 1, []string{"user1", "user2"})
+ if err != nil {
+ t.Errorf("Issues.AddAssignees returned error: %v", err)
+ }
+
+ want := &Issue{Number: Int(1), Assignees: []*User{{Login: String("user1")}, {Login: String("user2")}}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Issues.AddAssignees = %+v, want %+v", got, want)
+ }
+}
+
+func TestIssuesService_RemoveAssignees(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/assignees", func(w http.ResponseWriter, r *http.Request) {
+ var assignees struct {
+ Assignees []string `json:"assignees,omitempty"`
+ }
+ json.NewDecoder(r.Body).Decode(&assignees)
+
+ testMethod(t, r, "DELETE")
+ want := []string{"user1", "user2"}
+ if !reflect.DeepEqual(assignees.Assignees, want) {
+ t.Errorf("assignees = %+v, want %+v", assignees, want)
+ }
+ fmt.Fprint(w, `{"number":1,"assignees":[]}`)
+ })
+
+ got, _, err := client.Issues.RemoveAssignees(context.Background(), "o", "r", 1, []string{"user1", "user2"})
+ if err != nil {
+ t.Errorf("Issues.RemoveAssignees returned error: %v", err)
+ }
+
+ want := &Issue{Number: Int(1), Assignees: []*User{}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Issues.RemoveAssignees = %+v, want %+v", got, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/issues_comments.go b/vendor/github.com/google/go-github/github/issues_comments.go
new file mode 100644
index 0000000..e6f6f21
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_comments.go
@@ -0,0 +1,152 @@
+// 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// IssueComment represents a comment left on an issue.
+type IssueComment struct {
+ ID *int64 `json:"id,omitempty"`
+ Body *string `json:"body,omitempty"`
+ User *User `json:"user,omitempty"`
+ Reactions *Reactions `json:"reactions,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+ // AuthorAssociation is the comment author's relationship to the issue's repository.
+ // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE".
+ AuthorAssociation *string `json:"author_association,omitempty"`
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ IssueURL *string `json:"issue_url,omitempty"`
+}
+
+func (i IssueComment) String() string {
+ return Stringify(i)
+}
+
+// IssueListCommentsOptions specifies the optional parameters to the
+// IssuesService.ListComments method.
+type IssueListCommentsOptions struct {
+ // Sort specifies how to sort comments. Possible values are: created, updated.
+ Sort string `url:"sort,omitempty"`
+
+ // Direction in which to sort comments. Possible values are: asc, desc.
+ Direction string `url:"direction,omitempty"`
+
+ // Since filters comments by time.
+ Since time.Time `url:"since,omitempty"`
+
+ ListOptions
+}
+
+// ListComments lists all comments on the specified issue. Specifying an issue
+// number of 0 will return all comments on all issues for the repository.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue
+func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opt *IssueListCommentsOptions) ([]*IssueComment, *Response, error) {
+ var u string
+ if number == 0 {
+ u = fmt.Sprintf("repos/%v/%v/issues/comments", owner, repo)
+ } else {
+ u = fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number)
+ }
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ var comments []*IssueComment
+ resp, err := s.client.Do(ctx, req, &comments)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return comments, resp, nil
+}
+
+// GetComment fetches the specified issue comment.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/comments/#get-a-single-comment
+func (s *IssuesService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*IssueComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID)
+
+ 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", mediaTypeReactionsPreview)
+
+ comment := new(IssueComment)
+ resp, err := s.client.Do(ctx, req, comment)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return comment, resp, nil
+}
+
+// CreateComment creates a new comment on the specified issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/comments/#create-a-comment
+func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *IssueComment) (*IssueComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number)
+ req, err := s.client.NewRequest("POST", u, comment)
+ if err != nil {
+ return nil, nil, err
+ }
+ c := new(IssueComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// EditComment updates an issue comment.
+// A non-nil comment.Body must be provided. Other comment fields should be left nil.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/comments/#edit-a-comment
+func (s *IssuesService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *IssueComment) (*IssueComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID)
+ req, err := s.client.NewRequest("PATCH", u, comment)
+ if err != nil {
+ return nil, nil, err
+ }
+ c := new(IssueComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// DeleteComment deletes an issue comment.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/comments/#delete-a-comment
+func (s *IssuesService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/issues_comments_test.go b/vendor/github.com/google/go-github/github/issues_comments_test.go
new file mode 100644
index 0000000..6911a79
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_comments_test.go
@@ -0,0 +1,203 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestIssuesService_ListComments_allIssues(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/comments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+ testFormValues(t, r, values{
+ "sort": "updated",
+ "direction": "desc",
+ "since": "2002-02-10T15:30:00Z",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &IssueListCommentsOptions{
+ Sort: "updated",
+ Direction: "desc",
+ Since: time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC),
+ ListOptions: ListOptions{Page: 2},
+ }
+ comments, _, err := client.Issues.ListComments(context.Background(), "o", "r", 0, opt)
+ if err != nil {
+ t.Errorf("Issues.ListComments returned error: %v", err)
+ }
+
+ want := []*IssueComment{{ID: Int64(1)}}
+ if !reflect.DeepEqual(comments, want) {
+ t.Errorf("Issues.ListComments returned %+v, want %+v", comments, want)
+ }
+}
+
+func TestIssuesService_ListComments_specificIssue(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/comments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ comments, _, err := client.Issues.ListComments(context.Background(), "o", "r", 1, nil)
+ if err != nil {
+ t.Errorf("Issues.ListComments returned error: %v", err)
+ }
+
+ want := []*IssueComment{{ID: Int64(1)}}
+ if !reflect.DeepEqual(comments, want) {
+ t.Errorf("Issues.ListComments returned %+v, want %+v", comments, want)
+ }
+}
+
+func TestIssuesService_ListComments_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.ListComments(context.Background(), "%", "r", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_GetComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/comments/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ comment, _, err := client.Issues.GetComment(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Issues.GetComment returned error: %v", err)
+ }
+
+ want := &IssueComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Issues.GetComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestIssuesService_GetComment_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.GetComment(context.Background(), "%", "r", 1)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_CreateComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &IssueComment{Body: String("b")}
+
+ mux.HandleFunc("/repos/o/r/issues/1/comments", func(w http.ResponseWriter, r *http.Request) {
+ v := new(IssueComment)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ comment, _, err := client.Issues.CreateComment(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Issues.CreateComment returned error: %v", err)
+ }
+
+ want := &IssueComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Issues.CreateComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestIssuesService_CreateComment_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.CreateComment(context.Background(), "%", "r", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_EditComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &IssueComment{Body: String("b")}
+
+ mux.HandleFunc("/repos/o/r/issues/comments/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(IssueComment)
+ 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}`)
+ })
+
+ comment, _, err := client.Issues.EditComment(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Issues.EditComment returned error: %v", err)
+ }
+
+ want := &IssueComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Issues.EditComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestIssuesService_EditComment_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.EditComment(context.Background(), "%", "r", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_DeleteComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/comments/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Issues.DeleteComment(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Issues.DeleteComments returned error: %v", err)
+ }
+}
+
+func TestIssuesService_DeleteComment_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Issues.DeleteComment(context.Background(), "%", "r", 1)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/issues_events.go b/vendor/github.com/google/go-github/github/issues_events.go
new file mode 100644
index 0000000..f71e463
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_events.go
@@ -0,0 +1,158 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// IssueEvent represents an event that occurred around an Issue or Pull Request.
+type IssueEvent struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+
+ // The User that generated this event.
+ Actor *User `json:"actor,omitempty"`
+
+ // Event identifies the actual type of Event that occurred. Possible
+ // values are:
+ //
+ // closed
+ // The Actor closed the issue.
+ // If the issue was closed by commit message, CommitID holds the SHA1 hash of the commit.
+ //
+ // merged
+ // The Actor merged into master a branch containing a commit mentioning the issue.
+ // CommitID holds the SHA1 of the merge commit.
+ //
+ // referenced
+ // The Actor committed to master a commit mentioning the issue in its commit message.
+ // CommitID holds the SHA1 of the commit.
+ //
+ // reopened, unlocked
+ // The Actor did that to the issue.
+ //
+ // locked
+ // The Actor locked the issue.
+ // LockReason holds the reason of locking the issue (if provided while locking).
+ //
+ // renamed
+ // The Actor changed the issue title from Rename.From to Rename.To.
+ //
+ // mentioned
+ // Someone unspecified @mentioned the Actor [sic] in an issue comment body.
+ //
+ // assigned, unassigned
+ // The Assigner assigned the issue to or removed the assignment from the Assignee.
+ //
+ // labeled, unlabeled
+ // The Actor added or removed the Label from the issue.
+ //
+ // milestoned, demilestoned
+ // The Actor added or removed the issue from the Milestone.
+ //
+ // subscribed, unsubscribed
+ // The Actor subscribed to or unsubscribed from notifications for an issue.
+ //
+ // head_ref_deleted, head_ref_restored
+ // The pull request’s branch was deleted or restored.
+ //
+ Event *string `json:"event,omitempty"`
+
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ Issue *Issue `json:"issue,omitempty"`
+
+ // Only present on certain events; see above.
+ Assignee *User `json:"assignee,omitempty"`
+ Assigner *User `json:"assigner,omitempty"`
+ CommitID *string `json:"commit_id,omitempty"`
+ Milestone *Milestone `json:"milestone,omitempty"`
+ Label *Label `json:"label,omitempty"`
+ Rename *Rename `json:"rename,omitempty"`
+ LockReason *string `json:"lock_reason,omitempty"`
+}
+
+// ListIssueEvents lists events for the specified issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-an-issue
+func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*IssueEvent, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%v/events", owner, repo, number)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeLockReasonPreview)
+
+ var events []*IssueEvent
+ resp, err := s.client.Do(ctx, req, &events)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return events, resp, nil
+}
+
+// ListRepositoryEvents lists events for the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-a-repository
+func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo)
+ 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
+ }
+
+ var events []*IssueEvent
+ resp, err := s.client.Do(ctx, req, &events)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return events, resp, nil
+}
+
+// GetEvent returns the specified issue event.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/events/#get-a-single-event
+func (s *IssuesService) GetEvent(ctx context.Context, owner, repo string, id int64) (*IssueEvent, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/events/%v", owner, repo, id)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ event := new(IssueEvent)
+ resp, err := s.client.Do(ctx, req, event)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return event, resp, nil
+}
+
+// Rename contains details for 'renamed' events.
+type Rename struct {
+ From *string `json:"from,omitempty"`
+ To *string `json:"to,omitempty"`
+}
+
+func (r Rename) String() string {
+ return Stringify(r)
+}
diff --git a/vendor/github.com/google/go-github/github/issues_events_test.go b/vendor/github.com/google/go-github/github/issues_events_test.go
new file mode 100644
index 0000000..fe21ecb
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_events_test.go
@@ -0,0 +1,84 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestIssuesService_ListIssueEvents(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/events", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "1",
+ "per_page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ events, _, err := client.Issues.ListIssueEvents(context.Background(), "o", "r", 1, opt)
+ if err != nil {
+ t.Errorf("Issues.ListIssueEvents returned error: %v", err)
+ }
+
+ want := []*IssueEvent{{ID: Int64(1)}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Issues.ListIssueEvents returned %+v, want %+v", events, want)
+ }
+}
+
+func TestIssuesService_ListRepositoryEvents(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/events", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "1",
+ "per_page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ events, _, err := client.Issues.ListRepositoryEvents(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Issues.ListRepositoryEvents returned error: %v", err)
+ }
+
+ want := []*IssueEvent{{ID: Int64(1)}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Issues.ListRepositoryEvents returned %+v, want %+v", events, want)
+ }
+}
+
+func TestIssuesService_GetEvent(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/events/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ event, _, err := client.Issues.GetEvent(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Issues.GetEvent returned error: %v", err)
+ }
+
+ want := &IssueEvent{ID: Int64(1)}
+ if !reflect.DeepEqual(event, want) {
+ t.Errorf("Issues.GetEvent returned %+v, want %+v", event, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/issues_labels.go b/vendor/github.com/google/go-github/github/issues_labels.go
new file mode 100644
index 0000000..adcbe06
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_labels.go
@@ -0,0 +1,261 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// Label represents a GitHub label on an Issue
+type Label struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Color *string `json:"color,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Default *bool `json:"default,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+func (l Label) String() string {
+ return Stringify(l)
+}
+
+// ListLabels lists all labels for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#list-all-labels-for-this-repository
+func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Label, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/labels", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ var labels []*Label
+ resp, err := s.client.Do(ctx, req, &labels)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return labels, resp, nil
+}
+
+// GetLabel gets a single label.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#get-a-single-label
+func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, name string) (*Label, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name)
+ 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", mediaTypeLabelDescriptionSearchPreview)
+
+ label := new(Label)
+ resp, err := s.client.Do(ctx, req, label)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return label, resp, nil
+}
+
+// CreateLabel creates a new label on the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#create-a-label
+func (s *IssuesService) CreateLabel(ctx context.Context, owner string, repo string, label *Label) (*Label, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/labels", owner, repo)
+ req, err := s.client.NewRequest("POST", u, label)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ l := new(Label)
+ resp, err := s.client.Do(ctx, req, l)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return l, resp, nil
+}
+
+// EditLabel edits a label.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#update-a-label
+func (s *IssuesService) EditLabel(ctx context.Context, owner string, repo string, name string, label *Label) (*Label, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name)
+ req, err := s.client.NewRequest("PATCH", u, label)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ l := new(Label)
+ resp, err := s.client.Do(ctx, req, l)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return l, resp, nil
+}
+
+// DeleteLabel deletes a label.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#delete-a-label
+func (s *IssuesService) DeleteLabel(ctx context.Context, owner string, repo string, name string) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
+
+// ListLabelsByIssue lists all labels for an issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#list-labels-on-an-issue
+func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*Label, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ var labels []*Label
+ resp, err := s.client.Do(ctx, req, &labels)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return labels, resp, nil
+}
+
+// AddLabelsToIssue adds labels to an issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#add-labels-to-an-issue
+func (s *IssuesService) AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number)
+ req, err := s.client.NewRequest("POST", u, labels)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ var l []*Label
+ resp, err := s.client.Do(ctx, req, &l)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return l, resp, nil
+}
+
+// RemoveLabelForIssue removes a label for an issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#remove-a-label-from-an-issue
+func (s *IssuesService) RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%d/labels/%v", owner, repo, number, label)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ReplaceLabelsForIssue replaces all labels for an issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#replace-all-labels-for-an-issue
+func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number)
+ req, err := s.client.NewRequest("PUT", u, labels)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ var l []*Label
+ resp, err := s.client.Do(ctx, req, &l)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return l, resp, nil
+}
+
+// RemoveLabelsForIssue removes all labels for an issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#remove-all-labels-from-an-issue
+func (s *IssuesService) RemoveLabelsForIssue(ctx context.Context, owner string, repo string, number int) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ListLabelsForMilestone lists labels for every issue in a milestone.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/labels/#get-labels-for-every-issue-in-a-milestone
+func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*Label, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/milestones/%d/labels", owner, repo, number)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ var labels []*Label
+ resp, err := s.client.Do(ctx, req, &labels)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return labels, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/issues_labels_test.go b/vendor/github.com/google/go-github/github/issues_labels_test.go
new file mode 100644
index 0000000..6437d88
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_labels_test.go
@@ -0,0 +1,360 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestIssuesService_ListLabels(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/labels", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"name": "a"},{"name": "b"}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ labels, _, err := client.Issues.ListLabels(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Issues.ListLabels returned error: %v", err)
+ }
+
+ want := []*Label{{Name: String("a")}, {Name: String("b")}}
+ if !reflect.DeepEqual(labels, want) {
+ t.Errorf("Issues.ListLabels returned %+v, want %+v", labels, want)
+ }
+}
+
+func TestIssuesService_ListLabels_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.ListLabels(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_GetLabel(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/labels/n", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ fmt.Fprint(w, `{"url":"u", "name": "n", "color": "c", "description": "d"}`)
+ })
+
+ label, _, err := client.Issues.GetLabel(context.Background(), "o", "r", "n")
+ if err != nil {
+ t.Errorf("Issues.GetLabel returned error: %v", err)
+ }
+
+ want := &Label{URL: String("u"), Name: String("n"), Color: String("c"), Description: String("d")}
+ if !reflect.DeepEqual(label, want) {
+ t.Errorf("Issues.GetLabel returned %+v, want %+v", label, want)
+ }
+}
+
+func TestIssuesService_GetLabel_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.GetLabel(context.Background(), "%", "%", "%")
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_CreateLabel(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Label{Name: String("n")}
+
+ mux.HandleFunc("/repos/o/r/labels", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Label)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"url":"u"}`)
+ })
+
+ label, _, err := client.Issues.CreateLabel(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Issues.CreateLabel returned error: %v", err)
+ }
+
+ want := &Label{URL: String("u")}
+ if !reflect.DeepEqual(label, want) {
+ t.Errorf("Issues.CreateLabel returned %+v, want %+v", label, want)
+ }
+}
+
+func TestIssuesService_CreateLabel_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.CreateLabel(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_EditLabel(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Label{Name: String("z")}
+
+ mux.HandleFunc("/repos/o/r/labels/n", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Label)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"url":"u"}`)
+ })
+
+ label, _, err := client.Issues.EditLabel(context.Background(), "o", "r", "n", input)
+ if err != nil {
+ t.Errorf("Issues.EditLabel returned error: %v", err)
+ }
+
+ want := &Label{URL: String("u")}
+ if !reflect.DeepEqual(label, want) {
+ t.Errorf("Issues.EditLabel returned %+v, want %+v", label, want)
+ }
+}
+
+func TestIssuesService_EditLabel_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.EditLabel(context.Background(), "%", "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_DeleteLabel(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/labels/n", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Issues.DeleteLabel(context.Background(), "o", "r", "n")
+ if err != nil {
+ t.Errorf("Issues.DeleteLabel returned error: %v", err)
+ }
+}
+
+func TestIssuesService_DeleteLabel_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Issues.DeleteLabel(context.Background(), "%", "%", "%")
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_ListLabelsByIssue(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/labels", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"name":"a","id":1},{"name":"b","id":2}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ labels, _, err := client.Issues.ListLabelsByIssue(context.Background(), "o", "r", 1, opt)
+ if err != nil {
+ t.Errorf("Issues.ListLabelsByIssue returned error: %v", err)
+ }
+
+ want := []*Label{
+ {Name: String("a"), ID: Int64(1)},
+ {Name: String("b"), ID: Int64(2)},
+ }
+ if !reflect.DeepEqual(labels, want) {
+ t.Errorf("Issues.ListLabelsByIssue returned %+v, want %+v", labels, want)
+ }
+}
+
+func TestIssuesService_ListLabelsByIssue_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.ListLabelsByIssue(context.Background(), "%", "%", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_AddLabelsToIssue(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := []string{"a", "b"}
+
+ mux.HandleFunc("/repos/o/r/issues/1/labels", func(w http.ResponseWriter, r *http.Request) {
+ var v []string
+ json.NewDecoder(r.Body).Decode(&v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `[{"url":"u"}]`)
+ })
+
+ labels, _, err := client.Issues.AddLabelsToIssue(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Issues.AddLabelsToIssue returned error: %v", err)
+ }
+
+ want := []*Label{{URL: String("u")}}
+ if !reflect.DeepEqual(labels, want) {
+ t.Errorf("Issues.AddLabelsToIssue returned %+v, want %+v", labels, want)
+ }
+}
+
+func TestIssuesService_AddLabelsToIssue_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.AddLabelsToIssue(context.Background(), "%", "%", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_RemoveLabelForIssue(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/labels/l", func(w http.ResponseWriter, r *http.Request) {
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Issues.RemoveLabelForIssue(context.Background(), "o", "r", 1, "l")
+ if err != nil {
+ t.Errorf("Issues.RemoveLabelForIssue returned error: %v", err)
+ }
+}
+
+func TestIssuesService_RemoveLabelForIssue_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Issues.RemoveLabelForIssue(context.Background(), "%", "%", 1, "%")
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_ReplaceLabelsForIssue(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := []string{"a", "b"}
+
+ mux.HandleFunc("/repos/o/r/issues/1/labels", func(w http.ResponseWriter, r *http.Request) {
+ var v []string
+ json.NewDecoder(r.Body).Decode(&v)
+
+ testMethod(t, r, "PUT")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `[{"url":"u"}]`)
+ })
+
+ labels, _, err := client.Issues.ReplaceLabelsForIssue(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Issues.ReplaceLabelsForIssue returned error: %v", err)
+ }
+
+ want := []*Label{{URL: String("u")}}
+ if !reflect.DeepEqual(labels, want) {
+ t.Errorf("Issues.ReplaceLabelsForIssue returned %+v, want %+v", labels, want)
+ }
+}
+
+func TestIssuesService_ReplaceLabelsForIssue_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.ReplaceLabelsForIssue(context.Background(), "%", "%", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_RemoveLabelsForIssue(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/labels", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ })
+
+ _, err := client.Issues.RemoveLabelsForIssue(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Issues.RemoveLabelsForIssue returned error: %v", err)
+ }
+}
+
+func TestIssuesService_RemoveLabelsForIssue_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Issues.RemoveLabelsForIssue(context.Background(), "%", "%", 1)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_ListLabelsForMilestone(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/milestones/1/labels", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"name": "a"},{"name": "b"}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ labels, _, err := client.Issues.ListLabelsForMilestone(context.Background(), "o", "r", 1, opt)
+ if err != nil {
+ t.Errorf("Issues.ListLabelsForMilestone returned error: %v", err)
+ }
+
+ want := []*Label{{Name: String("a")}, {Name: String("b")}}
+ if !reflect.DeepEqual(labels, want) {
+ t.Errorf("Issues.ListLabelsForMilestone returned %+v, want %+v", labels, want)
+ }
+}
+
+func TestIssuesService_ListLabelsForMilestone_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.ListLabelsForMilestone(context.Background(), "%", "%", 1, nil)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/issues_milestones.go b/vendor/github.com/google/go-github/github/issues_milestones.go
new file mode 100644
index 0000000..ffe9aae
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_milestones.go
@@ -0,0 +1,148 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// Milestone represents a GitHub repository milestone.
+type Milestone struct {
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ LabelsURL *string `json:"labels_url,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+ Number *int `json:"number,omitempty"`
+ State *string `json:"state,omitempty"`
+ Title *string `json:"title,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Creator *User `json:"creator,omitempty"`
+ OpenIssues *int `json:"open_issues,omitempty"`
+ ClosedIssues *int `json:"closed_issues,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+ ClosedAt *time.Time `json:"closed_at,omitempty"`
+ DueOn *time.Time `json:"due_on,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+func (m Milestone) String() string {
+ return Stringify(m)
+}
+
+// MilestoneListOptions specifies the optional parameters to the
+// IssuesService.ListMilestones method.
+type MilestoneListOptions struct {
+ // State filters milestones based on their state. Possible values are:
+ // open, closed, all. Default is "open".
+ State string `url:"state,omitempty"`
+
+ // Sort specifies how to sort milestones. Possible values are: due_on, completeness.
+ // Default value is "due_on".
+ Sort string `url:"sort,omitempty"`
+
+ // Direction in which to sort milestones. Possible values are: asc, desc.
+ // Default is "asc".
+ Direction string `url:"direction,omitempty"`
+
+ ListOptions
+}
+
+// ListMilestones lists all milestones for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository
+func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo string, opt *MilestoneListOptions) ([]*Milestone, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo)
+ 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
+ }
+
+ var milestones []*Milestone
+ resp, err := s.client.Do(ctx, req, &milestones)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return milestones, resp, nil
+}
+
+// GetMilestone gets a single milestone.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/milestones/#get-a-single-milestone
+func (s *IssuesService) GetMilestone(ctx context.Context, owner string, repo string, number int) (*Milestone, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ milestone := new(Milestone)
+ resp, err := s.client.Do(ctx, req, milestone)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return milestone, resp, nil
+}
+
+// CreateMilestone creates a new milestone on the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/milestones/#create-a-milestone
+func (s *IssuesService) CreateMilestone(ctx context.Context, owner string, repo string, milestone *Milestone) (*Milestone, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo)
+ req, err := s.client.NewRequest("POST", u, milestone)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ m := new(Milestone)
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// EditMilestone edits a milestone.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/milestones/#update-a-milestone
+func (s *IssuesService) EditMilestone(ctx context.Context, owner string, repo string, number int, milestone *Milestone) (*Milestone, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number)
+ req, err := s.client.NewRequest("PATCH", u, milestone)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ m := new(Milestone)
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// DeleteMilestone deletes a milestone.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/milestones/#delete-a-milestone
+func (s *IssuesService) DeleteMilestone(ctx context.Context, owner string, repo string, number int) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/issues_milestones_test.go b/vendor/github.com/google/go-github/github/issues_milestones_test.go
new file mode 100644
index 0000000..019f00a
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_milestones_test.go
@@ -0,0 +1,174 @@
+// Copyright 2014 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestIssuesService_ListMilestones(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/milestones", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "state": "closed",
+ "sort": "due_date",
+ "direction": "asc",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"number":1}]`)
+ })
+
+ opt := &MilestoneListOptions{"closed", "due_date", "asc", ListOptions{Page: 2}}
+ milestones, _, err := client.Issues.ListMilestones(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("IssuesService.ListMilestones returned error: %v", err)
+ }
+
+ want := []*Milestone{{Number: Int(1)}}
+ if !reflect.DeepEqual(milestones, want) {
+ t.Errorf("IssuesService.ListMilestones returned %+v, want %+v", milestones, want)
+ }
+}
+
+func TestIssuesService_ListMilestones_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.ListMilestones(context.Background(), "%", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_GetMilestone(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"number":1}`)
+ })
+
+ milestone, _, err := client.Issues.GetMilestone(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("IssuesService.GetMilestone returned error: %v", err)
+ }
+
+ want := &Milestone{Number: Int(1)}
+ if !reflect.DeepEqual(milestone, want) {
+ t.Errorf("IssuesService.GetMilestone returned %+v, want %+v", milestone, want)
+ }
+}
+
+func TestIssuesService_GetMilestone_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.GetMilestone(context.Background(), "%", "r", 1)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_CreateMilestone(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Milestone{Title: String("t")}
+
+ mux.HandleFunc("/repos/o/r/milestones", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Milestone)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"number":1}`)
+ })
+
+ milestone, _, err := client.Issues.CreateMilestone(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("IssuesService.CreateMilestone returned error: %v", err)
+ }
+
+ want := &Milestone{Number: Int(1)}
+ if !reflect.DeepEqual(milestone, want) {
+ t.Errorf("IssuesService.CreateMilestone returned %+v, want %+v", milestone, want)
+ }
+}
+
+func TestIssuesService_CreateMilestone_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.CreateMilestone(context.Background(), "%", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_EditMilestone(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Milestone{Title: String("t")}
+
+ mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Milestone)
+ 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, `{"number":1}`)
+ })
+
+ milestone, _, err := client.Issues.EditMilestone(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("IssuesService.EditMilestone returned error: %v", err)
+ }
+
+ want := &Milestone{Number: Int(1)}
+ if !reflect.DeepEqual(milestone, want) {
+ t.Errorf("IssuesService.EditMilestone returned %+v, want %+v", milestone, want)
+ }
+}
+
+func TestIssuesService_EditMilestone_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.EditMilestone(context.Background(), "%", "r", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_DeleteMilestone(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Issues.DeleteMilestone(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("IssuesService.DeleteMilestone returned error: %v", err)
+ }
+}
+
+func TestIssuesService_DeleteMilestone_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Issues.DeleteMilestone(context.Background(), "%", "r", 1)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/issues_test.go b/vendor/github.com/google/go-github/github/issues_test.go
new file mode 100644
index 0000000..22190a0
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_test.go
@@ -0,0 +1,328 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+)
+
+func TestIssuesService_List_all(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ mux.HandleFunc("/issues", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ testFormValues(t, r, values{
+ "filter": "all",
+ "state": "closed",
+ "labels": "a,b",
+ "sort": "updated",
+ "direction": "asc",
+ "since": "2002-02-10T15:30:00Z",
+ "page": "1",
+ "per_page": "2",
+ })
+ fmt.Fprint(w, `[{"number":1}]`)
+ })
+
+ opt := &IssueListOptions{
+ "all", "closed", []string{"a", "b"}, "updated", "asc",
+ time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC),
+ ListOptions{Page: 1, PerPage: 2},
+ }
+ issues, _, err := client.Issues.List(context.Background(), true, opt)
+ if err != nil {
+ t.Errorf("Issues.List returned error: %v", err)
+ }
+
+ want := []*Issue{{Number: Int(1)}}
+ if !reflect.DeepEqual(issues, want) {
+ t.Errorf("Issues.List returned %+v, want %+v", issues, want)
+ }
+}
+
+func TestIssuesService_List_owned(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ mux.HandleFunc("/user/issues", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ fmt.Fprint(w, `[{"number":1}]`)
+ })
+
+ issues, _, err := client.Issues.List(context.Background(), false, nil)
+ if err != nil {
+ t.Errorf("Issues.List returned error: %v", err)
+ }
+
+ want := []*Issue{{Number: Int(1)}}
+ if !reflect.DeepEqual(issues, want) {
+ t.Errorf("Issues.List returned %+v, want %+v", issues, want)
+ }
+}
+
+func TestIssuesService_ListByOrg(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ mux.HandleFunc("/orgs/o/issues", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ fmt.Fprint(w, `[{"number":1}]`)
+ })
+
+ issues, _, err := client.Issues.ListByOrg(context.Background(), "o", nil)
+ if err != nil {
+ t.Errorf("Issues.ListByOrg returned error: %v", err)
+ }
+
+ want := []*Issue{{Number: Int(1)}}
+ if !reflect.DeepEqual(issues, want) {
+ t.Errorf("Issues.List returned %+v, want %+v", issues, want)
+ }
+}
+
+func TestIssuesService_ListByOrg_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.ListByOrg(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_ListByRepo(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeIntegrationPreview}
+ mux.HandleFunc("/repos/o/r/issues", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ testFormValues(t, r, values{
+ "milestone": "*",
+ "state": "closed",
+ "assignee": "a",
+ "creator": "c",
+ "mentioned": "m",
+ "labels": "a,b",
+ "sort": "updated",
+ "direction": "asc",
+ "since": "2002-02-10T15:30:00Z",
+ })
+ fmt.Fprint(w, `[{"number":1}]`)
+ })
+
+ opt := &IssueListByRepoOptions{
+ "*", "closed", "a", "c", "m", []string{"a", "b"}, "updated", "asc",
+ time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC),
+ ListOptions{0, 0},
+ }
+ issues, _, err := client.Issues.ListByRepo(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Issues.ListByOrg returned error: %v", err)
+ }
+
+ want := []*Issue{{Number: Int(1)}}
+ if !reflect.DeepEqual(issues, want) {
+ t.Errorf("Issues.List returned %+v, want %+v", issues, want)
+ }
+}
+
+func TestIssuesService_ListByRepo_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.ListByRepo(context.Background(), "%", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_Get(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ mux.HandleFunc("/repos/o/r/issues/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ fmt.Fprint(w, `{"number":1, "labels": [{"url": "u", "name": "n", "color": "c"}]}`)
+ })
+
+ issue, _, err := client.Issues.Get(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Issues.Get returned error: %v", err)
+ }
+
+ want := &Issue{
+ Number: Int(1),
+ Labels: []Label{{
+ URL: String("u"),
+ Name: String("n"),
+ Color: String("c"),
+ }},
+ }
+ if !reflect.DeepEqual(issue, want) {
+ t.Errorf("Issues.Get returned %+v, want %+v", issue, want)
+ }
+}
+
+func TestIssuesService_Get_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.Get(context.Background(), "%", "r", 1)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_Create(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &IssueRequest{
+ Title: String("t"),
+ Body: String("b"),
+ Assignee: String("a"),
+ Labels: &[]string{"l1", "l2"},
+ }
+
+ mux.HandleFunc("/repos/o/r/issues", func(w http.ResponseWriter, r *http.Request) {
+ v := new(IssueRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"number":1}`)
+ })
+
+ issue, _, err := client.Issues.Create(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Issues.Create returned error: %v", err)
+ }
+
+ want := &Issue{Number: Int(1)}
+ if !reflect.DeepEqual(issue, want) {
+ t.Errorf("Issues.Create returned %+v, want %+v", issue, want)
+ }
+}
+
+func TestIssuesService_Create_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.Create(context.Background(), "%", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_Edit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &IssueRequest{Title: String("t")}
+
+ mux.HandleFunc("/repos/o/r/issues/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(IssueRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"number":1}`)
+ })
+
+ issue, _, err := client.Issues.Edit(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Issues.Edit returned error: %v", err)
+ }
+
+ want := &Issue{Number: Int(1)}
+ if !reflect.DeepEqual(issue, want) {
+ t.Errorf("Issues.Edit returned %+v, want %+v", issue, want)
+ }
+}
+
+func TestIssuesService_Edit_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Issues.Edit(context.Background(), "%", "r", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestIssuesService_Lock(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/lock", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ if _, err := client.Issues.Lock(context.Background(), "o", "r", 1, nil); err != nil {
+ t.Errorf("Issues.Lock returned error: %v", err)
+ }
+}
+
+func TestIssuesService_LockWithReason(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/lock", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ testHeader(t, r, "Accept", mediaTypeLockReasonPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ opt := &LockIssueOptions{LockReason: "off-topic"}
+
+ if _, err := client.Issues.Lock(context.Background(), "o", "r", 1, opt); err != nil {
+ t.Errorf("Issues.Lock returned error: %v", err)
+ }
+}
+
+func TestIssuesService_Unlock(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/lock", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ if _, err := client.Issues.Unlock(context.Background(), "o", "r", 1); err != nil {
+ t.Errorf("Issues.Unlock returned error: %v", err)
+ }
+}
+
+func TestIsPullRequest(t *testing.T) {
+ i := new(Issue)
+ if i.IsPullRequest() == true {
+ t.Errorf("expected i.IsPullRequest (%v) to return false, got true", i)
+ }
+ i.PullRequestLinks = &PullRequestLinks{URL: String("http://example.com")}
+ if i.IsPullRequest() == false {
+ t.Errorf("expected i.IsPullRequest (%v) to return true, got false", i)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/issues_timeline.go b/vendor/github.com/google/go-github/github/issues_timeline.go
new file mode 100644
index 0000000..9cfda83
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_timeline.go
@@ -0,0 +1,149 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// Timeline represents an event that occurred around an Issue or Pull Request.
+//
+// It is similar to an IssueEvent but may contain more information.
+// GitHub API docs: https://developer.github.com/v3/issues/timeline/
+type Timeline struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ CommitURL *string `json:"commit_url,omitempty"`
+
+ // The User object that generated the event.
+ Actor *User `json:"actor,omitempty"`
+
+ // Event identifies the actual type of Event that occurred. Possible values
+ // are:
+ //
+ // assigned
+ // The issue was assigned to the assignee.
+ //
+ // closed
+ // The issue was closed by the actor. When the commit_id is present, it
+ // identifies the commit that closed the issue using "closes / fixes #NN"
+ // syntax.
+ //
+ // commented
+ // A comment was added to the issue.
+ //
+ // committed
+ // A commit was added to the pull request's 'HEAD' branch. Only provided
+ // for pull requests.
+ //
+ // cross-referenced
+ // The issue was referenced from another issue. The 'source' attribute
+ // contains the 'id', 'actor', and 'url' of the reference's source.
+ //
+ // demilestoned
+ // The issue was removed from a milestone.
+ //
+ // head_ref_deleted
+ // The pull request's branch was deleted.
+ //
+ // head_ref_restored
+ // The pull request's branch was restored.
+ //
+ // labeled
+ // A label was added to the issue.
+ //
+ // locked
+ // The issue was locked by the actor.
+ //
+ // mentioned
+ // The actor was @mentioned in an issue body.
+ //
+ // merged
+ // The issue was merged by the actor. The 'commit_id' attribute is the
+ // SHA1 of the HEAD commit that was merged.
+ //
+ // milestoned
+ // The issue was added to a milestone.
+ //
+ // referenced
+ // The issue was referenced from a commit message. The 'commit_id'
+ // attribute is the commit SHA1 of where that happened.
+ //
+ // renamed
+ // The issue title was changed.
+ //
+ // reopened
+ // The issue was reopened by the actor.
+ //
+ // subscribed
+ // The actor subscribed to receive notifications for an issue.
+ //
+ // unassigned
+ // The assignee was unassigned from the issue.
+ //
+ // unlabeled
+ // A label was removed from the issue.
+ //
+ // unlocked
+ // The issue was unlocked by the actor.
+ //
+ // unsubscribed
+ // The actor unsubscribed to stop receiving notifications for an issue.
+ //
+ Event *string `json:"event,omitempty"`
+
+ // The string SHA of a commit that referenced this Issue or Pull Request.
+ CommitID *string `json:"commit_id,omitempty"`
+ // The timestamp indicating when the event occurred.
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ // The Label object including `name` and `color` attributes. Only provided for
+ // 'labeled' and 'unlabeled' events.
+ Label *Label `json:"label,omitempty"`
+ // The User object which was assigned to (or unassigned from) this Issue or
+ // Pull Request. Only provided for 'assigned' and 'unassigned' events.
+ Assignee *User `json:"assignee,omitempty"`
+ // The Milestone object including a 'title' attribute.
+ // Only provided for 'milestoned' and 'demilestoned' events.
+ Milestone *Milestone `json:"milestone,omitempty"`
+ // The 'id', 'actor', and 'url' for the source of a reference from another issue.
+ // Only provided for 'cross-referenced' events.
+ Source *Source `json:"source,omitempty"`
+ // An object containing rename details including 'from' and 'to' attributes.
+ // Only provided for 'renamed' events.
+ Rename *Rename `json:"rename,omitempty"`
+}
+
+// Source represents a reference's source.
+type Source struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Actor *User `json:"actor,omitempty"`
+}
+
+// ListIssueTimeline lists events for the specified issue.
+//
+// GitHub API docs: https://developer.github.com/v3/issues/timeline/#list-events-for-an-issue
+func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*Timeline, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%v/timeline", owner, repo, number)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeTimelinePreview)
+
+ var events []*Timeline
+ resp, err := s.client.Do(ctx, req, &events)
+ return events, resp, err
+}
diff --git a/vendor/github.com/google/go-github/github/issues_timeline_test.go b/vendor/github.com/google/go-github/github/issues_timeline_test.go
new file mode 100644
index 0000000..93f6236
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/issues_timeline_test.go
@@ -0,0 +1,40 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestIssuesService_ListIssueTimeline(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/timeline", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeTimelinePreview)
+ testFormValues(t, r, values{
+ "page": "1",
+ "per_page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1, PerPage: 2}
+ events, _, err := client.Issues.ListIssueTimeline(context.Background(), "o", "r", 1, opt)
+ if err != nil {
+ t.Errorf("Issues.ListIssueTimeline returned error: %v", err)
+ }
+
+ want := []*Timeline{{ID: Int64(1)}}
+ if !reflect.DeepEqual(events, want) {
+ t.Errorf("Issues.ListIssueTimeline = %+v, want %+v", events, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/licenses.go b/vendor/github.com/google/go-github/github/licenses.go
new file mode 100644
index 0000000..1176d3a
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/licenses.go
@@ -0,0 +1,97 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// LicensesService handles communication with the license related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/licenses/
+type LicensesService service
+
+// RepositoryLicense represents the license for a repository.
+type RepositoryLicense struct {
+ Name *string `json:"name,omitempty"`
+ Path *string `json:"path,omitempty"`
+
+ SHA *string `json:"sha,omitempty"`
+ Size *int `json:"size,omitempty"`
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ GitURL *string `json:"git_url,omitempty"`
+ DownloadURL *string `json:"download_url,omitempty"`
+ Type *string `json:"type,omitempty"`
+ Content *string `json:"content,omitempty"`
+ Encoding *string `json:"encoding,omitempty"`
+ License *License `json:"license,omitempty"`
+}
+
+func (l RepositoryLicense) String() string {
+ return Stringify(l)
+}
+
+// License represents an open source license.
+type License struct {
+ Key *string `json:"key,omitempty"`
+ Name *string `json:"name,omitempty"`
+ URL *string `json:"url,omitempty"`
+
+ SPDXID *string `json:"spdx_id,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ Featured *bool `json:"featured,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Implementation *string `json:"implementation,omitempty"`
+ Permissions *[]string `json:"permissions,omitempty"`
+ Conditions *[]string `json:"conditions,omitempty"`
+ Limitations *[]string `json:"limitations,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(ctx context.Context) ([]*License, *Response, error) {
+ req, err := s.client.NewRequest("GET", "licenses", nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var licenses []*License
+ resp, err := s.client.Do(ctx, req, &licenses)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return licenses, resp, nil
+}
+
+// Get extended metadata for one license.
+//
+// GitHub API docs: https://developer.github.com/v3/licenses/#get-an-individual-license
+func (s *LicensesService) Get(ctx context.Context, 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
+ }
+
+ license := new(License)
+ resp, err := s.client.Do(ctx, req, license)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return license, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/licenses_test.go b/vendor/github.com/google/go-github/github/licenses_test.go
new file mode 100644
index 0000000..a71f6a4
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/licenses_test.go
@@ -0,0 +1,68 @@
+// 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestLicensesService_List(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/licenses", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"key":"mit","name":"MIT","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","featured":true}]`)
+ })
+
+ licenses, _, err := client.Licenses.List(context.Background())
+ if err != nil {
+ t.Errorf("Licenses.List returned error: %v", err)
+ }
+
+ want := []*License{{
+ Key: String("mit"),
+ Name: String("MIT"),
+ SPDXID: String("MIT"),
+ URL: String("https://api.github.com/licenses/mit"),
+ Featured: Bool(true),
+ }}
+ if !reflect.DeepEqual(licenses, want) {
+ t.Errorf("Licenses.List returned %+v, want %+v", licenses, want)
+ }
+}
+
+func TestLicensesService_Get(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/licenses/mit", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"key":"mit","name":"MIT"}`)
+ })
+
+ license, _, err := client.Licenses.Get(context.Background(), "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) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Licenses.Get(context.Background(), "%")
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/messages.go b/vendor/github.com/google/go-github/github/messages.go
new file mode 100644
index 0000000..519c1c0
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/messages.go
@@ -0,0 +1,247 @@
+// Copyright 2016 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.
+
+// This file provides functions for validating payloads from GitHub Webhooks.
+// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github
+
+package github
+
+import (
+ "crypto/hmac"
+ "crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "hash"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+const (
+ // sha1Prefix is the prefix used by GitHub before the HMAC hexdigest.
+ sha1Prefix = "sha1"
+ // sha256Prefix and sha512Prefix are provided for future compatibility.
+ sha256Prefix = "sha256"
+ sha512Prefix = "sha512"
+ // signatureHeader is the GitHub header key used to pass the HMAC hexdigest.
+ signatureHeader = "X-Hub-Signature"
+ // eventTypeHeader is the GitHub header key used to pass the event type.
+ eventTypeHeader = "X-Github-Event"
+ // deliveryIDHeader is the GitHub header key used to pass the unique ID for the webhook event.
+ deliveryIDHeader = "X-Github-Delivery"
+)
+
+var (
+ // eventTypeMapping maps webhooks types to their corresponding go-github struct types.
+ eventTypeMapping = map[string]string{
+ "check_run": "CheckRunEvent",
+ "check_suite": "CheckSuiteEvent",
+ "commit_comment": "CommitCommentEvent",
+ "create": "CreateEvent",
+ "delete": "DeleteEvent",
+ "deployment": "DeploymentEvent",
+ "deployment_status": "DeploymentStatusEvent",
+ "fork": "ForkEvent",
+ "gollum": "GollumEvent",
+ "installation": "InstallationEvent",
+ "installation_repositories": "InstallationRepositoriesEvent",
+ "issue_comment": "IssueCommentEvent",
+ "issues": "IssuesEvent",
+ "label": "LabelEvent",
+ "marketplace_purchase": "MarketplacePurchaseEvent",
+ "member": "MemberEvent",
+ "membership": "MembershipEvent",
+ "milestone": "MilestoneEvent",
+ "organization": "OrganizationEvent",
+ "org_block": "OrgBlockEvent",
+ "page_build": "PageBuildEvent",
+ "ping": "PingEvent",
+ "project": "ProjectEvent",
+ "project_card": "ProjectCardEvent",
+ "project_column": "ProjectColumnEvent",
+ "public": "PublicEvent",
+ "pull_request_review": "PullRequestReviewEvent",
+ "pull_request_review_comment": "PullRequestReviewCommentEvent",
+ "pull_request": "PullRequestEvent",
+ "push": "PushEvent",
+ "repository": "RepositoryEvent",
+ "release": "ReleaseEvent",
+ "status": "StatusEvent",
+ "team": "TeamEvent",
+ "team_add": "TeamAddEvent",
+ "watch": "WatchEvent",
+ }
+)
+
+// genMAC generates the HMAC signature for a message provided the secret key
+// and hashFunc.
+func genMAC(message, key []byte, hashFunc func() hash.Hash) []byte {
+ mac := hmac.New(hashFunc, key)
+ mac.Write(message)
+ return mac.Sum(nil)
+}
+
+// checkMAC reports whether messageMAC is a valid HMAC tag for message.
+func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool {
+ expectedMAC := genMAC(message, key, hashFunc)
+ return hmac.Equal(messageMAC, expectedMAC)
+}
+
+// messageMAC returns the hex-decoded HMAC tag from the signature and its
+// corresponding hash function.
+func messageMAC(signature string) ([]byte, func() hash.Hash, error) {
+ if signature == "" {
+ return nil, nil, errors.New("missing signature")
+ }
+ sigParts := strings.SplitN(signature, "=", 2)
+ if len(sigParts) != 2 {
+ return nil, nil, fmt.Errorf("error parsing signature %q", signature)
+ }
+
+ var hashFunc func() hash.Hash
+ switch sigParts[0] {
+ case sha1Prefix:
+ hashFunc = sha1.New
+ case sha256Prefix:
+ hashFunc = sha256.New
+ case sha512Prefix:
+ hashFunc = sha512.New
+ default:
+ return nil, nil, fmt.Errorf("unknown hash type prefix: %q", sigParts[0])
+ }
+
+ buf, err := hex.DecodeString(sigParts[1])
+ if err != nil {
+ return nil, nil, fmt.Errorf("error decoding signature %q: %v", signature, err)
+ }
+ return buf, hashFunc, nil
+}
+
+// ValidatePayload validates an incoming GitHub Webhook event request
+// and returns the (JSON) payload.
+// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded".
+// If the Content-Type is neither then an error is returned.
+// secretKey is the GitHub Webhook secret message.
+//
+// Example usage:
+//
+// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+// payload, err := github.ValidatePayload(r, s.webhookSecretKey)
+// if err != nil { ... }
+// // Process payload...
+// }
+//
+func ValidatePayload(r *http.Request, secretKey []byte) (payload []byte, err error) {
+ var body []byte // Raw body that GitHub uses to calculate the signature.
+
+ switch ct := r.Header.Get("Content-Type"); ct {
+ case "application/json":
+ var err error
+ if body, err = ioutil.ReadAll(r.Body); err != nil {
+ return nil, err
+ }
+
+ // If the content type is application/json,
+ // the JSON payload is just the original body.
+ payload = body
+
+ case "application/x-www-form-urlencoded":
+ // payloadFormParam is the name of the form parameter that the JSON payload
+ // will be in if a webhook has its content type set to application/x-www-form-urlencoded.
+ const payloadFormParam = "payload"
+
+ var err error
+ if body, err = ioutil.ReadAll(r.Body); err != nil {
+ return nil, err
+ }
+
+ // If the content type is application/x-www-form-urlencoded,
+ // the JSON payload will be under the "payload" form param.
+ form, err := url.ParseQuery(string(body))
+ if err != nil {
+ return nil, err
+ }
+ payload = []byte(form.Get(payloadFormParam))
+
+ default:
+ return nil, fmt.Errorf("Webhook request has unsupported Content-Type %q", ct)
+ }
+
+ sig := r.Header.Get(signatureHeader)
+ if err := ValidateSignature(sig, body, secretKey); err != nil {
+ return nil, err
+ }
+ return payload, nil
+}
+
+// ValidateSignature validates the signature for the given payload.
+// signature is the GitHub hash signature delivered in the X-Hub-Signature header.
+// payload is the JSON payload sent by GitHub Webhooks.
+// secretKey is the GitHub Webhook secret message.
+//
+// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github
+func ValidateSignature(signature string, payload, secretKey []byte) error {
+ messageMAC, hashFunc, err := messageMAC(signature)
+ if err != nil {
+ return err
+ }
+ if !checkMAC(payload, messageMAC, secretKey, hashFunc) {
+ return errors.New("payload signature check failed")
+ }
+ return nil
+}
+
+// WebHookType returns the event type of webhook request r.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/hooks/#webhook-headers
+func WebHookType(r *http.Request) string {
+ return r.Header.Get(eventTypeHeader)
+}
+
+// DeliveryID returns the unique delivery ID of webhook request r.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/hooks/#webhook-headers
+func DeliveryID(r *http.Request) string {
+ return r.Header.Get(deliveryIDHeader)
+}
+
+// ParseWebHook parses the event payload. For recognized event types, a
+// value of the corresponding struct type will be returned (as returned
+// by Event.ParsePayload()). An error will be returned for unrecognized event
+// types.
+//
+// Example usage:
+//
+// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+// payload, err := github.ValidatePayload(r, s.webhookSecretKey)
+// if err != nil { ... }
+// event, err := github.ParseWebHook(github.WebHookType(r), payload)
+// if err != nil { ... }
+// switch event := event.(type) {
+// case *github.CommitCommentEvent:
+// processCommitCommentEvent(event)
+// case *github.CreateEvent:
+// processCreateEvent(event)
+// ...
+// }
+// }
+//
+func ParseWebHook(messageType string, payload []byte) (interface{}, error) {
+ eventType, ok := eventTypeMapping[messageType]
+ if !ok {
+ return nil, fmt.Errorf("unknown X-Github-Event in message: %v", messageType)
+ }
+
+ event := Event{
+ Type: &eventType,
+ RawPayload: (*json.RawMessage)(&payload),
+ }
+ return event.ParsePayload()
+}
diff --git a/vendor/github.com/google/go-github/github/messages_test.go b/vendor/github.com/google/go-github/github/messages_test.go
new file mode 100644
index 0000000..0b677ca
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/messages_test.go
@@ -0,0 +1,338 @@
+// Copyright 2016 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 (
+ "bytes"
+ "encoding/json"
+ "net/http"
+ "net/url"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestValidatePayload(t *testing.T) {
+ const defaultBody = `{"yo":true}` // All tests below use the default request body and signature.
+ const defaultSignature = "sha1=126f2c800419c60137ce748d7672e77b65cf16d6"
+ secretKey := []byte("0123456789abcdef")
+ tests := []struct {
+ signature string
+ eventID string
+ event string
+ wantEventID string
+ wantEvent string
+ wantPayload string
+ }{
+ // The following tests generate expected errors:
+ {}, // Missing signature
+ {signature: "yo"}, // Missing signature prefix
+ {signature: "sha1=yo"}, // Signature not hex string
+ {signature: "sha1=012345"}, // Invalid signature
+ // The following tests expect err=nil:
+ {
+ signature: defaultSignature,
+ eventID: "dead-beef",
+ event: "ping",
+ wantEventID: "dead-beef",
+ wantEvent: "ping",
+ wantPayload: defaultBody,
+ },
+ {
+ signature: defaultSignature,
+ event: "ping",
+ wantEvent: "ping",
+ wantPayload: defaultBody,
+ },
+ {
+ signature: "sha256=b1f8020f5b4cd42042f807dd939015c4a418bc1ff7f604dd55b0a19b5d953d9b",
+ event: "ping",
+ wantEvent: "ping",
+ wantPayload: defaultBody,
+ },
+ {
+ signature: "sha512=8456767023c1195682e182a23b3f5d19150ecea598fde8cb85918f7281b16079471b1329f92b912c4d8bd7455cb159777db8f29608b20c7c87323ba65ae62e1f",
+ event: "ping",
+ wantEvent: "ping",
+ wantPayload: defaultBody,
+ },
+ }
+
+ for _, test := range tests {
+ buf := bytes.NewBufferString(defaultBody)
+ req, err := http.NewRequest("GET", "http://localhost/event", buf)
+ if err != nil {
+ t.Fatalf("NewRequest: %v", err)
+ }
+ if test.signature != "" {
+ req.Header.Set(signatureHeader, test.signature)
+ }
+ req.Header.Set("Content-Type", "application/json")
+
+ got, err := ValidatePayload(req, secretKey)
+ if err != nil {
+ if test.wantPayload != "" {
+ t.Errorf("ValidatePayload(%#v): err = %v, want nil", test, err)
+ }
+ continue
+ }
+ if string(got) != test.wantPayload {
+ t.Errorf("ValidatePayload = %q, want %q", got, test.wantPayload)
+ }
+ }
+}
+
+func TestValidatePayload_FormGet(t *testing.T) {
+ payload := `{"yo":true}`
+ signature := "sha1=3374ef144403e8035423b23b02e2c9d7a4c50368"
+ secretKey := []byte("0123456789abcdef")
+
+ form := url.Values{}
+ form.Add("payload", payload)
+ req, err := http.NewRequest("POST", "http://localhost/event", strings.NewReader(form.Encode()))
+ if err != nil {
+ t.Fatalf("NewRequest: %v", err)
+ }
+ req.PostForm = form
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ req.Header.Set(signatureHeader, signature)
+
+ got, err := ValidatePayload(req, secretKey)
+ if err != nil {
+ t.Errorf("ValidatePayload(%#v): err = %v, want nil", payload, err)
+ }
+ if string(got) != payload {
+ t.Errorf("ValidatePayload = %q, want %q", got, payload)
+ }
+
+ // check that if payload is invalid we get error
+ req.Header.Set(signatureHeader, "invalid signature")
+ if _, err = ValidatePayload(req, nil); err == nil {
+ t.Error("ValidatePayload = nil, want err")
+ }
+}
+
+func TestValidatePayload_FormPost(t *testing.T) {
+ payload := `{"yo":true}`
+ signature := "sha1=3374ef144403e8035423b23b02e2c9d7a4c50368"
+ secretKey := []byte("0123456789abcdef")
+
+ form := url.Values{}
+ form.Set("payload", payload)
+ buf := bytes.NewBufferString(form.Encode())
+ req, err := http.NewRequest("POST", "http://localhost/event", buf)
+ if err != nil {
+ t.Fatalf("NewRequest: %v", err)
+ }
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ req.Header.Set(signatureHeader, signature)
+
+ got, err := ValidatePayload(req, secretKey)
+ if err != nil {
+ t.Errorf("ValidatePayload(%#v): err = %v, want nil", payload, err)
+ }
+ if string(got) != payload {
+ t.Errorf("ValidatePayload = %q, want %q", got, payload)
+ }
+
+ // check that if payload is invalid we get error
+ req.Header.Set(signatureHeader, "invalid signature")
+ if _, err = ValidatePayload(req, nil); err == nil {
+ t.Error("ValidatePayload = nil, want err")
+ }
+}
+
+func TestValidatePayload_InvalidContentType(t *testing.T) {
+ req, err := http.NewRequest("POST", "http://localhost/event", nil)
+ if err != nil {
+ t.Fatalf("NewRequest: %v", err)
+ }
+ req.Header.Set("Content-Type", "invalid content type")
+ if _, err = ValidatePayload(req, nil); err == nil {
+ t.Error("ValidatePayload = nil, want err")
+ }
+}
+
+func TestParseWebHook(t *testing.T) {
+ tests := []struct {
+ payload interface{}
+ messageType string
+ }{
+ {
+ payload: &CheckRunEvent{},
+ messageType: "check_run",
+ },
+ {
+ payload: &CheckSuiteEvent{},
+ messageType: "check_suite",
+ },
+ {
+ payload: &CommitCommentEvent{},
+ messageType: "commit_comment",
+ },
+ {
+ payload: &CreateEvent{},
+ messageType: "create",
+ },
+ {
+ payload: &DeleteEvent{},
+ messageType: "delete",
+ },
+ {
+ payload: &DeploymentEvent{},
+ messageType: "deployment",
+ },
+
+ {
+ payload: &DeploymentStatusEvent{},
+ messageType: "deployment_status",
+ },
+ {
+ payload: &ForkEvent{},
+ messageType: "fork",
+ },
+ {
+ payload: &GollumEvent{},
+ messageType: "gollum",
+ },
+ {
+ payload: &InstallationEvent{},
+ messageType: "installation",
+ },
+ {
+ payload: &InstallationRepositoriesEvent{},
+ messageType: "installation_repositories",
+ },
+ {
+ payload: &IssueCommentEvent{},
+ messageType: "issue_comment",
+ },
+ {
+ payload: &IssuesEvent{},
+ messageType: "issues",
+ },
+ {
+ payload: &LabelEvent{},
+ messageType: "label",
+ },
+ {
+ payload: &MarketplacePurchaseEvent{},
+ messageType: "marketplace_purchase",
+ },
+ {
+ payload: &MemberEvent{},
+ messageType: "member",
+ },
+ {
+ payload: &MembershipEvent{},
+ messageType: "membership",
+ },
+ {
+ payload: &MilestoneEvent{},
+ messageType: "milestone",
+ },
+ {
+ payload: &OrganizationEvent{},
+ messageType: "organization",
+ },
+ {
+ payload: &OrgBlockEvent{},
+ messageType: "org_block",
+ },
+ {
+ payload: &PageBuildEvent{},
+ messageType: "page_build",
+ },
+ {
+ payload: &PingEvent{},
+ messageType: "ping",
+ },
+ {
+ payload: &ProjectEvent{},
+ messageType: "project",
+ },
+ {
+ payload: &ProjectCardEvent{},
+ messageType: "project_card",
+ },
+ {
+ payload: &ProjectColumnEvent{},
+ messageType: "project_column",
+ },
+ {
+ payload: &PublicEvent{},
+ messageType: "public",
+ },
+ {
+ payload: &PullRequestEvent{},
+ messageType: "pull_request",
+ },
+ {
+ payload: &PullRequestReviewEvent{},
+ messageType: "pull_request_review",
+ },
+ {
+ payload: &PullRequestReviewCommentEvent{},
+ messageType: "pull_request_review_comment",
+ },
+ {
+ payload: &PushEvent{},
+ messageType: "push",
+ },
+ {
+ payload: &ReleaseEvent{},
+ messageType: "release",
+ },
+ {
+ payload: &RepositoryEvent{},
+ messageType: "repository",
+ },
+ {
+ payload: &StatusEvent{},
+ messageType: "status",
+ },
+ {
+ payload: &TeamEvent{},
+ messageType: "team",
+ },
+ {
+ payload: &TeamAddEvent{},
+ messageType: "team_add",
+ },
+ {
+ payload: &WatchEvent{},
+ messageType: "watch",
+ },
+ }
+
+ for _, test := range tests {
+ p, err := json.Marshal(test.payload)
+ if err != nil {
+ t.Fatalf("Marshal(%#v): %v", test.payload, err)
+ }
+ got, err := ParseWebHook(test.messageType, p)
+ if err != nil {
+ t.Fatalf("ParseWebHook: %v", err)
+ }
+ if want := test.payload; !reflect.DeepEqual(got, want) {
+ t.Errorf("ParseWebHook(%#v, %#v) = %#v, want %#v", test.messageType, p, got, want)
+ }
+ }
+}
+
+func TestDeliveryID(t *testing.T) {
+ id := "8970a780-244e-11e7-91ca-da3aabcb9793"
+ req, err := http.NewRequest("POST", "http://localhost", nil)
+ if err != nil {
+ t.Fatalf("DeliveryID: %v", err)
+ }
+ req.Header.Set("X-Github-Delivery", id)
+
+ got := DeliveryID(req)
+ if got != id {
+ t.Errorf("DeliveryID(%#v) = %q, want %q", req, got, id)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/migrations.go b/vendor/github.com/google/go-github/github/migrations.go
new file mode 100644
index 0000000..90cc1fa
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/migrations.go
@@ -0,0 +1,224 @@
+// Copyright 2016 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 (
+ "context"
+ "errors"
+ "fmt"
+ "net/http"
+ "strings"
+)
+
+// MigrationService provides access to the migration related functions
+// in the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/
+type MigrationService service
+
+// Migration represents a GitHub migration (archival).
+type Migration struct {
+ ID *int64 `json:"id,omitempty"`
+ GUID *string `json:"guid,omitempty"`
+ // State is the current state of a migration.
+ // Possible values are:
+ // "pending" which means the migration hasn't started yet,
+ // "exporting" which means the migration is in progress,
+ // "exported" which means the migration finished successfully, or
+ // "failed" which means the migration failed.
+ State *string `json:"state,omitempty"`
+ // LockRepositories indicates whether repositories are locked (to prevent
+ // manipulation) while migrating data.
+ LockRepositories *bool `json:"lock_repositories,omitempty"`
+ // ExcludeAttachments indicates whether attachments should be excluded from
+ // the migration (to reduce migration archive file size).
+ ExcludeAttachments *bool `json:"exclude_attachments,omitempty"`
+ URL *string `json:"url,omitempty"`
+ CreatedAt *string `json:"created_at,omitempty"`
+ UpdatedAt *string `json:"updated_at,omitempty"`
+ Repositories []*Repository `json:"repositories,omitempty"`
+}
+
+func (m Migration) String() string {
+ return Stringify(m)
+}
+
+// MigrationOptions specifies the optional parameters to Migration methods.
+type MigrationOptions struct {
+ // LockRepositories indicates whether repositories should be locked (to prevent
+ // manipulation) while migrating data.
+ LockRepositories bool
+
+ // ExcludeAttachments indicates whether attachments should be excluded from
+ // the migration (to reduce migration archive file size).
+ ExcludeAttachments bool
+}
+
+// startMigration represents the body of a StartMigration request.
+type startMigration struct {
+ // Repositories is a slice of repository names to migrate.
+ Repositories []string `json:"repositories,omitempty"`
+
+ // LockRepositories indicates whether repositories should be locked (to prevent
+ // manipulation) while migrating data.
+ LockRepositories *bool `json:"lock_repositories,omitempty"`
+
+ // ExcludeAttachments indicates whether attachments should be excluded from
+ // the migration (to reduce migration archive file size).
+ ExcludeAttachments *bool `json:"exclude_attachments,omitempty"`
+}
+
+// StartMigration starts the generation of a migration archive.
+// repos is a slice of repository names to migrate.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/migrations/#start-a-migration
+func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opt *MigrationOptions) (*Migration, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/migrations", org)
+
+ body := &startMigration{Repositories: repos}
+ if opt != nil {
+ body.LockRepositories = Bool(opt.LockRepositories)
+ body.ExcludeAttachments = Bool(opt.ExcludeAttachments)
+ }
+
+ req, err := s.client.NewRequest("POST", u, body)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeMigrationsPreview)
+
+ m := &Migration{}
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// ListMigrations lists the most recent migrations.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/migrations/#get-a-list-of-migrations
+func (s *MigrationService) ListMigrations(ctx context.Context, org string) ([]*Migration, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/migrations", 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", mediaTypeMigrationsPreview)
+
+ var m []*Migration
+ resp, err := s.client.Do(ctx, req, &m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// MigrationStatus gets the status of a specific migration archive.
+// id is the migration ID.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/migrations/#get-the-status-of-a-migration
+func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/migrations/%v", org, id)
+
+ 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", mediaTypeMigrationsPreview)
+
+ m := &Migration{}
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// MigrationArchiveURL fetches a migration archive URL.
+// id is the migration ID.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/migrations/#download-a-migration-archive
+func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, id int64) (url string, err error) {
+ u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return "", err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeMigrationsPreview)
+
+ s.client.clientMu.Lock()
+ defer s.client.clientMu.Unlock()
+
+ // Disable the redirect mechanism because AWS fails if the GitHub auth token is provided.
+ var loc string
+ saveRedirect := s.client.client.CheckRedirect
+ s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
+ loc = req.URL.String()
+ return errors.New("disable redirect")
+ }
+ defer func() { s.client.client.CheckRedirect = saveRedirect }()
+
+ _, err = s.client.Do(ctx, req, nil) // expect error from disable redirect
+ if err == nil {
+ return "", errors.New("expected redirect, none provided")
+ }
+ if !strings.Contains(err.Error(), "disable redirect") {
+ return "", err
+ }
+ return loc, nil
+}
+
+// DeleteMigration deletes a previous migration archive.
+// id is the migration ID.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/migrations/#delete-a-migration-archive
+func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) {
+ u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeMigrationsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// UnlockRepo unlocks a repository that was locked for migration.
+// id is the migration ID.
+// You should unlock each migrated repository and delete them when the migration
+// is complete and you no longer need the source data.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/migrations/#unlock-a-repository
+func (s *MigrationService) UnlockRepo(ctx context.Context, org string, id int64, repo string) (*Response, error) {
+ u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeMigrationsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/migrations_source_import.go b/vendor/github.com/google/go-github/github/migrations_source_import.go
new file mode 100644
index 0000000..fd45e78
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/migrations_source_import.go
@@ -0,0 +1,329 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+)
+
+// Import represents a repository import request.
+type Import struct {
+ // The URL of the originating repository.
+ VCSURL *string `json:"vcs_url,omitempty"`
+ // The originating VCS type. Can be one of 'subversion', 'git',
+ // 'mercurial', or 'tfvc'. Without this parameter, the import job will
+ // take additional time to detect the VCS type before beginning the
+ // import. This detection step will be reflected in the response.
+ VCS *string `json:"vcs,omitempty"`
+ // VCSUsername and VCSPassword are only used for StartImport calls that
+ // are importing a password-protected repository.
+ VCSUsername *string `json:"vcs_username,omitempty"`
+ VCSPassword *string `json:"vcs_password,omitempty"`
+ // For a tfvc import, the name of the project that is being imported.
+ TFVCProject *string `json:"tfvc_project,omitempty"`
+
+ // LFS related fields that may be preset in the Import Progress response
+
+ // Describes whether the import has been opted in or out of using Git
+ // LFS. The value can be 'opt_in', 'opt_out', or 'undecided' if no
+ // action has been taken.
+ UseLFS *string `json:"use_lfs,omitempty"`
+ // Describes whether files larger than 100MB were found during the
+ // importing step.
+ HasLargeFiles *bool `json:"has_large_files,omitempty"`
+ // The total size in gigabytes of files larger than 100MB found in the
+ // originating repository.
+ LargeFilesSize *int `json:"large_files_size,omitempty"`
+ // The total number of files larger than 100MB found in the originating
+ // repository. To see a list of these files, call LargeFiles.
+ LargeFilesCount *int `json:"large_files_count,omitempty"`
+
+ // Identifies the current status of an import. An import that does not
+ // have errors will progress through these steps:
+ //
+ // detecting - the "detection" step of the import is in progress
+ // because the request did not include a VCS parameter. The
+ // import is identifying the type of source control present at
+ // the URL.
+ // importing - the "raw" step of the import is in progress. This is
+ // where commit data is fetched from the original repository.
+ // The import progress response will include CommitCount (the
+ // total number of raw commits that will be imported) and
+ // Percent (0 - 100, the current progress through the import).
+ // mapping - the "rewrite" step of the import is in progress. This
+ // is where SVN branches are converted to Git branches, and
+ // where author updates are applied. The import progress
+ // response does not include progress information.
+ // pushing - the "push" step of the import is in progress. This is
+ // where the importer updates the repository on GitHub. The
+ // import progress response will include PushPercent, which is
+ // the percent value reported by git push when it is "Writing
+ // objects".
+ // complete - the import is complete, and the repository is ready
+ // on GitHub.
+ //
+ // If there are problems, you will see one of these in the status field:
+ //
+ // auth_failed - the import requires authentication in order to
+ // connect to the original repository. Make an UpdateImport
+ // request, and include VCSUsername and VCSPassword.
+ // error - the import encountered an error. The import progress
+ // response will include the FailedStep and an error message.
+ // Contact GitHub support for more information.
+ // detection_needs_auth - the importer requires authentication for
+ // the originating repository to continue detection. Make an
+ // UpdatImport request, and include VCSUsername and
+ // VCSPassword.
+ // detection_found_nothing - the importer didn't recognize any
+ // source control at the URL.
+ // detection_found_multiple - the importer found several projects
+ // or repositories at the provided URL. When this is the case,
+ // the Import Progress response will also include a
+ // ProjectChoices field with the possible project choices as
+ // values. Make an UpdateImport request, and include VCS and
+ // (if applicable) TFVCProject.
+ Status *string `json:"status,omitempty"`
+ CommitCount *int `json:"commit_count,omitempty"`
+ StatusText *string `json:"status_text,omitempty"`
+ AuthorsCount *int `json:"authors_count,omitempty"`
+ Percent *int `json:"percent,omitempty"`
+ PushPercent *int `json:"push_percent,omitempty"`
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ AuthorsURL *string `json:"authors_url,omitempty"`
+ RepositoryURL *string `json:"repository_url,omitempty"`
+ Message *string `json:"message,omitempty"`
+ FailedStep *string `json:"failed_step,omitempty"`
+
+ // Human readable display name, provided when the Import appears as
+ // part of ProjectChoices.
+ HumanName *string `json:"human_name,omitempty"`
+
+ // When the importer finds several projects or repositories at the
+ // provided URLs, this will identify the available choices. Call
+ // UpdateImport with the selected Import value.
+ ProjectChoices []Import `json:"project_choices,omitempty"`
+}
+
+func (i Import) String() string {
+ return Stringify(i)
+}
+
+// SourceImportAuthor identifies an author imported from a source repository.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-commit-authors
+type SourceImportAuthor struct {
+ ID *int64 `json:"id,omitempty"`
+ RemoteID *string `json:"remote_id,omitempty"`
+ RemoteName *string `json:"remote_name,omitempty"`
+ Email *string `json:"email,omitempty"`
+ Name *string `json:"name,omitempty"`
+ URL *string `json:"url,omitempty"`
+ ImportURL *string `json:"import_url,omitempty"`
+}
+
+func (a SourceImportAuthor) String() string {
+ return Stringify(a)
+}
+
+// LargeFile identifies a file larger than 100MB found during a repository import.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-large-files
+type LargeFile struct {
+ RefName *string `json:"ref_name,omitempty"`
+ Path *string `json:"path,omitempty"`
+ OID *string `json:"oid,omitempty"`
+ Size *int `json:"size,omitempty"`
+}
+
+func (f LargeFile) String() string {
+ return Stringify(f)
+}
+
+// StartImport initiates a repository import.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#start-an-import
+func (s *MigrationService) StartImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
+ req, err := s.client.NewRequest("PUT", u, in)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeImportPreview)
+
+ out := new(Import)
+ resp, err := s.client.Do(ctx, req, out)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return out, resp, nil
+}
+
+// ImportProgress queries for the status and progress of an ongoing repository import.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-import-progress
+func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo string) (*Import, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
+ 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", mediaTypeImportPreview)
+
+ out := new(Import)
+ resp, err := s.client.Do(ctx, req, out)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return out, resp, nil
+}
+
+// UpdateImport initiates a repository import.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#update-existing-import
+func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
+ req, err := s.client.NewRequest("PATCH", u, in)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeImportPreview)
+
+ out := new(Import)
+ resp, err := s.client.Do(ctx, req, out)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return out, resp, nil
+}
+
+// CommitAuthors gets the authors mapped from the original repository.
+//
+// Each type of source control system represents authors in a different way.
+// For example, a Git commit author has a display name and an email address,
+// but a Subversion commit author just has a username. The GitHub Importer will
+// make the author information valid, but the author might not be correct. For
+// example, it will change the bare Subversion username "hubot" into something
+// like "hubot ".
+//
+// This method and MapCommitAuthor allow you to provide correct Git author
+// information.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-commit-authors
+func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string) ([]*SourceImportAuthor, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/import/authors", owner, repo)
+ 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", mediaTypeImportPreview)
+
+ var authors []*SourceImportAuthor
+ resp, err := s.client.Do(ctx, req, &authors)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return authors, resp, nil
+}
+
+// MapCommitAuthor updates an author's identity for the import. Your
+// application can continue updating authors any time before you push new
+// commits to the repository.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#map-a-commit-author
+func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo string, id int64, author *SourceImportAuthor) (*SourceImportAuthor, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/import/authors/%v", owner, repo, id)
+ req, err := s.client.NewRequest("PATCH", u, author)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeImportPreview)
+
+ out := new(SourceImportAuthor)
+ resp, err := s.client.Do(ctx, req, out)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return out, resp, nil
+}
+
+// SetLFSPreference sets whether imported repositories should use Git LFS for
+// files larger than 100MB. Only the UseLFS field on the provided Import is
+// used.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#set-git-lfs-preference
+func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/import/lfs", owner, repo)
+ req, err := s.client.NewRequest("PATCH", u, in)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeImportPreview)
+
+ out := new(Import)
+ resp, err := s.client.Do(ctx, req, out)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return out, resp, nil
+}
+
+// LargeFiles lists files larger than 100MB found during the import.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-large-files
+func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ([]*LargeFile, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/import/large_files", owner, repo)
+ 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", mediaTypeImportPreview)
+
+ var files []*LargeFile
+ resp, err := s.client.Do(ctx, req, &files)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return files, resp, nil
+}
+
+// CancelImport stops an import for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#cancel-an-import
+func (s *MigrationService) CancelImport(ctx context.Context, owner, repo string) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeImportPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/migrations_source_import_test.go b/vendor/github.com/google/go-github/github/migrations_source_import_test.go
new file mode 100644
index 0000000..e9e9be0
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/migrations_source_import_test.go
@@ -0,0 +1,226 @@
+// Copyright 2016 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestMigrationService_StartImport(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Import{
+ VCS: String("git"),
+ VCSURL: String("url"),
+ VCSUsername: String("u"),
+ VCSPassword: String("p"),
+ }
+
+ mux.HandleFunc("/repos/o/r/import", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Import)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PUT")
+ testHeader(t, r, "Accept", mediaTypeImportPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ w.WriteHeader(http.StatusCreated)
+ fmt.Fprint(w, `{"status":"importing"}`)
+ })
+
+ got, _, err := client.Migrations.StartImport(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("StartImport returned error: %v", err)
+ }
+ want := &Import{Status: String("importing")}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("StartImport = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_ImportProgress(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/import", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeImportPreview)
+ fmt.Fprint(w, `{"status":"complete"}`)
+ })
+
+ got, _, err := client.Migrations.ImportProgress(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("ImportProgress returned error: %v", err)
+ }
+ want := &Import{Status: String("complete")}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("ImportProgress = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_UpdateImport(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Import{
+ VCS: String("git"),
+ VCSURL: String("url"),
+ VCSUsername: String("u"),
+ VCSPassword: String("p"),
+ }
+
+ mux.HandleFunc("/repos/o/r/import", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Import)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeImportPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ w.WriteHeader(http.StatusCreated)
+ fmt.Fprint(w, `{"status":"importing"}`)
+ })
+
+ got, _, err := client.Migrations.UpdateImport(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("UpdateImport returned error: %v", err)
+ }
+ want := &Import{Status: String("importing")}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("UpdateImport = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_CommitAuthors(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/import/authors", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeImportPreview)
+ fmt.Fprint(w, `[{"id":1,"name":"a"},{"id":2,"name":"b"}]`)
+ })
+
+ got, _, err := client.Migrations.CommitAuthors(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("CommitAuthors returned error: %v", err)
+ }
+ want := []*SourceImportAuthor{
+ {ID: Int64(1), Name: String("a")},
+ {ID: Int64(2), Name: String("b")},
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("CommitAuthors = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_MapCommitAuthor(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &SourceImportAuthor{Name: String("n"), Email: String("e")}
+
+ mux.HandleFunc("/repos/o/r/import/authors/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(SourceImportAuthor)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeImportPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id": 1}`)
+ })
+
+ got, _, err := client.Migrations.MapCommitAuthor(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("MapCommitAuthor returned error: %v", err)
+ }
+ want := &SourceImportAuthor{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("MapCommitAuthor = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_SetLFSPreference(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Import{UseLFS: String("opt_in")}
+
+ mux.HandleFunc("/repos/o/r/import/lfs", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Import)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeImportPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ w.WriteHeader(http.StatusCreated)
+ fmt.Fprint(w, `{"status":"importing"}`)
+ })
+
+ got, _, err := client.Migrations.SetLFSPreference(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("SetLFSPreference returned error: %v", err)
+ }
+ want := &Import{Status: String("importing")}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("SetLFSPreference = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_LargeFiles(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/import/large_files", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeImportPreview)
+ fmt.Fprint(w, `[{"oid":"a"},{"oid":"b"}]`)
+ })
+
+ got, _, err := client.Migrations.LargeFiles(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("LargeFiles returned error: %v", err)
+ }
+ want := []*LargeFile{
+ {OID: String("a")},
+ {OID: String("b")},
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("LargeFiles = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_CancelImport(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/import", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeImportPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Migrations.CancelImport(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("CancelImport returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/migrations_test.go b/vendor/github.com/google/go-github/github/migrations_test.go
new file mode 100644
index 0000000..687f89a
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/migrations_test.go
@@ -0,0 +1,178 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestMigrationService_StartMigration(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/migrations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ w.WriteHeader(http.StatusCreated)
+ w.Write(migrationJSON)
+ })
+
+ opt := &MigrationOptions{
+ LockRepositories: true,
+ ExcludeAttachments: false,
+ }
+ got, _, err := client.Migrations.StartMigration(context.Background(), "o", []string{"r"}, opt)
+ if err != nil {
+ t.Errorf("StartMigration returned error: %v", err)
+ }
+ if want := wantMigration; !reflect.DeepEqual(got, want) {
+ t.Errorf("StartMigration = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_ListMigrations(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/migrations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(fmt.Sprintf("[%s]", migrationJSON)))
+ })
+
+ got, _, err := client.Migrations.ListMigrations(context.Background(), "o")
+ if err != nil {
+ t.Errorf("ListMigrations returned error: %v", err)
+ }
+ if want := []*Migration{wantMigration}; !reflect.DeepEqual(got, want) {
+ t.Errorf("ListMigrations = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_MigrationStatus(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/migrations/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write(migrationJSON)
+ })
+
+ got, _, err := client.Migrations.MigrationStatus(context.Background(), "o", 1)
+ if err != nil {
+ t.Errorf("MigrationStatus returned error: %v", err)
+ }
+ if want := wantMigration; !reflect.DeepEqual(got, want) {
+ t.Errorf("MigrationStatus = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_MigrationArchiveURL(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/migrations/1/archive", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ http.Redirect(w, r, "/yo", http.StatusFound)
+ })
+ mux.HandleFunc("/yo", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte("0123456789abcdef"))
+ })
+
+ got, err := client.Migrations.MigrationArchiveURL(context.Background(), "o", 1)
+ if err != nil {
+ t.Errorf("MigrationStatus returned error: %v", err)
+ }
+ if want := "/yo"; !strings.HasSuffix(got, want) {
+ t.Errorf("MigrationArchiveURL = %+v, want %+v", got, want)
+ }
+}
+
+func TestMigrationService_DeleteMigration(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/migrations/1/archive", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ if _, err := client.Migrations.DeleteMigration(context.Background(), "o", 1); err != nil {
+ t.Errorf("DeleteMigration returned error: %v", err)
+ }
+}
+
+func TestMigrationService_UnlockRepo(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/migrations/1/repos/r/lock", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ if _, err := client.Migrations.UnlockRepo(context.Background(), "o", 1, "r"); err != nil {
+ t.Errorf("UnlockRepo returned error: %v", err)
+ }
+}
+
+var migrationJSON = []byte(`{
+ "id": 79,
+ "guid": "0b989ba4-242f-11e5-81e1-c7b6966d2516",
+ "state": "pending",
+ "lock_repositories": true,
+ "exclude_attachments": false,
+ "url": "https://api.github.com/orgs/octo-org/migrations/79",
+ "created_at": "2015-07-06T15:33:38-07:00",
+ "updated_at": "2015-07-06T15:33:38-07:00",
+ "repositories": [
+ {
+ "id": 1296269,
+ "name": "Hello-World",
+ "full_name": "octocat/Hello-World",
+ "description": "This your first repo!"
+ }
+ ]
+}`)
+
+var wantMigration = &Migration{
+ ID: Int64(79),
+ GUID: String("0b989ba4-242f-11e5-81e1-c7b6966d2516"),
+ State: String("pending"),
+ LockRepositories: Bool(true),
+ ExcludeAttachments: Bool(false),
+ URL: String("https://api.github.com/orgs/octo-org/migrations/79"),
+ CreatedAt: String("2015-07-06T15:33:38-07:00"),
+ UpdatedAt: String("2015-07-06T15:33:38-07:00"),
+ Repositories: []*Repository{
+ {
+ ID: Int64(1296269),
+ Name: String("Hello-World"),
+ FullName: String("octocat/Hello-World"),
+ Description: String("This your first repo!"),
+ },
+ },
+}
diff --git a/vendor/github.com/google/go-github/github/migrations_user.go b/vendor/github.com/google/go-github/github/migrations_user.go
new file mode 100644
index 0000000..ae53e68
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/migrations_user.go
@@ -0,0 +1,214 @@
+// Copyright 2018 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 (
+ "context"
+ "errors"
+ "fmt"
+ "net/http"
+)
+
+// UserMigration represents a GitHub migration (archival).
+type UserMigration struct {
+ ID *int64 `json:"id,omitempty"`
+ GUID *string `json:"guid,omitempty"`
+ // State is the current state of a migration.
+ // Possible values are:
+ // "pending" which means the migration hasn't started yet,
+ // "exporting" which means the migration is in progress,
+ // "exported" which means the migration finished successfully, or
+ // "failed" which means the migration failed.
+ State *string `json:"state,omitempty"`
+ // LockRepositories indicates whether repositories are locked (to prevent
+ // manipulation) while migrating data.
+ LockRepositories *bool `json:"lock_repositories,omitempty"`
+ // ExcludeAttachments indicates whether attachments should be excluded from
+ // the migration (to reduce migration archive file size).
+ ExcludeAttachments *bool `json:"exclude_attachments,omitempty"`
+ URL *string `json:"url,omitempty"`
+ CreatedAt *string `json:"created_at,omitempty"`
+ UpdatedAt *string `json:"updated_at,omitempty"`
+ Repositories []*Repository `json:"repositories,omitempty"`
+}
+
+func (m UserMigration) String() string {
+ return Stringify(m)
+}
+
+// UserMigrationOptions specifies the optional parameters to Migration methods.
+type UserMigrationOptions struct {
+ // LockRepositories indicates whether repositories should be locked (to prevent
+ // manipulation) while migrating data.
+ LockRepositories bool
+
+ // ExcludeAttachments indicates whether attachments should be excluded from
+ // the migration (to reduce migration archive file size).
+ ExcludeAttachments bool
+}
+
+// startUserMigration represents the body of a StartMigration request.
+type startUserMigration struct {
+ // Repositories is a slice of repository names to migrate.
+ Repositories []string `json:"repositories,omitempty"`
+
+ // LockRepositories indicates whether repositories should be locked (to prevent
+ // manipulation) while migrating data.
+ LockRepositories *bool `json:"lock_repositories,omitempty"`
+
+ // ExcludeAttachments indicates whether attachments should be excluded from
+ // the migration (to reduce migration archive file size).
+ ExcludeAttachments *bool `json:"exclude_attachments,omitempty"`
+}
+
+// StartUserMigration starts the generation of a migration archive.
+// repos is a slice of repository names to migrate.
+//
+// GitHub API docs: https://developer.github.com/v3/migrations/users/#start-a-user-migration
+func (s *MigrationService) StartUserMigration(ctx context.Context, repos []string, opt *UserMigrationOptions) (*UserMigration, *Response, error) {
+ u := "user/migrations"
+
+ body := &startUserMigration{Repositories: repos}
+ if opt != nil {
+ body.LockRepositories = Bool(opt.LockRepositories)
+ body.ExcludeAttachments = Bool(opt.ExcludeAttachments)
+ }
+
+ req, err := s.client.NewRequest("POST", u, body)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeMigrationsPreview)
+
+ m := &UserMigration{}
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// ListUserMigrations lists the most recent migrations.
+//
+// GitHub API docs: https://developer.github.com/v3/migrations/users/#get-a-list-of-user-migrations
+func (s *MigrationService) ListUserMigrations(ctx context.Context) ([]*UserMigration, *Response, error) {
+ u := "user/migrations"
+
+ 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", mediaTypeMigrationsPreview)
+
+ var m []*UserMigration
+ resp, err := s.client.Do(ctx, req, &m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// UserMigrationStatus gets the status of a specific migration archive.
+// id is the migration ID.
+//
+// GitHub API docs: https://developer.github.com/v3/migrations/users/#get-the-status-of-a-user-migration
+func (s *MigrationService) UserMigrationStatus(ctx context.Context, id int64) (*UserMigration, *Response, error) {
+ u := fmt.Sprintf("user/migrations/%v", id)
+
+ 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", mediaTypeMigrationsPreview)
+
+ m := &UserMigration{}
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// UserMigrationArchiveURL gets the URL for a specific migration archive.
+// id is the migration ID.
+//
+// GitHub API docs: https://developer.github.com/v3/migrations/users/#download-a-user-migration-archive
+func (s *MigrationService) UserMigrationArchiveURL(ctx context.Context, id int64) (string, error) {
+ url := fmt.Sprintf("user/migrations/%v/archive", id)
+
+ req, err := s.client.NewRequest("GET", url, nil)
+ if err != nil {
+ return "", err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeMigrationsPreview)
+
+ m := &UserMigration{}
+
+ var loc string
+ originalRedirect := s.client.client.CheckRedirect
+ s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
+ loc = req.URL.String()
+ return http.ErrUseLastResponse
+ }
+ defer func() {
+ s.client.client.CheckRedirect = originalRedirect
+ }()
+ resp, err := s.client.Do(ctx, req, m)
+ if err == nil {
+ return "", errors.New("expected redirect, none provided")
+ }
+ loc = resp.Header.Get("Location")
+ return loc, nil
+}
+
+// DeleteUserMigration will delete a previous migration archive.
+// id is the migration ID.
+//
+// GitHub API docs: https://developer.github.com/v3/migrations/users/#delete-a-user-migration-archive
+func (s *MigrationService) DeleteUserMigration(ctx context.Context, id int64) (*Response, error) {
+ url := fmt.Sprintf("user/migrations/%v/archive", id)
+
+ req, err := s.client.NewRequest("DELETE", url, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeMigrationsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// UnlockUserRepository will unlock a repo that was locked for migration.
+// id is migration ID.
+// You should unlock each migrated repository and delete them when the migration
+// is complete and you no longer need the source data.
+//
+// GitHub API docs: https://developer.github.com/v3/migrations/users/#unlock-a-user-repository
+func (s *MigrationService) UnlockUserRepo(ctx context.Context, id int64, repo string) (*Response, error) {
+ url := fmt.Sprintf("user/migrations/%v/repos/%v/lock", id, repo)
+
+ req, err := s.client.NewRequest("DELETE", url, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeMigrationsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/migrations_user_test.go b/vendor/github.com/google/go-github/github/migrations_user_test.go
new file mode 100644
index 0000000..c271e02
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/migrations_user_test.go
@@ -0,0 +1,197 @@
+// Copyright 2018 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestMigrationService_StartUserMigration(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/migrations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ w.WriteHeader(http.StatusCreated)
+ w.Write(userMigrationJSON)
+ })
+
+ opt := &UserMigrationOptions{
+ LockRepositories: true,
+ ExcludeAttachments: false,
+ }
+
+ got, _, err := client.Migrations.StartUserMigration(context.Background(), []string{"r"}, opt)
+ if err != nil {
+ t.Errorf("StartUserMigration returned error: %v", err)
+ }
+
+ want := wantUserMigration
+ if !reflect.DeepEqual(want, got) {
+ t.Errorf("StartUserMigration = %v, want = %v", got, want)
+ }
+}
+
+func TestMigrationService_ListUserMigrations(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/migrations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(fmt.Sprintf("[%s]", userMigrationJSON)))
+ })
+
+ got, _, err := client.Migrations.ListUserMigrations(context.Background())
+ if err != nil {
+ t.Errorf("ListUserMigrations returned error %v", err)
+ }
+
+ want := []*UserMigration{wantUserMigration}
+ if !reflect.DeepEqual(want, got) {
+ t.Errorf("ListUserMigrations = %v, want = %v", got, want)
+ }
+}
+
+func TestMigrationService_UserMigrationStatus(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/migrations/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write(userMigrationJSON)
+ })
+
+ got, _, err := client.Migrations.UserMigrationStatus(context.Background(), 1)
+ if err != nil {
+ t.Errorf("UserMigrationStatus returned error %v", err)
+ }
+
+ want := wantUserMigration
+ if !reflect.DeepEqual(want, got) {
+ t.Errorf("UserMigrationStatus = %v, want = %v", got, want)
+ }
+}
+
+func TestMigrationService_UserMigrationArchiveURL(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/migrations/1/archive", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ http.Redirect(w, r, "/go-github", http.StatusFound)
+ })
+
+ mux.HandleFunc("/go-github", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ w.WriteHeader(http.StatusOK)
+ })
+
+ got, err := client.Migrations.UserMigrationArchiveURL(context.Background(), 1)
+ if err != nil {
+ t.Errorf("UserMigrationArchiveURL returned error %v", err)
+ }
+
+ want := "/go-github"
+ if !strings.HasSuffix(got, want) {
+ t.Errorf("UserMigrationArchiveURL = %v, want = %v", got, want)
+ }
+}
+
+func TestMigrationService_DeleteUserMigration(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/migrations/1/archive", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ got, err := client.Migrations.DeleteUserMigration(context.Background(), 1)
+ if err != nil {
+ t.Errorf("DeleteUserMigration returned error %v", err)
+ }
+
+ if got.StatusCode != http.StatusNoContent {
+ t.Errorf("DeleteUserMigration returned status = %v, want = %v", got.StatusCode, http.StatusNoContent)
+ }
+}
+
+func TestMigrationService_UnlockUserRepo(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/migrations/1/repos/r/lock", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
+
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ got, err := client.Migrations.UnlockUserRepo(context.Background(), 1, "r")
+ if err != nil {
+ t.Errorf("UnlockUserRepo returned error %v", err)
+ }
+
+ if got.StatusCode != http.StatusNoContent {
+ t.Errorf("UnlockUserRepo returned status = %v, want = %v", got.StatusCode, http.StatusNoContent)
+ }
+}
+
+var userMigrationJSON = []byte(`{
+ "id": 79,
+ "guid": "0b989ba4-242f-11e5-81e1-c7b6966d2516",
+ "state": "pending",
+ "lock_repositories": true,
+ "exclude_attachments": false,
+ "url": "https://api.github.com/orgs/octo-org/migrations/79",
+ "created_at": "2015-07-06T15:33:38-07:00",
+ "updated_at": "2015-07-06T15:33:38-07:00",
+ "repositories": [
+ {
+ "id": 1296269,
+ "name": "Hello-World",
+ "full_name": "octocat/Hello-World",
+ "description": "This your first repo!"
+ }
+ ]
+}`)
+
+var wantUserMigration = &UserMigration{
+ ID: Int64(79),
+ GUID: String("0b989ba4-242f-11e5-81e1-c7b6966d2516"),
+ State: String("pending"),
+ LockRepositories: Bool(true),
+ ExcludeAttachments: Bool(false),
+ URL: String("https://api.github.com/orgs/octo-org/migrations/79"),
+ CreatedAt: String("2015-07-06T15:33:38-07:00"),
+ UpdatedAt: String("2015-07-06T15:33:38-07:00"),
+ Repositories: []*Repository{
+ {
+ ID: Int64(1296269),
+ Name: String("Hello-World"),
+ FullName: String("octocat/Hello-World"),
+ Description: String("This your first repo!"),
+ },
+ },
+}
diff --git a/vendor/github.com/google/go-github/github/misc.go b/vendor/github.com/google/go-github/github/misc.go
new file mode 100644
index 0000000..e9b0ea2
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/misc.go
@@ -0,0 +1,257 @@
+// Copyright 2014 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 (
+ "bytes"
+ "context"
+ "fmt"
+ "net/url"
+)
+
+// MarkdownOptions specifies optional parameters to the Markdown method.
+type MarkdownOptions struct {
+ // Mode identifies the rendering mode. Possible values are:
+ // markdown - render a document as plain Markdown, just like
+ // README files are rendered.
+ //
+ // gfm - to render a document as user-content, e.g. like user
+ // comments or issues are rendered. In GFM mode, hard line breaks are
+ // always taken into account, and issue and user mentions are linked
+ // accordingly.
+ //
+ // Default is "markdown".
+ Mode string
+
+ // Context identifies the repository context. Only taken into account
+ // when rendering as "gfm".
+ Context string
+}
+
+type markdownRequest struct {
+ Text *string `json:"text,omitempty"`
+ Mode *string `json:"mode,omitempty"`
+ Context *string `json:"context,omitempty"`
+}
+
+// Markdown renders an arbitrary Markdown document.
+//
+// GitHub API docs: https://developer.github.com/v3/markdown/
+func (c *Client) Markdown(ctx context.Context, text string, opt *MarkdownOptions) (string, *Response, error) {
+ request := &markdownRequest{Text: String(text)}
+ if opt != nil {
+ if opt.Mode != "" {
+ request.Mode = String(opt.Mode)
+ }
+ if opt.Context != "" {
+ request.Context = String(opt.Context)
+ }
+ }
+
+ req, err := c.NewRequest("POST", "markdown", request)
+ if err != nil {
+ return "", nil, err
+ }
+
+ buf := new(bytes.Buffer)
+ resp, err := c.Do(ctx, req, buf)
+ if err != nil {
+ return "", resp, err
+ }
+
+ return buf.String(), resp, nil
+}
+
+// ListEmojis returns the emojis available to use on GitHub.
+//
+// GitHub API docs: https://developer.github.com/v3/emojis/
+func (c *Client) ListEmojis(ctx context.Context) (map[string]string, *Response, error) {
+ req, err := c.NewRequest("GET", "emojis", nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var emoji map[string]string
+ resp, err := c.Do(ctx, req, &emoji)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return emoji, resp, nil
+}
+
+// CodeOfConduct represents a code of conduct.
+type CodeOfConduct struct {
+ Name *string `json:"name,omitempty"`
+ Key *string `json:"key,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Body *string `json:"body,omitempty"`
+}
+
+func (c *CodeOfConduct) String() string {
+ return Stringify(c)
+}
+
+// ListCodesOfConduct returns all codes of conduct.
+//
+// GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#list-all-codes-of-conduct
+func (c *Client) ListCodesOfConduct(ctx context.Context) ([]*CodeOfConduct, *Response, error) {
+ req, err := c.NewRequest("GET", "codes_of_conduct", nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeCodesOfConductPreview)
+
+ var cs []*CodeOfConduct
+ resp, err := c.Do(ctx, req, &cs)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return cs, resp, nil
+}
+
+// GetCodeOfConduct returns an individual code of conduct.
+//
+// https://developer.github.com/v3/codes_of_conduct/#get-an-individual-code-of-conduct
+func (c *Client) GetCodeOfConduct(ctx context.Context, key string) (*CodeOfConduct, *Response, error) {
+ u := fmt.Sprintf("codes_of_conduct/%s", key)
+ req, err := c.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", mediaTypeCodesOfConductPreview)
+
+ coc := new(CodeOfConduct)
+ resp, err := c.Do(ctx, req, coc)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return coc, resp, nil
+}
+
+// APIMeta represents metadata about the GitHub API.
+type APIMeta struct {
+ // An Array of IP addresses in CIDR format specifying the addresses
+ // that incoming service hooks will originate from on GitHub.com.
+ Hooks []string `json:"hooks,omitempty"`
+
+ // An Array of IP addresses in CIDR format specifying the Git servers
+ // for GitHub.com.
+ Git []string `json:"git,omitempty"`
+
+ // Whether authentication with username and password is supported.
+ // (GitHub Enterprise instances using CAS or OAuth for authentication
+ // will return false. Features like Basic Authentication with a
+ // 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"`
+
+ // An Array of IP addresses specifying the addresses that source imports
+ // will originate from on GitHub.com.
+ Importer []string `json:"importer,omitempty"`
+}
+
+// APIMeta returns information about GitHub.com, the service. Or, if you access
+// this endpoint on your organization’s GitHub Enterprise installation, this
+// endpoint provides information about that installation.
+//
+// GitHub API docs: https://developer.github.com/v3/meta/
+func (c *Client) APIMeta(ctx context.Context) (*APIMeta, *Response, error) {
+ req, err := c.NewRequest("GET", "meta", nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ meta := new(APIMeta)
+ resp, err := c.Do(ctx, req, meta)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return meta, resp, nil
+}
+
+// Octocat returns an ASCII art octocat with the specified message in a speech
+// bubble. If message is empty, a random zen phrase is used.
+func (c *Client) Octocat(ctx context.Context, message string) (string, *Response, error) {
+ u := "octocat"
+ if message != "" {
+ u = fmt.Sprintf("%s?s=%s", u, url.QueryEscape(message))
+ }
+
+ req, err := c.NewRequest("GET", u, nil)
+ if err != nil {
+ return "", nil, err
+ }
+
+ buf := new(bytes.Buffer)
+ resp, err := c.Do(ctx, req, buf)
+ if err != nil {
+ return "", resp, err
+ }
+
+ return buf.String(), resp, nil
+}
+
+// Zen returns a random line from The Zen of GitHub.
+//
+// see also: http://warpspire.com/posts/taste/
+func (c *Client) Zen(ctx context.Context) (string, *Response, error) {
+ req, err := c.NewRequest("GET", "zen", nil)
+ if err != nil {
+ return "", nil, err
+ }
+
+ buf := new(bytes.Buffer)
+ resp, err := c.Do(ctx, req, buf)
+ if err != nil {
+ return "", resp, err
+ }
+
+ 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(ctx context.Context) ([]*ServiceHook, *Response, error) {
+ u := "hooks"
+ req, err := c.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var hooks []*ServiceHook
+ resp, err := c.Do(ctx, req, &hooks)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return hooks, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/misc_test.go b/vendor/github.com/google/go-github/github/misc_test.go
new file mode 100644
index 0000000..b7144f9
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/misc_test.go
@@ -0,0 +1,234 @@
+// Copyright 2014 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestMarkdown(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &markdownRequest{
+ Text: String("# text #"),
+ Mode: String("gfm"),
+ Context: String("google/go-github"),
+ }
+ mux.HandleFunc("/markdown", func(w http.ResponseWriter, r *http.Request) {
+ v := new(markdownRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+ fmt.Fprint(w, `text
`)
+ })
+
+ md, _, err := client.Markdown(context.Background(), "# text #", &MarkdownOptions{
+ Mode: "gfm",
+ Context: "google/go-github",
+ })
+ if err != nil {
+ t.Errorf("Markdown returned error: %v", err)
+ }
+
+ if want := "text
"; want != md {
+ t.Errorf("Markdown returned %+v, want %+v", md, want)
+ }
+}
+
+func TestListEmojis(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/emojis", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"+1": "+1.png"}`)
+ })
+
+ emoji, _, err := client.ListEmojis(context.Background())
+ if err != nil {
+ t.Errorf("ListEmojis returned error: %v", err)
+ }
+
+ want := map[string]string{"+1": "+1.png"}
+ if !reflect.DeepEqual(want, emoji) {
+ t.Errorf("ListEmojis returned %+v, want %+v", emoji, want)
+ }
+}
+
+func TestListCodesOfConduct(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/codes_of_conduct", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeCodesOfConductPreview)
+ fmt.Fprint(w, `[{
+ "key": "key",
+ "name": "name",
+ "url": "url"}
+ ]`)
+ })
+
+ cs, _, err := client.ListCodesOfConduct(context.Background())
+ if err != nil {
+ t.Errorf("ListCodesOfConduct returned error: %v", err)
+ }
+
+ want := []*CodeOfConduct{
+ {
+ Key: String("key"),
+ Name: String("name"),
+ URL: String("url"),
+ }}
+ if !reflect.DeepEqual(want, cs) {
+ t.Errorf("ListCodesOfConduct returned %+v, want %+v", cs, want)
+ }
+}
+
+func TestGetCodeOfConduct(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/codes_of_conduct/k", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeCodesOfConductPreview)
+ fmt.Fprint(w, `{
+ "key": "key",
+ "name": "name",
+ "url": "url",
+ "body": "body"}`,
+ )
+ })
+
+ coc, _, err := client.GetCodeOfConduct(context.Background(), "k")
+ if err != nil {
+ t.Errorf("ListCodesOfConduct returned error: %v", err)
+ }
+
+ want := &CodeOfConduct{
+ Key: String("key"),
+ Name: String("name"),
+ URL: String("url"),
+ Body: String("body"),
+ }
+ if !reflect.DeepEqual(want, coc) {
+ t.Errorf("GetCodeOfConductByKey returned %+v, want %+v", coc, want)
+ }
+}
+
+func TestAPIMeta(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/meta", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"hooks":["h"], "git":["g"], "pages":["p"], "importer":["i"], "verifiable_password_authentication": true}`)
+ })
+
+ meta, _, err := client.APIMeta(context.Background())
+ if err != nil {
+ t.Errorf("APIMeta returned error: %v", err)
+ }
+
+ want := &APIMeta{
+ Hooks: []string{"h"},
+ Git: []string{"g"},
+ Pages: []string{"p"},
+ Importer: []string{"i"},
+
+ VerifiablePasswordAuthentication: Bool(true),
+ }
+ if !reflect.DeepEqual(want, meta) {
+ t.Errorf("APIMeta returned %+v, want %+v", meta, want)
+ }
+}
+
+func TestOctocat(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := "input"
+ output := "sample text"
+
+ mux.HandleFunc("/octocat", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"s": input})
+ w.Header().Set("Content-Type", "application/octocat-stream")
+ fmt.Fprint(w, output)
+ })
+
+ got, _, err := client.Octocat(context.Background(), input)
+ if err != nil {
+ t.Errorf("Octocat returned error: %v", err)
+ }
+
+ if want := output; got != want {
+ t.Errorf("Octocat returned %+v, want %+v", got, want)
+ }
+}
+
+func TestZen(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ output := "sample text"
+
+ mux.HandleFunc("/zen", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.Header().Set("Content-Type", "text/plain;charset=utf-8")
+ fmt.Fprint(w, output)
+ })
+
+ got, _, err := client.Zen(context.Background())
+ if err != nil {
+ t.Errorf("Zen returned error: %v", err)
+ }
+
+ if want := output; got != want {
+ t.Errorf("Zen returned %+v, want %+v", got, want)
+ }
+}
+
+func TestListServiceHooks(t *testing.T) {
+ client, mux, _, teardown := 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.ListServiceHooks(context.Background())
+ if err != nil {
+ t.Errorf("ListServiceHooks 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("ListServiceHooks returned %+v, want %+v", hooks, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/orgs.go b/vendor/github.com/google/go-github/github/orgs.go
new file mode 100644
index 0000000..3be91a3
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs.go
@@ -0,0 +1,198 @@
+// 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// OrganizationsService provides access to the organization related functions
+// in the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/
+type OrganizationsService service
+
+// Organization represents a GitHub organization account.
+type Organization struct {
+ Login *string `json:"login,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ AvatarURL *string `json:"avatar_url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Company *string `json:"company,omitempty"`
+ Blog *string `json:"blog,omitempty"`
+ Location *string `json:"location,omitempty"`
+ Email *string `json:"email,omitempty"`
+ Description *string `json:"description,omitempty"`
+ PublicRepos *int `json:"public_repos,omitempty"`
+ PublicGists *int `json:"public_gists,omitempty"`
+ Followers *int `json:"followers,omitempty"`
+ Following *int `json:"following,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+ TotalPrivateRepos *int `json:"total_private_repos,omitempty"`
+ OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"`
+ PrivateGists *int `json:"private_gists,omitempty"`
+ DiskUsage *int `json:"disk_usage,omitempty"`
+ Collaborators *int `json:"collaborators,omitempty"`
+ BillingEmail *string `json:"billing_email,omitempty"`
+ Type *string `json:"type,omitempty"`
+ Plan *Plan `json:"plan,omitempty"`
+ TwoFactorRequirementEnabled *bool `json:"two_factor_requirement_enabled,omitempty"`
+
+ // API URLs
+ URL *string `json:"url,omitempty"`
+ EventsURL *string `json:"events_url,omitempty"`
+ HooksURL *string `json:"hooks_url,omitempty"`
+ IssuesURL *string `json:"issues_url,omitempty"`
+ MembersURL *string `json:"members_url,omitempty"`
+ PublicMembersURL *string `json:"public_members_url,omitempty"`
+ ReposURL *string `json:"repos_url,omitempty"`
+}
+
+func (o Organization) String() string {
+ return Stringify(o)
+}
+
+// Plan represents the payment plan for an account. See plans at https://github.com/plans.
+type Plan struct {
+ Name *string `json:"name,omitempty"`
+ Space *int `json:"space,omitempty"`
+ Collaborators *int `json:"collaborators,omitempty"`
+ PrivateRepos *int `json:"private_repos,omitempty"`
+}
+
+func (p Plan) String() string {
+ return Stringify(p)
+}
+
+// OrganizationsListOptions specifies the optional parameters to the
+// OrganizationsService.ListAll method.
+type OrganizationsListOptions struct {
+ // Since filters Organizations by ID.
+ Since int64 `url:"since,omitempty"`
+
+ // Note: Pagination is powered exclusively by the Since parameter,
+ // ListOptions.Page has no effect.
+ // ListOptions.PerPage controls an undocumented GitHub API parameter.
+ ListOptions
+}
+
+// ListAll lists all organizations, in the order that they were created on GitHub.
+//
+// Note: Pagination is powered exclusively by the since parameter. To continue
+// listing the next set of organizations, use the ID of the last-returned organization
+// as the opts.Since parameter for the next call.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/#list-all-organizations
+func (s *OrganizationsService) ListAll(ctx context.Context, opt *OrganizationsListOptions) ([]*Organization, *Response, error) {
+ u, err := addOptions("organizations", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ orgs := []*Organization{}
+ resp, err := s.client.Do(ctx, req, &orgs)
+ if err != nil {
+ return nil, resp, err
+ }
+ return orgs, resp, nil
+}
+
+// List the organizations for a user. Passing the empty string will list
+// organizations for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/#list-user-organizations
+func (s *OrganizationsService) List(ctx context.Context, user string, opt *ListOptions) ([]*Organization, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v/orgs", user)
+ } else {
+ u = "user/orgs"
+ }
+ 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
+ }
+
+ var orgs []*Organization
+ resp, err := s.client.Do(ctx, req, &orgs)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return orgs, resp, nil
+}
+
+// Get fetches an organization by name.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/#get-an-organization
+func (s *OrganizationsService) Get(ctx context.Context, org string) (*Organization, *Response, error) {
+ u := fmt.Sprintf("orgs/%v", org)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ organization := new(Organization)
+ resp, err := s.client.Do(ctx, req, organization)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return organization, resp, nil
+}
+
+// GetByID fetches an organization.
+//
+// Note: GetByID uses the undocumented GitHub API endpoint /organizations/:id.
+func (s *OrganizationsService) GetByID(ctx context.Context, id int64) (*Organization, *Response, error) {
+ u := fmt.Sprintf("organizations/%d", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ organization := new(Organization)
+ resp, err := s.client.Do(ctx, req, organization)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return organization, resp, nil
+}
+
+// Edit an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/#edit-an-organization
+func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organization) (*Organization, *Response, error) {
+ u := fmt.Sprintf("orgs/%v", name)
+ req, err := s.client.NewRequest("PATCH", u, org)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ o := new(Organization)
+ resp, err := s.client.Do(ctx, req, o)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return o, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_hooks.go b/vendor/github.com/google/go-github/github/orgs_hooks.go
new file mode 100644
index 0000000..ab1d02d
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_hooks.go
@@ -0,0 +1,107 @@
+// 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 (
+ "context"
+ "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(ctx context.Context, 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
+ }
+
+ var hooks []*Hook
+ resp, err := s.client.Do(ctx, req, &hooks)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return hooks, resp, nil
+}
+
+// GetHook returns a single specified Hook.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#get-single-hook
+func (s *OrganizationsService) GetHook(ctx context.Context, org string, id int64) (*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(ctx, 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(ctx context.Context, 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(ctx, req, h)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return h, resp, nil
+}
+
+// EditHook updates a specified Hook.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#edit-a-hook
+func (s *OrganizationsService) EditHook(ctx context.Context, org string, id int64, 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(ctx, 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(ctx context.Context, org string, id int64) (*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(ctx, req, nil)
+}
+
+// DeleteHook deletes a specified Hook.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#delete-a-hook
+func (s *OrganizationsService) DeleteHook(ctx context.Context, org string, id int64) (*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(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_hooks_test.go b/vendor/github.com/google/go-github/github/orgs_hooks_test.go
new file mode 100644
index 0000000..1adfef2
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_hooks_test.go
@@ -0,0 +1,147 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestOrganizationsService_ListHooks(t *testing.T) {
+ client, mux, _, teardown := 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(context.Background(), "o", opt)
+ if err != nil {
+ t.Errorf("Organizations.ListHooks returned error: %v", err)
+ }
+
+ want := []*Hook{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(hooks, want) {
+ t.Errorf("Organizations.ListHooks returned %+v, want %+v", hooks, want)
+ }
+}
+
+func TestOrganizationsService_ListHooks_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Organizations.ListHooks(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestOrganizationsService_GetHook(t *testing.T) {
+ client, mux, _, teardown := 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(context.Background(), "o", 1)
+ if err != nil {
+ t.Errorf("Organizations.GetHook returned error: %v", err)
+ }
+
+ want := &Hook{ID: Int64(1)}
+ if !reflect.DeepEqual(hook, want) {
+ t.Errorf("Organizations.GetHook returned %+v, want %+v", hook, want)
+ }
+}
+
+func TestOrganizationsService_GetHook_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Organizations.GetHook(context.Background(), "%", 1)
+ testURLParseError(t, err)
+}
+
+func TestOrganizationsService_EditHook(t *testing.T) {
+ client, mux, _, teardown := 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(context.Background(), "o", 1, input)
+ if err != nil {
+ t.Errorf("Organizations.EditHook returned error: %v", err)
+ }
+
+ want := &Hook{ID: Int64(1)}
+ if !reflect.DeepEqual(hook, want) {
+ t.Errorf("Organizations.EditHook returned %+v, want %+v", hook, want)
+ }
+}
+
+func TestOrganizationsService_EditHook_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Organizations.EditHook(context.Background(), "%", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestOrganizationsService_PingHook(t *testing.T) {
+ client, mux, _, teardown := 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(context.Background(), "o", 1)
+ if err != nil {
+ t.Errorf("Organizations.PingHook returned error: %v", err)
+ }
+}
+
+func TestOrganizationsService_DeleteHook(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/hooks/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Organizations.DeleteHook(context.Background(), "o", 1)
+ if err != nil {
+ t.Errorf("Organizations.DeleteHook returned error: %v", err)
+ }
+}
+
+func TestOrganizationsService_DeleteHook_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Organizations.DeleteHook(context.Background(), "%", 1)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_members.go b/vendor/github.com/google/go-github/github/orgs_members.go
new file mode 100644
index 0000000..d184359
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_members.go
@@ -0,0 +1,370 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// Membership represents the status of a user's membership in an organization or team.
+type Membership struct {
+ URL *string `json:"url,omitempty"`
+
+ // State is the user's status within the organization or team.
+ // Possible values are: "active", "pending"
+ State *string `json:"state,omitempty"`
+
+ // 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.
+ OrganizationURL *string `json:"organization_url,omitempty"`
+
+ // For organization membership, the organization the membership is for.
+ Organization *Organization `json:"organization,omitempty"`
+
+ // For organization membership, the user the membership is for.
+ User *User `json:"user,omitempty"`
+}
+
+func (m Membership) String() string {
+ return Stringify(m)
+}
+
+// ListMembersOptions specifies optional parameters to the
+// OrganizationsService.ListMembers method.
+type ListMembersOptions struct {
+ // If true (or if the authenticated user is not an owner of the
+ // organization), list only publicly visible members.
+ PublicOnly bool `url:"-"`
+
+ // Filter members returned in the list. Possible values are:
+ // 2fa_disabled, all. Default is "all".
+ Filter string `url:"filter,omitempty"`
+
+ // Role filters members returned by their role in the organization.
+ // Possible values are:
+ // all - all members of the organization, regardless of role
+ // admin - organization owners
+ // member - non-owner organization members
+ //
+ // Default is "all".
+ Role string `url:"role,omitempty"`
+
+ ListOptions
+}
+
+// ListMembers lists the members for an organization. If the authenticated
+// user is an owner of the organization, this will return both concealed and
+// public members, otherwise it will only return public members.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/members/#members-list
+func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opt *ListMembersOptions) ([]*User, *Response, error) {
+ var u string
+ if opt != nil && opt.PublicOnly {
+ u = fmt.Sprintf("orgs/%v/public_members", org)
+ } else {
+ u = fmt.Sprintf("orgs/%v/members", 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
+ }
+
+ var members []*User
+ resp, err := s.client.Do(ctx, req, &members)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return members, resp, nil
+}
+
+// IsMember checks if a user is a member of an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/members/#check-membership
+func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) (bool, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/members/%v", org, user)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+
+ resp, err := s.client.Do(ctx, req, nil)
+ member, err := parseBoolResponse(err)
+ return member, resp, err
+}
+
+// IsPublicMember checks if a user is a public member of an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/members/#check-public-membership
+func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user string) (bool, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/public_members/%v", org, user)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+
+ resp, err := s.client.Do(ctx, req, nil)
+ member, err := parseBoolResponse(err)
+ return member, resp, err
+}
+
+// RemoveMember removes a user from all teams of an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-a-member
+func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user string) (*Response, error) {
+ u := fmt.Sprintf("orgs/%v/members/%v", org, user)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// PublicizeMembership publicizes a user's membership in an organization. (A
+// user cannot publicize the membership for another user.)
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/members/#publicize-a-users-membership
+func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, user string) (*Response, error) {
+ u := fmt.Sprintf("orgs/%v/public_members/%v", org, user)
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ConcealMembership conceals a user's membership in an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/members/#conceal-a-users-membership
+func (s *OrganizationsService) ConcealMembership(ctx context.Context, org, user string) (*Response, error) {
+ u := fmt.Sprintf("orgs/%v/public_members/%v", org, user)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ListOrgMembershipsOptions specifies optional parameters to the
+// OrganizationsService.ListOrgMemberships method.
+type ListOrgMembershipsOptions struct {
+ // Filter memberships to include only those with the specified state.
+ // Possible values are: "active", "pending".
+ State string `url:"state,omitempty"`
+
+ ListOptions
+}
+
+// ListOrgMemberships lists the organization memberships for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-your-organization-memberships
+func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opt *ListOrgMembershipsOptions) ([]*Membership, *Response, error) {
+ u := "user/memberships/orgs"
+ 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
+ }
+
+ var memberships []*Membership
+ resp, err := s.client.Do(ctx, req, &memberships)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return memberships, resp, nil
+}
+
+// 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
+// https://developer.github.com/v3/orgs/members/#get-your-organization-membership
+func (s *OrganizationsService) GetOrgMembership(ctx context.Context, 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
+ }
+
+ membership := new(Membership)
+ resp, err := s.client.Do(ctx, req, membership)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return membership, resp, nil
+}
+
+// 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(ctx context.Context, user, org string, membership *Membership) (*Membership, *Response, error) {
+ var u, method string
+ if user != "" {
+ u = fmt.Sprintf("orgs/%v/memberships/%v", org, user)
+ method = "PUT"
+ } else {
+ u = fmt.Sprintf("user/memberships/orgs/%v", org)
+ method = "PATCH"
+ }
+
+ req, err := s.client.NewRequest(method, u, membership)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ m := new(Membership)
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// 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(ctx context.Context, 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(ctx, req, nil)
+}
+
+// ListPendingOrgInvitations returns a list of pending invitations.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations
+func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, org string, opt *ListOptions) ([]*Invitation, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/invitations", 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
+ }
+
+ var pendingInvitations []*Invitation
+ resp, err := s.client.Do(ctx, req, &pendingInvitations)
+ if err != nil {
+ return nil, resp, err
+ }
+ return pendingInvitations, resp, nil
+}
+
+// CreateOrgInvitationOptions specifies the parameters to the OrganizationService.Invite
+// method.
+type CreateOrgInvitationOptions struct {
+ // GitHub user ID for the person you are inviting. Not required if you provide Email.
+ InviteeID *int64 `json:"invitee_id,omitempty"`
+ // Email address of the person you are inviting, which can be an existing GitHub user.
+ // Not required if you provide InviteeID
+ Email *string `json:"email,omitempty"`
+ // Specify role for new member. Can be one of:
+ // * admin - Organization owners with full administrative rights to the
+ // organization and complete access to all repositories and teams.
+ // * direct_member - Non-owner organization members with ability to see
+ // other members and join teams by invitation.
+ // * billing_manager - Non-owner organization members with ability to
+ // manage the billing settings of your organization.
+ // Default is "direct_member".
+ Role *string `json:"role"`
+ TeamID []int64 `json:"team_ids"`
+}
+
+// CreateOrgInvitation invites people to an organization by using their GitHub user ID or their email address.
+// In order to create invitations in an organization,
+// the authenticated user must be an organization owner.
+//
+// https://developer.github.com/v3/orgs/members/#create-organization-invitation
+func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opt *CreateOrgInvitationOptions) (*Invitation, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/invitations", org)
+
+ req, err := s.client.NewRequest("POST", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview)
+
+ var invitation *Invitation
+ resp, err := s.client.Do(ctx, req, &invitation)
+ if err != nil {
+ return nil, resp, err
+ }
+ return invitation, resp, nil
+}
+
+// ListOrgInvitationTeams lists all teams associated with an invitation. In order to see invitations in an organization,
+// the authenticated user must be an organization owner.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-organization-invitation-teams
+func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, invitationID string, opt *ListOptions) ([]*Team, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/invitations/%v/teams", org, invitationID)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview)
+
+ var orgInvitationTeams []*Team
+ resp, err := s.client.Do(ctx, req, &orgInvitationTeams)
+ if err != nil {
+ return nil, resp, err
+ }
+ return orgInvitationTeams, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_members_test.go b/vendor/github.com/google/go-github/github/orgs_members_test.go
new file mode 100644
index 0000000..e524d03
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_members_test.go
@@ -0,0 +1,535 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestOrganizationsService_ListMembers(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/members", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "filter": "2fa_disabled",
+ "role": "admin",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListMembersOptions{
+ PublicOnly: false,
+ Filter: "2fa_disabled",
+ Role: "admin",
+ ListOptions: ListOptions{Page: 2},
+ }
+ members, _, err := client.Organizations.ListMembers(context.Background(), "o", opt)
+ if err != nil {
+ t.Errorf("Organizations.ListMembers returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}}
+ if !reflect.DeepEqual(members, want) {
+ t.Errorf("Organizations.ListMembers returned %+v, want %+v", members, want)
+ }
+}
+
+func TestOrganizationsService_ListMembers_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Organizations.ListMembers(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestOrganizationsService_ListMembers_public(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/public_members", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListMembersOptions{PublicOnly: true}
+ members, _, err := client.Organizations.ListMembers(context.Background(), "o", opt)
+ if err != nil {
+ t.Errorf("Organizations.ListMembers returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}}
+ if !reflect.DeepEqual(members, want) {
+ t.Errorf("Organizations.ListMembers returned %+v, want %+v", members, want)
+ }
+}
+
+func TestOrganizationsService_IsMember(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ member, _, err := client.Organizations.IsMember(context.Background(), "o", "u")
+ if err != nil {
+ t.Errorf("Organizations.IsMember returned error: %v", err)
+ }
+ if want := true; member != want {
+ t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want)
+ }
+}
+
+// ensure that a 404 response is interpreted as "false" and not an error
+func TestOrganizationsService_IsMember_notMember(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNotFound)
+ })
+
+ member, _, err := client.Organizations.IsMember(context.Background(), "o", "u")
+ if err != nil {
+ t.Errorf("Organizations.IsMember returned error: %+v", err)
+ }
+ if want := false; member != want {
+ t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want)
+ }
+}
+
+// ensure that a 400 response is interpreted as an actual error, and not simply
+// as "false" like the above case of a 404
+func TestOrganizationsService_IsMember_error(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ http.Error(w, "BadRequest", http.StatusBadRequest)
+ })
+
+ member, _, err := client.Organizations.IsMember(context.Background(), "o", "u")
+ if err == nil {
+ t.Errorf("Expected HTTP 400 response")
+ }
+ if want := false; member != want {
+ t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want)
+ }
+}
+
+func TestOrganizationsService_IsMember_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Organizations.IsMember(context.Background(), "%", "u")
+ testURLParseError(t, err)
+}
+
+func TestOrganizationsService_IsPublicMember(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ member, _, err := client.Organizations.IsPublicMember(context.Background(), "o", "u")
+ if err != nil {
+ t.Errorf("Organizations.IsPublicMember returned error: %v", err)
+ }
+ if want := true; member != want {
+ t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want)
+ }
+}
+
+// ensure that a 404 response is interpreted as "false" and not an error
+func TestOrganizationsService_IsPublicMember_notMember(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNotFound)
+ })
+
+ member, _, err := client.Organizations.IsPublicMember(context.Background(), "o", "u")
+ if err != nil {
+ t.Errorf("Organizations.IsPublicMember returned error: %v", err)
+ }
+ if want := false; member != want {
+ t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want)
+ }
+}
+
+// ensure that a 400 response is interpreted as an actual error, and not simply
+// as "false" like the above case of a 404
+func TestOrganizationsService_IsPublicMember_error(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ http.Error(w, "BadRequest", http.StatusBadRequest)
+ })
+
+ member, _, err := client.Organizations.IsPublicMember(context.Background(), "o", "u")
+ if err == nil {
+ t.Errorf("Expected HTTP 400 response")
+ }
+ if want := false; member != want {
+ t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want)
+ }
+}
+
+func TestOrganizationsService_IsPublicMember_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Organizations.IsPublicMember(context.Background(), "%", "u")
+ testURLParseError(t, err)
+}
+
+func TestOrganizationsService_RemoveMember(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Organizations.RemoveMember(context.Background(), "o", "u")
+ if err != nil {
+ t.Errorf("Organizations.RemoveMember returned error: %v", err)
+ }
+}
+
+func TestOrganizationsService_RemoveMember_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Organizations.RemoveMember(context.Background(), "%", "u")
+ testURLParseError(t, err)
+}
+
+func TestOrganizationsService_ListOrgMemberships(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/memberships/orgs", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "state": "active",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"url":"u"}]`)
+ })
+
+ opt := &ListOrgMembershipsOptions{
+ State: "active",
+ ListOptions: ListOptions{Page: 2},
+ }
+ memberships, _, err := client.Organizations.ListOrgMemberships(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Organizations.ListOrgMemberships returned error: %v", err)
+ }
+
+ want := []*Membership{{URL: String("u")}}
+ if !reflect.DeepEqual(memberships, want) {
+ t.Errorf("Organizations.ListOrgMemberships returned %+v, want %+v", memberships, want)
+ }
+}
+
+func TestOrganizationsService_GetOrgMembership_AuthenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/memberships/orgs/o", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"url":"u"}`)
+ })
+
+ membership, _, err := client.Organizations.GetOrgMembership(context.Background(), "", "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_GetOrgMembership_SpecifiedUser(t *testing.T) {
+ client, mux, _, teardown := 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(context.Background(), "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) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Membership{State: String("active")}
+
+ mux.HandleFunc("/user/memberships/orgs/o", 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(context.Background(), "", "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_EditOrgMembership_SpecifiedUser(t *testing.T) {
+ client, mux, _, teardown := 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, "PUT")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"url":"u"}`)
+ })
+
+ membership, _, err := client.Organizations.EditOrgMembership(context.Background(), "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) {
+ client, mux, _, teardown := 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(context.Background(), "u", "o")
+ if err != nil {
+ t.Errorf("Organizations.RemoveOrgMembership returned error: %v", err)
+ }
+}
+
+func TestOrganizationsService_ListPendingOrgInvitations(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/invitations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "1"})
+ fmt.Fprint(w, `[
+ {
+ "id": 1,
+ "login": "monalisa",
+ "email": "octocat@github.com",
+ "role": "direct_member",
+ "created_at": "2017-01-21T00:00:00Z",
+ "inviter": {
+ "login": "other_user",
+ "id": 1,
+ "avatar_url": "https://github.com/images/error/other_user_happy.gif",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/other_user",
+ "html_url": "https://github.com/other_user",
+ "followers_url": "https://api.github.com/users/other_user/followers",
+ "following_url": "https://api.github.com/users/other_user/following/other_user",
+ "gists_url": "https://api.github.com/users/other_user/gists/gist_id",
+ "starred_url": "https://api.github.com/users/other_user/starred/owner/repo",
+ "subscriptions_url": "https://api.github.com/users/other_user/subscriptions",
+ "organizations_url": "https://api.github.com/users/other_user/orgs",
+ "repos_url": "https://api.github.com/users/other_user/repos",
+ "events_url": "https://api.github.com/users/other_user/events/privacy",
+ "received_events_url": "https://api.github.com/users/other_user/received_events/privacy",
+ "type": "User",
+ "site_admin": false
+ },
+ "team_count": 2,
+ "invitation_team_url": "https://api.github.com/organizations/2/invitations/1/teams"
+ }
+ ]`)
+ })
+
+ opt := &ListOptions{Page: 1}
+ invitations, _, err := client.Organizations.ListPendingOrgInvitations(context.Background(), "o", opt)
+ if err != nil {
+ t.Errorf("Organizations.ListPendingOrgInvitations returned error: %v", err)
+ }
+
+ createdAt := time.Date(2017, time.January, 21, 0, 0, 0, 0, time.UTC)
+ want := []*Invitation{
+ {
+ ID: Int64(1),
+ Login: String("monalisa"),
+ Email: String("octocat@github.com"),
+ Role: String("direct_member"),
+ CreatedAt: &createdAt,
+ Inviter: &User{
+ Login: String("other_user"),
+ ID: Int64(1),
+ AvatarURL: String("https://github.com/images/error/other_user_happy.gif"),
+ GravatarID: String(""),
+ URL: String("https://api.github.com/users/other_user"),
+ HTMLURL: String("https://github.com/other_user"),
+ FollowersURL: String("https://api.github.com/users/other_user/followers"),
+ FollowingURL: String("https://api.github.com/users/other_user/following/other_user"),
+ GistsURL: String("https://api.github.com/users/other_user/gists/gist_id"),
+ StarredURL: String("https://api.github.com/users/other_user/starred/owner/repo"),
+ SubscriptionsURL: String("https://api.github.com/users/other_user/subscriptions"),
+ OrganizationsURL: String("https://api.github.com/users/other_user/orgs"),
+ ReposURL: String("https://api.github.com/users/other_user/repos"),
+ EventsURL: String("https://api.github.com/users/other_user/events/privacy"),
+ ReceivedEventsURL: String("https://api.github.com/users/other_user/received_events/privacy"),
+ Type: String("User"),
+ SiteAdmin: Bool(false),
+ },
+ TeamCount: Int(2),
+ InvitationTeamURL: String("https://api.github.com/organizations/2/invitations/1/teams"),
+ }}
+
+ if !reflect.DeepEqual(invitations, want) {
+ t.Errorf("Organizations.ListPendingOrgInvitations returned %+v, want %+v", invitations, want)
+ }
+}
+
+func TestOrganizationsService_CreateOrgInvitation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ input := &CreateOrgInvitationOptions{
+ Email: String("octocat@github.com"),
+ Role: String("direct_member"),
+ TeamID: []int64{
+ 12,
+ 26,
+ },
+ }
+
+ mux.HandleFunc("/orgs/o/invitations", func(w http.ResponseWriter, r *http.Request) {
+ v := new(CreateOrgInvitationOptions)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeOrganizationInvitationPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprintln(w, `{"email": "octocat@github.com"}`)
+
+ })
+
+ invitations, _, err := client.Organizations.CreateOrgInvitation(context.Background(), "o", input)
+ if err != nil {
+ t.Errorf("Organizations.CreateOrgInvitation returned error: %v", err)
+ }
+
+ want := &Invitation{Email: String("octocat@github.com")}
+ if !reflect.DeepEqual(invitations, want) {
+ t.Errorf("Organizations.ListPendingOrgInvitations returned %+v, want %+v", invitations, want)
+ }
+}
+
+func TestOrganizationsService_ListOrgInvitationTeams(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/invitations/22/teams", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "1"})
+ testHeader(t, r, "Accept", mediaTypeOrganizationInvitationPreview)
+ fmt.Fprint(w, `[
+ {
+ "id": 1,
+ "url": "https://api.github.com/teams/1",
+ "name": "Justice League",
+ "slug": "justice-league",
+ "description": "A great team.",
+ "privacy": "closed",
+ "permission": "admin",
+ "members_url": "https://api.github.com/teams/1/members{/member}",
+ "repositories_url": "https://api.github.com/teams/1/repos"
+ }
+ ]`)
+ })
+
+ opt := &ListOptions{Page: 1}
+ invitations, _, err := client.Organizations.ListOrgInvitationTeams(context.Background(), "o", "22", opt)
+ if err != nil {
+ t.Errorf("Organizations.ListOrgInvitationTeams returned error: %v", err)
+ }
+
+ want := []*Team{
+ {
+ ID: Int64(1),
+ URL: String("https://api.github.com/teams/1"),
+ Name: String("Justice League"),
+ Slug: String("justice-league"),
+ Description: String("A great team."),
+ Privacy: String("closed"),
+ Permission: String("admin"),
+ MembersURL: String("https://api.github.com/teams/1/members{/member}"),
+ RepositoriesURL: String("https://api.github.com/teams/1/repos"),
+ },
+ }
+
+ if !reflect.DeepEqual(invitations, want) {
+ t.Errorf("Organizations.ListOrgInvitationTeams returned %+v, want %+v", invitations, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_outside_collaborators.go b/vendor/github.com/google/go-github/github/orgs_outside_collaborators.go
new file mode 100644
index 0000000..85ffd05
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_outside_collaborators.go
@@ -0,0 +1,81 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+)
+
+// ListOutsideCollaboratorsOptions specifies optional parameters to the
+// OrganizationsService.ListOutsideCollaborators method.
+type ListOutsideCollaboratorsOptions struct {
+ // Filter outside collaborators returned in the list. Possible values are:
+ // 2fa_disabled, all. Default is "all".
+ Filter string `url:"filter,omitempty"`
+
+ ListOptions
+}
+
+// ListOutsideCollaborators lists outside collaborators of organization's repositories.
+// This will only work if the authenticated
+// user is an owner of the organization.
+//
+// Warning: The API may change without advance notice during the preview period.
+// Preview features are not supported for production use.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#list-outside-collaborators
+func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org string, opt *ListOutsideCollaboratorsOptions) ([]*User, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/outside_collaborators", 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
+ }
+
+ var members []*User
+ resp, err := s.client.Do(ctx, req, &members)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return members, resp, nil
+}
+
+// RemoveOutsideCollaborator removes a user from the list of outside collaborators;
+// consequently, removing them from all the organization's repositories.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#remove-outside-collaborator
+func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) {
+ u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ConvertMemberToOutsideCollaborator reduces the permission level of a member of the
+// organization to that of an outside collaborator. Therefore, they will only
+// have access to the repositories that their current team membership allows.
+// Responses for converting a non-member or the last owner to an outside collaborator
+// are listed in GitHub API docs.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#convert-member-to-outside-collaborator
+func (s *OrganizationsService) ConvertMemberToOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) {
+ u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user)
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_outside_collaborators_test.go b/vendor/github.com/google/go-github/github/orgs_outside_collaborators_test.go
new file mode 100644
index 0000000..8b72feb
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_outside_collaborators_test.go
@@ -0,0 +1,134 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestOrganizationsService_ListOutsideCollaborators(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/outside_collaborators", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "filter": "2fa_disabled",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOutsideCollaboratorsOptions{
+ Filter: "2fa_disabled",
+ ListOptions: ListOptions{Page: 2},
+ }
+ members, _, err := client.Organizations.ListOutsideCollaborators(context.Background(), "o", opt)
+ if err != nil {
+ t.Errorf("Organizations.ListOutsideCollaborators returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}}
+ if !reflect.DeepEqual(members, want) {
+ t.Errorf("Organizations.ListOutsideCollaborators returned %+v, want %+v", members, want)
+ }
+}
+
+func TestOrganizationsService_ListOutsideCollaborators_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Organizations.ListOutsideCollaborators(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestOrganizationsService_RemoveOutsideCollaborator(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ }
+ mux.HandleFunc("/orgs/o/outside_collaborators/u", handler)
+
+ _, err := client.Organizations.RemoveOutsideCollaborator(context.Background(), "o", "u")
+ if err != nil {
+ t.Errorf("Organizations.RemoveOutsideCollaborator returned error: %v", err)
+ }
+}
+
+func TestOrganizationsService_RemoveOutsideCollaborator_NonMember(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNotFound)
+ }
+ mux.HandleFunc("/orgs/o/outside_collaborators/u", handler)
+
+ _, err := client.Organizations.RemoveOutsideCollaborator(context.Background(), "o", "u")
+ if err, ok := err.(*ErrorResponse); !ok {
+ t.Errorf("Organizations.RemoveOutsideCollaborator did not return an error")
+ } else if err.Response.StatusCode != http.StatusNotFound {
+ t.Errorf("Organizations.RemoveOutsideCollaborator did not return 404 status code")
+ }
+}
+
+func TestOrganizationsService_RemoveOutsideCollaborator_Member(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusUnprocessableEntity)
+ }
+ mux.HandleFunc("/orgs/o/outside_collaborators/u", handler)
+
+ _, err := client.Organizations.RemoveOutsideCollaborator(context.Background(), "o", "u")
+ if err, ok := err.(*ErrorResponse); !ok {
+ t.Errorf("Organizations.RemoveOutsideCollaborator did not return an error")
+ } else if err.Response.StatusCode != http.StatusUnprocessableEntity {
+ t.Errorf("Organizations.RemoveOutsideCollaborator did not return 422 status code")
+ }
+}
+
+func TestOrganizationsService_ConvertMemberToOutsideCollaborator(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ }
+ mux.HandleFunc("/orgs/o/outside_collaborators/u", handler)
+
+ _, err := client.Organizations.ConvertMemberToOutsideCollaborator(context.Background(), "o", "u")
+ if err != nil {
+ t.Errorf("Organizations.ConvertMemberToOutsideCollaborator returned error: %v", err)
+ }
+}
+
+func TestOrganizationsService_ConvertMemberToOutsideCollaborator_NonMemberOrLastOwner(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ w.WriteHeader(http.StatusForbidden)
+ }
+ mux.HandleFunc("/orgs/o/outside_collaborators/u", handler)
+
+ _, err := client.Organizations.ConvertMemberToOutsideCollaborator(context.Background(), "o", "u")
+ if err, ok := err.(*ErrorResponse); !ok {
+ t.Errorf("Organizations.ConvertMemberToOutsideCollaborator did not return an error")
+ } else if err.Response.StatusCode != http.StatusForbidden {
+ t.Errorf("Organizations.ConvertMemberToOutsideCollaborator did not return 403 status code")
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_projects.go b/vendor/github.com/google/go-github/github/orgs_projects.go
new file mode 100644
index 0000000..e57cba9
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_projects.go
@@ -0,0 +1,60 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+)
+
+// ListProjects lists the projects for an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/#list-organization-projects
+func (s *OrganizationsService) ListProjects(ctx context.Context, org string, opt *ProjectListOptions) ([]*Project, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/projects", 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ var projects []*Project
+ resp, err := s.client.Do(ctx, req, &projects)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return projects, resp, nil
+}
+
+// CreateProject creates a GitHub Project for the specified organization.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/#create-an-organization-project
+func (s *OrganizationsService) CreateProject(ctx context.Context, org string, opt *ProjectOptions) (*Project, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/projects", org)
+ req, err := s.client.NewRequest("POST", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ project := &Project{}
+ resp, err := s.client.Do(ctx, req, project)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return project, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_projects_test.go b/vendor/github.com/google/go-github/github/orgs_projects_test.go
new file mode 100644
index 0000000..efea5cb
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_projects_test.go
@@ -0,0 +1,68 @@
+// Copyright 2017 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestOrganizationsService_ListProjects(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/projects", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+ testFormValues(t, r, values{"state": "open", "page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ProjectListOptions{State: "open", ListOptions: ListOptions{Page: 2}}
+ projects, _, err := client.Organizations.ListProjects(context.Background(), "o", opt)
+ if err != nil {
+ t.Errorf("Organizations.ListProjects returned error: %v", err)
+ }
+
+ want := []*Project{{ID: Int64(1)}}
+ if !reflect.DeepEqual(projects, want) {
+ t.Errorf("Organizations.ListProjects returned %+v, want %+v", projects, want)
+ }
+}
+
+func TestOrganizationsService_CreateProject(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ProjectOptions{Name: String("Project Name"), Body: String("Project body.")}
+
+ mux.HandleFunc("/orgs/o/projects", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+
+ v := &ProjectOptions{}
+ json.NewDecoder(r.Body).Decode(v)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ project, _, err := client.Organizations.CreateProject(context.Background(), "o", input)
+ if err != nil {
+ t.Errorf("Organizations.CreateProject returned error: %v", err)
+ }
+
+ want := &Project{ID: Int64(1)}
+ if !reflect.DeepEqual(project, want) {
+ t.Errorf("Organizations.CreateProject returned %+v, want %+v", project, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_test.go b/vendor/github.com/google/go-github/github/orgs_test.go
new file mode 100644
index 0000000..9fe484d
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_test.go
@@ -0,0 +1,173 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestOrganizationsService_ListAll(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ since := int64(1342004)
+ mux.HandleFunc("/organizations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"since": "1342004"})
+ fmt.Fprint(w, `[{"id":4314092}]`)
+ })
+
+ opt := &OrganizationsListOptions{Since: since}
+ orgs, _, err := client.Organizations.ListAll(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Organizations.ListAll returned error: %v", err)
+ }
+
+ want := []*Organization{{ID: Int64(4314092)}}
+ if !reflect.DeepEqual(orgs, want) {
+ t.Errorf("Organizations.ListAll returned %+v, want %+v", orgs, want)
+ }
+}
+
+func TestOrganizationsService_List_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/orgs", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1},{"id":2}]`)
+ })
+
+ orgs, _, err := client.Organizations.List(context.Background(), "", nil)
+ if err != nil {
+ t.Errorf("Organizations.List returned error: %v", err)
+ }
+
+ want := []*Organization{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(orgs, want) {
+ t.Errorf("Organizations.List returned %+v, want %+v", orgs, want)
+ }
+}
+
+func TestOrganizationsService_List_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/orgs", 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}
+ orgs, _, err := client.Organizations.List(context.Background(), "u", opt)
+ if err != nil {
+ t.Errorf("Organizations.List returned error: %v", err)
+ }
+
+ want := []*Organization{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(orgs, want) {
+ t.Errorf("Organizations.List returned %+v, want %+v", orgs, want)
+ }
+}
+
+func TestOrganizationsService_List_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Organizations.List(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestOrganizationsService_Get(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1, "login":"l", "url":"u", "avatar_url": "a", "location":"l"}`)
+ })
+
+ org, _, err := client.Organizations.Get(context.Background(), "o")
+ if err != nil {
+ t.Errorf("Organizations.Get returned error: %v", err)
+ }
+
+ want := &Organization{ID: Int64(1), Login: String("l"), URL: String("u"), AvatarURL: String("a"), Location: String("l")}
+ if !reflect.DeepEqual(org, want) {
+ t.Errorf("Organizations.Get returned %+v, want %+v", org, want)
+ }
+}
+
+func TestOrganizationsService_Get_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Organizations.Get(context.Background(), "%")
+ testURLParseError(t, err)
+}
+
+func TestOrganizationsService_GetByID(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/organizations/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1, "login":"l", "url":"u", "avatar_url": "a", "location":"l"}`)
+ })
+
+ org, _, err := client.Organizations.GetByID(context.Background(), 1)
+ if err != nil {
+ t.Fatalf("Organizations.GetByID returned error: %v", err)
+ }
+
+ want := &Organization{ID: Int64(1), Login: String("l"), URL: String("u"), AvatarURL: String("a"), Location: String("l")}
+ if !reflect.DeepEqual(org, want) {
+ t.Errorf("Organizations.GetByID returned %+v, want %+v", org, want)
+ }
+}
+
+func TestOrganizationsService_Edit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Organization{Login: String("l")}
+
+ mux.HandleFunc("/orgs/o", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Organization)
+ 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}`)
+ })
+
+ org, _, err := client.Organizations.Edit(context.Background(), "o", input)
+ if err != nil {
+ t.Errorf("Organizations.Edit returned error: %v", err)
+ }
+
+ want := &Organization{ID: Int64(1)}
+ if !reflect.DeepEqual(org, want) {
+ t.Errorf("Organizations.Edit returned %+v, want %+v", org, want)
+ }
+}
+
+func TestOrganizationsService_Edit_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Organizations.Edit(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_users_blocking.go b/vendor/github.com/google/go-github/github/orgs_users_blocking.go
new file mode 100644
index 0000000..b1aecf4
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_users_blocking.go
@@ -0,0 +1,91 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+)
+
+// ListBlockedUsers lists all the users blocked by an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#list-blocked-users
+func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, opt *ListOptions) ([]*User, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/blocks", 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeBlockUsersPreview)
+
+ var blockedUsers []*User
+ resp, err := s.client.Do(ctx, req, &blockedUsers)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return blockedUsers, resp, nil
+}
+
+// IsBlocked reports whether specified user is blocked from an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#check-whether-a-user-is-blocked-from-an-organization
+func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user string) (bool, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/blocks/%v", org, user)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeBlockUsersPreview)
+
+ resp, err := s.client.Do(ctx, req, nil)
+ isBlocked, err := parseBoolResponse(err)
+ return isBlocked, resp, err
+}
+
+// BlockUser blocks specified user from an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#block-a-user
+func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user string) (*Response, error) {
+ u := fmt.Sprintf("orgs/%v/blocks/%v", org, user)
+
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeBlockUsersPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// UnblockUser unblocks specified user from an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#unblock-a-user
+func (s *OrganizationsService) UnblockUser(ctx context.Context, org string, user string) (*Response, error) {
+ u := fmt.Sprintf("orgs/%v/blocks/%v", org, user)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeBlockUsersPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/orgs_users_blocking_test.go b/vendor/github.com/google/go-github/github/orgs_users_blocking_test.go
new file mode 100644
index 0000000..5d38cc4
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/orgs_users_blocking_test.go
@@ -0,0 +1,90 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestOrganizationsService_ListBlockedUsers(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/blocks", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeBlockUsersPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{
+ "login": "octocat"
+ }]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ blockedUsers, _, err := client.Organizations.ListBlockedUsers(context.Background(), "o", opt)
+ if err != nil {
+ t.Errorf("Organizations.ListBlockedUsers returned error: %v", err)
+ }
+
+ want := []*User{{Login: String("octocat")}}
+ if !reflect.DeepEqual(blockedUsers, want) {
+ t.Errorf("Organizations.ListBlockedUsers returned %+v, want %+v", blockedUsers, want)
+ }
+}
+
+func TestOrganizationsService_IsBlocked(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/blocks/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeBlockUsersPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ isBlocked, _, err := client.Organizations.IsBlocked(context.Background(), "o", "u")
+ if err != nil {
+ t.Errorf("Organizations.IsBlocked returned error: %v", err)
+ }
+ if want := true; isBlocked != want {
+ t.Errorf("Organizations.IsBlocked returned %+v, want %+v", isBlocked, want)
+ }
+}
+
+func TestOrganizationsService_BlockUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/blocks/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ testHeader(t, r, "Accept", mediaTypeBlockUsersPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Organizations.BlockUser(context.Background(), "o", "u")
+ if err != nil {
+ t.Errorf("Organizations.BlockUser returned error: %v", err)
+ }
+}
+
+func TestOrganizationsService_UnblockUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/blocks/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeBlockUsersPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Organizations.UnblockUser(context.Background(), "o", "u")
+ if err != nil {
+ t.Errorf("Organizations.UnblockUser returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/projects.go b/vendor/github.com/google/go-github/github/projects.go
new file mode 100644
index 0000000..76ef1e0
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/projects.go
@@ -0,0 +1,462 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+)
+
+// ProjectsService provides access to the projects functions in the
+// GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/
+type ProjectsService service
+
+// Project represents a GitHub Project.
+type Project struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ ColumnsURL *string `json:"columns_url,omitempty"`
+ OwnerURL *string `json:"owner_url,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Body *string `json:"body,omitempty"`
+ Number *int `json:"number,omitempty"`
+ State *string `json:"state,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+
+ // The User object that generated the project.
+ Creator *User `json:"creator,omitempty"`
+}
+
+func (p Project) String() string {
+ return Stringify(p)
+}
+
+// GetProject gets a GitHub Project for a repo.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/#get-a-project
+func (s *ProjectsService) GetProject(ctx context.Context, id int64) (*Project, *Response, error) {
+ u := fmt.Sprintf("projects/%v", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ project := &Project{}
+ resp, err := s.client.Do(ctx, req, project)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return project, resp, nil
+}
+
+// ProjectOptions specifies the parameters to the
+// RepositoriesService.CreateProject and
+// ProjectsService.UpdateProject methods.
+type ProjectOptions struct {
+ // The name of the project. (Required for creation; optional for update.)
+ Name *string `json:"name,omitempty"`
+ // The body of the project. (Optional.)
+ Body *string `json:"body,omitempty"`
+
+ // The following field(s) are only applicable for update.
+ // They should be left with zero values for creation.
+
+ // State of the project. Either "open" or "closed". (Optional.)
+ State *string `json:"state,omitempty"`
+ // The permission level that all members of the project's organization
+ // will have on this project.
+ // Setting the organization permission is only available
+ // for organization projects. (Optional.)
+ OrganizationPermission *string `json:"organization_permission,omitempty"`
+ // Sets visibility of the project within the organization.
+ // Setting visibility is only available
+ // for organization projects.(Optional.)
+ Public *bool `json:"public,omitempty"`
+}
+
+// UpdateProject updates a repository project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/#update-a-project
+func (s *ProjectsService) UpdateProject(ctx context.Context, id int64, opt *ProjectOptions) (*Project, *Response, error) {
+ u := fmt.Sprintf("projects/%v", id)
+ req, err := s.client.NewRequest("PATCH", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ project := &Project{}
+ resp, err := s.client.Do(ctx, req, project)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return project, resp, nil
+}
+
+// DeleteProject deletes a GitHub Project from a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/#delete-a-project
+func (s *ProjectsService) DeleteProject(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("projects/%v", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ProjectColumn represents a column of a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/projects/
+type ProjectColumn struct {
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ URL *string `json:"url,omitempty"`
+ ProjectURL *string `json:"project_url,omitempty"`
+ CardsURL *string `json:"cards_url,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+// ListProjectColumns lists the columns of a GitHub Project for a repo.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/columns/#list-project-columns
+func (s *ProjectsService) ListProjectColumns(ctx context.Context, projectID int64, opt *ListOptions) ([]*ProjectColumn, *Response, error) {
+ u := fmt.Sprintf("projects/%v/columns", projectID)
+ 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ columns := []*ProjectColumn{}
+ resp, err := s.client.Do(ctx, req, &columns)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return columns, resp, nil
+}
+
+// GetProjectColumn gets a column of a GitHub Project for a repo.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/columns/#get-a-project-column
+func (s *ProjectsService) GetProjectColumn(ctx context.Context, id int64) (*ProjectColumn, *Response, error) {
+ u := fmt.Sprintf("projects/columns/%v", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ column := &ProjectColumn{}
+ resp, err := s.client.Do(ctx, req, column)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return column, resp, nil
+}
+
+// ProjectColumnOptions specifies the parameters to the
+// ProjectsService.CreateProjectColumn and
+// ProjectsService.UpdateProjectColumn methods.
+type ProjectColumnOptions struct {
+ // The name of the project column. (Required for creation and update.)
+ Name string `json:"name"`
+}
+
+// CreateProjectColumn creates a column for the specified (by number) project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/columns/#create-a-project-column
+func (s *ProjectsService) CreateProjectColumn(ctx context.Context, projectID int64, opt *ProjectColumnOptions) (*ProjectColumn, *Response, error) {
+ u := fmt.Sprintf("projects/%v/columns", projectID)
+ req, err := s.client.NewRequest("POST", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ column := &ProjectColumn{}
+ resp, err := s.client.Do(ctx, req, column)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return column, resp, nil
+}
+
+// UpdateProjectColumn updates a column of a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/columns/#update-a-project-column
+func (s *ProjectsService) UpdateProjectColumn(ctx context.Context, columnID int64, opt *ProjectColumnOptions) (*ProjectColumn, *Response, error) {
+ u := fmt.Sprintf("projects/columns/%v", columnID)
+ req, err := s.client.NewRequest("PATCH", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ column := &ProjectColumn{}
+ resp, err := s.client.Do(ctx, req, column)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return column, resp, nil
+}
+
+// DeleteProjectColumn deletes a column from a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/columns/#delete-a-project-column
+func (s *ProjectsService) DeleteProjectColumn(ctx context.Context, columnID int64) (*Response, error) {
+ u := fmt.Sprintf("projects/columns/%v", columnID)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ProjectColumnMoveOptions specifies the parameters to the
+// ProjectsService.MoveProjectColumn method.
+type ProjectColumnMoveOptions struct {
+ // Position can be one of "first", "last", or "after:", where
+ // is the ID of a column in the same project. (Required.)
+ Position string `json:"position"`
+}
+
+// MoveProjectColumn moves a column within a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/columns/#move-a-project-column
+func (s *ProjectsService) MoveProjectColumn(ctx context.Context, columnID int64, opt *ProjectColumnMoveOptions) (*Response, error) {
+ u := fmt.Sprintf("projects/columns/%v/moves", columnID)
+ req, err := s.client.NewRequest("POST", u, opt)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ProjectCard represents a card in a column of a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card
+type ProjectCard struct {
+ URL *string `json:"url,omitempty"`
+ ColumnURL *string `json:"column_url,omitempty"`
+ ContentURL *string `json:"content_url,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+ Note *string `json:"note,omitempty"`
+ Creator *User `json:"creator,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ Archived *bool `json:"archived,omitempty"`
+
+ // The following fields are only populated by Webhook events.
+ ColumnID *int64 `json:"column_id,omitempty"`
+}
+
+// ProjectCardListOptions specifies the optional parameters to the
+// ProjectsService.ListProjectCards method.
+type ProjectCardListOptions struct {
+ // ArchivedState is used to list all, archived, or not_archived project cards.
+ // Defaults to not_archived when you omit this parameter.
+ ArchivedState *string `url:"archived_state,omitempty"`
+
+ ListOptions
+}
+
+// ListProjectCards lists the cards in a column of a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/cards/#list-project-cards
+func (s *ProjectsService) ListProjectCards(ctx context.Context, columnID int64, opt *ProjectCardListOptions) ([]*ProjectCard, *Response, error) {
+ u := fmt.Sprintf("projects/columns/%v/cards", columnID)
+ 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ cards := []*ProjectCard{}
+ resp, err := s.client.Do(ctx, req, &cards)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return cards, resp, nil
+}
+
+// GetProjectCard gets a card in a column of a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card
+func (s *ProjectsService) GetProjectCard(ctx context.Context, columnID int64) (*ProjectCard, *Response, error) {
+ u := fmt.Sprintf("projects/columns/cards/%v", columnID)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ card := &ProjectCard{}
+ resp, err := s.client.Do(ctx, req, card)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return card, resp, nil
+}
+
+// ProjectCardOptions specifies the parameters to the
+// ProjectsService.CreateProjectCard and
+// ProjectsService.UpdateProjectCard methods.
+type ProjectCardOptions struct {
+ // The note of the card. Note and ContentID are mutually exclusive.
+ Note string `json:"note,omitempty"`
+ // The ID (not Number) of the Issue to associate with this card.
+ // Note and ContentID are mutually exclusive.
+ ContentID int64 `json:"content_id,omitempty"`
+ // The type of content to associate with this card. Possible values are: "Issue".
+ ContentType string `json:"content_type,omitempty"`
+ // Use true to archive a project card.
+ // Specify false if you need to restore a previously archived project card.
+ Archived *bool `json:"archived,omitempty"`
+}
+
+// CreateProjectCard creates a card in the specified column of a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/cards/#create-a-project-card
+func (s *ProjectsService) CreateProjectCard(ctx context.Context, columnID int64, opt *ProjectCardOptions) (*ProjectCard, *Response, error) {
+ u := fmt.Sprintf("projects/columns/%v/cards", columnID)
+ req, err := s.client.NewRequest("POST", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ card := &ProjectCard{}
+ resp, err := s.client.Do(ctx, req, card)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return card, resp, nil
+}
+
+// UpdateProjectCard updates a card of a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/cards/#update-a-project-card
+func (s *ProjectsService) UpdateProjectCard(ctx context.Context, cardID int64, opt *ProjectCardOptions) (*ProjectCard, *Response, error) {
+ u := fmt.Sprintf("projects/columns/cards/%v", cardID)
+ req, err := s.client.NewRequest("PATCH", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ card := &ProjectCard{}
+ resp, err := s.client.Do(ctx, req, card)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return card, resp, nil
+}
+
+// DeleteProjectCard deletes a card from a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/cards/#delete-a-project-card
+func (s *ProjectsService) DeleteProjectCard(ctx context.Context, cardID int64) (*Response, error) {
+ u := fmt.Sprintf("projects/columns/cards/%v", cardID)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ProjectCardMoveOptions specifies the parameters to the
+// ProjectsService.MoveProjectCard method.
+type ProjectCardMoveOptions struct {
+ // Position can be one of "top", "bottom", or "after:", where
+ // is the ID of a card in the same project.
+ Position string `json:"position"`
+ // ColumnID is the ID of a column in the same project. Note that ColumnID
+ // is required when using Position "after:" when that card is in
+ // another column; otherwise it is optional.
+ ColumnID int64 `json:"column_id,omitempty"`
+}
+
+// MoveProjectCard moves a card within a GitHub Project.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/cards/#move-a-project-card
+func (s *ProjectsService) MoveProjectCard(ctx context.Context, cardID int64, opt *ProjectCardMoveOptions) (*Response, error) {
+ u := fmt.Sprintf("projects/columns/cards/%v/moves", cardID)
+ req, err := s.client.NewRequest("POST", u, opt)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/projects_test.go b/vendor/github.com/google/go-github/github/projects_test.go
new file mode 100644
index 0000000..9f12272
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/projects_test.go
@@ -0,0 +1,384 @@
+// Copyright 2016 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestProjectsService_UpdateProject(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ProjectOptions{
+ Name: String("Project Name"),
+ Body: String("Project body."),
+ State: String("open"),
+ Public: Bool(true),
+
+ OrganizationPermission: String("read"),
+ }
+
+ mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+
+ v := &ProjectOptions{}
+ json.NewDecoder(r.Body).Decode(v)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ project, _, err := client.Projects.UpdateProject(context.Background(), 1, input)
+ if err != nil {
+ t.Errorf("Projects.UpdateProject returned error: %v", err)
+ }
+
+ want := &Project{ID: Int64(1)}
+ if !reflect.DeepEqual(project, want) {
+ t.Errorf("Projects.UpdateProject returned %+v, want %+v", project, want)
+ }
+}
+
+func TestProjectsService_GetProject(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ project, _, err := client.Projects.GetProject(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Projects.GetProject returned error: %v", err)
+ }
+
+ want := &Project{ID: Int64(1)}
+ if !reflect.DeepEqual(project, want) {
+ t.Errorf("Projects.GetProject returned %+v, want %+v", project, want)
+ }
+}
+
+func TestProjectsService_DeleteProject(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+ })
+
+ _, err := client.Projects.DeleteProject(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Projects.DeleteProject returned error: %v", err)
+ }
+}
+
+func TestProjectsService_ListProjectColumns(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeProjectsPreview}
+ mux.HandleFunc("/projects/1/columns", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ columns, _, err := client.Projects.ListProjectColumns(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Projects.ListProjectColumns returned error: %v", err)
+ }
+
+ want := []*ProjectColumn{{ID: Int64(1)}}
+ if !reflect.DeepEqual(columns, want) {
+ t.Errorf("Projects.ListProjectColumns returned %+v, want %+v", columns, want)
+ }
+}
+
+func TestProjectsService_GetProjectColumn(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ column, _, err := client.Projects.GetProjectColumn(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Projects.GetProjectColumn returned error: %v", err)
+ }
+
+ want := &ProjectColumn{ID: Int64(1)}
+ if !reflect.DeepEqual(column, want) {
+ t.Errorf("Projects.GetProjectColumn returned %+v, want %+v", column, want)
+ }
+}
+
+func TestProjectsService_CreateProjectColumn(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ProjectColumnOptions{Name: "Column Name"}
+
+ mux.HandleFunc("/projects/1/columns", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+
+ v := &ProjectColumnOptions{}
+ json.NewDecoder(r.Body).Decode(v)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ column, _, err := client.Projects.CreateProjectColumn(context.Background(), 1, input)
+ if err != nil {
+ t.Errorf("Projects.CreateProjectColumn returned error: %v", err)
+ }
+
+ want := &ProjectColumn{ID: Int64(1)}
+ if !reflect.DeepEqual(column, want) {
+ t.Errorf("Projects.CreateProjectColumn returned %+v, want %+v", column, want)
+ }
+}
+
+func TestProjectsService_UpdateProjectColumn(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ProjectColumnOptions{Name: "Column Name"}
+
+ mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+
+ v := &ProjectColumnOptions{}
+ json.NewDecoder(r.Body).Decode(v)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ column, _, err := client.Projects.UpdateProjectColumn(context.Background(), 1, input)
+ if err != nil {
+ t.Errorf("Projects.UpdateProjectColumn returned error: %v", err)
+ }
+
+ want := &ProjectColumn{ID: Int64(1)}
+ if !reflect.DeepEqual(column, want) {
+ t.Errorf("Projects.UpdateProjectColumn returned %+v, want %+v", column, want)
+ }
+}
+
+func TestProjectsService_DeleteProjectColumn(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+ })
+
+ _, err := client.Projects.DeleteProjectColumn(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Projects.DeleteProjectColumn returned error: %v", err)
+ }
+}
+
+func TestProjectsService_MoveProjectColumn(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ProjectColumnMoveOptions{Position: "after:12345"}
+
+ mux.HandleFunc("/projects/columns/1/moves", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+
+ v := &ProjectColumnMoveOptions{}
+ json.NewDecoder(r.Body).Decode(v)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+ })
+
+ _, err := client.Projects.MoveProjectColumn(context.Background(), 1, input)
+ if err != nil {
+ t.Errorf("Projects.MoveProjectColumn returned error: %v", err)
+ }
+}
+
+func TestProjectsService_ListProjectCards(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/projects/columns/1/cards", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+ testFormValues(t, r, values{
+ "archived_state": "all",
+ "page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ProjectCardListOptions{
+ ArchivedState: String("all"),
+ ListOptions: ListOptions{Page: 2}}
+ cards, _, err := client.Projects.ListProjectCards(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Projects.ListProjectCards returned error: %v", err)
+ }
+
+ want := []*ProjectCard{{ID: Int64(1)}}
+ if !reflect.DeepEqual(cards, want) {
+ t.Errorf("Projects.ListProjectCards returned %+v, want %+v", cards, want)
+ }
+}
+
+func TestProjectsService_GetProjectCard(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ card, _, err := client.Projects.GetProjectCard(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Projects.GetProjectCard returned error: %v", err)
+ }
+
+ want := &ProjectCard{ID: Int64(1)}
+ if !reflect.DeepEqual(card, want) {
+ t.Errorf("Projects.GetProjectCard returned %+v, want %+v", card, want)
+ }
+}
+
+func TestProjectsService_CreateProjectCard(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ProjectCardOptions{
+ ContentID: 12345,
+ ContentType: "Issue",
+ }
+
+ mux.HandleFunc("/projects/columns/1/cards", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+
+ v := &ProjectCardOptions{}
+ json.NewDecoder(r.Body).Decode(v)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ card, _, err := client.Projects.CreateProjectCard(context.Background(), 1, input)
+ if err != nil {
+ t.Errorf("Projects.CreateProjectCard returned error: %v", err)
+ }
+
+ want := &ProjectCard{ID: Int64(1)}
+ if !reflect.DeepEqual(card, want) {
+ t.Errorf("Projects.CreateProjectCard returned %+v, want %+v", card, want)
+ }
+}
+
+func TestProjectsService_UpdateProjectCard(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ProjectCardOptions{
+ ContentID: 12345,
+ ContentType: "Issue",
+ }
+
+ mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+
+ v := &ProjectCardOptions{}
+ json.NewDecoder(r.Body).Decode(v)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1, "archived":false}`)
+ })
+
+ card, _, err := client.Projects.UpdateProjectCard(context.Background(), 1, input)
+ if err != nil {
+ t.Errorf("Projects.UpdateProjectCard returned error: %v", err)
+ }
+
+ want := &ProjectCard{ID: Int64(1), Archived: Bool(false)}
+ if !reflect.DeepEqual(card, want) {
+ t.Errorf("Projects.UpdateProjectCard returned %+v, want %+v", card, want)
+ }
+}
+
+func TestProjectsService_DeleteProjectCard(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+ })
+
+ _, err := client.Projects.DeleteProjectCard(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Projects.DeleteProjectCard returned error: %v", err)
+ }
+}
+
+func TestProjectsService_MoveProjectCard(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ProjectCardMoveOptions{Position: "after:12345"}
+
+ mux.HandleFunc("/projects/columns/cards/1/moves", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+
+ v := &ProjectCardMoveOptions{}
+ json.NewDecoder(r.Body).Decode(v)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+ })
+
+ _, err := client.Projects.MoveProjectCard(context.Background(), 1, input)
+ if err != nil {
+ t.Errorf("Projects.MoveProjectCard returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/pulls.go b/vendor/github.com/google/go-github/github/pulls.go
new file mode 100644
index 0000000..a123ec5
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/pulls.go
@@ -0,0 +1,383 @@
+// 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 (
+ "bytes"
+ "context"
+ "fmt"
+ "strings"
+ "time"
+)
+
+// PullRequestsService handles communication with the pull request related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/
+type PullRequestsService service
+
+// PullRequest represents a GitHub pull request on a repository.
+type PullRequest struct {
+ ID *int64 `json:"id,omitempty"`
+ Number *int `json:"number,omitempty"`
+ State *string `json:"state,omitempty"`
+ Title *string `json:"title,omitempty"`
+ Body *string `json:"body,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+ ClosedAt *time.Time `json:"closed_at,omitempty"`
+ MergedAt *time.Time `json:"merged_at,omitempty"`
+ Labels []*Label `json:"labels,omitempty"`
+ User *User `json:"user,omitempty"`
+ Merged *bool `json:"merged,omitempty"`
+ Mergeable *bool `json:"mergeable,omitempty"`
+ MergeableState *string `json:"mergeable_state,omitempty"`
+ MergedBy *User `json:"merged_by,omitempty"`
+ MergeCommitSHA *string `json:"merge_commit_sha,omitempty"`
+ Comments *int `json:"comments,omitempty"`
+ Commits *int `json:"commits,omitempty"`
+ Additions *int `json:"additions,omitempty"`
+ Deletions *int `json:"deletions,omitempty"`
+ ChangedFiles *int `json:"changed_files,omitempty"`
+ URL *string `json:"url,omitempty"`
+ 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"`
+ CommitsURL *string `json:"commits_url,omitempty"`
+ CommentsURL *string `json:"comments_url,omitempty"`
+ ReviewCommentsURL *string `json:"review_comments_url,omitempty"`
+ ReviewCommentURL *string `json:"review_comment_url,omitempty"`
+ Assignee *User `json:"assignee,omitempty"`
+ Assignees []*User `json:"assignees,omitempty"`
+ Milestone *Milestone `json:"milestone,omitempty"`
+ MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"`
+ AuthorAssociation *string `json:"author_association,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ RequestedReviewers []*User `json:"requested_reviewers,omitempty"`
+
+ Head *PullRequestBranch `json:"head,omitempty"`
+ Base *PullRequestBranch `json:"base,omitempty"`
+
+ // ActiveLockReason is populated only when LockReason is provided while locking the pull request.
+ // Possible values are: "off-topic", "too heated", "resolved", and "spam".
+ ActiveLockReason *string `json:"active_lock_reason,omitempty"`
+}
+
+func (p PullRequest) String() string {
+ return Stringify(p)
+}
+
+// PullRequestBranch represents a base or head branch in a GitHub pull request.
+type PullRequestBranch struct {
+ Label *string `json:"label,omitempty"`
+ Ref *string `json:"ref,omitempty"`
+ SHA *string `json:"sha,omitempty"`
+ Repo *Repository `json:"repo,omitempty"`
+ User *User `json:"user,omitempty"`
+}
+
+// PullRequestListOptions specifies the optional parameters to the
+// PullRequestsService.List method.
+type PullRequestListOptions struct {
+ // State filters pull requests based on their state. Possible values are:
+ // open, closed. Default is "open".
+ State string `url:"state,omitempty"`
+
+ // Head filters pull requests by head user and branch name in the format of:
+ // "user:ref-name".
+ Head string `url:"head,omitempty"`
+
+ // 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
+}
+
+// List the pull requests for the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests
+func (s *PullRequestsService) List(ctx context.Context, owner string, repo string, opt *PullRequestListOptions) ([]*PullRequest, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+ var pulls []*PullRequest
+ resp, err := s.client.Do(ctx, req, &pulls)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return pulls, resp, nil
+}
+
+// Get a single pull request.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/#get-a-single-pull-request
+func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string, number int) (*PullRequest, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number)
+ 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.
+ acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+ pull := new(PullRequest)
+ resp, err := s.client.Do(ctx, req, pull)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return pull, resp, nil
+}
+
+// GetRaw gets a single pull request in raw (diff or patch) format.
+func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo string, number int, opt RawOptions) (string, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return "", nil, err
+ }
+
+ switch opt.Type {
+ case Diff:
+ req.Header.Set("Accept", mediaTypeV3Diff)
+ case Patch:
+ req.Header.Set("Accept", mediaTypeV3Patch)
+ default:
+ return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type)
+ }
+
+ var buf bytes.Buffer
+ resp, err := s.client.Do(ctx, req, &buf)
+ if err != nil {
+ return "", resp, err
+ }
+
+ return buf.String(), resp, nil
+}
+
+// NewPullRequest represents a new pull request to be created.
+type NewPullRequest struct {
+ Title *string `json:"title,omitempty"`
+ Head *string `json:"head,omitempty"`
+ Base *string `json:"base,omitempty"`
+ Body *string `json:"body,omitempty"`
+ Issue *int `json:"issue,omitempty"`
+ MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"`
+}
+
+// Create a new pull request on the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/#create-a-pull-request
+func (s *PullRequestsService) Create(ctx context.Context, owner string, repo string, pull *NewPullRequest) (*PullRequest, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo)
+ req, err := s.client.NewRequest("POST", u, pull)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+
+ p := new(PullRequest)
+ resp, err := s.client.Do(ctx, req, p)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return p, resp, nil
+}
+
+type pullRequestUpdate struct {
+ Title *string `json:"title,omitempty"`
+ Body *string `json:"body,omitempty"`
+ State *string `json:"state,omitempty"`
+ Base *string `json:"base,omitempty"`
+ MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"`
+}
+
+// Edit a pull request.
+// pull must not be nil.
+//
+// The following fields are editable: Title, Body, State, Base.Ref and MaintainerCanModify.
+// Base.Ref updates the base branch of the pull request.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/#update-a-pull-request
+func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo string, number int, pull *PullRequest) (*PullRequest, *Response, error) {
+ if pull == nil {
+ return nil, nil, fmt.Errorf("pull must be provided")
+ }
+
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number)
+
+ update := &pullRequestUpdate{
+ Title: pull.Title,
+ Body: pull.Body,
+ State: pull.State,
+ MaintainerCanModify: pull.MaintainerCanModify,
+ }
+ if pull.Base != nil {
+ update.Base = pull.Base.Ref
+ }
+
+ req, err := s.client.NewRequest("PATCH", u, update)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+ p := new(PullRequest)
+ resp, err := s.client.Do(ctx, req, p)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return p, resp, nil
+}
+
+// ListCommits lists the commits in a pull request.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request
+func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*RepositoryCommit, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/commits", owner, repo, number)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeGitSigningPreview)
+
+ var commits []*RepositoryCommit
+ resp, err := s.client.Do(ctx, req, &commits)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return commits, resp, nil
+}
+
+// ListFiles lists the files in a pull request.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests-files
+func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*CommitFile, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/files", owner, repo, number)
+ 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
+ }
+
+ var commitFiles []*CommitFile
+ resp, err := s.client.Do(ctx, req, &commitFiles)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return commitFiles, resp, nil
+}
+
+// IsMerged checks if a pull request has been merged.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/#get-if-a-pull-request-has-been-merged
+func (s *PullRequestsService) IsMerged(ctx context.Context, owner string, repo string, number int) (bool, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+
+ resp, err := s.client.Do(ctx, req, nil)
+ merged, err := parseBoolResponse(err)
+ return merged, resp, err
+}
+
+// PullRequestMergeResult represents the result of merging a pull request.
+type PullRequestMergeResult struct {
+ SHA *string `json:"sha,omitempty"`
+ Merged *bool `json:"merged,omitempty"`
+ Message *string `json:"message,omitempty"`
+}
+
+// PullRequestOptions lets you define how a pull request will be merged.
+type PullRequestOptions struct {
+ CommitTitle string // Extra detail to append to automatic commit message. (Optional.)
+ SHA string // SHA that pull request head must match to allow merge. (Optional.)
+
+ // The merge method to use. Possible values include: "merge", "squash", and "rebase" with the default being merge. (Optional.)
+ MergeMethod string
+}
+
+type pullRequestMergeRequest struct {
+ CommitMessage string `json:"commit_message"`
+ CommitTitle string `json:"commit_title,omitempty"`
+ MergeMethod string `json:"merge_method,omitempty"`
+ SHA string `json:"sha,omitempty"`
+}
+
+// Merge a pull request (Merge Button™).
+// commitMessage is the title for the automatic commit message.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-buttontrade
+func (s *PullRequestsService) Merge(ctx context.Context, owner string, repo string, number int, commitMessage string, options *PullRequestOptions) (*PullRequestMergeResult, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number)
+
+ pullRequestBody := &pullRequestMergeRequest{CommitMessage: commitMessage}
+ if options != nil {
+ pullRequestBody.CommitTitle = options.CommitTitle
+ pullRequestBody.MergeMethod = options.MergeMethod
+ pullRequestBody.SHA = options.SHA
+ }
+ req, err := s.client.NewRequest("PUT", u, pullRequestBody)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ mergeResult := new(PullRequestMergeResult)
+ resp, err := s.client.Do(ctx, req, mergeResult)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return mergeResult, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/pulls_comments.go b/vendor/github.com/google/go-github/github/pulls_comments.go
new file mode 100644
index 0000000..f306776
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/pulls_comments.go
@@ -0,0 +1,188 @@
+// 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// PullRequestComment represents a comment left on a pull request.
+type PullRequestComment struct {
+ ID *int64 `json:"id,omitempty"`
+ InReplyTo *int64 `json:"in_reply_to_id,omitempty"`
+ Body *string `json:"body,omitempty"`
+ Path *string `json:"path,omitempty"`
+ DiffHunk *string `json:"diff_hunk,omitempty"`
+ PullRequestReviewID *int64 `json:"pull_request_review_id,omitempty"`
+ Position *int `json:"position,omitempty"`
+ OriginalPosition *int `json:"original_position,omitempty"`
+ CommitID *string `json:"commit_id,omitempty"`
+ OriginalCommitID *string `json:"original_commit_id,omitempty"`
+ User *User `json:"user,omitempty"`
+ Reactions *Reactions `json:"reactions,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+ // AuthorAssociation is the comment author's relationship to the pull request's repository.
+ // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE".
+ AuthorAssociation *string `json:"author_association,omitempty"`
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ PullRequestURL *string `json:"pull_request_url,omitempty"`
+}
+
+func (p PullRequestComment) String() string {
+ return Stringify(p)
+}
+
+// PullRequestListCommentsOptions specifies the optional parameters to the
+// PullRequestsService.ListComments method.
+type PullRequestListCommentsOptions struct {
+ // Sort specifies how to sort comments. Possible values are: created, updated.
+ Sort string `url:"sort,omitempty"`
+
+ // Direction in which to sort comments. Possible values are: asc, desc.
+ Direction string `url:"direction,omitempty"`
+
+ // Since filters comments by time.
+ Since time.Time `url:"since,omitempty"`
+
+ ListOptions
+}
+
+// ListComments lists all comments on the specified pull request. Specifying a
+// pull request number of 0 will return all comments on all pull requests for
+// the repository.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request
+func (s *PullRequestsService) ListComments(ctx context.Context, owner string, repo string, number int, opt *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) {
+ var u string
+ if number == 0 {
+ u = fmt.Sprintf("repos/%v/%v/pulls/comments", owner, repo)
+ } else {
+ u = fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number)
+ }
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ var comments []*PullRequestComment
+ resp, err := s.client.Do(ctx, req, &comments)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return comments, resp, nil
+}
+
+// GetComment fetches the specified pull request comment.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/comments/#get-a-single-comment
+func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*PullRequestComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID)
+ 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", mediaTypeReactionsPreview)
+
+ comment := new(PullRequestComment)
+ resp, err := s.client.Do(ctx, req, comment)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return comment, resp, nil
+}
+
+// CreateComment creates a new comment on the specified pull request.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-comment
+func (s *PullRequestsService) CreateComment(ctx context.Context, 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)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c := new(PullRequestComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// CreateCommentInReplyTo creates a new comment as a reply to an existing pull request comment.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/comments/#alternative-input
+func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner string, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) {
+ comment := &struct {
+ Body string `json:"body,omitempty"`
+ InReplyTo int64 `json:"in_reply_to,omitempty"`
+ }{
+ Body: body,
+ InReplyTo: commentID,
+ }
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number)
+ req, err := s.client.NewRequest("POST", u, comment)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c := new(PullRequestComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// EditComment updates a pull request comment.
+// A non-nil comment.Body must be provided. Other comment fields should be left nil.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/comments/#edit-a-comment
+func (s *PullRequestsService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID)
+ req, err := s.client.NewRequest("PATCH", u, comment)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c := new(PullRequestComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// DeleteComment deletes a pull request comment.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/comments/#delete-a-comment
+func (s *PullRequestsService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/pulls_comments_test.go b/vendor/github.com/google/go-github/github/pulls_comments_test.go
new file mode 100644
index 0000000..76b78cf
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/pulls_comments_test.go
@@ -0,0 +1,203 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestPullRequestsService_ListComments_allPulls(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/comments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+ testFormValues(t, r, values{
+ "sort": "updated",
+ "direction": "desc",
+ "since": "2002-02-10T15:30:00Z",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &PullRequestListCommentsOptions{
+ Sort: "updated",
+ Direction: "desc",
+ Since: time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC),
+ ListOptions: ListOptions{Page: 2},
+ }
+ pulls, _, err := client.PullRequests.ListComments(context.Background(), "o", "r", 0, opt)
+ if err != nil {
+ t.Errorf("PullRequests.ListComments returned error: %v", err)
+ }
+
+ want := []*PullRequestComment{{ID: Int64(1)}}
+ if !reflect.DeepEqual(pulls, want) {
+ t.Errorf("PullRequests.ListComments returned %+v, want %+v", pulls, want)
+ }
+}
+
+func TestPullRequestsService_ListComments_specificPull(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/comments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+ fmt.Fprint(w, `[{"id":1, "pull_request_review_id":42}]`)
+ })
+
+ pulls, _, err := client.PullRequests.ListComments(context.Background(), "o", "r", 1, nil)
+ if err != nil {
+ t.Errorf("PullRequests.ListComments returned error: %v", err)
+ }
+
+ want := []*PullRequestComment{{ID: Int64(1), PullRequestReviewID: Int64(42)}}
+ if !reflect.DeepEqual(pulls, want) {
+ t.Errorf("PullRequests.ListComments returned %+v, want %+v", pulls, want)
+ }
+}
+
+func TestPullRequestsService_ListComments_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.ListComments(context.Background(), "%", "r", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_GetComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/comments/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ comment, _, err := client.PullRequests.GetComment(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("PullRequests.GetComment returned error: %v", err)
+ }
+
+ want := &PullRequestComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("PullRequests.GetComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestPullRequestsService_GetComment_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.GetComment(context.Background(), "%", "r", 1)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_CreateComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &PullRequestComment{Body: String("b")}
+
+ mux.HandleFunc("/repos/o/r/pulls/1/comments", func(w http.ResponseWriter, r *http.Request) {
+ v := new(PullRequestComment)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ comment, _, err := client.PullRequests.CreateComment(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("PullRequests.CreateComment returned error: %v", err)
+ }
+
+ want := &PullRequestComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("PullRequests.CreateComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestPullRequestsService_CreateComment_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.CreateComment(context.Background(), "%", "r", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_EditComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &PullRequestComment{Body: String("b")}
+
+ mux.HandleFunc("/repos/o/r/pulls/comments/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(PullRequestComment)
+ 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}`)
+ })
+
+ comment, _, err := client.PullRequests.EditComment(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("PullRequests.EditComment returned error: %v", err)
+ }
+
+ want := &PullRequestComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("PullRequests.EditComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestPullRequestsService_EditComment_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.EditComment(context.Background(), "%", "r", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_DeleteComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/comments/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.PullRequests.DeleteComment(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("PullRequests.DeleteComment returned error: %v", err)
+ }
+}
+
+func TestPullRequestsService_DeleteComment_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.PullRequests.DeleteComment(context.Background(), "%", "r", 1)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/pulls_reviewers.go b/vendor/github.com/google/go-github/github/pulls_reviewers.go
new file mode 100644
index 0000000..a1d7853
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/pulls_reviewers.go
@@ -0,0 +1,79 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+)
+
+// ReviewersRequest specifies users and teams for a pull request review request.
+type ReviewersRequest struct {
+ Reviewers []string `json:"reviewers,omitempty"`
+ TeamReviewers []string `json:"team_reviewers,omitempty"`
+}
+
+// Reviewers represents reviewers of a pull request.
+type Reviewers struct {
+ Users []*User `json:"users,omitempty"`
+ Teams []*Team `json:"teams,omitempty"`
+}
+
+// RequestReviewers creates a review request for the provided reviewers for the specified pull request.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#create-a-review-request
+func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*PullRequest, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number)
+ req, err := s.client.NewRequest("POST", u, &reviewers)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(PullRequest)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// ListReviewers lists reviewers whose reviews have been requested on the specified pull request.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#list-review-requests
+func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo string, number int, opt *ListOptions) (*Reviewers, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/requested_reviewers", owner, repo, number)
+ 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
+ }
+
+ reviewers := new(Reviewers)
+ resp, err := s.client.Do(ctx, req, reviewers)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return reviewers, resp, nil
+}
+
+// RemoveReviewers removes the review request for the provided reviewers for the specified pull request.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#delete-a-review-request
+func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number)
+ req, err := s.client.NewRequest("DELETE", u, &reviewers)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/pulls_reviewers_test.go b/vendor/github.com/google/go-github/github/pulls_reviewers_test.go
new file mode 100644
index 0000000..7c550e1
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/pulls_reviewers_test.go
@@ -0,0 +1,101 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRequestReviewers(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/requested_reviewers", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testBody(t, r, `{"reviewers":["octocat","googlebot"],"team_reviewers":["justice-league","injustice-league"]}`+"\n")
+ fmt.Fprint(w, `{"number":1}`)
+ })
+
+ // This returns a PR, unmarshalling of which is tested elsewhere
+ pull, _, err := client.PullRequests.RequestReviewers(context.Background(), "o", "r", 1, ReviewersRequest{Reviewers: []string{"octocat", "googlebot"}, TeamReviewers: []string{"justice-league", "injustice-league"}})
+ if err != nil {
+ t.Errorf("PullRequests.RequestReviewers returned error: %v", err)
+ }
+ want := &PullRequest{Number: Int(1)}
+ if !reflect.DeepEqual(pull, want) {
+ t.Errorf("PullRequests.RequestReviewers returned %+v, want %+v", pull, want)
+ }
+}
+
+func TestRemoveReviewers(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/requested_reviewers", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testBody(t, r, `{"reviewers":["octocat","googlebot"],"team_reviewers":["justice-league"]}`+"\n")
+ })
+
+ _, err := client.PullRequests.RemoveReviewers(context.Background(), "o", "r", 1, ReviewersRequest{Reviewers: []string{"octocat", "googlebot"}, TeamReviewers: []string{"justice-league"}})
+ if err != nil {
+ t.Errorf("PullRequests.RemoveReviewers returned error: %v", err)
+ }
+}
+
+func TestListReviewers(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/requested_reviewers", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"users":[{"login":"octocat","id":1}],"teams":[{"id":1,"name":"Justice League"}]}`)
+ })
+
+ reviewers, _, err := client.PullRequests.ListReviewers(context.Background(), "o", "r", 1, nil)
+ if err != nil {
+ t.Errorf("PullRequests.ListReviewers returned error: %v", err)
+ }
+
+ want := &Reviewers{
+ Users: []*User{
+ {
+ Login: String("octocat"),
+ ID: Int64(1),
+ },
+ },
+ Teams: []*Team{
+ {
+ ID: Int64(1),
+ Name: String("Justice League"),
+ },
+ },
+ }
+ if !reflect.DeepEqual(reviewers, want) {
+ t.Errorf("PullRequests.ListReviewers returned %+v, want %+v", reviewers, want)
+ }
+}
+
+func TestListReviewers_withOptions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/requested_reviewers", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "2",
+ })
+ fmt.Fprint(w, `{}`)
+ })
+
+ _, _, err := client.PullRequests.ListReviewers(context.Background(), "o", "r", 1, &ListOptions{Page: 2})
+ if err != nil {
+ t.Errorf("PullRequests.ListReviewers returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/pulls_reviews.go b/vendor/github.com/google/go-github/github/pulls_reviews.go
new file mode 100644
index 0000000..57d3c63
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/pulls_reviews.go
@@ -0,0 +1,236 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// PullRequestReview represents a review of a pull request.
+type PullRequestReview struct {
+ ID *int64 `json:"id,omitempty"`
+ User *User `json:"user,omitempty"`
+ Body *string `json:"body,omitempty"`
+ SubmittedAt *time.Time `json:"submitted_at,omitempty"`
+ CommitID *string `json:"commit_id,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ PullRequestURL *string `json:"pull_request_url,omitempty"`
+ State *string `json:"state,omitempty"`
+}
+
+func (p PullRequestReview) String() string {
+ return Stringify(p)
+}
+
+// DraftReviewComment represents a comment part of the review.
+type DraftReviewComment struct {
+ Path *string `json:"path,omitempty"`
+ Position *int `json:"position,omitempty"`
+ Body *string `json:"body,omitempty"`
+}
+
+func (c DraftReviewComment) String() string {
+ return Stringify(c)
+}
+
+// PullRequestReviewRequest represents a request to create a review.
+type PullRequestReviewRequest struct {
+ CommitID *string `json:"commit_id,omitempty"`
+ Body *string `json:"body,omitempty"`
+ Event *string `json:"event,omitempty"`
+ Comments []*DraftReviewComment `json:"comments,omitempty"`
+}
+
+func (r PullRequestReviewRequest) String() string {
+ return Stringify(r)
+}
+
+// PullRequestReviewDismissalRequest represents a request to dismiss a review.
+type PullRequestReviewDismissalRequest struct {
+ Message *string `json:"message,omitempty"`
+}
+
+func (r PullRequestReviewDismissalRequest) String() string {
+ return Stringify(r)
+}
+
+// ListReviews lists all reviews on the specified pull request.
+//
+// TODO: Follow up with GitHub support about an issue with this method's
+// returned error format and remove this comment once it's fixed.
+// Read more about it here - https://github.com/google/go-github/issues/540
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request
+func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*PullRequestReview, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)
+ 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
+ }
+
+ var reviews []*PullRequestReview
+ resp, err := s.client.Do(ctx, req, &reviews)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return reviews, resp, nil
+}
+
+// GetReview fetches the specified pull request review.
+//
+// TODO: Follow up with GitHub support about an issue with this method's
+// returned error format and remove this comment once it's fixed.
+// Read more about it here - https://github.com/google/go-github/issues/540
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-a-single-review
+func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ review := new(PullRequestReview)
+ resp, err := s.client.Do(ctx, req, review)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return review, resp, nil
+}
+
+// DeletePendingReview deletes the specified pull request pending review.
+//
+// TODO: Follow up with GitHub support about an issue with this method's
+// returned error format and remove this comment once it's fixed.
+// Read more about it here - https://github.com/google/go-github/issues/540
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review
+func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ review := new(PullRequestReview)
+ resp, err := s.client.Do(ctx, req, review)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return review, resp, nil
+}
+
+// ListReviewComments lists all the comments for the specified review.
+//
+// TODO: Follow up with GitHub support about an issue with this method's
+// returned error format and remove this comment once it's fixed.
+// Read more about it here - https://github.com/google/go-github/issues/540
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review
+func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opt *ListOptions) ([]*PullRequestComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID)
+ 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
+ }
+
+ var comments []*PullRequestComment
+ resp, err := s.client.Do(ctx, req, &comments)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return comments, resp, nil
+}
+
+// CreateReview creates a new review on the specified pull request.
+//
+// TODO: Follow up with GitHub support about an issue with this method's
+// returned error format and remove this comment once it's fixed.
+// Read more about it here - https://github.com/google/go-github/issues/540
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review
+func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)
+
+ req, err := s.client.NewRequest("POST", u, review)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(PullRequestReview)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// SubmitReview submits a specified review on the specified pull request.
+//
+// TODO: Follow up with GitHub support about an issue with this method's
+// returned error format and remove this comment once it's fixed.
+// Read more about it here - https://github.com/google/go-github/issues/540
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review
+func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID)
+
+ req, err := s.client.NewRequest("POST", u, review)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(PullRequestReview)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// DismissReview dismisses a specified review on the specified pull request.
+//
+// TODO: Follow up with GitHub support about an issue with this method's
+// returned error format and remove this comment once it's fixed.
+// Read more about it here - https://github.com/google/go-github/issues/540
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review
+func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID)
+
+ req, err := s.client.NewRequest("PUT", u, review)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(PullRequestReview)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/pulls_reviews_test.go b/vendor/github.com/google/go-github/github/pulls_reviews_test.go
new file mode 100644
index 0000000..58e301b
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/pulls_reviews_test.go
@@ -0,0 +1,273 @@
+// Copyright 2016 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestPullRequestsService_ListReviews(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/reviews", 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}
+ reviews, _, err := client.PullRequests.ListReviews(context.Background(), "o", "r", 1, opt)
+ if err != nil {
+ t.Errorf("PullRequests.ListReviews returned error: %v", err)
+ }
+
+ want := []*PullRequestReview{
+ {ID: Int64(1)},
+ {ID: Int64(2)},
+ }
+ if !reflect.DeepEqual(reviews, want) {
+ t.Errorf("PullRequests.ListReviews returned %+v, want %+v", reviews, want)
+ }
+}
+
+func TestPullRequestsService_ListReviews_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.ListReviews(context.Background(), "%", "r", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_GetReview(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ review, _, err := client.PullRequests.GetReview(context.Background(), "o", "r", 1, 1)
+ if err != nil {
+ t.Errorf("PullRequests.GetReview returned error: %v", err)
+ }
+
+ want := &PullRequestReview{ID: Int64(1)}
+ if !reflect.DeepEqual(review, want) {
+ t.Errorf("PullRequests.GetReview returned %+v, want %+v", review, want)
+ }
+}
+
+func TestPullRequestsService_GetReview_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.GetReview(context.Background(), "%", "r", 1, 1)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_DeletePendingReview(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ review, _, err := client.PullRequests.DeletePendingReview(context.Background(), "o", "r", 1, 1)
+ if err != nil {
+ t.Errorf("PullRequests.DeletePendingReview returned error: %v", err)
+ }
+
+ want := &PullRequestReview{ID: Int64(1)}
+ if !reflect.DeepEqual(review, want) {
+ t.Errorf("PullRequests.DeletePendingReview returned %+v, want %+v", review, want)
+ }
+}
+
+func TestPullRequestsService_DeletePendingReview_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.DeletePendingReview(context.Background(), "%", "r", 1, 1)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_ListReviewComments(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/comments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1},{"id":2}]`)
+ })
+
+ comments, _, err := client.PullRequests.ListReviewComments(context.Background(), "o", "r", 1, 1, nil)
+ if err != nil {
+ t.Errorf("PullRequests.ListReviewComments returned error: %v", err)
+ }
+
+ want := []*PullRequestComment{
+ {ID: Int64(1)},
+ {ID: Int64(2)},
+ }
+ if !reflect.DeepEqual(comments, want) {
+ t.Errorf("PullRequests.ListReviewComments returned %+v, want %+v", comments, want)
+ }
+}
+
+func TestPullRequestsService_ListReviewComments_withOptions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/comments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "2",
+ })
+ fmt.Fprint(w, `[]`)
+ })
+
+ _, _, err := client.PullRequests.ListReviewComments(context.Background(), "o", "r", 1, 1, &ListOptions{Page: 2})
+ if err != nil {
+ t.Errorf("PullRequests.ListReviewComments returned error: %v", err)
+ }
+}
+
+func TestPullRequestsService_ListReviewComments_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.ListReviewComments(context.Background(), "%", "r", 1, 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_CreateReview(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &PullRequestReviewRequest{
+ CommitID: String("commit_id"),
+ Body: String("b"),
+ Event: String("APPROVE"),
+ }
+
+ mux.HandleFunc("/repos/o/r/pulls/1/reviews", func(w http.ResponseWriter, r *http.Request) {
+ v := new(PullRequestReviewRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ review, _, err := client.PullRequests.CreateReview(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("PullRequests.CreateReview returned error: %v", err)
+ }
+
+ want := &PullRequestReview{ID: Int64(1)}
+ if !reflect.DeepEqual(review, want) {
+ t.Errorf("PullRequests.CreateReview returned %+v, want %+v", review, want)
+ }
+}
+
+func TestPullRequestsService_CreateReview_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.CreateReview(context.Background(), "%", "r", 1, &PullRequestReviewRequest{})
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_SubmitReview(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &PullRequestReviewRequest{
+ Body: String("b"),
+ Event: String("APPROVE"),
+ }
+
+ mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/events", func(w http.ResponseWriter, r *http.Request) {
+ v := new(PullRequestReviewRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ review, _, err := client.PullRequests.SubmitReview(context.Background(), "o", "r", 1, 1, input)
+ if err != nil {
+ t.Errorf("PullRequests.SubmitReview returned error: %v", err)
+ }
+
+ want := &PullRequestReview{ID: Int64(1)}
+ if !reflect.DeepEqual(review, want) {
+ t.Errorf("PullRequests.SubmitReview returned %+v, want %+v", review, want)
+ }
+}
+
+func TestPullRequestsService_SubmitReview_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.SubmitReview(context.Background(), "%", "r", 1, 1, &PullRequestReviewRequest{})
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_DismissReview(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &PullRequestReviewDismissalRequest{Message: String("m")}
+
+ mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/dismissals", func(w http.ResponseWriter, r *http.Request) {
+ v := new(PullRequestReviewDismissalRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PUT")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ review, _, err := client.PullRequests.DismissReview(context.Background(), "o", "r", 1, 1, input)
+ if err != nil {
+ t.Errorf("PullRequests.DismissReview returned error: %v", err)
+ }
+
+ want := &PullRequestReview{ID: Int64(1)}
+ if !reflect.DeepEqual(review, want) {
+ t.Errorf("PullRequests.DismissReview returned %+v, want %+v", review, want)
+ }
+}
+
+func TestPullRequestsService_DismissReview_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.DismissReview(context.Background(), "%", "r", 1, 1, &PullRequestReviewDismissalRequest{})
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/pulls_test.go b/vendor/github.com/google/go-github/github/pulls_test.go
new file mode 100644
index 0000000..3b2449f
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/pulls_test.go
@@ -0,0 +1,532 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestPullRequestsService_List(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ mux.HandleFunc("/repos/o/r/pulls", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ testFormValues(t, r, values{
+ "state": "closed",
+ "head": "h",
+ "base": "b",
+ "sort": "created",
+ "direction": "desc",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"number":1}]`)
+ })
+
+ opt := &PullRequestListOptions{"closed", "h", "b", "created", "desc", ListOptions{Page: 2}}
+ pulls, _, err := client.PullRequests.List(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("PullRequests.List returned error: %v", err)
+ }
+
+ want := []*PullRequest{{Number: Int(1)}}
+ if !reflect.DeepEqual(pulls, want) {
+ t.Errorf("PullRequests.List returned %+v, want %+v", pulls, want)
+ }
+}
+
+func TestPullRequestsService_List_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.List(context.Background(), "%", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_Get(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ fmt.Fprint(w, `{"number":1}`)
+ })
+
+ pull, _, err := client.PullRequests.Get(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("PullRequests.Get returned error: %v", err)
+ }
+
+ want := &PullRequest{Number: Int(1)}
+ if !reflect.DeepEqual(pull, want) {
+ t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want)
+ }
+}
+
+func TestPullRequestsService_GetRaw_diff(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ const rawStr = "@@diff content"
+
+ mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeV3Diff)
+ fmt.Fprint(w, rawStr)
+ })
+
+ got, _, err := client.PullRequests.GetRaw(context.Background(), "o", "r", 1, RawOptions{Diff})
+ if err != nil {
+ t.Fatalf("PullRequests.GetRaw returned error: %v", err)
+ }
+ want := rawStr
+ if got != want {
+ t.Errorf("PullRequests.GetRaw returned %s want %s", got, want)
+ }
+}
+
+func TestPullRequestsService_GetRaw_patch(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ const rawStr = "@@patch content"
+
+ mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeV3Patch)
+ fmt.Fprint(w, rawStr)
+ })
+
+ got, _, err := client.PullRequests.GetRaw(context.Background(), "o", "r", 1, RawOptions{Patch})
+ if err != nil {
+ t.Fatalf("PullRequests.GetRaw returned error: %v", err)
+ }
+ want := rawStr
+ if got != want {
+ t.Errorf("PullRequests.GetRaw returned %s want %s", got, want)
+ }
+}
+
+func TestPullRequestsService_GetRaw_invalid(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.GetRaw(context.Background(), "o", "r", 1, RawOptions{100})
+ if err == nil {
+ t.Fatal("PullRequests.GetRaw should return error")
+ }
+ if !strings.Contains(err.Error(), "unsupported raw type") {
+ t.Error("PullRequests.GetRaw should return unsupported raw type error")
+ }
+}
+
+func TestPullRequestsService_Get_headAndBase(t *testing.T) {
+ client, mux, _, teardown := 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,"head":{"ref":"r2","repo":{"id":2}},"base":{"ref":"r1","repo":{"id":1}}}`)
+ })
+
+ pull, _, err := client.PullRequests.Get(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("PullRequests.Get returned error: %v", err)
+ }
+
+ want := &PullRequest{
+ Number: Int(1),
+ Head: &PullRequestBranch{
+ Ref: String("r2"),
+ Repo: &Repository{ID: Int64(2)},
+ },
+ Base: &PullRequestBranch{
+ Ref: String("r1"),
+ Repo: &Repository{ID: Int64(1)},
+ },
+ }
+ if !reflect.DeepEqual(pull, want) {
+ t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want)
+ }
+}
+
+func TestPullRequestsService_Get_urlFields(t *testing.T) {
+ client, mux, _, teardown := 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,
+ "url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347",
+ "html_url": "https://github.com/octocat/Hello-World/pull/1347",
+ "issue_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347",
+ "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e",
+ "diff_url": "https://github.com/octocat/Hello-World/pull/1347.diff",
+ "patch_url": "https://github.com/octocat/Hello-World/pull/1347.patch",
+ "review_comments_url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments",
+ "review_comment_url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}"}`)
+ })
+
+ pull, _, err := client.PullRequests.Get(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("PullRequests.Get returned error: %v", err)
+ }
+
+ want := &PullRequest{
+ Number: Int(1),
+ URL: String("https://api.github.com/repos/octocat/Hello-World/pulls/1347"),
+ HTMLURL: String("https://github.com/octocat/Hello-World/pull/1347"),
+ IssueURL: String("https://api.github.com/repos/octocat/Hello-World/issues/1347"),
+ StatusesURL: String("https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e"),
+ DiffURL: String("https://github.com/octocat/Hello-World/pull/1347.diff"),
+ PatchURL: String("https://github.com/octocat/Hello-World/pull/1347.patch"),
+ ReviewCommentsURL: String("https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments"),
+ ReviewCommentURL: String("https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}"),
+ }
+
+ if !reflect.DeepEqual(pull, want) {
+ t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want)
+ }
+}
+
+func TestPullRequestsService_Get_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.Get(context.Background(), "%", "r", 1)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_Create(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &NewPullRequest{Title: String("t")}
+
+ mux.HandleFunc("/repos/o/r/pulls", func(w http.ResponseWriter, r *http.Request) {
+ v := new(NewPullRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"number":1}`)
+ })
+
+ pull, _, err := client.PullRequests.Create(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("PullRequests.Create returned error: %v", err)
+ }
+
+ want := &PullRequest{Number: Int(1)}
+ if !reflect.DeepEqual(pull, want) {
+ t.Errorf("PullRequests.Create returned %+v, want %+v", pull, want)
+ }
+}
+
+func TestPullRequestsService_Create_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.Create(context.Background(), "%", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_Edit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ tests := []struct {
+ input *PullRequest
+ sendResponse string
+
+ wantUpdate string
+ want *PullRequest
+ }{
+ {
+ input: &PullRequest{Title: String("t")},
+ sendResponse: `{"number":1}`,
+ wantUpdate: `{"title":"t"}`,
+ want: &PullRequest{Number: Int(1)},
+ },
+ {
+ // base update
+ input: &PullRequest{Base: &PullRequestBranch{Ref: String("master")}},
+ sendResponse: `{"number":1,"base":{"ref":"master"}}`,
+ wantUpdate: `{"base":"master"}`,
+ want: &PullRequest{
+ Number: Int(1),
+ Base: &PullRequestBranch{Ref: String("master")},
+ },
+ },
+ }
+
+ for i, tt := range tests {
+ madeRequest := false
+ acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+ mux.HandleFunc(fmt.Sprintf("/repos/o/r/pulls/%v", i), func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ testBody(t, r, tt.wantUpdate+"\n")
+ io.WriteString(w, tt.sendResponse)
+ madeRequest = true
+ })
+
+ pull, _, err := client.PullRequests.Edit(context.Background(), "o", "r", i, tt.input)
+ if err != nil {
+ t.Errorf("%d: PullRequests.Edit returned error: %v", i, err)
+ }
+
+ if !reflect.DeepEqual(pull, tt.want) {
+ t.Errorf("%d: PullRequests.Edit returned %+v, want %+v", i, pull, tt.want)
+ }
+
+ if !madeRequest {
+ t.Errorf("%d: PullRequest.Edit did not make the expected request", i)
+ }
+ }
+}
+
+func TestPullRequestsService_Edit_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.PullRequests.Edit(context.Background(), "%", "r", 1, &PullRequest{})
+ testURLParseError(t, err)
+}
+
+func TestPullRequestsService_ListCommits(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/commits", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeGitSigningPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `
+ [
+ {
+ "sha": "3",
+ "parents": [
+ {
+ "sha": "2"
+ }
+ ]
+ },
+ {
+ "sha": "2",
+ "parents": [
+ {
+ "sha": "1"
+ }
+ ]
+ }
+ ]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ commits, _, err := client.PullRequests.ListCommits(context.Background(), "o", "r", 1, opt)
+ if err != nil {
+ t.Errorf("PullRequests.ListCommits returned error: %v", err)
+ }
+
+ want := []*RepositoryCommit{
+ {
+ SHA: String("3"),
+ Parents: []Commit{
+ {
+ SHA: String("2"),
+ },
+ },
+ },
+ {
+ SHA: String("2"),
+ Parents: []Commit{
+ {
+ SHA: String("1"),
+ },
+ },
+ },
+ }
+ if !reflect.DeepEqual(commits, want) {
+ t.Errorf("PullRequests.ListCommits returned %+v, want %+v", commits, want)
+ }
+}
+
+func TestPullRequestsService_ListFiles(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/files", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `
+ [
+ {
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
+ "filename": "file1.txt",
+ "status": "added",
+ "additions": 103,
+ "deletions": 21,
+ "changes": 124,
+ "patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"
+ },
+ {
+ "sha": "f61aebed695e2e4193db5e6dcb09b5b57875f334",
+ "filename": "file2.txt",
+ "status": "modified",
+ "additions": 5,
+ "deletions": 3,
+ "changes": 103,
+ "patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"
+ }
+ ]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ commitFiles, _, err := client.PullRequests.ListFiles(context.Background(), "o", "r", 1, opt)
+ if err != nil {
+ t.Errorf("PullRequests.ListFiles returned error: %v", err)
+ }
+
+ want := []*CommitFile{
+ {
+ SHA: String("6dcb09b5b57875f334f61aebed695e2e4193db5e"),
+ Filename: String("file1.txt"),
+ Additions: Int(103),
+ Deletions: Int(21),
+ Changes: Int(124),
+ Status: String("added"),
+ Patch: String("@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"),
+ },
+ {
+ SHA: String("f61aebed695e2e4193db5e6dcb09b5b57875f334"),
+ Filename: String("file2.txt"),
+ Additions: Int(5),
+ Deletions: Int(3),
+ Changes: Int(103),
+ Status: String("modified"),
+ Patch: String("@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"),
+ },
+ }
+
+ if !reflect.DeepEqual(commitFiles, want) {
+ t.Errorf("PullRequests.ListFiles returned %+v, want %+v", commitFiles, want)
+ }
+}
+
+func TestPullRequestsService_IsMerged(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/merge", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ isMerged, _, err := client.PullRequests.IsMerged(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("PullRequests.IsMerged returned error: %v", err)
+ }
+
+ want := true
+ if !reflect.DeepEqual(isMerged, want) {
+ t.Errorf("PullRequests.IsMerged returned %+v, want %+v", isMerged, want)
+ }
+}
+
+func TestPullRequestsService_Merge(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/1/merge", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ fmt.Fprint(w, `
+ {
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
+ "merged": true,
+ "message": "Pull Request successfully merged"
+ }`)
+ })
+
+ options := &PullRequestOptions{MergeMethod: "rebase"}
+ merge, _, err := client.PullRequests.Merge(context.Background(), "o", "r", 1, "merging pull request", options)
+ if err != nil {
+ t.Errorf("PullRequests.Merge returned error: %v", err)
+ }
+
+ want := &PullRequestMergeResult{
+ SHA: String("6dcb09b5b57875f334f61aebed695e2e4193db5e"),
+ Merged: Bool(true),
+ Message: String("Pull Request successfully merged"),
+ }
+ if !reflect.DeepEqual(merge, want) {
+ t.Errorf("PullRequests.Merge returned %+v, want %+v", merge, want)
+ }
+}
+
+// Test that different merge options produce expected PUT requests. See issue https://github.com/google/go-github/issues/500.
+func TestPullRequestsService_Merge_options(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ tests := []struct {
+ options *PullRequestOptions
+ wantBody string
+ }{
+ {
+ options: nil,
+ wantBody: `{"commit_message":"merging pull request"}`,
+ },
+ {
+ options: &PullRequestOptions{},
+ wantBody: `{"commit_message":"merging pull request"}`,
+ },
+ {
+ options: &PullRequestOptions{MergeMethod: "rebase"},
+ wantBody: `{"commit_message":"merging pull request","merge_method":"rebase"}`,
+ },
+ {
+ options: &PullRequestOptions{SHA: "6dcb09b5b57875f334f61aebed695e2e4193db5e"},
+ wantBody: `{"commit_message":"merging pull request","sha":"6dcb09b5b57875f334f61aebed695e2e4193db5e"}`,
+ },
+ {
+ options: &PullRequestOptions{
+ CommitTitle: "Extra detail",
+ SHA: "6dcb09b5b57875f334f61aebed695e2e4193db5e",
+ MergeMethod: "squash",
+ },
+ wantBody: `{"commit_message":"merging pull request","commit_title":"Extra detail","merge_method":"squash","sha":"6dcb09b5b57875f334f61aebed695e2e4193db5e"}`,
+ },
+ }
+
+ for i, test := range tests {
+ madeRequest := false
+ mux.HandleFunc(fmt.Sprintf("/repos/o/r/pulls/%d/merge", i), func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ testBody(t, r, test.wantBody+"\n")
+ madeRequest = true
+ })
+ _, _, _ = client.PullRequests.Merge(context.Background(), "o", "r", i, "merging pull request", test.options)
+ if !madeRequest {
+ t.Errorf("%d: PullRequests.Merge(%#v): expected request was not made", i, test.options)
+ }
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/reactions.go b/vendor/github.com/google/go-github/github/reactions.go
new file mode 100644
index 0000000..ddc055c
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/reactions.go
@@ -0,0 +1,375 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+)
+
+// ReactionsService provides access to the reactions-related functions in the
+// GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/
+type ReactionsService service
+
+// Reaction represents a GitHub reaction.
+type Reaction struct {
+ // ID is the Reaction ID.
+ ID *int64 `json:"id,omitempty"`
+ User *User `json:"user,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ // Content is the type of reaction.
+ // Possible values are:
+ // "+1", "-1", "laugh", "confused", "heart", "hooray".
+ Content *string `json:"content,omitempty"`
+}
+
+// Reactions represents a summary of GitHub reactions.
+type Reactions struct {
+ TotalCount *int `json:"total_count,omitempty"`
+ PlusOne *int `json:"+1,omitempty"`
+ MinusOne *int `json:"-1,omitempty"`
+ Laugh *int `json:"laugh,omitempty"`
+ Confused *int `json:"confused,omitempty"`
+ Heart *int `json:"heart,omitempty"`
+ Hooray *int `json:"hooray,omitempty"`
+ URL *string `json:"url,omitempty"`
+}
+
+func (r Reaction) String() string {
+ return Stringify(r)
+}
+
+// ListCommentReactions lists the reactions for a commit comment.
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment
+func (s *ReactionsService) ListCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id)
+ 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ var m []*Reaction
+ resp, err := s.client.Do(ctx, req, &m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// CreateCommentReaction creates a reaction for a commit comment.
+// Note that if you have already created a reaction of type content, the
+// previously created reaction will be returned with Status: 200 OK.
+// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-commit-comment
+func (s ReactionsService) CreateCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id)
+
+ body := &Reaction{Content: String(content)}
+ req, err := s.client.NewRequest("POST", u, body)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ m := &Reaction{}
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// ListIssueReactions lists the reactions for an issue.
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue
+func (s *ReactionsService) ListIssueReactions(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*Reaction, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number)
+ 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ var m []*Reaction
+ resp, err := s.client.Do(ctx, req, &m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// CreateIssueReaction creates a reaction for an issue.
+// Note that if you have already created a reaction of type content, the
+// previously created reaction will be returned with Status: 200 OK.
+// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue
+func (s ReactionsService) CreateIssueReaction(ctx context.Context, owner, repo string, number int, content string) (*Reaction, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number)
+
+ body := &Reaction{Content: String(content)}
+ req, err := s.client.NewRequest("POST", u, body)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ m := &Reaction{}
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// ListIssueCommentReactions lists the reactions for an issue comment.
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment
+func (s *ReactionsService) ListIssueCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id)
+ 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ var m []*Reaction
+ resp, err := s.client.Do(ctx, req, &m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// CreateIssueCommentReaction creates a reaction for an issue comment.
+// Note that if you have already created a reaction of type content, the
+// previously created reaction will be returned with Status: 200 OK.
+// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment
+func (s ReactionsService) CreateIssueCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id)
+
+ body := &Reaction{Content: String(content)}
+ req, err := s.client.NewRequest("POST", u, body)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ m := &Reaction{}
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// ListPullRequestCommentReactions lists the reactions for a pull request review comment.
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment
+func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id)
+ 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ var m []*Reaction
+ resp, err := s.client.Do(ctx, req, &m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// CreatePullRequestCommentReaction creates a reaction for a pull request review comment.
+// Note that if you have already created a reaction of type content, the
+// previously created reaction will be returned with Status: 200 OK.
+// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment
+func (s ReactionsService) CreatePullRequestCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id)
+
+ body := &Reaction{Content: String(content)}
+ req, err := s.client.NewRequest("POST", u, body)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ m := &Reaction{}
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// ListTeamDiscussionReactions lists the reactions for a team discussion.
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-team-discussion
+func (s *ReactionsService) ListTeamDiscussionReactions(ctx context.Context, teamID int64, discussionNumber int, opt *ListOptions) ([]*Reaction, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ var m []*Reaction
+ resp, err := s.client.Do(ctx, req, &m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// CreateTeamDiscussionReaction creates a reaction for a team discussion.
+// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-team-discussion
+func (s *ReactionsService) CreateTeamDiscussionReaction(ctx context.Context, teamID int64, discussionNumber int, content string) (*Reaction, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber)
+
+ body := &Reaction{Content: String(content)}
+ req, err := s.client.NewRequest("POST", u, body)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ m := &Reaction{}
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// ListTeamDiscussionCommentReactions lists the reactions for a team discussion comment.
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-team-discussion-comment
+func (s *ReactionsService) ListTeamDiscussionCommentReactions(ctx context.Context, teamID int64, discussionNumber, commentNumber int, opt *ListOptions) ([]*Reaction, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ var m []*Reaction
+ resp, err := s.client.Do(ctx, req, &m)
+
+ return m, resp, nil
+}
+
+// CreateTeamDiscussionCommentReaction creates a reaction for a team discussion comment.
+// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
+//
+// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-team-discussion-comment
+func (s *ReactionsService) CreateTeamDiscussionCommentReaction(ctx context.Context, teamID int64, discussionNumber, commentNumber int, content string) (*Reaction, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber)
+
+ body := &Reaction{Content: String(content)}
+ req, err := s.client.NewRequest("POST", u, body)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ m := &Reaction{}
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return m, resp, nil
+}
+
+// DeleteReaction deletes a reaction.
+//
+// GitHub API docs: https://developer.github.com/v3/reaction/reactions/#delete-a-reaction-archive
+func (s *ReactionsService) DeleteReaction(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("reactions/%v", id)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/reactions_test.go b/vendor/github.com/google/go-github/github/reactions_test.go
new file mode 100644
index 0000000..e1baec3
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/reactions_test.go
@@ -0,0 +1,293 @@
+// Copyright 2016 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 (
+ "context"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestReactionsService_ListCommentReactions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`))
+ })
+
+ got, _, err := client.Reactions.ListCommentReactions(context.Background(), "o", "r", 1, nil)
+ if err != nil {
+ t.Errorf("ListCommentReactions returned error: %v", err)
+ }
+ want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("ListCommentReactions = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionsService_CreateCommentReaction(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`))
+ })
+
+ got, _, err := client.Reactions.CreateCommentReaction(context.Background(), "o", "r", 1, "+1")
+ if err != nil {
+ t.Errorf("CreateCommentReaction returned error: %v", err)
+ }
+ want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("CreateCommentReaction = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionsService_ListIssueReactions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`))
+ })
+
+ got, _, err := client.Reactions.ListIssueReactions(context.Background(), "o", "r", 1, nil)
+ if err != nil {
+ t.Errorf("ListIssueReactions returned error: %v", err)
+ }
+ want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("ListIssueReactions = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionsService_CreateIssueReaction(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/1/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`))
+ })
+
+ got, _, err := client.Reactions.CreateIssueReaction(context.Background(), "o", "r", 1, "+1")
+ if err != nil {
+ t.Errorf("CreateIssueReaction returned error: %v", err)
+ }
+ want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("CreateIssueReaction = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionsService_ListIssueCommentReactions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`))
+ })
+
+ got, _, err := client.Reactions.ListIssueCommentReactions(context.Background(), "o", "r", 1, nil)
+ if err != nil {
+ t.Errorf("ListIssueCommentReactions returned error: %v", err)
+ }
+ want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("ListIssueCommentReactions = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionsService_CreateIssueCommentReaction(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/issues/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`))
+ })
+
+ got, _, err := client.Reactions.CreateIssueCommentReaction(context.Background(), "o", "r", 1, "+1")
+ if err != nil {
+ t.Errorf("CreateIssueCommentReaction returned error: %v", err)
+ }
+ want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("CreateIssueCommentReaction = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionsService_ListPullRequestCommentReactions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`))
+ })
+
+ got, _, err := client.Reactions.ListPullRequestCommentReactions(context.Background(), "o", "r", 1, nil)
+ if err != nil {
+ t.Errorf("ListPullRequestCommentReactions returned error: %v", err)
+ }
+ want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("ListPullRequestCommentReactions = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionsService_CreatePullRequestCommentReaction(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pulls/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`))
+ })
+
+ got, _, err := client.Reactions.CreatePullRequestCommentReaction(context.Background(), "o", "r", 1, "+1")
+ if err != nil {
+ t.Errorf("CreatePullRequestCommentReaction returned error: %v", err)
+ }
+ want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("CreatePullRequestCommentReaction = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionsService_ListTeamDiscussionReactions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/discussions/2/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`))
+ })
+
+ got, _, err := client.Reactions.ListTeamDiscussionReactions(context.Background(), 1, 2, nil)
+ if err != nil {
+ t.Errorf("ListTeamDiscussionReactions returned error: %v", err)
+ }
+ want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("ListTeamDiscussionReactions = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionsService_CreateTeamDiscussionReaction(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/discussions/2/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`))
+ })
+
+ got, _, err := client.Reactions.CreateTeamDiscussionReaction(context.Background(), 1, 2, "+1")
+ if err != nil {
+ t.Errorf("CreateTeamDiscussionReaction returned error: %v", err)
+ }
+ want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("CreateTeamDiscussionReaction = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionService_ListTeamDiscussionCommentReactions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/discussions/2/comments/3/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`))
+ })
+
+ got, _, err := client.Reactions.ListTeamDiscussionCommentReactions(context.Background(), 1, 2, 3, nil)
+ if err != nil {
+ t.Errorf("ListTeamDiscussionCommentReactions returned error: %v", err)
+ }
+ want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("ListTeamDiscussionCommentReactions = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionService_CreateTeamDiscussionCommentReaction(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/discussions/2/comments/3/reactions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`))
+ })
+
+ got, _, err := client.Reactions.CreateTeamDiscussionCommentReaction(context.Background(), 1, 2, 3, "+1")
+ if err != nil {
+ t.Errorf("CreateTeamDiscussionCommentReaction returned error: %v", err)
+ }
+ want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("CreateTeamDiscussionCommentReaction = %+v, want %+v", got, want)
+ }
+}
+
+func TestReactionsService_DeleteReaction(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/reactions/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ if _, err := client.Reactions.DeleteReaction(context.Background(), 1); err != nil {
+ t.Errorf("DeleteReaction returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos.go b/vendor/github.com/google/go-github/github/repos.go
new file mode 100644
index 0000000..fe05272
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos.go
@@ -0,0 +1,1082 @@
+// 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 (
+ "context"
+ "fmt"
+ "strings"
+)
+
+// RepositoriesService handles communication with the repository related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/
+type RepositoriesService service
+
+// Repository represents a GitHub repository.
+type Repository struct {
+ ID *int64 `json:"id,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ Owner *User `json:"owner,omitempty"`
+ Name *string `json:"name,omitempty"`
+ FullName *string `json:"full_name,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Homepage *string `json:"homepage,omitempty"`
+ CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"`
+ DefaultBranch *string `json:"default_branch,omitempty"`
+ MasterBranch *string `json:"master_branch,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ PushedAt *Timestamp `json:"pushed_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ CloneURL *string `json:"clone_url,omitempty"`
+ GitURL *string `json:"git_url,omitempty"`
+ MirrorURL *string `json:"mirror_url,omitempty"`
+ SSHURL *string `json:"ssh_url,omitempty"`
+ SVNURL *string `json:"svn_url,omitempty"`
+ Language *string `json:"language,omitempty"`
+ Fork *bool `json:"fork,omitempty"`
+ ForksCount *int `json:"forks_count,omitempty"`
+ NetworkCount *int `json:"network_count,omitempty"`
+ OpenIssuesCount *int `json:"open_issues_count,omitempty"`
+ StargazersCount *int `json:"stargazers_count,omitempty"`
+ SubscribersCount *int `json:"subscribers_count,omitempty"`
+ WatchersCount *int `json:"watchers_count,omitempty"`
+ Size *int `json:"size,omitempty"`
+ AutoInit *bool `json:"auto_init,omitempty"`
+ Parent *Repository `json:"parent,omitempty"`
+ Source *Repository `json:"source,omitempty"`
+ Organization *Organization `json:"organization,omitempty"`
+ Permissions *map[string]bool `json:"permissions,omitempty"`
+ AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"`
+ AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"`
+ AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"`
+ Topics []string `json:"topics,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,omitempty"`
+ HasIssues *bool `json:"has_issues,omitempty"`
+ HasWiki *bool `json:"has_wiki,omitempty"`
+ HasPages *bool `json:"has_pages,omitempty"`
+ HasProjects *bool `json:"has_projects,omitempty"`
+ HasDownloads *bool `json:"has_downloads,omitempty"`
+ LicenseTemplate *string `json:"license_template,omitempty"`
+ GitignoreTemplate *string `json:"gitignore_template,omitempty"`
+ Archived *bool `json:"archived,omitempty"`
+
+ // Creating an organization repository. Required for non-owners.
+ TeamID *int64 `json:"team_id,omitempty"`
+
+ // API URLs
+ URL *string `json:"url,omitempty"`
+ ArchiveURL *string `json:"archive_url,omitempty"`
+ AssigneesURL *string `json:"assignees_url,omitempty"`
+ BlobsURL *string `json:"blobs_url,omitempty"`
+ BranchesURL *string `json:"branches_url,omitempty"`
+ CollaboratorsURL *string `json:"collaborators_url,omitempty"`
+ CommentsURL *string `json:"comments_url,omitempty"`
+ CommitsURL *string `json:"commits_url,omitempty"`
+ CompareURL *string `json:"compare_url,omitempty"`
+ ContentsURL *string `json:"contents_url,omitempty"`
+ ContributorsURL *string `json:"contributors_url,omitempty"`
+ DeploymentsURL *string `json:"deployments_url,omitempty"`
+ DownloadsURL *string `json:"downloads_url,omitempty"`
+ EventsURL *string `json:"events_url,omitempty"`
+ ForksURL *string `json:"forks_url,omitempty"`
+ GitCommitsURL *string `json:"git_commits_url,omitempty"`
+ GitRefsURL *string `json:"git_refs_url,omitempty"`
+ GitTagsURL *string `json:"git_tags_url,omitempty"`
+ HooksURL *string `json:"hooks_url,omitempty"`
+ IssueCommentURL *string `json:"issue_comment_url,omitempty"`
+ IssueEventsURL *string `json:"issue_events_url,omitempty"`
+ IssuesURL *string `json:"issues_url,omitempty"`
+ KeysURL *string `json:"keys_url,omitempty"`
+ LabelsURL *string `json:"labels_url,omitempty"`
+ LanguagesURL *string `json:"languages_url,omitempty"`
+ MergesURL *string `json:"merges_url,omitempty"`
+ MilestonesURL *string `json:"milestones_url,omitempty"`
+ NotificationsURL *string `json:"notifications_url,omitempty"`
+ PullsURL *string `json:"pulls_url,omitempty"`
+ ReleasesURL *string `json:"releases_url,omitempty"`
+ StargazersURL *string `json:"stargazers_url,omitempty"`
+ StatusesURL *string `json:"statuses_url,omitempty"`
+ SubscribersURL *string `json:"subscribers_url,omitempty"`
+ SubscriptionURL *string `json:"subscription_url,omitempty"`
+ TagsURL *string `json:"tags_url,omitempty"`
+ TreesURL *string `json:"trees_url,omitempty"`
+ TeamsURL *string `json:"teams_url,omitempty"`
+
+ // TextMatches is only populated from search results that request text matches
+ // See: search.go and https://developer.github.com/v3/search/#text-match-metadata
+ TextMatches []TextMatch `json:"text_matches,omitempty"`
+}
+
+func (r Repository) String() string {
+ return Stringify(r)
+}
+
+// RepositoryListOptions specifies the optional parameters to the
+// RepositoriesService.List method.
+type RepositoryListOptions struct {
+ // Visibility of repositories to list. Can be one of all, public, or private.
+ // Default: all
+ Visibility string `url:"visibility,omitempty"`
+
+ // List repos of given affiliation[s].
+ // Comma-separated list of values. Can include:
+ // * owner: Repositories that are owned by the authenticated user.
+ // * collaborator: Repositories that the user has been added to as a
+ // collaborator.
+ // * organization_member: Repositories that the user has access to through
+ // being a member of an organization. This includes every repository on
+ // every team that the user is on.
+ // Default: owner,collaborator,organization_member
+ Affiliation string `url:"affiliation,omitempty"`
+
+ // Type of repositories to list.
+ // Can be one of all, owner, public, private, member. Default: all
+ // Will cause a 422 error if used in the same request as visibility or
+ // affiliation.
+ Type string `url:"type,omitempty"`
+
+ // How to sort the repository list. Can be one of created, updated, pushed,
+ // full_name. Default: full_name
+ Sort string `url:"sort,omitempty"`
+
+ // Direction in which to sort repositories. Can be one of asc or desc.
+ // Default: when using full_name: asc; otherwise desc
+ Direction string `url:"direction,omitempty"`
+
+ ListOptions
+}
+
+// List the repositories for a user. Passing the empty string will list
+// repositories for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#list-user-repositories
+func (s *RepositoriesService) List(ctx context.Context, user string, opt *RepositoryListOptions) ([]*Repository, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v/repos", user)
+ } else {
+ u = "user/repos"
+ }
+ 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview}
+ req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+ var repos []*Repository
+ resp, err := s.client.Do(ctx, req, &repos)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return repos, resp, nil
+}
+
+// RepositoryListByOrgOptions specifies the optional parameters to the
+// RepositoriesService.ListByOrg method.
+type RepositoryListByOrgOptions struct {
+ // Type of repositories to list. Possible values are: all, public, private,
+ // forks, sources, member. Default is "all".
+ Type string `url:"type,omitempty"`
+
+ ListOptions
+}
+
+// ListByOrg lists the repositories for an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#list-organization-repositories
+func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opt *RepositoryListByOrgOptions) ([]*Repository, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/repos", 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview}
+ req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+ var repos []*Repository
+ resp, err := s.client.Do(ctx, req, &repos)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return repos, resp, nil
+}
+
+// RepositoryListAllOptions specifies the optional parameters to the
+// RepositoriesService.ListAll method.
+type RepositoryListAllOptions struct {
+ // ID of the last repository seen
+ Since int64 `url:"since,omitempty"`
+}
+
+// ListAll lists all GitHub repositories in the order that they were created.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#list-all-public-repositories
+func (s *RepositoriesService) ListAll(ctx context.Context, opt *RepositoryListAllOptions) ([]*Repository, *Response, error) {
+ u, err := addOptions("repositories", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var repos []*Repository
+ resp, err := s.client.Do(ctx, req, &repos)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return repos, resp, nil
+}
+
+// Create a new repository. If an organization is specified, the new
+// repository will be created under that org. If the empty string is
+// specified, it will be created for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#create
+func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) {
+ var u string
+ if org != "" {
+ u = fmt.Sprintf("orgs/%v/repos", org)
+ } else {
+ u = "user/repos"
+ }
+
+ req, err := s.client.NewRequest("POST", u, repo)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(Repository)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// Get fetches a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#get
+func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v", owner, repo)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ 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
+ acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview}
+ req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+ repository := new(Repository)
+ resp, err := s.client.Do(ctx, req, repository)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return repository, resp, nil
+}
+
+// GetCodeOfConduct gets the contents of a repository's code of conduct.
+//
+// GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#get-the-contents-of-a-repositorys-code-of-conduct
+func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/community/code_of_conduct", owner, repo)
+ 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", mediaTypeCodesOfConductPreview)
+
+ coc := new(CodeOfConduct)
+ resp, err := s.client.Do(ctx, req, coc)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return coc, resp, nil
+}
+
+// GetByID fetches a repository.
+//
+// Note: GetByID uses the undocumented GitHub API endpoint /repositories/:id.
+func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repository, *Response, error) {
+ u := fmt.Sprintf("repositories/%d", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ repository := new(Repository)
+ resp, err := s.client.Do(ctx, req, repository)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return repository, resp, nil
+}
+
+// Edit updates a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#edit
+func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v", owner, repo)
+ req, err := s.client.NewRequest("PATCH", u, repository)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(Repository)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// Delete a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#delete-a-repository
+func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v", owner, repo)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// Contributor represents a repository contributor
+type Contributor struct {
+ Login *string `json:"login,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+ AvatarURL *string `json:"avatar_url,omitempty"`
+ GravatarID *string `json:"gravatar_id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ FollowersURL *string `json:"followers_url,omitempty"`
+ FollowingURL *string `json:"following_url,omitempty"`
+ GistsURL *string `json:"gists_url,omitempty"`
+ StarredURL *string `json:"starred_url,omitempty"`
+ SubscriptionsURL *string `json:"subscriptions_url,omitempty"`
+ OrganizationsURL *string `json:"organizations_url,omitempty"`
+ ReposURL *string `json:"repos_url,omitempty"`
+ EventsURL *string `json:"events_url,omitempty"`
+ ReceivedEventsURL *string `json:"received_events_url,omitempty"`
+ Type *string `json:"type,omitempty"`
+ SiteAdmin *bool `json:"site_admin,omitempty"`
+ Contributions *int `json:"contributions,omitempty"`
+}
+
+// ListContributorsOptions specifies the optional parameters to the
+// RepositoriesService.ListContributors method.
+type ListContributorsOptions struct {
+ // Include anonymous contributors in results or not
+ Anon string `url:"anon,omitempty"`
+
+ ListOptions
+}
+
+// ListContributors lists contributors for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#list-contributors
+func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opt *ListContributorsOptions) ([]*Contributor, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository)
+ 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
+ }
+
+ var contributor []*Contributor
+ resp, err := s.client.Do(ctx, req, &contributor)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return contributor, resp, nil
+}
+
+// ListLanguages lists languages for the specified repository. The returned map
+// specifies the languages and the number of bytes of code written in that
+// language. For example:
+//
+// {
+// "C": 78769,
+// "Python": 7769
+// }
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#list-languages
+func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/languages", owner, repo)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ languages := make(map[string]int)
+ resp, err := s.client.Do(ctx, req, &languages)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return languages, resp, nil
+}
+
+// ListTeams lists the teams for the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#list-teams
+func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Team, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/teams", owner, repo)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
+
+ var teams []*Team
+ resp, err := s.client.Do(ctx, req, &teams)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return teams, resp, nil
+}
+
+// RepositoryTag represents a repository tag.
+type RepositoryTag struct {
+ Name *string `json:"name,omitempty"`
+ Commit *Commit `json:"commit,omitempty"`
+ ZipballURL *string `json:"zipball_url,omitempty"`
+ TarballURL *string `json:"tarball_url,omitempty"`
+}
+
+// ListTags lists tags for the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#list-tags
+func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*RepositoryTag, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/tags", owner, repo)
+ 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
+ }
+
+ var tags []*RepositoryTag
+ resp, err := s.client.Do(ctx, req, &tags)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return tags, resp, nil
+}
+
+// Branch represents a repository branch
+type Branch struct {
+ Name *string `json:"name,omitempty"`
+ Commit *RepositoryCommit `json:"commit,omitempty"`
+ Protected *bool `json:"protected,omitempty"`
+}
+
+// Protection represents a repository branch's protection.
+type Protection struct {
+ RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"`
+ RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"`
+ EnforceAdmins *AdminEnforcement `json:"enforce_admins"`
+ Restrictions *BranchRestrictions `json:"restrictions"`
+}
+
+// ProtectionRequest represents a request to create/edit a branch's protection.
+type ProtectionRequest struct {
+ RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"`
+ RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"`
+ EnforceAdmins bool `json:"enforce_admins"`
+ Restrictions *BranchRestrictionsRequest `json:"restrictions"`
+}
+
+// RequiredStatusChecks represents the protection status of a individual branch.
+type RequiredStatusChecks struct {
+ // Require branches to be up to date before merging. (Required.)
+ Strict bool `json:"strict"`
+ // The list of status checks to require in order to merge into this
+ // branch. (Required; use []string{} instead of nil for empty list.)
+ Contexts []string `json:"contexts"`
+}
+
+// RequiredStatusChecksRequest represents a request to edit a protected branch's status checks.
+type RequiredStatusChecksRequest struct {
+ Strict *bool `json:"strict,omitempty"`
+ Contexts []string `json:"contexts,omitempty"`
+}
+
+// PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch.
+type PullRequestReviewsEnforcement struct {
+ // Specifies which users and teams can dismiss pull request reviews.
+ DismissalRestrictions DismissalRestrictions `json:"dismissal_restrictions"`
+ // Specifies if approved reviews are dismissed automatically, when a new commit is pushed.
+ DismissStaleReviews bool `json:"dismiss_stale_reviews"`
+ // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner.
+ RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"`
+ // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged.
+ // Valid values are 1-6.
+ RequiredApprovingReviewCount int `json:"required_approving_review_count"`
+}
+
+// PullRequestReviewsEnforcementRequest represents request to set the pull request review
+// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcement above
+// because the request structure is different from the response structure.
+type PullRequestReviewsEnforcementRequest struct {
+ // Specifies which users and teams should be allowed to dismiss pull request reviews.
+ // User and team dismissal restrictions are only available for
+ // organization-owned repositories. Must be nil for personal repositories.
+ DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"`
+ // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. (Required)
+ DismissStaleReviews bool `json:"dismiss_stale_reviews"`
+ // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner.
+ RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"`
+ // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged.
+ // Valid values are 1-6.
+ RequiredApprovingReviewCount int `json:"required_approving_review_count"`
+}
+
+// PullRequestReviewsEnforcementUpdate represents request to patch the pull request review
+// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcementRequest above
+// because the patch request does not require all fields to be initialized.
+type PullRequestReviewsEnforcementUpdate struct {
+ // Specifies which users and teams can dismiss pull request reviews. Can be omitted.
+ DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"`
+ // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. Can be omitted.
+ DismissStaleReviews *bool `json:"dismiss_stale_reviews,omitempty"`
+ // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner.
+ RequireCodeOwnerReviews bool `json:"require_code_owner_reviews,omitempty"`
+ // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged.
+ // Valid values are 1 - 6.
+ RequiredApprovingReviewCount int `json:"required_approving_review_count"`
+}
+
+// AdminEnforcement represents the configuration to enforce required status checks for repository administrators.
+type AdminEnforcement struct {
+ URL *string `json:"url,omitempty"`
+ Enabled bool `json:"enabled"`
+}
+
+// BranchRestrictions represents the restriction that only certain users or
+// teams may push to a branch.
+type BranchRestrictions struct {
+ // The list of user logins with push access.
+ Users []*User `json:"users"`
+ // The list of team slugs with push access.
+ Teams []*Team `json:"teams"`
+}
+
+// BranchRestrictionsRequest represents the request to create/edit the
+// restriction that only certain users or teams may push to a branch. It is
+// separate from BranchRestrictions above because the request structure is
+// different from the response structure.
+type BranchRestrictionsRequest struct {
+ // The list of user logins with push access. (Required; use []string{} instead of nil for empty list.)
+ Users []string `json:"users"`
+ // The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.)
+ Teams []string `json:"teams"`
+}
+
+// DismissalRestrictions specifies which users and teams can dismiss pull request reviews.
+type DismissalRestrictions struct {
+ // The list of users who can dimiss pull request reviews.
+ Users []*User `json:"users"`
+ // The list of teams which can dismiss pull request reviews.
+ Teams []*Team `json:"teams"`
+}
+
+// DismissalRestrictionsRequest represents the request to create/edit the
+// restriction to allows only specific users or teams to dimiss pull request reviews. It is
+// separate from DismissalRestrictions above because the request structure is
+// different from the response structure.
+// Note: Both Users and Teams must be nil, or both must be non-nil.
+type DismissalRestrictionsRequest struct {
+ // The list of user logins who can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.)
+ Users *[]string `json:"users,omitempty"`
+ // The list of team slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.)
+ Teams *[]string `json:"teams,omitempty"`
+}
+
+// ListBranches lists branches for the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#list-branches
+func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Branch, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
+
+ var branches []*Branch
+ resp, err := s.client.Do(ctx, req, &branches)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return branches, resp, nil
+}
+
+// GetBranch gets the specified branch for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#get-branch
+func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string) (*Branch, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch)
+ 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", mediaTypeRequiredApprovingReviewsPreview)
+
+ b := new(Branch)
+ resp, err := s.client.Do(ctx, req, b)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return b, resp, nil
+}
+
+// GetBranchProtection gets the protection of a given branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-branch-protection
+func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch)
+ 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", mediaTypeRequiredApprovingReviewsPreview)
+
+ p := new(Protection)
+ resp, err := s.client.Do(ctx, req, p)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return p, resp, nil
+}
+
+// GetRequiredStatusChecks gets the required status checks for a given protected branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-required-status-checks-of-protected-branch
+func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch)
+ 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", mediaTypeRequiredApprovingReviewsPreview)
+
+ p := new(RequiredStatusChecks)
+ resp, err := s.client.Do(ctx, req, p)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return p, resp, nil
+}
+
+// ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#list-required-status-checks-contexts-of-protected-branch
+func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch)
+ 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", mediaTypeRequiredApprovingReviewsPreview)
+
+ resp, err = s.client.Do(ctx, req, &contexts)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return contexts, resp, nil
+}
+
+// UpdateBranchProtection updates the protection of a given branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-branch-protection
+func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch)
+ req, err := s.client.NewRequest("PUT", u, preq)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
+
+ p := new(Protection)
+ resp, err := s.client.Do(ctx, req, p)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return p, resp, nil
+}
+
+// RemoveBranchProtection removes the protection of a given branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-branch-protection
+func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// UpdateRequiredStatusChecks updates the required status checks for a given protected branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch
+func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch)
+ req, err := s.client.NewRequest("PATCH", u, sreq)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ sc := new(RequiredStatusChecks)
+ resp, err := s.client.Do(ctx, req, sc)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return sc, resp, nil
+}
+
+// License gets the contents of a repository's license if one is detected.
+//
+// GitHub API docs: https://developer.github.com/v3/licenses/#get-the-contents-of-a-repositorys-license
+func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/license", owner, repo)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := &RepositoryLicense{}
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-pull-request-review-enforcement-of-protected-branch
+func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
+ 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", mediaTypeRequiredApprovingReviewsPreview)
+
+ r := new(PullRequestReviewsEnforcement)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch.
+// It requires admin access and branch protection to be enabled.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch
+func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
+ req, err := s.client.NewRequest("PATCH", u, patch)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
+
+ r := new(PullRequestReviewsEnforcement)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, err
+}
+
+// DisableDismissalRestrictions disables dismissal restrictions of a protected branch.
+// It requires admin access and branch protection to be enabled.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch
+func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
+
+ data := struct {
+ R []interface{} `json:"dismissal_restrictions"`
+ }{[]interface{}{}}
+
+ req, err := s.client.NewRequest("PATCH", u, data)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
+
+ r := new(PullRequestReviewsEnforcement)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, err
+}
+
+// RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-pull-request-review-enforcement-of-protected-branch
+func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// GetAdminEnforcement gets admin enforcement information of a protected branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-admin-enforcement-of-protected-branch
+func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
+ 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", mediaTypeRequiredApprovingReviewsPreview)
+
+ r := new(AdminEnforcement)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
+
+// AddAdminEnforcement adds admin enforcement to a protected branch.
+// It requires admin access and branch protection to be enabled.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#add-admin-enforcement-of-protected-branch
+func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
+ req, err := s.client.NewRequest("POST", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
+
+ r := new(AdminEnforcement)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, err
+}
+
+// RemoveAdminEnforcement removes admin enforcement from a protected branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-admin-enforcement-of-protected-branch
+func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// repositoryTopics represents a collection of repository topics.
+type repositoryTopics struct {
+ Names []string `json:"names"`
+}
+
+// ListAllTopics lists topics for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#list-all-topics-for-a-repository
+func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/topics", owner, repo)
+ 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", mediaTypeTopicsPreview)
+
+ topics := new(repositoryTopics)
+ resp, err := s.client.Do(ctx, req, topics)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return topics.Names, resp, nil
+}
+
+// ReplaceAllTopics replaces topics for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#replace-all-topics-for-a-repository
+func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/topics", owner, repo)
+ t := &repositoryTopics{
+ Names: topics,
+ }
+ if t.Names == nil {
+ t.Names = []string{}
+ }
+ req, err := s.client.NewRequest("PUT", u, t)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeTopicsPreview)
+
+ t = new(repositoryTopics)
+ resp, err := s.client.Do(ctx, req, t)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return t.Names, resp, nil
+}
+
+// TransferRequest represents a request to transfer a repository.
+type TransferRequest struct {
+ NewOwner string `json:"new_owner"`
+ TeamID []int64 `json:"team_ids,omitempty"`
+}
+
+// Transfer transfers a repository from one account or organization to another.
+//
+// This method might return an *AcceptedError and a status code of
+// 202. This is because this is the status that GitHub returns to signify that
+// it has now scheduled the transfer of the repository in a background task.
+// A follow up request, after a delay of a second or so, should result
+// in a successful request.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#transfer-a-repository
+func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string, transfer TransferRequest) (*Repository, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/transfer", owner, repo)
+
+ req, err := s.client.NewRequest("POST", u, &transfer)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeRepositoryTransferPreview)
+
+ r := new(Repository)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return r, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_collaborators.go b/vendor/github.com/google/go-github/github/repos_collaborators.go
new file mode 100644
index 0000000..61ee9d3
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_collaborators.go
@@ -0,0 +1,140 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// ListCollaboratorsOptions specifies the optional parameters to the
+// RepositoriesService.ListCollaborators method.
+type ListCollaboratorsOptions struct {
+ // Affiliation specifies how collaborators should be filtered by their affiliation.
+ // Possible values are:
+ // outside - All outside collaborators of an organization-owned repository
+ // direct - All collaborators with permissions to an organization-owned repository,
+ // regardless of organization membership status
+ // all - All collaborators the authenticated user can see
+ //
+ // Default value is "all".
+ Affiliation string `url:"affiliation,omitempty"`
+
+ ListOptions
+}
+
+// ListCollaborators lists the GitHub users that have access to the repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#list-collaborators
+func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo string, opt *ListCollaboratorsOptions) ([]*User, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/collaborators", owner, repo)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
+
+ var users []*User
+ resp, err := s.client.Do(ctx, req, &users)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return users, resp, nil
+}
+
+// IsCollaborator checks whether the specified GitHub user has collaborator
+// access to the given repo.
+// Note: This will return false if the user is not a collaborator OR the user
+// is not a GitHub user.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#get
+func (s *RepositoriesService) IsCollaborator(ctx context.Context, owner, repo, user string) (bool, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+
+ resp, err := s.client.Do(ctx, req, nil)
+ isCollab, err := parseBoolResponse(err)
+ return isCollab, resp, err
+}
+
+// RepositoryPermissionLevel represents the permission level an organization
+// member has for a given repository.
+type RepositoryPermissionLevel struct {
+ // Possible values: "admin", "write", "read", "none"
+ Permission *string `json:"permission,omitempty"`
+
+ User *User `json:"user,omitempty"`
+}
+
+// GetPermissionLevel retrieves the specific permission level a collaborator has for a given repository.
+// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level
+func (s *RepositoriesService) GetPermissionLevel(ctx context.Context, owner, repo, user string) (*RepositoryPermissionLevel, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/collaborators/%v/permission", owner, repo, user)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ rpl := new(RepositoryPermissionLevel)
+ resp, err := s.client.Do(ctx, req, rpl)
+ if err != nil {
+ return nil, resp, err
+ }
+ return rpl, resp, nil
+}
+
+// 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 "push". This option is only valid for organization-owned repositories.
+ Permission string `json:"permission,omitempty"`
+}
+
+// AddCollaborator sends an invitation to the specified GitHub user
+// to become a collaborator to the given repo.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator
+func (s *RepositoriesService) AddCollaborator(ctx context.Context, 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, opt)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// RemoveCollaborator removes the specified GitHub user as collaborator from the given repo.
+// Note: Does not return error if a valid user that is not a collaborator is removed.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#remove-collaborator
+func (s *RepositoriesService) RemoveCollaborator(ctx context.Context, owner, repo, user string) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_collaborators_test.go b/vendor/github.com/google/go-github/github/repos_collaborators_test.go
new file mode 100644
index 0000000..c814a5f
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_collaborators_test.go
@@ -0,0 +1,201 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_ListCollaborators(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/collaborators", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprintf(w, `[{"id":1}, {"id":2}]`)
+ })
+
+ opt := &ListCollaboratorsOptions{
+ ListOptions: ListOptions{Page: 2},
+ }
+ users, _, err := client.Repositories.ListCollaborators(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListCollaborators returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(users, want) {
+ t.Errorf("Repositori es.ListCollaborators returned %+v, want %+v", users, want)
+ }
+}
+
+func TestRepositoriesService_ListCollaborators_withAffiliation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/collaborators", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"affiliation": "all", "page": "2"})
+ fmt.Fprintf(w, `[{"id":1}, {"id":2}]`)
+ })
+
+ opt := &ListCollaboratorsOptions{
+ ListOptions: ListOptions{Page: 2},
+ Affiliation: "all",
+ }
+ users, _, err := client.Repositories.ListCollaborators(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListCollaborators returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(users, want) {
+ t.Errorf("Repositories.ListCollaborators returned %+v, want %+v", users, want)
+ }
+}
+
+func TestRepositoriesService_ListCollaborators_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.ListCollaborators(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_IsCollaborator_True(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/collaborators/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ isCollab, _, err := client.Repositories.IsCollaborator(context.Background(), "o", "r", "u")
+ if err != nil {
+ t.Errorf("Repositories.IsCollaborator returned error: %v", err)
+ }
+
+ if !isCollab {
+ t.Errorf("Repositories.IsCollaborator returned false, want true")
+ }
+}
+
+func TestRepositoriesService_IsCollaborator_False(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/collaborators/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNotFound)
+ })
+
+ isCollab, _, err := client.Repositories.IsCollaborator(context.Background(), "o", "r", "u")
+ if err != nil {
+ t.Errorf("Repositories.IsCollaborator returned error: %v", err)
+ }
+
+ if isCollab {
+ t.Errorf("Repositories.IsCollaborator returned true, want false")
+ }
+}
+
+func TestRepositoriesService_IsCollaborator_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.IsCollaborator(context.Background(), "%", "%", "%")
+ testURLParseError(t, err)
+}
+
+func TestRepositoryService_GetPermissionLevel(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/collaborators/u/permission", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprintf(w, `{"permission":"admin","user":{"login":"u"}}`)
+ })
+
+ rpl, _, err := client.Repositories.GetPermissionLevel(context.Background(), "o", "r", "u")
+ if err != nil {
+ t.Errorf("Repositories.GetPermissionLevel returned error: %v", err)
+ }
+
+ want := &RepositoryPermissionLevel{
+ Permission: String("admin"),
+ User: &User{
+ Login: String("u"),
+ },
+ }
+
+ if !reflect.DeepEqual(rpl, want) {
+ t.Errorf("Repositories.GetPermissionLevel returned %+v, want %+v", rpl, want)
+ }
+}
+
+func TestRepositoriesService_AddCollaborator(t *testing.T) {
+ client, mux, _, teardown := 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", mediaTypeRepositoryInvitationsPreview)
+ if !reflect.DeepEqual(v, opt) {
+ t.Errorf("Request body = %+v, want %+v", v, opt)
+ }
+
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Repositories.AddCollaborator(context.Background(), "o", "r", "u", opt)
+ if err != nil {
+ t.Errorf("Repositories.AddCollaborator returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_AddCollaborator_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Repositories.AddCollaborator(context.Background(), "%", "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_RemoveCollaborator(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/collaborators/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Repositories.RemoveCollaborator(context.Background(), "o", "r", "u")
+ if err != nil {
+ t.Errorf("Repositories.RemoveCollaborator returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_RemoveCollaborator_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Repositories.RemoveCollaborator(context.Background(), "%", "%", "%")
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_comments.go b/vendor/github.com/google/go-github/github/repos_comments.go
new file mode 100644
index 0000000..fa2377d
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_comments.go
@@ -0,0 +1,161 @@
+// 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// RepositoryComment represents a comment for a commit, file, or line in a repository.
+type RepositoryComment struct {
+ HTMLURL *string `json:"html_url,omitempty"`
+ URL *string `json:"url,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+ CommitID *string `json:"commit_id,omitempty"`
+ User *User `json:"user,omitempty"`
+ Reactions *Reactions `json:"reactions,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+
+ // User-mutable fields
+ Body *string `json:"body"`
+ // User-initialized fields
+ Path *string `json:"path,omitempty"`
+ Position *int `json:"position,omitempty"`
+}
+
+func (r RepositoryComment) String() string {
+ return Stringify(r)
+}
+
+// ListComments lists all the comments for the repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/comments/#list-commit-comments-for-a-repository
+func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/comments", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ var comments []*RepositoryComment
+ resp, err := s.client.Do(ctx, req, &comments)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return comments, resp, nil
+}
+
+// ListCommitComments lists all the comments for a given commit SHA.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/comments/#list-comments-for-a-single-commit
+func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, repo, sha string, opt *ListOptions) ([]*RepositoryComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+ var comments []*RepositoryComment
+ resp, err := s.client.Do(ctx, req, &comments)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return comments, resp, nil
+}
+
+// CreateComment creates a comment for the given commit.
+// Note: GitHub allows for comments to be created for non-existing files and positions.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/comments/#create-a-commit-comment
+func (s *RepositoriesService) CreateComment(ctx context.Context, owner, repo, sha string, comment *RepositoryComment) (*RepositoryComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha)
+ req, err := s.client.NewRequest("POST", u, comment)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c := new(RepositoryComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// GetComment gets a single comment from a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/comments/#get-a-single-commit-comment
+func (s *RepositoriesService) GetComment(ctx context.Context, owner, repo string, id int64) (*RepositoryComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id)
+ 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", mediaTypeReactionsPreview)
+
+ c := new(RepositoryComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// UpdateComment updates the body of a single comment.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/comments/#update-a-commit-comment
+func (s *RepositoriesService) UpdateComment(ctx context.Context, owner, repo string, id int64, comment *RepositoryComment) (*RepositoryComment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id)
+ req, err := s.client.NewRequest("PATCH", u, comment)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c := new(RepositoryComment)
+ resp, err := s.client.Do(ctx, req, c)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return c, resp, nil
+}
+
+// DeleteComment deletes a single comment from a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/comments/#delete-a-commit-comment
+func (s *RepositoriesService) DeleteComment(ctx context.Context, owner, repo string, id int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_comments_test.go b/vendor/github.com/google/go-github/github/repos_comments_test.go
new file mode 100644
index 0000000..0eb54eb
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_comments_test.go
@@ -0,0 +1,202 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_ListComments(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/comments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}, {"id":2}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ comments, _, err := client.Repositories.ListComments(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListComments returned error: %v", err)
+ }
+
+ want := []*RepositoryComment{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(comments, want) {
+ t.Errorf("Repositories.ListComments returned %+v, want %+v", comments, want)
+ }
+}
+
+func TestRepositoriesService_ListComments_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.ListComments(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_ListCommitComments(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/commits/s/comments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}, {"id":2}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ comments, _, err := client.Repositories.ListCommitComments(context.Background(), "o", "r", "s", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListCommitComments returned error: %v", err)
+ }
+
+ want := []*RepositoryComment{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(comments, want) {
+ t.Errorf("Repositories.ListCommitComments returned %+v, want %+v", comments, want)
+ }
+}
+
+func TestRepositoriesService_ListCommitComments_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.ListCommitComments(context.Background(), "%", "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_CreateComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &RepositoryComment{Body: String("b")}
+
+ mux.HandleFunc("/repos/o/r/commits/s/comments", func(w http.ResponseWriter, r *http.Request) {
+ v := new(RepositoryComment)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ comment, _, err := client.Repositories.CreateComment(context.Background(), "o", "r", "s", input)
+ if err != nil {
+ t.Errorf("Repositories.CreateComment returned error: %v", err)
+ }
+
+ want := &RepositoryComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Repositories.CreateComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestRepositoriesService_CreateComment_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.CreateComment(context.Background(), "%", "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_GetComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/comments/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ comment, _, err := client.Repositories.GetComment(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.GetComment returned error: %v", err)
+ }
+
+ want := &RepositoryComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Repositories.GetComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestRepositoriesService_GetComment_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.GetComment(context.Background(), "%", "%", 1)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_UpdateComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &RepositoryComment{Body: String("b")}
+
+ mux.HandleFunc("/repos/o/r/comments/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(RepositoryComment)
+ 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}`)
+ })
+
+ comment, _, err := client.Repositories.UpdateComment(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Repositories.UpdateComment returned error: %v", err)
+ }
+
+ want := &RepositoryComment{ID: Int64(1)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Repositories.UpdateComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestRepositoriesService_UpdateComment_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.UpdateComment(context.Background(), "%", "%", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_DeleteComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/comments/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Repositories.DeleteComment(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.DeleteComment returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_DeleteComment_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Repositories.DeleteComment(context.Background(), "%", "%", 1)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_commits.go b/vendor/github.com/google/go-github/github/repos_commits.go
new file mode 100644
index 0000000..04faa3e
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_commits.go
@@ -0,0 +1,237 @@
+// 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 (
+ "bytes"
+ "context"
+ "fmt"
+ "time"
+)
+
+// RepositoryCommit represents a commit in a repo.
+// Note that it's wrapping a Commit, so author/committer information is in two places,
+// but contain different details about them: in RepositoryCommit "github details", in Commit - "git details".
+type RepositoryCommit struct {
+ SHA *string `json:"sha,omitempty"`
+ Commit *Commit `json:"commit,omitempty"`
+ Author *User `json:"author,omitempty"`
+ Committer *User `json:"committer,omitempty"`
+ Parents []Commit `json:"parents,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ URL *string `json:"url,omitempty"`
+ CommentsURL *string `json:"comments_url,omitempty"`
+
+ // Details about how many changes were made in this commit. Only filled in during GetCommit!
+ Stats *CommitStats `json:"stats,omitempty"`
+ // Details about which files, and how this commit touched. Only filled in during GetCommit!
+ Files []CommitFile `json:"files,omitempty"`
+}
+
+func (r RepositoryCommit) String() string {
+ return Stringify(r)
+}
+
+// CommitStats represents the number of additions / deletions from a file in a given RepositoryCommit or GistCommit.
+type CommitStats struct {
+ Additions *int `json:"additions,omitempty"`
+ Deletions *int `json:"deletions,omitempty"`
+ Total *int `json:"total,omitempty"`
+}
+
+func (c CommitStats) String() string {
+ return Stringify(c)
+}
+
+// CommitFile represents a file modified in a commit.
+type CommitFile struct {
+ SHA *string `json:"sha,omitempty"`
+ Filename *string `json:"filename,omitempty"`
+ Additions *int `json:"additions,omitempty"`
+ Deletions *int `json:"deletions,omitempty"`
+ Changes *int `json:"changes,omitempty"`
+ Status *string `json:"status,omitempty"`
+ Patch *string `json:"patch,omitempty"`
+ BlobURL *string `json:"blob_url,omitempty"`
+ RawURL *string `json:"raw_url,omitempty"`
+ ContentsURL *string `json:"contents_url,omitempty"`
+}
+
+func (c CommitFile) String() string {
+ return Stringify(c)
+}
+
+// CommitsComparison is the result of comparing two commits.
+// See CompareCommits() for details.
+type CommitsComparison struct {
+ BaseCommit *RepositoryCommit `json:"base_commit,omitempty"`
+ MergeBaseCommit *RepositoryCommit `json:"merge_base_commit,omitempty"`
+
+ // Head can be 'behind' or 'ahead'
+ Status *string `json:"status,omitempty"`
+ AheadBy *int `json:"ahead_by,omitempty"`
+ BehindBy *int `json:"behind_by,omitempty"`
+ TotalCommits *int `json:"total_commits,omitempty"`
+
+ Commits []RepositoryCommit `json:"commits,omitempty"`
+
+ Files []CommitFile `json:"files,omitempty"`
+
+ HTMLURL *string `json:"html_url,omitempty"`
+ PermalinkURL *string `json:"permalink_url,omitempty"`
+ DiffURL *string `json:"diff_url,omitempty"`
+ PatchURL *string `json:"patch_url,omitempty"`
+ URL *string `json:"url,omitempty"` // API URL.
+}
+
+func (c CommitsComparison) String() string {
+ return Stringify(c)
+}
+
+// CommitsListOptions specifies the optional parameters to the
+// RepositoriesService.ListCommits method.
+type CommitsListOptions struct {
+ // SHA or branch to start listing Commits from.
+ SHA string `url:"sha,omitempty"`
+
+ // Path that should be touched by the returned Commits.
+ Path string `url:"path,omitempty"`
+
+ // Author of by which to filter Commits.
+ Author string `url:"author,omitempty"`
+
+ // Since when should Commits be included in the response.
+ Since time.Time `url:"since,omitempty"`
+
+ // Until when should Commits be included in the response.
+ Until time.Time `url:"until,omitempty"`
+
+ ListOptions
+}
+
+// ListCommits lists the commits of a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/commits/#list
+func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opt *CommitsListOptions) ([]*RepositoryCommit, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/commits", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeGitSigningPreview)
+
+ var commits []*RepositoryCommit
+ resp, err := s.client.Do(ctx, req, &commits)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return commits, resp, nil
+}
+
+// GetCommit fetches the specified commit, including all details about it.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-single-commit
+// See also: https://developer.github.com/v3/git/commits/#get-a-single-commit provides the same functionality
+func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string) (*RepositoryCommit, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha)
+
+ 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", mediaTypeGitSigningPreview)
+
+ commit := new(RepositoryCommit)
+ resp, err := s.client.Do(ctx, req, commit)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return commit, resp, nil
+}
+
+// GetCommitRaw fetches the specified commit in raw (diff or patch) format.
+func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opt RawOptions) (string, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return "", nil, err
+ }
+
+ switch opt.Type {
+ case Diff:
+ req.Header.Set("Accept", mediaTypeV3Diff)
+ case Patch:
+ req.Header.Set("Accept", mediaTypeV3Patch)
+ default:
+ return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type)
+ }
+
+ var buf bytes.Buffer
+ resp, err := s.client.Do(ctx, req, &buf)
+ if err != nil {
+ return "", resp, err
+ }
+
+ return buf.String(), resp, nil
+}
+
+// GetCommitSHA1 gets the SHA-1 of a commit reference. If a last-known SHA1 is
+// supplied and no new commits have occurred, a 304 Unmodified response is returned.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-the-sha-1-of-a-commit-reference
+func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, ref, lastSHA string) (string, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, ref)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return "", nil, err
+ }
+ if lastSHA != "" {
+ req.Header.Set("If-None-Match", `"`+lastSHA+`"`)
+ }
+
+ req.Header.Set("Accept", mediaTypeV3SHA)
+
+ var buf bytes.Buffer
+ resp, err := s.client.Do(ctx, req, &buf)
+ if err != nil {
+ return "", resp, err
+ }
+
+ return buf.String(), resp, nil
+}
+
+// CompareCommits compares a range of commits with each other.
+// todo: support media formats - https://github.com/google/go-github/issues/6
+//
+// GitHub API docs: https://developer.github.com/v3/repos/commits/#compare-two-commits
+func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo string, base, head string) (*CommitsComparison, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, base, head)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ comp := new(CommitsComparison)
+ resp, err := s.client.Do(ctx, req, comp)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return comp, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_commits_test.go b/vendor/github.com/google/go-github/github/repos_commits_test.go
new file mode 100644
index 0000000..3f7039d
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_commits_test.go
@@ -0,0 +1,325 @@
+// 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+)
+
+func TestRepositoriesService_ListCommits(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ // given
+ mux.HandleFunc("/repos/o/r/commits", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeGitSigningPreview)
+ testFormValues(t, r,
+ values{
+ "sha": "s",
+ "path": "p",
+ "author": "a",
+ "since": "2013-08-01T00:00:00Z",
+ "until": "2013-09-03T00:00:00Z",
+ })
+ fmt.Fprintf(w, `[{"sha": "s"}]`)
+ })
+
+ opt := &CommitsListOptions{
+ SHA: "s",
+ Path: "p",
+ Author: "a",
+ Since: time.Date(2013, time.August, 1, 0, 0, 0, 0, time.UTC),
+ Until: time.Date(2013, time.September, 3, 0, 0, 0, 0, time.UTC),
+ }
+ commits, _, err := client.Repositories.ListCommits(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListCommits returned error: %v", err)
+ }
+
+ want := []*RepositoryCommit{{SHA: String("s")}}
+ if !reflect.DeepEqual(commits, want) {
+ t.Errorf("Repositories.ListCommits returned %+v, want %+v", commits, want)
+ }
+}
+
+func TestRepositoriesService_GetCommit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/commits/s", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeGitSigningPreview)
+ fmt.Fprintf(w, `{
+ "sha": "s",
+ "commit": { "message": "m" },
+ "author": { "login": "l" },
+ "committer": { "login": "l" },
+ "parents": [ { "sha": "s" } ],
+ "stats": { "additions": 104, "deletions": 4, "total": 108 },
+ "files": [
+ {
+ "filename": "f",
+ "additions": 10,
+ "deletions": 2,
+ "changes": 12,
+ "status": "s",
+ "patch": "p",
+ "blob_url": "b",
+ "raw_url": "r",
+ "contents_url": "c"
+ }
+ ]
+ }`)
+ })
+
+ commit, _, err := client.Repositories.GetCommit(context.Background(), "o", "r", "s")
+ if err != nil {
+ t.Errorf("Repositories.GetCommit returned error: %v", err)
+ }
+
+ want := &RepositoryCommit{
+ SHA: String("s"),
+ Commit: &Commit{
+ Message: String("m"),
+ },
+ Author: &User{
+ Login: String("l"),
+ },
+ Committer: &User{
+ Login: String("l"),
+ },
+ Parents: []Commit{
+ {
+ SHA: String("s"),
+ },
+ },
+ Stats: &CommitStats{
+ Additions: Int(104),
+ Deletions: Int(4),
+ Total: Int(108),
+ },
+ Files: []CommitFile{
+ {
+ Filename: String("f"),
+ Additions: Int(10),
+ Deletions: Int(2),
+ Changes: Int(12),
+ Status: String("s"),
+ Patch: String("p"),
+ BlobURL: String("b"),
+ RawURL: String("r"),
+ ContentsURL: String("c"),
+ },
+ },
+ }
+ if !reflect.DeepEqual(commit, want) {
+ t.Errorf("Repositories.GetCommit returned \n%+v, want \n%+v", commit, want)
+ }
+}
+
+func TestRepositoriesService_GetCommitRaw_diff(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ const rawStr = "@@diff content"
+
+ mux.HandleFunc("/repos/o/r/commits/s", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeV3Diff)
+ fmt.Fprint(w, rawStr)
+ })
+
+ got, _, err := client.Repositories.GetCommitRaw(context.Background(), "o", "r", "s", RawOptions{Type: Diff})
+ if err != nil {
+ t.Fatalf("Repositories.GetCommitRaw returned error: %v", err)
+ }
+ want := rawStr
+ if got != want {
+ t.Errorf("Repositories.GetCommitRaw returned %s want %s", got, want)
+ }
+}
+
+func TestRepositoriesService_GetCommitRaw_patch(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ const rawStr = "@@patch content"
+
+ mux.HandleFunc("/repos/o/r/commits/s", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeV3Patch)
+ fmt.Fprint(w, rawStr)
+ })
+
+ got, _, err := client.Repositories.GetCommitRaw(context.Background(), "o", "r", "s", RawOptions{Type: Patch})
+ if err != nil {
+ t.Fatalf("Repositories.GetCommitRaw returned error: %v", err)
+ }
+ want := rawStr
+ if got != want {
+ t.Errorf("Repositories.GetCommitRaw returned %s want %s", got, want)
+ }
+}
+
+func TestRepositoriesService_GetCommitRaw_invalid(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.GetCommitRaw(context.Background(), "o", "r", "s", RawOptions{100})
+ if err == nil {
+ t.Fatal("Repositories.GetCommitRaw should return error")
+ }
+ if !strings.Contains(err.Error(), "unsupported raw type") {
+ t.Error("Repositories.GetCommitRaw should return unsupported raw type error")
+ }
+}
+
+func TestRepositoriesService_GetCommitSHA1(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ const sha1 = "01234abcde"
+
+ mux.HandleFunc("/repos/o/r/commits/master", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeV3SHA)
+
+ fmt.Fprintf(w, sha1)
+ })
+
+ got, _, err := client.Repositories.GetCommitSHA1(context.Background(), "o", "r", "master", "")
+ if err != nil {
+ t.Errorf("Repositories.GetCommitSHA1 returned error: %v", err)
+ }
+
+ want := sha1
+ if got != want {
+ t.Errorf("Repositories.GetCommitSHA1 = %v, want %v", got, want)
+ }
+
+ mux.HandleFunc("/repos/o/r/commits/tag", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeV3SHA)
+ testHeader(t, r, "If-None-Match", `"`+sha1+`"`)
+
+ w.WriteHeader(http.StatusNotModified)
+ })
+
+ got, _, err = client.Repositories.GetCommitSHA1(context.Background(), "o", "r", "tag", sha1)
+ if err == nil {
+ t.Errorf("Expected HTTP 304 response")
+ }
+
+ want = ""
+ if got != want {
+ t.Errorf("Repositories.GetCommitSHA1 = %v, want %v", got, want)
+ }
+}
+
+func TestRepositoriesService_CompareCommits(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/compare/b...h", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprintf(w, `{
+ "base_commit": {
+ "sha": "s",
+ "commit": {
+ "author": { "name": "n" },
+ "committer": { "name": "n" },
+ "message": "m",
+ "tree": { "sha": "t" }
+ },
+ "author": { "login": "l" },
+ "committer": { "login": "l" },
+ "parents": [ { "sha": "s" } ]
+ },
+ "status": "s",
+ "ahead_by": 1,
+ "behind_by": 2,
+ "total_commits": 1,
+ "commits": [
+ {
+ "sha": "s",
+ "commit": { "author": { "name": "n" } },
+ "author": { "login": "l" },
+ "committer": { "login": "l" },
+ "parents": [ { "sha": "s" } ]
+ }
+ ],
+ "files": [ { "filename": "f" } ],
+ "html_url": "https://github.com/o/r/compare/b...h",
+ "permalink_url": "https://github.com/o/r/compare/o:bbcd538c8e72b8c175046e27cc8f907076331401...o:0328041d1152db8ae77652d1618a02e57f745f17",
+ "diff_url": "https://github.com/o/r/compare/b...h.diff",
+ "patch_url": "https://github.com/o/r/compare/b...h.patch",
+ "url": "https://api.github.com/repos/o/r/compare/b...h"
+ }`)
+ })
+
+ got, _, err := client.Repositories.CompareCommits(context.Background(), "o", "r", "b", "h")
+ if err != nil {
+ t.Errorf("Repositories.CompareCommits returned error: %v", err)
+ }
+
+ want := &CommitsComparison{
+ BaseCommit: &RepositoryCommit{
+ SHA: String("s"),
+ Commit: &Commit{
+ Author: &CommitAuthor{Name: String("n")},
+ Committer: &CommitAuthor{Name: String("n")},
+ Message: String("m"),
+ Tree: &Tree{SHA: String("t")},
+ },
+ Author: &User{Login: String("l")},
+ Committer: &User{Login: String("l")},
+ Parents: []Commit{
+ {
+ SHA: String("s"),
+ },
+ },
+ },
+ Status: String("s"),
+ AheadBy: Int(1),
+ BehindBy: Int(2),
+ TotalCommits: Int(1),
+ Commits: []RepositoryCommit{
+ {
+ SHA: String("s"),
+ Commit: &Commit{
+ Author: &CommitAuthor{Name: String("n")},
+ },
+ Author: &User{Login: String("l")},
+ Committer: &User{Login: String("l")},
+ Parents: []Commit{
+ {
+ SHA: String("s"),
+ },
+ },
+ },
+ },
+ Files: []CommitFile{
+ {
+ Filename: String("f"),
+ },
+ },
+ HTMLURL: String("https://github.com/o/r/compare/b...h"),
+ PermalinkURL: String("https://github.com/o/r/compare/o:bbcd538c8e72b8c175046e27cc8f907076331401...o:0328041d1152db8ae77652d1618a02e57f745f17"),
+ DiffURL: String("https://github.com/o/r/compare/b...h.diff"),
+ PatchURL: String("https://github.com/o/r/compare/b...h.patch"),
+ URL: String("https://api.github.com/repos/o/r/compare/b...h"),
+ }
+
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.CompareCommits returned \n%+v, want \n%+v", got, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_community_health.go b/vendor/github.com/google/go-github/github/repos_community_health.go
new file mode 100644
index 0000000..73d1d57
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_community_health.go
@@ -0,0 +1,59 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// Metric represents the different fields for one file in community health files.
+type Metric struct {
+ Name *string `json:"name"`
+ Key *string `json:"key"`
+ URL *string `json:"url"`
+ HTMLURL *string `json:"html_url"`
+}
+
+// CommunityHealthFiles represents the different files in the community health metrics response.
+type CommunityHealthFiles struct {
+ CodeOfConduct *Metric `json:"code_of_conduct"`
+ Contributing *Metric `json:"contributing"`
+ IssueTemplate *Metric `json:"issue_template"`
+ PullRequestTemplate *Metric `json:"pull_request_template"`
+ License *Metric `json:"license"`
+ Readme *Metric `json:"readme"`
+}
+
+// CommunityHealthMetrics represents a response containing the community metrics of a repository.
+type CommunityHealthMetrics struct {
+ HealthPercentage *int `json:"health_percentage"`
+ Files *CommunityHealthFiles `json:"files"`
+ UpdatedAt *time.Time `json:"updated_at"`
+}
+
+// GetCommunityHealthMetrics retrieves all the community health metrics for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/community/#retrieve-community-health-metrics
+func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, owner, repo string) (*CommunityHealthMetrics, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/community/profile", owner, repo)
+ 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", mediaTypeRepositoryCommunityHealthMetricsPreview)
+
+ metrics := &CommunityHealthMetrics{}
+ resp, err := s.client.Do(ctx, req, metrics)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return metrics, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_community_health_test.go b/vendor/github.com/google/go-github/github/repos_community_health_test.go
new file mode 100644
index 0000000..6092af0
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_community_health_test.go
@@ -0,0 +1,86 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestRepositoriesService_GetCommunityHealthMetrics(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/community/profile", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeRepositoryCommunityHealthMetricsPreview)
+ fmt.Fprintf(w, `{
+ "health_percentage": 100,
+ "files": {
+ "code_of_conduct": {
+ "name": "Contributor Covenant",
+ "key": "contributor_covenant",
+ "url": null,
+ "html_url": "https://github.com/octocat/Hello-World/blob/master/CODE_OF_CONDUCT.md"
+ },
+ "contributing": {
+ "url": "https://api.github.com/repos/octocat/Hello-World/contents/CONTRIBUTING",
+ "html_url": "https://github.com/octocat/Hello-World/blob/master/CONTRIBUTING"
+ },
+ "license": {
+ "name": "MIT License",
+ "key": "mit",
+ "url": "https://api.github.com/licenses/mit",
+ "html_url": "https://github.com/octocat/Hello-World/blob/master/LICENSE"
+ },
+ "readme": {
+ "url": "https://api.github.com/repos/octocat/Hello-World/contents/README.md",
+ "html_url": "https://github.com/octocat/Hello-World/blob/master/README.md"
+ }
+ },
+ "updated_at": "2017-02-28T00:00:00Z"
+ }`)
+ })
+
+ got, _, err := client.Repositories.GetCommunityHealthMetrics(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.GetCommunityHealthMetrics returned error: %v", err)
+ }
+
+ updatedAt := time.Date(2017, time.February, 28, 0, 0, 0, 0, time.UTC)
+ want := &CommunityHealthMetrics{
+ HealthPercentage: Int(100),
+ UpdatedAt: &updatedAt,
+ Files: &CommunityHealthFiles{
+ CodeOfConduct: &Metric{
+ Name: String("Contributor Covenant"),
+ Key: String("contributor_covenant"),
+ HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/CODE_OF_CONDUCT.md"),
+ },
+ Contributing: &Metric{
+ URL: String("https://api.github.com/repos/octocat/Hello-World/contents/CONTRIBUTING"),
+ HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/CONTRIBUTING"),
+ },
+ License: &Metric{
+ Name: String("MIT License"),
+ Key: String("mit"),
+ URL: String("https://api.github.com/licenses/mit"),
+ HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/LICENSE"),
+ },
+ Readme: &Metric{
+ URL: String("https://api.github.com/repos/octocat/Hello-World/contents/README.md"),
+ HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/README.md"),
+ },
+ },
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.GetCommunityHealthMetrics:\ngot:\n%v\nwant:\n%v", Stringify(got), Stringify(want))
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_contents.go b/vendor/github.com/google/go-github/github/repos_contents.go
new file mode 100644
index 0000000..ffb56b9
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_contents.go
@@ -0,0 +1,266 @@
+// 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.
+
+// Repository contents API methods.
+// GitHub API docs: https://developer.github.com/v3/repos/contents/
+
+package github
+
+import (
+ "context"
+ "encoding/base64"
+ "encoding/json"
+ "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 contains the actual file content, which may be encoded.
+ // Callers should call GetContent which will decode the content if
+ // necessary.
+ 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.
+type RepositoryContentResponse struct {
+ Content *RepositoryContent `json:"content,omitempty"`
+ Commit `json:"commit,omitempty"`
+}
+
+// RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile.
+type RepositoryContentFileOptions struct {
+ Message *string `json:"message,omitempty"`
+ Content []byte `json:"content,omitempty"` // unencoded
+ SHA *string `json:"sha,omitempty"`
+ Branch *string `json:"branch,omitempty"`
+ Author *CommitAuthor `json:"author,omitempty"`
+ Committer *CommitAuthor `json:"committer,omitempty"`
+}
+
+// RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA,
+// branch, or tag
+type RepositoryContentGetOptions struct {
+ Ref string `url:"ref,omitempty"`
+}
+
+// String converts RepositoryContent to a string. It's primarily for testing.
+func (r RepositoryContent) String() string {
+ return Stringify(r)
+}
+
+// GetContent returns the content of r, decoding it if necessary.
+func (r *RepositoryContent) GetContent() (string, error) {
+ var encoding string
+ if r.Encoding != nil {
+ encoding = *r.Encoding
+ }
+
+ switch encoding {
+ case "base64":
+ c, err := base64.StdEncoding.DecodeString(*r.Content)
+ return string(c), err
+ case "":
+ if r.Content == nil {
+ return "", nil
+ }
+ return *r.Content, nil
+ default:
+ return "", fmt.Errorf("unsupported content encoding: %v", encoding)
+ }
+}
+
+// GetReadme gets the Readme file for the repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-the-readme
+func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string, opt *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/readme", owner, repo)
+ 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
+ }
+ readme := new(RepositoryContent)
+ resp, err := s.client.Do(ctx, req, readme)
+ if err != nil {
+ return nil, resp, err
+ }
+ return readme, resp, nil
+}
+
+// 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(ctx context.Context, owner, repo, filepath string, opt *RepositoryContentGetOptions) (io.ReadCloser, error) {
+ dir := path.Dir(filepath)
+ filename := path.Base(filepath)
+ _, dirContents, _, err := s.GetContents(ctx, 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
+// easy to distinguish between both result types and to mimic the API as much
+// as possible, both result types will be returned but only one will contain a
+// value and the other will be nil.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-contents
+func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opt *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) {
+ escapedPath := (&url.URL{Path: path}).String()
+ u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath)
+ u, err = addOptions(u, opt)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ var rawJSON json.RawMessage
+ resp, err = s.client.Do(ctx, req, &rawJSON)
+ if err != nil {
+ return nil, nil, resp, err
+ }
+ fileUnmarshalError := json.Unmarshal(rawJSON, &fileContent)
+ if fileUnmarshalError == nil {
+ return fileContent, nil, resp, nil
+ }
+ directoryUnmarshalError := json.Unmarshal(rawJSON, &directoryContent)
+ if directoryUnmarshalError == nil {
+ return nil, directoryContent, resp, nil
+ }
+ return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s", fileUnmarshalError, directoryUnmarshalError)
+}
+
+// CreateFile creates a new file in a repository at the given path and returns
+// the commit and file metadata.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/contents/#create-a-file
+func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
+ req, err := s.client.NewRequest("PUT", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+ createResponse := new(RepositoryContentResponse)
+ resp, err := s.client.Do(ctx, req, createResponse)
+ if err != nil {
+ return nil, resp, err
+ }
+ return createResponse, resp, nil
+}
+
+// UpdateFile updates a file in a repository at the given path and returns the
+// commit and file metadata. Requires the blob SHA of the file being updated.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/contents/#update-a-file
+func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
+ req, err := s.client.NewRequest("PUT", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+ updateResponse := new(RepositoryContentResponse)
+ resp, err := s.client.Do(ctx, req, updateResponse)
+ if err != nil {
+ return nil, resp, err
+ }
+ return updateResponse, resp, nil
+}
+
+// DeleteFile deletes a file from a repository and returns the commit.
+// Requires the blob SHA of the file to be deleted.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/contents/#delete-a-file
+func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
+ req, err := s.client.NewRequest("DELETE", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+ deleteResponse := new(RepositoryContentResponse)
+ resp, err := s.client.Do(ctx, req, deleteResponse)
+ if err != nil {
+ return nil, resp, err
+ }
+ return deleteResponse, resp, nil
+}
+
+// archiveFormat is used to define the archive type when calling GetArchiveLink.
+type archiveFormat string
+
+const (
+ // Tarball specifies an archive in gzipped tar format.
+ Tarball archiveFormat = "tarball"
+
+ // Zipball specifies an archive in zip format.
+ Zipball archiveFormat = "zipball"
+)
+
+// GetArchiveLink returns an URL to download a tarball or zipball archive for a
+// repository. The archiveFormat can be specified by either the github.Tarball
+// or github.Zipball constant.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-archive-link
+func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo string, archiveformat archiveFormat, opt *RepositoryContentGetOptions) (*url.URL, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat)
+ if opt != nil && opt.Ref != "" {
+ u += fmt.Sprintf("/%s", opt.Ref)
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+ var resp *http.Response
+ // Use http.DefaultTransport if no custom Transport is configured
+ req = withContext(ctx, req)
+ 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, nil, err
+ }
+ resp.Body.Close()
+ if resp.StatusCode != http.StatusFound {
+ return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status)
+ }
+ parsedURL, err := url.Parse(resp.Header.Get("Location"))
+ return parsedURL, newResponse(resp), err
+}
diff --git a/vendor/github.com/google/go-github/github/repos_contents_test.go b/vendor/github.com/google/go-github/github/repos_contents_test.go
new file mode 100644
index 0000000..29bab8d
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_contents_test.go
@@ -0,0 +1,389 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoryContent_GetContent(t *testing.T) {
+ tests := []struct {
+ encoding, content *string // input encoding and content
+ want string // desired output
+ wantErr bool // whether an error is expected
+ }{
+ {
+ encoding: String(""),
+ content: String("hello"),
+ want: "hello",
+ wantErr: false,
+ },
+ {
+ encoding: nil,
+ content: String("hello"),
+ want: "hello",
+ wantErr: false,
+ },
+ {
+ encoding: nil,
+ content: nil,
+ want: "",
+ wantErr: false,
+ },
+ {
+ encoding: String("base64"),
+ content: String("aGVsbG8="),
+ want: "hello",
+ wantErr: false,
+ },
+ {
+ encoding: String("bad"),
+ content: String("aGVsbG8="),
+ want: "",
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ r := RepositoryContent{Encoding: tt.encoding, Content: tt.content}
+ got, err := r.GetContent()
+ if err != nil && !tt.wantErr {
+ t.Errorf("RepositoryContent(%s, %s) returned unexpected error: %v",
+ stringOrNil(tt.encoding), stringOrNil(tt.content), err)
+ }
+ if err == nil && tt.wantErr {
+ t.Errorf("RepositoryContent(%s, %s) did not return unexpected error",
+ stringOrNil(tt.encoding), stringOrNil(tt.content))
+ }
+ if want := tt.want; got != want {
+ t.Errorf("RepositoryContent.GetContent returned %+v, want %+v", got, want)
+ }
+ }
+}
+
+// stringOrNil converts a potentially null string pointer to string.
+// For non-nil input pointer, the returned string is enclosed in double-quotes.
+func stringOrNil(s *string) string {
+ if s == nil {
+ return ""
+ }
+ return fmt.Sprintf("%q", *s)
+}
+
+func TestRepositoriesService_GetReadme(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ mux.HandleFunc("/repos/o/r/readme", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{
+ "type": "file",
+ "encoding": "base64",
+ "size": 5362,
+ "name": "README.md",
+ "path": "README.md"
+ }`)
+ })
+ readme, _, err := client.Repositories.GetReadme(context.Background(), "o", "r", &RepositoryContentGetOptions{})
+ if err != nil {
+ t.Errorf("Repositories.GetReadme returned error: %v", err)
+ }
+ want := &RepositoryContent{Type: String("file"), Name: String("README.md"), Size: Int(5362), Encoding: String("base64"), Path: String("README.md")}
+ if !reflect.DeepEqual(readme, want) {
+ t.Errorf("Repositories.GetReadme returned %+v, want %+v", readme, want)
+ }
+}
+
+func TestRepositoriesService_DownloadContents_Success(t *testing.T) {
+ client, mux, serverURL, teardown := 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": "`+serverURL+baseURLPath+`/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(context.Background(), "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) {
+ client, mux, _, teardown := 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(context.Background(), "o", "r", "d/f", nil)
+ if err == nil {
+ t.Errorf("Repositories.DownloadContents did not return expected error")
+ }
+}
+
+func TestRepositoriesService_DownloadContents_NoFile(t *testing.T) {
+ client, mux, _, teardown := 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(context.Background(), "o", "r", "d/f", nil)
+ if err == nil {
+ t.Errorf("Repositories.DownloadContents did not return expected error")
+ }
+}
+
+func TestRepositoriesService_GetContents_File(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{
+ "type": "file",
+ "encoding": "base64",
+ "size": 20678,
+ "name": "LICENSE",
+ "path": "LICENSE"
+ }`)
+ })
+ fileContents, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "p", &RepositoryContentGetOptions{})
+ if err != nil {
+ 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) {
+ t.Errorf("Repositories.GetContents returned %+v, want %+v", fileContents, want)
+ }
+}
+
+func TestRepositoriesService_GetContents_FilenameNeedsEscape(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ mux.HandleFunc("/repos/o/r/contents/p#?%/中.go", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{}`)
+ })
+ _, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "p#?%/中.go", &RepositoryContentGetOptions{})
+ if err != nil {
+ t.Fatalf("Repositories.GetContents returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_GetContents_DirectoryWithSpaces(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ mux.HandleFunc("/repos/o/r/contents/some directory/file.go", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{}`)
+ })
+ _, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "some directory/file.go", &RepositoryContentGetOptions{})
+ if err != nil {
+ t.Fatalf("Repositories.GetContents returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_GetContents_DirectoryWithPlusChars(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ mux.HandleFunc("/repos/o/r/contents/some directory+name/file.go", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{}`)
+ })
+ _, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "some directory+name/file.go", &RepositoryContentGetOptions{})
+ if err != nil {
+ t.Fatalf("Repositories.GetContents returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_GetContents_Directory(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{
+ "type": "dir",
+ "name": "lib",
+ "path": "lib"
+ },
+ {
+ "type": "file",
+ "size": 20678,
+ "name": "LICENSE",
+ "path": "LICENSE"
+ }]`)
+ })
+ _, directoryContents, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "p", &RepositoryContentGetOptions{})
+ if err != nil {
+ 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")}}
+ if !reflect.DeepEqual(directoryContents, want) {
+ t.Errorf("Repositories.GetContents_Directory returned %+v, want %+v", directoryContents, want)
+ }
+}
+
+func TestRepositoriesService_CreateFile(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ fmt.Fprint(w, `{
+ "content":{
+ "name":"p"
+ },
+ "commit":{
+ "message":"m",
+ "sha":"f5f369044773ff9c6383c087466d12adb6fa0828"
+ }
+ }`)
+ })
+ message := "m"
+ content := []byte("c")
+ repositoryContentsOptions := &RepositoryContentFileOptions{
+ Message: &message,
+ Content: content,
+ Committer: &CommitAuthor{Name: String("n"), Email: String("e")},
+ }
+ createResponse, _, err := client.Repositories.CreateFile(context.Background(), "o", "r", "p", repositoryContentsOptions)
+ if err != nil {
+ t.Errorf("Repositories.CreateFile returned error: %v", err)
+ }
+ want := &RepositoryContentResponse{
+ Content: &RepositoryContent{Name: String("p")},
+ Commit: Commit{
+ Message: String("m"),
+ SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"),
+ },
+ }
+ if !reflect.DeepEqual(createResponse, want) {
+ t.Errorf("Repositories.CreateFile returned %+v, want %+v", createResponse, want)
+ }
+}
+
+func TestRepositoriesService_UpdateFile(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ fmt.Fprint(w, `{
+ "content":{
+ "name":"p"
+ },
+ "commit":{
+ "message":"m",
+ "sha":"f5f369044773ff9c6383c087466d12adb6fa0828"
+ }
+ }`)
+ })
+ message := "m"
+ content := []byte("c")
+ sha := "f5f369044773ff9c6383c087466d12adb6fa0828"
+ repositoryContentsOptions := &RepositoryContentFileOptions{
+ Message: &message,
+ Content: content,
+ SHA: &sha,
+ Committer: &CommitAuthor{Name: String("n"), Email: String("e")},
+ }
+ updateResponse, _, err := client.Repositories.UpdateFile(context.Background(), "o", "r", "p", repositoryContentsOptions)
+ if err != nil {
+ t.Errorf("Repositories.UpdateFile returned error: %v", err)
+ }
+ want := &RepositoryContentResponse{
+ Content: &RepositoryContent{Name: String("p")},
+ Commit: Commit{
+ Message: String("m"),
+ SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"),
+ },
+ }
+ if !reflect.DeepEqual(updateResponse, want) {
+ t.Errorf("Repositories.UpdateFile returned %+v, want %+v", updateResponse, want)
+ }
+}
+
+func TestRepositoriesService_DeleteFile(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ fmt.Fprint(w, `{
+ "content": null,
+ "commit":{
+ "message":"m",
+ "sha":"f5f369044773ff9c6383c087466d12adb6fa0828"
+ }
+ }`)
+ })
+ message := "m"
+ sha := "f5f369044773ff9c6383c087466d12adb6fa0828"
+ repositoryContentsOptions := &RepositoryContentFileOptions{
+ Message: &message,
+ SHA: &sha,
+ Committer: &CommitAuthor{Name: String("n"), Email: String("e")},
+ }
+ deleteResponse, _, err := client.Repositories.DeleteFile(context.Background(), "o", "r", "p", repositoryContentsOptions)
+ if err != nil {
+ t.Errorf("Repositories.DeleteFile returned error: %v", err)
+ }
+ want := &RepositoryContentResponse{
+ Content: nil,
+ Commit: Commit{
+ Message: String("m"),
+ SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"),
+ },
+ }
+ if !reflect.DeepEqual(deleteResponse, want) {
+ t.Errorf("Repositories.DeleteFile returned %+v, want %+v", deleteResponse, want)
+ }
+}
+
+func TestRepositoriesService_GetArchiveLink(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+ mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ http.Redirect(w, r, "http://github.com/a", http.StatusFound)
+ })
+ url, resp, err := client.Repositories.GetArchiveLink(context.Background(), "o", "r", Tarball, &RepositoryContentGetOptions{})
+ if err != nil {
+ t.Errorf("Repositories.GetArchiveLink returned error: %v", err)
+ }
+ if resp.StatusCode != http.StatusFound {
+ t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound)
+ }
+ want := "http://github.com/a"
+ if url.String() != want {
+ t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_deployments.go b/vendor/github.com/google/go-github/github/repos_deployments.go
new file mode 100644
index 0000000..794c323
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_deployments.go
@@ -0,0 +1,224 @@
+// Copyright 2014 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+)
+
+// Deployment represents a deployment in a repo
+type Deployment struct {
+ URL *string `json:"url,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+ SHA *string `json:"sha,omitempty"`
+ Ref *string `json:"ref,omitempty"`
+ Task *string `json:"task,omitempty"`
+ Payload json.RawMessage `json:"payload,omitempty"`
+ Environment *string `json:"environment,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Creator *User `json:"creator,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ StatusesURL *string `json:"statuses_url,omitempty"`
+ RepositoryURL *string `json:"repository_url,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+// 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"`
+ TransientEnvironment *bool `json:"transient_environment,omitempty"`
+ ProductionEnvironment *bool `json:"production_environment,omitempty"`
+}
+
+// DeploymentsListOptions specifies the optional parameters to the
+// RepositoriesService.ListDeployments method.
+type DeploymentsListOptions struct {
+ // SHA of the Deployment.
+ SHA string `url:"sha,omitempty"`
+
+ // List deployments for a given ref.
+ Ref string `url:"ref,omitempty"`
+
+ // List deployments for a given task.
+ Task string `url:"task,omitempty"`
+
+ // List deployments for a given environment.
+ Environment string `url:"environment,omitempty"`
+
+ ListOptions
+}
+
+// ListDeployments lists the deployments of a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployments
+func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opt *DeploymentsListOptions) ([]*Deployment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo)
+ 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
+ }
+
+ var deployments []*Deployment
+ resp, err := s.client.Do(ctx, req, &deployments)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return deployments, resp, nil
+}
+
+// GetDeployment returns a single deployment of a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment
+func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Deployment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ deployment := new(Deployment)
+ resp, err := s.client.Do(ctx, req, deployment)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return deployment, resp, nil
+}
+
+// CreateDeployment creates a new deployment for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment
+func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo string, request *DeploymentRequest) (*Deployment, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo)
+
+ req, err := s.client.NewRequest("POST", u, request)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeDeploymentStatusPreview)
+
+ d := new(Deployment)
+ resp, err := s.client.Do(ctx, req, d)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return d, resp, nil
+}
+
+// DeploymentStatus represents the status of a
+// particular deployment.
+type DeploymentStatus struct {
+ ID *int64 `json:"id,omitempty"`
+ // State is the deployment state.
+ // Possible values are: "pending", "success", "failure", "error", "inactive".
+ State *string `json:"state,omitempty"`
+ Creator *User `json:"creator,omitempty"`
+ Description *string `json:"description,omitempty"`
+ TargetURL *string `json:"target_url,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ DeploymentURL *string `json:"deployment_url,omitempty"`
+ RepositoryURL *string `json:"repository_url,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+// DeploymentStatusRequest represents a deployment request
+type DeploymentStatusRequest struct {
+ State *string `json:"state,omitempty"`
+ LogURL *string `json:"log_url,omitempty"`
+ Description *string `json:"description,omitempty"`
+ EnvironmentURL *string `json:"environment_url,omitempty"`
+ AutoInactive *bool `json:"auto_inactive,omitempty"`
+}
+
+// ListDeploymentStatuses lists the statuses of a given deployment of a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployment-statuses
+func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opt *ListOptions) ([]*DeploymentStatus, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment)
+ 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
+ }
+
+ var statuses []*DeploymentStatus
+ resp, err := s.client.Do(ctx, req, &statuses)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return statuses, resp, nil
+}
+
+// GetDeploymentStatus returns a single deployment status of a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment-status
+func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, repo string, deploymentID, deploymentStatusID int64) (*DeploymentStatus, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses/%v", owner, repo, deploymentID, deploymentStatusID)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeDeploymentStatusPreview)
+
+ d := new(DeploymentStatus)
+ resp, err := s.client.Do(ctx, req, d)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return d, resp, nil
+}
+
+// CreateDeploymentStatus creates a new status for a deployment.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment-status
+func (s *RepositoriesService) CreateDeploymentStatus(ctx context.Context, owner, repo string, deployment int64, request *DeploymentStatusRequest) (*DeploymentStatus, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment)
+
+ req, err := s.client.NewRequest("POST", u, request)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeDeploymentStatusPreview)
+
+ d := new(DeploymentStatus)
+ resp, err := s.client.Do(ctx, req, d)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return d, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_deployments_test.go b/vendor/github.com/google/go-github/github/repos_deployments_test.go
new file mode 100644
index 0000000..f6f333a
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_deployments_test.go
@@ -0,0 +1,161 @@
+// Copyright 2014 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_ListDeployments(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/deployments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"environment": "test"})
+ fmt.Fprint(w, `[{"id":1}, {"id":2}]`)
+ })
+
+ opt := &DeploymentsListOptions{Environment: "test"}
+ deployments, _, err := client.Repositories.ListDeployments(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListDeployments returned error: %v", err)
+ }
+
+ want := []*Deployment{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(deployments, want) {
+ t.Errorf("Repositories.ListDeployments returned %+v, want %+v", deployments, want)
+ }
+}
+
+func TestRepositoriesService_GetDeployment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/deployments/3", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":3}`)
+ })
+
+ deployment, _, err := client.Repositories.GetDeployment(context.Background(), "o", "r", 3)
+ if err != nil {
+ t.Errorf("Repositories.GetDeployment returned error: %v", err)
+ }
+
+ want := &Deployment{ID: Int64(3)}
+
+ if !reflect.DeepEqual(deployment, want) {
+ t.Errorf("Repositories.GetDeployment returned %+v, want %+v", deployment, want)
+ }
+}
+
+func TestRepositoriesService_CreateDeployment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &DeploymentRequest{Ref: String("1111"), Task: String("deploy"), TransientEnvironment: Bool(true)}
+
+ mux.HandleFunc("/repos/o/r/deployments", func(w http.ResponseWriter, r *http.Request) {
+ v := new(DeploymentRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeDeploymentStatusPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"ref": "1111", "task": "deploy"}`)
+ })
+
+ deployment, _, err := client.Repositories.CreateDeployment(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Repositories.CreateDeployment returned error: %v", err)
+ }
+
+ want := &Deployment{Ref: String("1111"), Task: String("deploy")}
+ if !reflect.DeepEqual(deployment, want) {
+ t.Errorf("Repositories.CreateDeployment returned %+v, want %+v", deployment, want)
+ }
+}
+
+func TestRepositoriesService_ListDeploymentStatuses(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/deployments/1/statuses", 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}
+ statutses, _, err := client.Repositories.ListDeploymentStatuses(context.Background(), "o", "r", 1, opt)
+ if err != nil {
+ t.Errorf("Repositories.ListDeploymentStatuses returned error: %v", err)
+ }
+
+ want := []*DeploymentStatus{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(statutses, want) {
+ t.Errorf("Repositories.ListDeploymentStatuses returned %+v, want %+v", statutses, want)
+ }
+}
+
+func TestRepositoriesService_GetDeploymentStatus(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/deployments/3/statuses/4", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeDeploymentStatusPreview)
+ fmt.Fprint(w, `{"id":4}`)
+ })
+
+ deploymentStatus, _, err := client.Repositories.GetDeploymentStatus(context.Background(), "o", "r", 3, 4)
+ if err != nil {
+ t.Errorf("Repositories.GetDeploymentStatus returned error: %v", err)
+ }
+
+ want := &DeploymentStatus{ID: Int64(4)}
+ if !reflect.DeepEqual(deploymentStatus, want) {
+ t.Errorf("Repositories.GetDeploymentStatus returned %+v, want %+v", deploymentStatus, want)
+ }
+}
+
+func TestRepositoriesService_CreateDeploymentStatus(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &DeploymentStatusRequest{State: String("inactive"), Description: String("deploy"), AutoInactive: Bool(false)}
+
+ mux.HandleFunc("/repos/o/r/deployments/1/statuses", func(w http.ResponseWriter, r *http.Request) {
+ v := new(DeploymentStatusRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeDeploymentStatusPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"state": "inactive", "description": "deploy"}`)
+ })
+
+ deploymentStatus, _, err := client.Repositories.CreateDeploymentStatus(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Repositories.CreateDeploymentStatus returned error: %v", err)
+ }
+
+ want := &DeploymentStatus{State: String("inactive"), Description: String("deploy")}
+ if !reflect.DeepEqual(deploymentStatus, want) {
+ t.Errorf("Repositories.CreateDeploymentStatus returned %+v, want %+v", deploymentStatus, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_forks.go b/vendor/github.com/google/go-github/github/repos_forks.go
new file mode 100644
index 0000000..d0bff54
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_forks.go
@@ -0,0 +1,89 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// RepositoryListForksOptions specifies the optional parameters to the
+// RepositoriesService.ListForks method.
+type RepositoryListForksOptions struct {
+ // How to sort the forks list. Possible values are: newest, oldest,
+ // watchers. Default is "newest".
+ Sort string `url:"sort,omitempty"`
+
+ ListOptions
+}
+
+// ListForks lists the forks of the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/forks/#list-forks
+func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, opt *RepositoryListForksOptions) ([]*Repository, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/forks", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept header when topics API fully launches.
+ req.Header.Set("Accept", mediaTypeTopicsPreview)
+
+ var repos []*Repository
+ resp, err := s.client.Do(ctx, req, &repos)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return repos, resp, nil
+}
+
+// RepositoryCreateForkOptions specifies the optional parameters to the
+// RepositoriesService.CreateFork method.
+type RepositoryCreateForkOptions struct {
+ // The organization to fork the repository into.
+ Organization string `url:"organization,omitempty"`
+}
+
+// CreateFork creates a fork of the specified repository.
+//
+// This method might return an *AcceptedError and a status code of
+// 202. This is because this is the status that GitHub returns to signify that
+// it is now computing creating the fork in a background task. In this event,
+// the Repository value will be returned, which includes the details about the pending fork.
+// A follow up request, after a delay of a second or so, should result
+// in a successful request.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/forks/#create-a-fork
+func (s *RepositoriesService) CreateFork(ctx context.Context, owner, repo string, opt *RepositoryCreateForkOptions) (*Repository, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/forks", owner, repo)
+ u, err := addOptions(u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("POST", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ fork := new(Repository)
+ resp, err := s.client.Do(ctx, req, fork)
+ if _, ok := err.(*AcceptedError); ok {
+ return fork, resp, err
+ }
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return fork, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_forks_test.go b/vendor/github.com/google/go-github/github/repos_forks_test.go
new file mode 100644
index 0000000..065f592
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_forks_test.go
@@ -0,0 +1,105 @@
+// 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_ListForks(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/forks", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+ testFormValues(t, r, values{
+ "sort": "newest",
+ "page": "3",
+ })
+ fmt.Fprint(w, `[{"id":1},{"id":2}]`)
+ })
+
+ opt := &RepositoryListForksOptions{
+ Sort: "newest",
+ ListOptions: ListOptions{Page: 3},
+ }
+ repos, _, err := client.Repositories.ListForks(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListForks returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(repos, want) {
+ t.Errorf("Repositories.ListForks returned %+v, want %+v", repos, want)
+ }
+}
+
+func TestRepositoriesService_ListForks_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.ListForks(context.Background(), "%", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_CreateFork(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/forks", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testFormValues(t, r, values{"organization": "o"})
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ opt := &RepositoryCreateForkOptions{Organization: "o"}
+ repo, _, err := client.Repositories.CreateFork(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.CreateFork returned error: %v", err)
+ }
+
+ want := &Repository{ID: Int64(1)}
+ if !reflect.DeepEqual(repo, want) {
+ t.Errorf("Repositories.CreateFork returned %+v, want %+v", repo, want)
+ }
+}
+
+func TestRepositoriesService_CreateFork_deferred(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/forks", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testFormValues(t, r, values{"organization": "o"})
+ // This response indicates the fork will happen asynchronously.
+ w.WriteHeader(http.StatusAccepted)
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ opt := &RepositoryCreateForkOptions{Organization: "o"}
+ repo, _, err := client.Repositories.CreateFork(context.Background(), "o", "r", opt)
+ if _, ok := err.(*AcceptedError); !ok {
+ t.Errorf("Repositories.CreateFork returned error: %v (want AcceptedError)", err)
+ }
+
+ want := &Repository{ID: Int64(1)}
+ if !reflect.DeepEqual(repo, want) {
+ t.Errorf("Repositories.CreateFork returned %+v, want %+v", repo, want)
+ }
+}
+
+func TestRepositoriesService_CreateFork_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.CreateFork(context.Background(), "%", "r", nil)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_hooks.go b/vendor/github.com/google/go-github/github/repos_hooks.go
new file mode 100644
index 0000000..1e9e884
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_hooks.go
@@ -0,0 +1,200 @@
+// 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// WebHookPayload represents the data that is received from GitHub when a push
+// event hook is triggered. The format of these payloads pre-date most of the
+// GitHub v3 API, so there are lots of minor incompatibilities with the types
+// defined in the rest of the API. Therefore, several types are duplicated
+// here to account for these differences.
+//
+// GitHub API docs: https://help.github.com/articles/post-receive-hooks
+type WebHookPayload struct {
+ After *string `json:"after,omitempty"`
+ Before *string `json:"before,omitempty"`
+ Commits []WebHookCommit `json:"commits,omitempty"`
+ Compare *string `json:"compare,omitempty"`
+ Created *bool `json:"created,omitempty"`
+ Deleted *bool `json:"deleted,omitempty"`
+ Forced *bool `json:"forced,omitempty"`
+ HeadCommit *WebHookCommit `json:"head_commit,omitempty"`
+ Pusher *User `json:"pusher,omitempty"`
+ Ref *string `json:"ref,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Sender *User `json:"sender,omitempty"`
+}
+
+func (w WebHookPayload) String() string {
+ return Stringify(w)
+}
+
+// WebHookCommit represents the commit variant we receive from GitHub in a
+// WebHookPayload.
+type WebHookCommit struct {
+ Added []string `json:"added,omitempty"`
+ Author *WebHookAuthor `json:"author,omitempty"`
+ Committer *WebHookAuthor `json:"committer,omitempty"`
+ Distinct *bool `json:"distinct,omitempty"`
+ ID *string `json:"id,omitempty"`
+ Message *string `json:"message,omitempty"`
+ Modified []string `json:"modified,omitempty"`
+ Removed []string `json:"removed,omitempty"`
+ Timestamp *time.Time `json:"timestamp,omitempty"`
+}
+
+func (w WebHookCommit) String() string {
+ return Stringify(w)
+}
+
+// WebHookAuthor represents the author or committer of a commit, as specified
+// in a WebHookCommit. The commit author may not correspond to a GitHub User.
+type WebHookAuthor struct {
+ Email *string `json:"email,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Username *string `json:"username,omitempty"`
+}
+
+func (w WebHookAuthor) String() string {
+ return Stringify(w)
+}
+
+// Hook represents a GitHub (web and service) hook for a repository.
+type Hook struct {
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+ Name *string `json:"name,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Events []string `json:"events,omitempty"`
+ Active *bool `json:"active,omitempty"`
+ Config map[string]interface{} `json:"config,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+}
+
+func (h Hook) String() string {
+ return Stringify(h)
+}
+
+// CreateHook creates a Hook for the specified repository.
+// Name and Config are required fields.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/hooks/#create-a-hook
+func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo)
+ req, err := s.client.NewRequest("POST", u, hook)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ h := new(Hook)
+ resp, err := s.client.Do(ctx, req, h)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return h, resp, nil
+}
+
+// ListHooks lists all Hooks for the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/hooks/#list
+func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Hook, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo)
+ 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
+ }
+
+ var hooks []*Hook
+ resp, err := s.client.Do(ctx, req, &hooks)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return hooks, resp, nil
+}
+
+// GetHook returns a single specified Hook.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/hooks/#get-single-hook
+func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+ h := new(Hook)
+ resp, err := s.client.Do(ctx, req, h)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return h, resp, nil
+}
+
+// EditHook updates a specified Hook.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/hooks/#edit-a-hook
+func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id)
+ req, err := s.client.NewRequest("PATCH", u, hook)
+ if err != nil {
+ return nil, nil, err
+ }
+ h := new(Hook)
+ resp, err := s.client.Do(ctx, req, h)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return h, resp, nil
+}
+
+// DeleteHook deletes a specified Hook.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/hooks/#delete-a-hook
+func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, 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(ctx context.Context, owner, repo string, id int64) (*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(ctx, req, nil)
+}
+
+// TestHook triggers a test Hook by github.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/hooks/#test-a-push-hook
+func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id)
+ req, err := s.client.NewRequest("POST", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_hooks_test.go b/vendor/github.com/google/go-github/github/repos_hooks_test.go
new file mode 100644
index 0000000..a143561
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_hooks_test.go
@@ -0,0 +1,206 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_CreateHook(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Hook{Name: String("t")}
+
+ mux.HandleFunc("/repos/o/r/hooks", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Hook)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ hook, _, err := client.Repositories.CreateHook(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Repositories.CreateHook returned error: %v", err)
+ }
+
+ want := &Hook{ID: Int64(1)}
+ if !reflect.DeepEqual(hook, want) {
+ t.Errorf("Repositories.CreateHook returned %+v, want %+v", hook, want)
+ }
+}
+
+func TestRepositoriesService_CreateHook_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.CreateHook(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_ListHooks(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/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.Repositories.ListHooks(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListHooks returned error: %v", err)
+ }
+
+ want := []*Hook{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(hooks, want) {
+ t.Errorf("Repositories.ListHooks returned %+v, want %+v", hooks, want)
+ }
+}
+
+func TestRepositoriesService_ListHooks_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.ListHooks(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_GetHook(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/hooks/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ hook, _, err := client.Repositories.GetHook(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.GetHook returned error: %v", err)
+ }
+
+ want := &Hook{ID: Int64(1)}
+ if !reflect.DeepEqual(hook, want) {
+ t.Errorf("Repositories.GetHook returned %+v, want %+v", hook, want)
+ }
+}
+
+func TestRepositoriesService_GetHook_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.GetHook(context.Background(), "%", "%", 1)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_EditHook(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Hook{Name: String("t")}
+
+ mux.HandleFunc("/repos/o/r/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.Repositories.EditHook(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Repositories.EditHook returned error: %v", err)
+ }
+
+ want := &Hook{ID: Int64(1)}
+ if !reflect.DeepEqual(hook, want) {
+ t.Errorf("Repositories.EditHook returned %+v, want %+v", hook, want)
+ }
+}
+
+func TestRepositoriesService_EditHook_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.EditHook(context.Background(), "%", "%", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_DeleteHook(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/hooks/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Repositories.DeleteHook(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.DeleteHook returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_DeleteHook_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Repositories.DeleteHook(context.Background(), "%", "%", 1)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_PingHook(t *testing.T) {
+ client, mux, _, teardown := 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(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.PingHook returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_TestHook(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/hooks/1/tests", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ })
+
+ _, err := client.Repositories.TestHook(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.TestHook returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_TestHook_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Repositories.TestHook(context.Background(), "%", "%", 1)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_invitations.go b/vendor/github.com/google/go-github/github/repos_invitations.go
new file mode 100644
index 0000000..34bf383
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_invitations.go
@@ -0,0 +1,98 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+)
+
+// RepositoryInvitation represents an invitation to collaborate on a repo.
+type RepositoryInvitation struct {
+ ID *int64 `json:"id,omitempty"`
+ Repo *Repository `json:"repository,omitempty"`
+ Invitee *User `json:"invitee,omitempty"`
+ Inviter *User `json:"inviter,omitempty"`
+
+ // Permissions represents the permissions that the associated user will have
+ // on the repository. Possible values are: "read", "write", "admin".
+ Permissions *string `json:"permissions,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+}
+
+// ListInvitations lists all currently-open repository invitations.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository
+func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/invitations", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
+
+ invites := []*RepositoryInvitation{}
+ resp, err := s.client.Do(ctx, req, &invites)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return invites, resp, nil
+}
+
+// DeleteInvitation deletes a repository invitation.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/invitations/#delete-a-repository-invitation
+func (s *RepositoriesService) DeleteInvitation(ctx context.Context, owner, repo string, invitationID int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// UpdateInvitation updates the permissions associated with a repository
+// invitation.
+//
+// permissions represents the permissions that the associated user will have
+// on the repository. Possible values are: "read", "write", "admin".
+//
+// GitHub API docs: https://developer.github.com/v3/repos/invitations/#update-a-repository-invitation
+func (s *RepositoriesService) UpdateInvitation(ctx context.Context, owner, repo string, invitationID int64, permissions string) (*RepositoryInvitation, *Response, error) {
+ opts := &struct {
+ Permissions string `json:"permissions"`
+ }{Permissions: permissions}
+ u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID)
+ req, err := s.client.NewRequest("PATCH", u, opts)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
+
+ invite := &RepositoryInvitation{}
+ resp, err := s.client.Do(ctx, req, invite)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return invite, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_invitations_test.go b/vendor/github.com/google/go-github/github/repos_invitations_test.go
new file mode 100644
index 0000000..27bec41
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_invitations_test.go
@@ -0,0 +1,74 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_ListInvitations(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/invitations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprintf(w, `[{"id":1}, {"id":2}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ got, _, err := client.Repositories.ListInvitations(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListInvitations returned error: %v", err)
+ }
+
+ want := []*RepositoryInvitation{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.ListInvitations = %+v, want %+v", got, want)
+ }
+}
+
+func TestRepositoriesService_DeleteInvitation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/invitations/2", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Repositories.DeleteInvitation(context.Background(), "o", "r", 2)
+ if err != nil {
+ t.Errorf("Repositories.DeleteInvitation returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_UpdateInvitation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/invitations/2", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
+ fmt.Fprintf(w, `{"id":1}`)
+ })
+
+ got, _, err := client.Repositories.UpdateInvitation(context.Background(), "o", "r", 2, "write")
+ if err != nil {
+ t.Errorf("Repositories.UpdateInvitation returned error: %v", err)
+ }
+
+ want := &RepositoryInvitation{ID: Int64(1)}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.UpdateInvitation = %+v, want %+v", got, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_keys.go b/vendor/github.com/google/go-github/github/repos_keys.go
new file mode 100644
index 0000000..b484f84
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_keys.go
@@ -0,0 +1,111 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// The Key type is defined in users_keys.go
+
+// ListKeys lists the deploy keys for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/keys/#list
+func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Key, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/keys", owner, repo)
+ 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
+ }
+
+ var keys []*Key
+ resp, err := s.client.Do(ctx, req, &keys)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return keys, resp, nil
+}
+
+// GetKey fetches a single deploy key.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/keys/#get
+func (s *RepositoriesService) GetKey(ctx context.Context, owner string, repo string, id int64) (*Key, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ key := new(Key)
+ resp, err := s.client.Do(ctx, req, key)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return key, resp, nil
+}
+
+// CreateKey adds a deploy key for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/keys/#create
+func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo string, key *Key) (*Key, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/keys", owner, repo)
+
+ req, err := s.client.NewRequest("POST", u, key)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ k := new(Key)
+ resp, err := s.client.Do(ctx, req, k)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return k, resp, nil
+}
+
+// EditKey edits a deploy key.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/keys/#edit
+func (s *RepositoriesService) EditKey(ctx context.Context, owner string, repo string, id int64, key *Key) (*Key, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id)
+
+ req, err := s.client.NewRequest("PATCH", u, key)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ k := new(Key)
+ resp, err := s.client.Do(ctx, req, k)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return k, resp, nil
+}
+
+// DeleteKey deletes a deploy key.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/keys/#delete
+func (s *RepositoriesService) DeleteKey(ctx context.Context, owner string, repo string, id int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_keys_test.go b/vendor/github.com/google/go-github/github/repos_keys_test.go
new file mode 100644
index 0000000..75a1735
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_keys_test.go
@@ -0,0 +1,169 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_ListKeys(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/keys", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ keys, _, err := client.Repositories.ListKeys(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListKeys returned error: %v", err)
+ }
+
+ want := []*Key{{ID: Int64(1)}}
+ if !reflect.DeepEqual(keys, want) {
+ t.Errorf("Repositories.ListKeys returned %+v, want %+v", keys, want)
+ }
+}
+
+func TestRepositoriesService_ListKeys_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.ListKeys(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_GetKey(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/keys/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ key, _, err := client.Repositories.GetKey(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.GetKey returned error: %v", err)
+ }
+
+ want := &Key{ID: Int64(1)}
+ if !reflect.DeepEqual(key, want) {
+ t.Errorf("Repositories.GetKey returned %+v, want %+v", key, want)
+ }
+}
+
+func TestRepositoriesService_GetKey_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.GetKey(context.Background(), "%", "%", 1)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_CreateKey(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Key{Key: String("k"), Title: String("t")}
+
+ mux.HandleFunc("/repos/o/r/keys", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Key)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ key, _, err := client.Repositories.CreateKey(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Repositories.GetKey returned error: %v", err)
+ }
+
+ want := &Key{ID: Int64(1)}
+ if !reflect.DeepEqual(key, want) {
+ t.Errorf("Repositories.GetKey returned %+v, want %+v", key, want)
+ }
+}
+
+func TestRepositoriesService_CreateKey_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.CreateKey(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_EditKey(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Key{Key: String("k"), Title: String("t")}
+
+ mux.HandleFunc("/repos/o/r/keys/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Key)
+ 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}`)
+ })
+
+ key, _, err := client.Repositories.EditKey(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Repositories.EditKey returned error: %v", err)
+ }
+
+ want := &Key{ID: Int64(1)}
+ if !reflect.DeepEqual(key, want) {
+ t.Errorf("Repositories.EditKey returned %+v, want %+v", key, want)
+ }
+}
+
+func TestRepositoriesService_EditKey_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.EditKey(context.Background(), "%", "%", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_DeleteKey(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/keys/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Repositories.DeleteKey(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.DeleteKey returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_DeleteKey_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Repositories.DeleteKey(context.Background(), "%", "%", 1)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_merging.go b/vendor/github.com/google/go-github/github/repos_merging.go
new file mode 100644
index 0000000..04383c1
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_merging.go
@@ -0,0 +1,38 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+)
+
+// RepositoryMergeRequest represents a request to merge a branch in a
+// repository.
+type RepositoryMergeRequest struct {
+ Base *string `json:"base,omitempty"`
+ Head *string `json:"head,omitempty"`
+ CommitMessage *string `json:"commit_message,omitempty"`
+}
+
+// Merge a branch in the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/merging/#perform-a-merge
+func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/merges", owner, repo)
+ req, err := s.client.NewRequest("POST", u, request)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ commit := new(RepositoryCommit)
+ resp, err := s.client.Do(ctx, req, commit)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return commit, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_merging_test.go b/vendor/github.com/google/go-github/github/repos_merging_test.go
new file mode 100644
index 0000000..086f24b
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_merging_test.go
@@ -0,0 +1,48 @@
+// Copyright 2014 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_Merge(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &RepositoryMergeRequest{
+ Base: String("b"),
+ Head: String("h"),
+ CommitMessage: String("c"),
+ }
+
+ mux.HandleFunc("/repos/o/r/merges", func(w http.ResponseWriter, r *http.Request) {
+ v := new(RepositoryMergeRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"sha":"s"}`)
+ })
+
+ commit, _, err := client.Repositories.Merge(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Repositories.Merge returned error: %v", err)
+ }
+
+ want := &RepositoryCommit{SHA: String("s")}
+ if !reflect.DeepEqual(commit, want) {
+ t.Errorf("Repositories.Merge returned %+v, want %+v", commit, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_pages.go b/vendor/github.com/google/go-github/github/repos_pages.go
new file mode 100644
index 0000000..94a95f2
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_pages.go
@@ -0,0 +1,143 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+)
+
+// Pages represents a GitHub Pages site configuration.
+type Pages struct {
+ URL *string `json:"url,omitempty"`
+ Status *string `json:"status,omitempty"`
+ CNAME *string `json:"cname,omitempty"`
+ Custom404 *bool `json:"custom_404,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+}
+
+// PagesError represents a build error for a GitHub Pages site.
+type PagesError struct {
+ Message *string `json:"message,omitempty"`
+}
+
+// PagesBuild represents the build information for a GitHub Pages site.
+type PagesBuild struct {
+ URL *string `json:"url,omitempty"`
+ Status *string `json:"status,omitempty"`
+ Error *PagesError `json:"error,omitempty"`
+ Pusher *User `json:"pusher,omitempty"`
+ Commit *string `json:"commit,omitempty"`
+ Duration *int `json:"duration,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+}
+
+// GetPagesInfo fetches information about a GitHub Pages site.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/pages/#get-information-about-a-pages-site
+func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo string) (*Pages, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pages", owner, repo)
+ 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", mediaTypePagesPreview)
+
+ site := new(Pages)
+ resp, err := s.client.Do(ctx, req, site)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return site, resp, nil
+}
+
+// ListPagesBuilds lists the builds for a GitHub Pages site.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-pages-builds
+func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo string, opt *ListOptions) ([]*PagesBuild, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo)
+ 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
+ }
+
+ var pages []*PagesBuild
+ resp, err := s.client.Do(ctx, req, &pages)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return pages, resp, nil
+}
+
+// GetLatestPagesBuild fetches the latest build information for a GitHub pages site.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-latest-pages-build
+func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ build := new(PagesBuild)
+ resp, err := s.client.Do(ctx, req, build)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return build, resp, nil
+}
+
+// GetPageBuild fetches the specific build information for a GitHub pages site.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-a-specific-pages-build
+func (s *RepositoriesService) GetPageBuild(ctx context.Context, owner, repo string, id int64) (*PagesBuild, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pages/builds/%v", owner, repo, id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ build := new(PagesBuild)
+ resp, err := s.client.Do(ctx, req, build)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return build, resp, nil
+}
+
+// RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/pages/#request-a-page-build
+func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo)
+ req, err := s.client.NewRequest("POST", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypePagesPreview)
+
+ build := new(PagesBuild)
+ resp, err := s.client.Do(ctx, req, build)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return build, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_pages_test.go b/vendor/github.com/google/go-github/github/repos_pages_test.go
new file mode 100644
index 0000000..21a00f9
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_pages_test.go
@@ -0,0 +1,134 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_GetPagesInfo(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pages", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypePagesPreview)
+ fmt.Fprint(w, `{"url":"u","status":"s","cname":"c","custom_404":false,"html_url":"h"}`)
+ })
+
+ page, _, err := client.Repositories.GetPagesInfo(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.GetPagesInfo returned error: %v", err)
+ }
+
+ want := &Pages{URL: String("u"), Status: String("s"), CNAME: String("c"), Custom404: Bool(false), HTMLURL: String("h")}
+ if !reflect.DeepEqual(page, want) {
+ t.Errorf("Repositories.GetPagesInfo returned %+v, want %+v", page, want)
+ }
+}
+
+func TestRepositoriesService_ListPagesBuilds(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pages/builds", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"url":"u","status":"s","commit":"c"}]`)
+ })
+
+ pages, _, err := client.Repositories.ListPagesBuilds(context.Background(), "o", "r", nil)
+ if err != nil {
+ t.Errorf("Repositories.ListPagesBuilds returned error: %v", err)
+ }
+
+ want := []*PagesBuild{{URL: String("u"), Status: String("s"), Commit: String("c")}}
+ if !reflect.DeepEqual(pages, want) {
+ t.Errorf("Repositories.ListPagesBuilds returned %+v, want %+v", pages, want)
+ }
+}
+
+func TestRepositoriesService_ListPagesBuilds_withOptions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pages/builds", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "2",
+ })
+ fmt.Fprint(w, `[]`)
+ })
+
+ _, _, err := client.Repositories.ListPagesBuilds(context.Background(), "o", "r", &ListOptions{Page: 2})
+ if err != nil {
+ t.Errorf("Repositories.ListPagesBuilds returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_GetLatestPagesBuild(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pages/builds/latest", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"url":"u","status":"s","commit":"c"}`)
+ })
+
+ build, _, err := client.Repositories.GetLatestPagesBuild(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.GetLatestPagesBuild returned error: %v", err)
+ }
+
+ want := &PagesBuild{URL: String("u"), Status: String("s"), Commit: String("c")}
+ if !reflect.DeepEqual(build, want) {
+ t.Errorf("Repositories.GetLatestPagesBuild returned %+v, want %+v", build, want)
+ }
+}
+
+func TestRepositoriesService_GetPageBuild(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pages/builds/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"url":"u","status":"s","commit":"c"}`)
+ })
+
+ build, _, err := client.Repositories.GetPageBuild(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.GetPageBuild returned error: %v", err)
+ }
+
+ want := &PagesBuild{URL: String("u"), Status: String("s"), Commit: String("c")}
+ if !reflect.DeepEqual(build, want) {
+ t.Errorf("Repositories.GetPageBuild returned %+v, want %+v", build, want)
+ }
+}
+
+func TestRepositoriesService_RequestPageBuild(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pages/builds", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypePagesPreview)
+ fmt.Fprint(w, `{"url":"u","status":"s"}`)
+ })
+
+ build, _, err := client.Repositories.RequestPageBuild(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.RequestPageBuild returned error: %v", err)
+ }
+
+ want := &PagesBuild{URL: String("u"), Status: String("s")}
+ if !reflect.DeepEqual(build, want) {
+ t.Errorf("Repositories.RequestPageBuild returned %+v, want %+v", build, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_prereceive_hooks.go b/vendor/github.com/google/go-github/github/repos_prereceive_hooks.go
new file mode 100644
index 0000000..cab09f7
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_prereceive_hooks.go
@@ -0,0 +1,110 @@
+// Copyright 2018 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 (
+ "context"
+ "fmt"
+)
+
+// PreReceiveHook represents a GitHub pre-receive hook for a repository.
+type PreReceiveHook struct {
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Enforcement *string `json:"enforcement,omitempty"`
+ ConfigURL *string `json:"configuration_url,omitempty"`
+}
+
+func (p PreReceiveHook) String() string {
+ return Stringify(p)
+}
+
+// ListPreReceiveHooks lists all pre-receive hooks for the specified repository.
+//
+// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#list-pre-receive-hooks
+func (s *RepositoriesService) ListPreReceiveHooks(ctx context.Context, owner, repo string, opt *ListOptions) ([]*PreReceiveHook, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypePreReceiveHooksPreview)
+
+ var hooks []*PreReceiveHook
+ resp, err := s.client.Do(ctx, req, &hooks)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return hooks, resp, nil
+}
+
+// GetPreReceiveHook returns a single specified pre-receive hook.
+//
+// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#get-a-single-pre-receive-hook
+func (s *RepositoriesService) GetPreReceiveHook(ctx context.Context, owner, repo string, id int64) (*PreReceiveHook, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id)
+ 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", mediaTypePreReceiveHooksPreview)
+
+ h := new(PreReceiveHook)
+ resp, err := s.client.Do(ctx, req, h)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return h, resp, nil
+}
+
+// UpdatePreReceiveHook updates a specified pre-receive hook.
+//
+// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#update-pre-receive-hook-enforcement
+func (s *RepositoriesService) UpdatePreReceiveHook(ctx context.Context, owner, repo string, id int64, hook *PreReceiveHook) (*PreReceiveHook, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id)
+ req, err := s.client.NewRequest("PATCH", u, hook)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypePreReceiveHooksPreview)
+
+ h := new(PreReceiveHook)
+ resp, err := s.client.Do(ctx, req, h)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return h, resp, nil
+}
+
+// DeletePreReceiveHook deletes a specified pre-receive hook.
+//
+// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#remove-enforcement-overrides-for-a-pre-receive-hook
+func (s *RepositoriesService) DeletePreReceiveHook(ctx context.Context, owner, repo string, id int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypePreReceiveHooksPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_prereceive_hooks_test.go b/vendor/github.com/google/go-github/github/repos_prereceive_hooks_test.go
new file mode 100644
index 0000000..8660e59
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_prereceive_hooks_test.go
@@ -0,0 +1,135 @@
+// Copyright 2018 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_ListPreReceiveHooks(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pre-receive-hooks", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypePreReceiveHooksPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}, {"id":2}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+
+ hooks, _, err := client.Repositories.ListPreReceiveHooks(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListHooks returned error: %v", err)
+ }
+
+ want := []*PreReceiveHook{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(hooks, want) {
+ t.Errorf("Repositories.ListPreReceiveHooks returned %+v, want %+v", hooks, want)
+ }
+}
+
+func TestRepositoriesService_ListPreReceiveHooks_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.ListPreReceiveHooks(context.Background(), "%", "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_GetPreReceiveHook(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pre-receive-hooks/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypePreReceiveHooksPreview)
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ hook, _, err := client.Repositories.GetPreReceiveHook(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.GetPreReceiveHook returned error: %v", err)
+ }
+
+ want := &PreReceiveHook{ID: Int64(1)}
+ if !reflect.DeepEqual(hook, want) {
+ t.Errorf("Repositories.GetPreReceiveHook returned %+v, want %+v", hook, want)
+ }
+}
+
+func TestRepositoriesService_GetPreReceiveHook_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.GetPreReceiveHook(context.Background(), "%", "%", 1)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_UpdatePreReceiveHook(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &PreReceiveHook{Name: String("t")}
+
+ mux.HandleFunc("/repos/o/r/pre-receive-hooks/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(PreReceiveHook)
+ 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.Repositories.UpdatePreReceiveHook(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Repositories.UpdatePreReceiveHook returned error: %v", err)
+ }
+
+ want := &PreReceiveHook{ID: Int64(1)}
+ if !reflect.DeepEqual(hook, want) {
+ t.Errorf("Repositories.UpdatePreReceiveHook returned %+v, want %+v", hook, want)
+ }
+}
+
+func TestRepositoriesService_PreReceiveHook_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.UpdatePreReceiveHook(context.Background(), "%", "%", 1, nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_DeletePreReceiveHook(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/pre-receive-hooks/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Repositories.DeletePreReceiveHook(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.DeletePreReceiveHook returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_DeletePreReceiveHook_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Repositories.DeletePreReceiveHook(context.Background(), "%", "%", 1)
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/repos_projects.go b/vendor/github.com/google/go-github/github/repos_projects.go
new file mode 100644
index 0000000..d6486d2
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_projects.go
@@ -0,0 +1,69 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+)
+
+// ProjectListOptions specifies the optional parameters to the
+// OrganizationsService.ListProjects and RepositoriesService.ListProjects methods.
+type ProjectListOptions struct {
+ // Indicates the state of the projects to return. Can be either open, closed, or all. Default: open
+ State string `url:"state,omitempty"`
+
+ ListOptions
+}
+
+// ListProjects lists the projects for a repo.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/#list-repository-projects
+func (s *RepositoriesService) ListProjects(ctx context.Context, owner, repo string, opt *ProjectListOptions) ([]*Project, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/projects", owner, repo)
+ 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
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ var projects []*Project
+ resp, err := s.client.Do(ctx, req, &projects)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return projects, resp, nil
+}
+
+// CreateProject creates a GitHub Project for the specified repository.
+//
+// GitHub API docs: https://developer.github.com/v3/projects/#create-a-repository-project
+func (s *RepositoriesService) CreateProject(ctx context.Context, owner, repo string, opt *ProjectOptions) (*Project, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/projects", owner, repo)
+ req, err := s.client.NewRequest("POST", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept headers when APIs fully launch.
+ req.Header.Set("Accept", mediaTypeProjectsPreview)
+
+ project := &Project{}
+ resp, err := s.client.Do(ctx, req, project)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return project, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_projects_test.go b/vendor/github.com/google/go-github/github/repos_projects_test.go
new file mode 100644
index 0000000..2d54eaa
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_projects_test.go
@@ -0,0 +1,68 @@
+// Copyright 2017 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_ListProjects(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/projects", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ProjectListOptions{ListOptions: ListOptions{Page: 2}}
+ projects, _, err := client.Repositories.ListProjects(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListProjects returned error: %v", err)
+ }
+
+ want := []*Project{{ID: Int64(1)}}
+ if !reflect.DeepEqual(projects, want) {
+ t.Errorf("Repositories.ListProjects returned %+v, want %+v", projects, want)
+ }
+}
+
+func TestRepositoriesService_CreateProject(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ProjectOptions{Name: String("Project Name"), Body: String("Project body.")}
+
+ mux.HandleFunc("/repos/o/r/projects", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeProjectsPreview)
+
+ v := &ProjectOptions{}
+ json.NewDecoder(r.Body).Decode(v)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ project, _, err := client.Repositories.CreateProject(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Repositories.CreateProject returned error: %v", err)
+ }
+
+ want := &Project{ID: Int64(1)}
+ if !reflect.DeepEqual(project, want) {
+ t.Errorf("Repositories.CreateProject returned %+v, want %+v", project, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_releases.go b/vendor/github.com/google/go-github/github/repos_releases.go
new file mode 100644
index 0000000..bf58743
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_releases.go
@@ -0,0 +1,370 @@
+// 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 (
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "mime"
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// RepositoryRelease represents a GitHub release in a repository.
+type RepositoryRelease struct {
+ TagName *string `json:"tag_name,omitempty"`
+ TargetCommitish *string `json:"target_commitish,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Body *string `json:"body,omitempty"`
+ Draft *bool `json:"draft,omitempty"`
+ Prerelease *bool `json:"prerelease,omitempty"`
+
+ // The following fields are not used in CreateRelease or EditRelease:
+ ID *int64 `json:"id,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ PublishedAt *Timestamp `json:"published_at,omitempty"`
+ URL *string `json:"url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ AssetsURL *string `json:"assets_url,omitempty"`
+ Assets []ReleaseAsset `json:"assets,omitempty"`
+ UploadURL *string `json:"upload_url,omitempty"`
+ ZipballURL *string `json:"zipball_url,omitempty"`
+ TarballURL *string `json:"tarball_url,omitempty"`
+ Author *User `json:"author,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+func (r RepositoryRelease) String() string {
+ return Stringify(r)
+}
+
+// ReleaseAsset represents a GitHub release asset in a repository.
+type ReleaseAsset struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Label *string `json:"label,omitempty"`
+ State *string `json:"state,omitempty"`
+ ContentType *string `json:"content_type,omitempty"`
+ Size *int `json:"size,omitempty"`
+ DownloadCount *int `json:"download_count,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ BrowserDownloadURL *string `json:"browser_download_url,omitempty"`
+ Uploader *User `json:"uploader,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+}
+
+func (r ReleaseAsset) String() string {
+ return Stringify(r)
+}
+
+// ListReleases lists the releases for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository
+func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryRelease, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases", owner, repo)
+ 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
+ }
+
+ var releases []*RepositoryRelease
+ resp, err := s.client.Do(ctx, req, &releases)
+ if err != nil {
+ return nil, resp, err
+ }
+ return releases, resp, nil
+}
+
+// GetRelease fetches a single release.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release
+func (s *RepositoriesService) GetRelease(ctx context.Context, owner, repo string, id int64) (*RepositoryRelease, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id)
+ return s.getSingleRelease(ctx, u)
+}
+
+// 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(ctx context.Context, owner, repo string) (*RepositoryRelease, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases/latest", owner, repo)
+ return s.getSingleRelease(ctx, 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(ctx context.Context, owner, repo, tag string) (*RepositoryRelease, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases/tags/%s", owner, repo, tag)
+ return s.getSingleRelease(ctx, u)
+}
+
+func (s *RepositoriesService) getSingleRelease(ctx context.Context, url string) (*RepositoryRelease, *Response, error) {
+ req, err := s.client.NewRequest("GET", url, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ release := new(RepositoryRelease)
+ resp, err := s.client.Do(ctx, req, release)
+ if err != nil {
+ return nil, resp, err
+ }
+ return release, resp, nil
+}
+
+// repositoryReleaseRequest is a subset of RepositoryRelease and
+// is used internally by CreateRelease and EditRelease to pass
+// only the known fields for these endpoints.
+//
+// See https://github.com/google/go-github/issues/992 for more
+// information.
+type repositoryReleaseRequest struct {
+ TagName *string `json:"tag_name,omitempty"`
+ TargetCommitish *string `json:"target_commitish,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Body *string `json:"body,omitempty"`
+ Draft *bool `json:"draft,omitempty"`
+ Prerelease *bool `json:"prerelease,omitempty"`
+}
+
+// CreateRelease adds a new release for a repository.
+//
+// Note that only a subset of the release fields are used.
+// See RepositoryRelease for more information.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#create-a-release
+func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo string, release *RepositoryRelease) (*RepositoryRelease, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases", owner, repo)
+
+ releaseReq := &repositoryReleaseRequest{
+ TagName: release.TagName,
+ TargetCommitish: release.TargetCommitish,
+ Name: release.Name,
+ Body: release.Body,
+ Draft: release.Draft,
+ Prerelease: release.Prerelease,
+ }
+
+ req, err := s.client.NewRequest("POST", u, releaseReq)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(RepositoryRelease)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+ return r, resp, nil
+}
+
+// EditRelease edits a repository release.
+//
+// Note that only a subset of the release fields are used.
+// See RepositoryRelease for more information.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release
+func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo string, id int64, release *RepositoryRelease) (*RepositoryRelease, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id)
+
+ releaseReq := &repositoryReleaseRequest{
+ TagName: release.TagName,
+ TargetCommitish: release.TargetCommitish,
+ Name: release.Name,
+ Body: release.Body,
+ Draft: release.Draft,
+ Prerelease: release.Prerelease,
+ }
+
+ req, err := s.client.NewRequest("PATCH", u, releaseReq)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ r := new(RepositoryRelease)
+ resp, err := s.client.Do(ctx, req, r)
+ if err != nil {
+ return nil, resp, err
+ }
+ return r, resp, nil
+}
+
+// DeleteRelease delete a single release from a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#delete-a-release
+func (s *RepositoriesService) DeleteRelease(ctx context.Context, owner, repo string, id int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
+
+// ListReleaseAssets lists the release's assets.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#list-assets-for-a-release
+func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*ReleaseAsset, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id)
+ 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
+ }
+
+ var assets []*ReleaseAsset
+ resp, err := s.client.Do(ctx, req, &assets)
+ if err != nil {
+ return nil, resp, err
+ }
+ return assets, resp, nil
+}
+
+// GetReleaseAsset fetches a single release asset.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release-asset
+func (s *RepositoriesService) GetReleaseAsset(ctx context.Context, owner, repo string, id int64) (*ReleaseAsset, *Response, 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, nil, err
+ }
+
+ asset := new(ReleaseAsset)
+ resp, err := s.client.Do(ctx, req, asset)
+ if err != nil {
+ return nil, resp, err
+ }
+ return asset, resp, nil
+}
+
+// DownloadReleaseAsset downloads a release asset or returns a redirect URL.
+//
+// DownloadReleaseAsset returns an io.ReadCloser that reads the contents of the
+// specified release asset. It is the caller's responsibility to close the ReadCloser.
+// If a redirect is returned, the redirect URL will be returned as a string instead
+// of the io.ReadCloser. Exactly one of rc and redirectURL will be zero.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release-asset
+func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, repo string, id int64) (rc io.ReadCloser, redirectURL string, err 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)
+
+ s.client.clientMu.Lock()
+ defer s.client.clientMu.Unlock()
+
+ var loc string
+ saveRedirect := s.client.client.CheckRedirect
+ s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
+ loc = req.URL.String()
+ return errors.New("disable redirect")
+ }
+ defer func() { s.client.client.CheckRedirect = saveRedirect }()
+
+ req = withContext(ctx, req)
+ resp, err := s.client.client.Do(req)
+ if err != nil {
+ if !strings.Contains(err.Error(), "disable redirect") {
+ return nil, "", err
+ }
+ return nil, loc, nil // Intentionally return no error with valid redirect URL.
+ }
+
+ if err := CheckResponse(resp); err != nil {
+ resp.Body.Close()
+ return nil, "", err
+ }
+
+ return resp.Body, "", nil
+}
+
+// EditReleaseAsset edits a repository release asset.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release-asset
+func (s *RepositoriesService) EditReleaseAsset(ctx context.Context, owner, repo string, id int64, release *ReleaseAsset) (*ReleaseAsset, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id)
+
+ req, err := s.client.NewRequest("PATCH", u, release)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ asset := new(ReleaseAsset)
+ resp, err := s.client.Do(ctx, req, asset)
+ if err != nil {
+ return nil, resp, err
+ }
+ return asset, resp, nil
+}
+
+// DeleteReleaseAsset delete a single release asset from a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#delete-a-release-asset
+func (s *RepositoriesService) DeleteReleaseAsset(ctx context.Context, owner, repo string, id int64) (*Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+ return s.client.Do(ctx, req, nil)
+}
+
+// UploadReleaseAsset creates an asset by uploading a file into a release repository.
+// To upload assets that cannot be represented by an os.File, call NewUploadRequest directly.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/releases/#upload-a-release-asset
+func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, repo string, id int64, opt *UploadOptions, file *os.File) (*ReleaseAsset, *Response, error) {
+ u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id)
+ u, err := addOptions(u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ stat, err := file.Stat()
+ if err != nil {
+ return nil, nil, err
+ }
+ if stat.IsDir() {
+ return nil, nil, errors.New("the asset to upload can't be a directory")
+ }
+
+ mediaType := mime.TypeByExtension(filepath.Ext(file.Name()))
+ req, err := s.client.NewUploadRequest(u, file, stat.Size(), mediaType)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ asset := new(ReleaseAsset)
+ resp, err := s.client.Do(ctx, req, asset)
+ if err != nil {
+ return nil, resp, err
+ }
+ return asset, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_releases_test.go b/vendor/github.com/google/go-github/github/repos_releases_test.go
new file mode 100644
index 0000000..d9a9332
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_releases_test.go
@@ -0,0 +1,385 @@
+// 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 (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestRepositoriesService_ListReleases(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/releases", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ releases, _, err := client.Repositories.ListReleases(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListReleases returned error: %v", err)
+ }
+ want := []*RepositoryRelease{{ID: Int64(1)}}
+ if !reflect.DeepEqual(releases, want) {
+ t.Errorf("Repositories.ListReleases returned %+v, want %+v", releases, want)
+ }
+}
+
+func TestRepositoriesService_GetRelease(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1,"author":{"login":"l"}}`)
+ })
+
+ release, resp, err := client.Repositories.GetRelease(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.GetRelease returned error: %v\n%v", err, resp.Body)
+ }
+
+ want := &RepositoryRelease{ID: Int64(1), Author: &User{Login: String("l")}}
+ if !reflect.DeepEqual(release, want) {
+ t.Errorf("Repositories.GetRelease returned %+v, want %+v", release, want)
+ }
+}
+
+func TestRepositoriesService_GetLatestRelease(t *testing.T) {
+ client, mux, _, teardown := 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(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.GetLatestRelease returned error: %v\n%v", err, resp.Body)
+ }
+
+ want := &RepositoryRelease{ID: Int64(3)}
+ if !reflect.DeepEqual(release, want) {
+ t.Errorf("Repositories.GetLatestRelease returned %+v, want %+v", release, want)
+ }
+}
+
+func TestRepositoriesService_GetReleaseByTag(t *testing.T) {
+ client, mux, _, teardown := 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(context.Background(), "o", "r", "foo")
+ if err != nil {
+ t.Errorf("Repositories.GetReleaseByTag returned error: %v\n%v", err, resp.Body)
+ }
+
+ want := &RepositoryRelease{ID: Int64(13)}
+ if !reflect.DeepEqual(release, want) {
+ t.Errorf("Repositories.GetReleaseByTag returned %+v, want %+v", release, want)
+ }
+}
+
+func TestRepositoriesService_CreateRelease(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &RepositoryRelease{
+ Name: String("v1.0"),
+ // Fields to be removed:
+ ID: Int64(2),
+ CreatedAt: &Timestamp{referenceTime},
+ PublishedAt: &Timestamp{referenceTime},
+ URL: String("http://url/"),
+ HTMLURL: String("http://htmlurl/"),
+ AssetsURL: String("http://assetsurl/"),
+ Assets: []ReleaseAsset{{ID: Int64(5)}},
+ UploadURL: String("http://uploadurl/"),
+ ZipballURL: String("http://zipballurl/"),
+ TarballURL: String("http://tarballurl/"),
+ Author: &User{Name: String("octocat")},
+ NodeID: String("nodeid"),
+ }
+
+ mux.HandleFunc("/repos/o/r/releases", func(w http.ResponseWriter, r *http.Request) {
+ v := new(repositoryReleaseRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ want := &repositoryReleaseRequest{Name: String("v1.0")}
+ if !reflect.DeepEqual(v, want) {
+ t.Errorf("Request body = %+v, want %+v", v, want)
+ }
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ release, _, err := client.Repositories.CreateRelease(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Repositories.CreateRelease returned error: %v", err)
+ }
+
+ want := &RepositoryRelease{ID: Int64(1)}
+ if !reflect.DeepEqual(release, want) {
+ t.Errorf("Repositories.CreateRelease returned %+v, want %+v", release, want)
+ }
+}
+
+func TestRepositoriesService_EditRelease(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &RepositoryRelease{
+ Name: String("n"),
+ // Fields to be removed:
+ ID: Int64(2),
+ CreatedAt: &Timestamp{referenceTime},
+ PublishedAt: &Timestamp{referenceTime},
+ URL: String("http://url/"),
+ HTMLURL: String("http://htmlurl/"),
+ AssetsURL: String("http://assetsurl/"),
+ Assets: []ReleaseAsset{{ID: Int64(5)}},
+ UploadURL: String("http://uploadurl/"),
+ ZipballURL: String("http://zipballurl/"),
+ TarballURL: String("http://tarballurl/"),
+ Author: &User{Name: String("octocat")},
+ NodeID: String("nodeid"),
+ }
+
+ mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(repositoryReleaseRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ want := &repositoryReleaseRequest{Name: String("n")}
+ if !reflect.DeepEqual(v, want) {
+ t.Errorf("Request body = %+v, want %+v", v, want)
+ }
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ release, _, err := client.Repositories.EditRelease(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Repositories.EditRelease returned error: %v", err)
+ }
+ want := &RepositoryRelease{ID: Int64(1)}
+ if !reflect.DeepEqual(release, want) {
+ t.Errorf("Repositories.EditRelease returned = %+v, want %+v", release, want)
+ }
+}
+
+func TestRepositoriesService_DeleteRelease(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Repositories.DeleteRelease(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.DeleteRelease returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_ListReleaseAssets(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/releases/1/assets", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ assets, _, err := client.Repositories.ListReleaseAssets(context.Background(), "o", "r", 1, opt)
+ if err != nil {
+ t.Errorf("Repositories.ListReleaseAssets returned error: %v", err)
+ }
+ want := []*ReleaseAsset{{ID: Int64(1)}}
+ if !reflect.DeepEqual(assets, want) {
+ t.Errorf("Repositories.ListReleaseAssets returned %+v, want %+v", assets, want)
+ }
+}
+
+func TestRepositoriesService_GetReleaseAsset(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ asset, _, err := client.Repositories.GetReleaseAsset(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.GetReleaseAsset returned error: %v", err)
+ }
+ want := &ReleaseAsset{ID: Int64(1)}
+ if !reflect.DeepEqual(asset, want) {
+ t.Errorf("Repositories.GetReleaseAsset returned %+v, want %+v", asset, want)
+ }
+}
+
+func TestRepositoriesService_DownloadReleaseAsset_Stream(t *testing.T) {
+ client, mux, _, teardown := 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.DownloadReleaseAsset(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err)
+ }
+ want := []byte("Hello World")
+ content, err := ioutil.ReadAll(reader)
+ if err != nil {
+ t.Errorf("Repositories.DownloadReleaseAsset returned bad reader: %v", err)
+ }
+ if !bytes.Equal(want, content) {
+ t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", content, want)
+ }
+}
+
+func TestRepositoriesService_DownloadReleaseAsset_Redirect(t *testing.T) {
+ client, mux, _, teardown := 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)
+ http.Redirect(w, r, "/yo", http.StatusFound)
+ })
+
+ _, got, err := client.Repositories.DownloadReleaseAsset(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err)
+ }
+ want := "/yo"
+ if !strings.HasSuffix(got, want) {
+ t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", got, want)
+ }
+}
+
+func TestRepositoriesService_DownloadReleaseAsset_APIError(t *testing.T) {
+ client, mux, _, teardown := 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.WriteHeader(http.StatusNotFound)
+ fmt.Fprint(w, `{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}`)
+ })
+
+ resp, loc, err := client.Repositories.DownloadReleaseAsset(context.Background(), "o", "r", 1)
+ if err == nil {
+ t.Error("Repositories.DownloadReleaseAsset did not return an error")
+ }
+
+ if resp != nil {
+ resp.Close()
+ t.Error("Repositories.DownloadReleaseAsset returned stream, want nil")
+ }
+
+ if loc != "" {
+ t.Errorf(`Repositories.DownloadReleaseAsset returned "%s", want empty ""`, loc)
+ }
+}
+
+func TestRepositoriesService_EditReleaseAsset(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ReleaseAsset{Name: String("n")}
+
+ mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(ReleaseAsset)
+ 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}`)
+ })
+
+ asset, _, err := client.Repositories.EditReleaseAsset(context.Background(), "o", "r", 1, input)
+ if err != nil {
+ t.Errorf("Repositories.EditReleaseAsset returned error: %v", err)
+ }
+ want := &ReleaseAsset{ID: Int64(1)}
+ if !reflect.DeepEqual(asset, want) {
+ t.Errorf("Repositories.EditReleaseAsset returned = %+v, want %+v", asset, want)
+ }
+}
+
+func TestRepositoriesService_DeleteReleaseAsset(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Repositories.DeleteReleaseAsset(context.Background(), "o", "r", 1)
+ if err != nil {
+ t.Errorf("Repositories.DeleteReleaseAsset returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_UploadReleaseAsset(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/releases/1/assets", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Content-Type", "text/plain; charset=utf-8")
+ testHeader(t, r, "Content-Length", "12")
+ testFormValues(t, r, values{"name": "n"})
+ testBody(t, r, "Upload me !\n")
+
+ fmt.Fprintf(w, `{"id":1}`)
+ })
+
+ file, dir, err := openTestFile("upload.txt", "Upload me !\n")
+ if err != nil {
+ t.Fatalf("Unable to create temp file: %v", err)
+ }
+ defer os.RemoveAll(dir)
+
+ opt := &UploadOptions{Name: "n"}
+ asset, _, err := client.Repositories.UploadReleaseAsset(context.Background(), "o", "r", 1, opt, file)
+ if err != nil {
+ t.Errorf("Repositories.UploadReleaseAssert returned error: %v", err)
+ }
+ want := &ReleaseAsset{ID: Int64(1)}
+ if !reflect.DeepEqual(asset, want) {
+ t.Errorf("Repositories.UploadReleaseAssert returned %+v, want %+v", asset, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_stats.go b/vendor/github.com/google/go-github/github/repos_stats.go
new file mode 100644
index 0000000..bb355ae
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_stats.go
@@ -0,0 +1,226 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// ContributorStats represents a contributor to a repository and their
+// weekly contributions to a given repo.
+type ContributorStats struct {
+ Author *Contributor `json:"author,omitempty"`
+ Total *int `json:"total,omitempty"`
+ Weeks []WeeklyStats `json:"weeks,omitempty"`
+}
+
+func (c ContributorStats) String() string {
+ return Stringify(c)
+}
+
+// WeeklyStats represents the number of additions, deletions and commits
+// a Contributor made in a given week.
+type WeeklyStats struct {
+ Week *Timestamp `json:"w,omitempty"`
+ Additions *int `json:"a,omitempty"`
+ Deletions *int `json:"d,omitempty"`
+ Commits *int `json:"c,omitempty"`
+}
+
+func (w WeeklyStats) String() string {
+ return Stringify(w)
+}
+
+// ListContributorsStats gets a repo's contributor list with additions,
+// deletions and commit counts.
+//
+// If this is the first time these statistics are requested for the given
+// repository, this method will return an *AcceptedError and a status code of
+// 202. This is because this is the status that GitHub returns to signify that
+// it is now computing the requested statistics. A follow up request, after a
+// delay of a second or so, should result in a successful request.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/statistics/#contributors
+func (s *RepositoriesService) ListContributorsStats(ctx context.Context, owner, repo string) ([]*ContributorStats, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/stats/contributors", owner, repo)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var contributorStats []*ContributorStats
+ resp, err := s.client.Do(ctx, req, &contributorStats)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return contributorStats, resp, nil
+}
+
+// WeeklyCommitActivity represents the weekly commit activity for a repository.
+// The days array is a group of commits per day, starting on Sunday.
+type WeeklyCommitActivity struct {
+ Days []int `json:"days,omitempty"`
+ Total *int `json:"total,omitempty"`
+ Week *Timestamp `json:"week,omitempty"`
+}
+
+func (w WeeklyCommitActivity) String() string {
+ return Stringify(w)
+}
+
+// ListCommitActivity returns the last year of commit activity
+// grouped by week. The days array is a group of commits per day,
+// starting on Sunday.
+//
+// If this is the first time these statistics are requested for the given
+// repository, this method will return an *AcceptedError and a status code of
+// 202. This is because this is the status that GitHub returns to signify that
+// it is now computing the requested statistics. A follow up request, after a
+// delay of a second or so, should result in a successful request.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/statistics/#commit-activity
+func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, repo string) ([]*WeeklyCommitActivity, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/stats/commit_activity", owner, repo)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var weeklyCommitActivity []*WeeklyCommitActivity
+ resp, err := s.client.Do(ctx, req, &weeklyCommitActivity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return weeklyCommitActivity, resp, nil
+}
+
+// ListCodeFrequency returns a weekly aggregate of the number of additions and
+// deletions pushed to a repository. Returned WeeklyStats will contain
+// additions and deletions, but not total commits.
+//
+// If this is the first time these statistics are requested for the given
+// repository, this method will return an *AcceptedError and a status code of
+// 202. This is because this is the status that GitHub returns to signify that
+// it is now computing the requested statistics. A follow up request, after a
+// delay of a second or so, should result in a successful request.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/statistics/#code-frequency
+func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo string) ([]*WeeklyStats, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var weeks [][]int
+ resp, err := s.client.Do(ctx, req, &weeks)
+
+ // convert int slices into WeeklyStats
+ var stats []*WeeklyStats
+ for _, week := range weeks {
+ if len(week) != 3 {
+ continue
+ }
+ stat := &WeeklyStats{
+ Week: &Timestamp{time.Unix(int64(week[0]), 0)},
+ Additions: Int(week[1]),
+ Deletions: Int(week[2]),
+ }
+ stats = append(stats, stat)
+ }
+
+ return stats, resp, err
+}
+
+// RepositoryParticipation is the number of commits by everyone
+// who has contributed to the repository (including the owner)
+// as well as the number of commits by the owner themself.
+type RepositoryParticipation struct {
+ All []int `json:"all,omitempty"`
+ Owner []int `json:"owner,omitempty"`
+}
+
+func (r RepositoryParticipation) String() string {
+ return Stringify(r)
+}
+
+// ListParticipation returns the total commit counts for the 'owner'
+// and total commit counts in 'all'. 'all' is everyone combined,
+// including the 'owner' in the last 52 weeks. If you’d like to get
+// the commit counts for non-owners, you can subtract 'all' from 'owner'.
+//
+// The array order is oldest week (index 0) to most recent week.
+//
+// If this is the first time these statistics are requested for the given
+// repository, this method will return an *AcceptedError and a status code of
+// 202. This is because this is the status that GitHub returns to signify that
+// it is now computing the requested statistics. A follow up request, after a
+// delay of a second or so, should result in a successful request.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/statistics/#participation
+func (s *RepositoriesService) ListParticipation(ctx context.Context, owner, repo string) (*RepositoryParticipation, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/stats/participation", owner, repo)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ participation := new(RepositoryParticipation)
+ resp, err := s.client.Do(ctx, req, participation)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return participation, resp, nil
+}
+
+// PunchCard represents the number of commits made during a given hour of a
+// day of the week.
+type PunchCard struct {
+ Day *int // Day of the week (0-6: =Sunday - Saturday).
+ Hour *int // Hour of day (0-23).
+ Commits *int // Number of commits.
+}
+
+// ListPunchCard returns the number of commits per hour in each day.
+//
+// If this is the first time these statistics are requested for the given
+// repository, this method will return an *AcceptedError and a status code of
+// 202. This is because this is the status that GitHub returns to signify that
+// it is now computing the requested statistics. A follow up request, after a
+// delay of a second or so, should result in a successful request.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/statistics/#punch-card
+func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo string) ([]*PunchCard, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var results [][]int
+ resp, err := s.client.Do(ctx, req, &results)
+
+ // convert int slices into Punchcards
+ var cards []*PunchCard
+ for _, result := range results {
+ if len(result) != 3 {
+ continue
+ }
+ card := &PunchCard{
+ Day: Int(result[0]),
+ Hour: Int(result[1]),
+ Commits: Int(result[2]),
+ }
+ cards = append(cards, card)
+ }
+
+ return cards, resp, err
+}
diff --git a/vendor/github.com/google/go-github/github/repos_stats_test.go b/vendor/github.com/google/go-github/github/repos_stats_test.go
new file mode 100644
index 0000000..e0d7be7
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_stats_test.go
@@ -0,0 +1,211 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestRepositoriesService_ListContributorsStats(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/stats/contributors", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ fmt.Fprint(w, `
+[
+ {
+ "author": {
+ "id": 1
+ },
+ "total": 135,
+ "weeks": [
+ {
+ "w": 1367712000,
+ "a": 6898,
+ "d": 77,
+ "c": 10
+ }
+ ]
+ }
+]
+`)
+ })
+
+ stats, _, err := client.Repositories.ListContributorsStats(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("RepositoriesService.ListContributorsStats returned error: %v", err)
+ }
+
+ want := []*ContributorStats{
+ {
+ Author: &Contributor{
+ ID: Int64(1),
+ },
+ Total: Int(135),
+ Weeks: []WeeklyStats{
+ {
+ Week: &Timestamp{time.Date(2013, time.May, 05, 00, 00, 00, 0, time.UTC).Local()},
+ Additions: Int(6898),
+ Deletions: Int(77),
+ Commits: Int(10),
+ },
+ },
+ },
+ }
+
+ if !reflect.DeepEqual(stats, want) {
+ t.Errorf("RepositoriesService.ListContributorsStats returned %+v, want %+v", stats, want)
+ }
+}
+
+func TestRepositoriesService_ListCommitActivity(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/stats/commit_activity", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ fmt.Fprint(w, `
+[
+ {
+ "days": [0, 3, 26, 20, 39, 1, 0],
+ "total": 89,
+ "week": 1336280400
+ }
+]
+`)
+ })
+
+ activity, _, err := client.Repositories.ListCommitActivity(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("RepositoriesService.ListCommitActivity returned error: %v", err)
+ }
+
+ want := []*WeeklyCommitActivity{
+ {
+ Days: []int{0, 3, 26, 20, 39, 1, 0},
+ Total: Int(89),
+ Week: &Timestamp{time.Date(2012, time.May, 06, 05, 00, 00, 0, time.UTC).Local()},
+ },
+ }
+
+ if !reflect.DeepEqual(activity, want) {
+ t.Errorf("RepositoriesService.ListCommitActivity returned %+v, want %+v", activity, want)
+ }
+}
+
+func TestRepositoriesService_ListCodeFrequency(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/stats/code_frequency", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ fmt.Fprint(w, `[[1302998400, 1124, -435]]`)
+ })
+
+ code, _, err := client.Repositories.ListCodeFrequency(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("RepositoriesService.ListCodeFrequency returned error: %v", err)
+ }
+
+ want := []*WeeklyStats{{
+ Week: &Timestamp{time.Date(2011, time.April, 17, 00, 00, 00, 0, time.UTC).Local()},
+ Additions: Int(1124),
+ Deletions: Int(-435),
+ }}
+
+ if !reflect.DeepEqual(code, want) {
+ t.Errorf("RepositoriesService.ListCodeFrequency returned %+v, want %+v", code, want)
+ }
+}
+
+func TestRepositoriesService_Participation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/stats/participation", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ fmt.Fprint(w, `
+{
+ "all": [
+ 11,21,15,2,8,1,8,23,17,21,11,10,33,
+ 91,38,34,22,23,32,3,43,87,71,18,13,5,
+ 13,16,66,27,12,45,110,117,13,8,18,9,19,
+ 26,39,12,20,31,46,91,45,10,24,9,29,7
+ ],
+ "owner": [
+ 3,2,3,0,2,0,5,14,7,9,1,5,0,
+ 48,19,2,0,1,10,2,23,40,35,8,8,2,
+ 10,6,30,0,2,9,53,104,3,3,10,4,7,
+ 11,21,4,4,22,26,63,11,2,14,1,10,3
+ ]
+}
+`)
+ })
+
+ participation, _, err := client.Repositories.ListParticipation(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("RepositoriesService.ListParticipation returned error: %v", err)
+ }
+
+ want := &RepositoryParticipation{
+ All: []int{
+ 11, 21, 15, 2, 8, 1, 8, 23, 17, 21, 11, 10, 33,
+ 91, 38, 34, 22, 23, 32, 3, 43, 87, 71, 18, 13, 5,
+ 13, 16, 66, 27, 12, 45, 110, 117, 13, 8, 18, 9, 19,
+ 26, 39, 12, 20, 31, 46, 91, 45, 10, 24, 9, 29, 7,
+ },
+ Owner: []int{
+ 3, 2, 3, 0, 2, 0, 5, 14, 7, 9, 1, 5, 0,
+ 48, 19, 2, 0, 1, 10, 2, 23, 40, 35, 8, 8, 2,
+ 10, 6, 30, 0, 2, 9, 53, 104, 3, 3, 10, 4, 7,
+ 11, 21, 4, 4, 22, 26, 63, 11, 2, 14, 1, 10, 3,
+ },
+ }
+
+ if !reflect.DeepEqual(participation, want) {
+ t.Errorf("RepositoriesService.ListParticipation returned %+v, want %+v", participation, want)
+ }
+}
+
+func TestRepositoriesService_ListPunchCard(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/stats/punch_card", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ fmt.Fprint(w, `[
+ [0, 0, 5],
+ [0, 1, 43],
+ [0, 2, 21]
+ ]`)
+ })
+
+ card, _, err := client.Repositories.ListPunchCard(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("RepositoriesService.ListPunchCard returned error: %v", err)
+ }
+
+ want := []*PunchCard{
+ {Day: Int(0), Hour: Int(0), Commits: Int(5)},
+ {Day: Int(0), Hour: Int(1), Commits: Int(43)},
+ {Day: Int(0), Hour: Int(2), Commits: Int(21)},
+ }
+
+ if !reflect.DeepEqual(card, want) {
+ t.Errorf("RepositoriesService.ListPunchCard returned %+v, want %+v", card, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_statuses.go b/vendor/github.com/google/go-github/github/repos_statuses.go
new file mode 100644
index 0000000..f94fdc8
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_statuses.go
@@ -0,0 +1,129 @@
+// 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// RepoStatus represents the status of a repository at a particular reference.
+type RepoStatus struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+
+ // State is the current state of the repository. Possible values are:
+ // pending, success, error, or failure.
+ State *string `json:"state,omitempty"`
+
+ // TargetURL is the URL of the page representing this status. It will be
+ // linked from the GitHub UI to allow users to see the source of the status.
+ TargetURL *string `json:"target_url,omitempty"`
+
+ // Description is a short high level summary of the status.
+ Description *string `json:"description,omitempty"`
+
+ // A string label to differentiate this status from the statuses of other systems.
+ Context *string `json:"context,omitempty"`
+
+ Creator *User `json:"creator,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+}
+
+func (r RepoStatus) String() string {
+ return Stringify(r)
+}
+
+// ListStatuses lists the statuses of a repository at the specified
+// reference. ref can be a SHA, a branch name, or a tag name.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref
+func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref string, opt *ListOptions) ([]*RepoStatus, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/commits/%v/statuses", owner, repo, ref)
+ 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
+ }
+
+ var statuses []*RepoStatus
+ resp, err := s.client.Do(ctx, req, &statuses)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return statuses, resp, nil
+}
+
+// CreateStatus creates a new status for a repository at the specified
+// reference. Ref can be a SHA, a branch name, or a tag name.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/statuses/#create-a-status
+func (s *RepositoriesService) CreateStatus(ctx context.Context, owner, repo, ref string, status *RepoStatus) (*RepoStatus, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/statuses/%v", owner, repo, ref)
+ req, err := s.client.NewRequest("POST", u, status)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ repoStatus := new(RepoStatus)
+ resp, err := s.client.Do(ctx, req, repoStatus)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return repoStatus, resp, nil
+}
+
+// CombinedStatus represents the combined status of a repository at a particular reference.
+type CombinedStatus struct {
+ // State is the combined state of the repository. Possible values are:
+ // failure, pending, or success.
+ State *string `json:"state,omitempty"`
+
+ Name *string `json:"name,omitempty"`
+ SHA *string `json:"sha,omitempty"`
+ TotalCount *int `json:"total_count,omitempty"`
+ Statuses []RepoStatus `json:"statuses,omitempty"`
+
+ CommitURL *string `json:"commit_url,omitempty"`
+ RepositoryURL *string `json:"repository_url,omitempty"`
+}
+
+func (s CombinedStatus) String() string {
+ return Stringify(s)
+}
+
+// GetCombinedStatus returns the combined status of a repository at the specified
+// reference. ref can be a SHA, a branch name, or a tag name.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref
+func (s *RepositoriesService) GetCombinedStatus(ctx context.Context, owner, repo, ref string, opt *ListOptions) (*CombinedStatus, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/commits/%v/status", owner, repo, ref)
+ 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
+ }
+
+ status := new(CombinedStatus)
+ resp, err := s.client.Do(ctx, req, status)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return status, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_statuses_test.go b/vendor/github.com/google/go-github/github/repos_statuses_test.go
new file mode 100644
index 0000000..b556b71
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_statuses_test.go
@@ -0,0 +1,103 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestRepositoriesService_ListStatuses(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/commits/r/statuses", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ statuses, _, err := client.Repositories.ListStatuses(context.Background(), "o", "r", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListStatuses returned error: %v", err)
+ }
+
+ want := []*RepoStatus{{ID: Int64(1)}}
+ if !reflect.DeepEqual(statuses, want) {
+ t.Errorf("Repositories.ListStatuses returned %+v, want %+v", statuses, want)
+ }
+}
+
+func TestRepositoriesService_ListStatuses_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.ListStatuses(context.Background(), "%", "r", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_CreateStatus(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &RepoStatus{State: String("s"), TargetURL: String("t"), Description: String("d")}
+
+ mux.HandleFunc("/repos/o/r/statuses/r", func(w http.ResponseWriter, r *http.Request) {
+ v := new(RepoStatus)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ status, _, err := client.Repositories.CreateStatus(context.Background(), "o", "r", "r", input)
+ if err != nil {
+ t.Errorf("Repositories.CreateStatus returned error: %v", err)
+ }
+
+ want := &RepoStatus{ID: Int64(1)}
+ if !reflect.DeepEqual(status, want) {
+ t.Errorf("Repositories.CreateStatus returned %+v, want %+v", status, want)
+ }
+}
+
+func TestRepositoriesService_CreateStatus_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.CreateStatus(context.Background(), "%", "r", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_GetCombinedStatus(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/commits/r/status", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `{"state":"success", "statuses":[{"id":1}]}`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ status, _, err := client.Repositories.GetCombinedStatus(context.Background(), "o", "r", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.GetCombinedStatus returned error: %v", err)
+ }
+
+ want := &CombinedStatus{State: String("success"), Statuses: []RepoStatus{{ID: Int64(1)}}}
+ if !reflect.DeepEqual(status, want) {
+ t.Errorf("Repositories.GetCombinedStatus returned %+v, want %+v", status, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_test.go b/vendor/github.com/google/go-github/github/repos_test.go
new file mode 100644
index 0000000..80aca7a
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_test.go
@@ -0,0 +1,1238 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestRepositoriesService_List_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview}
+ mux.HandleFunc("/user/repos", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ fmt.Fprint(w, `[{"id":1},{"id":2}]`)
+ })
+
+ repos, _, err := client.Repositories.List(context.Background(), "", nil)
+ if err != nil {
+ t.Errorf("Repositories.List returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(repos, want) {
+ t.Errorf("Repositories.List returned %+v, want %+v", repos, want)
+ }
+}
+
+func TestRepositoriesService_List_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview}
+ mux.HandleFunc("/users/u/repos", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ testFormValues(t, r, values{
+ "visibility": "public",
+ "affiliation": "owner,collaborator",
+ "sort": "created",
+ "direction": "asc",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &RepositoryListOptions{
+ Visibility: "public",
+ Affiliation: "owner,collaborator",
+ Sort: "created",
+ Direction: "asc",
+ ListOptions: ListOptions{Page: 2},
+ }
+ repos, _, err := client.Repositories.List(context.Background(), "u", opt)
+ if err != nil {
+ t.Errorf("Repositories.List returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}}
+ if !reflect.DeepEqual(repos, want) {
+ t.Errorf("Repositories.List returned %+v, want %+v", repos, want)
+ }
+}
+
+func TestRepositoriesService_List_specifiedUser_type(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview}
+ mux.HandleFunc("/users/u/repos", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ testFormValues(t, r, values{
+ "type": "owner",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &RepositoryListOptions{
+ Type: "owner",
+ }
+ repos, _, err := client.Repositories.List(context.Background(), "u", opt)
+ if err != nil {
+ t.Errorf("Repositories.List returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}}
+ if !reflect.DeepEqual(repos, want) {
+ t.Errorf("Repositories.List returned %+v, want %+v", repos, want)
+ }
+}
+
+func TestRepositoriesService_List_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.List(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_ListByOrg(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview}
+ mux.HandleFunc("/orgs/o/repos", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ testFormValues(t, r, values{
+ "type": "forks",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &RepositoryListByOrgOptions{"forks", ListOptions{Page: 2}}
+ repos, _, err := client.Repositories.ListByOrg(context.Background(), "o", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListByOrg returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}}
+ if !reflect.DeepEqual(repos, want) {
+ t.Errorf("Repositories.ListByOrg returned %+v, want %+v", repos, want)
+ }
+}
+
+func TestRepositoriesService_ListByOrg_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.ListByOrg(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_ListAll(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repositories", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "since": "1",
+ })
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &RepositoryListAllOptions{1}
+ repos, _, err := client.Repositories.ListAll(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Repositories.ListAll returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}}
+ if !reflect.DeepEqual(repos, want) {
+ t.Errorf("Repositories.ListAll returned %+v, want %+v", repos, want)
+ }
+}
+
+func TestRepositoriesService_Create_user(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Repository{Name: String("n")}
+
+ mux.HandleFunc("/user/repos", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Repository)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ repo, _, err := client.Repositories.Create(context.Background(), "", input)
+ if err != nil {
+ t.Errorf("Repositories.Create returned error: %v", err)
+ }
+
+ want := &Repository{ID: Int64(1)}
+ if !reflect.DeepEqual(repo, want) {
+ t.Errorf("Repositories.Create returned %+v, want %+v", repo, want)
+ }
+}
+
+func TestRepositoriesService_Create_org(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Repository{Name: String("n")}
+
+ mux.HandleFunc("/orgs/o/repos", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Repository)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ repo, _, err := client.Repositories.Create(context.Background(), "o", input)
+ if err != nil {
+ t.Errorf("Repositories.Create returned error: %v", err)
+ }
+
+ want := &Repository{ID: Int64(1)}
+ if !reflect.DeepEqual(repo, want) {
+ t.Errorf("Repositories.Create returned %+v, want %+v", repo, want)
+ }
+}
+
+func TestRepositoriesService_Create_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.Create(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_Get(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview}
+ mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`)
+ })
+
+ repo, _, err := client.Repositories.Get(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.Get returned error: %v", err)
+ }
+
+ want := &Repository{ID: Int64(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)
+ }
+}
+
+func TestRepositoriesService_GetCodeOfConduct(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/community/code_of_conduct", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeCodesOfConductPreview)
+ fmt.Fprint(w, `{
+ "key": "key",
+ "name": "name",
+ "url": "url",
+ "body": "body"}`,
+ )
+ })
+
+ coc, _, err := client.Repositories.GetCodeOfConduct(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.GetCodeOfConduct returned error: %v", err)
+ }
+
+ want := &CodeOfConduct{
+ Key: String("key"),
+ Name: String("name"),
+ URL: String("url"),
+ Body: String("body"),
+ }
+
+ if !reflect.DeepEqual(coc, want) {
+ t.Errorf("Repositories.Get returned %+v, want %+v", coc, want)
+ }
+}
+
+func TestRepositoriesService_GetByID(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repositories/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`)
+ })
+
+ repo, _, err := client.Repositories.GetByID(context.Background(), 1)
+ if err != nil {
+ t.Fatalf("Repositories.GetByID returned error: %v", err)
+ }
+
+ want := &Repository{ID: Int64(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.GetByID returned %+v, want %+v", repo, want)
+ }
+}
+
+func TestRepositoriesService_Edit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ i := true
+ input := &Repository{HasIssues: &i}
+
+ mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Repository)
+ 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}`)
+ })
+
+ repo, _, err := client.Repositories.Edit(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Repositories.Edit returned error: %v", err)
+ }
+
+ want := &Repository{ID: Int64(1)}
+ if !reflect.DeepEqual(repo, want) {
+ t.Errorf("Repositories.Edit returned %+v, want %+v", repo, want)
+ }
+}
+
+func TestRepositoriesService_Delete(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Repositories.Delete(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.Delete returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_Get_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.Get(context.Background(), "%", "r")
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_Edit_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.Edit(context.Background(), "%", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_ListContributors(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/contributors", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "anon": "true",
+ "page": "2",
+ })
+ fmt.Fprint(w, `[{"contributions":42}]`)
+ })
+
+ opts := &ListContributorsOptions{Anon: "true", ListOptions: ListOptions{Page: 2}}
+ contributors, _, err := client.Repositories.ListContributors(context.Background(), "o", "r", opts)
+ if err != nil {
+ t.Errorf("Repositories.ListContributors returned error: %v", err)
+ }
+
+ want := []*Contributor{{Contributions: Int(42)}}
+ if !reflect.DeepEqual(contributors, want) {
+ t.Errorf("Repositories.ListContributors returned %+v, want %+v", contributors, want)
+ }
+}
+
+func TestRepositoriesService_ListLanguages(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/languages", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"go":1}`)
+ })
+
+ languages, _, err := client.Repositories.ListLanguages(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.ListLanguages returned error: %v", err)
+ }
+
+ want := map[string]int{"go": 1}
+ if !reflect.DeepEqual(languages, want) {
+ t.Errorf("Repositories.ListLanguages returned %+v, want %+v", languages, want)
+ }
+}
+
+func TestRepositoriesService_ListTeams(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/teams", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ teams, _, err := client.Repositories.ListTeams(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListTeams returned error: %v", err)
+ }
+
+ want := []*Team{{ID: Int64(1)}}
+ if !reflect.DeepEqual(teams, want) {
+ t.Errorf("Repositories.ListTeams returned %+v, want %+v", teams, want)
+ }
+}
+
+func TestRepositoriesService_ListTags(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/tags", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"name":"n", "commit" : {"sha" : "s", "url" : "u"}, "zipball_url": "z", "tarball_url": "t"}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ tags, _, err := client.Repositories.ListTags(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListTags returned error: %v", err)
+ }
+
+ want := []*RepositoryTag{
+ {
+ Name: String("n"),
+ Commit: &Commit{
+ SHA: String("s"),
+ URL: String("u"),
+ },
+ ZipballURL: String("z"),
+ TarballURL: String("t"),
+ },
+ }
+ if !reflect.DeepEqual(tags, want) {
+ t.Errorf("Repositories.ListTags returned %+v, want %+v", tags, want)
+ }
+}
+
+func TestRepositoriesService_ListBranches(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ // TODO: remove custom Accept header when this API fully launches
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"name":"master", "commit" : {"sha" : "a57781", "url" : "https://api.github.com/repos/o/r/commits/a57781"}}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ branches, _, err := client.Repositories.ListBranches(context.Background(), "o", "r", opt)
+ if err != nil {
+ t.Errorf("Repositories.ListBranches returned error: %v", err)
+ }
+
+ want := []*Branch{{Name: String("master"), Commit: &RepositoryCommit{SHA: String("a57781"), URL: String("https://api.github.com/repos/o/r/commits/a57781")}}}
+ if !reflect.DeepEqual(branches, want) {
+ t.Errorf("Repositories.ListBranches returned %+v, want %+v", branches, want)
+ }
+}
+
+func TestRepositoriesService_GetBranch(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ // TODO: remove custom Accept header when this API fully launches
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true}`)
+ })
+
+ branch, _, err := client.Repositories.GetBranch(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.GetBranch returned error: %v", err)
+ }
+
+ want := &Branch{
+ Name: String("n"),
+ Commit: &RepositoryCommit{
+ SHA: String("s"),
+ Commit: &Commit{
+ Message: String("m"),
+ },
+ },
+ Protected: Bool(true),
+ }
+
+ if !reflect.DeepEqual(branch, want) {
+ t.Errorf("Repositories.GetBranch returned %+v, want %+v", branch, want)
+ }
+}
+
+func TestRepositoriesService_GetBranchProtection(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
+ v := new(ProtectionRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "GET")
+ // TODO: remove custom Accept header when this API fully launches
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ fmt.Fprintf(w, `{
+ "required_status_checks":{
+ "strict":true,
+ "contexts":["continuous-integration"]
+ },
+ "required_pull_request_reviews":{
+ "dismissal_restrictions":{
+ "users":[{
+ "id":3,
+ "login":"u"
+ }],
+ "teams":[{
+ "id":4,
+ "slug":"t"
+ }]
+ },
+ "dismiss_stale_reviews":true,
+ "require_code_owner_reviews":true,
+ "required_approving_review_count":1
+ },
+ "enforce_admins":{
+ "url":"/repos/o/r/branches/b/protection/enforce_admins",
+ "enabled":true
+ },
+ "restrictions":{
+ "users":[{"id":1,"login":"u"}],
+ "teams":[{"id":2,"slug":"t"}]
+ }
+ }`)
+ })
+
+ protection, _, err := client.Repositories.GetBranchProtection(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.GetBranchProtection returned error: %v", err)
+ }
+
+ want := &Protection{
+ RequiredStatusChecks: &RequiredStatusChecks{
+ Strict: true,
+ Contexts: []string{"continuous-integration"},
+ },
+ RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
+ DismissStaleReviews: true,
+ DismissalRestrictions: DismissalRestrictions{
+ Users: []*User{
+ {Login: String("u"), ID: Int64(3)},
+ },
+ Teams: []*Team{
+ {Slug: String("t"), ID: Int64(4)},
+ },
+ },
+ RequireCodeOwnerReviews: true,
+ RequiredApprovingReviewCount: 1,
+ },
+ EnforceAdmins: &AdminEnforcement{
+ URL: String("/repos/o/r/branches/b/protection/enforce_admins"),
+ Enabled: true,
+ },
+ Restrictions: &BranchRestrictions{
+ Users: []*User{
+ {Login: String("u"), ID: Int64(1)},
+ },
+ Teams: []*Team{
+ {Slug: String("t"), ID: Int64(2)},
+ },
+ },
+ }
+ if !reflect.DeepEqual(protection, want) {
+ t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want)
+ }
+}
+
+func TestRepositoriesService_UpdateBranchProtection(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &ProtectionRequest{
+ RequiredStatusChecks: &RequiredStatusChecks{
+ Strict: true,
+ Contexts: []string{"continuous-integration"},
+ },
+ RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
+ DismissStaleReviews: true,
+ DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
+ Users: &[]string{"uu"},
+ Teams: &[]string{"tt"},
+ },
+ },
+ Restrictions: &BranchRestrictionsRequest{
+ Users: []string{"u"},
+ Teams: []string{"t"},
+ },
+ }
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
+ v := new(ProtectionRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PUT")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ // TODO: remove custom Accept header when this API fully launches
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ fmt.Fprintf(w, `{
+ "required_status_checks":{
+ "strict":true,
+ "contexts":["continuous-integration"]
+ },
+ "required_pull_request_reviews":{
+ "dismissal_restrictions":{
+ "users":[{
+ "id":3,
+ "login":"uu"
+ }],
+ "teams":[{
+ "id":4,
+ "slug":"tt"
+ }]
+ },
+ "dismiss_stale_reviews":true,
+ "require_code_owner_reviews":true
+ },
+ "restrictions":{
+ "users":[{"id":1,"login":"u"}],
+ "teams":[{"id":2,"slug":"t"}]
+ }
+ }`)
+ })
+
+ protection, _, err := client.Repositories.UpdateBranchProtection(context.Background(), "o", "r", "b", input)
+ if err != nil {
+ t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
+ }
+
+ want := &Protection{
+ RequiredStatusChecks: &RequiredStatusChecks{
+ Strict: true,
+ Contexts: []string{"continuous-integration"},
+ },
+ RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
+ DismissStaleReviews: true,
+ DismissalRestrictions: DismissalRestrictions{
+ Users: []*User{
+ {Login: String("uu"), ID: Int64(3)},
+ },
+ Teams: []*Team{
+ {Slug: String("tt"), ID: Int64(4)},
+ },
+ },
+ RequireCodeOwnerReviews: true,
+ },
+ Restrictions: &BranchRestrictions{
+ Users: []*User{
+ {Login: String("u"), ID: Int64(1)},
+ },
+ Teams: []*Team{
+ {Slug: String("t"), ID: Int64(2)},
+ },
+ },
+ }
+ if !reflect.DeepEqual(protection, want) {
+ t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
+ }
+}
+
+func TestRepositoriesService_RemoveBranchProtection(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ // TODO: remove custom Accept header when this API fully launches
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Repositories.RemoveBranchProtection(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.RemoveBranchProtection returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_ListLanguages_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Repositories.ListLanguages(context.Background(), "%", "%")
+ testURLParseError(t, err)
+}
+
+func TestRepositoriesService_License(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/license", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"name": "LICENSE", "path": "LICENSE", "license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","featured":true}}`)
+ })
+
+ got, _, err := client.Repositories.License(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.License returned error: %v", err)
+ }
+
+ want := &RepositoryLicense{
+ Name: String("LICENSE"),
+ Path: String("LICENSE"),
+ License: &License{
+ Name: String("MIT License"),
+ Key: String("mit"),
+ SPDXID: String("MIT"),
+ URL: String("https://api.github.com/licenses/mit"),
+ Featured: Bool(true),
+ },
+ }
+
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.License returned %+v, want %+v", got, want)
+ }
+}
+
+func TestRepositoriesService_GetRequiredStatusChecks(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) {
+ v := new(ProtectionRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "GET")
+ // TODO: remove custom Accept header when this API fully launches
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ fmt.Fprint(w, `{"strict": true,"contexts": ["x","y","z"]}`)
+ })
+
+ checks, _, err := client.Repositories.GetRequiredStatusChecks(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.GetRequiredStatusChecks returned error: %v", err)
+ }
+
+ want := &RequiredStatusChecks{
+ Strict: true,
+ Contexts: []string{"x", "y", "z"},
+ }
+ if !reflect.DeepEqual(checks, want) {
+ t.Errorf("Repositories.GetRequiredStatusChecks returned %+v, want %+v", checks, want)
+ }
+}
+
+func TestRepositoriesService_UpdateRequiredStatusChecks(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &RequiredStatusChecksRequest{
+ Strict: Bool(true),
+ Contexts: []string{"continuous-integration"},
+ }
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) {
+ v := new(RequiredStatusChecksRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+ testHeader(t, r, "Accept", mediaTypeV3)
+ fmt.Fprintf(w, `{"strict":true,"contexts":["continuous-integration"]}`)
+ })
+
+ statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(context.Background(), "o", "r", "b", input)
+ if err != nil {
+ t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err)
+ }
+
+ want := &RequiredStatusChecks{
+ Strict: true,
+ Contexts: []string{"continuous-integration"},
+ }
+ if !reflect.DeepEqual(statusChecks, want) {
+ t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want)
+ }
+}
+
+func TestRepositoriesService_ListRequiredStatusChecksContexts(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks/contexts", func(w http.ResponseWriter, r *http.Request) {
+ v := new(ProtectionRequest)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "GET")
+ // TODO: remove custom Accept header when this API fully launches
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ fmt.Fprint(w, `["x", "y", "z"]`)
+ })
+
+ contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.ListRequiredStatusChecksContexts returned error: %v", err)
+ }
+
+ want := []string{"x", "y", "z"}
+ if !reflect.DeepEqual(contexts, want) {
+ t.Errorf("Repositories.ListRequiredStatusChecksContexts returned %+v, want %+v", contexts, want)
+ }
+}
+
+func TestRepositoriesService_GetPullRequestReviewEnforcement(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ // TODO: remove custom Accept header when this API fully launches
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ fmt.Fprintf(w, `{
+ "dismissal_restrictions":{
+ "users":[{"id":1,"login":"u"}],
+ "teams":[{"id":2,"slug":"t"}]
+ },
+ "dismiss_stale_reviews":true,
+ "require_code_owner_reviews":true,
+ "required_approving_review_count":1
+ }`)
+ })
+
+ enforcement, _, err := client.Repositories.GetPullRequestReviewEnforcement(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.GetPullRequestReviewEnforcement returned error: %v", err)
+ }
+
+ want := &PullRequestReviewsEnforcement{
+ DismissStaleReviews: true,
+ DismissalRestrictions: DismissalRestrictions{
+ Users: []*User{
+ {Login: String("u"), ID: Int64(1)},
+ },
+ Teams: []*Team{
+ {Slug: String("t"), ID: Int64(2)},
+ },
+ },
+ RequireCodeOwnerReviews: true,
+ RequiredApprovingReviewCount: 1,
+ }
+
+ if !reflect.DeepEqual(enforcement, want) {
+ t.Errorf("Repositories.GetPullRequestReviewEnforcement returned %+v, want %+v", enforcement, want)
+ }
+}
+
+func TestRepositoriesService_UpdatePullRequestReviewEnforcement(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &PullRequestReviewsEnforcementUpdate{
+ DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
+ Users: &[]string{"u"},
+ Teams: &[]string{"t"},
+ },
+ }
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
+ v := new(PullRequestReviewsEnforcementUpdate)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+ // TODO: remove custom Accept header when this API fully launches
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ fmt.Fprintf(w, `{
+ "dismissal_restrictions":{
+ "users":[{"id":1,"login":"u"}],
+ "teams":[{"id":2,"slug":"t"}]
+ },
+ "dismiss_stale_reviews":true,
+ "require_code_owner_reviews":true,
+ "required_approving_review_count":3
+ }`)
+ })
+
+ enforcement, _, err := client.Repositories.UpdatePullRequestReviewEnforcement(context.Background(), "o", "r", "b", input)
+ if err != nil {
+ t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned error: %v", err)
+ }
+
+ want := &PullRequestReviewsEnforcement{
+ DismissStaleReviews: true,
+ DismissalRestrictions: DismissalRestrictions{
+ Users: []*User{
+ {Login: String("u"), ID: Int64(1)},
+ },
+ Teams: []*Team{
+ {Slug: String("t"), ID: Int64(2)},
+ },
+ },
+ RequireCodeOwnerReviews: true,
+ RequiredApprovingReviewCount: 3,
+ }
+ if !reflect.DeepEqual(enforcement, want) {
+ t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned %+v, want %+v", enforcement, want)
+ }
+}
+
+func TestRepositoriesService_DisableDismissalRestrictions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PATCH")
+ // TODO: remove custom Accept header when this API fully launches
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ testBody(t, r, `{"dismissal_restrictions":[]}`+"\n")
+ fmt.Fprintf(w, `{"dismissal_restrictions":{"users":[],"teams":[]},"dismiss_stale_reviews":true,"require_code_owner_reviews":true,"required_approving_review_count":1}`)
+ })
+
+ enforcement, _, err := client.Repositories.DisableDismissalRestrictions(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.DisableDismissalRestrictions returned error: %v", err)
+ }
+
+ want := &PullRequestReviewsEnforcement{
+ DismissStaleReviews: true,
+ DismissalRestrictions: DismissalRestrictions{
+ Users: []*User{},
+ Teams: []*Team{},
+ },
+ RequireCodeOwnerReviews: true,
+ RequiredApprovingReviewCount: 1,
+ }
+ if !reflect.DeepEqual(enforcement, want) {
+ t.Errorf("Repositories.DisableDismissalRestrictions returned %+v, want %+v", enforcement, want)
+ }
+}
+
+func TestRepositoriesService_RemovePullRequestReviewEnforcement(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Repositories.RemovePullRequestReviewEnforcement(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.RemovePullRequestReviewEnforcement returned error: %v", err)
+ }
+}
+
+func TestRepositoriesService_GetAdminEnforcement(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`)
+ })
+
+ enforcement, _, err := client.Repositories.GetAdminEnforcement(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.GetAdminEnforcement returned error: %v", err)
+ }
+
+ want := &AdminEnforcement{
+ URL: String("/repos/o/r/branches/b/protection/enforce_admins"),
+ Enabled: true,
+ }
+
+ if !reflect.DeepEqual(enforcement, want) {
+ t.Errorf("Repositories.GetAdminEnforcement returned %+v, want %+v", enforcement, want)
+ }
+}
+
+func TestRepositoriesService_AddAdminEnforcement(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`)
+ })
+
+ enforcement, _, err := client.Repositories.AddAdminEnforcement(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.AddAdminEnforcement returned error: %v", err)
+ }
+
+ want := &AdminEnforcement{
+ URL: String("/repos/o/r/branches/b/protection/enforce_admins"),
+ Enabled: true,
+ }
+ if !reflect.DeepEqual(enforcement, want) {
+ t.Errorf("Repositories.AddAdminEnforcement returned %+v, want %+v", enforcement, want)
+ }
+}
+
+func TestRepositoriesService_RemoveAdminEnforcement(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Repositories.RemoveAdminEnforcement(context.Background(), "o", "r", "b")
+ if err != nil {
+ t.Errorf("Repositories.RemoveAdminEnforcement returned error: %v", err)
+ }
+}
+
+func TestPullRequestReviewsEnforcementRequest_MarshalJSON_nilDismissalRestirctions(t *testing.T) {
+ req := PullRequestReviewsEnforcementRequest{}
+
+ got, err := json.Marshal(req)
+ if err != nil {
+ t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
+ }
+
+ want := `{"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
+ if want != string(got) {
+ t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
+ }
+
+ req = PullRequestReviewsEnforcementRequest{
+ DismissalRestrictionsRequest: &DismissalRestrictionsRequest{},
+ }
+
+ got, err = json.Marshal(req)
+ if err != nil {
+ t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
+ }
+
+ want = `{"dismissal_restrictions":{},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
+ if want != string(got) {
+ t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
+ }
+
+ req = PullRequestReviewsEnforcementRequest{
+ DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
+ Users: &[]string{},
+ Teams: &[]string{},
+ },
+ }
+
+ got, err = json.Marshal(req)
+ if err != nil {
+ t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
+ }
+
+ want = `{"dismissal_restrictions":{"users":[],"teams":[]},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
+ if want != string(got) {
+ t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
+ }
+}
+
+func TestRepositoriesService_ListAllTopics(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+ fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`)
+ })
+
+ got, _, err := client.Repositories.ListAllTopics(context.Background(), "o", "r")
+ if err != nil {
+ t.Fatalf("Repositories.ListAllTopics returned error: %v", err)
+ }
+
+ want := []string{"go", "go-github", "github"}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want)
+ }
+}
+
+func TestRepositoriesService_ListAllTopics_emptyTopics(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+ fmt.Fprint(w, `{"names":[]}`)
+ })
+
+ got, _, err := client.Repositories.ListAllTopics(context.Background(), "o", "r")
+ if err != nil {
+ t.Fatalf("Repositories.ListAllTopics returned error: %v", err)
+ }
+
+ want := []string{}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want)
+ }
+}
+
+func TestRepositoriesService_ReplaceAllTopics(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+ fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`)
+ })
+
+ got, _, err := client.Repositories.ReplaceAllTopics(context.Background(), "o", "r", []string{"go", "go-github", "github"})
+ if err != nil {
+ t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
+ }
+
+ want := []string{"go", "go-github", "github"}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
+ }
+}
+
+func TestRepositoriesService_ReplaceAllTopics_nilSlice(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+ testBody(t, r, `{"names":[]}`+"\n")
+ fmt.Fprint(w, `{"names":[]}`)
+ })
+
+ got, _, err := client.Repositories.ReplaceAllTopics(context.Background(), "o", "r", nil)
+ if err != nil {
+ t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
+ }
+
+ want := []string{}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
+ }
+}
+
+func TestRepositoriesService_ReplaceAllTopics_emptySlice(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+ testBody(t, r, `{"names":[]}`+"\n")
+ fmt.Fprint(w, `{"names":[]}`)
+ })
+
+ got, _, err := client.Repositories.ReplaceAllTopics(context.Background(), "o", "r", []string{})
+ if err != nil {
+ t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
+ }
+
+ want := []string{}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
+ }
+}
+
+func TestRepositoriesService_Transfer(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := TransferRequest{NewOwner: "a", TeamID: []int64{123}}
+
+ mux.HandleFunc("/repos/o/r/transfer", func(w http.ResponseWriter, r *http.Request) {
+ var v TransferRequest
+ json.NewDecoder(r.Body).Decode(&v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeRepositoryTransferPreview)
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"owner":{"login":"a"}}`)
+ })
+
+ got, _, err := client.Repositories.Transfer(context.Background(), "o", "r", input)
+ if err != nil {
+ t.Errorf("Repositories.Transfer returned error: %v", err)
+ }
+
+ want := &Repository{Owner: &User{Login: String("a")}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Repositories.Transfer returned %+v, want %+v", got, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/repos_traffic.go b/vendor/github.com/google/go-github/github/repos_traffic.go
new file mode 100644
index 0000000..fb1c976
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_traffic.go
@@ -0,0 +1,141 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+)
+
+// TrafficReferrer represent information about traffic from a referrer .
+type TrafficReferrer struct {
+ Referrer *string `json:"referrer,omitempty"`
+ Count *int `json:"count,omitempty"`
+ Uniques *int `json:"uniques,omitempty"`
+}
+
+// TrafficPath represent information about the traffic on a path of the repo.
+type TrafficPath struct {
+ Path *string `json:"path,omitempty"`
+ Title *string `json:"title,omitempty"`
+ Count *int `json:"count,omitempty"`
+ Uniques *int `json:"uniques,omitempty"`
+}
+
+// TrafficData represent information about a specific timestamp in views or clones list.
+type TrafficData struct {
+ Timestamp *Timestamp `json:"timestamp,omitempty"`
+ Count *int `json:"count,omitempty"`
+ Uniques *int `json:"uniques,omitempty"`
+}
+
+// TrafficViews represent information about the number of views in the last 14 days.
+type TrafficViews struct {
+ Views []*TrafficData `json:"views,omitempty"`
+ Count *int `json:"count,omitempty"`
+ Uniques *int `json:"uniques,omitempty"`
+}
+
+// TrafficClones represent information about the number of clones in the last 14 days.
+type TrafficClones struct {
+ Clones []*TrafficData `json:"clones,omitempty"`
+ Count *int `json:"count,omitempty"`
+ Uniques *int `json:"uniques,omitempty"`
+}
+
+// TrafficBreakdownOptions specifies the parameters to methods that support breakdown per day or week.
+// Can be one of: day, week. Default: day.
+type TrafficBreakdownOptions struct {
+ Per string `url:"per,omitempty"`
+}
+
+// ListTrafficReferrers list the top 10 referrers over the last 14 days.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/traffic/#list-referrers
+func (s *RepositoriesService) ListTrafficReferrers(ctx context.Context, owner, repo string) ([]*TrafficReferrer, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/traffic/popular/referrers", owner, repo)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var trafficReferrers []*TrafficReferrer
+ resp, err := s.client.Do(ctx, req, &trafficReferrers)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return trafficReferrers, resp, nil
+}
+
+// ListTrafficPaths list the top 10 popular content over the last 14 days.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/traffic/#list-paths
+func (s *RepositoriesService) ListTrafficPaths(ctx context.Context, owner, repo string) ([]*TrafficPath, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/traffic/popular/paths", owner, repo)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var paths []*TrafficPath
+ resp, err := s.client.Do(ctx, req, &paths)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return paths, resp, nil
+}
+
+// ListTrafficViews get total number of views for the last 14 days and breaks it down either per day or week.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/traffic/#views
+func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo string, opt *TrafficBreakdownOptions) (*TrafficViews, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/traffic/views", owner, repo)
+ 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
+ }
+
+ trafficViews := new(TrafficViews)
+ resp, err := s.client.Do(ctx, req, &trafficViews)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return trafficViews, resp, nil
+}
+
+// ListTrafficClones get total number of clones for the last 14 days and breaks it down either per day or week for the last 14 days.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/traffic/#views
+func (s *RepositoriesService) ListTrafficClones(ctx context.Context, owner, repo string, opt *TrafficBreakdownOptions) (*TrafficClones, *Response, error) {
+ u := fmt.Sprintf("repos/%v/%v/traffic/clones", owner, repo)
+ 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
+ }
+
+ trafficClones := new(TrafficClones)
+ resp, err := s.client.Do(ctx, req, &trafficClones)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return trafficClones, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/repos_traffic_test.go b/vendor/github.com/google/go-github/github/repos_traffic_test.go
new file mode 100644
index 0000000..0a2eb4f
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/repos_traffic_test.go
@@ -0,0 +1,145 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestRepositoriesService_ListTrafficReferrers(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/traffic/popular/referrers", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprintf(w, `[{
+ "referrer": "Google",
+ "count": 4,
+ "uniques": 3
+ }]`)
+ })
+ referrers, _, err := client.Repositories.ListTrafficReferrers(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.ListPaths returned error: %+v", err)
+ }
+
+ want := []*TrafficReferrer{{
+ Referrer: String("Google"),
+ Count: Int(4),
+ Uniques: Int(3),
+ }}
+ if !reflect.DeepEqual(referrers, want) {
+ t.Errorf("Repositories.ListReferrers returned %+v, want %+v", referrers, want)
+ }
+
+}
+
+func TestRepositoriesService_ListTrafficPaths(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/traffic/popular/paths", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprintf(w, `[{
+ "path": "/github/hubot",
+ "title": "github/hubot: A customizable life embetterment robot.",
+ "count": 3542,
+ "uniques": 2225
+ }]`)
+ })
+ paths, _, err := client.Repositories.ListTrafficPaths(context.Background(), "o", "r")
+ if err != nil {
+ t.Errorf("Repositories.ListPaths returned error: %+v", err)
+ }
+
+ want := []*TrafficPath{{
+ Path: String("/github/hubot"),
+ Title: String("github/hubot: A customizable life embetterment robot."),
+ Count: Int(3542),
+ Uniques: Int(2225),
+ }}
+ if !reflect.DeepEqual(paths, want) {
+ t.Errorf("Repositories.ListPaths returned %+v, want %+v", paths, want)
+ }
+
+}
+
+func TestRepositoriesService_ListTrafficViews(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/traffic/views", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprintf(w, `{"count": 7,
+ "uniques": 6,
+ "views": [{
+ "timestamp": "2016-05-31T16:00:00.000Z",
+ "count": 7,
+ "uniques": 6
+ }]}`)
+ })
+
+ views, _, err := client.Repositories.ListTrafficViews(context.Background(), "o", "r", nil)
+ if err != nil {
+ t.Errorf("Repositories.ListPaths returned error: %+v", err)
+ }
+
+ want := &TrafficViews{
+ Views: []*TrafficData{{
+ Timestamp: &Timestamp{time.Date(2016, time.May, 31, 16, 0, 0, 0, time.UTC)},
+ Count: Int(7),
+ Uniques: Int(6),
+ }},
+ Count: Int(7),
+ Uniques: Int(6),
+ }
+
+ if !reflect.DeepEqual(views, want) {
+ t.Errorf("Repositories.ListViews returned %+v, want %+v", views, want)
+ }
+
+}
+
+func TestRepositoriesService_ListTrafficClones(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/repos/o/r/traffic/clones", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprintf(w, `{"count": 7,
+ "uniques": 6,
+ "clones": [{
+ "timestamp": "2016-05-31T16:00:00.00Z",
+ "count": 7,
+ "uniques": 6
+ }]}`)
+ })
+
+ clones, _, err := client.Repositories.ListTrafficClones(context.Background(), "o", "r", nil)
+ if err != nil {
+ t.Errorf("Repositories.ListPaths returned error: %+v", err)
+ }
+
+ want := &TrafficClones{
+ Clones: []*TrafficData{{
+ Timestamp: &Timestamp{time.Date(2016, time.May, 31, 16, 0, 0, 0, time.UTC)},
+ Count: Int(7),
+ Uniques: Int(6),
+ }},
+ Count: Int(7),
+ Uniques: Int(6),
+ }
+
+ if !reflect.DeepEqual(clones, want) {
+ t.Errorf("Repositories.ListViews returned %+v, want %+v", clones, want)
+ }
+
+}
diff --git a/vendor/github.com/google/go-github/github/search.go b/vendor/github.com/google/go-github/github/search.go
new file mode 100644
index 0000000..abaf5e1
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/search.go
@@ -0,0 +1,261 @@
+// 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 (
+ "context"
+ "fmt"
+ "net/url"
+ "strconv"
+ "strings"
+
+ qs "github.com/google/go-querystring/query"
+)
+
+// SearchService provides access to the search related functions
+// in the GitHub API.
+//
+// Each method takes a query string defining the search keywords and any search qualifiers.
+// For example, when searching issues, the query "gopher is:issue language:go" will search
+// for issues containing the word "gopher" in Go repositories. The method call
+// opts := &github.SearchOptions{Sort: "created", Order: "asc"}
+// cl.Search.Issues(ctx, "gopher is:issue language:go", opts)
+// will search for such issues, sorting by creation date in ascending order
+// (i.e., oldest first).
+//
+// GitHub API docs: https://developer.github.com/v3/search/
+type SearchService service
+
+// SearchOptions specifies optional parameters to the SearchService methods.
+type SearchOptions struct {
+ // How to sort the search results. Possible values are:
+ // - for repositories: stars, fork, updated
+ // - for commits: author-date, committer-date
+ // - for code: indexed
+ // - for issues: comments, created, updated
+ // - for users: followers, repositories, joined
+ //
+ // Default is to sort by best match.
+ Sort string `url:"sort,omitempty"`
+
+ // Sort order if sort parameter is provided. Possible values are: asc,
+ // desc. Default is desc.
+ Order string `url:"order,omitempty"`
+
+ // Whether to retrieve text match metadata with a query
+ TextMatch bool `url:"-"`
+
+ ListOptions
+}
+
+// Common search parameters.
+type searchParameters struct {
+ Query string
+ RepositoryID *int64 // Sent if non-nil.
+}
+
+// RepositoriesSearchResult represents the result of a repositories search.
+type RepositoriesSearchResult struct {
+ Total *int `json:"total_count,omitempty"`
+ IncompleteResults *bool `json:"incomplete_results,omitempty"`
+ Repositories []Repository `json:"items,omitempty"`
+}
+
+// Repositories searches repositories via various criteria.
+//
+// GitHub API docs: https://developer.github.com/v3/search/#search-repositories
+func (s *SearchService) Repositories(ctx context.Context, query string, opt *SearchOptions) (*RepositoriesSearchResult, *Response, error) {
+ result := new(RepositoriesSearchResult)
+ resp, err := s.search(ctx, "repositories", &searchParameters{Query: query}, opt, result)
+ return result, resp, err
+}
+
+// CommitsSearchResult represents the result of a commits search.
+type CommitsSearchResult struct {
+ Total *int `json:"total_count,omitempty"`
+ IncompleteResults *bool `json:"incomplete_results,omitempty"`
+ Commits []*CommitResult `json:"items,omitempty"`
+}
+
+// CommitResult represents a commit object as returned in commit search endpoint response.
+type CommitResult struct {
+ SHA *string `json:"sha,omitempty"`
+ Commit *Commit `json:"commit,omitempty"`
+ Author *User `json:"author,omitempty"`
+ Committer *User `json:"committer,omitempty"`
+ Parents []*Commit `json:"parents,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ URL *string `json:"url,omitempty"`
+ CommentsURL *string `json:"comments_url,omitempty"`
+
+ Repository *Repository `json:"repository,omitempty"`
+ Score *float64 `json:"score,omitempty"`
+}
+
+// Commits searches commits via various criteria.
+//
+// GitHub API docs: https://developer.github.com/v3/search/#search-commits
+func (s *SearchService) Commits(ctx context.Context, query string, opt *SearchOptions) (*CommitsSearchResult, *Response, error) {
+ result := new(CommitsSearchResult)
+ resp, err := s.search(ctx, "commits", &searchParameters{Query: query}, opt, result)
+ return result, resp, err
+}
+
+// IssuesSearchResult represents the result of an issues search.
+type IssuesSearchResult struct {
+ Total *int `json:"total_count,omitempty"`
+ IncompleteResults *bool `json:"incomplete_results,omitempty"`
+ Issues []Issue `json:"items,omitempty"`
+}
+
+// Issues searches issues via various criteria.
+//
+// GitHub API docs: https://developer.github.com/v3/search/#search-issues
+func (s *SearchService) Issues(ctx context.Context, query string, opt *SearchOptions) (*IssuesSearchResult, *Response, error) {
+ result := new(IssuesSearchResult)
+ resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opt, result)
+ return result, resp, err
+}
+
+// UsersSearchResult represents the result of a users search.
+type UsersSearchResult struct {
+ Total *int `json:"total_count,omitempty"`
+ IncompleteResults *bool `json:"incomplete_results,omitempty"`
+ Users []User `json:"items,omitempty"`
+}
+
+// Users searches users via various criteria.
+//
+// GitHub API docs: https://developer.github.com/v3/search/#search-users
+func (s *SearchService) Users(ctx context.Context, query string, opt *SearchOptions) (*UsersSearchResult, *Response, error) {
+ result := new(UsersSearchResult)
+ resp, err := s.search(ctx, "users", &searchParameters{Query: query}, opt, result)
+ return result, resp, err
+}
+
+// Match represents a single text match.
+type Match struct {
+ Text *string `json:"text,omitempty"`
+ Indices []int `json:"indices,omitempty"`
+}
+
+// TextMatch represents a text match for a SearchResult
+type TextMatch struct {
+ ObjectURL *string `json:"object_url,omitempty"`
+ ObjectType *string `json:"object_type,omitempty"`
+ Property *string `json:"property,omitempty"`
+ Fragment *string `json:"fragment,omitempty"`
+ Matches []Match `json:"matches,omitempty"`
+}
+
+func (tm TextMatch) String() string {
+ return Stringify(tm)
+}
+
+// CodeSearchResult represents the result of a code search.
+type CodeSearchResult struct {
+ Total *int `json:"total_count,omitempty"`
+ IncompleteResults *bool `json:"incomplete_results,omitempty"`
+ CodeResults []CodeResult `json:"items,omitempty"`
+}
+
+// CodeResult represents a single search result.
+type CodeResult struct {
+ Name *string `json:"name,omitempty"`
+ Path *string `json:"path,omitempty"`
+ SHA *string `json:"sha,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ Repository *Repository `json:"repository,omitempty"`
+ TextMatches []TextMatch `json:"text_matches,omitempty"`
+}
+
+func (c CodeResult) String() string {
+ return Stringify(c)
+}
+
+// Code searches code via various criteria.
+//
+// GitHub API docs: https://developer.github.com/v3/search/#search-code
+func (s *SearchService) Code(ctx context.Context, query string, opt *SearchOptions) (*CodeSearchResult, *Response, error) {
+ result := new(CodeSearchResult)
+ resp, err := s.search(ctx, "code", &searchParameters{Query: query}, opt, result)
+ return result, resp, err
+}
+
+// LabelsSearchResult represents the result of a code search.
+type LabelsSearchResult struct {
+ Total *int `json:"total_count,omitempty"`
+ IncompleteResults *bool `json:"incomplete_results,omitempty"`
+ Labels []*LabelResult `json:"items,omitempty"`
+}
+
+// LabelResult represents a single search result.
+type LabelResult struct {
+ ID *int64 `json:"id,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Color *string `json:"color,omitempty"`
+ Default *bool `json:"default,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Score *float64 `json:"score,omitempty"`
+}
+
+func (l LabelResult) String() string {
+ return Stringify(l)
+}
+
+// Labels searches labels in the repository with ID repoID via various criteria.
+//
+// GitHub API docs: https://developer.github.com/v3/search/#search-labels
+func (s *SearchService) Labels(ctx context.Context, repoID int64, query string, opt *SearchOptions) (*LabelsSearchResult, *Response, error) {
+ result := new(LabelsSearchResult)
+ resp, err := s.search(ctx, "labels", &searchParameters{RepositoryID: &repoID, Query: query}, opt, result)
+ return result, resp, err
+}
+
+// Helper function that executes search queries against different
+// GitHub search types (repositories, commits, code, issues, users, labels)
+func (s *SearchService) search(ctx context.Context, searchType string, parameters *searchParameters, opt *SearchOptions, result interface{}) (*Response, error) {
+ params, err := qs.Values(opt)
+ if err != nil {
+ return nil, err
+ }
+ q := strings.Replace(parameters.Query, " ", "+", -1)
+ if parameters.RepositoryID != nil {
+ params.Set("repository_id", strconv.FormatInt(*parameters.RepositoryID, 10))
+ }
+ query := "q=" + url.PathEscape(q)
+ if v := params.Encode(); v != "" {
+ query = query + "&" + v
+ }
+ u := fmt.Sprintf("search/%s?%s", searchType, query)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ switch {
+ case searchType == "commits":
+ // Accept header for search commits preview endpoint
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeCommitSearchPreview)
+ case searchType == "repositories":
+ // Accept header for search repositories based on topics preview endpoint
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeTopicsPreview)
+ case searchType == "labels":
+ // Accept header for search labels based on label description preview endpoint.
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+ case opt != nil && opt.TextMatch:
+ // Accept header defaults to "application/vnd.github.v3+json"
+ // We change it here to fetch back text-match metadata
+ req.Header.Set("Accept", "application/vnd.github.v3.text-match+json")
+ }
+
+ return s.client.Do(ctx, req, result)
+}
diff --git a/vendor/github.com/google/go-github/github/search_test.go b/vendor/github.com/google/go-github/github/search_test.go
new file mode 100644
index 0000000..f6e40d2
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/search_test.go
@@ -0,0 +1,351 @@
+// 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+
+ "testing"
+)
+
+func TestSearchService_Repositories(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/search/repositories", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "q": "blah",
+ "sort": "forks",
+ "order": "desc",
+ "page": "2",
+ "per_page": "2",
+ })
+
+ fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id":1},{"id":2}]}`)
+ })
+
+ opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}}
+ result, _, err := client.Search.Repositories(context.Background(), "blah", opts)
+ if err != nil {
+ t.Errorf("Search.Repositories returned error: %v", err)
+ }
+
+ want := &RepositoriesSearchResult{
+ Total: Int(4),
+ IncompleteResults: Bool(false),
+ Repositories: []Repository{{ID: Int64(1)}, {ID: Int64(2)}},
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("Search.Repositories returned %+v, want %+v", result, want)
+ }
+}
+
+func TestSearchService_Commits(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/search/commits", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "q": "blah",
+ "sort": "author-date",
+ "order": "desc",
+ })
+
+ fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"sha":"random_hash1"},{"sha":"random_hash2"}]}`)
+ })
+
+ opts := &SearchOptions{Sort: "author-date", Order: "desc"}
+ result, _, err := client.Search.Commits(context.Background(), "blah", opts)
+ if err != nil {
+ t.Errorf("Search.Commits returned error: %v", err)
+ }
+
+ want := &CommitsSearchResult{
+ Total: Int(4),
+ IncompleteResults: Bool(false),
+ Commits: []*CommitResult{{SHA: String("random_hash1")}, {SHA: String("random_hash2")}},
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("Search.Commits returned %+v, want %+v", result, want)
+ }
+}
+
+func TestSearchService_Issues(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "q": "blah",
+ "sort": "forks",
+ "order": "desc",
+ "page": "2",
+ "per_page": "2",
+ })
+
+ fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`)
+ })
+
+ opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}}
+ result, _, err := client.Search.Issues(context.Background(), "blah", opts)
+ if err != nil {
+ t.Errorf("Search.Issues returned error: %v", err)
+ }
+
+ want := &IssuesSearchResult{
+ Total: Int(4),
+ IncompleteResults: Bool(true),
+ Issues: []Issue{{Number: Int(1)}, {Number: Int(2)}},
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("Search.Issues returned %+v, want %+v", result, want)
+ }
+}
+
+func TestSearchService_Issues_withQualifiersNoOpts(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ const q = "gopher is:issue label:bug language:go pushed:>=2018-01-01 stars:>=200"
+
+ var requestURI string
+ mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "q": q,
+ })
+ requestURI = r.RequestURI
+
+ fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`)
+ })
+
+ opts := &SearchOptions{}
+ result, _, err := client.Search.Issues(context.Background(), q, opts)
+ if err != nil {
+ t.Errorf("Search.Issues returned error: %v", err)
+ }
+
+ if want := "/api-v3/search/issues?q=gopher+is:issue+label:bug+language:go+pushed:%3E=2018-01-01+stars:%3E=200"; requestURI != want {
+ t.Fatalf("URI encoding failed: got %v, want %v", requestURI, want)
+ }
+
+ want := &IssuesSearchResult{
+ Total: Int(4),
+ IncompleteResults: Bool(true),
+ Issues: []Issue{{Number: Int(1)}, {Number: Int(2)}},
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("Search.Issues returned %+v, want %+v", result, want)
+ }
+}
+
+func TestSearchService_Issues_withQualifiersAndOpts(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ const q = "gopher is:issue label:bug language:go pushed:>=2018-01-01 stars:>=200"
+
+ var requestURI string
+ mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "q": q,
+ "sort": "forks",
+ })
+ requestURI = r.RequestURI
+
+ fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`)
+ })
+
+ opts := &SearchOptions{Sort: "forks"}
+ result, _, err := client.Search.Issues(context.Background(), q, opts)
+ if err != nil {
+ t.Errorf("Search.Issues returned error: %v", err)
+ }
+
+ if want := "/api-v3/search/issues?q=gopher+is:issue+label:bug+language:go+pushed:%3E=2018-01-01+stars:%3E=200&sort=forks"; requestURI != want {
+ t.Fatalf("URI encoding failed: got %v, want %v", requestURI, want)
+ }
+
+ want := &IssuesSearchResult{
+ Total: Int(4),
+ IncompleteResults: Bool(true),
+ Issues: []Issue{{Number: Int(1)}, {Number: Int(2)}},
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("Search.Issues returned %+v, want %+v", result, want)
+ }
+}
+
+func TestSearchService_Users(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/search/users", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "q": "blah",
+ "sort": "forks",
+ "order": "desc",
+ "page": "2",
+ "per_page": "2",
+ })
+
+ fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id":1},{"id":2}]}`)
+ })
+
+ opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}}
+ result, _, err := client.Search.Users(context.Background(), "blah", opts)
+ if err != nil {
+ t.Errorf("Search.Issues returned error: %v", err)
+ }
+
+ want := &UsersSearchResult{
+ Total: Int(4),
+ IncompleteResults: Bool(false),
+ Users: []User{{ID: Int64(1)}, {ID: Int64(2)}},
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("Search.Users returned %+v, want %+v", result, want)
+ }
+}
+
+func TestSearchService_Code(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/search/code", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "q": "blah",
+ "sort": "forks",
+ "order": "desc",
+ "page": "2",
+ "per_page": "2",
+ })
+
+ fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"name":"1"},{"name":"2"}]}`)
+ })
+
+ opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}}
+ result, _, err := client.Search.Code(context.Background(), "blah", opts)
+ if err != nil {
+ t.Errorf("Search.Code returned error: %v", err)
+ }
+
+ want := &CodeSearchResult{
+ Total: Int(4),
+ IncompleteResults: Bool(false),
+ CodeResults: []CodeResult{{Name: String("1")}, {Name: String("2")}},
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("Search.Code returned %+v, want %+v", result, want)
+ }
+}
+
+func TestSearchService_CodeTextMatch(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/search/code", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+
+ textMatchResponse := `
+ {
+ "total_count": 1,
+ "incomplete_results": false,
+ "items": [
+ {
+ "name":"gopher1",
+ "text_matches": [
+ {
+ "fragment": "I'm afraid my friend what you have found\nIs a gopher who lives to feed",
+ "matches": [
+ {
+ "text": "gopher",
+ "indices": [
+ 14,
+ 21
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ `
+
+ fmt.Fprint(w, textMatchResponse)
+ })
+
+ opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}, TextMatch: true}
+ result, _, err := client.Search.Code(context.Background(), "blah", opts)
+ if err != nil {
+ t.Errorf("Search.Code returned error: %v", err)
+ }
+
+ wantedCodeResult := CodeResult{
+ Name: String("gopher1"),
+ TextMatches: []TextMatch{{
+ Fragment: String("I'm afraid my friend what you have found\nIs a gopher who lives to feed"),
+ Matches: []Match{{Text: String("gopher"), Indices: []int{14, 21}}},
+ },
+ },
+ }
+
+ want := &CodeSearchResult{
+ Total: Int(1),
+ IncompleteResults: Bool(false),
+ CodeResults: []CodeResult{wantedCodeResult},
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("Search.Code returned %+v, want %+v", result, want)
+ }
+}
+
+func TestSearchService_Labels(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/search/labels", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "repository_id": "1234",
+ "q": "blah",
+ "sort": "updated",
+ "order": "desc",
+ "page": "2",
+ "per_page": "2",
+ })
+
+ fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id": 1234, "name":"bug", "description": "some text"},{"id": 4567, "name":"feature"}]}`)
+ })
+
+ opts := &SearchOptions{Sort: "updated", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}}
+ result, _, err := client.Search.Labels(context.Background(), 1234, "blah", opts)
+ if err != nil {
+ t.Errorf("Search.Code returned error: %v", err)
+ }
+
+ want := &LabelsSearchResult{
+ Total: Int(4),
+ IncompleteResults: Bool(false),
+ Labels: []*LabelResult{
+ {ID: Int64(1234), Name: String("bug"), Description: String("some text")},
+ {ID: Int64(4567), Name: String("feature")},
+ },
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("Search.Labels returned %+v, want %+v", result, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/strings.go b/vendor/github.com/google/go-github/github/strings.go
new file mode 100644
index 0000000..431e1cc
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/strings.go
@@ -0,0 +1,93 @@
+// 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 (
+ "bytes"
+ "fmt"
+ "io"
+
+ "reflect"
+)
+
+var timestampType = reflect.TypeOf(Timestamp{})
+
+// Stringify attempts to create a reasonable string representation of types in
+// the GitHub library. It does things like resolve pointers to their values
+// and omits struct fields with nil values.
+func Stringify(message interface{}) string {
+ var buf bytes.Buffer
+ v := reflect.ValueOf(message)
+ stringifyValue(&buf, v)
+ return buf.String()
+}
+
+// stringifyValue was heavily inspired by the goprotobuf library.
+
+func stringifyValue(w io.Writer, val reflect.Value) {
+ if val.Kind() == reflect.Ptr && val.IsNil() {
+ w.Write([]byte(""))
+ return
+ }
+
+ v := reflect.Indirect(val)
+
+ switch v.Kind() {
+ case reflect.String:
+ fmt.Fprintf(w, `"%s"`, v)
+ case reflect.Slice:
+ w.Write([]byte{'['})
+ for i := 0; i < v.Len(); i++ {
+ if i > 0 {
+ w.Write([]byte{' '})
+ }
+
+ stringifyValue(w, v.Index(i))
+ }
+
+ w.Write([]byte{']'})
+ return
+ case reflect.Struct:
+ if v.Type().Name() != "" {
+ w.Write([]byte(v.Type().String()))
+ }
+
+ // special handling of Timestamp values
+ if v.Type() == timestampType {
+ fmt.Fprintf(w, "{%s}", v.Interface())
+ return
+ }
+
+ w.Write([]byte{'{'})
+
+ var sep bool
+ for i := 0; i < v.NumField(); i++ {
+ fv := v.Field(i)
+ if fv.Kind() == reflect.Ptr && fv.IsNil() {
+ continue
+ }
+ if fv.Kind() == reflect.Slice && fv.IsNil() {
+ continue
+ }
+
+ if sep {
+ w.Write([]byte(", "))
+ } else {
+ sep = true
+ }
+
+ w.Write([]byte(v.Type().Field(i).Name))
+ w.Write([]byte{':'})
+ stringifyValue(w, fv)
+ }
+
+ w.Write([]byte{'}'})
+ default:
+ if v.CanInterface() {
+ fmt.Fprint(w, v.Interface())
+ }
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/strings_test.go b/vendor/github.com/google/go-github/github/strings_test.go
new file mode 100644
index 0000000..beef089
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/strings_test.go
@@ -0,0 +1,141 @@
+// 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"
+ "testing"
+ "time"
+)
+
+func TestStringify(t *testing.T) {
+ var nilPointer *string
+
+ var tests = []struct {
+ in interface{}
+ out string
+ }{
+ // basic types
+ {"foo", `"foo"`},
+ {123, `123`},
+ {1.5, `1.5`},
+ {false, `false`},
+ {
+ []string{"a", "b"},
+ `["a" "b"]`,
+ },
+ {
+ struct {
+ A []string
+ }{nil},
+ // nil slice is skipped
+ `{}`,
+ },
+ {
+ struct {
+ A string
+ }{"foo"},
+ // structs not of a named type get no prefix
+ `{A:"foo"}`,
+ },
+
+ // pointers
+ {nilPointer, ``},
+ {String("foo"), `"foo"`},
+ {Int(123), `123`},
+ {Bool(false), `false`},
+ {
+ []*string{String("a"), String("b")},
+ `["a" "b"]`,
+ },
+
+ // actual GitHub structs
+ {
+ Timestamp{time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)},
+ `github.Timestamp{2006-01-02 15:04:05 +0000 UTC}`,
+ },
+ {
+ &Timestamp{time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)},
+ `github.Timestamp{2006-01-02 15:04:05 +0000 UTC}`,
+ },
+ {
+ User{ID: Int64(123), Name: String("n")},
+ `github.User{ID:123, Name:"n"}`,
+ },
+ {
+ Repository{Owner: &User{ID: Int64(123)}},
+ `github.Repository{Owner:github.User{ID:123}}`,
+ },
+ }
+
+ for i, tt := range tests {
+ s := Stringify(tt.in)
+ if s != tt.out {
+ t.Errorf("%d. Stringify(%q) => %q, want %q", i, tt.in, s, tt.out)
+ }
+ }
+}
+
+// Directly test the String() methods on various GitHub types. We don't do an
+// exaustive test of all the various field types, since TestStringify() above
+// takes care of that. Rather, we just make sure that Stringify() is being
+// used to build the strings, which we do by verifying that pointers are
+// stringified as their underlying value.
+func TestString(t *testing.T) {
+ var tests = []struct {
+ in interface{}
+ out string
+ }{
+ {CodeResult{Name: String("n")}, `github.CodeResult{Name:"n"}`},
+ {CommitAuthor{Name: String("n")}, `github.CommitAuthor{Name:"n"}`},
+ {CommitFile{SHA: String("s")}, `github.CommitFile{SHA:"s"}`},
+ {CommitStats{Total: Int(1)}, `github.CommitStats{Total:1}`},
+ {CommitsComparison{TotalCommits: Int(1)}, `github.CommitsComparison{TotalCommits:1}`},
+ {Commit{SHA: String("s")}, `github.Commit{SHA:"s"}`},
+ {Event{ID: String("1")}, `github.Event{ID:"1"}`},
+ {GistComment{ID: Int64(1)}, `github.GistComment{ID:1}`},
+ {GistFile{Size: Int(1)}, `github.GistFile{Size:1}`},
+ {Gist{ID: String("1")}, `github.Gist{ID:"1", Files:map[]}`},
+ {GitObject{SHA: String("s")}, `github.GitObject{SHA:"s"}`},
+ {Gitignore{Name: String("n")}, `github.Gitignore{Name:"n"}`},
+ {Hook{ID: Int64(1)}, `github.Hook{Config:map[], ID:1}`},
+ {IssueComment{ID: Int64(1)}, `github.IssueComment{ID:1}`},
+ {Issue{Number: Int(1)}, `github.Issue{Number:1}`},
+ {Key{ID: Int64(1)}, `github.Key{ID:1}`},
+ {Label{ID: Int64(1), Name: String("l")}, `github.Label{ID:1, Name:"l"}`},
+ {Organization{ID: Int64(1)}, `github.Organization{ID:1}`},
+ {PullRequestComment{ID: Int64(1)}, `github.PullRequestComment{ID:1}`},
+ {PullRequest{Number: Int(1)}, `github.PullRequest{Number:1}`},
+ {PullRequestReview{ID: Int64(1)}, `github.PullRequestReview{ID:1}`},
+ {DraftReviewComment{Position: Int(1)}, `github.DraftReviewComment{Position:1}`},
+ {PullRequestReviewRequest{Body: String("r")}, `github.PullRequestReviewRequest{Body:"r"}`},
+ {PullRequestReviewDismissalRequest{Message: String("r")}, `github.PullRequestReviewDismissalRequest{Message:"r"}`},
+ {PushEventCommit{SHA: String("s")}, `github.PushEventCommit{SHA:"s"}`},
+ {PushEvent{PushID: Int64(1)}, `github.PushEvent{PushID:1}`},
+ {Reference{Ref: String("r")}, `github.Reference{Ref:"r"}`},
+ {ReleaseAsset{ID: Int64(1)}, `github.ReleaseAsset{ID:1}`},
+ {RepoStatus{ID: Int64(1)}, `github.RepoStatus{ID:1}`},
+ {RepositoryComment{ID: Int64(1)}, `github.RepositoryComment{ID:1}`},
+ {RepositoryCommit{SHA: String("s")}, `github.RepositoryCommit{SHA:"s"}`},
+ {RepositoryContent{Name: String("n")}, `github.RepositoryContent{Name:"n"}`},
+ {RepositoryRelease{ID: Int64(1)}, `github.RepositoryRelease{ID:1}`},
+ {Repository{ID: Int64(1)}, `github.Repository{ID:1}`},
+ {Team{ID: Int64(1)}, `github.Team{ID:1}`},
+ {TreeEntry{SHA: String("s")}, `github.TreeEntry{SHA:"s"}`},
+ {Tree{SHA: String("s")}, `github.Tree{SHA:"s"}`},
+ {User{ID: Int64(1)}, `github.User{ID:1}`},
+ {WebHookAuthor{Name: String("n")}, `github.WebHookAuthor{Name:"n"}`},
+ {WebHookCommit{ID: String("1")}, `github.WebHookCommit{ID:"1"}`},
+ {WebHookPayload{Ref: String("r")}, `github.WebHookPayload{Ref:"r"}`},
+ }
+
+ for i, tt := range tests {
+ s := tt.in.(fmt.Stringer).String()
+ if s != tt.out {
+ t.Errorf("%d. String() => %q, want %q", i, tt.in, tt.out)
+ }
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/teams.go b/vendor/github.com/google/go-github/github/teams.go
new file mode 100644
index 0000000..c3773e0
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/teams.go
@@ -0,0 +1,357 @@
+// Copyright 2018 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 (
+ "context"
+ "fmt"
+ "strings"
+ "time"
+)
+
+// TeamsService provides access to the team-related functions
+// in the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/
+type TeamsService service
+
+// Team represents a team within a GitHub organization. Teams are used to
+// manage access to an organization's repositories.
+type Team struct {
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Description *string `json:"description,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Slug *string `json:"slug,omitempty"`
+
+ // Permission specifies the default permission for repositories owned by the team.
+ 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"`
+ MembersURL *string `json:"members_url,omitempty"`
+ RepositoriesURL *string `json:"repositories_url,omitempty"`
+ Parent *Team `json:"parent,omitempty"`
+
+ // LDAPDN is only available in GitHub Enterprise and when the team
+ // membership is synchronized with LDAP.
+ LDAPDN *string `json:"ldap_dn,omitempty"`
+}
+
+func (t Team) String() string {
+ return Stringify(t)
+}
+
+// Invitation represents a team member's invitation status.
+type Invitation struct {
+ ID *int64 `json:"id,omitempty"`
+ Login *string `json:"login,omitempty"`
+ Email *string `json:"email,omitempty"`
+ // Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'.
+ Role *string `json:"role,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ Inviter *User `json:"inviter,omitempty"`
+ TeamCount *int `json:"team_count,omitempty"`
+ InvitationTeamURL *string `json:"invitation_team_url,omitempty"`
+}
+
+func (i Invitation) String() string {
+ return Stringify(i)
+}
+
+// ListTeams lists all of the teams for an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/#list-teams
+func (s *TeamsService) ListTeams(ctx context.Context, org string, opt *ListOptions) ([]*Team, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/teams", 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
+
+ var teams []*Team
+ resp, err := s.client.Do(ctx, req, &teams)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return teams, resp, nil
+}
+
+// GetTeam fetches a team by ID.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/#get-team
+func (s *TeamsService) GetTeam(ctx context.Context, team int64) (*Team, *Response, error) {
+ u := fmt.Sprintf("teams/%v", team)
+ 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", mediaTypeNestedTeamsPreview)
+
+ t := new(Team)
+ resp, err := s.client.Do(ctx, req, t)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return t, resp, nil
+}
+
+// NewTeam represents a team to be created or modified.
+type NewTeam struct {
+ Name string `json:"name"` // Name of the team. (Required.)
+ Description *string `json:"description,omitempty"`
+ Maintainers []string `json:"maintainers,omitempty"`
+ RepoNames []string `json:"repo_names,omitempty"`
+ ParentTeamID *int64 `json:"parent_team_id,omitempty"`
+
+ // Deprecated: 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"`
+
+ // LDAPDN may be used in GitHub Enterprise when the team membership
+ // is synchronized with LDAP.
+ LDAPDN *string `json:"ldap_dn,omitempty"`
+}
+
+func (s NewTeam) String() string {
+ return Stringify(s)
+}
+
+// CreateTeam creates a new team within an organization.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/#create-team
+func (s *TeamsService) CreateTeam(ctx context.Context, org string, team NewTeam) (*Team, *Response, error) {
+ u := fmt.Sprintf("orgs/%v/teams", org)
+ req, err := s.client.NewRequest("POST", u, team)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
+
+ t := new(Team)
+ resp, err := s.client.Do(ctx, req, t)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return t, resp, nil
+}
+
+// EditTeam edits a team.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/#edit-team
+func (s *TeamsService) EditTeam(ctx context.Context, id int64, team NewTeam) (*Team, *Response, error) {
+ u := fmt.Sprintf("teams/%v", id)
+ req, err := s.client.NewRequest("PATCH", u, team)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
+
+ t := new(Team)
+ resp, err := s.client.Do(ctx, req, t)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return t, resp, nil
+}
+
+// DeleteTeam deletes a team.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/#delete-team
+func (s *TeamsService) DeleteTeam(ctx context.Context, team int64) (*Response, error) {
+ u := fmt.Sprintf("teams/%v", team)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ListChildTeams lists child teams for a team.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/#list-child-teams
+func (s *TeamsService) ListChildTeams(ctx context.Context, teamID int64, opt *ListOptions) ([]*Team, *Response, error) {
+ u := fmt.Sprintf("teams/%v/teams", teamID)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
+
+ var teams []*Team
+ resp, err := s.client.Do(ctx, req, &teams)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return teams, resp, nil
+}
+
+// ListTeamRepos lists the repositories that the specified team has access to.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/#list-team-repos
+func (s *TeamsService) ListTeamRepos(ctx context.Context, team int64, opt *ListOptions) ([]*Repository, *Response, error) {
+ u := fmt.Sprintf("teams/%v/repos", team)
+ 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
+ }
+
+ // TODO: remove custom Accept header when topics API fully launches.
+ headers := []string{mediaTypeTopicsPreview, mediaTypeNestedTeamsPreview}
+ req.Header.Set("Accept", strings.Join(headers, ", "))
+
+ var repos []*Repository
+ resp, err := s.client.Do(ctx, req, &repos)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return repos, resp, nil
+}
+
+// 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: https://developer.github.com/v3/teams/#check-if-a-team-manages-a-repository
+func (s *TeamsService) IsTeamRepo(ctx context.Context, team int64, 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 nil, nil, err
+ }
+
+ headers := []string{mediaTypeOrgPermissionRepo, mediaTypeNestedTeamsPreview}
+ req.Header.Set("Accept", strings.Join(headers, ", "))
+
+ repository := new(Repository)
+ resp, err := s.client.Do(ctx, req, repository)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return repository, resp, nil
+}
+
+// TeamAddTeamRepoOptions specifies the optional parameters to the
+// TeamsService.AddTeamRepo method.
+type TeamAddTeamRepoOptions 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
+// specified repository must be owned by the organization to which the team
+// belongs, or a direct fork of a repository owned by the organization.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/#add-team-repo
+func (s *TeamsService) AddTeamRepo(ctx context.Context, team int64, owner string, repo string, opt *TeamAddTeamRepoOptions) (*Response, error) {
+ u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo)
+ req, err := s.client.NewRequest("PUT", u, opt)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// RemoveTeamRepo removes a repository from being managed by the specified
+// team. Note that this does not delete the repository, it just removes it
+// from the team.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/#remove-team-repo
+func (s *TeamsService) RemoveTeamRepo(ctx context.Context, team int64, owner string, repo string) (*Response, error) {
+ u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ListUserTeams lists a user's teams
+// GitHub API docs: https://developer.github.com/v3/teams/#list-user-teams
+func (s *TeamsService) ListUserTeams(ctx context.Context, opt *ListOptions) ([]*Team, *Response, error) {
+ u := "user/teams"
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
+
+ var teams []*Team
+ resp, err := s.client.Do(ctx, req, &teams)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return teams, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/teams_discussion_comments.go b/vendor/github.com/google/go-github/github/teams_discussion_comments.go
new file mode 100644
index 0000000..a0206b9
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/teams_discussion_comments.go
@@ -0,0 +1,155 @@
+// Copyright 2018 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 (
+ "context"
+ "fmt"
+)
+
+// DiscussionComment represents a GitHub dicussion in a team.
+type DiscussionComment struct {
+ Author *User `json:"author,omitempty"`
+ Body *string `json:"body,omitempty"`
+ BodyHTML *string `json:"body_html,omitempty"`
+ BodyVersion *string `json:"body_version,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ LastEditedAt *Timestamp `json:"last_edited_at,omitempty"`
+ DiscussionURL *string `json:"discussion_url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ Number *int `json:"number,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Reactions *Reactions `json:"reactions,omitempty"`
+}
+
+func (c DiscussionComment) String() string {
+ return Stringify(c)
+}
+
+// DiscussionCommentListOptions specifies optional parameters to the
+// TeamServices.ListComments method.
+type DiscussionCommentListOptions struct {
+ // Sorts the discussion comments by the date they were created.
+ // Accepted values are asc and desc. Default is desc.
+ Direction string `url:"direction,omitempty"`
+}
+
+// ListComments lists all comments on a team discussion.
+// Authenticated user must grant read:discussion scope.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#list-comments
+func (s *TeamsService) ListComments(ctx context.Context, teamID int64, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v/comments", teamID, discussionNumber)
+ u, err := addOptions(u, options)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ 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", mediaTypeTeamDiscussionsPreview)
+
+ var comments []*DiscussionComment
+ resp, err := s.client.Do(ctx, req, &comments)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return comments, resp, nil
+}
+
+// GetComment gets a specific comment on a team discussion.
+// Authenticated user must grant read:discussion scope.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#get-a-single-comment
+func (s *TeamsService) GetComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber)
+ 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", mediaTypeTeamDiscussionsPreview)
+
+ discussionComment := &DiscussionComment{}
+ resp, err := s.client.Do(ctx, req, discussionComment)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return discussionComment, resp, nil
+}
+
+// CreateComment creates a new discussion post on a team discussion.
+// Authenticated user must grant write:discussion scope.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#create-a-comment
+func (s *TeamsService) CreateComment(ctx context.Context, teamID int64, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v/comments", teamID, discsusionNumber)
+ req, err := s.client.NewRequest("POST", u, comment)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
+
+ discussionComment := &DiscussionComment{}
+ resp, err := s.client.Do(ctx, req, discussionComment)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return discussionComment, resp, nil
+}
+
+// EditComment edits the body text of a discussion comment.
+// Authenticated user must grant write:discussion scope.
+// User is allowed to edit body of a comment only.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#edit-a-comment
+func (s *TeamsService) EditComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber)
+ req, err := s.client.NewRequest("PATCH", u, comment)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
+
+ discussionComment := &DiscussionComment{}
+ resp, err := s.client.Do(ctx, req, discussionComment)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return discussionComment, resp, nil
+}
+
+// DeleteComment deletes a comment on a team discussion.
+// Authenticated user must grant write:discussion scope.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#delete-a-comment
+func (s *TeamsService) DeleteComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int) (*Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/teams_discussion_comments_test.go b/vendor/github.com/google/go-github/github/teams_discussion_comments_test.go
new file mode 100644
index 0000000..f4c9f96
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/teams_discussion_comments_test.go
@@ -0,0 +1,203 @@
+// Copyright 2018 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestTeamsService_ListComments(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/2/discussions/3/comments", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview)
+ testFormValues(t, r, values{
+ "direction": "desc",
+ })
+ fmt.Fprintf(w,
+ `[
+ {
+ "author": {
+ "login": "author",
+ "id": 0,
+ "avatar_url": "https://avatars1.githubusercontent.com/u/0?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/author",
+ "html_url": "https://github.com/author",
+ "followers_url": "https://api.github.com/users/author/followers",
+ "following_url": "https://api.github.com/users/author/following{/other_user}",
+ "gists_url": "https://api.github.com/users/author/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/author/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/author/subscriptions",
+ "organizations_url": "https://api.github.com/users/author/orgs",
+ "repos_url": "https://api.github.com/users/author/repos",
+ "events_url": "https://api.github.com/users/author/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/author/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "body": "comment",
+ "body_html": "comment
",
+ "body_version": "version",
+ "created_at": "2018-01-01T00:00:00Z",
+ "last_edited_at": null,
+ "discussion_url": "https://api.github.com/teams/2/discussions/3",
+ "html_url": "https://github.com/orgs/1/teams/2/discussions/3/comments/4",
+ "node_id": "node",
+ "number": 4,
+ "updated_at": "2018-01-01T00:00:00Z",
+ "url": "https://api.github.com/teams/2/discussions/3/comments/4"
+ }
+ ]`)
+ })
+
+ comments, _, err := client.Teams.ListComments(context.Background(), 2, 3, &DiscussionCommentListOptions{"desc"})
+ if err != nil {
+ t.Errorf("Teams.ListComments returned error: %v", err)
+ }
+
+ want := []*DiscussionComment{
+ {
+ Author: &User{
+ Login: String("author"),
+ ID: Int64(0),
+ AvatarURL: String("https://avatars1.githubusercontent.com/u/0?v=4"),
+ GravatarID: String(""),
+ URL: String("https://api.github.com/users/author"),
+ HTMLURL: String("https://github.com/author"),
+ FollowersURL: String("https://api.github.com/users/author/followers"),
+ FollowingURL: String("https://api.github.com/users/author/following{/other_user}"),
+ GistsURL: String("https://api.github.com/users/author/gists{/gist_id}"),
+ StarredURL: String("https://api.github.com/users/author/starred{/owner}{/repo}"),
+ SubscriptionsURL: String("https://api.github.com/users/author/subscriptions"),
+ OrganizationsURL: String("https://api.github.com/users/author/orgs"),
+ ReposURL: String("https://api.github.com/users/author/repos"),
+ EventsURL: String("https://api.github.com/users/author/events{/privacy}"),
+ ReceivedEventsURL: String("https://api.github.com/users/author/received_events"),
+ Type: String("User"),
+ SiteAdmin: Bool(false),
+ },
+ Body: String("comment"),
+ BodyHTML: String("comment
"),
+ BodyVersion: String("version"),
+ CreatedAt: &Timestamp{time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)},
+ LastEditedAt: nil,
+ DiscussionURL: String("https://api.github.com/teams/2/discussions/3"),
+ HTMLURL: String("https://github.com/orgs/1/teams/2/discussions/3/comments/4"),
+ NodeID: String("node"),
+ Number: Int(4),
+ UpdatedAt: &Timestamp{time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)},
+ URL: String("https://api.github.com/teams/2/discussions/3/comments/4"),
+ },
+ }
+ if !reflect.DeepEqual(comments, want) {
+ t.Errorf("Teams.ListComments returned %+v, want %+v", comments, want)
+ }
+}
+
+func TestTeamsService_GetComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/2/discussions/3/comments/4", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview)
+ fmt.Fprint(w, `{"number":4}`)
+ })
+
+ comment, _, err := client.Teams.GetComment(context.Background(), 2, 3, 4)
+ if err != nil {
+ t.Errorf("Teams.GetComment returned error: %v", err)
+ }
+
+ want := &DiscussionComment{Number: Int(4)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Teams.GetComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestTeamsService_CreateComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := DiscussionComment{Body: String("c")}
+
+ mux.HandleFunc("/teams/2/discussions/3/comments", func(w http.ResponseWriter, r *http.Request) {
+ v := new(DiscussionComment)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview)
+ if !reflect.DeepEqual(v, &input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"number":4}`)
+ })
+
+ comment, _, err := client.Teams.CreateComment(context.Background(), 2, 3, input)
+ if err != nil {
+ t.Errorf("Teams.CreateComment returned error: %v", err)
+ }
+
+ want := &DiscussionComment{Number: Int(4)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Teams.CreateComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestTeamsService_EditComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := DiscussionComment{Body: String("e")}
+
+ mux.HandleFunc("/teams/2/discussions/3/comments/4", func(w http.ResponseWriter, r *http.Request) {
+ v := new(DiscussionComment)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview)
+ if !reflect.DeepEqual(v, &input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"number":4}`)
+ })
+
+ comment, _, err := client.Teams.EditComment(context.Background(), 2, 3, 4, input)
+ if err != nil {
+ t.Errorf("Teams.EditComment returned error: %v", err)
+ }
+
+ want := &DiscussionComment{Number: Int(4)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Teams.EditComment returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestTeamsService_DeleteComment(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/2/discussions/3/comments/4", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview)
+ })
+
+ _, err := client.Teams.DeleteComment(context.Background(), 2, 3, 4)
+ if err != nil {
+ t.Errorf("Teams.DeleteComment returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/teams_discussions.go b/vendor/github.com/google/go-github/github/teams_discussions.go
new file mode 100644
index 0000000..f491c9d
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/teams_discussions.go
@@ -0,0 +1,160 @@
+// Copyright 2018 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 (
+ "context"
+ "fmt"
+)
+
+// TeamDiscussion represents a GitHub dicussion in a team.
+type TeamDiscussion struct {
+ Author *User `json:"author,omitempty"`
+ Body *string `json:"body,omitempty"`
+ BodyHTML *string `json:"body_html,omitempty"`
+ BodyVersion *string `json:"body_version,omitempty"`
+ CommentsCount *int `json:"comments_count,omitempty"`
+ CommentsURL *string `json:"comments_url,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ LastEditedAt *Timestamp `json:"last_edited_at,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ Number *int `json:"number,omitempty"`
+ Pinned *bool `json:"pinned,omitempty"`
+ Private *bool `json:"private,omitempty"`
+ TeamURL *string `json:"team_url,omitempty"`
+ Title *string `json:"title,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Reactions *Reactions `json:"reactions,omitempty"`
+}
+
+func (d TeamDiscussion) String() string {
+ return Stringify(d)
+}
+
+// DiscussionListOptions specifies optional parameters to the
+// TeamServices.ListDiscussions method.
+type DiscussionListOptions struct {
+ // Sorts the discussion by the date they were created.
+ // Accepted values are asc and desc. Default is desc.
+ Direction string `url:"direction,omitempty"`
+}
+
+// ListDiscussions lists all discussions on team's page.
+// Authenticated user must grant read:discussion scope.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/discussions/#list-discussions
+func (s *TeamsService) ListDiscussions(ctx context.Context, teamID int64, options *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions", teamID)
+ u, err := addOptions(u, options)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ 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", mediaTypeTeamDiscussionsPreview)
+
+ var teamDiscussions []*TeamDiscussion
+ resp, err := s.client.Do(ctx, req, &teamDiscussions)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return teamDiscussions, resp, nil
+}
+
+// GetDiscussion gets a specific discussion on a team's page.
+// Authenticated user must grant read:discussion scope.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/discussions/#get-a-single-discussion
+func (s *TeamsService) GetDiscussion(ctx context.Context, teamID int64, discussionNumber int) (*TeamDiscussion, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber)
+ 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", mediaTypeTeamDiscussionsPreview)
+
+ teamDiscussion := &TeamDiscussion{}
+ resp, err := s.client.Do(ctx, req, teamDiscussion)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return teamDiscussion, resp, nil
+}
+
+// CreateDiscussion creates a new discussion post on a team's page.
+// Authenticated user must grant write:discussion scope.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/discussions/#create-a-discussion
+func (s *TeamsService) CreateDiscussion(ctx context.Context, teamID int64, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions", teamID)
+ req, err := s.client.NewRequest("POST", u, discussion)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
+
+ teamDiscussion := &TeamDiscussion{}
+ resp, err := s.client.Do(ctx, req, teamDiscussion)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return teamDiscussion, resp, nil
+}
+
+// EditDiscussion edits the title and body text of a discussion post.
+// Authenticated user must grant write:discussion scope.
+// User is allowed to change Title and Body of a discussion only.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/discussions/#edit-a-discussion
+func (s *TeamsService) EditDiscussion(ctx context.Context, teamID int64, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber)
+ req, err := s.client.NewRequest("PATCH", u, discussion)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
+
+ teamDiscussion := &TeamDiscussion{}
+ resp, err := s.client.Do(ctx, req, teamDiscussion)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return teamDiscussion, resp, nil
+}
+
+// DeleteDiscussion deletes a discussion from team's page.
+// Authenticated user must grant write:discussion scope.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/discussions/#delete-a-discussion
+func (s *TeamsService) DeleteDiscussion(ctx context.Context, teamID int64, discussionNumber int) (*Response, error) {
+ u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/teams_discussions_test.go b/vendor/github.com/google/go-github/github/teams_discussions_test.go
new file mode 100644
index 0000000..c588c22
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/teams_discussions_test.go
@@ -0,0 +1,212 @@
+// Copyright 2018 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestTeamsService_ListDiscussions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/2/discussions", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview)
+ testFormValues(t, r, values{
+ "direction": "desc",
+ })
+ fmt.Fprintf(w,
+ `[
+ {
+ "author": {
+ "login": "author",
+ "id": 0,
+ "avatar_url": "https://avatars1.githubusercontent.com/u/0?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/author",
+ "html_url": "https://github.com/author",
+ "followers_url": "https://api.github.com/users/author/followers",
+ "following_url": "https://api.github.com/users/author/following{/other_user}",
+ "gists_url": "https://api.github.com/users/author/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/author/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/author/subscriptions",
+ "organizations_url": "https://api.github.com/users/author/orgs",
+ "repos_url": "https://api.github.com/users/author/repos",
+ "events_url": "https://api.github.com/users/author/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/author/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "body": "test",
+ "body_html": "test
",
+ "body_version": "version",
+ "comments_count": 1,
+ "comments_url": "https://api.github.com/teams/2/discussions/3/comments",
+ "created_at": "2018-01-01T00:00:00Z",
+ "last_edited_at": null,
+ "html_url": "https://github.com/orgs/1/teams/2/discussions/3",
+ "node_id": "node",
+ "number": 3,
+ "pinned": false,
+ "private": false,
+ "team_url": "https://api.github.com/teams/2",
+ "title": "test",
+ "updated_at": "2018-01-01T00:00:00Z",
+ "url": "https://api.github.com/teams/2/discussions/3"
+ }
+ ]`)
+ })
+ discussions, _, err := client.Teams.ListDiscussions(context.Background(), 2, &DiscussionListOptions{"desc"})
+ if err != nil {
+ t.Errorf("Teams.ListDiscussions returned error: %v", err)
+ }
+
+ want := []*TeamDiscussion{
+ {
+ Author: &User{
+ Login: String("author"),
+ ID: Int64(0),
+ AvatarURL: String("https://avatars1.githubusercontent.com/u/0?v=4"),
+ GravatarID: String(""),
+ URL: String("https://api.github.com/users/author"),
+ HTMLURL: String("https://github.com/author"),
+ FollowersURL: String("https://api.github.com/users/author/followers"),
+ FollowingURL: String("https://api.github.com/users/author/following{/other_user}"),
+ GistsURL: String("https://api.github.com/users/author/gists{/gist_id}"),
+ StarredURL: String("https://api.github.com/users/author/starred{/owner}{/repo}"),
+ SubscriptionsURL: String("https://api.github.com/users/author/subscriptions"),
+ OrganizationsURL: String("https://api.github.com/users/author/orgs"),
+ ReposURL: String("https://api.github.com/users/author/repos"),
+ EventsURL: String("https://api.github.com/users/author/events{/privacy}"),
+ ReceivedEventsURL: String("https://api.github.com/users/author/received_events"),
+ Type: String("User"),
+ SiteAdmin: Bool(false),
+ },
+ Body: String("test"),
+ BodyHTML: String("test
"),
+ BodyVersion: String("version"),
+ CommentsCount: Int(1),
+ CommentsURL: String("https://api.github.com/teams/2/discussions/3/comments"),
+ CreatedAt: &Timestamp{time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)},
+ LastEditedAt: nil,
+ HTMLURL: String("https://github.com/orgs/1/teams/2/discussions/3"),
+ NodeID: String("node"),
+ Number: Int(3),
+ Pinned: Bool(false),
+ Private: Bool(false),
+ TeamURL: String("https://api.github.com/teams/2"),
+ Title: String("test"),
+ UpdatedAt: &Timestamp{time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)},
+ URL: String("https://api.github.com/teams/2/discussions/3"),
+ },
+ }
+ if !reflect.DeepEqual(discussions, want) {
+ t.Errorf("Teams.ListDiscussions returned %+v, want %+v", discussions, want)
+ }
+}
+
+func TestTeamsService_GetDiscussion(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/2/discussions/3", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview)
+ fmt.Fprint(w, `{"number":3}`)
+ })
+
+ discussion, _, err := client.Teams.GetDiscussion(context.Background(), 2, 3)
+ if err != nil {
+ t.Errorf("Teams.GetDiscussion returned error: %v", err)
+ }
+
+ want := &TeamDiscussion{Number: Int(3)}
+ if !reflect.DeepEqual(discussion, want) {
+ t.Errorf("Teams.GetDiscussion returned %+v, want %+v", discussion, want)
+ }
+}
+
+func TestTeamsService_CreateDiscussion(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := TeamDiscussion{Title: String("c_t"), Body: String("c_b")}
+
+ mux.HandleFunc("/teams/2/discussions", func(w http.ResponseWriter, r *http.Request) {
+ v := new(TeamDiscussion)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview)
+ if !reflect.DeepEqual(v, &input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"number":3}`)
+ })
+
+ comment, _, err := client.Teams.CreateDiscussion(context.Background(), 2, input)
+ if err != nil {
+ t.Errorf("Teams.CreateDiscussion returned error: %v", err)
+ }
+
+ want := &TeamDiscussion{Number: Int(3)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Teams.CreateDiscussion returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestTeamsService_EditDiscussion(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := TeamDiscussion{Title: String("e_t"), Body: String("e_b")}
+
+ mux.HandleFunc("/teams/2/discussions/3", func(w http.ResponseWriter, r *http.Request) {
+ v := new(TeamDiscussion)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview)
+ if !reflect.DeepEqual(v, &input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"number":3}`)
+ })
+
+ comment, _, err := client.Teams.EditDiscussion(context.Background(), 2, 3, input)
+ if err != nil {
+ t.Errorf("Teams.EditDiscussion returned error: %v", err)
+ }
+
+ want := &TeamDiscussion{Number: Int(3)}
+ if !reflect.DeepEqual(comment, want) {
+ t.Errorf("Teams.EditDiscussion returned %+v, want %+v", comment, want)
+ }
+}
+
+func TestTeamsService_DeleteDiscussion(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/2/discussions/3", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview)
+ })
+
+ _, err := client.Teams.DeleteDiscussion(context.Background(), 2, 3)
+ if err != nil {
+ t.Errorf("Teams.DeleteDiscussion returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/teams_members.go b/vendor/github.com/google/go-github/github/teams_members.go
new file mode 100644
index 0000000..d5cfa0d
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/teams_members.go
@@ -0,0 +1,174 @@
+// Copyright 2018 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 (
+ "context"
+ "fmt"
+)
+
+// TeamListTeamMembersOptions specifies the optional parameters to the
+// TeamsService.ListTeamMembers method.
+type TeamListTeamMembersOptions 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: https://developer.github.com/v3/teams/members/#list-team-members
+func (s *TeamsService) ListTeamMembers(ctx context.Context, team int64, opt *TeamListTeamMembersOptions) ([]*User, *Response, error) {
+ u := fmt.Sprintf("teams/%v/members", team)
+ 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
+ }
+
+ req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
+
+ var members []*User
+ resp, err := s.client.Do(ctx, req, &members)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return members, resp, nil
+}
+
+// IsTeamMember checks if a user is a member of the specified team.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/members/#get-team-member
+//
+// Deprecated: This API has been marked as deprecated in the Github API docs,
+// TeamsService.GetTeamMembership method should be used instead.
+func (s *TeamsService) IsTeamMember(ctx context.Context, team int64, user string) (bool, *Response, error) {
+ u := fmt.Sprintf("teams/%v/members/%v", team, user)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+
+ resp, err := s.client.Do(ctx, req, nil)
+ member, err := parseBoolResponse(err)
+ return member, resp, err
+}
+
+// GetTeamMembership returns the membership status for a user in a team.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/members/#get-team-membership
+func (s *TeamsService) GetTeamMembership(ctx context.Context, team int64, user string) (*Membership, *Response, error) {
+ u := fmt.Sprintf("teams/%v/memberships/%v", team, user)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
+
+ t := new(Membership)
+ resp, err := s.client.Do(ctx, req, t)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return t, resp, nil
+}
+
+// TeamAddTeamMembershipOptions specifies the optional
+// parameters to the TeamsService.AddTeamMembership method.
+type TeamAddTeamMembershipOptions 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
+// user must have 'admin' permissions to the team or be an owner of the
+// organization that the team is associated with.
+//
+// If the user is already a part of the team's organization (meaning they're on
+// at least one other team in the organization), this endpoint will add the
+// user to the team.
+//
+// If the user is completely unaffiliated with the team's organization (meaning
+// they're on none of the organization's teams), this endpoint will send an
+// invitation to the user via email. This newly-created membership will be in
+// the "pending" state until the user accepts the invitation, at which point
+// the membership will transition to the "active" state and the user will be
+// added as a member of the team.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/members/#add-or-update-team-membership
+func (s *TeamsService) AddTeamMembership(ctx context.Context, team int64, user string, opt *TeamAddTeamMembershipOptions) (*Membership, *Response, error) {
+ u := fmt.Sprintf("teams/%v/memberships/%v", team, user)
+ req, err := s.client.NewRequest("PUT", u, opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ t := new(Membership)
+ resp, err := s.client.Do(ctx, req, t)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return t, resp, nil
+}
+
+// RemoveTeamMembership removes a user from a team.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/members/#remove-team-membership
+func (s *TeamsService) RemoveTeamMembership(ctx context.Context, team int64, user string) (*Response, error) {
+ u := fmt.Sprintf("teams/%v/memberships/%v", team, user)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// ListPendingTeamInvitations get pending invitaion list in team.
+// Warning: The API may change without advance notice during the preview period.
+// Preview features are not supported for production use.
+//
+// GitHub API docs: https://developer.github.com/v3/teams/members/#list-pending-team-invitations
+func (s *TeamsService) ListPendingTeamInvitations(ctx context.Context, team int64, opt *ListOptions) ([]*Invitation, *Response, error) {
+ u := fmt.Sprintf("teams/%v/invitations", team)
+ 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
+ }
+
+ var pendingInvitations []*Invitation
+ resp, err := s.client.Do(ctx, req, &pendingInvitations)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return pendingInvitations, resp, nil
+}
diff --git a/vendor/github.com/google/go-github/github/teams_members_test.go b/vendor/github.com/google/go-github/github/teams_members_test.go
new file mode 100644
index 0000000..2489da0
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/teams_members_test.go
@@ -0,0 +1,167 @@
+// Copyright 2018 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestTeamsService__ListTeamMembers(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/members", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ testFormValues(t, r, values{"role": "member", "page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &TeamListTeamMembersOptions{Role: "member", ListOptions: ListOptions{Page: 2}}
+ members, _, err := client.Teams.ListTeamMembers(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Teams.ListTeamMembers returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}}
+ if !reflect.DeepEqual(members, want) {
+ t.Errorf("Teams.ListTeamMembers returned %+v, want %+v", members, want)
+ }
+}
+
+func TestTeamsService__IsTeamMember_true(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/members/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ })
+
+ member, _, err := client.Teams.IsTeamMember(context.Background(), 1, "u")
+ if err != nil {
+ t.Errorf("Teams.IsTeamMember returned error: %v", err)
+ }
+ if want := true; member != want {
+ t.Errorf("Teams.IsTeamMember returned %+v, want %+v", member, want)
+ }
+}
+
+// ensure that a 404 response is interpreted as "false" and not an error
+func TestTeamsService__IsTeamMember_false(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/members/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNotFound)
+ })
+
+ member, _, err := client.Teams.IsTeamMember(context.Background(), 1, "u")
+ if err != nil {
+ t.Errorf("Teams.IsTeamMember returned error: %+v", err)
+ }
+ if want := false; member != want {
+ t.Errorf("Teams.IsTeamMember returned %+v, want %+v", member, want)
+ }
+}
+
+// ensure that a 400 response is interpreted as an actual error, and not simply
+// as "false" like the above case of a 404
+func TestTeamsService__IsTeamMember_error(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/members/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ http.Error(w, "BadRequest", http.StatusBadRequest)
+ })
+
+ member, _, err := client.Teams.IsTeamMember(context.Background(), 1, "u")
+ if err == nil {
+ t.Errorf("Expected HTTP 400 response")
+ }
+ if want := false; member != want {
+ t.Errorf("Teams.IsTeamMember returned %+v, want %+v", member, want)
+ }
+}
+
+func TestTeamsService__IsTeamMember_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Teams.IsTeamMember(context.Background(), 1, "%")
+ testURLParseError(t, err)
+}
+
+func TestTeamsService__GetTeamMembership(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ fmt.Fprint(w, `{"url":"u", "state":"active"}`)
+ })
+
+ membership, _, err := client.Teams.GetTeamMembership(context.Background(), 1, "u")
+ if err != nil {
+ t.Errorf("Teams.GetTeamMembership returned error: %v", err)
+ }
+
+ want := &Membership{URL: String("u"), State: String("active")}
+ if !reflect.DeepEqual(membership, want) {
+ t.Errorf("Teams.GetTeamMembership returned %+v, want %+v", membership, want)
+ }
+}
+
+func TestTeamsService__AddTeamMembership(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ opt := &TeamAddTeamMembershipOptions{Role: "maintainer"}
+
+ mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) {
+ v := new(TeamAddTeamMembershipOptions)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PUT")
+ if !reflect.DeepEqual(v, opt) {
+ t.Errorf("Request body = %+v, want %+v", v, opt)
+ }
+
+ fmt.Fprint(w, `{"url":"u", "state":"pending"}`)
+ })
+
+ membership, _, err := client.Teams.AddTeamMembership(context.Background(), 1, "u", opt)
+ if err != nil {
+ t.Errorf("Teams.AddTeamMembership returned error: %v", err)
+ }
+
+ want := &Membership{URL: String("u"), State: String("pending")}
+ if !reflect.DeepEqual(membership, want) {
+ t.Errorf("Teams.AddTeamMembership returned %+v, want %+v", membership, want)
+ }
+}
+
+func TestTeamsService__RemoveTeamMembership(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Teams.RemoveTeamMembership(context.Background(), 1, "u")
+ if err != nil {
+ t.Errorf("Teams.RemoveTeamMembership returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/teams_test.go b/vendor/github.com/google/go-github/github/teams_test.go
new file mode 100644
index 0000000..89708b4
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/teams_test.go
@@ -0,0 +1,465 @@
+// Copyright 2018 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+)
+
+func TestTeamsService_ListTeams(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/orgs/o/teams", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ teams, _, err := client.Teams.ListTeams(context.Background(), "o", opt)
+ if err != nil {
+ t.Errorf("Teams.ListTeams returned error: %v", err)
+ }
+
+ want := []*Team{{ID: Int64(1)}}
+ if !reflect.DeepEqual(teams, want) {
+ t.Errorf("Teams.ListTeams returned %+v, want %+v", teams, want)
+ }
+}
+
+func TestTeamsService_ListTeams_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Teams.ListTeams(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestTeamsService_GetTeam(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ fmt.Fprint(w, `{"id":1, "name":"n", "description": "d", "url":"u", "slug": "s", "permission":"p", "ldap_dn":"cn=n,ou=groups,dc=example,dc=com", "parent":null}`)
+ })
+
+ team, _, err := client.Teams.GetTeam(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Teams.GetTeam returned error: %v", err)
+ }
+
+ want := &Team{ID: Int64(1), Name: String("n"), Description: String("d"), URL: String("u"), Slug: String("s"), Permission: String("p"), LDAPDN: String("cn=n,ou=groups,dc=example,dc=com")}
+ if !reflect.DeepEqual(team, want) {
+ t.Errorf("Teams.GetTeam returned %+v, want %+v", team, want)
+ }
+}
+
+func TestTeamsService_GetTeam_nestedTeams(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ fmt.Fprint(w, `{"id":1, "name":"n", "description": "d", "url":"u", "slug": "s", "permission":"p",
+ "parent": {"id":2, "name":"n", "description": "d", "parent": null}}`)
+ })
+
+ team, _, err := client.Teams.GetTeam(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Teams.GetTeam returned error: %v", err)
+ }
+
+ want := &Team{ID: Int64(1), Name: String("n"), Description: String("d"), URL: String("u"), Slug: String("s"), Permission: String("p"),
+ Parent: &Team{ID: Int64(2), Name: String("n"), Description: String("d")},
+ }
+ if !reflect.DeepEqual(team, want) {
+ t.Errorf("Teams.GetTeam returned %+v, want %+v", team, want)
+ }
+}
+
+func TestTeamsService_CreateTeam(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := NewTeam{Name: "n", Privacy: String("closed"), RepoNames: []string{"r"}}
+
+ mux.HandleFunc("/orgs/o/teams", func(w http.ResponseWriter, r *http.Request) {
+ v := new(NewTeam)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ if !reflect.DeepEqual(v, &input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ team, _, err := client.Teams.CreateTeam(context.Background(), "o", input)
+ if err != nil {
+ t.Errorf("Teams.CreateTeam returned error: %v", err)
+ }
+
+ want := &Team{ID: Int64(1)}
+ if !reflect.DeepEqual(team, want) {
+ t.Errorf("Teams.CreateTeam returned %+v, want %+v", team, want)
+ }
+}
+
+func TestTeamsService_CreateTeam_invalidOrg(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Teams.CreateTeam(context.Background(), "%", NewTeam{})
+ testURLParseError(t, err)
+}
+
+func TestTeamsService_EditTeam(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := NewTeam{Name: "n", Privacy: String("closed")}
+
+ mux.HandleFunc("/teams/1", func(w http.ResponseWriter, r *http.Request) {
+ v := new(NewTeam)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ testMethod(t, r, "PATCH")
+ if !reflect.DeepEqual(v, &input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ team, _, err := client.Teams.EditTeam(context.Background(), 1, input)
+ if err != nil {
+ t.Errorf("Teams.EditTeam returned error: %v", err)
+ }
+
+ want := &Team{ID: Int64(1)}
+ if !reflect.DeepEqual(team, want) {
+ t.Errorf("Teams.EditTeam returned %+v, want %+v", team, want)
+ }
+}
+
+func TestTeamsService_DeleteTeam(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ })
+
+ _, err := client.Teams.DeleteTeam(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Teams.DeleteTeam returned error: %v", err)
+ }
+}
+
+func TestTeamsService_ListChildTeams(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/teams", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":2}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ teams, _, err := client.Teams.ListChildTeams(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Teams.ListTeams returned error: %v", err)
+ }
+
+ want := []*Team{{ID: Int64(2)}}
+ if !reflect.DeepEqual(teams, want) {
+ t.Errorf("Teams.ListTeams returned %+v, want %+v", teams, want)
+ }
+}
+
+func TestTeamsService_ListTeamRepos(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/repos", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ acceptHeaders := []string{mediaTypeTopicsPreview, mediaTypeNestedTeamsPreview}
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ members, _, err := client.Teams.ListTeamRepos(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Teams.ListTeamRepos returned error: %v", err)
+ }
+
+ want := []*Repository{{ID: Int64(1)}}
+ if !reflect.DeepEqual(members, want) {
+ t.Errorf("Teams.ListTeamRepos returned %+v, want %+v", members, want)
+ }
+}
+
+func TestTeamsService_IsTeamRepo_true(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ acceptHeaders := []string{mediaTypeOrgPermissionRepo, mediaTypeNestedTeamsPreview}
+ testHeader(t, r, "Accept", strings.Join(acceptHeaders, ", "))
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ repo, _, err := client.Teams.IsTeamRepo(context.Background(), 1, "o", "r")
+ if err != nil {
+ t.Errorf("Teams.IsTeamRepo returned error: %v", err)
+ }
+
+ want := &Repository{ID: Int64(1)}
+ if !reflect.DeepEqual(repo, want) {
+ t.Errorf("Teams.IsTeamRepo returned %+v, want %+v", repo, want)
+ }
+}
+
+func TestTeamsService_IsTeamRepo_false(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNotFound)
+ })
+
+ repo, resp, err := client.Teams.IsTeamRepo(context.Background(), 1, "o", "r")
+ if err == nil {
+ t.Errorf("Expected HTTP 404 response")
+ }
+ if got, want := resp.Response.StatusCode, http.StatusNotFound; got != want {
+ t.Errorf("Teams.IsTeamRepo returned status %d, want %d", got, want)
+ }
+ if repo != nil {
+ t.Errorf("Teams.IsTeamRepo returned %+v, want nil", repo)
+ }
+}
+
+func TestTeamsService_IsTeamRepo_error(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ http.Error(w, "BadRequest", http.StatusBadRequest)
+ })
+
+ repo, resp, err := client.Teams.IsTeamRepo(context.Background(), 1, "o", "r")
+ if err == nil {
+ t.Errorf("Expected HTTP 400 response")
+ }
+ if got, want := resp.Response.StatusCode, http.StatusBadRequest; got != want {
+ t.Errorf("Teams.IsTeamRepo returned status %d, want %d", got, want)
+ }
+ if repo != nil {
+ t.Errorf("Teams.IsTeamRepo returned %+v, want nil", repo)
+ }
+}
+
+func TestTeamsService_IsTeamRepo_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Teams.IsTeamRepo(context.Background(), 1, "%", "r")
+ testURLParseError(t, err)
+}
+
+func TestTeamsService_AddTeamRepo(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ opt := &TeamAddTeamRepoOptions{Permission: "admin"}
+
+ mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
+ v := new(TeamAddTeamRepoOptions)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "PUT")
+ if !reflect.DeepEqual(v, opt) {
+ t.Errorf("Request body = %+v, want %+v", v, opt)
+ }
+
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Teams.AddTeamRepo(context.Background(), 1, "o", "r", opt)
+ if err != nil {
+ t.Errorf("Teams.AddTeamRepo returned error: %v", err)
+ }
+}
+
+func TestTeamsService_AddTeamRepo_noAccess(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ w.WriteHeader(http.StatusUnprocessableEntity)
+ })
+
+ _, err := client.Teams.AddTeamRepo(context.Background(), 1, "o", "r", nil)
+ if err == nil {
+ t.Errorf("Expcted error to be returned")
+ }
+}
+
+func TestTeamsService_AddTeamRepo_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Teams.AddTeamRepo(context.Background(), 1, "%", "r", nil)
+ testURLParseError(t, err)
+}
+
+func TestTeamsService_RemoveTeamRepo(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Teams.RemoveTeamRepo(context.Background(), 1, "o", "r")
+ if err != nil {
+ t.Errorf("Teams.RemoveTeamRepo returned error: %v", err)
+ }
+}
+
+func TestTeamsService_RemoveTeamRepo_invalidOwner(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Teams.RemoveTeamRepo(context.Background(), 1, "%", "r")
+ testURLParseError(t, err)
+}
+
+func TestTeamsService_ListUserTeams(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/teams", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview)
+ testFormValues(t, r, values{"page": "1"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 1}
+ teams, _, err := client.Teams.ListUserTeams(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Teams.ListUserTeams returned error: %v", err)
+ }
+
+ want := []*Team{{ID: Int64(1)}}
+ if !reflect.DeepEqual(teams, want) {
+ t.Errorf("Teams.ListUserTeams returned %+v, want %+v", teams, want)
+ }
+}
+
+func TestTeamsService_ListPendingTeamInvitations(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/teams/1/invitations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "1"})
+ fmt.Fprint(w, `[
+ {
+ "id": 1,
+ "login": "monalisa",
+ "email": "octocat@github.com",
+ "role": "direct_member",
+ "created_at": "2017-01-21T00:00:00Z",
+ "inviter": {
+ "login": "other_user",
+ "id": 1,
+ "avatar_url": "https://github.com/images/error/other_user_happy.gif",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/other_user",
+ "html_url": "https://github.com/other_user",
+ "followers_url": "https://api.github.com/users/other_user/followers",
+ "following_url": "https://api.github.com/users/other_user/following/other_user",
+ "gists_url": "https://api.github.com/users/other_user/gists/gist_id",
+ "starred_url": "https://api.github.com/users/other_user/starred/owner/repo",
+ "subscriptions_url": "https://api.github.com/users/other_user/subscriptions",
+ "organizations_url": "https://api.github.com/users/other_user/orgs",
+ "repos_url": "https://api.github.com/users/other_user/repos",
+ "events_url": "https://api.github.com/users/other_user/events/privacy",
+ "received_events_url": "https://api.github.com/users/other_user/received_events/privacy",
+ "type": "User",
+ "site_admin": false
+ }
+ }
+ ]`)
+ })
+
+ opt := &ListOptions{Page: 1}
+ invitations, _, err := client.Teams.ListPendingTeamInvitations(context.Background(), 1, opt)
+ if err != nil {
+ t.Errorf("Teams.ListPendingTeamInvitations returned error: %v", err)
+ }
+
+ createdAt := time.Date(2017, time.January, 21, 0, 0, 0, 0, time.UTC)
+ want := []*Invitation{
+ {
+ ID: Int64(1),
+ Login: String("monalisa"),
+ Email: String("octocat@github.com"),
+ Role: String("direct_member"),
+ CreatedAt: &createdAt,
+ Inviter: &User{
+ Login: String("other_user"),
+ ID: Int64(1),
+ AvatarURL: String("https://github.com/images/error/other_user_happy.gif"),
+ GravatarID: String(""),
+ URL: String("https://api.github.com/users/other_user"),
+ HTMLURL: String("https://github.com/other_user"),
+ FollowersURL: String("https://api.github.com/users/other_user/followers"),
+ FollowingURL: String("https://api.github.com/users/other_user/following/other_user"),
+ GistsURL: String("https://api.github.com/users/other_user/gists/gist_id"),
+ StarredURL: String("https://api.github.com/users/other_user/starred/owner/repo"),
+ SubscriptionsURL: String("https://api.github.com/users/other_user/subscriptions"),
+ OrganizationsURL: String("https://api.github.com/users/other_user/orgs"),
+ ReposURL: String("https://api.github.com/users/other_user/repos"),
+ EventsURL: String("https://api.github.com/users/other_user/events/privacy"),
+ ReceivedEventsURL: String("https://api.github.com/users/other_user/received_events/privacy"),
+ Type: String("User"),
+ SiteAdmin: Bool(false),
+ },
+ }}
+
+ if !reflect.DeepEqual(invitations, want) {
+ t.Errorf("Teams.ListPendingTeamInvitations returned %+v, want %+v", invitations, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/timestamp.go b/vendor/github.com/google/go-github/github/timestamp.go
new file mode 100644
index 0000000..90929d5
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/timestamp.go
@@ -0,0 +1,41 @@
+// 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 (
+ "strconv"
+ "time"
+)
+
+// Timestamp represents a time that can be unmarshalled from a JSON string
+// formatted as either an RFC3339 or Unix timestamp. This is necessary for some
+// fields since the GitHub API is inconsistent in how it represents times. All
+// exported methods of time.Time can be called on Timestamp.
+type Timestamp struct {
+ time.Time
+}
+
+func (t Timestamp) String() string {
+ return t.Time.String()
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+// Time is expected in RFC3339 or Unix format.
+func (t *Timestamp) UnmarshalJSON(data []byte) (err error) {
+ str := string(data)
+ i, err := strconv.ParseInt(str, 10, 64)
+ if err == nil {
+ t.Time = time.Unix(i, 0)
+ } else {
+ t.Time, err = time.Parse(`"`+time.RFC3339+`"`, str)
+ }
+ return
+}
+
+// Equal reports whether t and u are equal based on time.Equal
+func (t Timestamp) Equal(u Timestamp) bool {
+ return t.Time.Equal(u.Time)
+}
diff --git a/vendor/github.com/google/go-github/github/timestamp_test.go b/vendor/github.com/google/go-github/github/timestamp_test.go
new file mode 100644
index 0000000..dc09eaf
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/timestamp_test.go
@@ -0,0 +1,189 @@
+// 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 (
+ "encoding/json"
+ "fmt"
+ "testing"
+ "time"
+)
+
+const (
+ emptyTimeStr = `"0001-01-01T00:00:00Z"`
+ referenceTimeStr = `"2006-01-02T15:04:05Z"`
+ referenceTimeStrFractional = `"2006-01-02T15:04:05.000Z"` // This format was returned by the Projects API before October 1, 2017.
+ referenceUnixTimeStr = `1136214245`
+)
+
+var (
+ referenceTime = time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)
+ unixOrigin = time.Unix(0, 0).In(time.UTC)
+)
+
+func TestTimestamp_Marshal(t *testing.T) {
+ testCases := []struct {
+ desc string
+ data Timestamp
+ want string
+ wantErr bool
+ equal bool
+ }{
+ {"Reference", Timestamp{referenceTime}, referenceTimeStr, false, true},
+ {"Empty", Timestamp{}, emptyTimeStr, false, true},
+ {"Mismatch", Timestamp{}, referenceTimeStr, false, false},
+ }
+ for _, tc := range testCases {
+ out, err := json.Marshal(tc.data)
+ if gotErr := err != nil; gotErr != tc.wantErr {
+ t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err)
+ }
+ got := string(out)
+ equal := got == tc.want
+ if (got == tc.want) != tc.equal {
+ t.Errorf("%s: got=%s, want=%s, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal)
+ }
+ }
+}
+
+func TestTimestamp_Unmarshal(t *testing.T) {
+ testCases := []struct {
+ desc string
+ data string
+ want Timestamp
+ wantErr bool
+ equal bool
+ }{
+ {"Reference", referenceTimeStr, Timestamp{referenceTime}, false, true},
+ {"ReferenceUnix", referenceUnixTimeStr, Timestamp{referenceTime}, false, true},
+ {"ReferenceFractional", referenceTimeStrFractional, Timestamp{referenceTime}, false, true},
+ {"Empty", emptyTimeStr, Timestamp{}, false, true},
+ {"UnixStart", `0`, Timestamp{unixOrigin}, false, true},
+ {"Mismatch", referenceTimeStr, Timestamp{}, false, false},
+ {"MismatchUnix", `0`, Timestamp{}, false, false},
+ {"Invalid", `"asdf"`, Timestamp{referenceTime}, true, false},
+ }
+ for _, tc := range testCases {
+ var got Timestamp
+ err := json.Unmarshal([]byte(tc.data), &got)
+ if gotErr := err != nil; gotErr != tc.wantErr {
+ t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err)
+ continue
+ }
+ equal := got.Equal(tc.want)
+ if equal != tc.equal {
+ t.Errorf("%s: got=%#v, want=%#v, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal)
+ }
+ }
+}
+
+func TestTimstamp_MarshalReflexivity(t *testing.T) {
+ testCases := []struct {
+ desc string
+ data Timestamp
+ }{
+ {"Reference", Timestamp{referenceTime}},
+ {"Empty", Timestamp{}},
+ }
+ for _, tc := range testCases {
+ data, err := json.Marshal(tc.data)
+ if err != nil {
+ t.Errorf("%s: Marshal err=%v", tc.desc, err)
+ }
+ var got Timestamp
+ err = json.Unmarshal(data, &got)
+ if err != nil {
+ t.Errorf("%s: Unmarshal err=%v", tc.desc, err)
+ }
+ if !got.Equal(tc.data) {
+ t.Errorf("%s: %+v != %+v", tc.desc, got, data)
+ }
+ }
+}
+
+type WrappedTimestamp struct {
+ A int
+ Time Timestamp
+}
+
+func TestWrappedTimstamp_Marshal(t *testing.T) {
+ testCases := []struct {
+ desc string
+ data WrappedTimestamp
+ want string
+ wantErr bool
+ equal bool
+ }{
+ {"Reference", WrappedTimestamp{0, Timestamp{referenceTime}}, fmt.Sprintf(`{"A":0,"Time":%s}`, referenceTimeStr), false, true},
+ {"Empty", WrappedTimestamp{}, fmt.Sprintf(`{"A":0,"Time":%s}`, emptyTimeStr), false, true},
+ {"Mismatch", WrappedTimestamp{}, fmt.Sprintf(`{"A":0,"Time":%s}`, referenceTimeStr), false, false},
+ }
+ for _, tc := range testCases {
+ out, err := json.Marshal(tc.data)
+ if gotErr := err != nil; gotErr != tc.wantErr {
+ t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err)
+ }
+ got := string(out)
+ equal := got == tc.want
+ if equal != tc.equal {
+ t.Errorf("%s: got=%s, want=%s, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal)
+ }
+ }
+}
+
+func TestWrappedTimstamp_Unmarshal(t *testing.T) {
+ testCases := []struct {
+ desc string
+ data string
+ want WrappedTimestamp
+ wantErr bool
+ equal bool
+ }{
+ {"Reference", referenceTimeStr, WrappedTimestamp{0, Timestamp{referenceTime}}, false, true},
+ {"ReferenceUnix", referenceUnixTimeStr, WrappedTimestamp{0, Timestamp{referenceTime}}, false, true},
+ {"Empty", emptyTimeStr, WrappedTimestamp{0, Timestamp{}}, false, true},
+ {"UnixStart", `0`, WrappedTimestamp{0, Timestamp{unixOrigin}}, false, true},
+ {"Mismatch", referenceTimeStr, WrappedTimestamp{0, Timestamp{}}, false, false},
+ {"MismatchUnix", `0`, WrappedTimestamp{0, Timestamp{}}, false, false},
+ {"Invalid", `"asdf"`, WrappedTimestamp{0, Timestamp{referenceTime}}, true, false},
+ }
+ for _, tc := range testCases {
+ var got Timestamp
+ err := json.Unmarshal([]byte(tc.data), &got)
+ if gotErr := err != nil; gotErr != tc.wantErr {
+ t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err)
+ continue
+ }
+ equal := got.Time.Equal(tc.want.Time.Time)
+ if equal != tc.equal {
+ t.Errorf("%s: got=%#v, want=%#v, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal)
+ }
+ }
+}
+
+func TestWrappedTimstamp_MarshalReflexivity(t *testing.T) {
+ testCases := []struct {
+ desc string
+ data WrappedTimestamp
+ }{
+ {"Reference", WrappedTimestamp{0, Timestamp{referenceTime}}},
+ {"Empty", WrappedTimestamp{0, Timestamp{}}},
+ }
+ for _, tc := range testCases {
+ bytes, err := json.Marshal(tc.data)
+ if err != nil {
+ t.Errorf("%s: Marshal err=%v", tc.desc, err)
+ }
+ var got WrappedTimestamp
+ err = json.Unmarshal(bytes, &got)
+ if err != nil {
+ t.Errorf("%s: Unmarshal err=%v", tc.desc, err)
+ }
+ if !got.Time.Equal(tc.data.Time) {
+ t.Errorf("%s: %+v != %+v", tc.desc, got, tc.data)
+ }
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/users.go b/vendor/github.com/google/go-github/github/users.go
new file mode 100644
index 0000000..f164d55
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users.go
@@ -0,0 +1,284 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// UsersService handles communication with the user related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://developer.github.com/v3/users/
+type UsersService service
+
+// User represents a GitHub user.
+type User struct {
+ Login *string `json:"login,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+ NodeID *string `json:"node_id,omitempty"`
+ AvatarURL *string `json:"avatar_url,omitempty"`
+ HTMLURL *string `json:"html_url,omitempty"`
+ GravatarID *string `json:"gravatar_id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Company *string `json:"company,omitempty"`
+ Blog *string `json:"blog,omitempty"`
+ Location *string `json:"location,omitempty"`
+ Email *string `json:"email,omitempty"`
+ Hireable *bool `json:"hireable,omitempty"`
+ Bio *string `json:"bio,omitempty"`
+ PublicRepos *int `json:"public_repos,omitempty"`
+ PublicGists *int `json:"public_gists,omitempty"`
+ Followers *int `json:"followers,omitempty"`
+ Following *int `json:"following,omitempty"`
+ CreatedAt *Timestamp `json:"created_at,omitempty"`
+ UpdatedAt *Timestamp `json:"updated_at,omitempty"`
+ SuspendedAt *Timestamp `json:"suspended_at,omitempty"`
+ Type *string `json:"type,omitempty"`
+ SiteAdmin *bool `json:"site_admin,omitempty"`
+ TotalPrivateRepos *int `json:"total_private_repos,omitempty"`
+ OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"`
+ PrivateGists *int `json:"private_gists,omitempty"`
+ DiskUsage *int `json:"disk_usage,omitempty"`
+ Collaborators *int `json:"collaborators,omitempty"`
+ Plan *Plan `json:"plan,omitempty"`
+
+ // API URLs
+ URL *string `json:"url,omitempty"`
+ EventsURL *string `json:"events_url,omitempty"`
+ FollowingURL *string `json:"following_url,omitempty"`
+ FollowersURL *string `json:"followers_url,omitempty"`
+ GistsURL *string `json:"gists_url,omitempty"`
+ OrganizationsURL *string `json:"organizations_url,omitempty"`
+ ReceivedEventsURL *string `json:"received_events_url,omitempty"`
+ ReposURL *string `json:"repos_url,omitempty"`
+ StarredURL *string `json:"starred_url,omitempty"`
+ SubscriptionsURL *string `json:"subscriptions_url,omitempty"`
+
+ // TextMatches is only populated from search results that request text matches
+ // See: search.go and https://developer.github.com/v3/search/#text-match-metadata
+ TextMatches []TextMatch `json:"text_matches,omitempty"`
+
+ // 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 {
+ return Stringify(u)
+}
+
+// Get fetches a user. Passing the empty string will fetch the authenticated
+// user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/#get-a-single-user
+func (s *UsersService) Get(ctx context.Context, user string) (*User, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v", user)
+ } else {
+ u = "user"
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ uResp := new(User)
+ resp, err := s.client.Do(ctx, req, uResp)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return uResp, resp, nil
+}
+
+// GetByID fetches a user.
+//
+// Note: GetByID uses the undocumented GitHub API endpoint /user/:id.
+func (s *UsersService) GetByID(ctx context.Context, id int64) (*User, *Response, error) {
+ u := fmt.Sprintf("user/%d", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ user := new(User)
+ resp, err := s.client.Do(ctx, req, user)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return user, resp, nil
+}
+
+// Edit the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/#update-the-authenticated-user
+func (s *UsersService) Edit(ctx context.Context, user *User) (*User, *Response, error) {
+ u := "user"
+ req, err := s.client.NewRequest("PATCH", u, user)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ uResp := new(User)
+ resp, err := s.client.Do(ctx, req, uResp)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return uResp, resp, nil
+}
+
+// HovercardOptions specifies optional parameters to the UsersService.GetHovercard
+// method.
+type HovercardOptions struct {
+ // SubjectType specifies the additional information to be received about the hovercard.
+ // Possible values are: organization, repository, issue, pull_request. (Required when using subject_id.)
+ SubjectType string `url:"subject_type"`
+
+ // SubjectID specifies the ID for the SubjectType. (Required when using subject_type.)
+ SubjectID string `url:"subject_id"`
+}
+
+// Hovercard represents hovercard information about a user.
+type Hovercard struct {
+ Contexts []*UserContext `json:"contexts,omitempty"`
+}
+
+// UserContext represents the contextual information about user.
+type UserContext struct {
+ Message *string `json:"message,omitempty"`
+ Octicon *string `json:"octicon,omitempty"`
+}
+
+// GetHovercard fetches contextual information about user. It requires authentication
+// via Basic Auth or via OAuth with the repo scope.
+//
+// GitHub API docs: https://developer.github.com/v3/users/#get-contextual-information-about-a-user
+func (s *UsersService) GetHovercard(ctx context.Context, user string, opt *HovercardOptions) (*Hovercard, *Response, error) {
+ u := fmt.Sprintf("users/%v/hovercard", user)
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeHovercardPreview)
+
+ hc := new(Hovercard)
+ resp, err := s.client.Do(ctx, req, hc)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return hc, resp, nil
+}
+
+// UserListOptions specifies optional parameters to the UsersService.ListAll
+// method.
+type UserListOptions struct {
+ // ID of the last user seen
+ Since int64 `url:"since,omitempty"`
+
+ // Note: Pagination is powered exclusively by the Since parameter,
+ // ListOptions.Page has no effect.
+ // ListOptions.PerPage controls an undocumented GitHub API parameter.
+ ListOptions
+}
+
+// ListAll lists all GitHub users.
+//
+// To paginate through all users, populate 'Since' with the ID of the last user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/#get-all-users
+func (s *UsersService) ListAll(ctx context.Context, opt *UserListOptions) ([]*User, *Response, error) {
+ u, err := addOptions("users", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var users []*User
+ resp, err := s.client.Do(ctx, req, &users)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return users, resp, nil
+}
+
+// ListInvitations lists all currently-open repository invitations for the
+// authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-a-users-repository-invitations
+func (s *UsersService) ListInvitations(ctx context.Context, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) {
+ u, err := addOptions("user/repository_invitations", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ 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", mediaTypeRepositoryInvitationsPreview)
+
+ invites := []*RepositoryInvitation{}
+ resp, err := s.client.Do(ctx, req, &invites)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return invites, resp, nil
+}
+
+// AcceptInvitation accepts the currently-open repository invitation for the
+// authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/invitations/#accept-a-repository-invitation
+func (s *UsersService) AcceptInvitation(ctx context.Context, invitationID int64) (*Response, error) {
+ u := fmt.Sprintf("user/repository_invitations/%v", invitationID)
+ req, err := s.client.NewRequest("PATCH", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// DeclineInvitation declines the currently-open repository invitation for the
+// authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/invitations/#decline-a-repository-invitation
+func (s *UsersService) DeclineInvitation(ctx context.Context, invitationID int64) (*Response, error) {
+ u := fmt.Sprintf("user/repository_invitations/%v", invitationID)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/users_administration.go b/vendor/github.com/google/go-github/github/users_administration.go
new file mode 100644
index 0000000..e042398
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_administration.go
@@ -0,0 +1,67 @@
+// Copyright 2014 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 (
+ "context"
+ "fmt"
+)
+
+// PromoteSiteAdmin promotes a user to a site administrator of a GitHub Enterprise instance.
+//
+// GitHub API docs: https://developer.github.com/v3/users/administration/#promote-an-ordinary-user-to-a-site-administrator
+func (s *UsersService) PromoteSiteAdmin(ctx context.Context, user string) (*Response, error) {
+ u := fmt.Sprintf("users/%v/site_admin", user)
+
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// DemoteSiteAdmin demotes a user from site administrator of a GitHub Enterprise instance.
+//
+// GitHub API docs: https://developer.github.com/v3/users/administration/#demote-a-site-administrator-to-an-ordinary-user
+func (s *UsersService) DemoteSiteAdmin(ctx context.Context, user string) (*Response, error) {
+ u := fmt.Sprintf("users/%v/site_admin", user)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// Suspend a user on a GitHub Enterprise instance.
+//
+// GitHub API docs: https://developer.github.com/v3/users/administration/#suspend-a-user
+func (s *UsersService) Suspend(ctx context.Context, user string) (*Response, error) {
+ u := fmt.Sprintf("users/%v/suspended", user)
+
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// Unsuspend a user on a GitHub Enterprise instance.
+//
+// GitHub API docs: https://developer.github.com/v3/users/administration/#unsuspend-a-user
+func (s *UsersService) Unsuspend(ctx context.Context, user string) (*Response, error) {
+ u := fmt.Sprintf("users/%v/suspended", user)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/users_administration_test.go b/vendor/github.com/google/go-github/github/users_administration_test.go
new file mode 100644
index 0000000..4b0955e
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_administration_test.go
@@ -0,0 +1,72 @@
+// Copyright 2014 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 (
+ "context"
+ "net/http"
+ "testing"
+)
+
+func TestUsersService_PromoteSiteAdmin(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/site_admin", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Users.PromoteSiteAdmin(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Users.PromoteSiteAdmin returned error: %v", err)
+ }
+}
+
+func TestUsersService_DemoteSiteAdmin(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/site_admin", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Users.DemoteSiteAdmin(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Users.DemoteSiteAdmin returned error: %v", err)
+ }
+}
+
+func TestUsersService_Suspend(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/suspended", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Users.Suspend(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Users.Suspend returned error: %v", err)
+ }
+}
+
+func TestUsersService_Unsuspend(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/suspended", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Users.Unsuspend(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Users.Unsuspend returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/users_blocking.go b/vendor/github.com/google/go-github/github/users_blocking.go
new file mode 100644
index 0000000..39e4560
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_blocking.go
@@ -0,0 +1,91 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+)
+
+// ListBlockedUsers lists all the blocked users by the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/blocking/#list-blocked-users
+func (s *UsersService) ListBlockedUsers(ctx context.Context, opt *ListOptions) ([]*User, *Response, error) {
+ u := "user/blocks"
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeBlockUsersPreview)
+
+ var blockedUsers []*User
+ resp, err := s.client.Do(ctx, req, &blockedUsers)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return blockedUsers, resp, nil
+}
+
+// IsBlocked reports whether specified user is blocked by the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/blocking/#check-whether-youve-blocked-a-user
+func (s *UsersService) IsBlocked(ctx context.Context, user string) (bool, *Response, error) {
+ u := fmt.Sprintf("user/blocks/%v", user)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeBlockUsersPreview)
+
+ resp, err := s.client.Do(ctx, req, nil)
+ isBlocked, err := parseBoolResponse(err)
+ return isBlocked, resp, err
+}
+
+// BlockUser blocks specified user for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/blocking/#block-a-user
+func (s *UsersService) BlockUser(ctx context.Context, user string) (*Response, error) {
+ u := fmt.Sprintf("user/blocks/%v", user)
+
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeBlockUsersPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// UnblockUser unblocks specified user for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/blocking/#unblock-a-user
+func (s *UsersService) UnblockUser(ctx context.Context, user string) (*Response, error) {
+ u := fmt.Sprintf("user/blocks/%v", user)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeBlockUsersPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/users_blocking_test.go b/vendor/github.com/google/go-github/github/users_blocking_test.go
new file mode 100644
index 0000000..83e8e30
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_blocking_test.go
@@ -0,0 +1,90 @@
+// Copyright 2017 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestUsersService_ListBlockedUsers(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/blocks", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeBlockUsersPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{
+ "login": "octocat"
+ }]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ blockedUsers, _, err := client.Users.ListBlockedUsers(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Users.ListBlockedUsers returned error: %v", err)
+ }
+
+ want := []*User{{Login: String("octocat")}}
+ if !reflect.DeepEqual(blockedUsers, want) {
+ t.Errorf("Users.ListBlockedUsers returned %+v, want %+v", blockedUsers, want)
+ }
+}
+
+func TestUsersService_IsBlocked(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/blocks/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeBlockUsersPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ isBlocked, _, err := client.Users.IsBlocked(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Users.IsBlocked returned error: %v", err)
+ }
+ if want := true; isBlocked != want {
+ t.Errorf("Users.IsBlocked returned %+v, want %+v", isBlocked, want)
+ }
+}
+
+func TestUsersService_BlockUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/blocks/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ testHeader(t, r, "Accept", mediaTypeBlockUsersPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Users.BlockUser(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Users.BlockUser returned error: %v", err)
+ }
+}
+
+func TestUsersService_UnblockUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/blocks/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeBlockUsersPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ _, err := client.Users.UnblockUser(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Users.UnblockUser returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/users_emails.go b/vendor/github.com/google/go-github/github/users_emails.go
new file mode 100644
index 0000000..0bbd462
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_emails.go
@@ -0,0 +1,71 @@
+// 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 "context"
+
+// UserEmail represents user's email address
+type UserEmail struct {
+ Email *string `json:"email,omitempty"`
+ Primary *bool `json:"primary,omitempty"`
+ Verified *bool `json:"verified,omitempty"`
+}
+
+// ListEmails lists all email addresses for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user
+func (s *UsersService) ListEmails(ctx context.Context, opt *ListOptions) ([]*UserEmail, *Response, error) {
+ u := "user/emails"
+ 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
+ }
+
+ var emails []*UserEmail
+ resp, err := s.client.Do(ctx, req, &emails)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return emails, resp, nil
+}
+
+// AddEmails adds email addresses of the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/emails/#add-email-addresses
+func (s *UsersService) AddEmails(ctx context.Context, emails []string) ([]*UserEmail, *Response, error) {
+ u := "user/emails"
+ req, err := s.client.NewRequest("POST", u, emails)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var e []*UserEmail
+ resp, err := s.client.Do(ctx, req, &e)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return e, resp, nil
+}
+
+// DeleteEmails deletes email addresses from authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/emails/#delete-email-addresses
+func (s *UsersService) DeleteEmails(ctx context.Context, emails []string) (*Response, error) {
+ u := "user/emails"
+ req, err := s.client.NewRequest("DELETE", u, emails)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/users_emails_test.go b/vendor/github.com/google/go-github/github/users_emails_test.go
new file mode 100644
index 0000000..3f72b40
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_emails_test.go
@@ -0,0 +1,95 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestUsersService_ListEmails(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/emails", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{
+ "email": "user@example.com",
+ "verified": false,
+ "primary": true
+ }]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ emails, _, err := client.Users.ListEmails(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Users.ListEmails returned error: %v", err)
+ }
+
+ want := []*UserEmail{{Email: String("user@example.com"), Verified: Bool(false), Primary: Bool(true)}}
+ if !reflect.DeepEqual(emails, want) {
+ t.Errorf("Users.ListEmails returned %+v, want %+v", emails, want)
+ }
+}
+
+func TestUsersService_AddEmails(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := []string{"new@example.com"}
+
+ mux.HandleFunc("/user/emails", func(w http.ResponseWriter, r *http.Request) {
+ var v []string
+ json.NewDecoder(r.Body).Decode(&v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `[{"email":"old@example.com"}, {"email":"new@example.com"}]`)
+ })
+
+ emails, _, err := client.Users.AddEmails(context.Background(), input)
+ if err != nil {
+ t.Errorf("Users.AddEmails returned error: %v", err)
+ }
+
+ want := []*UserEmail{
+ {Email: String("old@example.com")},
+ {Email: String("new@example.com")},
+ }
+ if !reflect.DeepEqual(emails, want) {
+ t.Errorf("Users.AddEmails returned %+v, want %+v", emails, want)
+ }
+}
+
+func TestUsersService_DeleteEmails(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := []string{"user@example.com"}
+
+ mux.HandleFunc("/user/emails", func(w http.ResponseWriter, r *http.Request) {
+ var v []string
+ json.NewDecoder(r.Body).Decode(&v)
+
+ testMethod(t, r, "DELETE")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+ })
+
+ _, err := client.Users.DeleteEmails(context.Background(), input)
+ if err != nil {
+ t.Errorf("Users.DeleteEmails returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/users_followers.go b/vendor/github.com/google/go-github/github/users_followers.go
new file mode 100644
index 0000000..c222409
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_followers.go
@@ -0,0 +1,119 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// ListFollowers lists the followers for a user. Passing the empty string will
+// fetch followers for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/followers/#list-followers-of-a-user
+func (s *UsersService) ListFollowers(ctx context.Context, user string, opt *ListOptions) ([]*User, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v/followers", user)
+ } else {
+ u = "user/followers"
+ }
+ 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
+ }
+
+ var users []*User
+ resp, err := s.client.Do(ctx, req, &users)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return users, resp, nil
+}
+
+// ListFollowing lists the people that a user is following. Passing the empty
+// string will list people the authenticated user is following.
+//
+// GitHub API docs: https://developer.github.com/v3/users/followers/#list-users-followed-by-another-user
+func (s *UsersService) ListFollowing(ctx context.Context, user string, opt *ListOptions) ([]*User, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v/following", user)
+ } else {
+ u = "user/following"
+ }
+ 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
+ }
+
+ var users []*User
+ resp, err := s.client.Do(ctx, req, &users)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return users, resp, nil
+}
+
+// IsFollowing checks if "user" is following "target". Passing the empty
+// string for "user" will check if the authenticated user is following "target".
+//
+// GitHub API docs: https://developer.github.com/v3/users/followers/#check-if-you-are-following-a-user
+func (s *UsersService) IsFollowing(ctx context.Context, user, target string) (bool, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v/following/%v", user, target)
+ } else {
+ u = fmt.Sprintf("user/following/%v", target)
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return false, nil, err
+ }
+
+ resp, err := s.client.Do(ctx, req, nil)
+ following, err := parseBoolResponse(err)
+ return following, resp, err
+}
+
+// Follow will cause the authenticated user to follow the specified user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/followers/#follow-a-user
+func (s *UsersService) Follow(ctx context.Context, user string) (*Response, error) {
+ u := fmt.Sprintf("user/following/%v", user)
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+// Unfollow will cause the authenticated user to unfollow the specified user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/followers/#unfollow-a-user
+func (s *UsersService) Unfollow(ctx context.Context, user string) (*Response, error) {
+ u := fmt.Sprintf("user/following/%v", user)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/users_followers_test.go b/vendor/github.com/google/go-github/github/users_followers_test.go
new file mode 100644
index 0000000..777fe80
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_followers_test.go
@@ -0,0 +1,238 @@
+// 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 (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestUsersService_ListFollowers_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/followers", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ users, _, err := client.Users.ListFollowers(context.Background(), "", opt)
+ if err != nil {
+ t.Errorf("Users.ListFollowers returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}}
+ if !reflect.DeepEqual(users, want) {
+ t.Errorf("Users.ListFollowers returned %+v, want %+v", users, want)
+ }
+}
+
+func TestUsersService_ListFollowers_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/followers", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ users, _, err := client.Users.ListFollowers(context.Background(), "u", nil)
+ if err != nil {
+ t.Errorf("Users.ListFollowers returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}}
+ if !reflect.DeepEqual(users, want) {
+ t.Errorf("Users.ListFollowers returned %+v, want %+v", users, want)
+ }
+}
+
+func TestUsersService_ListFollowers_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Users.ListFollowers(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestUsersService_ListFollowing_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/following", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opts := &ListOptions{Page: 2}
+ users, _, err := client.Users.ListFollowing(context.Background(), "", opts)
+ if err != nil {
+ t.Errorf("Users.ListFollowing returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}}
+ if !reflect.DeepEqual(users, want) {
+ t.Errorf("Users.ListFollowing returned %+v, want %+v", users, want)
+ }
+}
+
+func TestUsersService_ListFollowing_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/following", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ users, _, err := client.Users.ListFollowing(context.Background(), "u", nil)
+ if err != nil {
+ t.Errorf("Users.ListFollowing returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(1)}}
+ if !reflect.DeepEqual(users, want) {
+ t.Errorf("Users.ListFollowing returned %+v, want %+v", users, want)
+ }
+}
+
+func TestUsersService_ListFollowing_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Users.ListFollowing(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestUsersService_IsFollowing_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/following/t", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ following, _, err := client.Users.IsFollowing(context.Background(), "", "t")
+ if err != nil {
+ t.Errorf("Users.IsFollowing returned error: %v", err)
+ }
+ if want := true; following != want {
+ t.Errorf("Users.IsFollowing returned %+v, want %+v", following, want)
+ }
+}
+
+func TestUsersService_IsFollowing_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/following/t", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ following, _, err := client.Users.IsFollowing(context.Background(), "u", "t")
+ if err != nil {
+ t.Errorf("Users.IsFollowing returned error: %v", err)
+ }
+ if want := true; following != want {
+ t.Errorf("Users.IsFollowing returned %+v, want %+v", following, want)
+ }
+}
+
+func TestUsersService_IsFollowing_false(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/following/t", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ w.WriteHeader(http.StatusNotFound)
+ })
+
+ following, _, err := client.Users.IsFollowing(context.Background(), "u", "t")
+ if err != nil {
+ t.Errorf("Users.IsFollowing returned error: %v", err)
+ }
+ if want := false; following != want {
+ t.Errorf("Users.IsFollowing returned %+v, want %+v", following, want)
+ }
+}
+
+func TestUsersService_IsFollowing_error(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/following/t", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ http.Error(w, "BadRequest", http.StatusBadRequest)
+ })
+
+ following, _, err := client.Users.IsFollowing(context.Background(), "u", "t")
+ if err == nil {
+ t.Errorf("Expected HTTP 400 response")
+ }
+ if want := false; following != want {
+ t.Errorf("Users.IsFollowing returned %+v, want %+v", following, want)
+ }
+}
+
+func TestUsersService_IsFollowing_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Users.IsFollowing(context.Background(), "%", "%")
+ testURLParseError(t, err)
+}
+
+func TestUsersService_Follow(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/following/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PUT")
+ })
+
+ _, err := client.Users.Follow(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Users.Follow returned error: %v", err)
+ }
+}
+
+func TestUsersService_Follow_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Users.Follow(context.Background(), "%")
+ testURLParseError(t, err)
+}
+
+func TestUsersService_Unfollow(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/following/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Users.Unfollow(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Users.Follow returned error: %v", err)
+ }
+}
+
+func TestUsersService_Unfollow_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, err := client.Users.Unfollow(context.Background(), "%")
+ testURLParseError(t, err)
+}
diff --git a/vendor/github.com/google/go-github/github/users_gpg_keys.go b/vendor/github.com/google/go-github/github/users_gpg_keys.go
new file mode 100644
index 0000000..d8bbc52
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_gpg_keys.go
@@ -0,0 +1,140 @@
+// Copyright 2016 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 (
+ "context"
+ "fmt"
+ "time"
+)
+
+// GPGKey represents a GitHub user's public GPG key used to verify GPG signed commits and tags.
+//
+// https://developer.github.com/changes/2016-04-04-git-signing-api-preview/
+type GPGKey struct {
+ ID *int64 `json:"id,omitempty"`
+ PrimaryKeyID *int64 `json:"primary_key_id,omitempty"`
+ KeyID *string `json:"key_id,omitempty"`
+ PublicKey *string `json:"public_key,omitempty"`
+ Emails []GPGEmail `json:"emails,omitempty"`
+ Subkeys []GPGKey `json:"subkeys,omitempty"`
+ CanSign *bool `json:"can_sign,omitempty"`
+ CanEncryptComms *bool `json:"can_encrypt_comms,omitempty"`
+ CanEncryptStorage *bool `json:"can_encrypt_storage,omitempty"`
+ CanCertify *bool `json:"can_certify,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ ExpiresAt *time.Time `json:"expires_at,omitempty"`
+}
+
+// String stringifies a GPGKey.
+func (k GPGKey) String() string {
+ return Stringify(k)
+}
+
+// GPGEmail represents an email address associated to a GPG key.
+type GPGEmail struct {
+ Email *string `json:"email,omitempty"`
+ Verified *bool `json:"verified,omitempty"`
+}
+
+// ListGPGKeys lists the public GPG keys for a user. Passing the empty
+// string will fetch keys for the authenticated user. It requires authentication
+// via Basic Auth or via OAuth with at least read:gpg_key scope.
+//
+// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#list-gpg-keys-for-a-user
+func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opt *ListOptions) ([]*GPGKey, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v/gpg_keys", user)
+ } else {
+ u = "user/gpg_keys"
+ }
+ 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
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeGitSigningPreview)
+
+ var keys []*GPGKey
+ resp, err := s.client.Do(ctx, req, &keys)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return keys, resp, nil
+}
+
+// GetGPGKey gets extended details for a single GPG key. It requires authentication
+// via Basic Auth or via OAuth with at least read:gpg_key scope.
+//
+// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#get-a-single-gpg-key
+func (s *UsersService) GetGPGKey(ctx context.Context, id int64) (*GPGKey, *Response, error) {
+ u := fmt.Sprintf("user/gpg_keys/%v", id)
+ 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", mediaTypeGitSigningPreview)
+
+ key := &GPGKey{}
+ resp, err := s.client.Do(ctx, req, key)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return key, resp, nil
+}
+
+// CreateGPGKey creates a GPG key. It requires authenticatation via Basic Auth
+// or OAuth with at least write:gpg_key scope.
+//
+// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#create-a-gpg-key
+func (s *UsersService) CreateGPGKey(ctx context.Context, armoredPublicKey string) (*GPGKey, *Response, error) {
+ gpgKey := &struct {
+ ArmoredPublicKey string `json:"armored_public_key"`
+ }{ArmoredPublicKey: armoredPublicKey}
+ req, err := s.client.NewRequest("POST", "user/gpg_keys", gpgKey)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeGitSigningPreview)
+
+ key := &GPGKey{}
+ resp, err := s.client.Do(ctx, req, key)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return key, resp, nil
+}
+
+// DeleteGPGKey deletes a GPG key. It requires authentication via Basic Auth or
+// via OAuth with at least admin:gpg_key scope.
+//
+// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#delete-a-gpg-key
+func (s *UsersService) DeleteGPGKey(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("user/gpg_keys/%v", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: remove custom Accept header when this API fully launches.
+ req.Header.Set("Accept", mediaTypeGitSigningPreview)
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/users_gpg_keys_test.go b/vendor/github.com/google/go-github/github/users_gpg_keys_test.go
new file mode 100644
index 0000000..ca0207e
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_gpg_keys_test.go
@@ -0,0 +1,142 @@
+// Copyright 2016 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestUsersService_ListGPGKeys_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/gpg_keys", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeGitSigningPreview)
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1,"primary_key_id":2}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ keys, _, err := client.Users.ListGPGKeys(context.Background(), "", opt)
+ if err != nil {
+ t.Errorf("Users.ListGPGKeys returned error: %v", err)
+ }
+
+ want := []*GPGKey{{ID: Int64(1), PrimaryKeyID: Int64(2)}}
+ if !reflect.DeepEqual(keys, want) {
+ t.Errorf("Users.ListGPGKeys = %+v, want %+v", keys, want)
+ }
+}
+
+func TestUsersService_ListGPGKeys_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/gpg_keys", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeGitSigningPreview)
+ fmt.Fprint(w, `[{"id":1,"primary_key_id":2}]`)
+ })
+
+ keys, _, err := client.Users.ListGPGKeys(context.Background(), "u", nil)
+ if err != nil {
+ t.Errorf("Users.ListGPGKeys returned error: %v", err)
+ }
+
+ want := []*GPGKey{{ID: Int64(1), PrimaryKeyID: Int64(2)}}
+ if !reflect.DeepEqual(keys, want) {
+ t.Errorf("Users.ListGPGKeys = %+v, want %+v", keys, want)
+ }
+}
+
+func TestUsersService_ListGPGKeys_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Users.ListGPGKeys(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestUsersService_GetGPGKey(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/gpg_keys/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeGitSigningPreview)
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ key, _, err := client.Users.GetGPGKey(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Users.GetGPGKey returned error: %v", err)
+ }
+
+ want := &GPGKey{ID: Int64(1)}
+ if !reflect.DeepEqual(key, want) {
+ t.Errorf("Users.GetGPGKey = %+v, want %+v", key, want)
+ }
+}
+
+func TestUsersService_CreateGPGKey(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := `
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Comment: GPGTools - https://gpgtools.org
+
+mQINBFcEd9kBEACo54TDbGhKlXKWMvJgecEUKPPcv7XdnpKdGb3LRw5MvFwT0V0f
+...
+=tqfb
+-----END PGP PUBLIC KEY BLOCK-----`
+
+ mux.HandleFunc("/user/gpg_keys", func(w http.ResponseWriter, r *http.Request) {
+ var gpgKey struct {
+ ArmoredPublicKey *string `json:"armored_public_key,omitempty"`
+ }
+ json.NewDecoder(r.Body).Decode(&gpgKey)
+
+ testMethod(t, r, "POST")
+ testHeader(t, r, "Accept", mediaTypeGitSigningPreview)
+ if gpgKey.ArmoredPublicKey == nil || *gpgKey.ArmoredPublicKey != input {
+ t.Errorf("gpgKey = %+v, want %q", gpgKey, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ gpgKey, _, err := client.Users.CreateGPGKey(context.Background(), input)
+ if err != nil {
+ t.Errorf("Users.GetGPGKey returned error: %v", err)
+ }
+
+ want := &GPGKey{ID: Int64(1)}
+ if !reflect.DeepEqual(gpgKey, want) {
+ t.Errorf("Users.GetGPGKey = %+v, want %+v", gpgKey, want)
+ }
+}
+
+func TestUsersService_DeleteGPGKey(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/gpg_keys/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeGitSigningPreview)
+ })
+
+ _, err := client.Users.DeleteGPGKey(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Users.DeleteGPGKey returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/users_keys.go b/vendor/github.com/google/go-github/github/users_keys.go
new file mode 100644
index 0000000..ddc832a
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_keys.go
@@ -0,0 +1,108 @@
+// 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 (
+ "context"
+ "fmt"
+)
+
+// Key represents a public SSH key used to authenticate a user or deploy script.
+type Key struct {
+ ID *int64 `json:"id,omitempty"`
+ Key *string `json:"key,omitempty"`
+ URL *string `json:"url,omitempty"`
+ Title *string `json:"title,omitempty"`
+ ReadOnly *bool `json:"read_only,omitempty"`
+}
+
+func (k Key) String() string {
+ return Stringify(k)
+}
+
+// ListKeys lists the verified public keys for a user. Passing the empty
+// string will fetch keys for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user
+func (s *UsersService) ListKeys(ctx context.Context, user string, opt *ListOptions) ([]*Key, *Response, error) {
+ var u string
+ if user != "" {
+ u = fmt.Sprintf("users/%v/keys", user)
+ } else {
+ u = "user/keys"
+ }
+ 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
+ }
+
+ var keys []*Key
+ resp, err := s.client.Do(ctx, req, &keys)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return keys, resp, nil
+}
+
+// GetKey fetches a single public key.
+//
+// GitHub API docs: https://developer.github.com/v3/users/keys/#get-a-single-public-key
+func (s *UsersService) GetKey(ctx context.Context, id int64) (*Key, *Response, error) {
+ u := fmt.Sprintf("user/keys/%v", id)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ key := new(Key)
+ resp, err := s.client.Do(ctx, req, key)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return key, resp, nil
+}
+
+// CreateKey adds a public key for the authenticated user.
+//
+// GitHub API docs: https://developer.github.com/v3/users/keys/#create-a-public-key
+func (s *UsersService) CreateKey(ctx context.Context, key *Key) (*Key, *Response, error) {
+ u := "user/keys"
+
+ req, err := s.client.NewRequest("POST", u, key)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ k := new(Key)
+ resp, err := s.client.Do(ctx, req, k)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return k, resp, nil
+}
+
+// DeleteKey deletes a public key.
+//
+// GitHub API docs: https://developer.github.com/v3/users/keys/#delete-a-public-key
+func (s *UsersService) DeleteKey(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("user/keys/%v", id)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/vendor/github.com/google/go-github/github/users_keys_test.go b/vendor/github.com/google/go-github/github/users_keys_test.go
new file mode 100644
index 0000000..3115fdb
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_keys_test.go
@@ -0,0 +1,128 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestUsersService_ListKeys_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/keys", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"page": "2"})
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ opt := &ListOptions{Page: 2}
+ keys, _, err := client.Users.ListKeys(context.Background(), "", opt)
+ if err != nil {
+ t.Errorf("Users.ListKeys returned error: %v", err)
+ }
+
+ want := []*Key{{ID: Int64(1)}}
+ if !reflect.DeepEqual(keys, want) {
+ t.Errorf("Users.ListKeys returned %+v, want %+v", keys, want)
+ }
+}
+
+func TestUsersService_ListKeys_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/keys", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `[{"id":1}]`)
+ })
+
+ keys, _, err := client.Users.ListKeys(context.Background(), "u", nil)
+ if err != nil {
+ t.Errorf("Users.ListKeys returned error: %v", err)
+ }
+
+ want := []*Key{{ID: Int64(1)}}
+ if !reflect.DeepEqual(keys, want) {
+ t.Errorf("Users.ListKeys returned %+v, want %+v", keys, want)
+ }
+}
+
+func TestUsersService_ListKeys_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Users.ListKeys(context.Background(), "%", nil)
+ testURLParseError(t, err)
+}
+
+func TestUsersService_GetKey(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/keys/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ key, _, err := client.Users.GetKey(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Users.GetKey returned error: %v", err)
+ }
+
+ want := &Key{ID: Int64(1)}
+ if !reflect.DeepEqual(key, want) {
+ t.Errorf("Users.GetKey returned %+v, want %+v", key, want)
+ }
+}
+
+func TestUsersService_CreateKey(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &Key{Key: String("k"), Title: String("t")}
+
+ mux.HandleFunc("/user/keys", func(w http.ResponseWriter, r *http.Request) {
+ v := new(Key)
+ json.NewDecoder(r.Body).Decode(v)
+
+ testMethod(t, r, "POST")
+ if !reflect.DeepEqual(v, input) {
+ t.Errorf("Request body = %+v, want %+v", v, input)
+ }
+
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ key, _, err := client.Users.CreateKey(context.Background(), input)
+ if err != nil {
+ t.Errorf("Users.GetKey returned error: %v", err)
+ }
+
+ want := &Key{ID: Int64(1)}
+ if !reflect.DeepEqual(key, want) {
+ t.Errorf("Users.GetKey returned %+v, want %+v", key, want)
+ }
+}
+
+func TestUsersService_DeleteKey(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/keys/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ })
+
+ _, err := client.Users.DeleteKey(context.Background(), 1)
+ if err != nil {
+ t.Errorf("Users.DeleteKey returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/users_test.go b/vendor/github.com/google/go-github/github/users_test.go
new file mode 100644
index 0000000..b011908
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/users_test.go
@@ -0,0 +1,268 @@
+// 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 (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestUser_marshall(t *testing.T) {
+ testJSONMarshal(t, &User{}, "{}")
+
+ u := &User{
+ Login: String("l"),
+ ID: Int64(1),
+ URL: String("u"),
+ AvatarURL: String("a"),
+ GravatarID: String("g"),
+ Name: String("n"),
+ Company: String("c"),
+ Blog: String("b"),
+ Location: String("l"),
+ Email: String("e"),
+ Hireable: Bool(true),
+ PublicRepos: Int(1),
+ Followers: Int(1),
+ Following: Int(1),
+ CreatedAt: &Timestamp{referenceTime},
+ SuspendedAt: &Timestamp{referenceTime},
+ }
+ want := `{
+ "login": "l",
+ "id": 1,
+ "avatar_url": "a",
+ "gravatar_id": "g",
+ "name": "n",
+ "company": "c",
+ "blog": "b",
+ "location": "l",
+ "email": "e",
+ "hireable": true,
+ "public_repos": 1,
+ "followers": 1,
+ "following": 1,
+ "created_at": ` + referenceTimeStr + `,
+ "suspended_at": ` + referenceTimeStr + `,
+ "url": "u"
+ }`
+ testJSONMarshal(t, u, want)
+}
+
+func TestUsersService_Get_authenticatedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ user, _, err := client.Users.Get(context.Background(), "")
+ if err != nil {
+ t.Errorf("Users.Get returned error: %v", err)
+ }
+
+ want := &User{ID: Int64(1)}
+ if !reflect.DeepEqual(user, want) {
+ t.Errorf("Users.Get returned %+v, want %+v", user, want)
+ }
+}
+
+func TestUsersService_Get_specifiedUser(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ user, _, err := client.Users.Get(context.Background(), "u")
+ if err != nil {
+ t.Errorf("Users.Get returned error: %v", err)
+ }
+
+ want := &User{ID: Int64(1)}
+ if !reflect.DeepEqual(user, want) {
+ t.Errorf("Users.Get returned %+v, want %+v", user, want)
+ }
+}
+
+func TestUsersService_Get_invalidUser(t *testing.T) {
+ client, _, _, teardown := setup()
+ defer teardown()
+
+ _, _, err := client.Users.Get(context.Background(), "%")
+ testURLParseError(t, err)
+}
+
+func TestUsersService_GetByID(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ fmt.Fprint(w, `{"id":1}`)
+ })
+
+ user, _, err := client.Users.GetByID(context.Background(), 1)
+ if err != nil {
+ t.Fatalf("Users.GetByID returned error: %v", err)
+ }
+
+ want := &User{ID: Int64(1)}
+ if !reflect.DeepEqual(user, want) {
+ t.Errorf("Users.GetByID returned %+v, want %+v", user, want)
+ }
+}
+
+func TestUsersService_Edit(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ input := &User{Name: String("n")}
+
+ mux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
+ v := new(User)
+ 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}`)
+ })
+
+ user, _, err := client.Users.Edit(context.Background(), input)
+ if err != nil {
+ t.Errorf("Users.Edit returned error: %v", err)
+ }
+
+ want := &User{ID: Int64(1)}
+ if !reflect.DeepEqual(user, want) {
+ t.Errorf("Users.Edit returned %+v, want %+v", user, want)
+ }
+}
+
+func TestUsersService_GetHovercard(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users/u/hovercard", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeHovercardPreview)
+ testFormValues(t, r, values{"subject_type": "repository", "subject_id": "20180408"})
+ fmt.Fprint(w, `{"contexts": [{"message":"Owns this repository", "octicon": "repo"}]}`)
+ })
+
+ opt := &HovercardOptions{SubjectType: "repository", SubjectID: "20180408"}
+ hovercard, _, err := client.Users.GetHovercard(context.Background(), "u", opt)
+ if err != nil {
+ t.Errorf("Users.GetHovercard returned error: %v", err)
+ }
+
+ want := &Hovercard{Contexts: []*UserContext{{Message: String("Owns this repository"), Octicon: String("repo")}}}
+ if !reflect.DeepEqual(hovercard, want) {
+ t.Errorf("Users.GetHovercard returned %+v, want %+v", hovercard, want)
+ }
+}
+
+func TestUsersService_ListAll(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{"since": "1", "page": "2"})
+ fmt.Fprint(w, `[{"id":2}]`)
+ })
+
+ opt := &UserListOptions{1, ListOptions{Page: 2}}
+ users, _, err := client.Users.ListAll(context.Background(), opt)
+ if err != nil {
+ t.Errorf("Users.Get returned error: %v", err)
+ }
+
+ want := []*User{{ID: Int64(2)}}
+ if !reflect.DeepEqual(users, want) {
+ t.Errorf("Users.ListAll returned %+v, want %+v", users, want)
+ }
+}
+
+func TestUsersService_ListInvitations(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/repository_invitations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
+ fmt.Fprintf(w, `[{"id":1}, {"id":2}]`)
+ })
+
+ got, _, err := client.Users.ListInvitations(context.Background(), nil)
+ if err != nil {
+ t.Errorf("Users.ListInvitations returned error: %v", err)
+ }
+
+ want := []*RepositoryInvitation{{ID: Int64(1)}, {ID: Int64(2)}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Users.ListInvitations = %+v, want %+v", got, want)
+ }
+}
+
+func TestUsersService_ListInvitations_withOptions(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/repository_invitations", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "GET")
+ testFormValues(t, r, values{
+ "page": "2",
+ })
+ testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
+ fmt.Fprintf(w, `[{"id":1}, {"id":2}]`)
+ })
+
+ _, _, err := client.Users.ListInvitations(context.Background(), &ListOptions{Page: 2})
+ if err != nil {
+ t.Errorf("Users.ListInvitations returned error: %v", err)
+ }
+}
+func TestUsersService_AcceptInvitation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/repository_invitations/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "PATCH")
+ testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ if _, err := client.Users.AcceptInvitation(context.Background(), 1); err != nil {
+ t.Errorf("Users.AcceptInvitation returned error: %v", err)
+ }
+}
+
+func TestUsersService_DeclineInvitation(t *testing.T) {
+ client, mux, _, teardown := setup()
+ defer teardown()
+
+ mux.HandleFunc("/user/repository_invitations/1", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, "DELETE")
+ testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ if _, err := client.Users.DeclineInvitation(context.Background(), 1); err != nil {
+ t.Errorf("Users.DeclineInvitation returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/google/go-github/github/with_appengine.go b/vendor/github.com/google/go-github/github/with_appengine.go
new file mode 100644
index 0000000..59ce26b
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/with_appengine.go
@@ -0,0 +1,20 @@
+// Copyright 2017 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.
+
+// +build appengine
+
+// This file provides glue for making github work on App Engine.
+
+package github
+
+import (
+ "context"
+ "net/http"
+)
+
+func withContext(ctx context.Context, req *http.Request) *http.Request {
+ // No-op because App Engine adds context to a request differently.
+ return req
+}
diff --git a/vendor/github.com/google/go-github/github/without_appengine.go b/vendor/github.com/google/go-github/github/without_appengine.go
new file mode 100644
index 0000000..6f8fdac
--- /dev/null
+++ b/vendor/github.com/google/go-github/github/without_appengine.go
@@ -0,0 +1,19 @@
+// Copyright 2017 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.
+
+// +build !appengine
+
+// This file provides glue for making github work without App Engine.
+
+package github
+
+import (
+ "context"
+ "net/http"
+)
+
+func withContext(ctx context.Context, req *http.Request) *http.Request {
+ return req.WithContext(ctx)
+}
diff --git a/vendor/github.com/google/go-github/go.mod b/vendor/github.com/google/go-github/go.mod
new file mode 100644
index 0000000..9fb89f5
--- /dev/null
+++ b/vendor/github.com/google/go-github/go.mod
@@ -0,0 +1,11 @@
+module github.com/google/go-github/v18
+
+require (
+ github.com/golang/protobuf v1.2.0 // indirect
+ github.com/google/go-querystring v1.0.0
+ golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac
+ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d // indirect
+ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
+ golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87 // indirect
+ google.golang.org/appengine v1.1.0
+)
diff --git a/vendor/github.com/google/go-github/go.sum b/vendor/github.com/google/go-github/go.sum
new file mode 100644
index 0000000..0f7b90e
--- /dev/null
+++ b/vendor/github.com/google/go-github/go.sum
@@ -0,0 +1,15 @@
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0=
+github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac h1:7d7lG9fHOLdL6jZPtnV4LpI41SbohIJ1Atq7U991dMg=
+golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87 h1:GqwDwfvIpC33dK9bA1fD+JiDUNsuAiQiEkpHqUKze4o=
+golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
diff --git a/vendor/github.com/google/go-github/test/README.md b/vendor/github.com/google/go-github/test/README.md
new file mode 100644
index 0000000..cb3ef55
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/README.md
@@ -0,0 +1,62 @@
+go-github tests
+===============
+
+This directory contains additional test suites beyond the unit tests already in
+[../github](../github). Whereas the unit tests run very quickly (since they
+don't make any network calls) and are run by Travis on every commit, the tests
+in this directory are only run manually.
+
+The test packages are:
+
+integration
+-----------
+
+This will exercise the entire go-github library (or at least as much as is
+practical) against the live GitHub API. These tests will verify that the
+library is properly coded against the actual behavior of the API, and will
+(hopefully) fail upon any incompatible change in the API.
+
+Because these tests are running using live data, there is a much higher
+probability of false positives in test failures due to network issues, test
+data having been changed, etc.
+
+These tests send real network traffic to the GitHub API and will exhaust the
+default unregistered rate limit (60 requests per hour) very quickly.
+Additionally, in order to test the methods that modify data, a real OAuth token
+will need to be present. While the tests will try to be well-behaved in terms
+of what data they modify, it is **strongly** recommended that these tests only
+be run using a dedicated test account.
+
+Run tests using:
+
+ GITHUB_AUTH_TOKEN=XXX go test -v -tags=integration ./integration
+
+Additionally there are a set of integration tests for the Authorizations API.
+These tests require a GitHub user (username and password), and also that a
+[GitHub Application](https://github.com/settings/applications/new) (with
+attendant Client ID and Client Secret) be available. Then, to execute just the
+Authorization tests:
+
+ GITHUB_USERNAME='' GITHUB_PASSWORD='' GITHUB_CLIENT_ID='' GITHUB_CLIENT_SECRET='' go test -v -tags=integration -run=Authorizations ./integration
+
+If some or all of these environment variables are not available, certain of the
+Authorization integration tests will be skipped.
+
+fields
+------
+
+This will identify the fields being returned by the live GitHub API that are
+not currently being mapped into the relevant Go data type. Sometimes fields
+are deliberately not mapped, so the results of this tool should just be taken
+as a hint.
+
+This test sends real network traffic to the GitHub API and will exhaust the
+default unregistered rate limit (60 requests per hour) very quickly.
+Additionally, some data is only returned for authenticated API calls. Unlike
+the integration tests above, these tests only read data, so it's less
+imperitive that these be run using a dedicated test account (though you still
+really should).
+
+Run the fields tool using:
+
+ GITHUB_AUTH_TOKEN=XXX go run ./fields/fields.go
diff --git a/vendor/github.com/google/go-github/test/fields/fields.go b/vendor/github.com/google/go-github/test/fields/fields.go
new file mode 100644
index 0000000..1a75a4c
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/fields/fields.go
@@ -0,0 +1,148 @@
+// Copyright 2014 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.
+
+// This tool tests for the JSON mappings in the go-github data types. It will
+// identify fields that are returned by the live GitHub API, but that are not
+// currently mapped into a struct field of the relevant go-github type. This
+// helps to ensure that all relevant data returned by the API is being made
+// accessible, particularly new fields that are periodically (and sometimes
+// quietly) added to the API over time.
+//
+// These tests simply aid in identifying which fields aren't being mapped; it
+// is not necessarily true that every one of them should always be mapped.
+// Some fields may be undocumented for a reason, either because they aren't
+// actually used yet or should not be relied upon.
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "os"
+ "reflect"
+ "strings"
+
+ "github.com/google/go-github/v18/github"
+ "golang.org/x/oauth2"
+)
+
+var (
+ client *github.Client
+
+ // auth indicates whether tests are being run with an OAuth token.
+ // Tests can use this flag to skip certain tests when run without auth.
+ auth bool
+
+ skipURLs = flag.Bool("skip_urls", false, "skip url fields")
+)
+
+func main() {
+ flag.Parse()
+
+ token := os.Getenv("GITHUB_AUTH_TOKEN")
+ if token == "" {
+ print("!!! No OAuth token. Some tests won't run. !!!\n\n")
+ client = github.NewClient(nil)
+ } else {
+ tc := oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(
+ &oauth2.Token{AccessToken: token},
+ ))
+ client = github.NewClient(tc)
+ auth = true
+ }
+
+ for _, tt := range []struct {
+ url string
+ typ interface{}
+ }{
+ //{"rate_limit", &github.RateLimits{}},
+ {"users/octocat", &github.User{}},
+ {"user", &github.User{}},
+ {"users/willnorris/keys", &[]github.Key{}},
+ {"orgs/google-test", &github.Organization{}},
+ {"repos/google/go-github", &github.Repository{}},
+ {"repos/google/go-github/issues/1", &github.Issue{}},
+ {"/gists/9257657", &github.Gist{}},
+ } {
+ err := testType(tt.url, tt.typ)
+ if err != nil {
+ fmt.Printf("error: %v\n", err)
+ }
+ }
+}
+
+// testType fetches the JSON resource at urlStr and compares its keys to the
+// struct fields of typ.
+func testType(urlStr string, typ interface{}) error {
+ slice := reflect.Indirect(reflect.ValueOf(typ)).Kind() == reflect.Slice
+
+ req, err := client.NewRequest("GET", urlStr, nil)
+ if err != nil {
+ return err
+ }
+
+ // start with a json.RawMessage so we can decode multiple ways below
+ raw := new(json.RawMessage)
+ _, err = client.Do(context.Background(), req, raw)
+ if err != nil {
+ return err
+ }
+
+ // unmarshal directly to a map
+ var m1 map[string]interface{}
+ if slice {
+ var s []map[string]interface{}
+ err = json.Unmarshal(*raw, &s)
+ if err != nil {
+ return err
+ }
+ m1 = s[0]
+ } else {
+ err = json.Unmarshal(*raw, &m1)
+ if err != nil {
+ return err
+ }
+ }
+
+ // unmarshal to typ first, then re-marshal and unmarshal to a map
+ err = json.Unmarshal(*raw, typ)
+ if err != nil {
+ return err
+ }
+
+ var byt []byte
+ if slice {
+ // use first item in slice
+ v := reflect.Indirect(reflect.ValueOf(typ))
+ byt, err = json.Marshal(v.Index(0).Interface())
+ if err != nil {
+ return err
+ }
+ } else {
+ byt, err = json.Marshal(typ)
+ if err != nil {
+ return err
+ }
+ }
+
+ var m2 map[string]interface{}
+ err = json.Unmarshal(byt, &m2)
+ if err != nil {
+ return err
+ }
+
+ // now compare the two maps
+ for k, v := range m1 {
+ if *skipURLs && strings.HasSuffix(k, "_url") {
+ continue
+ }
+ if _, ok := m2[k]; !ok {
+ fmt.Printf("%v missing field for key: %v (example value: %v)\n", reflect.TypeOf(typ), k, v)
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/google/go-github/test/integration/activity_test.go b/vendor/github.com/google/go-github/test/integration/activity_test.go
new file mode 100644
index 0000000..df6c34d
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/integration/activity_test.go
@@ -0,0 +1,141 @@
+// Copyright 2014 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.
+
+// +build integration
+
+package integration
+
+import (
+ "context"
+ "testing"
+
+ "github.com/google/go-github/github"
+)
+
+const (
+ owner = "google"
+ repo = "go-github"
+)
+
+func TestActivity_Starring(t *testing.T) {
+ stargazers, _, err := client.Activity.ListStargazers(context.Background(), owner, repo, nil)
+ if err != nil {
+ t.Fatalf("Activity.ListStargazers returned error: %v", err)
+ }
+
+ if len(stargazers) == 0 {
+ t.Errorf("Activity.ListStargazers(%q, %q) returned no stargazers", owner, repo)
+ }
+
+ // the rest of the tests requires auth
+ if !checkAuth("TestActivity_Starring") {
+ return
+ }
+
+ // first, check if already starred the target repository
+ star, _, err := client.Activity.IsStarred(context.Background(), owner, repo)
+ if err != nil {
+ t.Fatalf("Activity.IsStarred returned error: %v", err)
+ }
+ if star {
+ t.Fatalf("Already starring %v/%v. Please manually unstar it first.", owner, repo)
+ }
+
+ // star the target repository
+ _, err = client.Activity.Star(context.Background(), owner, repo)
+ if err != nil {
+ t.Fatalf("Activity.Star returned error: %v", err)
+ }
+
+ // check again and verify starred
+ star, _, err = client.Activity.IsStarred(context.Background(), owner, repo)
+ if err != nil {
+ t.Fatalf("Activity.IsStarred returned error: %v", err)
+ }
+ if !star {
+ t.Fatalf("Not starred %v/%v after starring it.", owner, repo)
+ }
+
+ // unstar
+ _, err = client.Activity.Unstar(context.Background(), owner, repo)
+ if err != nil {
+ t.Fatalf("Activity.Unstar returned error: %v", err)
+ }
+
+ // check again and verify not watching
+ star, _, err = client.Activity.IsStarred(context.Background(), owner, repo)
+ if err != nil {
+ t.Fatalf("Activity.IsStarred returned error: %v", err)
+ }
+ if star {
+ t.Fatalf("Still starred %v/%v after unstarring it.", owner, repo)
+ }
+}
+
+func deleteSubscription(t *testing.T) {
+ // delete subscription
+ _, err := client.Activity.DeleteRepositorySubscription(context.Background(), owner, repo)
+ if err != nil {
+ t.Fatalf("Activity.DeleteRepositorySubscription returned error: %v", err)
+ }
+
+ // check again and verify not watching
+ sub, _, err := client.Activity.GetRepositorySubscription(context.Background(), owner, repo)
+ if err != nil {
+ t.Fatalf("Activity.GetRepositorySubscription returned error: %v", err)
+ }
+ if sub != nil {
+ t.Fatalf("Still watching %v/%v after deleting subscription.", owner, repo)
+ }
+}
+
+func createSubscription(t *testing.T) {
+ // watch the target repository
+ sub := &github.Subscription{Subscribed: github.Bool(true)}
+ _, _, err := client.Activity.SetRepositorySubscription(context.Background(), owner, repo, sub)
+ if err != nil {
+ t.Fatalf("Activity.SetRepositorySubscription returned error: %v", err)
+ }
+
+ // check again and verify watching
+ sub, _, err = client.Activity.GetRepositorySubscription(context.Background(), owner, repo)
+ if err != nil {
+ t.Fatalf("Activity.GetRepositorySubscription returned error: %v", err)
+ }
+ if sub == nil || !*sub.Subscribed {
+ t.Fatalf("Not watching %v/%v after setting subscription.", owner, repo)
+ }
+}
+
+func TestActivity_Watching(t *testing.T) {
+ watchers, _, err := client.Activity.ListWatchers(context.Background(), owner, repo, nil)
+ if err != nil {
+ t.Fatalf("Activity.ListWatchers returned error: %v", err)
+ }
+
+ if len(watchers) == 0 {
+ t.Errorf("Activity.ListWatchers(%q, %q) returned no watchers", owner, repo)
+ }
+
+ // the rest of the tests requires auth
+ if !checkAuth("TestActivity_Watching") {
+ return
+ }
+
+ // first, check if already watching the target repository
+ sub, _, err := client.Activity.GetRepositorySubscription(context.Background(), owner, repo)
+ if err != nil {
+ t.Fatalf("Activity.GetRepositorySubscription returned error: %v", err)
+ }
+
+ switch {
+ case sub != nil: // If already subscribing, delete then recreate subscription.
+ deleteSubscription(t)
+ createSubscription(t)
+ case sub == nil: // Otherwise, create subscription and then delete it.
+ createSubscription(t)
+ deleteSubscription(t)
+ }
+}
diff --git a/vendor/github.com/google/go-github/test/integration/authorizations_test.go b/vendor/github.com/google/go-github/test/integration/authorizations_test.go
new file mode 100644
index 0000000..532ac76
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/integration/authorizations_test.go
@@ -0,0 +1,306 @@
+// Copyright 2016 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.
+
+// +build integration
+
+package integration
+
+import (
+ "context"
+ "math/rand"
+ "os"
+ "strconv"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/google/go-github/github"
+)
+
+const msgEnvMissing = "Skipping test because the required environment variable (%v) is not present."
+const envKeyGitHubUsername = "GITHUB_USERNAME"
+const envKeyGitHubPassword = "GITHUB_PASSWORD"
+const envKeyClientID = "GITHUB_CLIENT_ID"
+const envKeyClientSecret = "GITHUB_CLIENT_SECRET"
+const InvalidTokenValue = "iamnotacroken"
+
+// TestAuthorizationsBasicOperations tests the basic CRUD operations of the API (mostly for
+// the Personal Access Token scenario).
+func TestAuthorizationsBasicOperations(t *testing.T) {
+
+ client := getUserPassClient(t)
+
+ auths, resp, err := client.Authorizations.List(context.Background(), nil)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 200)
+
+ initialAuthCount := len(auths)
+
+ authReq := generatePersonalAuthTokenRequest()
+
+ createdAuth, resp, err := client.Authorizations.Create(context.Background(), authReq)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 201)
+
+ if *authReq.Note != *createdAuth.Note {
+ t.Fatal("Returned Authorization does not match the requested Authorization.")
+ }
+
+ auths, resp, err = client.Authorizations.List(context.Background(), nil)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 200)
+
+ if len(auths) != initialAuthCount+1 {
+ t.Fatalf("The number of Authorizations should have increased. Expected [%v], was [%v]", initialAuthCount+1, len(auths))
+ }
+
+ // Test updating the authorization
+ authUpdate := new(github.AuthorizationUpdateRequest)
+ authUpdate.Note = github.String("Updated note: " + randString())
+
+ updatedAuth, resp, err := client.Authorizations.Edit(context.Background(), *createdAuth.ID, authUpdate)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 200)
+
+ if *updatedAuth.Note != *authUpdate.Note {
+ t.Fatal("The returned Authorization does not match the requested updated value.")
+ }
+
+ // Verify that the Get operation also reflects the update
+ retrievedAuth, resp, err := client.Authorizations.Get(context.Background(), *createdAuth.ID)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 200)
+
+ if *retrievedAuth.Note != *updatedAuth.Note {
+ t.Fatal("The retrieved Authorization does not match the expected (updated) value.")
+ }
+
+ // Now, let's delete...
+ resp, err = client.Authorizations.Delete(context.Background(), *createdAuth.ID)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 204)
+
+ // Verify that we can no longer retrieve the auth
+ retrievedAuth, resp, err = client.Authorizations.Get(context.Background(), *createdAuth.ID)
+ if err == nil {
+ t.Fatal("Should have failed due to 404")
+ }
+ failIfNotStatusCode(t, resp, 404)
+
+ // Verify that our count reset back to the initial value
+ auths, resp, err = client.Authorizations.List(context.Background(), nil)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 200)
+
+ if len(auths) != initialAuthCount {
+ t.Fatalf("The number of Authorizations should match the initial count Expected [%v], got [%v]", initialAuthCount, len(auths))
+ }
+
+}
+
+// TestAuthorizationsAppOperations tests the application/token related operations, such
+// as creating, testing, resetting and revoking application OAuth tokens.
+func TestAuthorizationsAppOperations(t *testing.T) {
+
+ userAuthenticatedClient := getUserPassClient(t)
+
+ appAuthenticatedClient := getOAuthAppClient(t)
+
+ // We know these vars are set because getOAuthAppClient would have
+ // skipped the test by now
+ clientID := os.Getenv(envKeyClientID)
+ clientSecret := os.Getenv(envKeyClientSecret)
+
+ authRequest := generateAppAuthTokenRequest(clientID, clientSecret)
+
+ createdAuth, resp, err := userAuthenticatedClient.Authorizations.GetOrCreateForApp(context.Background(), clientID, authRequest)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 201)
+
+ // Quick sanity check:
+ if *createdAuth.Note != *authRequest.Note {
+ t.Fatal("The returned auth does not match expected value.")
+ }
+
+ // Let's try the same request again, this time it should return the same
+ // auth instead of creating a new one
+ secondAuth, resp, err := userAuthenticatedClient.Authorizations.GetOrCreateForApp(context.Background(), clientID, authRequest)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 200)
+
+ // Verify that the IDs are the same
+ if *createdAuth.ID != *secondAuth.ID {
+ t.Fatalf("The ID of the second returned auth should be the same as the first. Expected [%v], got [%v]", createdAuth.ID, secondAuth.ID)
+ }
+
+ // Verify the token
+ appAuth, resp, err := appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, *createdAuth.Token)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 200)
+
+ // Quick sanity check
+ if *appAuth.ID != *createdAuth.ID || *appAuth.Token != *createdAuth.Token {
+ t.Fatal("The returned auth/token does not match.")
+ }
+
+ // Let's verify that we get a 404 for a non-existent token
+ _, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, InvalidTokenValue)
+ if err == nil {
+ t.Fatal("An error should have been returned because of the invalid token.")
+ }
+ failIfNotStatusCode(t, resp, 404)
+
+ // Let's reset the token
+ resetAuth, resp, err := appAuthenticatedClient.Authorizations.Reset(context.Background(), clientID, *createdAuth.Token)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 200)
+
+ // Let's verify that we get a 404 for a non-existent token
+ _, resp, err = appAuthenticatedClient.Authorizations.Reset(context.Background(), clientID, InvalidTokenValue)
+ if err == nil {
+ t.Fatal("An error should have been returned because of the invalid token.")
+ }
+ failIfNotStatusCode(t, resp, 404)
+
+ // Verify that the token has changed
+ if resetAuth.Token == createdAuth.Token {
+ t.Fatal("The reset token should be different from the original.")
+ }
+
+ // Verify that we do have a token value
+ if *resetAuth.Token == "" {
+ t.Fatal("A token value should have been returned.")
+ }
+
+ // Verify that the original token is now invalid
+ _, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, *createdAuth.Token)
+ if err == nil {
+ t.Fatal("The original token should be invalid.")
+ }
+ failIfNotStatusCode(t, resp, 404)
+
+ // Check that the reset token is valid
+ _, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, *resetAuth.Token)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 200)
+
+ // Let's revoke the token
+ resp, err = appAuthenticatedClient.Authorizations.Revoke(context.Background(), clientID, *resetAuth.Token)
+ failOnError(t, err)
+ failIfNotStatusCode(t, resp, 204)
+
+ // Sleep for two seconds... I've seen cases where the revocation appears not
+ // to have take place immediately.
+ time.Sleep(time.Second * 2)
+
+ // Now, the reset token should also be invalid
+ _, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, *resetAuth.Token)
+ if err == nil {
+ t.Fatal("The reset token should be invalid.")
+ }
+ failIfNotStatusCode(t, resp, 404)
+}
+
+// generatePersonalAuthTokenRequest is a helper function that generates an
+// AuthorizationRequest for a Personal Access Token (no client id).
+func generatePersonalAuthTokenRequest() *github.AuthorizationRequest {
+
+ rand := randString()
+ auth := github.AuthorizationRequest{
+ Note: github.String("Personal token: Note generated by test: " + rand),
+ Scopes: []github.Scope{github.ScopePublicRepo},
+ Fingerprint: github.String("Personal token: Fingerprint generated by test: " + rand),
+ }
+
+ return &auth
+}
+
+// generatePersonalAuthTokenRequest is a helper function that generates an
+// AuthorizationRequest for an OAuth application Token (uses client id).
+func generateAppAuthTokenRequest(clientID string, clientSecret string) *github.AuthorizationRequest {
+
+ rand := randString()
+ auth := github.AuthorizationRequest{
+ Note: github.String("App token: Note generated by test: " + rand),
+ Scopes: []github.Scope{github.ScopePublicRepo},
+ Fingerprint: github.String("App token: Fingerprint generated by test: " + rand),
+ ClientID: github.String(clientID),
+ ClientSecret: github.String(clientSecret),
+ }
+
+ return &auth
+}
+
+// randString returns a (kinda) random string for uniqueness purposes.
+func randString() string {
+ return strconv.FormatInt(rand.NewSource(time.Now().UnixNano()).Int63(), 10)
+}
+
+// failOnError invokes t.Fatal() if err is present.
+func failOnError(t *testing.T, err error) {
+
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+// failIfNotStatusCode invokes t.Fatal() if the response's status code doesn't match the expected code.
+func failIfNotStatusCode(t *testing.T, resp *github.Response, expectedCode int) {
+
+ if resp.StatusCode != expectedCode {
+ t.Fatalf("Expected HTTP status code [%v] but received [%v]", expectedCode, resp.StatusCode)
+ }
+
+}
+
+// getUserPassClient returns a GitHub client for authorization testing. The client
+// uses BasicAuth via GH username and password passed in environment variables
+// (and will skip the calling test if those vars are not present).
+func getUserPassClient(t *testing.T) *github.Client {
+ username, ok := os.LookupEnv(envKeyGitHubUsername)
+ if !ok {
+ t.Skipf(msgEnvMissing, envKeyGitHubUsername)
+ }
+
+ password, ok := os.LookupEnv(envKeyGitHubPassword)
+ if !ok {
+ t.Skipf(msgEnvMissing, envKeyGitHubPassword)
+ }
+
+ tp := github.BasicAuthTransport{
+ Username: strings.TrimSpace(username),
+ Password: strings.TrimSpace(password),
+ }
+
+ return github.NewClient(tp.Client())
+}
+
+// getOAuthAppClient returns a GitHub client for authorization testing. The client
+// uses BasicAuth, but instead of username and password, it uses the client id
+// and client secret passed in via environment variables
+// (and will skip the calling test if those vars are not present). Certain API operations (check
+// an authorization; reset an authorization; revoke an authorization for an app)
+// require this authentication mechanism.
+//
+// See GitHub API docs: https://developer.com/v3/oauth_authorizations/#check-an-authorization
+func getOAuthAppClient(t *testing.T) *github.Client {
+
+ username, ok := os.LookupEnv(envKeyClientID)
+ if !ok {
+ t.Skipf(msgEnvMissing, envKeyClientID)
+ }
+
+ password, ok := os.LookupEnv(envKeyClientSecret)
+ if !ok {
+ t.Skipf(msgEnvMissing, envKeyClientSecret)
+ }
+
+ tp := github.BasicAuthTransport{
+ Username: strings.TrimSpace(username),
+ Password: strings.TrimSpace(password),
+ }
+
+ return github.NewClient(tp.Client())
+}
diff --git a/vendor/github.com/google/go-github/test/integration/doc.go b/vendor/github.com/google/go-github/test/integration/doc.go
new file mode 100644
index 0000000..5ee470c
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/integration/doc.go
@@ -0,0 +1,11 @@
+// Copyright 2016 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 integration contains integration tests.
+//
+// These tests call the live GitHub API, and therefore require a little more
+// setup to run. See https://github.com/google/go-github/tree/master/test#integration
+// for more information.
+package integration
diff --git a/vendor/github.com/google/go-github/test/integration/github_test.go b/vendor/github.com/google/go-github/test/integration/github_test.go
new file mode 100644
index 0000000..489d38a
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/integration/github_test.go
@@ -0,0 +1,84 @@
+// Copyright 2014 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.
+
+// +build integration
+
+package integration
+
+import (
+ "context"
+ "fmt"
+ "math/rand"
+ "net/http"
+ "os"
+
+ "github.com/google/go-github/github"
+ "golang.org/x/oauth2"
+)
+
+var (
+ client *github.Client
+
+ // auth indicates whether tests are being run with an OAuth token.
+ // Tests can use this flag to skip certain tests when run without auth.
+ auth bool
+)
+
+func init() {
+ token := os.Getenv("GITHUB_AUTH_TOKEN")
+ if token == "" {
+ print("!!! No OAuth token. Some tests won't run. !!!\n\n")
+ client = github.NewClient(nil)
+ } else {
+ tc := oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(
+ &oauth2.Token{AccessToken: token},
+ ))
+ client = github.NewClient(tc)
+ auth = true
+ }
+
+ // Environment variables required for Authorization integration tests
+ vars := []string{envKeyGitHubUsername, envKeyGitHubPassword, envKeyClientID, envKeyClientSecret}
+
+ for _, v := range vars {
+ value := os.Getenv(v)
+ if value == "" {
+ print("!!! " + fmt.Sprintf(msgEnvMissing, v) + " !!!\n\n")
+ }
+ }
+
+}
+
+func checkAuth(name string) bool {
+ if !auth {
+ fmt.Printf("No auth - skipping portions of %v\n", name)
+ }
+ return auth
+}
+
+func createRandomTestRepository(owner string, autoinit bool) (*github.Repository, error) {
+ // create random repo name that does not currently exist
+ var repoName string
+ for {
+ repoName = fmt.Sprintf("test-%d", rand.Int())
+ _, resp, err := client.Repositories.Get(context.Background(), owner, repoName)
+ if err != nil {
+ if resp.StatusCode == http.StatusNotFound {
+ // found a non-existent repo, perfect
+ break
+ }
+
+ return nil, err
+ }
+ }
+
+ // create the repository
+ repo, _, err := client.Repositories.Create(context.Background(), "", &github.Repository{Name: github.String(repoName), AutoInit: github.Bool(autoinit)})
+ if err != nil {
+ return nil, err
+ }
+
+ return repo, nil
+}
diff --git a/vendor/github.com/google/go-github/test/integration/issues_test.go b/vendor/github.com/google/go-github/test/integration/issues_test.go
new file mode 100644
index 0000000..a5e4890
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/integration/issues_test.go
@@ -0,0 +1,42 @@
+// Copyright 2014 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.
+
+// +build integration
+
+package integration
+
+import (
+ "context"
+ "testing"
+)
+
+func TestIssueEvents(t *testing.T) {
+ events, _, err := client.Issues.ListRepositoryEvents(context.Background(), "google", "go-github", nil)
+ if err != nil {
+ t.Fatalf("Issues.ListRepositoryEvents returned error: %v", err)
+ }
+
+ if len(events) == 0 {
+ t.Errorf("ListRepositoryEvents returned no events")
+ }
+
+ events, _, err = client.Issues.ListIssueEvents(context.Background(), "google", "go-github", 1, nil)
+ if err != nil {
+ t.Fatalf("Issues.ListIssueEvents returned error: %v", err)
+ }
+
+ if len(events) == 0 {
+ t.Errorf("ListIssueEvents returned no events")
+ }
+
+ event, _, err := client.Issues.GetEvent(context.Background(), "google", "go-github", *events[0].ID)
+ if err != nil {
+ t.Fatalf("Issues.GetEvent returned error: %v", err)
+ }
+
+ if *event.URL != *events[0].URL {
+ t.Fatalf("Issues.GetEvent returned event URL: %v, want %v", *event.URL, *events[0].URL)
+ }
+}
diff --git a/vendor/github.com/google/go-github/test/integration/misc_test.go b/vendor/github.com/google/go-github/test/integration/misc_test.go
new file mode 100644
index 0000000..1595cf0
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/integration/misc_test.go
@@ -0,0 +1,79 @@
+// Copyright 2014 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.
+
+// +build integration
+
+package integration
+
+import (
+ "context"
+ "testing"
+ "time"
+)
+
+func TestEmojis(t *testing.T) {
+ emoji, _, err := client.ListEmojis(context.Background())
+ if err != nil {
+ t.Fatalf("ListEmojis returned error: %v", err)
+ }
+
+ if len(emoji) == 0 {
+ t.Errorf("ListEmojis returned no emojis")
+ }
+
+ if _, ok := emoji["+1"]; !ok {
+ t.Errorf("ListEmojis missing '+1' emoji")
+ }
+}
+
+func TestAPIMeta(t *testing.T) {
+ meta, _, err := client.APIMeta(context.Background())
+ if err != nil {
+ t.Fatalf("APIMeta returned error: %v", err)
+ }
+
+ if len(meta.Hooks) == 0 {
+ t.Errorf("APIMeta returned no hook addresses")
+ }
+
+ if len(meta.Git) == 0 {
+ t.Errorf("APIMeta returned no git addresses")
+ }
+
+ if !*meta.VerifiablePasswordAuthentication {
+ t.Errorf("APIMeta VerifiablePasswordAuthentication is false")
+ }
+}
+
+func TestRateLimits(t *testing.T) {
+ limits, _, err := client.RateLimits(context.Background())
+ if err != nil {
+ t.Fatalf("RateLimits returned error: %v", err)
+ }
+
+ // do some sanity checks
+ if limits.Core.Limit == 0 {
+ t.Errorf("RateLimits returned 0 core limit")
+ }
+
+ if limits.Core.Limit < limits.Core.Remaining {
+ t.Errorf("Core.Limits is less than Core.Remaining.")
+ }
+
+ if limits.Core.Reset.Time.Before(time.Now().Add(-1 * time.Minute)) {
+ t.Errorf("Core.Reset is more than 1 minute in the past; that doesn't seem right.")
+ }
+}
+
+func TestListServiceHooks(t *testing.T) {
+ hooks, _, err := client.ListServiceHooks(context.Background())
+ if err != nil {
+ t.Fatalf("ListServiceHooks returned error: %v", err)
+ }
+
+ if len(hooks) == 0 {
+ t.Fatalf("ListServiceHooks returned no hooks")
+ }
+}
diff --git a/vendor/github.com/google/go-github/test/integration/pulls_test.go b/vendor/github.com/google/go-github/test/integration/pulls_test.go
new file mode 100644
index 0000000..4aadfbd
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/integration/pulls_test.go
@@ -0,0 +1,28 @@
+// Copyright 2014 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.
+
+// +build integration
+
+package integration
+
+import (
+ "context"
+ "testing"
+)
+
+func TestPullRequests_ListCommits(t *testing.T) {
+ commits, _, err := client.PullRequests.ListCommits(context.Background(), "google", "go-github", 2, nil)
+ if err != nil {
+ t.Fatalf("PullRequests.ListCommits() returned error: %v", err)
+ }
+
+ if got, want := len(commits), 3; got != want {
+ t.Fatalf("PullRequests.ListCommits() returned %d commits, want %d", got, want)
+ }
+
+ if got, want := *commits[0].Author.Login, "sqs"; got != want {
+ t.Fatalf("PullRequests.ListCommits()[0].Author.Login returned %v, want %v", got, want)
+ }
+}
diff --git a/vendor/github.com/google/go-github/test/integration/repos_test.go b/vendor/github.com/google/go-github/test/integration/repos_test.go
new file mode 100644
index 0000000..58aa182
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/integration/repos_test.go
@@ -0,0 +1,181 @@
+// Copyright 2014 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.
+
+// +build integration
+
+package integration
+
+import (
+ "context"
+ "net/http"
+ "reflect"
+ "testing"
+
+ "github.com/google/go-github/github"
+)
+
+func TestRepositories_CRUD(t *testing.T) {
+ if !checkAuth("TestRepositories_CRUD") {
+ return
+ }
+
+ // get authenticated user
+ me, _, err := client.Users.Get(context.Background(), "")
+ if err != nil {
+ t.Fatalf("Users.Get('') returned error: %v", err)
+ }
+
+ repo, err := createRandomTestRepository(*me.Login, false)
+ if err != nil {
+ t.Fatalf("createRandomTestRepository returned error: %v", err)
+ }
+
+ // update the repository description
+ repo.Description = github.String("description")
+ repo.DefaultBranch = nil // FIXME: this shouldn't be necessary
+ _, _, err = client.Repositories.Edit(context.Background(), *repo.Owner.Login, *repo.Name, repo)
+ if err != nil {
+ t.Fatalf("Repositories.Edit() returned error: %v", err)
+ }
+
+ // delete the repository
+ _, err = client.Repositories.Delete(context.Background(), *repo.Owner.Login, *repo.Name)
+ if err != nil {
+ t.Fatalf("Repositories.Delete() returned error: %v", err)
+ }
+
+ // verify that the repository was deleted
+ _, resp, err := client.Repositories.Get(context.Background(), *repo.Owner.Login, *repo.Name)
+ if err == nil {
+ t.Fatalf("Test repository still exists after deleting it.")
+ }
+ if err != nil && resp.StatusCode != http.StatusNotFound {
+ t.Fatalf("Repositories.Get() returned error: %v", err)
+ }
+}
+
+func TestRepositories_BranchesTags(t *testing.T) {
+ // branches
+ branches, _, err := client.Repositories.ListBranches(context.Background(), "git", "git", nil)
+ if err != nil {
+ t.Fatalf("Repositories.ListBranches() returned error: %v", err)
+ }
+
+ if len(branches) == 0 {
+ t.Fatalf("Repositories.ListBranches('git', 'git') returned no branches")
+ }
+
+ _, _, err = client.Repositories.GetBranch(context.Background(), "git", "git", *branches[0].Name)
+ if err != nil {
+ t.Fatalf("Repositories.GetBranch() returned error: %v", err)
+ }
+
+ // tags
+ tags, _, err := client.Repositories.ListTags(context.Background(), "git", "git", nil)
+ if err != nil {
+ t.Fatalf("Repositories.ListTags() returned error: %v", err)
+ }
+
+ if len(tags) == 0 {
+ t.Fatalf("Repositories.ListTags('git', 'git') returned no tags")
+ }
+}
+
+func TestRepositories_EditBranches(t *testing.T) {
+ if !checkAuth("TestRepositories_EditBranches") {
+ return
+ }
+
+ // get authenticated user
+ me, _, err := client.Users.Get(context.Background(), "")
+ if err != nil {
+ t.Fatalf("Users.Get('') returned error: %v", err)
+ }
+
+ repo, err := createRandomTestRepository(*me.Login, true)
+ if err != nil {
+ t.Fatalf("createRandomTestRepository returned error: %v", err)
+ }
+
+ branch, _, err := client.Repositories.GetBranch(context.Background(), *repo.Owner.Login, *repo.Name, "master")
+ if err != nil {
+ t.Fatalf("Repositories.GetBranch() returned error: %v", err)
+ }
+
+ if *branch.Protected {
+ t.Fatalf("Branch %v of repo %v is already protected", "master", *repo.Name)
+ }
+
+ protectionRequest := &github.ProtectionRequest{
+ RequiredStatusChecks: &github.RequiredStatusChecks{
+ Strict: true,
+ Contexts: []string{"continuous-integration"},
+ },
+ RequiredPullRequestReviews: &github.PullRequestReviewsEnforcementRequest{
+ DismissStaleReviews: true,
+ },
+ EnforceAdmins: true,
+ // TODO: Only organization repositories can have users and team restrictions.
+ // In order to be able to test these Restrictions, need to add support
+ // for creating temporary organization repositories.
+ Restrictions: nil,
+ }
+
+ protection, _, err := client.Repositories.UpdateBranchProtection(context.Background(), *repo.Owner.Login, *repo.Name, "master", protectionRequest)
+ if err != nil {
+ t.Fatalf("Repositories.UpdateBranchProtection() returned error: %v", err)
+ }
+
+ want := &github.Protection{
+ RequiredStatusChecks: &github.RequiredStatusChecks{
+ Strict: true,
+ Contexts: []string{"continuous-integration"},
+ },
+ RequiredPullRequestReviews: &github.PullRequestReviewsEnforcement{
+ DismissStaleReviews: true,
+ RequiredApprovingReviewCount: 0,
+ },
+ EnforceAdmins: &github.AdminEnforcement{
+ URL: github.String("https://api.github.com/repos/" + *repo.Owner.Login + "/" + *repo.Name + "/branches/master/protection/enforce_admins"),
+ Enabled: true,
+ },
+ Restrictions: nil,
+ }
+ if !reflect.DeepEqual(protection, want) {
+ t.Errorf("Repositories.UpdateBranchProtection() returned %+v, want %+v", protection, want)
+ }
+
+ _, err = client.Repositories.Delete(context.Background(), *repo.Owner.Login, *repo.Name)
+ if err != nil {
+ t.Fatalf("Repositories.Delete() returned error: %v", err)
+ }
+}
+
+func TestRepositories_List(t *testing.T) {
+ if !checkAuth("TestRepositories_List") {
+ return
+ }
+
+ _, _, err := client.Repositories.List(context.Background(), "", nil)
+ if err != nil {
+ t.Fatalf("Repositories.List('') returned error: %v", err)
+ }
+
+ _, _, err = client.Repositories.List(context.Background(), "google", nil)
+ if err != nil {
+ t.Fatalf("Repositories.List('google') returned error: %v", err)
+ }
+
+ opt := github.RepositoryListOptions{Sort: "created"}
+ repos, _, err := client.Repositories.List(context.Background(), "google", &opt)
+ if err != nil {
+ t.Fatalf("Repositories.List('google') with Sort opt returned error: %v", err)
+ }
+ for i, repo := range repos {
+ if i > 0 && (*repos[i-1].CreatedAt).Time.Before((*repo.CreatedAt).Time) {
+ t.Fatalf("Repositories.List('google') with default descending Sort returned incorrect order")
+ }
+ }
+}
diff --git a/vendor/github.com/google/go-github/test/integration/users_test.go b/vendor/github.com/google/go-github/test/integration/users_test.go
new file mode 100644
index 0000000..3c47c36
--- /dev/null
+++ b/vendor/github.com/google/go-github/test/integration/users_test.go
@@ -0,0 +1,244 @@
+// Copyright 2014 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.
+
+// +build integration
+
+package integration
+
+import (
+ "context"
+ "fmt"
+ "math/rand"
+ "testing"
+
+ "github.com/google/go-github/github"
+)
+
+func TestUsers_Get(t *testing.T) {
+ // list all users
+ users, _, err := client.Users.ListAll(context.Background(), nil)
+ if err != nil {
+ t.Fatalf("Users.ListAll returned error: %v", err)
+ }
+
+ if len(users) == 0 {
+ t.Errorf("Users.ListAll returned no users")
+ }
+
+ // mojombo is user #1
+ if want := "mojombo"; want != *users[0].Login {
+ t.Errorf("user[0].Login was %q, wanted %q", *users[0].Login, want)
+ }
+
+ // get individual user
+ u, _, err := client.Users.Get(context.Background(), "octocat")
+ if err != nil {
+ t.Fatalf("Users.Get('octocat') returned error: %v", err)
+ }
+
+ if want := "octocat"; want != *u.Login {
+ t.Errorf("user.Login was %q, wanted %q", *u.Login, want)
+ }
+ if want := "The Octocat"; want != *u.Name {
+ t.Errorf("user.Name was %q, wanted %q", *u.Name, want)
+ }
+}
+
+func TestUsers_Update(t *testing.T) {
+ if !checkAuth("TestUsers_Get") {
+ return
+ }
+
+ u, _, err := client.Users.Get(context.Background(), "")
+ if err != nil {
+ t.Fatalf("Users.Get('') returned error: %v", err)
+ }
+
+ if *u.Login == "" {
+ t.Errorf("wanted non-empty values for user.Login")
+ }
+
+ // save original location
+ var location string
+ if u.Location != nil {
+ location = *u.Location
+ }
+
+ // update location to test value
+ testLoc := fmt.Sprintf("test-%d", rand.Int())
+ u.Location = &testLoc
+
+ _, _, err = client.Users.Edit(context.Background(), u)
+ if err != nil {
+ t.Fatalf("Users.Update returned error: %v", err)
+ }
+
+ // refetch user and check location value
+ u, _, err = client.Users.Get(context.Background(), "")
+ if err != nil {
+ t.Fatalf("Users.Get('') returned error: %v", err)
+ }
+
+ if testLoc != *u.Location {
+ t.Errorf("Users.Get('') has location: %v, want: %v", *u.Location, testLoc)
+ }
+
+ // set location back to the original value
+ u.Location = &location
+ _, _, err = client.Users.Edit(context.Background(), u)
+ if err != nil {
+ t.Fatalf("Users.Edit returned error: %v", err)
+ }
+}
+
+func TestUsers_Emails(t *testing.T) {
+ if !checkAuth("TestUsers_Emails") {
+ return
+ }
+
+ emails, _, err := client.Users.ListEmails(context.Background(), nil)
+ if err != nil {
+ t.Fatalf("Users.ListEmails() returned error: %v", err)
+ }
+
+ // create random address not currently in user's emails
+ var email string
+EmailLoop:
+ for {
+ email = fmt.Sprintf("test-%d@example.com", rand.Int())
+ for _, e := range emails {
+ if e.Email != nil && *e.Email == email {
+ continue EmailLoop
+ }
+ }
+ break
+ }
+
+ // Add new address
+ _, _, err = client.Users.AddEmails(context.Background(), []string{email})
+ if err != nil {
+ t.Fatalf("Users.AddEmails() returned error: %v", err)
+ }
+
+ // List emails again and verify new email is present
+ emails, _, err = client.Users.ListEmails(context.Background(), nil)
+ if err != nil {
+ t.Fatalf("Users.ListEmails() returned error: %v", err)
+ }
+
+ var found bool
+ for _, e := range emails {
+ if e.Email != nil && *e.Email == email {
+ found = true
+ break
+ }
+ }
+
+ if !found {
+ t.Fatalf("Users.ListEmails() does not contain new address: %v", email)
+ }
+
+ // Remove new address
+ _, err = client.Users.DeleteEmails(context.Background(), []string{email})
+ if err != nil {
+ t.Fatalf("Users.DeleteEmails() returned error: %v", err)
+ }
+
+ // List emails again and verify new email was removed
+ emails, _, err = client.Users.ListEmails(context.Background(), nil)
+ if err != nil {
+ t.Fatalf("Users.ListEmails() returned error: %v", err)
+ }
+
+ for _, e := range emails {
+ if e.Email != nil && *e.Email == email {
+ t.Fatalf("Users.ListEmails() still contains address %v after removing it", email)
+ }
+ }
+}
+
+func TestUsers_Keys(t *testing.T) {
+ keys, _, err := client.Users.ListKeys(context.Background(), "willnorris", nil)
+ if err != nil {
+ t.Fatalf("Users.ListKeys('willnorris') returned error: %v", err)
+ }
+
+ if len(keys) == 0 {
+ t.Errorf("Users.ListKeys('willnorris') returned no keys")
+ }
+
+ // the rest of the tests requires auth
+ if !checkAuth("TestUsers_Keys") {
+ return
+ }
+
+ // TODO: make this integration test work for any authenticated user.
+ keys, _, err = client.Users.ListKeys(context.Background(), "", nil)
+ if err != nil {
+ t.Fatalf("Users.ListKeys('') returned error: %v", err)
+ }
+
+ // ssh public key for testing (fingerprint: a7:22:ad:8c:36:9f:68:65:eb:ae:a1:e4:59:73:c1:76)
+ key := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCy/RIqaMFj2wjkOEjx9EAU0ReLAIhodga82/feo5nnT9UUkHLbL9xrIavfdLHx28lD3xYgPfAoSicUMaAeNwuQhmuerr2c2LFGxzrdXP8pVsQ+Ol7y7OdmFPfe0KrzoZaLJs9aSiZ4VKyY4z5Se/k2UgcJTdgQVlLfw/P96aqCx8yUu94BiWqkDqYEvgWKRNHrTiIo1EXeVBCCcfgNZe1suFfNJUJSUU2T3EG2bpwBbSOCjE3FyH8+Lz3K3BOGzm3df8E7Regj9j4YIcD8cWJYO86jLJoGgQ0L5MSOq+ishNaHQXech22Ix03D1lVMjCvDT7S/C94Z1LzhI2lhvyff"
+ for _, k := range keys {
+ if k.Key != nil && *k.Key == key {
+ t.Fatalf("Test key already exists for user. Please manually remove it first.")
+ }
+ }
+
+ // Add new key
+ _, _, err = client.Users.CreateKey(context.Background(), &github.Key{
+ Title: github.String("go-github test key"),
+ Key: github.String(key),
+ })
+ if err != nil {
+ t.Fatalf("Users.CreateKey() returned error: %v", err)
+ }
+
+ // List keys again and verify new key is present
+ keys, _, err = client.Users.ListKeys(context.Background(), "", nil)
+ if err != nil {
+ t.Fatalf("Users.ListKeys('') returned error: %v", err)
+ }
+
+ var id int64
+ for _, k := range keys {
+ if k.Key != nil && *k.Key == key {
+ id = *k.ID
+ break
+ }
+ }
+
+ if id == 0 {
+ t.Fatalf("Users.ListKeys('') does not contain added test key")
+ }
+
+ // Verify that fetching individual key works
+ k, _, err := client.Users.GetKey(context.Background(), id)
+ if err != nil {
+ t.Fatalf("Users.GetKey(%q) returned error: %v", id, err)
+ }
+ if *k.Key != key {
+ t.Fatalf("Users.GetKey(%q) returned key %v, want %v", id, *k.Key, key)
+ }
+
+ // Remove test key
+ _, err = client.Users.DeleteKey(context.Background(), id)
+ if err != nil {
+ t.Fatalf("Users.DeleteKey(%d) returned error: %v", id, err)
+ }
+
+ // List keys again and verify test key was removed
+ keys, _, err = client.Users.ListKeys(context.Background(), "", nil)
+ if err != nil {
+ t.Fatalf("Users.ListKeys('') returned error: %v", err)
+ }
+
+ for _, k := range keys {
+ if k.Key != nil && *k.Key == key {
+ t.Fatalf("Users.ListKeys('') still contains test key after removing it")
+ }
+ }
+}
diff --git a/vendor/github.com/google/go-querystring/.gitignore b/vendor/github.com/google/go-querystring/.gitignore
new file mode 100644
index 0000000..9ed3b07
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/.gitignore
@@ -0,0 +1 @@
+*.test
diff --git a/vendor/github.com/google/go-querystring/CONTRIBUTING.md b/vendor/github.com/google/go-querystring/CONTRIBUTING.md
new file mode 100644
index 0000000..51cf5cd
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/CONTRIBUTING.md
@@ -0,0 +1,67 @@
+# How to contribute #
+
+We'd love to accept your patches and contributions to this project. There are
+a just a few small guidelines you need to follow.
+
+
+## Contributor License Agreement ##
+
+Contributions to any Google project must be accompanied by a Contributor
+License Agreement. This is not a copyright **assignment**, it simply gives
+Google permission to use and redistribute your contributions as part of the
+project.
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual
+ CLA][].
+
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA][].
+
+You generally only need to submit a CLA once, so if you've already submitted
+one (even if it was for a different project), you probably don't need to do it
+again.
+
+[individual CLA]: https://developers.google.com/open-source/cla/individual
+[corporate CLA]: https://developers.google.com/open-source/cla/corporate
+
+
+## Submitting a patch ##
+
+ 1. It's generally best to start by opening a new issue describing the bug or
+ feature you're intending to fix. Even if you think it's relatively minor,
+ it's helpful to know what people are working on. Mention in the initial
+ issue that you are planning to work on that bug or feature so that it can
+ be assigned to you.
+
+ 1. Follow the normal process of [forking][] the project, and setup a new
+ branch to work in. It's important that each group of changes be done in
+ separate branches in order to ensure that a pull request only includes the
+ commits related to that bug or feature.
+
+ 1. Go makes it very simple to ensure properly formatted code, so always run
+ `go fmt` on your code before committing it. You should also run
+ [golint][] over your code. As noted in the [golint readme][], it's not
+ strictly necessary that your code be completely "lint-free", but this will
+ help you find common style issues.
+
+ 1. Any significant changes should almost always be accompanied by tests. The
+ project already has good test coverage, so look at some of the existing
+ tests if you're unsure how to go about it. [gocov][] and [gocov-html][]
+ are invaluable tools for seeing which parts of your code aren't being
+ exercised by your tests.
+
+ 1. Do your best to have [well-formed commit messages][] for each change.
+ This provides consistency throughout the project, and ensures that commit
+ messages are able to be formatted properly by various git tools.
+
+ 1. Finally, push the commits to your fork and submit a [pull request][].
+
+[forking]: https://help.github.com/articles/fork-a-repo
+[golint]: https://github.com/golang/lint
+[golint readme]: https://github.com/golang/lint/blob/master/README
+[gocov]: https://github.com/axw/gocov
+[gocov-html]: https://github.com/matm/gocov-html
+[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
+[squash]: http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
+[pull request]: https://help.github.com/articles/creating-a-pull-request
diff --git a/vendor/github.com/google/go-querystring/LICENSE b/vendor/github.com/google/go-querystring/LICENSE
new file mode 100644
index 0000000..ae121a1
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2013 Google. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/google/go-querystring/README.md b/vendor/github.com/google/go-querystring/README.md
new file mode 100644
index 0000000..03e9370
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/README.md
@@ -0,0 +1,39 @@
+# go-querystring #
+
+go-querystring is Go library for encoding structs into URL query parameters.
+
+
+**Documentation:**
+**Build Status:** [](https://drone.io/github.com/google/go-querystring/latest)
+
+## Usage ##
+
+```go
+import "github.com/google/go-querystring/query"
+```
+
+go-querystring is designed to assist in scenarios where you want to construct a
+URL using a struct that represents the URL query parameters. You might do this
+to enforce the type safety of your parameters, for example, as is done in the
+[go-github][] library.
+
+The query package exports a single `Values()` function. A simple example:
+
+```go
+type Options struct {
+ Query string `url:"q"`
+ ShowAll bool `url:"all"`
+ Page int `url:"page"`
+}
+
+opt := Options{ "foo", true, 2 }
+v, _ := query.Values(opt)
+fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2"
+```
+
+[go-github]: https://github.com/google/go-github/commit/994f6f8405f052a117d2d0b500054341048fbb08
+
+## License ##
+
+This library is distributed under the BSD-style license found in the [LICENSE](./LICENSE)
+file.
diff --git a/vendor/github.com/google/go-querystring/go.mod b/vendor/github.com/google/go-querystring/go.mod
new file mode 100644
index 0000000..45dca2d
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/go.mod
@@ -0,0 +1 @@
+module github.com/google/go-querystring
diff --git a/vendor/github.com/google/go-querystring/query/encode.go b/vendor/github.com/google/go-querystring/query/encode.go
new file mode 100644
index 0000000..37080b1
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/query/encode.go
@@ -0,0 +1,320 @@
+// Copyright 2013 The Go 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 query implements encoding of structs into URL query parameters.
+//
+// As a simple example:
+//
+// type Options struct {
+// Query string `url:"q"`
+// ShowAll bool `url:"all"`
+// Page int `url:"page"`
+// }
+//
+// opt := Options{ "foo", true, 2 }
+// v, _ := query.Values(opt)
+// fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2"
+//
+// The exact mapping between Go values and url.Values is described in the
+// documentation for the Values() function.
+package query
+
+import (
+ "bytes"
+ "fmt"
+ "net/url"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+)
+
+var timeType = reflect.TypeOf(time.Time{})
+
+var encoderType = reflect.TypeOf(new(Encoder)).Elem()
+
+// Encoder is an interface implemented by any type that wishes to encode
+// itself into URL values in a non-standard way.
+type Encoder interface {
+ EncodeValues(key string, v *url.Values) error
+}
+
+// Values returns the url.Values encoding of v.
+//
+// Values expects to be passed a struct, and traverses it recursively using the
+// following encoding rules.
+//
+// Each exported struct field is encoded as a URL parameter unless
+//
+// - the field's tag is "-", or
+// - the field is empty and its tag specifies the "omitempty" option
+//
+// The empty values are false, 0, any nil pointer or interface value, any array
+// slice, map, or string of length zero, and any time.Time that returns true
+// for IsZero().
+//
+// The URL parameter name defaults to the struct field name but can be
+// specified in the struct field's tag value. The "url" key in the struct
+// field's tag value is the key name, followed by an optional comma and
+// options. For example:
+//
+// // Field is ignored by this package.
+// Field int `url:"-"`
+//
+// // Field appears as URL parameter "myName".
+// Field int `url:"myName"`
+//
+// // Field appears as URL parameter "myName" and the field is omitted if
+// // its value is empty
+// Field int `url:"myName,omitempty"`
+//
+// // Field appears as URL parameter "Field" (the default), but the field
+// // is skipped if empty. Note the leading comma.
+// Field int `url:",omitempty"`
+//
+// For encoding individual field values, the following type-dependent rules
+// apply:
+//
+// Boolean values default to encoding as the strings "true" or "false".
+// Including the "int" option signals that the field should be encoded as the
+// strings "1" or "0".
+//
+// time.Time values default to encoding as RFC3339 timestamps. Including the
+// "unix" option signals that the field should be encoded as a Unix time (see
+// time.Unix())
+//
+// Slice and Array values default to encoding as multiple URL values of the
+// same name. Including the "comma" option signals that the field should be
+// encoded as a single comma-delimited value. Including the "space" option
+// similarly encodes the value as a single space-delimited string. Including
+// the "semicolon" option will encode the value as a semicolon-delimited string.
+// Including the "brackets" option signals that the multiple URL values should
+// have "[]" appended to the value name. "numbered" will append a number to
+// the end of each incidence of the value name, example:
+// name0=value0&name1=value1, etc.
+//
+// Anonymous struct fields are usually encoded as if their inner exported
+// fields were fields in the outer struct, subject to the standard Go
+// visibility rules. An anonymous struct field with a name given in its URL
+// tag is treated as having that name, rather than being anonymous.
+//
+// Non-nil pointer values are encoded as the value pointed to.
+//
+// Nested structs are encoded including parent fields in value names for
+// scoping. e.g:
+//
+// "user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO"
+//
+// All other values are encoded using their default string representation.
+//
+// Multiple fields that encode to the same URL parameter name will be included
+// as multiple URL values of the same name.
+func Values(v interface{}) (url.Values, error) {
+ values := make(url.Values)
+ val := reflect.ValueOf(v)
+ for val.Kind() == reflect.Ptr {
+ if val.IsNil() {
+ return values, nil
+ }
+ val = val.Elem()
+ }
+
+ if v == nil {
+ return values, nil
+ }
+
+ if val.Kind() != reflect.Struct {
+ return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind())
+ }
+
+ err := reflectValue(values, val, "")
+ return values, err
+}
+
+// reflectValue populates the values parameter from the struct fields in val.
+// Embedded structs are followed recursively (using the rules defined in the
+// Values function documentation) breadth-first.
+func reflectValue(values url.Values, val reflect.Value, scope string) error {
+ var embedded []reflect.Value
+
+ typ := val.Type()
+ for i := 0; i < typ.NumField(); i++ {
+ sf := typ.Field(i)
+ if sf.PkgPath != "" && !sf.Anonymous { // unexported
+ continue
+ }
+
+ sv := val.Field(i)
+ tag := sf.Tag.Get("url")
+ if tag == "-" {
+ continue
+ }
+ name, opts := parseTag(tag)
+ if name == "" {
+ if sf.Anonymous && sv.Kind() == reflect.Struct {
+ // save embedded struct for later processing
+ embedded = append(embedded, sv)
+ continue
+ }
+
+ name = sf.Name
+ }
+
+ if scope != "" {
+ name = scope + "[" + name + "]"
+ }
+
+ if opts.Contains("omitempty") && isEmptyValue(sv) {
+ continue
+ }
+
+ if sv.Type().Implements(encoderType) {
+ if !reflect.Indirect(sv).IsValid() {
+ sv = reflect.New(sv.Type().Elem())
+ }
+
+ m := sv.Interface().(Encoder)
+ if err := m.EncodeValues(name, &values); err != nil {
+ return err
+ }
+ continue
+ }
+
+ if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array {
+ var del byte
+ if opts.Contains("comma") {
+ del = ','
+ } else if opts.Contains("space") {
+ del = ' '
+ } else if opts.Contains("semicolon") {
+ del = ';'
+ } else if opts.Contains("brackets") {
+ name = name + "[]"
+ }
+
+ if del != 0 {
+ s := new(bytes.Buffer)
+ first := true
+ for i := 0; i < sv.Len(); i++ {
+ if first {
+ first = false
+ } else {
+ s.WriteByte(del)
+ }
+ s.WriteString(valueString(sv.Index(i), opts))
+ }
+ values.Add(name, s.String())
+ } else {
+ for i := 0; i < sv.Len(); i++ {
+ k := name
+ if opts.Contains("numbered") {
+ k = fmt.Sprintf("%s%d", name, i)
+ }
+ values.Add(k, valueString(sv.Index(i), opts))
+ }
+ }
+ continue
+ }
+
+ for sv.Kind() == reflect.Ptr {
+ if sv.IsNil() {
+ break
+ }
+ sv = sv.Elem()
+ }
+
+ if sv.Type() == timeType {
+ values.Add(name, valueString(sv, opts))
+ continue
+ }
+
+ if sv.Kind() == reflect.Struct {
+ reflectValue(values, sv, name)
+ continue
+ }
+
+ values.Add(name, valueString(sv, opts))
+ }
+
+ for _, f := range embedded {
+ if err := reflectValue(values, f, scope); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// valueString returns the string representation of a value.
+func valueString(v reflect.Value, opts tagOptions) string {
+ for v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return ""
+ }
+ v = v.Elem()
+ }
+
+ if v.Kind() == reflect.Bool && opts.Contains("int") {
+ if v.Bool() {
+ return "1"
+ }
+ return "0"
+ }
+
+ if v.Type() == timeType {
+ t := v.Interface().(time.Time)
+ if opts.Contains("unix") {
+ return strconv.FormatInt(t.Unix(), 10)
+ }
+ return t.Format(time.RFC3339)
+ }
+
+ return fmt.Sprint(v.Interface())
+}
+
+// isEmptyValue checks if a value should be considered empty for the purposes
+// of omitting fields with the "omitempty" option.
+func isEmptyValue(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ return v.Len() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ }
+
+ if v.Type() == timeType {
+ return v.Interface().(time.Time).IsZero()
+ }
+
+ return false
+}
+
+// tagOptions is the string following a comma in a struct field's "url" tag, or
+// the empty string. It does not include the leading comma.
+type tagOptions []string
+
+// parseTag splits a struct field's url tag into its name and comma-separated
+// options.
+func parseTag(tag string) (string, tagOptions) {
+ s := strings.Split(tag, ",")
+ return s[0], s[1:]
+}
+
+// Contains checks whether the tagOptions contains the specified option.
+func (o tagOptions) Contains(option string) bool {
+ for _, s := range o {
+ if s == option {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/google/go-querystring/query/encode_test.go b/vendor/github.com/google/go-querystring/query/encode_test.go
new file mode 100644
index 0000000..0f26a77
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/query/encode_test.go
@@ -0,0 +1,328 @@
+// Copyright 2013 The Go 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 query
+
+import (
+ "fmt"
+ "net/url"
+ "reflect"
+ "testing"
+ "time"
+)
+
+type Nested struct {
+ A SubNested `url:"a"`
+ B *SubNested `url:"b"`
+ Ptr *SubNested `url:"ptr,omitempty"`
+}
+
+type SubNested struct {
+ Value string `url:"value"`
+}
+
+func TestValues_types(t *testing.T) {
+ str := "string"
+ strPtr := &str
+ timeVal := time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC)
+
+ tests := []struct {
+ in interface{}
+ want url.Values
+ }{
+ {
+ // basic primitives
+ struct {
+ A string
+ B int
+ C uint
+ D float32
+ E bool
+ }{},
+ url.Values{
+ "A": {""},
+ "B": {"0"},
+ "C": {"0"},
+ "D": {"0"},
+ "E": {"false"},
+ },
+ },
+ {
+ // pointers
+ struct {
+ A *string
+ B *int
+ C **string
+ D *time.Time
+ }{
+ A: strPtr,
+ C: &strPtr,
+ D: &timeVal,
+ },
+ url.Values{
+ "A": {str},
+ "B": {""},
+ "C": {str},
+ "D": {"2000-01-01T12:34:56Z"},
+ },
+ },
+ {
+ // slices and arrays
+ struct {
+ A []string
+ B []string `url:",comma"`
+ C []string `url:",space"`
+ D [2]string
+ E [2]string `url:",comma"`
+ F [2]string `url:",space"`
+ G []*string `url:",space"`
+ H []bool `url:",int,space"`
+ I []string `url:",brackets"`
+ J []string `url:",semicolon"`
+ K []string `url:",numbered"`
+ }{
+ A: []string{"a", "b"},
+ B: []string{"a", "b"},
+ C: []string{"a", "b"},
+ D: [2]string{"a", "b"},
+ E: [2]string{"a", "b"},
+ F: [2]string{"a", "b"},
+ G: []*string{&str, &str},
+ H: []bool{true, false},
+ I: []string{"a", "b"},
+ J: []string{"a", "b"},
+ K: []string{"a", "b"},
+ },
+ url.Values{
+ "A": {"a", "b"},
+ "B": {"a,b"},
+ "C": {"a b"},
+ "D": {"a", "b"},
+ "E": {"a,b"},
+ "F": {"a b"},
+ "G": {"string string"},
+ "H": {"1 0"},
+ "I[]": {"a", "b"},
+ "J": {"a;b"},
+ "K0": {"a"},
+ "K1": {"b"},
+ },
+ },
+ {
+ // other types
+ struct {
+ A time.Time
+ B time.Time `url:",unix"`
+ C bool `url:",int"`
+ D bool `url:",int"`
+ }{
+ A: time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC),
+ B: time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC),
+ C: true,
+ D: false,
+ },
+ url.Values{
+ "A": {"2000-01-01T12:34:56Z"},
+ "B": {"946730096"},
+ "C": {"1"},
+ "D": {"0"},
+ },
+ },
+ {
+ struct {
+ Nest Nested `url:"nest"`
+ }{
+ Nested{
+ A: SubNested{
+ Value: "that",
+ },
+ },
+ },
+ url.Values{
+ "nest[a][value]": {"that"},
+ "nest[b]": {""},
+ },
+ },
+ {
+ struct {
+ Nest Nested `url:"nest"`
+ }{
+ Nested{
+ Ptr: &SubNested{
+ Value: "that",
+ },
+ },
+ },
+ url.Values{
+ "nest[a][value]": {""},
+ "nest[b]": {""},
+ "nest[ptr][value]": {"that"},
+ },
+ },
+ {
+ nil,
+ url.Values{},
+ },
+ }
+
+ for i, tt := range tests {
+ v, err := Values(tt.in)
+ if err != nil {
+ t.Errorf("%d. Values(%q) returned error: %v", i, tt.in, err)
+ }
+
+ if !reflect.DeepEqual(tt.want, v) {
+ t.Errorf("%d. Values(%q) returned %v, want %v", i, tt.in, v, tt.want)
+ }
+ }
+}
+
+func TestValues_omitEmpty(t *testing.T) {
+ str := ""
+ s := struct {
+ a string
+ A string
+ B string `url:",omitempty"`
+ C string `url:"-"`
+ D string `url:"omitempty"` // actually named omitempty, not an option
+ E *string `url:",omitempty"`
+ }{E: &str}
+
+ v, err := Values(s)
+ if err != nil {
+ t.Errorf("Values(%q) returned error: %v", s, err)
+ }
+
+ want := url.Values{
+ "A": {""},
+ "omitempty": {""},
+ "E": {""}, // E is included because the pointer is not empty, even though the string being pointed to is
+ }
+ if !reflect.DeepEqual(want, v) {
+ t.Errorf("Values(%q) returned %v, want %v", s, v, want)
+ }
+}
+
+type A struct {
+ B
+}
+
+type B struct {
+ C string
+}
+
+type D struct {
+ B
+ C string
+}
+
+type e struct {
+ B
+ C string
+}
+
+type F struct {
+ e
+}
+
+func TestValues_embeddedStructs(t *testing.T) {
+ tests := []struct {
+ in interface{}
+ want url.Values
+ }{
+ {
+ A{B{C: "foo"}},
+ url.Values{"C": {"foo"}},
+ },
+ {
+ D{B: B{C: "bar"}, C: "foo"},
+ url.Values{"C": {"foo", "bar"}},
+ },
+ {
+ F{e{B: B{C: "bar"}, C: "foo"}}, // With unexported embed
+ url.Values{"C": {"foo", "bar"}},
+ },
+ }
+
+ for i, tt := range tests {
+ v, err := Values(tt.in)
+ if err != nil {
+ t.Errorf("%d. Values(%q) returned error: %v", i, tt.in, err)
+ }
+
+ if !reflect.DeepEqual(tt.want, v) {
+ t.Errorf("%d. Values(%q) returned %v, want %v", i, tt.in, v, tt.want)
+ }
+ }
+}
+
+func TestValues_invalidInput(t *testing.T) {
+ _, err := Values("")
+ if err == nil {
+ t.Errorf("expected Values() to return an error on invalid input")
+ }
+}
+
+type EncodedArgs []string
+
+func (m EncodedArgs) EncodeValues(key string, v *url.Values) error {
+ for i, arg := range m {
+ v.Set(fmt.Sprintf("%s.%d", key, i), arg)
+ }
+ return nil
+}
+
+func TestValues_Marshaler(t *testing.T) {
+ s := struct {
+ Args EncodedArgs `url:"arg"`
+ }{[]string{"a", "b", "c"}}
+ v, err := Values(s)
+ if err != nil {
+ t.Errorf("Values(%q) returned error: %v", s, err)
+ }
+
+ want := url.Values{
+ "arg.0": {"a"},
+ "arg.1": {"b"},
+ "arg.2": {"c"},
+ }
+ if !reflect.DeepEqual(want, v) {
+ t.Errorf("Values(%q) returned %v, want %v", s, v, want)
+ }
+}
+
+func TestValues_MarshalerWithNilPointer(t *testing.T) {
+ s := struct {
+ Args *EncodedArgs `url:"arg"`
+ }{}
+ v, err := Values(s)
+ if err != nil {
+ t.Errorf("Values(%q) returned error: %v", s, err)
+ }
+
+ want := url.Values{}
+ if !reflect.DeepEqual(want, v) {
+ t.Errorf("Values(%q) returned %v, want %v", s, v, want)
+ }
+}
+
+func TestTagParsing(t *testing.T) {
+ name, opts := parseTag("field,foobar,foo")
+ if name != "field" {
+ t.Fatalf("name = %q, want field", name)
+ }
+ for _, tt := range []struct {
+ opt string
+ want bool
+ }{
+ {"foobar", true},
+ {"foo", true},
+ {"bar", false},
+ {"field", false},
+ } {
+ if opts.Contains(tt.opt) != tt.want {
+ t.Errorf("Contains(%q) = %v", tt.opt, !tt.want)
+ }
+ }
+}