Bump deps

This commit is contained in:
Jeff Mitchell 2017-11-07 11:57:05 -05:00
parent fe52ce1115
commit 07dfc1da27
192 changed files with 6197 additions and 3433 deletions

54
vendor/cloud.google.com/go/internal/annotate.go generated vendored Normal file
View File

@ -0,0 +1,54 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package internal
import (
"fmt"
"google.golang.org/api/googleapi"
"google.golang.org/grpc/status"
)
// Annotate prepends msg to the error message in err, attempting
// to preserve other information in err, like an error code.
//
// Annotate panics if err is nil.
//
// Annotate knows about these error types:
// - "google.golang.org/grpc/status".Status
// - "google.golang.org/api/googleapi".Error
// If the error is not one of these types, Annotate behaves
// like
// fmt.Errorf("%s: %v", msg, err)
func Annotate(err error, msg string) error {
if err == nil {
panic("Annotate called with nil")
}
if s, ok := status.FromError(err); ok {
p := s.Proto()
p.Message = msg + ": " + p.Message
return status.ErrorProto(p)
}
if g, ok := err.(*googleapi.Error); ok {
g.Message = msg + ": " + g.Message
return g
}
return fmt.Errorf("%s: %v", msg, err)
}
// Annotatef uses format and args to format a string, then calls Annotate.
func Annotatef(err error, format string, args ...interface{}) error {
return Annotate(err, fmt.Sprintf(format, args...))
}

View File

@ -15,7 +15,6 @@
package internal
import (
"fmt"
"time"
gax "github.com/googleapis/gax-go"
@ -48,7 +47,7 @@ func retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error),
p := bo.Pause()
if cerr := sleep(ctx, p); cerr != nil {
if lastErr != nil {
return fmt.Errorf("%v; last function err: %v", cerr, lastErr)
return Annotatef(lastErr, "retry failed with %v; last error", cerr)
}
return cerr
}

View File

@ -258,14 +258,15 @@ func SignedURL(bucket, name string, opts *SignedURLOptions) (string, error) {
// ObjectHandle provides operations on an object in a Google Cloud Storage bucket.
// Use BucketHandle.Object to get a handle.
type ObjectHandle struct {
c *Client
bucket string
object string
acl ACLHandle
gen int64 // a negative value indicates latest
conds *Conditions
encryptionKey []byte // AES-256 key
userProject string // for requester-pays buckets
c *Client
bucket string
object string
acl ACLHandle
gen int64 // a negative value indicates latest
conds *Conditions
encryptionKey []byte // AES-256 key
userProject string // for requester-pays buckets
readCompressed bool // Accept-Encoding: gzip
}
// ACL provides access to the object's access control list.
@ -467,6 +468,13 @@ func (o *ObjectHandle) Delete(ctx context.Context) error {
return err
}
// ReadCompressed when true causes the read to happen without decompressing.
func (o *ObjectHandle) ReadCompressed(compressed bool) *ObjectHandle {
o2 := *o
o2.readCompressed = compressed
return &o2
}
// NewReader creates a new Reader to read the contents of the
// object.
// ErrObjectNotExist will be returned if the object is not found.
@ -514,6 +522,9 @@ func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64)
if o.userProject != "" {
req.Header.Set("X-Goog-User-Project", o.userProject)
}
if o.readCompressed {
req.Header.Set("Accept-Encoding", "gzip")
}
if err := setEncryptionHeaders(req.Header, o.encryptionKey, false); err != nil {
return nil, err
}

View File

@ -549,27 +549,7 @@ func (b *Blob) GetMetadata(options *GetBlobMetadataOptions) error {
}
func (b *Blob) writeMetadata(h http.Header) {
metadata := make(map[string]string)
for k, v := range h {
// Can't trust CanonicalHeaderKey() to munge case
// reliably. "_" is allowed in identifiers:
// https://msdn.microsoft.com/en-us/library/azure/dd179414.aspx
// https://msdn.microsoft.com/library/aa664670(VS.71).aspx
// http://tools.ietf.org/html/rfc7230#section-3.2
// ...but "_" is considered invalid by
// CanonicalMIMEHeaderKey in
// https://golang.org/src/net/textproto/reader.go?s=14615:14659#L542
// so k can be "X-Ms-Meta-Lol" or "x-ms-meta-lol_rofl".
k = strings.ToLower(k)
if len(v) == 0 || !strings.HasPrefix(k, strings.ToLower(userDefinedMetadataHeaderPrefix)) {
continue
}
// metadata["lol"] = content of the last X-Ms-Meta-Lol header
k = k[len(userDefinedMetadataHeaderPrefix):]
metadata[k] = v[len(v)-1]
}
b.Metadata = BlobMetadata(metadata)
b.Metadata = BlobMetadata(writeMetadata(h))
}
// DeleteBlobOptions includes the options for a delete blob operation

View File

@ -15,6 +15,7 @@ package storage
// limitations under the License.
import (
"encoding/xml"
"fmt"
"net/http"
"net/url"
@ -85,21 +86,53 @@ func (b BlobStorageClient) ListContainers(params ListContainersParameters) (*Con
uri := b.client.getEndpoint(blobServiceName, "", q)
headers := b.client.getStandardHeaders()
var out ContainerListResponse
type ContainerAlias struct {
bsc *BlobStorageClient
Name string `xml:"Name"`
Properties ContainerProperties `xml:"Properties"`
Metadata BlobMetadata
sasuri url.URL
}
type ContainerListResponseAlias struct {
XMLName xml.Name `xml:"EnumerationResults"`
Xmlns string `xml:"xmlns,attr"`
Prefix string `xml:"Prefix"`
Marker string `xml:"Marker"`
NextMarker string `xml:"NextMarker"`
MaxResults int64 `xml:"MaxResults"`
Containers []ContainerAlias `xml:"Containers>Container"`
}
var outAlias ContainerListResponseAlias
resp, err := b.client.exec(http.MethodGet, uri, headers, nil, b.auth)
if err != nil {
return nil, err
}
defer resp.body.Close()
err = xmlUnmarshal(resp.body, &out)
err = xmlUnmarshal(resp.body, &outAlias)
if err != nil {
return nil, err
}
// assign our client to the newly created Container objects
for i := range out.Containers {
out.Containers[i].bsc = &b
out := ContainerListResponse{
XMLName: outAlias.XMLName,
Xmlns: outAlias.Xmlns,
Prefix: outAlias.Prefix,
Marker: outAlias.Marker,
NextMarker: outAlias.NextMarker,
MaxResults: outAlias.MaxResults,
Containers: make([]Container, len(outAlias.Containers)),
}
for i, cnt := range outAlias.Containers {
out.Containers[i] = Container{
bsc: &b,
Name: cnt.Name,
Properties: cnt.Properties,
Metadata: map[string]string(cnt.Metadata),
sasuri: cnt.sasuri,
}
}
return &out, err
}
@ -124,3 +157,26 @@ func (p ListContainersParameters) getParameters() url.Values {
return out
}
func writeMetadata(h http.Header) map[string]string {
metadata := make(map[string]string)
for k, v := range h {
// Can't trust CanonicalHeaderKey() to munge case
// reliably. "_" is allowed in identifiers:
// https://msdn.microsoft.com/en-us/library/azure/dd179414.aspx
// https://msdn.microsoft.com/library/aa664670(VS.71).aspx
// http://tools.ietf.org/html/rfc7230#section-3.2
// ...but "_" is considered invalid by
// CanonicalMIMEHeaderKey in
// https://golang.org/src/net/textproto/reader.go?s=14615:14659#L542
// so k can be "X-Ms-Meta-Lol" or "x-ms-meta-lol_rofl".
k = strings.ToLower(k)
if len(v) == 0 || !strings.HasPrefix(k, strings.ToLower(userDefinedMetadataHeaderPrefix)) {
continue
}
// metadata["lol"] = content of the last X-Ms-Meta-Lol header
k = k[len(userDefinedMetadataHeaderPrefix):]
metadata[k] = v[len(v)-1]
}
return metadata
}

View File

@ -31,6 +31,7 @@ import (
"net/url"
"regexp"
"runtime"
"strconv"
"strings"
"time"
@ -69,6 +70,11 @@ const (
userAgentHeader = "User-Agent"
userDefinedMetadataHeaderPrefix = "x-ms-meta-"
connectionStringAccountName = "accountname"
connectionStringAccountKey = "accountkey"
connectionStringEndpointSuffix = "endpointsuffix"
connectionStringEndpointProtocol = "defaultendpointsprotocol"
)
var (
@ -204,6 +210,45 @@ func (e UnexpectedStatusCodeError) Got() int {
return e.got
}
// NewClientFromConnectionString creates a Client from the connection string.
func NewClientFromConnectionString(input string) (Client, error) {
var (
accountName, accountKey, endpointSuffix string
useHTTPS = defaultUseHTTPS
)
for _, pair := range strings.Split(input, ";") {
if pair == "" {
continue
}
equalDex := strings.IndexByte(pair, '=')
if equalDex <= 0 {
return Client{}, fmt.Errorf("Invalid connection segment %q", pair)
}
value := pair[equalDex+1:]
key := strings.ToLower(pair[:equalDex])
switch key {
case connectionStringAccountName:
accountName = value
case connectionStringAccountKey:
accountKey = value
case connectionStringEndpointSuffix:
endpointSuffix = value
case connectionStringEndpointProtocol:
useHTTPS = value == "https"
default:
// ignored
}
}
if accountName == StorageEmulatorAccountName {
return NewEmulatorClient()
}
return NewClient(accountName, accountKey, endpointSuffix, DefaultAPIVersion, useHTTPS)
}
// NewBasicClient constructs a Client with given storage service name and
// key.
func NewBasicClient(accountName, accountKey string) (Client, error) {
@ -613,12 +658,13 @@ func (c Client) exec(verb, url string, headers map[string]string, body io.Reader
return nil, errors.New("azure/storage: error creating request: " + err.Error())
}
// if a body was provided ensure that the content length was set.
// http.NewRequest() will automatically do this for a handful of types
// and for those that it doesn't we will handle here.
if body != nil && req.ContentLength < 1 {
if lr, ok := body.(*io.LimitedReader); ok {
setContentLengthFromLimitedReader(req, lr)
// http.NewRequest() will automatically set req.ContentLength for a handful of types
// otherwise we will handle here.
if req.ContentLength < 1 {
if clstr, ok := headers["Content-Length"]; ok {
if cl, err := strconv.ParseInt(clstr, 10, 64); err == nil {
req.ContentLength = cl
}
}
}

View File

@ -512,6 +512,81 @@ func (c *Container) ListBlobs(params ListBlobsParameters) (BlobListResponse, err
return out, err
}
// ContainerMetadataOptions includes options for container metadata operations
type ContainerMetadataOptions struct {
Timeout uint
LeaseID string `header:"x-ms-lease-id"`
RequestID string `header:"x-ms-client-request-id"`
}
// SetMetadata replaces the metadata for the specified container.
//
// Some keys may be converted to Camel-Case before sending. All keys
// are returned in lower case by GetBlobMetadata. HTTP header names
// are case-insensitive so case munging should not matter to other
// applications either.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/set-container-metadata
func (c *Container) SetMetadata(options *ContainerMetadataOptions) error {
params := url.Values{
"comp": {"metadata"},
"restype": {"container"},
}
headers := c.bsc.client.getStandardHeaders()
headers = c.bsc.client.addMetadataToHeaders(headers, c.Metadata)
if options != nil {
params = addTimeout(params, options.Timeout)
headers = mergeHeaders(headers, headersFromStruct(*options))
}
uri := c.bsc.client.getEndpoint(blobServiceName, c.buildPath(), params)
resp, err := c.bsc.client.exec(http.MethodPut, uri, headers, nil, c.bsc.auth)
if err != nil {
return err
}
readAndCloseBody(resp.body)
return checkRespCode(resp.statusCode, []int{http.StatusOK})
}
// GetMetadata returns all user-defined metadata for the specified container.
//
// All metadata keys will be returned in lower case. (HTTP header
// names are case-insensitive.)
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/get-container-metadata
func (c *Container) GetMetadata(options *ContainerMetadataOptions) error {
params := url.Values{
"comp": {"metadata"},
"restype": {"container"},
}
headers := c.bsc.client.getStandardHeaders()
if options != nil {
params = addTimeout(params, options.Timeout)
headers = mergeHeaders(headers, headersFromStruct(*options))
}
uri := c.bsc.client.getEndpoint(blobServiceName, c.buildPath(), params)
resp, err := c.bsc.client.exec(http.MethodGet, uri, headers, nil, c.bsc.auth)
if err != nil {
return err
}
readAndCloseBody(resp.body)
if err := checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
return err
}
c.writeMetadata(resp.headers)
return nil
}
func (c *Container) writeMetadata(h http.Header) {
c.Metadata = writeMetadata(h)
}
func generateContainerACLpayload(policies []ContainerAccessPolicy) (io.Reader, int, error) {
sil := SignedIdentifiers{
SignedIdentifiers: []SignedIdentifier{},

View File

@ -87,10 +87,10 @@ func (b *Blob) modifyRange(blobRange BlobRange, bytes io.Reader, options *PutPag
return errors.New("the value for rangeEnd must be greater than or equal to rangeStart")
}
if blobRange.Start%512 != 0 {
return errors.New("the value for rangeStart must be a modulus of 512")
return errors.New("the value for rangeStart must be a multiple of 512")
}
if blobRange.End%512 != 511 {
return errors.New("the value for rangeEnd must be a modulus of 511")
return errors.New("the value for rangeEnd must be a multiple of 512 - 1")
}
params := url.Values{"comp": {"page"}}
@ -147,7 +147,7 @@ func (b *Blob) GetPageRanges(options *GetPageRangesOptions) (GetPageRangesRespon
params = addTimeout(params, options.Timeout)
params = addSnapshot(params, options.Snapshot)
if options.PreviousSnapshot != nil {
params.Add("prevsnapshot", timeRfc1123Formatted(*options.PreviousSnapshot))
params.Add("prevsnapshot", timeRFC3339Formatted(*options.PreviousSnapshot))
}
if options.Range != nil {
headers["Range"] = options.Range.String()

View File

@ -71,6 +71,10 @@ func timeRfc1123Formatted(t time.Time) string {
return t.Format(http.TimeFormat)
}
func timeRFC3339Formatted(t time.Time) string {
return t.Format("2006-01-02T15:04:05.0000000Z")
}
func mergeParams(v1, v2 url.Values) url.Values {
out := url.Values{}
for k, v := range v1 {
@ -172,7 +176,7 @@ func addTimeout(params url.Values, timeout uint) url.Values {
func addSnapshot(params url.Values, snapshot *time.Time) url.Values {
if snapshot != nil {
params.Add("snapshot", snapshot.Format("2006-01-02T15:04:05.0000000Z"))
params.Add("snapshot", timeRFC3339Formatted(*snapshot))
}
return params
}

View File

@ -1,26 +0,0 @@
// +build !go1.8
// Copyright 2017 Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package storage
import (
"io"
"net/http"
)
func setContentLengthFromLimitedReader(req *http.Request, lr *io.LimitedReader) {
req.ContentLength = lr.N
}

View File

@ -1,32 +0,0 @@
// +build go1.8
// Copyright 2017 Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package storage
import (
"io"
"io/ioutil"
"net/http"
)
func setContentLengthFromLimitedReader(req *http.Request, lr *io.LimitedReader) {
req.ContentLength = lr.N
snapshot := *lr
req.GetBody = func() (io.ReadCloser, error) {
r := snapshot
return ioutil.NopCloser(&r), nil
}
}

View File

@ -16,6 +16,7 @@ package azure
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
@ -37,6 +38,109 @@ const (
operationSucceeded string = "Succeeded"
)
// Future provides a mechanism to access the status and results of an asynchronous request.
// Since futures are stateful they should be passed by value to avoid race conditions.
type Future struct {
req *http.Request
resp *http.Response
ps pollingState
}
// NewFuture returns a new Future object initialized with the specified request.
func NewFuture(req *http.Request) Future {
return Future{req: req}
}
// Response returns the last HTTP response or nil if there isn't one.
func (f Future) Response() *http.Response {
return f.resp
}
// Status returns the last status message of the operation.
func (f Future) Status() string {
if f.ps.State == "" {
return "Unknown"
}
return f.ps.State
}
// PollingMethod returns the method used to monitor the status of the asynchronous operation.
func (f Future) PollingMethod() PollingMethodType {
return f.ps.PollingMethod
}
// Done queries the service to see if the operation has completed.
func (f *Future) Done(sender autorest.Sender) (bool, error) {
// exit early if this future has terminated
if f.ps.hasTerminated() {
return true, f.errorInfo()
}
resp, err := sender.Do(f.req)
f.resp = resp
if err != nil {
return false, err
}
err = updatePollingState(resp, &f.ps)
if err != nil {
return false, err
}
if f.ps.hasTerminated() {
return true, f.errorInfo()
}
f.req, err = newPollingRequest(f.ps)
return false, err
}
// GetPollingDelay returns a duration the application should wait before checking
// the status of the asynchronous request and true; this value is returned from
// the service via the Retry-After response header. If the header wasn't returned
// then the function returns the zero-value time.Duration and false.
func (f Future) GetPollingDelay() (time.Duration, bool) {
if f.resp == nil {
return 0, false
}
retry := f.resp.Header.Get(autorest.HeaderRetryAfter)
if retry == "" {
return 0, false
}
d, err := time.ParseDuration(retry + "s")
if err != nil {
panic(err)
}
return d, true
}
// if the operation failed the polling state will contain
// error information and implements the error interface
func (f *Future) errorInfo() error {
if !f.ps.hasSucceeded() {
return f.ps
}
return nil
}
// MarshalJSON implements the json.Marshaler interface.
func (f Future) MarshalJSON() ([]byte, error) {
return json.Marshal(&f.ps)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (f *Future) UnmarshalJSON(data []byte) error {
err := json.Unmarshal(data, &f.ps)
if err != nil {
return err
}
f.req, err = newPollingRequest(f.ps)
return err
}
// DoPollForAsynchronous returns a SendDecorator that polls if the http.Response is for an Azure
// long-running operation. It will delay between requests for the duration specified in the
// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by
@ -66,10 +170,11 @@ func DoPollForAsynchronous(delay time.Duration) autorest.SendDecorator {
break
}
r, err = newPollingRequest(resp, ps)
r, err = newPollingRequest(ps)
if err != nil {
return resp, err
}
r.Cancel = resp.Request.Cancel
delay = autorest.GetRetryAfter(resp, delay)
resp, err = autorest.SendWithSender(s, r,
@ -160,36 +265,42 @@ func (ps provisioningStatus) hasProvisioningError() bool {
return ps.ProvisioningError != ServiceError{}
}
type pollingResponseFormat string
// PollingMethodType defines a type used for enumerating polling mechanisms.
type PollingMethodType string
const (
usesOperationResponse pollingResponseFormat = "OperationResponse"
usesProvisioningStatus pollingResponseFormat = "ProvisioningStatus"
formatIsUnknown pollingResponseFormat = ""
// PollingAsyncOperation indicates the polling method uses the Azure-AsyncOperation header.
PollingAsyncOperation PollingMethodType = "AsyncOperation"
// PollingLocation indicates the polling method uses the Location header.
PollingLocation PollingMethodType = "Location"
// PollingUnknown indicates an unknown polling method and is the default value.
PollingUnknown PollingMethodType = ""
)
type pollingState struct {
responseFormat pollingResponseFormat
uri string
state string
code string
message string
PollingMethod PollingMethodType `json:"pollingMethod"`
URI string `json:"uri"`
State string `json:"state"`
Code string `json:"code"`
Message string `json:"message"`
}
func (ps pollingState) hasSucceeded() bool {
return hasSucceeded(ps.state)
return hasSucceeded(ps.State)
}
func (ps pollingState) hasTerminated() bool {
return hasTerminated(ps.state)
return hasTerminated(ps.State)
}
func (ps pollingState) hasFailed() bool {
return hasFailed(ps.state)
return hasFailed(ps.State)
}
func (ps pollingState) Error() string {
return fmt.Sprintf("Long running operation terminated with status '%s': Code=%q Message=%q", ps.state, ps.code, ps.message)
return fmt.Sprintf("Long running operation terminated with status '%s': Code=%q Message=%q", ps.State, ps.Code, ps.Message)
}
// updatePollingState maps the operation status -- retrieved from either a provisioningState
@ -204,7 +315,7 @@ func updatePollingState(resp *http.Response, ps *pollingState) error {
// -- The first response will always be a provisioningStatus response; only the polling requests,
// depending on the header returned, may be something otherwise.
var pt provisioningTracker
if ps.responseFormat == usesOperationResponse {
if ps.PollingMethod == PollingAsyncOperation {
pt = &operationResource{}
} else {
pt = &provisioningStatus{}
@ -212,30 +323,30 @@ func updatePollingState(resp *http.Response, ps *pollingState) error {
// If this is the first request (that is, the polling response shape is unknown), determine how
// to poll and what to expect
if ps.responseFormat == formatIsUnknown {
if ps.PollingMethod == PollingUnknown {
req := resp.Request
if req == nil {
return autorest.NewError("azure", "updatePollingState", "Azure Polling Error - Original HTTP request is missing")
}
// Prefer the Azure-AsyncOperation header
ps.uri = getAsyncOperation(resp)
if ps.uri != "" {
ps.responseFormat = usesOperationResponse
ps.URI = getAsyncOperation(resp)
if ps.URI != "" {
ps.PollingMethod = PollingAsyncOperation
} else {
ps.responseFormat = usesProvisioningStatus
ps.PollingMethod = PollingLocation
}
// Else, use the Location header
if ps.uri == "" {
ps.uri = autorest.GetLocation(resp)
if ps.URI == "" {
ps.URI = autorest.GetLocation(resp)
}
// Lastly, requests against an existing resource, use the last request URI
if ps.uri == "" {
if ps.URI == "" {
m := strings.ToUpper(req.Method)
if m == http.MethodPatch || m == http.MethodPut || m == http.MethodGet {
ps.uri = req.URL.String()
ps.URI = req.URL.String()
}
}
}
@ -256,23 +367,23 @@ func updatePollingState(resp *http.Response, ps *pollingState) error {
// -- Unknown states are per-service inprogress states
// -- Otherwise, infer state from HTTP status code
if pt.hasTerminated() {
ps.state = pt.state()
ps.State = pt.state()
} else if pt.state() != "" {
ps.state = operationInProgress
ps.State = operationInProgress
} else {
switch resp.StatusCode {
case http.StatusAccepted:
ps.state = operationInProgress
ps.State = operationInProgress
case http.StatusNoContent, http.StatusCreated, http.StatusOK:
ps.state = operationSucceeded
ps.State = operationSucceeded
default:
ps.state = operationFailed
ps.State = operationFailed
}
}
if ps.state == operationInProgress && ps.uri == "" {
if ps.State == operationInProgress && ps.URI == "" {
return autorest.NewError("azure", "updatePollingState", "Azure Polling Error - Unable to obtain polling URI for %s %s", resp.Request.Method, resp.Request.URL)
}
@ -281,35 +392,30 @@ func updatePollingState(resp *http.Response, ps *pollingState) error {
// -- Response
// -- Otherwise, Unknown
if ps.hasFailed() {
if ps.responseFormat == usesOperationResponse {
if ps.PollingMethod == PollingAsyncOperation {
or := pt.(*operationResource)
ps.code = or.OperationError.Code
ps.message = or.OperationError.Message
ps.Code = or.OperationError.Code
ps.Message = or.OperationError.Message
} else {
p := pt.(*provisioningStatus)
if p.hasProvisioningError() {
ps.code = p.ProvisioningError.Code
ps.message = p.ProvisioningError.Message
ps.Code = p.ProvisioningError.Code
ps.Message = p.ProvisioningError.Message
} else {
ps.code = "Unknown"
ps.message = "None"
ps.Code = "Unknown"
ps.Message = "None"
}
}
}
return nil
}
func newPollingRequest(resp *http.Response, ps pollingState) (*http.Request, error) {
req := resp.Request
if req == nil {
return nil, autorest.NewError("azure", "newPollingRequest", "Azure Polling Error - Original HTTP request is missing")
}
reqPoll, err := autorest.Prepare(&http.Request{Cancel: req.Cancel},
func newPollingRequest(ps pollingState) (*http.Request, error) {
reqPoll, err := autorest.Prepare(&http.Request{},
autorest.AsGet(),
autorest.WithBaseURL(ps.uri))
autorest.WithBaseURL(ps.URI))
if err != nil {
return nil, autorest.NewErrorWithError(err, "azure", "newPollingRequest", nil, "Failure creating poll request to %s", ps.uri)
return nil, autorest.NewErrorWithError(err, "azure", "newPollingRequest", nil, "Failure creating poll request to %s", ps.URI)
}
return reqPoll, nil

View File

@ -15,10 +15,17 @@ package azure
// limitations under the License.
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strings"
)
// EnvironmentFilepathName captures the name of the environment variable containing the path to the file
// to be used while populating the Azure Environment.
const EnvironmentFilepathName = "AZURE_ENVIRONMENT_FILEPATH"
var environments = map[string]Environment{
"AZURECHINACLOUD": ChinaCloud,
"AZUREGERMANCLOUD": GermanCloud,
@ -133,12 +140,37 @@ var (
}
)
// EnvironmentFromName returns an Environment based on the common name specified
// EnvironmentFromName returns an Environment based on the common name specified.
func EnvironmentFromName(name string) (Environment, error) {
// IMPORTANT
// As per @radhikagupta5:
// This is technical debt, fundamentally here because Kubernetes is not currently accepting
// contributions to the providers. Once that is an option, the provider should be updated to
// directly call `EnvironmentFromFile`. Until then, we rely on dispatching Azure Stack environment creation
// from this method based on the name that is provided to us.
if strings.EqualFold(name, "AZURESTACKCLOUD") {
return EnvironmentFromFile(os.Getenv(EnvironmentFilepathName))
}
name = strings.ToUpper(name)
env, ok := environments[name]
if !ok {
return env, fmt.Errorf("autorest/azure: There is no cloud environment matching the name %q", name)
}
return env, nil
}
// EnvironmentFromFile loads an Environment from a configuration file available on disk.
// This function is particularly useful in the Hybrid Cloud model, where one must define their own
// endpoints.
func EnvironmentFromFile(location string) (unmarshaled Environment, err error) {
fileContents, err := ioutil.ReadFile(location)
if err != nil {
return
}
err = json.Unmarshal(fileContents, &unmarshaled)
return
}

View File

@ -55,15 +55,16 @@ func DoRetryWithRegistration(client autorest.Client) autorest.SendDecorator {
if err != nil {
return resp, err
}
err = re
if re.ServiceError != nil && re.ServiceError.Code == "MissingSubscriptionRegistration" {
err = register(client, r, re)
if err != nil {
return resp, fmt.Errorf("failed auto registering Resource Provider: %s", err)
regErr := register(client, r, re)
if regErr != nil {
return resp, fmt.Errorf("failed auto registering Resource Provider: %s. Original error: %s", regErr, err)
}
}
}
return resp, errors.New("failed request and resource provider registration")
return resp, fmt.Errorf("failed request: %s", err)
})
}
}

View File

@ -221,7 +221,8 @@ func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) Se
return resp, err
}
resp, err = s.Do(rr.Request())
if err != nil || !ResponseHasStatusCode(resp, codes...) {
// we want to retry if err is not nil (e.g. transient network failure)
if err == nil && !ResponseHasStatusCode(resp, codes...) {
return resp, err
}
delayed := DelayWithRetryAfter(resp, r.Cancel)
@ -237,6 +238,9 @@ func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) Se
// DelayWithRetryAfter invokes time.After for the duration specified in the "Retry-After" header in
// responses with status code 429
func DelayWithRetryAfter(resp *http.Response, cancel <-chan struct{}) bool {
if resp == nil {
return false
}
retryAfter, _ := strconv.Atoi(resp.Header.Get("Retry-After"))
if resp.StatusCode == http.StatusTooManyRequests && retryAfter > 0 {
select {

View File

@ -20,6 +20,7 @@ import (
"encoding/xml"
"fmt"
"io"
"net/http"
"net/url"
"reflect"
"sort"
@ -190,3 +191,14 @@ func createQuery(v url.Values) string {
}
return buf.String()
}
// ChangeToGet turns the specified http.Request into a GET (it assumes it wasn't).
// This is mainly useful for long-running operations that use the Azure-AsyncOperation
// header, so we change the initial PUT into a GET to retrieve the final result.
func ChangeToGet(req *http.Request) *http.Request {
req.Method = "GET"
req.Body = nil
req.ContentLength = 0
req.Header.Del("Content-Length")
return req
}

View File

@ -156,6 +156,7 @@ func IsPort(str string) bool
func IsPositive(value float64) bool
func IsPrintableASCII(str string) bool
func IsRFC3339(str string) bool
func IsRFC3339WithoutZone(str string) bool
func IsRGBcolor(str string) bool
func IsRequestURI(rawurl string) bool
func IsRequestURL(rawurl string) bool
@ -269,56 +270,57 @@ For completely custom validators (interface-based), see below.
Here is a list of available validators for struct fields (validator - used function):
```go
"email": IsEmail,
"url": IsURL,
"dialstring": IsDialString,
"requrl": IsRequestURL,
"requri": IsRequestURI,
"alpha": IsAlpha,
"utfletter": IsUTFLetter,
"alphanum": IsAlphanumeric,
"utfletternum": IsUTFLetterNumeric,
"numeric": IsNumeric,
"utfnumeric": IsUTFNumeric,
"utfdigit": IsUTFDigit,
"hexadecimal": IsHexadecimal,
"hexcolor": IsHexcolor,
"rgbcolor": IsRGBcolor,
"lowercase": IsLowerCase,
"uppercase": IsUpperCase,
"int": IsInt,
"float": IsFloat,
"null": IsNull,
"uuid": IsUUID,
"uuidv3": IsUUIDv3,
"uuidv4": IsUUIDv4,
"uuidv5": IsUUIDv5,
"creditcard": IsCreditCard,
"isbn10": IsISBN10,
"isbn13": IsISBN13,
"json": IsJSON,
"multibyte": IsMultibyte,
"ascii": IsASCII,
"printableascii": IsPrintableASCII,
"fullwidth": IsFullWidth,
"halfwidth": IsHalfWidth,
"variablewidth": IsVariableWidth,
"base64": IsBase64,
"datauri": IsDataURI,
"ip": IsIP,
"port": IsPort,
"ipv4": IsIPv4,
"ipv6": IsIPv6,
"dns": IsDNSName,
"host": IsHost,
"mac": IsMAC,
"latitude": IsLatitude,
"longitude": IsLongitude,
"ssn": IsSSN,
"semver": IsSemver,
"rfc3339": IsRFC3339,
"ISO3166Alpha2": IsISO3166Alpha2,
"ISO3166Alpha3": IsISO3166Alpha3,
"email": IsEmail,
"url": IsURL,
"dialstring": IsDialString,
"requrl": IsRequestURL,
"requri": IsRequestURI,
"alpha": IsAlpha,
"utfletter": IsUTFLetter,
"alphanum": IsAlphanumeric,
"utfletternum": IsUTFLetterNumeric,
"numeric": IsNumeric,
"utfnumeric": IsUTFNumeric,
"utfdigit": IsUTFDigit,
"hexadecimal": IsHexadecimal,
"hexcolor": IsHexcolor,
"rgbcolor": IsRGBcolor,
"lowercase": IsLowerCase,
"uppercase": IsUpperCase,
"int": IsInt,
"float": IsFloat,
"null": IsNull,
"uuid": IsUUID,
"uuidv3": IsUUIDv3,
"uuidv4": IsUUIDv4,
"uuidv5": IsUUIDv5,
"creditcard": IsCreditCard,
"isbn10": IsISBN10,
"isbn13": IsISBN13,
"json": IsJSON,
"multibyte": IsMultibyte,
"ascii": IsASCII,
"printableascii": IsPrintableASCII,
"fullwidth": IsFullWidth,
"halfwidth": IsHalfWidth,
"variablewidth": IsVariableWidth,
"base64": IsBase64,
"datauri": IsDataURI,
"ip": IsIP,
"port": IsPort,
"ipv4": IsIPv4,
"ipv6": IsIPv6,
"dns": IsDNSName,
"host": IsHost,
"mac": IsMAC,
"latitude": IsLatitude,
"longitude": IsLongitude,
"ssn": IsSSN,
"semver": IsSemver,
"rfc3339": IsRFC3339,
"rfc3339WithoutZone": IsRFC3339WithoutZone,
"ISO3166Alpha2": IsISO3166Alpha2,
"ISO3166Alpha3": IsISO3166Alpha3,
```
Validators with parameters
@ -409,7 +411,7 @@ Documentation is available here: [godoc.org](https://godoc.org/github.com/asaske
Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator).
#### Support
If you do have a contribution for the package feel free to put up a Pull Request or open Issue.
If you do have a contribution for the package, feel free to create a Pull Request or an Issue.
#### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors)
* [Daniel Lohse](https://github.com/annismckenzie)

View File

@ -72,57 +72,58 @@ var CustomTypeTagMap = &customTypeTagMap{validators: make(map[string]CustomTypeV
// TagMap is a map of functions, that can be used as tags for ValidateStruct function.
var TagMap = map[string]Validator{
"email": IsEmail,
"url": IsURL,
"dialstring": IsDialString,
"requrl": IsRequestURL,
"requri": IsRequestURI,
"alpha": IsAlpha,
"utfletter": IsUTFLetter,
"alphanum": IsAlphanumeric,
"utfletternum": IsUTFLetterNumeric,
"numeric": IsNumeric,
"utfnumeric": IsUTFNumeric,
"utfdigit": IsUTFDigit,
"hexadecimal": IsHexadecimal,
"hexcolor": IsHexcolor,
"rgbcolor": IsRGBcolor,
"lowercase": IsLowerCase,
"uppercase": IsUpperCase,
"int": IsInt,
"float": IsFloat,
"null": IsNull,
"uuid": IsUUID,
"uuidv3": IsUUIDv3,
"uuidv4": IsUUIDv4,
"uuidv5": IsUUIDv5,
"creditcard": IsCreditCard,
"isbn10": IsISBN10,
"isbn13": IsISBN13,
"json": IsJSON,
"multibyte": IsMultibyte,
"ascii": IsASCII,
"printableascii": IsPrintableASCII,
"fullwidth": IsFullWidth,
"halfwidth": IsHalfWidth,
"variablewidth": IsVariableWidth,
"base64": IsBase64,
"datauri": IsDataURI,
"ip": IsIP,
"port": IsPort,
"ipv4": IsIPv4,
"ipv6": IsIPv6,
"dns": IsDNSName,
"host": IsHost,
"mac": IsMAC,
"latitude": IsLatitude,
"longitude": IsLongitude,
"ssn": IsSSN,
"semver": IsSemver,
"rfc3339": IsRFC3339,
"ISO3166Alpha2": IsISO3166Alpha2,
"ISO3166Alpha3": IsISO3166Alpha3,
"ISO4217": IsISO4217,
"email": IsEmail,
"url": IsURL,
"dialstring": IsDialString,
"requrl": IsRequestURL,
"requri": IsRequestURI,
"alpha": IsAlpha,
"utfletter": IsUTFLetter,
"alphanum": IsAlphanumeric,
"utfletternum": IsUTFLetterNumeric,
"numeric": IsNumeric,
"utfnumeric": IsUTFNumeric,
"utfdigit": IsUTFDigit,
"hexadecimal": IsHexadecimal,
"hexcolor": IsHexcolor,
"rgbcolor": IsRGBcolor,
"lowercase": IsLowerCase,
"uppercase": IsUpperCase,
"int": IsInt,
"float": IsFloat,
"null": IsNull,
"uuid": IsUUID,
"uuidv3": IsUUIDv3,
"uuidv4": IsUUIDv4,
"uuidv5": IsUUIDv5,
"creditcard": IsCreditCard,
"isbn10": IsISBN10,
"isbn13": IsISBN13,
"json": IsJSON,
"multibyte": IsMultibyte,
"ascii": IsASCII,
"printableascii": IsPrintableASCII,
"fullwidth": IsFullWidth,
"halfwidth": IsHalfWidth,
"variablewidth": IsVariableWidth,
"base64": IsBase64,
"datauri": IsDataURI,
"ip": IsIP,
"port": IsPort,
"ipv4": IsIPv4,
"ipv6": IsIPv6,
"dns": IsDNSName,
"host": IsHost,
"mac": IsMAC,
"latitude": IsLatitude,
"longitude": IsLongitude,
"ssn": IsSSN,
"semver": IsSemver,
"rfc3339": IsRFC3339,
"rfc3339WithoutZone": IsRFC3339WithoutZone,
"ISO3166Alpha2": IsISO3166Alpha2,
"ISO3166Alpha3": IsISO3166Alpha3,
"ISO4217": IsISO4217,
}
// ISO3166Entry stores country codes

View File

@ -108,7 +108,7 @@ func CamelCaseToUnderscore(str string) string {
var output []rune
var segment []rune
for _, r := range str {
if !unicode.IsLower(r) {
if !unicode.IsLower(r) && string(r) != "_" {
output = addSegment(output, segment)
segment = nil
}

View File

@ -25,6 +25,7 @@ var (
const maxURLRuneCount = 2083
const minURLRuneCount = 3
const RF3339WithoutZone = "2006-01-02T15:04:05"
// SetFieldsRequiredByDefault causes validation to fail when struct fields
// do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`).
@ -569,7 +570,16 @@ func toJSONName(tag string) string {
// JSON name always comes first. If there's no options then split[0] is
// JSON name, if JSON name is not set, then split[0] is an empty string.
split := strings.SplitN(tag, ",", 2)
return split[0]
name := split[0]
// However it is possible that the field is skipped when
// (de-)serializing from/to JSON, in which case assume that there is no
// tag name to use
if name == "-" {
return ""
}
return name
}
// ValidateStruct use tags for fields.
@ -614,6 +624,14 @@ func ValidateStruct(s interface{}) (bool, error) {
jsonError.Name = jsonTag
err2 = jsonError
case Errors:
for i2, err3 := range jsonError {
switch customErr := err3.(type) {
case Error:
customErr.Name = jsonTag
jsonError[i2] = customErr
}
}
err2 = jsonError
}
}
@ -692,6 +710,11 @@ func IsRFC3339(str string) bool {
return IsTime(str, time.RFC3339)
}
// IsRFC3339WithoutZone check if string is valid timestamp value according to RFC3339 which excludes the timezone.
func IsRFC3339WithoutZone(str string) bool {
return IsTime(str, RF3339WithoutZone)
}
// IsISO4217 check if string is valid ISO currency code
func IsISO4217(str string) bool {
for _, currency := range ISO4217List {

View File

@ -2,6 +2,7 @@ package client
import (
"math/rand"
"strconv"
"sync"
"time"
@ -38,6 +39,10 @@ func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
minTime := 30
throttle := d.shouldThrottle(r)
if throttle {
if delay, ok := getRetryDelay(r); ok {
return delay
}
minTime = 500
}
@ -68,12 +73,49 @@ func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
// ShouldThrottle returns true if the request should be throttled.
func (d DefaultRetryer) shouldThrottle(r *request.Request) bool {
if r.HTTPResponse.StatusCode == 502 ||
r.HTTPResponse.StatusCode == 503 ||
r.HTTPResponse.StatusCode == 504 {
return true
switch r.HTTPResponse.StatusCode {
case 429:
case 502:
case 503:
case 504:
default:
return r.IsErrorThrottle()
}
return r.IsErrorThrottle()
return true
}
// This will look in the Retry-After header, RFC 7231, for how long
// it will wait before attempting another request
func getRetryDelay(r *request.Request) (time.Duration, bool) {
if !canUseRetryAfterHeader(r) {
return 0, false
}
delayStr := r.HTTPResponse.Header.Get("Retry-After")
if len(delayStr) == 0 {
return 0, false
}
delay, err := strconv.Atoi(delayStr)
if err != nil {
return 0, false
}
return time.Duration(delay) * time.Second, true
}
// Will look at the status code to see if the retry header pertains to
// the status code.
func canUseRetryAfterHeader(r *request.Request) bool {
switch r.HTTPResponse.StatusCode {
case 429:
case 503:
default:
return false
}
return true
}
// lockedSource is a thread-safe implementation of rand.Source

View File

@ -44,6 +44,7 @@ const (
// Service identifiers
const (
AcmServiceID = "acm" // Acm.
ApiPricingServiceID = "api.pricing" // ApiPricing.
ApigatewayServiceID = "apigateway" // Apigateway.
ApplicationAutoscalingServiceID = "application-autoscaling" // ApplicationAutoscaling.
Appstream2ServiceID = "appstream2" // Appstream2.
@ -256,6 +257,16 @@ var awsPartition = partition{
"us-west-2": endpoint{},
},
},
"api.pricing": service{
Defaults: endpoint{
CredentialScope: credentialScope{
Service: "pricing",
},
},
Endpoints: endpoints{
"us-east-1": endpoint{},
},
},
"apigateway": service{
Endpoints: endpoints{
@ -1933,6 +1944,12 @@ var awscnPartition = partition{
"cn-north-1": endpoint{},
},
},
"cognito-identity": service{
Endpoints: endpoints{
"cn-north-1": endpoint{},
},
},
"config": service{
Endpoints: endpoints{

View File

@ -28,6 +28,10 @@ const (
// during body reads.
ErrCodeResponseTimeout = "ResponseTimeout"
// ErrCodeInvalidPresignExpire is returned when the expire time provided to
// presign is invalid
ErrCodeInvalidPresignExpire = "InvalidPresignExpireError"
// CanceledErrorCode is the error code that will be returned by an
// API request that was canceled. Requests given a aws.Context may
// return this error when canceled.
@ -42,7 +46,6 @@ type Request struct {
Retryer
Time time.Time
ExpireTime time.Duration
Operation *Operation
HTTPRequest *http.Request
HTTPResponse *http.Response
@ -60,6 +63,11 @@ type Request struct {
LastSignedAt time.Time
DisableFollowRedirects bool
// A value greater than 0 instructs the request to be signed as Presigned URL
// You should not set this field directly. Instead use Request's
// Presign or PresignRequest methods.
ExpireTime time.Duration
context aws.Context
built bool
@ -250,40 +258,59 @@ func (r *Request) SetReaderBody(reader io.ReadSeeker) {
// Presign returns the request's signed URL. Error will be returned
// if the signing fails.
func (r *Request) Presign(expireTime time.Duration) (string, error) {
r.ExpireTime = expireTime
//
// It is invalid to create a presigned URL with a expire duration 0 or less. An
// error is returned if expire duration is 0 or less.
func (r *Request) Presign(expire time.Duration) (string, error) {
r = r.copy()
// Presign requires all headers be hoisted. There is no way to retrieve
// the signed headers not hoisted without this. Making the presigned URL
// useless.
r.NotHoist = false
if r.Operation.BeforePresignFn != nil {
r = r.copy()
err := r.Operation.BeforePresignFn(r)
if err != nil {
return "", err
}
}
r.Sign()
if r.Error != nil {
return "", r.Error
}
return r.HTTPRequest.URL.String(), nil
u, _, err := getPresignedURL(r, expire)
return u, err
}
// PresignRequest behaves just like presign, with the addition of returning a
// set of headers that were signed.
//
// It is invalid to create a presigned URL with a expire duration 0 or less. An
// error is returned if expire duration is 0 or less.
//
// Returns the URL string for the API operation with signature in the query string,
// and the HTTP headers that were included in the signature. These headers must
// be included in any HTTP request made with the presigned URL.
//
// To prevent hoisting any headers to the query string set NotHoist to true on
// this Request value prior to calling PresignRequest.
func (r *Request) PresignRequest(expireTime time.Duration) (string, http.Header, error) {
r.ExpireTime = expireTime
r.Sign()
if r.Error != nil {
return "", nil, r.Error
func (r *Request) PresignRequest(expire time.Duration) (string, http.Header, error) {
r = r.copy()
return getPresignedURL(r, expire)
}
func getPresignedURL(r *Request, expire time.Duration) (string, http.Header, error) {
if expire <= 0 {
return "", nil, awserr.New(
ErrCodeInvalidPresignExpire,
"presigned URL requires an expire duration greater than 0",
nil,
)
}
r.ExpireTime = expire
if r.Operation.BeforePresignFn != nil {
if err := r.Operation.BeforePresignFn(r); err != nil {
return "", nil, err
}
}
if err := r.Sign(); err != nil {
return "", nil, err
}
return r.HTTPRequest.URL.String(), r.SignedHeaderVals, nil
}

View File

@ -268,7 +268,7 @@ type signingCtx struct {
// "X-Amz-Content-Sha256" header with a precomputed value. The signer will
// only compute the hash if the request header value is empty.
func (v4 Signer) Sign(r *http.Request, body io.ReadSeeker, service, region string, signTime time.Time) (http.Header, error) {
return v4.signWithBody(r, body, service, region, 0, signTime)
return v4.signWithBody(r, body, service, region, 0, false, signTime)
}
// Presign signs AWS v4 requests with the provided body, service name, region
@ -302,10 +302,10 @@ func (v4 Signer) Sign(r *http.Request, body io.ReadSeeker, service, region strin
// presigned request's signature you can set the "X-Amz-Content-Sha256"
// HTTP header and that will be included in the request's signature.
func (v4 Signer) Presign(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, signTime time.Time) (http.Header, error) {
return v4.signWithBody(r, body, service, region, exp, signTime)
return v4.signWithBody(r, body, service, region, exp, true, signTime)
}
func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, signTime time.Time) (http.Header, error) {
func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, isPresign bool, signTime time.Time) (http.Header, error) {
currentTimeFn := v4.currentTimeFn
if currentTimeFn == nil {
currentTimeFn = time.Now
@ -317,7 +317,7 @@ func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, regi
Query: r.URL.Query(),
Time: signTime,
ExpireTime: exp,
isPresign: exp != 0,
isPresign: isPresign,
ServiceName: service,
Region: region,
DisableURIPathEscaping: v4.DisableURIPathEscaping,
@ -467,7 +467,7 @@ func signSDKRequestWithCurrTime(req *request.Request, curTimeFn func() time.Time
}
signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.GetBody(),
name, region, req.ExpireTime, signingTime,
name, region, req.ExpireTime, req.ExpireTime > 0, signingTime,
)
if err != nil {
req.Error = err

View File

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK
const SDKVersion = "1.12.19"
const SDKVersion = "1.12.23"

View File

@ -29,7 +29,7 @@
//
// Using the Client
//
// To Amazon DynamoDB with the SDK use the New function to create
// To contact Amazon DynamoDB with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//

View File

@ -60892,6 +60892,24 @@ const (
// InstanceTypeC48xlarge is a InstanceType enum value
InstanceTypeC48xlarge = "c4.8xlarge"
// InstanceTypeC5Large is a InstanceType enum value
InstanceTypeC5Large = "c5.large"
// InstanceTypeC5Xlarge is a InstanceType enum value
InstanceTypeC5Xlarge = "c5.xlarge"
// InstanceTypeC52xlarge is a InstanceType enum value
InstanceTypeC52xlarge = "c5.2xlarge"
// InstanceTypeC54xlarge is a InstanceType enum value
InstanceTypeC54xlarge = "c5.4xlarge"
// InstanceTypeC59xlarge is a InstanceType enum value
InstanceTypeC59xlarge = "c5.9xlarge"
// InstanceTypeC518xlarge is a InstanceType enum value
InstanceTypeC518xlarge = "c5.18xlarge"
// InstanceTypeCc14xlarge is a InstanceType enum value
InstanceTypeCc14xlarge = "cc1.4xlarge"

View File

@ -15,7 +15,7 @@
//
// Using the Client
//
// To Amazon Elastic Compute Cloud with the SDK use the New function to create
// To contact Amazon Elastic Compute Cloud with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//

View File

@ -64,7 +64,7 @@
//
// Using the Client
//
// To AWS Identity and Access Management with the SDK use the New function to create
// To contact AWS Identity and Access Management with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//

View File

@ -10,7 +10,7 @@
//
// Using the Client
//
// To Amazon Simple Storage Service with the SDK use the New function to create
// To contact Amazon Simple Storage Service with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//

View File

@ -56,7 +56,7 @@
//
// Using the Client
//
// To AWS Security Token Service with the SDK use the New function to create
// To contact AWS Security Token Service with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//

View File

@ -22,12 +22,13 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// ErrNoAddrAvilable is returned by Get() when the balancer does not have
// any active connection to endpoints at the time.
// This error is returned only when opts.BlockingWait is true.
var ErrNoAddrAvilable = grpc.Errorf(codes.Unavailable, "there is no address available")
var ErrNoAddrAvilable = status.Error(codes.Unavailable, "there is no address available")
type notifyMsg int

View File

@ -27,6 +27,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
)
const (
@ -91,7 +92,7 @@ func (wr *WatchResponse) Err() error {
return v3rpc.ErrCompacted
case wr.Canceled:
if len(wr.cancelReason) != 0 {
return v3rpc.Error(grpc.Errorf(codes.FailedPrecondition, "%s", wr.cancelReason))
return v3rpc.Error(status.Error(codes.FailedPrecondition, wr.cancelReason))
}
return v3rpc.ErrFutureRev
}

View File

@ -74,6 +74,7 @@ type ContainerLogsOptions struct {
ShowStdout bool
ShowStderr bool
Since string
Until string
Timestamps bool
Follow bool
Tail string

View File

@ -7,10 +7,22 @@ package container
// See hack/generate-swagger-api.sh
// ----------------------------------------------------------------------------
// ContainerWaitOKBodyError container waiting error, if any
// swagger:model ContainerWaitOKBodyError
type ContainerWaitOKBodyError struct {
// Details of an error
Message string `json:"Message,omitempty"`
}
// ContainerWaitOKBody container wait o k body
// swagger:model ContainerWaitOKBody
type ContainerWaitOKBody struct {
// error
// Required: true
Error *ContainerWaitOKBodyError `json:"Error"`
// Exit code of the container
// Required: true
StatusCode int64 `json:"StatusCode"`

View File

@ -20,6 +20,27 @@ func (i Isolation) IsDefault() bool {
return strings.ToLower(string(i)) == "default" || string(i) == ""
}
// IsHyperV indicates the use of a Hyper-V partition for isolation
func (i Isolation) IsHyperV() bool {
return strings.ToLower(string(i)) == "hyperv"
}
// IsProcess indicates the use of process isolation
func (i Isolation) IsProcess() bool {
return strings.ToLower(string(i)) == "process"
}
const (
// IsolationEmpty is unspecified (same behavior as default)
IsolationEmpty = Isolation("")
// IsolationDefault is the default isolation mode on current daemon
IsolationDefault = Isolation("default")
// IsolationProcess is process isolation mode
IsolationProcess = Isolation("process")
// IsolationHyperV is HyperV isolation mode
IsolationHyperV = Isolation("hyperv")
)
// IpcMode represents the container ipc stack.
type IpcMode string

View File

@ -1,9 +1,5 @@
package container
import (
"strings"
)
// IsBridge indicates whether container uses the bridge network stack
// in windows it is given the name NAT
func (n NetworkMode) IsBridge() bool {
@ -21,16 +17,6 @@ func (n NetworkMode) IsUserDefined() bool {
return !n.IsDefault() && !n.IsNone() && !n.IsBridge() && !n.IsContainer()
}
// IsHyperV indicates the use of a Hyper-V partition for isolation
func (i Isolation) IsHyperV() bool {
return strings.ToLower(string(i)) == "hyperv"
}
// IsProcess indicates the use of process isolation
func (i Isolation) IsProcess() bool {
return strings.ToLower(string(i)) == "process"
}
// IsValid indicates if an isolation technology is valid
func (i Isolation) IsValid() bool {
return i.IsDefault() || i.IsHyperV() || i.IsProcess()

View File

@ -65,8 +65,9 @@ type ContainerSpec struct {
// The format of extra hosts on swarmkit is specified in:
// http://man7.org/linux/man-pages/man5/hosts.5.html
// IP_address canonical_hostname [aliases...]
Hosts []string `json:",omitempty"`
DNSConfig *DNSConfig `json:",omitempty"`
Secrets []*SecretReference `json:",omitempty"`
Configs []*ConfigReference `json:",omitempty"`
Hosts []string `json:",omitempty"`
DNSConfig *DNSConfig `json:",omitempty"`
Secrets []*SecretReference `json:",omitempty"`
Configs []*ConfigReference `json:",omitempty"`
Isolation container.Isolation `json:",omitempty"`
}

View File

@ -263,6 +263,16 @@ func ValidateLabel(val string) (string, error) {
return val, nil
}
// ValidateSingleGenericResource validates that a single entry in the
// generic resource list is valid.
// i.e 'GPU=UID1' is valid however 'GPU:UID1' or 'UID1' isn't
func ValidateSingleGenericResource(val string) (string, error) {
if strings.Count(val, "=") < 1 {
return "", fmt.Errorf("invalid node-generic-resource format `%s` expected `name=value`", val)
}
return val, nil
}
// ParseLink parses and validates the specified string as a link format (name:alias)
func ParseLink(val string) (string, string, error) {
if val == "" {

View File

@ -1,4 +1,4 @@
// +build !linux,!freebsd freebsd,!cgo solaris,!cgo
// +build !linux,!freebsd freebsd,!cgo
package mount

View File

@ -13,7 +13,7 @@ func GetMounts() ([]*Info, error) {
}
// Mounted determines if a specified mountpoint has been mounted.
// On Linux it looks at /proc/self/mountinfo and on Solaris at mnttab.
// On Linux it looks at /proc/self/mountinfo.
func Mounted(mountpoint string) (bool, error) {
entries, err := parseMountTable()
if err != nil {

View File

@ -1,4 +1,4 @@
// +build !linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo
// +build !linux,!freebsd freebsd,!cgo
package mount

View File

@ -1,4 +1,4 @@
// +build !windows,!linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo
// +build !windows,!linux,!freebsd freebsd,!cgo
package mount

View File

@ -1,4 +1,4 @@
// +build !linux,!windows,!solaris
// +build !linux,!windows
package system

View File

@ -1,4 +1,4 @@
// +build linux freebsd solaris darwin
// +build linux freebsd darwin
package system

View File

@ -1,5 +1,4 @@
// +build !windows
// +build !solaris !cgo
package term

View File

@ -1,4 +1,4 @@
// +build !solaris,!windows
// +build !windows
package term

View File

@ -2,6 +2,7 @@
Abhishek Chanda
Adam Bell-Hanssen
Adnan Khan
Adrien Kohlbecker
Aldrin Leal
Alex Dadgar
@ -114,6 +115,7 @@ Lucas Clemente
Lucas Weiblen
Lyon Hill
Mantas Matelis
Manuel Vogel
Marguerite des Trois Maisons
Mariusz Borsa
Martin Sweeney

View File

@ -5,8 +5,8 @@ clone_folder: c:\gopath\src\github.com\fsouza\go-dockerclient
environment:
GOPATH: c:\gopath
matrix:
- GOVERSION: 1.8.4
- GOVERSION: 1.9.1
- GOVERSION: 1.8.5
- GOVERSION: 1.9.2
install:
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
- rmdir c:\go /s /q

View File

@ -426,8 +426,9 @@ type HealthConfig struct {
Test []string `json:"Test,omitempty" yaml:"Test,omitempty" toml:"Test,omitempty"`
// Zero means to inherit. Durations are expressed as integer nanoseconds.
Interval time.Duration `json:"Interval,omitempty" yaml:"Interval,omitempty" toml:"Interval,omitempty"` // Interval is the time to wait between checks.
Timeout time.Duration `json:"Timeout,omitempty" yaml:"Timeout,omitempty" toml:"Timeout,omitempty"` // Timeout is the time to wait before considering the check to have hung.
Interval time.Duration `json:"Interval,omitempty" yaml:"Interval,omitempty" toml:"Interval,omitempty"` // Interval is the time to wait between checks.
Timeout time.Duration `json:"Timeout,omitempty" yaml:"Timeout,omitempty" toml:"Timeout,omitempty"` // Timeout is the time to wait before considering the check to have hung.
StartPeriod time.Duration `json:"StartPeriod,omitempty" yaml:"StartPeriod,omitempty" toml:"StartPeriod,omitempty"` // The start period for the container to initialize before the retries starts to count down.
// Retries is the number of consecutive failures needed to consider a container as unhealthy.
// Zero means inherit.
@ -742,6 +743,7 @@ type HostConfig struct {
UTSMode string `json:"UTSMode,omitempty" yaml:"UTSMode,omitempty" toml:"UTSMode,omitempty"`
RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty" yaml:"RestartPolicy,omitempty" toml:"RestartPolicy,omitempty"`
Devices []Device `json:"Devices,omitempty" yaml:"Devices,omitempty" toml:"Devices,omitempty"`
DeviceCgroupRules []string `json:"DeviceCgroupRules,omitempty" yaml:"DeviceCgroupRules,omitempty" toml:"DeviceCgroupRules,omitempty"`
LogConfig LogConfig `json:"LogConfig,omitempty" yaml:"LogConfig,omitempty" toml:"LogConfig,omitempty"`
SecurityOpt []string `json:"SecurityOpt,omitempty" yaml:"SecurityOpt,omitempty" toml:"SecurityOpt,omitempty"`
Cgroup string `json:"Cgroup,omitempty" yaml:"Cgroup,omitempty" toml:"Cgroup,omitempty"`

View File

@ -473,6 +473,7 @@ type BuildImageOptions struct {
NetworkMode string `qs:"networkmode"`
InactivityTimeout time.Duration `qs:"-"`
CgroupParent string `qs:"cgroupparent"`
SecurityOpt []string `qs:"securityopt"`
Context context.Context
}

View File

@ -0,0 +1,171 @@
// Copyright 2017 go-dockerclient 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 docker
import (
"encoding/json"
"net/http"
"net/url"
"strconv"
"github.com/docker/docker/api/types/swarm"
"golang.org/x/net/context"
)
// NoSuchConfig is the error returned when a given config does not exist.
type NoSuchConfig struct {
ID string
Err error
}
func (err *NoSuchConfig) Error() string {
if err.Err != nil {
return err.Err.Error()
}
return "No such config: " + err.ID
}
// CreateConfigOptions specify parameters to the CreateConfig function.
//
// See https://goo.gl/KrVjHz for more details.
type CreateConfigOptions struct {
Auth AuthConfiguration `qs:"-"`
swarm.ConfigSpec
Context context.Context
}
// CreateConfig creates a new config, returning the config instance
// or an error in case of failure.
//
// See https://goo.gl/KrVjHz for more details.
func (c *Client) CreateConfig(opts CreateConfigOptions) (*swarm.Config, error) {
headers, err := headersWithAuth(opts.Auth)
if err != nil {
return nil, err
}
path := "/configs/create?" + queryString(opts)
resp, err := c.do("POST", path, doOptions{
headers: headers,
data: opts.ConfigSpec,
forceJSON: true,
context: opts.Context,
})
if err != nil {
return nil, err
}
defer resp.Body.Close()
var config swarm.Config
if err := json.NewDecoder(resp.Body).Decode(&config); err != nil {
return nil, err
}
return &config, nil
}
// RemoveConfigOptions encapsulates options to remove a config.
//
// See https://goo.gl/Tqrtya for more details.
type RemoveConfigOptions struct {
ID string `qs:"-"`
Context context.Context
}
// RemoveConfig removes a config, returning an error in case of failure.
//
// See https://goo.gl/Tqrtya for more details.
func (c *Client) RemoveConfig(opts RemoveConfigOptions) error {
path := "/configs/" + opts.ID
resp, err := c.do("DELETE", path, doOptions{context: opts.Context})
if err != nil {
if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
return &NoSuchConfig{ID: opts.ID}
}
return err
}
resp.Body.Close()
return nil
}
// UpdateConfigOptions specify parameters to the UpdateConfig function.
//
// See https://goo.gl/wu3MmS for more details.
type UpdateConfigOptions struct {
Auth AuthConfiguration `qs:"-"`
swarm.ConfigSpec
Context context.Context
Version uint64
}
// UpdateConfig updates the config at ID with the options
//
// Only label can be updated
// https://docs.docker.com/engine/api/v1.33/#operation/ConfigUpdate
// See https://goo.gl/wu3MmS for more details.
func (c *Client) UpdateConfig(id string, opts UpdateConfigOptions) error {
headers, err := headersWithAuth(opts.Auth)
if err != nil {
return err
}
params := make(url.Values)
params.Set("version", strconv.FormatUint(opts.Version, 10))
resp, err := c.do("POST", "/configs/"+id+"/update?"+params.Encode(), doOptions{
headers: headers,
data: opts.ConfigSpec,
forceJSON: true,
context: opts.Context,
})
if err != nil {
if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
return &NoSuchConfig{ID: id}
}
return err
}
defer resp.Body.Close()
return nil
}
// InspectConfig returns information about a config by its ID.
//
// See https://goo.gl/dHmr75 for more details.
func (c *Client) InspectConfig(id string) (*swarm.Config, error) {
path := "/configs/" + id
resp, err := c.do("GET", path, doOptions{})
if err != nil {
if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
return nil, &NoSuchConfig{ID: id}
}
return nil, err
}
defer resp.Body.Close()
var config swarm.Config
if err := json.NewDecoder(resp.Body).Decode(&config); err != nil {
return nil, err
}
return &config, nil
}
// ListConfigsOptions specify parameters to the ListConfigs function.
//
// See https://goo.gl/DwvNMd for more details.
type ListConfigsOptions struct {
Filters map[string][]string
Context context.Context
}
// ListConfigs returns a slice of configs matching the given criteria.
//
// See https://goo.gl/DwvNMd for more details.
func (c *Client) ListConfigs(opts ListConfigsOptions) ([]swarm.Config, error) {
path := "/configs?" + queryString(opts)
resp, err := c.do("GET", path, doOptions{context: opts.Context})
if err != nil {
return nil, err
}
defer resp.Body.Close()
var configs []swarm.Config
if err := json.NewDecoder(resp.Body).Decode(&configs); err != nil {
return nil, err
}
return configs, nil
}

View File

@ -0,0 +1,171 @@
// Copyright 2016 go-dockerclient 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 docker
import (
"encoding/json"
"net/http"
"net/url"
"strconv"
"github.com/docker/docker/api/types/swarm"
"golang.org/x/net/context"
)
// NoSuchSecret is the error returned when a given secret does not exist.
type NoSuchSecret struct {
ID string
Err error
}
func (err *NoSuchSecret) Error() string {
if err.Err != nil {
return err.Err.Error()
}
return "No such secret: " + err.ID
}
// CreateSecretOptions specify parameters to the CreateSecret function.
//
// See https://goo.gl/KrVjHz for more details.
type CreateSecretOptions struct {
Auth AuthConfiguration `qs:"-"`
swarm.SecretSpec
Context context.Context
}
// CreateSecret creates a new secret, returning the secret instance
// or an error in case of failure.
//
// See https://goo.gl/KrVjHz for more details.
func (c *Client) CreateSecret(opts CreateSecretOptions) (*swarm.Secret, error) {
headers, err := headersWithAuth(opts.Auth)
if err != nil {
return nil, err
}
path := "/secrets/create?" + queryString(opts)
resp, err := c.do("POST", path, doOptions{
headers: headers,
data: opts.SecretSpec,
forceJSON: true,
context: opts.Context,
})
if err != nil {
return nil, err
}
defer resp.Body.Close()
var secret swarm.Secret
if err := json.NewDecoder(resp.Body).Decode(&secret); err != nil {
return nil, err
}
return &secret, nil
}
// RemoveSecretOptions encapsulates options to remove a secret.
//
// See https://goo.gl/Tqrtya for more details.
type RemoveSecretOptions struct {
ID string `qs:"-"`
Context context.Context
}
// RemoveSecret removes a secret, returning an error in case of failure.
//
// See https://goo.gl/Tqrtya for more details.
func (c *Client) RemoveSecret(opts RemoveSecretOptions) error {
path := "/secrets/" + opts.ID
resp, err := c.do("DELETE", path, doOptions{context: opts.Context})
if err != nil {
if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
return &NoSuchSecret{ID: opts.ID}
}
return err
}
resp.Body.Close()
return nil
}
// UpdateSecretOptions specify parameters to the UpdateSecret function.
//
// Only label can be updated
// See https://docs.docker.com/engine/api/v1.33/#operation/SecretUpdate
// See https://goo.gl/wu3MmS for more details.
type UpdateSecretOptions struct {
Auth AuthConfiguration `qs:"-"`
swarm.SecretSpec
Context context.Context
Version uint64
}
// UpdateSecret updates the secret at ID with the options
//
// See https://goo.gl/wu3MmS for more details.
func (c *Client) UpdateSecret(id string, opts UpdateSecretOptions) error {
headers, err := headersWithAuth(opts.Auth)
if err != nil {
return err
}
params := make(url.Values)
params.Set("version", strconv.FormatUint(opts.Version, 10))
resp, err := c.do("POST", "/secrets/"+id+"/update?"+params.Encode(), doOptions{
headers: headers,
data: opts.SecretSpec,
forceJSON: true,
context: opts.Context,
})
if err != nil {
if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
return &NoSuchSecret{ID: id}
}
return err
}
defer resp.Body.Close()
return nil
}
// InspectSecret returns information about a secret by its ID.
//
// See https://goo.gl/dHmr75 for more details.
func (c *Client) InspectSecret(id string) (*swarm.Secret, error) {
path := "/secrets/" + id
resp, err := c.do("GET", path, doOptions{})
if err != nil {
if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
return nil, &NoSuchSecret{ID: id}
}
return nil, err
}
defer resp.Body.Close()
var secret swarm.Secret
if err := json.NewDecoder(resp.Body).Decode(&secret); err != nil {
return nil, err
}
return &secret, nil
}
// ListSecretsOptions specify parameters to the ListSecrets function.
//
// See https://goo.gl/DwvNMd for more details.
type ListSecretsOptions struct {
Filters map[string][]string
Context context.Context
}
// ListSecrets returns a slice of secrets matching the given criteria.
//
// See https://goo.gl/DwvNMd for more details.
func (c *Client) ListSecrets(opts ListSecretsOptions) ([]swarm.Secret, error) {
path := "/secrets?" + queryString(opts)
resp, err := c.do("GET", path, doOptions{context: opts.Context})
if err != nil {
return nil, err
}
defer resp.Body.Close()
var secrets []swarm.Secret
if err := json.NewDecoder(resp.Body).Decode(&secrets); err != nil {
return nil, err
}
return secrets, nil
}

View File

@ -118,15 +118,17 @@ func Wrap(e interface{}, skip int) *Error {
// 1 from its caller, etc.
func WrapPrefix(e interface{}, prefix string, skip int) *Error {
err := Wrap(e, skip)
err := Wrap(e, 1+skip)
if err.prefix != "" {
err.prefix = fmt.Sprintf("%s: %s", prefix, err.prefix)
} else {
err.prefix = prefix
prefix = fmt.Sprintf("%s: %s", prefix, err.prefix)
}
return err
return &Error{
Err: err.Err,
stack: err.stack,
prefix: prefix,
}
}

View File

@ -28,6 +28,7 @@ type SimpleSchema struct {
Items *Items `json:"items,omitempty"`
CollectionFormat string `json:"collectionFormat,omitempty"`
Default interface{} `json:"default,omitempty"`
Example interface{} `json:"example,omitempty"`
}
func (s *SimpleSchema) TypeName() string {

View File

@ -381,7 +381,7 @@ func (c *controlConn) HandleError(conn *Conn, err error, closed bool) {
return
}
c.reconnect(true)
c.reconnect(false)
}
func (c *controlConn) getConn() *connHost {

View File

@ -876,7 +876,7 @@ func (f *framer) parsePreparedMetadata() preparedMetadata {
}
if meta.flags&flagHasMorePages == flagHasMorePages {
meta.pagingState = f.readBytes()
meta.pagingState = copyBytes(f.readBytes())
}
if meta.flags&flagNoMetaData == flagNoMetaData {
@ -961,7 +961,7 @@ func (f *framer) parseResultMetadata() resultMetadata {
meta.actualColCount = meta.colCount
if meta.flags&flagHasMorePages == flagHasMorePages {
meta.pagingState = f.readBytes()
meta.pagingState = copyBytes(f.readBytes())
}
if meta.flags&flagNoMetaData == flagNoMetaData {

View File

@ -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
}

View File

@ -5,7 +5,11 @@
package github
import "context"
import (
"context"
"fmt"
"time"
)
// AppsService provides access to the installation related functions
// in the GitHub API.
@ -13,6 +17,57 @@ import "context"
// GitHub API docs: https://developer.github.com/v3/apps/
type AppsService service
// App represents a GitHub App.
type App struct {
ID *int `json:"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"`
}
// 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
@ -38,3 +93,77 @@ func (s *AppsService) ListInstallations(ctx context.Context, opt *ListOptions) (
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 int) (*Installation, *Response, error) {
u := fmt.Sprintf("app/installations/%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", mediaTypeIntegrationPreview)
i := new(Installation)
resp, err := s.client.Do(ctx, req, i)
if err != nil {
return nil, resp, err
}
return i, resp, nil
}
// 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 int) (*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
}

View File

@ -51,6 +51,33 @@ func (s *AppsService) ListRepos(ctx context.Context, opt *ListOptions) ([]*Repos
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 int, 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
}
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

View File

@ -36,6 +36,62 @@ func (a *APIMeta) GetVerifiablePasswordAuthentication() bool {
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() int {
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
}
// 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
}
// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
func (a *Authorization) GetCreatedAt() Timestamp {
if a == nil || a.CreatedAt == nil {
@ -388,6 +444,38 @@ func (c *CombinedStatus) GetTotalCount() int {
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
}
// GetCommentCount returns the CommentCount field if it's non-nil, zero value otherwise.
func (c *Commit) GetCommentCount() int {
if c == nil || c.CommentCount == nil {
@ -1588,6 +1676,30 @@ func (g *GistFork) GetURL() string {
return *g.URL
}
// 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 {
@ -1804,6 +1916,30 @@ func (h *Hook) GetURL() string {
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 {
@ -2036,6 +2172,22 @@ func (i *InstallationRepositoriesEvent) GetRepositorySelection() string {
return *i.RepositorySelection
}
// 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 {
@ -2388,6 +2540,30 @@ func (i *IssuesSearchResult) GetTotal() int {
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() int {
if k == nil || k.ID == nil {
@ -2900,6 +3076,30 @@ func (m *MilestoneEvent) GetAction() string {
return *m.Action
}
// 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 {
@ -2948,6 +3148,46 @@ func (n *NewPullRequest) GetTitle() string {
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() int {
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 {
@ -3284,6 +3524,38 @@ func (o *OrgBlockEvent) GetAction() string {
return *o.Action
}
// 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 {
@ -3436,6 +3708,14 @@ func (p *PagesError) GetMessage() string {
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
}
// GetHookID returns the HookID field if it's non-nil, zero value otherwise.
func (p *PingEvent) GetHookID() int {
if p == nil || p.HookID == nil {
@ -4260,6 +4540,38 @@ func (p *pullRequestUpdate) GetTitle() string {
return *p.Title
}
// 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 {
@ -6044,6 +6356,54 @@ func (r *RepositoryTag) GetZipballURL() string {
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 {
@ -7340,6 +7700,30 @@ func (u *UsersSearchResult) GetTotal() int {
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 {

View File

@ -27,7 +27,7 @@ import (
)
const (
libraryVersion = "13"
libraryVersion = "14"
defaultBaseURL = "https://api.github.com/"
uploadBaseURL = "https://uploads.github.com/"
userAgent = "go-github/" + libraryVersion
@ -102,6 +102,9 @@ const (
// https://developer.github.com/changes/2017-07-26-team-review-request-thor-preview/
mediaTypeTeamReviewPreview = "application/vnd.github.thor-preview+json"
// https://developer.github.com/changes/2017-08-30-preview-nested-teams/
mediaTypeNestedTeamsPreview = "application/vnd.github.hellcat-preview+json"
)
// A Client manages communication with the GitHub API.
@ -235,6 +238,37 @@ func NewClient(httpClient *http.Client) *Client {
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

View File

@ -8,6 +8,7 @@ package github
import (
"context"
"fmt"
"strings"
"time"
)
@ -20,11 +21,7 @@ type Team struct {
URL *string `json:"url,omitempty"`
Slug *string `json:"slug,omitempty"`
// Permission is deprecated when creating or editing a team in an org
// using the new GitHub permission model. It no longer identifies the
// permission a team has on its repos, but only specifies the default
// permission a repo is initially added with. Avoid confusion by
// specifying a permission value when calling AddTeamRepo.
// Permission 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.
@ -39,6 +36,7 @@ type Team struct {
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.
@ -79,6 +77,9 @@ func (s *OrganizationsService) ListTeams(ctx context.Context, org string, opt *L
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 {
@ -98,6 +99,9 @@ func (s *OrganizationsService) GetTeam(ctx context.Context, team int) (*Team, *R
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 {
@ -107,16 +111,50 @@ func (s *OrganizationsService) GetTeam(ctx context.Context, team int) (*Team, *R
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 *int `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/orgs/teams/#create-team
func (s *OrganizationsService) CreateTeam(ctx context.Context, org string, team *Team) (*Team, *Response, error) {
func (s *OrganizationsService) 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 {
@ -129,13 +167,16 @@ func (s *OrganizationsService) CreateTeam(ctx context.Context, org string, team
// EditTeam edits a team.
//
// GitHub API docs: https://developer.github.com/v3/orgs/teams/#edit-team
func (s *OrganizationsService) EditTeam(ctx context.Context, id int, team *Team) (*Team, *Response, error) {
func (s *OrganizationsService) EditTeam(ctx context.Context, id int, 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 {
@ -155,6 +196,8 @@ func (s *OrganizationsService) DeleteTeam(ctx context.Context, team int) (*Respo
return nil, err
}
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
return s.client.Do(ctx, req, nil)
}
@ -168,6 +211,32 @@ type OrganizationListTeamMembersOptions struct {
ListOptions
}
// ListChildTeams lists child teams for a team.
//
// GitHub API docs: https://developer.github.com/v3/orgs/teams/#list-child-teams
func (s *OrganizationsService) ListChildTeams(ctx context.Context, teamID int, 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
}
// ListTeamMembers lists all of the users who are members of the specified
// team.
//
@ -184,6 +253,8 @@ func (s *OrganizationsService) ListTeamMembers(ctx context.Context, team int, op
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
var members []*User
resp, err := s.client.Do(ctx, req, &members)
if err != nil {
@ -227,7 +298,8 @@ func (s *OrganizationsService) ListTeamRepos(ctx context.Context, team int, opt
}
// TODO: remove custom Accept header when topics API fully launches.
req.Header.Set("Accept", mediaTypeTopicsPreview)
headers := []string{mediaTypeTopicsPreview, mediaTypeNestedTeamsPreview}
req.Header.Set("Accept", strings.Join(headers, ", "))
var repos []*Repository
resp, err := s.client.Do(ctx, req, &repos)
@ -250,7 +322,8 @@ func (s *OrganizationsService) IsTeamRepo(ctx context.Context, team int, owner s
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeOrgPermissionRepo)
headers := []string{mediaTypeOrgPermissionRepo, mediaTypeNestedTeamsPreview}
req.Header.Set("Accept", strings.Join(headers, ", "))
repository := new(Repository)
resp, err := s.client.Do(ctx, req, repository)
@ -318,6 +391,9 @@ func (s *OrganizationsService) ListUserTeams(ctx context.Context, opt *ListOptio
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 {
@ -337,6 +413,8 @@ func (s *OrganizationsService) GetTeamMembership(ctx context.Context, team int,
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
t := new(Membership)
resp, err := s.client.Do(ctx, req, t)
if err != nil {

View File

@ -138,7 +138,7 @@ func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string
return pull, resp, nil
}
// GetRaw gets raw (diff or patch) format of a pull request.
// 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)
@ -155,13 +155,13 @@ func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo str
return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type)
}
ret := new(bytes.Buffer)
resp, err := s.client.Do(ctx, req, ret)
var buf bytes.Buffer
resp, err := s.client.Do(ctx, req, &buf)
if err != nil {
return "", resp, err
}
return ret.String(), resp, nil
return buf.String(), resp, nil
}
// NewPullRequest represents a new pull request to be created.

View File

@ -84,5 +84,5 @@ func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo s
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeTeamReviewPreview)
return s.client.Do(ctx, req, reviewers)
return s.client.Do(ctx, req, nil)
}

View File

@ -481,6 +481,8 @@ func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
var teams []*Team
resp, err := s.client.Do(ctx, req, &teams)
if err != nil {

View File

@ -41,6 +41,8 @@ func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeNestedTeamsPreview)
var users []*User
resp, err := s.client.Do(ctx, req, &users)
if err != nil {

View File

@ -140,10 +140,9 @@ func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo strin
}
// GetCommit fetches the specified commit, including all details about it.
// todo: support media formats - https://github.com/google/go-github/issues/6
//
// 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
// 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)
@ -164,6 +163,32 @@ func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha st
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.
//

View File

@ -15,6 +15,7 @@ type AgentCheck struct {
Output string
ServiceID string
ServiceName string
Definition HealthCheckDefinition
}
// AgentService represents a service known to the agent

View File

@ -42,6 +42,7 @@ type CatalogRegistration struct {
Datacenter string
Service *AgentService
Check *AgentCheck
SkipNodeUpdate bool
}
type CatalogDeregistration struct {

View File

@ -66,3 +66,41 @@ func (c *Coordinate) Nodes(q *QueryOptions) ([]*CoordinateEntry, *QueryMeta, err
}
return out, qm, nil
}
// Update inserts or updates the LAN coordinate of a node.
func (c *Coordinate) Update(coord *CoordinateEntry, q *WriteOptions) (*WriteMeta, error) {
r := c.c.newRequest("PUT", "/v1/coordinate/update")
r.setWriteOptions(q)
r.obj = coord
rtt, resp, err := requireOK(c.c.doRequest(r))
if err != nil {
return nil, err
}
defer resp.Body.Close()
wm := &WriteMeta{}
wm.RequestTime = rtt
return wm, nil
}
// Node is used to return the coordinates of a single in the LAN pool.
func (c *Coordinate) Node(node string, q *QueryOptions) ([]*CoordinateEntry, *QueryMeta, error) {
r := c.c.newRequest("GET", "/v1/coordinate/node/"+node)
r.setQueryOptions(q)
rtt, resp, err := requireOK(c.c.doRequest(r))
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
qm := &QueryMeta{}
parseQueryMeta(resp, qm)
qm.RequestTime = rtt
var out []*CoordinateEntry
if err := decodeBody(resp, &out); err != nil {
return nil, nil, err
}
return out, qm, nil
}

View File

@ -34,6 +34,21 @@ type HealthCheck struct {
ServiceID string
ServiceName string
ServiceTags []string
Definition HealthCheckDefinition
}
// HealthCheckDefinition is used to store the details about
// a health check's execution.
type HealthCheckDefinition struct {
HTTP string
Header map[string][]string
Method string
TLSSkipVerify bool
TCP string
Interval ReadableDuration
Timeout ReadableDuration
DeregisterCriticalServiceAfter ReadableDuration
}
// HealthChecks is a collection of HealthCheck structs.

View File

@ -5,6 +5,12 @@ import (
"time"
)
const (
// minRate is the minimum rate at which we allow an action to be performed
// across the whole cluster. The value is once a day: 1 / (1 * time.Day)
minRate = 1.0 / 86400
)
// DurationMinusBuffer returns a duration, minus a buffer and jitter
// subtracted from the duration. This function is used primarily for
// servicing Consul TTL Checks in advance of the TTL.
@ -43,7 +49,6 @@ func RandomStagger(intv time.Duration) time.Duration {
// order to target an aggregate number of actions per second across the whole
// cluster.
func RateScaledInterval(rate float64, min time.Duration, n int) time.Duration {
const minRate = 1 / 86400 // 1/(1 * time.Day)
if rate <= minRate {
return min
}

View File

@ -76,7 +76,7 @@ must be properly secured to protect this configuration.
## Architecture
The HashiCorp plugin system works by launching subprocesses and communicating
over RPC (using standard `net/rpc` or [gRPC](http://www.grpc.io). A single
over RPC (using standard `net/rpc` or [gRPC](http://www.grpc.io)). A single
connection is made between any plugin and the host process. For net/rpc-based
plugins, we use a [connection multiplexing](https://github.com/hashicorp/yamux)
library to multiplex any other connections on top. For gRPC-based plugins,

View File

@ -606,7 +606,7 @@ func (c *Client) Start() (addr net.Addr, err error) {
if int(coreProtocol) != CoreProtocolVersion {
err = fmt.Errorf("Incompatible core API version with plugin. "+
"Plugin version: %s, Ours: %d\n\n"+
"Plugin version: %s, Core version: %d\n\n"+
"To fix this, the plugin usually only needs to be recompiled.\n"+
"Please report this to the plugin author.", parts[0], CoreProtocolVersion)
return
@ -624,7 +624,7 @@ func (c *Client) Start() (addr net.Addr, err error) {
// Test the API version
if uint(protocol) != c.config.ProtocolVersion {
err = fmt.Errorf("Incompatible API version with plugin. "+
"Plugin version: %s, Ours: %d", parts[1], c.config.ProtocolVersion)
"Plugin version: %s, Core version: %d", parts[1], c.config.ProtocolVersion)
return
}

View File

@ -1,6 +1,7 @@
package sockaddr
import (
"encoding/binary"
"errors"
"fmt"
"math/big"
@ -866,6 +867,80 @@ func IfAddrMath(operation, value string, inputIfAddr IfAddr) (IfAddr, error) {
default:
return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
}
case "mask":
// "mask" operates on the IP address and returns the IP address on
// which the given integer mask has been applied. If the applied mask
// corresponds to a larger network than the mask of the IP address,
// the latter will be replaced by the former.
switch sockType := inputIfAddr.SockAddr.Type(); sockType {
case TypeIPv4:
i, err := strconv.ParseUint(value, 10, 32)
if err != nil {
return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
}
if i > 32 {
return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv4 addresses must be between 0 and 32", operation)
}
ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
ipv4Mask := net.CIDRMask(int(i), 32)
ipv4MaskUint32 := binary.BigEndian.Uint32(ipv4Mask)
maskedIpv4 := ipv4.NetIP().Mask(ipv4Mask)
maskedIpv4Uint32 := binary.BigEndian.Uint32(maskedIpv4)
maskedIpv4MaskUint32 := uint32(ipv4.Mask)
if ipv4MaskUint32 < maskedIpv4MaskUint32 {
maskedIpv4MaskUint32 = ipv4MaskUint32
}
return IfAddr{
SockAddr: IPv4Addr{
Address: IPv4Address(maskedIpv4Uint32),
Mask: IPv4Mask(maskedIpv4MaskUint32),
},
Interface: inputIfAddr.Interface,
}, nil
case TypeIPv6:
i, err := strconv.ParseUint(value, 10, 32)
if err != nil {
return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
}
if i > 128 {
return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv6 addresses must be between 0 and 64", operation)
}
ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
ipv6Mask := net.CIDRMask(int(i), 128)
ipv6MaskBigInt := new(big.Int)
ipv6MaskBigInt.SetBytes(ipv6Mask)
maskedIpv6 := ipv6.NetIP().Mask(ipv6Mask)
maskedIpv6BigInt := new(big.Int)
maskedIpv6BigInt.SetBytes(maskedIpv6)
maskedIpv6MaskBigInt := new(big.Int)
maskedIpv6MaskBigInt.Set(ipv6.Mask)
if ipv6MaskBigInt.Cmp(maskedIpv6MaskBigInt) == -1 {
maskedIpv6MaskBigInt = ipv6MaskBigInt
}
return IfAddr{
SockAddr: IPv6Addr{
Address: IPv6Address(maskedIpv6BigInt),
Mask: IPv6Mask(maskedIpv6MaskBigInt),
},
Interface: inputIfAddr.Interface,
}, nil
default:
return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
}
default:
return IfAddr{}, fmt.Errorf("unsupported math operation: %q", operation)
}

View File

@ -1,7 +1,7 @@
# Vault Plugin: Kubernetes Auth Backend
This is a standalone backend plugin for use with [Hashicorp Vault](https://www.github.com/hashicorp/vault).
This plugin allows for Kubernets Service Accounts to authenticate with Vault.
This plugin allows for Kubernetes Service Accounts to authenticate with Vault.
**Please note**: We take Vault's security and our users' trust very seriously. If you believe you have found a security issue in Vault, _please responsibly disclose_ by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com).

View File

@ -3,7 +3,7 @@
package isatty
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false

View File

@ -3,6 +3,8 @@ package complete
import (
"os"
"path/filepath"
"strings"
"unicode"
)
// Args describes command line arguments
@ -37,16 +39,41 @@ func (a Args) Directory() string {
return fixPathForm(a.Last, dir)
}
func newArgs(line []string) Args {
completed := removeLast(line[1:])
func newArgs(line string) Args {
var (
all []string
completed []string
)
parts := splitFields(line)
if len(parts) > 0 {
all = parts[1:]
completed = removeLast(parts[1:])
}
return Args{
All: line[1:],
All: all,
Completed: completed,
Last: last(line),
Last: last(parts),
LastCompleted: last(completed),
}
}
func splitFields(line string) []string {
parts := strings.Fields(line)
if len(line) > 0 && unicode.IsSpace(rune(line[len(line)-1])) {
parts = append(parts, "")
}
parts = splitLastEqual(parts)
return parts
}
func splitLastEqual(line []string) []string {
if len(line) == 0 {
return line
}
parts := strings.Split(line[len(line)-1], "=")
return append(line[:len(line)-1], parts...)
}
func (a Args) from(i int) Args {
if i > len(a.All) {
i = len(a.All)
@ -67,9 +94,9 @@ func removeLast(a []string) []string {
return a
}
func last(args []string) (last string) {
if len(args) > 0 {
last = args[len(args)-1]
func last(args []string) string {
if len(args) == 0 {
return ""
}
return
return args[len(args)-1]
}

View File

@ -1,7 +1,5 @@
package complete
import "github.com/posener/complete/match"
// Command represents a command line
// It holds the data that enables auto completion of command line
// Command can also be a sub command.
@ -25,9 +23,9 @@ type Command struct {
}
// Predict returns all possible predictions for args according to the command struct
func (c *Command) Predict(a Args) (predictions []string) {
predictions, _ = c.predict(a)
return
func (c *Command) Predict(a Args) []string {
options, _ := c.predict(a)
return options
}
// Commands is the type of Sub member, it maps a command name to a command struct
@ -36,9 +34,7 @@ type Commands map[string]Command
// Predict completion of sub command names names according to command line arguments
func (c Commands) Predict(a Args) (prediction []string) {
for sub := range c {
if match.Prefix(sub, a.Last) {
prediction = append(prediction, sub)
}
prediction = append(prediction, sub)
}
return
}
@ -56,10 +52,7 @@ func (f Flags) Predict(a Args) (prediction []string) {
if flagHyphenStart && !lastHyphenStart {
continue
}
if match.Prefix(flag, a.Last) {
prediction = append(prediction, flag)
}
prediction = append(prediction, flag)
}
return
}

View File

@ -8,10 +8,11 @@ package complete
import (
"flag"
"fmt"
"io"
"os"
"strings"
"github.com/posener/complete/cmd"
"github.com/posener/complete/match"
)
const (
@ -23,6 +24,7 @@ const (
type Complete struct {
Command Command
cmd.CLI
Out io.Writer
}
// New creates a new complete command.
@ -34,6 +36,7 @@ func New(name string, command Command) *Complete {
return &Complete{
Command: command,
CLI: cmd.CLI{Name: name},
Out: os.Stdout,
}
}
@ -59,28 +62,34 @@ func (c *Complete) Complete() bool {
return c.CLI.Run()
}
Log("Completing line: %s", line)
a := newArgs(line)
Log("Completing last field: %s", a.Last)
options := c.Command.Predict(a)
Log("Options: %s", options)
Log("Completion: %s", options)
output(options)
// filter only options that match the last argument
matches := []string{}
for _, option := range options {
if match.Prefix(option, a.Last) {
matches = append(matches, option)
}
}
Log("Matches: %s", matches)
c.output(matches)
return true
}
func getLine() ([]string, bool) {
func getLine() (string, bool) {
line := os.Getenv(envComplete)
if line == "" {
return nil, false
return "", false
}
return strings.Split(line, " "), true
return line, true
}
func output(options []string) {
Log("")
func (c *Complete) output(options []string) {
// stdout of program defines the complete options
for _, option := range options {
fmt.Println(option)
fmt.Fprintln(c.Out, option)
}
}

View File

@ -1,7 +1,5 @@
package complete
import "github.com/posener/complete/match"
// PredictSet expects specific set of terms, given in the options argument.
func PredictSet(options ...string) Predictor {
return predictSet(options)
@ -9,11 +7,6 @@ func PredictSet(options ...string) Predictor {
type predictSet []string
func (p predictSet) Predict(a Args) (prediction []string) {
for _, m := range p {
if match.Prefix(m, a.Last) {
prediction = append(prediction, m)
}
}
return
func (p predictSet) Predict(a Args) []string {
return p
}

View File

@ -568,6 +568,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
name = "strings"
case "intSlice":
name = "ints"
case "uintSlice":
name = "uints"
case "boolSlice":
name = "bools"
}
return

View File

@ -65,24 +65,18 @@ type bincEncDriver struct {
encDriverNoopContainerWriter
}
func (e *bincEncDriver) IsBuiltinType(rt uintptr) bool {
return rt == timeTypId
}
// func (e *bincEncDriver) IsBuiltinType(rt uintptr) bool {
// return rt == timeTypId
// }
func (e *bincEncDriver) EncodeBuiltin(rt uintptr, v interface{}) {
if rt == timeTypId {
var bs []byte
switch x := v.(type) {
case time.Time:
bs = encodeTime(x)
case *time.Time:
bs = encodeTime(*x)
default:
e.e.errorf("binc error encoding builtin: expect time.Time, received %T", v)
}
bs := encodeTime(v.(time.Time))
e.w.writen1(bincVdTimestamp<<4 | uint8(len(bs)))
e.w.writeb(bs)
return
}
e.e.errorf("binc error encoding builtin: expect time.Time, received %T", v)
}
func (e *bincEncDriver) EncodeNil() {
@ -388,9 +382,9 @@ func (d *bincDecDriver) TryDecodeAsNil() bool {
return false
}
func (d *bincDecDriver) IsBuiltinType(rt uintptr) bool {
return rt == timeTypId
}
// func (d *bincDecDriver) IsBuiltinType(rt uintptr) bool {
// return rt == timeTypId
// }
func (d *bincDecDriver) DecodeBuiltin(rt uintptr, v interface{}) {
if !d.bdRead {
@ -408,7 +402,9 @@ func (d *bincDecDriver) DecodeBuiltin(rt uintptr, v interface{}) {
var vt *time.Time = v.(*time.Time)
*vt = tt
d.bdRead = false
return
}
d.d.errorf("binc error decoding builtin: expect *time.Time, received %T", v)
}
func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {

View File

@ -974,13 +974,13 @@ func (d *Decoder) kInterfaceNaked(f *codecFnInfo) (rvn reflect.Value) {
rvn = reflect.ValueOf(&v2).Elem()
}
} else {
rvn = reflect.New(d.h.MapType)
if useLookupRecognizedTypes && d.mtr { // isRecognizedRtid(d.mtid) {
if d.mtr {
rvn = reflect.New(d.h.MapType)
d.decode(rv2i(rvn))
rvn = rvn.Elem()
} else {
rvn = rvn.Elem()
d.decodeValue(rvn, nil, false, true)
rvn = reflect.New(d.h.MapType).Elem()
d.decodeValue(rvn, nil, true)
}
}
case valueTypeArray:
@ -1002,13 +1002,13 @@ func (d *Decoder) kInterfaceNaked(f *codecFnInfo) (rvn reflect.Value) {
rvn = rvn2
}
} else {
rvn = reflect.New(d.h.SliceType)
if useLookupRecognizedTypes && d.str { // isRecognizedRtid(d.stid) {
if d.str {
rvn = reflect.New(d.h.SliceType)
d.decode(rv2i(rvn))
rvn = rvn.Elem()
} else {
rvn = rvn.Elem()
d.decodeValue(rvn, nil, false, true)
rvn = reflect.New(d.h.SliceType).Elem()
d.decodeValue(rvn, nil, true)
}
}
case valueTypeExt:
@ -1104,25 +1104,17 @@ func (d *Decoder) kInterface(f *codecFnInfo, rv reflect.Value) {
rvn2, canDecode := isDecodeable(rvn)
if canDecode {
d.decodeValue(rvn2, nil, true, true)
d.decodeValue(rvn2, nil, true)
return
}
rvn2 = reflect.New(rvn.Type()).Elem()
rvn2.Set(rvn)
d.decodeValue(rvn2, nil, true, true)
d.decodeValue(rvn2, nil, true)
rv.Set(rvn2)
}
func (d *Decoder) kStruct(f *codecFnInfo, rv reflect.Value) {
// checking if recognized within kstruct is too expensive.
// only check where you can determine if valid outside the loop
// ie on homogenous collections: slices, arrays and maps.
//
// if true, we don't create too many decFn's.
// It's a delicate balance.
const checkRecognized bool = false // false: TODO
fti := f.ti
dd := d.d
elemsep := d.hh.hasElemSeparators()
@ -1153,7 +1145,7 @@ func (d *Decoder) kStruct(f *codecFnInfo, rv reflect.Value) {
if dd.TryDecodeAsNil() {
si.setToZeroValue(rv)
} else {
d.decodeValue(sfn.field(si), nil, checkRecognized, true)
d.decodeValue(sfn.field(si), nil, true)
}
} else {
d.structFieldNotFound(-1, rvkencname)
@ -1180,7 +1172,7 @@ func (d *Decoder) kStruct(f *codecFnInfo, rv reflect.Value) {
if dd.TryDecodeAsNil() {
si.setToZeroValue(rv)
} else {
d.decodeValue(sfn.field(si), nil, checkRecognized, true)
d.decodeValue(sfn.field(si), nil, true)
}
}
if containerLen > len(fti.sfip) {
@ -1256,7 +1248,6 @@ func (d *Decoder) kSlice(f *codecFnInfo, rv reflect.Value) {
rtelem0Size := int(rtelem0.Size())
rtElem0Kind := rtelem0.Kind()
rtElem0Id := rt2id(rtelem0)
rtelem0Mut := !isImmutableKind(rtElem0Kind)
rtelem := rtelem0
rtelemkind := rtelem.Kind()
@ -1304,12 +1295,6 @@ func (d *Decoder) kSlice(f *codecFnInfo, rv reflect.Value) {
}
}
var recognizedRtid, recognizedRtidPtr bool
if useLookupRecognizedTypes {
recognizedRtid = isRecognizedRtid(rtElem0Id)
recognizedRtidPtr = isRecognizedRtidPtr(rtElem0Id)
}
// consider creating new element once, and just decoding into it.
var rtelem0Zero reflect.Value
var rtelem0ZeroValid bool
@ -1339,14 +1324,10 @@ func (d *Decoder) kSlice(f *codecFnInfo, rv reflect.Value) {
if rtelem0Mut || !rv9.IsValid() { // || (rtElem0Kind == reflect.Ptr && rv9.IsNil()) {
rv9 = reflect.New(rtelem0).Elem()
}
if useLookupRecognizedTypes && (recognizedRtid || recognizedRtidPtr) {
d.decode(rv2i(rv9.Addr()))
} else {
if fn == nil {
fn = d.cf.get(rtelem, true, true)
}
d.decodeValue(rv9, fn, false, true)
if fn == nil {
fn = d.cf.get(rtelem, true, true)
}
d.decodeValue(rv9, fn, true)
rv.Send(rv9)
} else {
// if indefinite, etc, then expand the slice if necessary
@ -1383,19 +1364,10 @@ func (d *Decoder) kSlice(f *codecFnInfo, rv reflect.Value) {
continue
}
if useLookupRecognizedTypes && recognizedRtid {
d.decode(rv2i(rv9.Addr()))
} else if useLookupRecognizedTypes && recognizedRtidPtr { // && !rv9.IsNil() {
if rv9.IsNil() {
rv9.Set(reflect.New(rtelem))
}
d.decode(rv2i(rv9))
} else {
if fn == nil {
fn = d.cf.get(rtelem, true, true)
}
d.decodeValue(rv9, fn, false, true)
if fn == nil {
fn = d.cf.get(rtelem, true, true)
}
d.decodeValue(rv9, fn, true)
}
}
}
@ -1441,15 +1413,7 @@ func (d *Decoder) kMap(f *codecFnInfo, rv reflect.Value) {
ktype, vtype := ti.rt.Key(), ti.rt.Elem()
ktypeId := rt2id(ktype)
vtypeId := rt2id(vtype)
vtypeKind := vtype.Kind()
var recognizedKtyp, recognizedVtyp, recognizedPtrKtyp, recognizedPtrVtyp bool
if useLookupRecognizedTypes {
recognizedKtyp = isRecognizedRtid(ktypeId)
recognizedVtyp = isRecognizedRtid(vtypeId)
recognizedPtrKtyp = isRecognizedRtidPtr(ktypeId)
recognizedPtrVtyp = isRecognizedRtidPtr(vtypeId)
}
var keyFn, valFn *codecFn
var ktypeLo, vtypeLo reflect.Type
@ -1501,26 +1465,19 @@ func (d *Decoder) kMap(f *codecFnInfo, rv reflect.Value) {
kstrbs = dd.DecodeStringAsBytes()
rvk.SetString(stringView(kstrbs))
// NOTE: if doing an insert, you MUST use a real string (not stringview)
} else if useLookupRecognizedTypes && recognizedKtyp {
d.decode(rv2i(rvkp))
// rvk = rvkp.Elem() //TODO: remove, unnecessary
} else if useLookupRecognizedTypes && recognizedPtrKtyp {
if rvk.IsNil() {
rvk = reflect.New(ktypeLo)
}
d.decode(rv2i(rvk))
} else {
if keyFn == nil {
keyFn = d.cf.get(ktypeLo, true, true)
}
d.decodeValue(rvk, keyFn, false, true)
d.decodeValue(rvk, keyFn, true)
}
// special case if a byte array.
if ktypeIsIntf {
if rvk2 := rvk.Elem(); rvk2.IsValid() {
rvk = rvk2
if rvk.Type() == uint8SliceTyp {
rvk = reflect.ValueOf(d.string(rvk.Bytes()))
if rvk2.Type() == uint8SliceTyp {
rvk = reflect.ValueOf(d.string(rvk2.Bytes()))
} else {
rvk = rvk2
}
}
}
@ -1579,21 +1536,11 @@ func (d *Decoder) kMap(f *codecFnInfo, rv reflect.Value) {
if mapSet && ktypeIsString {
rvk.SetString(d.string(kstrbs))
}
if useLookupRecognizedTypes && recognizedVtyp && rvv.CanAddr() {
d.decode(rv2i(rvv.Addr()))
} else if useLookupRecognizedTypes && recognizedPtrVtyp {
if rvv.IsNil() {
rvv = reflect.New(vtypeLo)
mapSet = true
}
d.decode(rv2i(rvv))
} else {
if valFn == nil {
valFn = d.cf.get(vtypeLo, true, true)
}
d.decodeValue(rvv, valFn, false, true)
// d.decodeValueFn(rvv, valFn)
if valFn == nil {
valFn = d.cf.get(vtypeLo, true, true)
}
d.decodeValue(rvv, valFn, true)
// d.decodeValueFn(rvv, valFn)
if mapSet {
rv.SetMapIndex(rvk, rvv)
}
@ -1719,7 +1666,7 @@ type Decoder struct {
hh Handle
h *BasicHandle
mtr, mtrp, str, strp bool //
mtr, str bool // whether maptype or slicetype are known types
be bool // is binary encoding
bytes bool // is bytes reader
@ -1812,23 +1759,16 @@ func (d *Decoder) resetCommon() {
d.d.reset()
d.cf.reset(d.hh)
d.err = nil
// reset all things which were cached from the Handle,
// but could be changed.
// reset all things which were cached from the Handle, but could change
d.mtid, d.stid = 0, 0
d.mtr, d.mtrp, d.str, d.strp = false, false, false, false
d.mtr, d.str = false, false
if d.h.MapType != nil {
d.mtid = rt2id(d.h.MapType)
if useLookupRecognizedTypes {
d.mtr = isRecognizedRtid(d.mtid)
d.mtrp = isRecognizedRtidPtr(d.mtid)
}
d.mtr = fastpathAV.index(d.mtid) != -1
}
if d.h.SliceType != nil {
d.stid = rt2id(d.h.SliceType)
if useLookupRecognizedTypes {
d.str = isRecognizedRtid(d.stid)
d.strp = isRecognizedRtidPtr(d.stid)
}
d.str = fastpathAV.index(d.stid) != -1
}
}
@ -1917,7 +1857,7 @@ func (d *Decoder) MustDecode(v interface{}) {
panic(d.err)
}
if d.d.TryDecodeAsNil() {
d.setZero(v)
setZero(v)
} else {
d.decode(v)
}
@ -1995,7 +1935,7 @@ func (d *Decoder) swallow() {
}
}
func (d *Decoder) setZero(iv interface{}) {
func setZero(iv interface{}) {
if iv == nil || definitelyNil(iv) {
return
}
@ -2038,7 +1978,7 @@ func (d *Decoder) setZero(iv interface{}) {
v.Set(reflect.Zero(v.Type()))
} // TODO: else drain if chan, clear if map, set all to nil if slice???
default:
if !fastpathDecodeSetZeroTypeSwitch(iv, d) {
if !fastpathDecodeSetZeroTypeSwitch(iv) {
v := reflect.ValueOf(iv)
if v, canDecode = isDecodeable(v); canDecode && v.CanSet() {
v.Set(reflect.Zero(v.Type()))
@ -2065,7 +2005,7 @@ func (d *Decoder) decode(iv interface{}) {
case reflect.Value:
v = d.ensureDecodeable(v)
d.decodeValue(v, nil, false, true) // TODO: maybe ask to recognize ...
d.decodeValue(v, nil, true) // TODO: maybe ask to recognize ...
case *string:
*v = d.d.DecodeString()
@ -2102,20 +2042,20 @@ func (d *Decoder) decode(iv interface{}) {
*v = d.rawBytes()
case *interface{}:
d.decodeValue(reflect.ValueOf(iv).Elem(), nil, false, true) // TODO: consider recognize here
d.decodeValue(reflect.ValueOf(iv).Elem(), nil, true) // TODO: consider recognize here
// d.decodeValueNotNil(reflect.ValueOf(iv).Elem())
default:
if !fastpathDecodeTypeSwitch(iv, d) {
v := reflect.ValueOf(iv)
v = d.ensureDecodeable(v)
d.decodeValue(v, nil, false, false)
d.decodeValue(v, nil, false)
// d.decodeValueFallback(v)
}
}
}
func (d *Decoder) decodeValue(rv reflect.Value, fn *codecFn, tryRecognized, chkAll bool) {
func (d *Decoder) decodeValue(rv reflect.Value, fn *codecFn, chkAll bool) {
// If stream is not containing a nil value, then we can deref to the base
// non-pointer value, and decode into that.
var rvp reflect.Value
@ -2134,16 +2074,6 @@ func (d *Decoder) decodeValue(rv reflect.Value, fn *codecFn, tryRecognized, chkA
}
}
if useLookupRecognizedTypes && tryRecognized && isRecognizedRtid(rv2rtid(rv)) {
if rvpValid {
d.decode(rv2i(rvp))
return
} else if rv.CanAddr() {
d.decode(rv2i(rv.Addr()))
return
}
}
if fn == nil {
// always pass checkCodecSelfer=true, in case T or ****T is passed, where *T is a Selfer
fn = d.cf.get(rv.Type(), chkAll, true) // chkAll, chkAll)

View File

@ -350,10 +350,6 @@ func (e *Encoder) builtin(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeBuiltin(f.ti.rtid, rv2i(rv))
}
func (e *Encoder) raw(f *codecFnInfo, rv reflect.Value) {
e.rawBytes(rv2i(rv).(Raw))
}
func (e *Encoder) rawExt(f *codecFnInfo, rv reflect.Value) {
// rev := rv2i(rv).(RawExt)
// e.e.EncodeRawExt(&rev, e)
@ -408,28 +404,8 @@ func (e *Encoder) jsonMarshal(f *codecFnInfo, rv reflect.Value) {
e.marshal(bs, fnerr, true, c_UTF8)
}
func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeBool(rv.Bool())
}
func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeString(c_UTF8, rv.String())
}
func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeFloat64(rv.Float())
}
func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeFloat32(float32(rv.Float()))
}
func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeInt(rv.Int())
}
func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeUint(rv.Uint())
func (e *Encoder) raw(f *codecFnInfo, rv reflect.Value) {
e.rawBytes(rv2i(rv).(Raw))
}
func (e *Encoder) kInvalid(f *codecFnInfo, rv reflect.Value) {
@ -508,20 +484,14 @@ func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
if l > 0 {
var fn *codecFn
var recognizedVtyp bool
if useLookupRecognizedTypes {
recognizedVtyp = isRecognizedRtidOrPtr(rt2id(rtelem))
for rtelem.Kind() == reflect.Ptr {
rtelem = rtelem.Elem()
}
if !(useLookupRecognizedTypes && recognizedVtyp) {
for rtelem.Kind() == reflect.Ptr {
rtelem = rtelem.Elem()
}
// if kind is reflect.Interface, do not pre-determine the
// encoding type, because preEncodeValue may break it down to
// a concrete type and kInterface will bomb.
if rtelem.Kind() != reflect.Interface {
fn = e.cf.get(rtelem, true, true)
}
// if kind is reflect.Interface, do not pre-determine the
// encoding type, because preEncodeValue may break it down to
// a concrete type and kInterface will bomb.
if rtelem.Kind() != reflect.Interface {
fn = e.cf.get(rtelem, true, true)
}
// TODO: Consider perf implication of encoding odd index values as symbols if type is string
for j := 0; j < l; j++ {
@ -538,20 +508,12 @@ func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
}
if f.seq == seqTypeChan {
if rv2, ok2 := rv.Recv(); ok2 {
if useLookupRecognizedTypes && recognizedVtyp {
e.encode(rv2i(rv2))
} else {
e.encodeValue(rv2, fn, true)
}
e.encodeValue(rv2, fn, true)
} else {
ee.EncodeNil() // WE HAVE TO DO SOMETHING, so nil if nothing received.
}
} else {
if useLookupRecognizedTypes && recognizedVtyp {
e.encode(rv2i(rv.Index(j)))
} else {
e.encodeValue(rv.Index(j), fn, true)
}
e.encodeValue(rv.Index(j), fn, true)
}
}
}
@ -768,7 +730,6 @@ func (e *Encoder) kMap(f *codecFnInfo, rv reflect.Value) {
rtval0 := ti.rt.Elem()
rtval := rtval0
rtkeyid := rt2id(rtkey0)
rtvalid := rt2id(rtval0)
for rtval.Kind() == reflect.Ptr {
rtval = rtval.Elem()
}
@ -783,17 +744,10 @@ func (e *Encoder) kMap(f *codecFnInfo, rv reflect.Value) {
return
}
var recognizedKtyp, recognizedVtyp bool
var keyTypeIsString = rtkeyid == stringTypId
if keyTypeIsString {
asSymbols = e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0
} else {
if useLookupRecognizedTypes {
recognizedKtyp = isRecognizedRtidOrPtr(rtkeyid)
if recognizedKtyp {
goto LABEL1
}
}
for rtkey.Kind() == reflect.Ptr {
rtkey = rtkey.Elem()
}
@ -804,10 +758,6 @@ func (e *Encoder) kMap(f *codecFnInfo, rv reflect.Value) {
}
// for j, lmks := 0, len(mks); j < lmks; j++ {
LABEL1:
if useLookupRecognizedTypes {
recognizedVtyp = isRecognizedRtidOrPtr(rtvalid)
}
for j := range mks {
if elemsep {
ee.WriteMapElemKey()
@ -818,19 +768,14 @@ LABEL1:
} else {
ee.EncodeString(c_UTF8, mks[j].String())
}
} else if useLookupRecognizedTypes && recognizedKtyp {
e.encode(rv2i(mks[j]))
} else {
e.encodeValue(mks[j], keyFn, true)
}
if elemsep {
ee.WriteMapElemValue()
}
if useLookupRecognizedTypes && recognizedVtyp {
e.encode(rv2i(rv.MapIndex(mks[j])))
} else {
e.encodeValue(rv.MapIndex(mks[j]), valFn, true)
}
e.encodeValue(rv.MapIndex(mks[j]), valFn, true)
}
ee.WriteMapEnd()
}
@ -1321,11 +1266,6 @@ TOP:
if fn == nil {
rt := rv.Type()
// TODO: calling isRecognizedRtid here is a major slowdown
if false && useLookupRecognizedTypes && isRecognizedRtidOrPtr(rt2id(rt)) {
e.encode(rv2i(rv))
return
}
// always pass checkCodecSelfer=true, in case T or ****T is passed, where *T is a Selfer
fn = e.cf.get(rt, checkFastpath, true)
}

View File

@ -80,19 +80,12 @@ var fastpathAV fastpathA
// due to possible initialization loop error, make fastpath in an init()
func init() {
if useLookupRecognizedTypes && recognizedRtidsLoaded {
panic("recognizedRtidsLoaded = true - cannot happen")
}
i := 0
fn := func(v interface{},
fe func(*Encoder, *codecFnInfo, reflect.Value),
fd func(*Decoder, *codecFnInfo, reflect.Value)) (f fastpathE) {
xrt := reflect.TypeOf(v)
xptr := rt2id(xrt)
if useLookupRecognizedTypes {
recognizedRtids = append(recognizedRtids, xptr)
recognizedRtidPtrs = append(recognizedRtidPtrs, rt2id(reflect.PtrTo(xrt)))
}
fastpathAV[i] = fastpathE{xptr, xrt, fe, fd}
i++
return
@ -15563,7 +15556,7 @@ func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool {
return true
}
func fastpathDecodeSetZeroTypeSwitch(iv interface{}, d *Decoder) bool {
func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool {
switch v := iv.(type) {
case *[]interface{}:

View File

@ -80,19 +80,12 @@ var fastpathAV fastpathA
// due to possible initialization loop error, make fastpath in an init()
func init() {
if useLookupRecognizedTypes && recognizedRtidsLoaded {
panic("recognizedRtidsLoaded = true - cannot happen")
}
i := 0
fn := func(v interface{},
fe func(*Encoder, *codecFnInfo, reflect.Value),
fd func(*Decoder, *codecFnInfo, reflect.Value)) (f fastpathE) {
xrt := reflect.TypeOf(v)
xptr := rt2id(xrt)
if useLookupRecognizedTypes {
recognizedRtids = append(recognizedRtids, xptr)
recognizedRtidPtrs = append(recognizedRtidPtrs, rt2id(reflect.PtrTo(xrt)))
}
fastpathAV[i] = fastpathE{xptr, xrt, fe, fd}
i++
return
@ -289,7 +282,7 @@ func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool {
return true
}
func fastpathDecodeSetZeroTypeSwitch(iv interface{}, d *Decoder) bool {
func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool {
switch v := iv.(type) {
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
case *[]{{ .Elem }}: {{else}}

View File

@ -14,11 +14,11 @@ const fastpathEnabled = false
// This tag disables fastpath during build, allowing for faster build, test execution,
// short-program runs, etc.
func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { return false }
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { return false }
func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { return false }
func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { return false }
func fastpathDecodeSetZeroTypeSwitch(iv interface{}, d *Decoder) bool { return false }
func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { return false }
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { return false }
func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { return false }
func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { return false }
func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool { return false }
type fastpathT struct{}
type fastpathE struct {
@ -33,3 +33,6 @@ func (x fastpathA) index(rtid uintptr) int { return -1 }
var fastpathAV fastpathA
var fastpathTV fastpathT
// ----
type TestMammoth2Wrapper struct{} // to allow testMammoth work in notfastpath mode

View File

@ -155,7 +155,7 @@ func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
if chkPtr {
rv = f.d.ensureDecodeable(rv)
}
f.d.decodeValue(rv, nil, false, false)
f.d.decodeValue(rv, nil, false)
// f.d.decodeValueFallback(rv)
}

View File

@ -142,7 +142,7 @@ func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
if chkPtr {
rv = f.d.ensureDecodeable(rv)
}
f.d.decodeValue(rv, nil, false, false)
f.d.decodeValue(rv, nil, false)
// f.d.decodeValueFallback(rv)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*

View File

@ -504,7 +504,7 @@ func (x *genRunner) selfer(encode bool) {
t0 := t
// always make decode use a pointer receiver,
// and structs always use a ptr receiver (encode|decode)
isptr := !encode || t.Kind() == reflect.Struct
isptr := !encode || (t.Kind() == reflect.Struct || t.Kind() == reflect.Array)
x.varsfxreset()
fnSigPfx := "func (x "
if isptr {
@ -701,11 +701,11 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
defer func() { x.line("}") }() //end if block
if t == rawTyp {
x.linef("} else { z.EncRaw(%v)", varname)
x.linef("} else { z.EncRaw(%s)", varname)
return
}
if t == rawExtTyp {
x.linef("} else { r.EncodeRawExt(%v, e)", varname)
x.linef("} else { r.EncodeRawExt(%s, e)", varname)
return
}
// HACK: Support for Builtins.
@ -714,7 +714,7 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
if t == timeTyp {
vrtid := genTempVarPfx + "m" + x.varsfx()
x.linef("} else if %s := z.TimeRtidIfBinc(); %s != 0 { ", vrtid, vrtid)
x.linef("r.EncodeBuiltin(%s, %s)", vrtid, varname)
x.linef("r.EncodeBuiltin(%s, *%s)", vrtid, varname)
}
// only check for extensions if the type is named, and has a packagePath.
if !x.nx && genImportPath(t) != "" && t.Name() != "" {
@ -999,7 +999,7 @@ func (x *genRunner) encListFallback(varname string, t reflect.Type) {
return
}
if t.Kind() == reflect.Array && t.Elem().Kind() == reflect.Uint8 {
x.linef("r.EncodeStringBytes(codecSelferC_RAW%s, ([%v]byte(%s))[:])", x.xs, t.Len(), varname)
x.linef("r.EncodeStringBytes(codecSelferC_RAW%s, ((*[%d]byte)(%s))[:])", x.xs, t.Len(), varname)
return
}
i := x.varsfx()
@ -1332,7 +1332,7 @@ func (x *genRunner) decListFallback(varname string, rtid uintptr, t reflect.Type
return
}
if t.Kind() == reflect.Array && t.Elem().Kind() == reflect.Uint8 {
x.linef("r.DecodeBytes( ((*[%s]byte)(%s))[:], true)", t.Len(), varname)
x.linef("r.DecodeBytes( ((*[%d]byte)(%s))[:], true)", t.Len(), varname)
return
}
type tstruc struct {

View File

@ -128,40 +128,6 @@ const (
// allowing zero-alloc initialization.
arrayCacheLen = 8
// We tried an optimization, where we detect if a type is one of the known types
// we optimized for (e.g. int, []uint64, etc).
//
// However, we notice some worse performance when using this optimization.
// So we hide it behind a flag, to turn on if needed.
useLookupRecognizedTypes = false
// using recognized allows us to do d.decode(interface{}) instead of d.decodeValue(reflect.Value)
// when we can infer that the kind of the interface{} is one of the ones hard-coded in the
// type switch for known types or the ones defined by fast-path.
//
// However, it seems we get better performance when we don't recognize, and just let
// reflection handle it.
//
// Reasoning is as below:
// typeswitch is a binary search with a branch to a code-point.
// getdecfn is a binary search with a call to a function pointer.
//
// both are about the same.
//
// so: why prefer typeswitch?
//
// is recognized does the following:
// - lookup rtid
// - check if in sorted list
// - calls decode(type switch)
// - 1 or 2 binary search to a point in code
// - branch there
//
// vs getdecfn
// - lookup rtid
// - check in sorted list for a function pointer
// - calls it to decode using reflection (optimized)
// always set xDebug = false before releasing software
xDebug = true
)
@ -224,32 +190,25 @@ const (
// valueTypeInvalid = 0xff
)
var valueTypeStrings = [...]string{
"Unset",
"Nil",
"Int",
"Uint",
"Float",
"Bool",
"String",
"Symbol",
"Bytes",
"Map",
"Array",
"Timestamp",
"Ext",
}
func (x valueType) String() string {
switch x {
case valueTypeNil:
return "Nil"
case valueTypeInt:
return "Int"
case valueTypeUint:
return "Uint"
case valueTypeFloat:
return "Float"
case valueTypeBool:
return "Bool"
case valueTypeString:
return "String"
case valueTypeSymbol:
return "Symbol"
case valueTypeBytes:
return "Bytes"
case valueTypeMap:
return "Map"
case valueTypeArray:
return "Array"
case valueTypeTimestamp:
return "Timestamp"
case valueTypeExt:
return "Ext"
if int(x) < len(valueTypeStrings) {
return valueTypeStrings[x]
}
return strconv.FormatInt(int64(x), 10)
}
@ -408,85 +367,6 @@ var immutableKindsSet = [32]bool{
// reflect.UnsafePointer
}
var (
recognizedRtids []uintptr
recognizedRtidPtrs []uintptr
recognizedRtidOrPtrs []uintptr
recognizedRtidsLoaded bool
)
func init() {
if !useLookupRecognizedTypes {
return
}
if recognizedRtidsLoaded {
panic("recognizedRtidsLoaded = true - cannot happen")
}
for _, v := range [...]interface{}{
float32(0),
float64(0),
uintptr(0),
uint(0),
uint8(0),
uint16(0),
uint32(0),
uint64(0),
uintptr(0),
int(0),
int8(0),
int16(0),
int32(0),
int64(0),
bool(false),
string(""),
Raw{},
[]byte(nil),
} {
rt := reflect.TypeOf(v)
recognizedRtids = append(recognizedRtids, rt2id(rt))
recognizedRtidPtrs = append(recognizedRtidPtrs, rt2id(reflect.PtrTo(rt)))
}
// now sort it.
sort.Sort(uintptrSlice(recognizedRtids))
sort.Sort(uintptrSlice(recognizedRtidPtrs))
recognizedRtidOrPtrs = make([]uintptr, len(recognizedRtids)+len(recognizedRtidPtrs))
copy(recognizedRtidOrPtrs, recognizedRtids)
copy(recognizedRtidOrPtrs[len(recognizedRtids):], recognizedRtidPtrs)
sort.Sort(uintptrSlice(recognizedRtidOrPtrs))
recognizedRtidsLoaded = true
}
func containsU(s []uintptr, v uintptr) bool {
// return false // TODO: REMOVE
h, i, j := 0, 0, len(s)
for i < j {
h = i + (j-i)/2
if s[h] < v {
i = h + 1
} else {
j = h
}
}
if i < len(s) && s[i] == v {
return true
}
return false
}
func isRecognizedRtid(rtid uintptr) bool {
return containsU(recognizedRtids, rtid)
}
func isRecognizedRtidPtr(rtid uintptr) bool {
return containsU(recognizedRtidPtrs, rtid)
}
func isRecognizedRtidOrPtr(rtid uintptr) bool {
return containsU(recognizedRtidOrPtrs, rtid)
}
// Selfer defines methods by which a value can encode or decode itself.
//
// Any type which implements Selfer will be able to encode or decode itself.
@ -823,10 +703,10 @@ func (si *structFieldInfo) field(v reflect.Value, update bool) (rv2 reflect.Valu
return v, true
}
func (si *structFieldInfo) fieldval(v reflect.Value, update bool) reflect.Value {
v, _ = si.field(v, update)
return v
}
// func (si *structFieldInfo) fieldval(v reflect.Value, update bool) reflect.Value {
// v, _ = si.field(v, update)
// return v
// }
func parseStructFieldInfo(fname string, stag string) *structFieldInfo {
// if fname == "" {
@ -1555,36 +1435,36 @@ func (c *codecFner) get(rt reflect.Type, checkFastpath, checkCodecSelfer bool) (
fn.fd = (*Decoder).kInt
fn.fe = (*Encoder).kInt
case reflect.Int8:
fn.fe = (*Encoder).kInt
fn.fe = (*Encoder).kInt8
fn.fd = (*Decoder).kInt8
case reflect.Int16:
fn.fe = (*Encoder).kInt
fn.fe = (*Encoder).kInt16
fn.fd = (*Decoder).kInt16
case reflect.Int32:
fn.fe = (*Encoder).kInt
fn.fe = (*Encoder).kInt32
fn.fd = (*Decoder).kInt32
case reflect.Int64:
fn.fe = (*Encoder).kInt
fn.fe = (*Encoder).kInt64
fn.fd = (*Decoder).kInt64
case reflect.Uint:
fn.fd = (*Decoder).kUint
fn.fe = (*Encoder).kUint
case reflect.Uint8:
fn.fe = (*Encoder).kUint
fn.fe = (*Encoder).kUint8
fn.fd = (*Decoder).kUint8
case reflect.Uint16:
fn.fe = (*Encoder).kUint
fn.fe = (*Encoder).kUint16
fn.fd = (*Decoder).kUint16
case reflect.Uint32:
fn.fe = (*Encoder).kUint
fn.fe = (*Encoder).kUint32
fn.fd = (*Decoder).kUint32
case reflect.Uint64:
fn.fe = (*Encoder).kUint
fn.fe = (*Encoder).kUint64
fn.fd = (*Decoder).kUint64
// case reflect.Ptr:
// fn.fd = (*Decoder).kPtr
case reflect.Uintptr:
fn.fe = (*Encoder).kUint
fn.fe = (*Encoder).kUintptr
fn.fd = (*Decoder).kUintptr
case reflect.Float32:
fn.fe = (*Encoder).kFloat32
@ -1594,6 +1474,7 @@ func (c *codecFner) get(rt reflect.Type, checkFastpath, checkCodecSelfer bool) (
fn.fd = (*Decoder).kFloat64
case reflect.Invalid:
fn.fe = (*Encoder).kInvalid
fn.fd = (*Decoder).kErr
case reflect.Chan:
fi.seq = seqTypeChan
fn.fe = (*Encoder).kSlice
@ -1631,6 +1512,7 @@ func (c *codecFner) get(rt reflect.Type, checkFastpath, checkCodecSelfer bool) (
case reflect.Interface:
// encode: reflect.Interface are handled already by preEncodeValue
fn.fd = (*Decoder).kInterface
fn.fe = (*Encoder).kErr
default:
fn.fe = (*Encoder).kErr
fn.fd = (*Decoder).kErr
@ -1886,39 +1768,42 @@ func (s *set) remove(v uintptr) (exists bool) {
type bitset256 [32]byte
func (x *bitset256) set(pos byte) {
x[pos>>3] |= (1 << (pos & 7))
}
func (x *bitset256) unset(pos byte) {
x[pos>>3] &^= (1 << (pos & 7))
}
func (x *bitset256) isset(pos byte) bool {
return x[pos>>3]&(1<<(pos&7)) != 0
}
func (x *bitset256) set(pos byte) {
x[pos>>3] |= (1 << (pos & 7))
}
// func (x *bitset256) unset(pos byte) {
// x[pos>>3] &^= (1 << (pos & 7))
// }
type bitset128 [16]byte
func (x *bitset128) set(pos byte) {
x[pos>>3] |= (1 << (pos & 7))
}
func (x *bitset128) unset(pos byte) {
x[pos>>3] &^= (1 << (pos & 7))
}
func (x *bitset128) isset(pos byte) bool {
return x[pos>>3]&(1<<(pos&7)) != 0
}
func (x *bitset128) set(pos byte) {
x[pos>>3] |= (1 << (pos & 7))
}
// func (x *bitset128) unset(pos byte) {
// x[pos>>3] &^= (1 << (pos & 7))
// }
type bitset32 [4]byte
func (x *bitset32) set(pos byte) {
x[pos>>3] |= (1 << (pos & 7))
}
func (x *bitset32) unset(pos byte) {
x[pos>>3] &^= (1 << (pos & 7))
}
func (x *bitset32) isset(pos byte) bool {
return x[pos>>3]&(1<<(pos&7)) != 0
}
func (x *bitset32) set(pos byte) {
x[pos>>3] |= (1 << (pos & 7))
}
// func (x *bitset32) unset(pos byte) {
// x[pos>>3] &^= (1 << (pos & 7))
// }
// ------------

View File

@ -158,3 +158,65 @@ func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
rv.SetUint(d.d.DecodeUint(64))
}
// ----------------
func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeBool(rv.Bool())
}
func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeString(c_UTF8, rv.String())
}
func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeFloat64(rv.Float())
}
func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeFloat32(float32(rv.Float()))
}
func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeInt(rv.Int())
}
func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeInt(rv.Int())
}
func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeInt(rv.Int())
}
func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeInt(rv.Int())
}
func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeInt(rv.Int())
}
func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeUint(rv.Uint())
}
func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeUint(rv.Uint())
}
func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeUint(rv.Uint())
}
func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeUint(rv.Uint())
}
func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeUint(rv.Uint())
}
func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeUint(rv.Uint())
}

View File

@ -219,6 +219,83 @@ func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
// ------------
func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeBool(*(*bool)(v.ptr))
}
func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeString(c_UTF8, *(*string)(v.ptr))
}
func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeFloat64(*(*float64)(v.ptr))
}
func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeFloat32(*(*float32)(v.ptr))
}
func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeInt(int64(*(*int)(v.ptr)))
}
func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeInt(int64(*(*int8)(v.ptr)))
}
func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeInt(int64(*(*int16)(v.ptr)))
}
func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeInt(int64(*(*int32)(v.ptr)))
}
func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeInt(int64(*(*int64)(v.ptr)))
}
func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeUint(uint64(*(*uint)(v.ptr)))
}
func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeUint(uint64(*(*uint8)(v.ptr)))
}
func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeUint(uint64(*(*uint16)(v.ptr)))
}
func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeUint(uint64(*(*uint32)(v.ptr)))
}
func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeUint(uint64(*(*uint64)(v.ptr)))
}
func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeUint(uint64(*(*uintptr)(v.ptr)))
}
// ------------
// func rt2id(rt reflect.Type) uintptr {
// return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
// // var i interface{} = rt

View File

@ -49,11 +49,11 @@ func doTestMammothSlices(t *testing.T, h Handle) {
// fmt.Printf(">>>> running mammoth slice v{{$i}}: %v\n", v)
var v{{$i}}v1, v{{$i}}v2, v{{$i}}v3, v{{$i}}v4 []{{ .Elem }}
v{{$i}}v1 = v
bs{{$i}}, _ := testMarshalErr(v{{$i}}v1, h, t, "enc-slice-v{{$i}}")
bs{{$i}} := testMarshalErr(v{{$i}}v1, h, t, "enc-slice-v{{$i}}")
if v != nil { v{{$i}}v2 = make([]{{ .Elem }}, len(v)) }
testUnmarshalErr(v{{$i}}v2, bs{{$i}}, h, t, "dec-slice-v{{$i}}")
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-slice-v{{$i}}")
bs{{$i}}, _ = testMarshalErr(&v{{$i}}v1, h, t, "enc-slice-v{{$i}}-p")
bs{{$i}} = testMarshalErr(&v{{$i}}v1, h, t, "enc-slice-v{{$i}}-p")
v{{$i}}v2 = nil
testUnmarshalErr(&v{{$i}}v2, bs{{$i}}, h, t, "dec-slice-v{{$i}}-p")
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-slice-v{{$i}}-p")
@ -61,12 +61,12 @@ func doTestMammothSlices(t *testing.T, h Handle) {
v{{$i}}v2 = nil
if v != nil { v{{$i}}v2 = make([]{{ .Elem }}, len(v)) }
v{{$i}}v3 = {{ .MethodNamePfx "type" false }}(v{{$i}}v1)
bs{{$i}}, _ = testMarshalErr(v{{$i}}v3, h, t, "enc-slice-v{{$i}}-custom")
bs{{$i}} = testMarshalErr(v{{$i}}v3, h, t, "enc-slice-v{{$i}}-custom")
v{{$i}}v4 = {{ .MethodNamePfx "type" false }}(v{{$i}}v2)
testUnmarshalErr(v{{$i}}v4, bs{{$i}}, h, t, "dec-slice-v{{$i}}-custom")
testDeepEqualErr(v{{$i}}v3, v{{$i}}v4, t, "equal-slice-v{{$i}}-custom")
v{{$i}}v2 = nil
bs{{$i}}, _ = testMarshalErr(&v{{$i}}v3, h, t, "enc-slice-v{{$i}}-custom-p")
bs{{$i}} = testMarshalErr(&v{{$i}}v3, h, t, "enc-slice-v{{$i}}-custom-p")
v{{$i}}v4 = {{ .MethodNamePfx "type" false }}(v{{$i}}v2)
testUnmarshalErr(&v{{$i}}v4, bs{{$i}}, h, t, "dec-slice-v{{$i}}-custom-p")
testDeepEqualErr(v{{$i}}v3, v{{$i}}v4, t, "equal-slice-v{{$i}}-custom-p")
@ -81,11 +81,11 @@ func doTestMammothMaps(t *testing.T, h Handle) {
// fmt.Printf(">>>> running mammoth map v{{$i}}: %v\n", v)
var v{{$i}}v1, v{{$i}}v2 map[{{ .MapKey }}]{{ .Elem }}
v{{$i}}v1 = v
bs{{$i}}, _ := testMarshalErr(v{{$i}}v1, h, t, "enc-map-v{{$i}}")
bs{{$i}} := testMarshalErr(v{{$i}}v1, h, t, "enc-map-v{{$i}}")
if v != nil { v{{$i}}v2 = make(map[{{ .MapKey }}]{{ .Elem }}, len(v)) }
testUnmarshalErr(v{{$i}}v2, bs{{$i}}, h, t, "dec-map-v{{$i}}")
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-map-v{{$i}}")
bs{{$i}}, _ = testMarshalErr(&v{{$i}}v1, h, t, "enc-map-v{{$i}}-p")
bs{{$i}} = testMarshalErr(&v{{$i}}v1, h, t, "enc-map-v{{$i}}-p")
v{{$i}}v2 = nil
testUnmarshalErr(&v{{$i}}v2, bs{{$i}}, h, t, "dec-map-v{{$i}}-p")
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-map-v{{$i}}-p")

View File

@ -0,0 +1,97 @@
// +build !notfastpath
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.
// ************************************************************
// DO NOT EDIT.
// THIS FILE IS AUTO-GENERATED from mammoth2-test.go.tmpl
// ************************************************************
package codec
// Increase codecoverage by covering all the codecgen paths, in fast-path and gen-helper.go....
//
// Add:
// - test file for creating a mammoth generated file as _mammoth_generated.go
// - generate a second mammoth files in a different file: mammoth2_generated_test.go
// - mammoth-test.go.tmpl will do this
// - run codecgen on it, into mammoth2_codecgen_generated_test.go (no build tags)
// - as part of TestMammoth, run it also
// - this will cover all the codecgen, gen-helper, etc in one full run
// - check in mammoth* files into github also
// - then
//
// Now, add some types:
// - some that implement BinaryMarshal, TextMarshal, JSONMarshal, and one that implements none of it
// - create a wrapper type that includes TestMammoth2, with it in slices, and maps, and the custom types
// - this wrapper object is what we work encode/decode (so that the codecgen methods are called)
// import "encoding/binary"
import "fmt"
type TestMammoth2 struct {
{{range .Values }}{{if .Primitive }}{{/*
*/}}{{ .MethodNamePfx "F" true }} {{ .Primitive }}
{{ .MethodNamePfx "Fptr" true }} *{{ .Primitive }}
{{end}}{{end}}
{{range .Values }}{{if not .Primitive }}{{if not .MapKey }}{{/*
*/}}{{ .MethodNamePfx "F" false }} []{{ .Elem }}
{{ .MethodNamePfx "Fptr" false }} *[]{{ .Elem }}
{{end}}{{end}}{{end}}
{{range .Values }}{{if not .Primitive }}{{if .MapKey }}{{/*
*/}}{{ .MethodNamePfx "F" false }} map[{{ .MapKey }}]{{ .Elem }}
{{ .MethodNamePfx "Fptr" false }} *map[{{ .MapKey }}]{{ .Elem }}
{{end}}{{end}}{{end}}
}
// -----------
type testMammoth2Binary uint64
func (x testMammoth2Binary) MarshalBinary() (data []byte, err error) {
data = make([]byte, 8)
bigen.PutUint64(data, uint64(x))
return
}
func (x *testMammoth2Binary) UnmarshalBinary(data []byte) (err error) {
*x = testMammoth2Binary(bigen.Uint64(data))
return
}
type testMammoth2Text uint64
func (x testMammoth2Text) MarshalText() (data []byte, err error) {
data = []byte(fmt.Sprintf("%b", uint64(x)))
return
}
func (x *testMammoth2Text) UnmarshalText(data []byte) (err error) {
_, err = fmt.Sscanf(string(data), "%b", (*uint64)(x))
return
}
type testMammoth2Json uint64
func (x testMammoth2Json) MarshalJSON() (data []byte, err error) {
data = []byte(fmt.Sprintf("%v", uint64(x)))
return
}
func (x *testMammoth2Json) UnmarshalJSON(data []byte) (err error) {
_, err = fmt.Sscanf(string(data), "%v", (*uint64)(x))
return
}
type testMammoth2Basic [4]uint64
type TestMammoth2Wrapper struct {
V TestMammoth2
T testMammoth2Text
B testMammoth2Binary
J testMammoth2Json
C testMammoth2Basic
M map[testMammoth2Basic]TestMammoth2
L []TestMammoth2
A [4]int64
}

Some files were not shown because too many files have changed in this diff Show More