提交 ea1fb4d2 编写于 作者: J Jingwen Owen Ou

Use the go-octokit fork

上级 99377725
{
"ImportPath": "github.com/jingweno/gh",
"GoVersion": "go1.1.2",
"GoVersion": "go1.2",
"Packages": [
"./..."
],
......@@ -19,6 +19,11 @@
"ImportPath": "github.com/howeyc/gopass",
"Rev": "4cf66881dcc3d6f0071eb6473d95c39e460de696"
},
{
"ImportPath": "github.com/jingweno/go-octokit/octokit",
"Comment": "v0.4.0-22-gcc97681",
"Rev": "cc97681bc2fdc6e33ac50d02b59d0c786be10809"
},
{
"ImportPath": "github.com/jtacoma/uritemplates",
"Comment": "0.1-14-g0a85813",
......@@ -39,12 +44,7 @@
},
{
"ImportPath": "github.com/lostisland/go-sawyer",
"Rev": "6570b8bacd2bc3d74897b2be63e88fe419276104"
},
{
"ImportPath": "github.com/octokit/go-octokit/octokit",
"Comment": "v0.4.0-18-g00bc554",
"Rev": "00bc55436cc2f34fba4207d970c3f994e6c61065"
"Rev": "5dec856d77069d70c2951c6b8f4f4ef00ea444d9"
}
]
}
......@@ -2,6 +2,7 @@ package octokit
import (
"github.com/lostisland/go-sawyer"
"github.com/lostisland/go-sawyer/hypermedia"
"net/http"
"net/url"
)
......@@ -19,6 +20,7 @@ type Client struct {
UserAgent string
AuthMethod AuthMethod
sawyerClient *sawyer.Client
rootRels hypermedia.Relations
}
func (c *Client) NewRequest(urlStr string) (req *Request, err error) {
......@@ -93,7 +95,7 @@ func (c *Client) put(url *url.URL, input interface{}, output interface{}) (resul
return
}
func (c *Client) Delete(url *url.URL, output interface{}) (result *Result) {
func (c *Client) delete(url *url.URL, output interface{}) (result *Result) {
req, err := c.NewRequest(url.String())
if err != nil {
result = newResult(nil, err)
......
package octokit
import (
"github.com/lostisland/go-sawyer/hypermedia"
"net/url"
)
var (
RootURL = Hyperlink("/")
)
func (c *Client) Rel(name string, m map[string]interface{}) (*url.URL, error) {
if c.rootRels == nil || len(c.rootRels) == 0 {
u, _ := url.Parse("/")
root, res := c.Root(u).One()
if res.HasError() {
return nil, res
}
c.rootRels = root.Rels()
}
return c.rootRels.Rel(name, m)
}
// Create a RooService with the base url.URL
func (c *Client) Root(url *url.URL) (root *RootService) {
root = &RootService{client: c, URL: url}
return
}
type RootService struct {
client *Client
URL *url.URL
}
func (r *RootService) One() (root *Root, result *Result) {
root = &Root{HALResource: &hypermedia.HALResource{}}
result = r.client.get(r.URL, &root)
if root != nil {
// Cached hyperlinks
root.PullsURL = hypermedia.Hyperlink(PullRequestsURL)
}
return
}
type Root struct {
*hypermedia.HALResource
UserSearchURL hypermedia.Hyperlink `rel:"user_search" json:"user_search_url,omitempty"`
UserRepositoriesURL hypermedia.Hyperlink `rel:"user_repositories" json:"user_repositories_url,omitempty"`
UserOrganizationsURL hypermedia.Hyperlink `rel:"user_organizations" json:"user_organizations_url,omitempty"`
UserURL hypermedia.Hyperlink `rel:"user" json:"user_url,omitempty"`
TeamURL hypermedia.Hyperlink `rel:"team" json:"team_url,omitempty"`
StarredGistsURL hypermedia.Hyperlink `rel:"starred_gists" json:"starred_gists_url,omitempty"`
StarredURL hypermedia.Hyperlink `rel:"starred" json:"starred_url,omitempty"`
CurrentUserRepositoriesURL hypermedia.Hyperlink `rel:"current_user_repositories" json:"current_user_repositories_url,omitempty"`
RepositorySearchURL hypermedia.Hyperlink `rel:"repository_search" json:"repository_search_url,omitempty"`
RepositoryURL hypermedia.Hyperlink `rel:"repository" json:"repository_url,omitempty"`
RateLimitURL hypermedia.Hyperlink `rel:"rate_limit" json:"rate_limit_url,omitempty"`
GistsURL hypermedia.Hyperlink `rel:"gists" json:"gists_url,omitempty"`
FollowingURL hypermedia.Hyperlink `rel:"following" json:"following_url,omitempty"`
FeedsURL hypermedia.Hyperlink `rel:"feeds" json:"feeds_url,omitempty"`
EventsURL hypermedia.Hyperlink `rel:"events" json:"events_url,omitempty"`
EmojisURL hypermedia.Hyperlink `rel:"emojis" json:"emojis_url,omitempty"`
EmailsURL hypermedia.Hyperlink `rel:"emails" json:"emails_url,omitempty"`
AuthorizationsURL hypermedia.Hyperlink `rel:"authorizations" json:"authorizations_url,omitempty"`
CurrentUserURL hypermedia.Hyperlink `rel:"current_user" json:"current_user_url,omitempty"`
HubURL hypermedia.Hyperlink `rel:"hub" json:"hub_url,omitempty"`
IssueSearchURL hypermedia.Hyperlink `rel:"issue_search" json:"issue_search_url,omitempty"`
IssuesURL hypermedia.Hyperlink `rel:"issues" json:"issues_url,omitempty"`
KeysURL hypermedia.Hyperlink `rel:"keys" json:"keys_url,omitempty"`
NotificationsURL hypermedia.Hyperlink `rel:"notifications" json:"notifications_url,omitempty"`
OrganizationRepositoriesURL hypermedia.Hyperlink `rel:"organization_repositories" json:"organization_repositories_url,omitempty"`
OrganizationURL hypermedia.Hyperlink `rel:"organization" json:"organization_url,omitempty"`
PublicGistsURL hypermedia.Hyperlink `rel:"public_gists" json:"public_gists_url,omitempty"`
PullsURL hypermedia.Hyperlink `rel:"pulls" json:"-"`
rels hypermedia.Relations `json:"-"`
}
func (r *Root) Rels() hypermedia.Relations {
if r.rels == nil || len(r.rels) == 0 {
r.rels = hypermedia.HyperFieldDecoder(r)
for key, hyperlink := range r.HALResource.Rels() {
r.rels[key] = hyperlink
}
}
return r.rels
}
......@@ -22,3 +22,17 @@ func TestRootService_One(t *testing.T) {
assert.T(t, !result.HasError())
assert.Equal(t, "https://api.github.com/users/{user}", string(root.UserURL))
}
func TestClientRel(t *testing.T) {
setup()
defer tearDown()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
respondWithJSON(w, loadFixture("root.json"))
})
u, err := client.Rel("user", M{"user": "root"})
assert.Equal(t, nil, err)
assert.Equal(t, "https://api.github.com/users/root", u.String())
}
language: go
go:
- 1.1.2
install:
- script/build
script: script/test
......@@ -95,7 +95,15 @@ func (l *Link) Expand(m M) (*url.URL, error) {
return l.Href.Expand(m)
}
// The HyperFieldDecoder
// The HyperFieldDecoder gets link relations from a resource by reflecting on
// its Hyperlink properties. The relation name is taken either from the name
// of the field, or a "rel" struct tag.
//
// type Foo struct {
// Url Hyperlink `rel:"self" json:"url"`
// CommentsUrl Hyperlink `rel:"comments" json:"comments_url"`
// }
//
func HyperFieldDecoder(res interface{}) Relations {
rels := make(Relations)
t := reflect.TypeOf(res).Elem()
......
......@@ -7,16 +7,27 @@ import (
var decoders = make(map[string]DecoderFunc)
// DecoderFunc is a function that creates a Decoder from an io.Reader.
type DecoderFunc func(r io.Reader) Decoder
// A Decoder will decode the given value to the Decoder's io.Reader.
type Decoder interface {
Decode(v interface{}) error
}
/*
AddDecoder installs a decoder for a given format.
AddDecoder("json", func(r io.Reader) Encoder { return json.NewDecoder(r) })
mt, err := Parse("application/json")
decoder, err := mt.Decoder(someReader)
*/
func AddDecoder(format string, decfunc DecoderFunc) {
decoders[format] = decfunc
}
// Decoder finds a decoder based on this MediaType's Format field. An error is
// returned if a decoder cannot be found.
func (m *MediaType) Decoder(body io.Reader) (Decoder, error) {
if decfunc, ok := decoders[m.Format]; ok {
return decfunc(body), nil
......@@ -24,6 +35,8 @@ func (m *MediaType) Decoder(body io.Reader) (Decoder, error) {
return nil, fmt.Errorf("No decoder found for format %s (%s)", m.Format, m.String())
}
// Encode uses this MediaType's Decoder to decode the io.Reader into the given
// value.
func (m *MediaType) Decode(v interface{}, body io.Reader) error {
if v == nil {
return nil
......
......@@ -8,16 +8,27 @@ import (
var encoders = make(map[string]EncoderFunc)
// EncoderFunc is a function that creates an Encoder from an io.Writer.
type EncoderFunc func(w io.Writer) Encoder
// An Encoder will encode the given value to the Encoder's io.Writer.
type Encoder interface {
Encode(v interface{}) error
}
/*
AddEncoder installs an encoder for a given format.
AddEncoder("json", func(w io.Writer) Encoder { return json.NewEncoder(w) })
mt, err := Parse("application/json")
encoder, err := mt.Encoder(someWriter)
*/
func AddEncoder(format string, encfunc EncoderFunc) {
encoders[format] = encfunc
}
// Encoder finds an encoder based on this MediaType's Format field. An error is
// returned if an encoder cannot be found.
func (m *MediaType) Encoder(w io.Writer) (Encoder, error) {
if encfunc, ok := encoders[m.Format]; ok {
return encfunc(w), nil
......@@ -25,6 +36,8 @@ func (m *MediaType) Encoder(w io.Writer) (Encoder, error) {
return nil, fmt.Errorf("No encoder found for format %s (%s)", m.Format, m.String())
}
// Encode uses this MediaType's Encoder to encode the given value into a
// bytes.Buffer.
func (m *MediaType) Encode(v interface{}) (*bytes.Buffer, error) {
if v == nil {
return nil, fmt.Errorf("Nothing to encode")
......
// Package mediatype contains helpers for parsing media type strings. Uses
// RFC4288 as a guide.
package mediatype
import (
......@@ -5,6 +7,39 @@ import (
"strings"
)
/*
A MediaType is a parsed representation of a media type string.
application/vnd.github.raw+json; version=3; charset=utf-8
This gets broken up into the various fields:
- Type: application/vnd.github.raw+json
- MainType: application
- SubType: vnd.github.raw
- Suffix: json
- Vendor: github
- Version: raw
- Format: json
- Params:
version: 3
charset: utf-8
There are a few special behaviors that prioritize custom media types for APIs:
If an API identifies with an "application/vnd" type, the Vendor and Version
fields are parsed from the remainder. The Version's semantic meaning depends on
the application.
If it's not an "application/vnd" type, the Version field is taken from the
"version" parameter.
The Format is taken from the Suffix by default. If not available, it is guessed
by looking for common strings anywhere in the media type. For instance,
"application/json" will identify as the "json" Format.
The Format is used to get an Encoder and a Decoder.
*/
type MediaType struct {
full string
Type string
......@@ -17,6 +52,7 @@ type MediaType struct {
Params map[string]string
}
// Parse builds a *MediaType from a given media type string.
func Parse(v string) (*MediaType, error) {
mt, params, err := mime.ParseMediaType(v)
if err != nil {
......@@ -30,10 +66,13 @@ func Parse(v string) (*MediaType, error) {
})
}
// String returns the full string representation of the MediaType.
func (m *MediaType) String() string {
return m.full
}
// IsVendor determines if this MediaType is associated with commercially
// available products.
func (m *MediaType) IsVendor() bool {
return len(m.Vendor) > 0
}
......
package octokit
import (
"github.com/lostisland/go-sawyer/hypermedia"
"net/url"
)
var (
RootURL = Hyperlink("/")
)
// Create a RooService with the base url.URL
func (c *Client) Root(url *url.URL) (root *RootService) {
root = &RootService{client: c, URL: url}
return
}
type RootService struct {
client *Client
URL *url.URL
}
func (r *RootService) One() (root *Root, result *Result) {
result = r.client.get(r.URL, &root)
if root != nil {
// Cached hyperlinks
root.PullsURL = PullRequestsURL
}
return
}
type Root struct {
*hypermedia.HALResource
UserSearchURL Hyperlink `json:"user_search_url,omitempty"`
UserRepositoriesURL Hyperlink `json:"user_repositories_url,omitempty"`
UserOrganizationsURL Hyperlink `json:"user_organizations_url,omitempty"`
UserURL Hyperlink `json:"user_url,omitempty"`
TeamURL Hyperlink `json:"team_url,omitempty"`
StarredGistsURL Hyperlink `json:"starred_gists_url,omitempty"`
StarredURL Hyperlink `json:"starred_url,omitempty"`
CurrentUserRepositoriesURL Hyperlink `json:"current_user_repositories_url,omitempty"`
RepositorySearchURL Hyperlink `json:"repository_search_url,omitempty"`
RepositoryURL Hyperlink `json:"repository_url,omitempty"`
RateLimitURL Hyperlink `json:"rate_limit_url,omitempty"`
GistsURL Hyperlink `json:"gists_url,omitempty"`
FollowingURL Hyperlink `json:"following_url,omitempty"`
FeedsURL Hyperlink `json:"feeds_url,omitempty"`
EventsURL Hyperlink `json:"events_url,omitempty"`
EmojisURL Hyperlink `json:"emojis_url,omitempty"`
EmailsURL Hyperlink `json:"emails_url,omitempty"`
AuthorizationsURL Hyperlink `json:"authorizations_url,omitempty"`
CurrentUserURL Hyperlink `json:"current_user_url,omitempty"`
HubURL Hyperlink `json:"hub_url,omitempty"`
IssueSearchURL Hyperlink `json:"issue_search_url,omitempty"`
IssuesURL Hyperlink `json:"issues_url,omitempty"`
KeysURL Hyperlink `json:"keys_url,omitempty"`
NotificationsURL Hyperlink `json:"notifications_url,omitempty"`
OrganizationRepositoriesURL Hyperlink `json:"organization_repositories_url,omitempty"`
OrganizationURL Hyperlink `json:"organization_url,omitempty"`
PublicGistsURL Hyperlink `json:"public_gists_url,omitempty"`
PullsURL Hyperlink `json:"-"`
}
......@@ -3,7 +3,7 @@ package commands
import (
"fmt"
"github.com/jingweno/gh/utils"
"github.com/octokit/go-octokit/octokit"
"github.com/jingweno/go-octokit/octokit"
)
var cmdCheckout = &Command{
......
......@@ -3,7 +3,7 @@ package commands
import (
"fmt"
"github.com/jingweno/gh/utils"
"github.com/octokit/go-octokit/octokit"
"github.com/jingweno/go-octokit/octokit"
)
var cmdMerge = &Command{
......
......@@ -2,7 +2,7 @@ package commands
import (
"github.com/bmizerany/assert"
"github.com/octokit/go-octokit/octokit"
"github.com/jingweno/go-octokit/octokit"
"testing"
)
......
......@@ -5,7 +5,7 @@ import (
"github.com/jingweno/gh/git"
"github.com/jingweno/gh/github"
"github.com/jingweno/gh/utils"
"github.com/octokit/go-octokit/octokit"
"github.com/jingweno/go-octokit/octokit"
"os"
"regexp"
"strings"
......
......@@ -2,7 +2,7 @@ package github
import (
"fmt"
"github.com/octokit/go-octokit/octokit"
"github.com/jingweno/go-octokit/octokit"
)
const (
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册