mirror of https://github.com/docker/cli.git
Merge pull request #1758 from thaJeztah/bump_some_deps
Update some dependencies
This commit is contained in:
commit
91339e1108
|
@ -43,10 +43,10 @@ github.com/grpc-ecosystem/grpc-gateway 1a03ca3bad1e1ebadaedd3abb76bc58d4ac8143b
|
||||||
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
||||||
github.com/hashicorp/golang-lru 0fb14efe8c47ae851c0034ed7a448854d3d34cf3
|
github.com/hashicorp/golang-lru 0fb14efe8c47ae851c0034ed7a448854d3d34cf3
|
||||||
github.com/hashicorp/go-version 23480c0
|
github.com/hashicorp/go-version 23480c0
|
||||||
github.com/imdario/mergo v0.3.6
|
github.com/imdario/mergo 7c29201646fa3de8506f701213473dd407f19646 # v0.3.7
|
||||||
github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 # v1.0
|
github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 # v1.0
|
||||||
github.com/json-iterator/go 1624edc4454b8682399def8740d46db5e4362ba4 # 1.1.5
|
github.com/json-iterator/go 0ff49de124c6f76f8494e194af75bde0f1a49a29 # 1.1.6
|
||||||
github.com/mattn/go-shellwords v1.0.3
|
github.com/mattn/go-shellwords a72fbe27a1b0ed0df2f02754945044ce1456608b # v1.0.5
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
||||||
github.com/Microsoft/hcsshim v0.8.6
|
github.com/Microsoft/hcsshim v0.8.6
|
||||||
github.com/Microsoft/go-winio v0.4.12
|
github.com/Microsoft/go-winio v0.4.12
|
||||||
|
@ -62,7 +62,7 @@ github.com/opencontainers/runc 2b18fe1d885ee5083ef9f0838fee39b62d653e30
|
||||||
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
|
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
|
||||||
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
|
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
|
||||||
github.com/peterbourgon/diskv 5f041e8faa004a95c88a202771f4cc3e991971e6 # v2.0.1
|
github.com/peterbourgon/diskv 5f041e8faa004a95c88a202771f4cc3e991971e6 # v2.0.1
|
||||||
github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9
|
github.com/pkg/errors ba968bfe8b2f7e042a574c888954fccecfa385b4 # v0.8.1
|
||||||
github.com/prometheus/client_golang c5b7fccd204277076155f10851dad72b76a49317 # v0.8.0
|
github.com/prometheus/client_golang c5b7fccd204277076155f10851dad72b76a49317 # v0.8.0
|
||||||
github.com/prometheus/client_model 6f3806018612930941127f2a7c6c453ba2c527d2
|
github.com/prometheus/client_model 6f3806018612930941127f2a7c6c453ba2c527d2
|
||||||
github.com/prometheus/common 7600349dcfe1abd18d72d3a1770870d9800a7801
|
github.com/prometheus/common 7600349dcfe1abd18d72d3a1770870d9800a7801
|
||||||
|
|
|
@ -13,6 +13,7 @@ It is ready for production use. [It is used in several projects by Docker, Googl
|
||||||
[![Build Status][1]][2]
|
[![Build Status][1]][2]
|
||||||
[![Coverage Status][7]][8]
|
[![Coverage Status][7]][8]
|
||||||
[![Sourcegraph][9]][10]
|
[![Sourcegraph][9]][10]
|
||||||
|
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield)
|
||||||
|
|
||||||
[1]: https://travis-ci.org/imdario/mergo.png
|
[1]: https://travis-ci.org/imdario/mergo.png
|
||||||
[2]: https://travis-ci.org/imdario/mergo
|
[2]: https://travis-ci.org/imdario/mergo
|
||||||
|
@ -27,7 +28,7 @@ It is ready for production use. [It is used in several projects by Docker, Googl
|
||||||
|
|
||||||
### Latest release
|
### Latest release
|
||||||
|
|
||||||
[Release v0.3.6](https://github.com/imdario/mergo/releases/tag/v0.3.6).
|
[Release v0.3.7](https://github.com/imdario/mergo/releases/tag/v0.3.7).
|
||||||
|
|
||||||
### Important note
|
### Important note
|
||||||
|
|
||||||
|
@ -217,6 +218,21 @@ If I can help you, you have an idea or you are using Mergo in your projects, don
|
||||||
|
|
||||||
Written by [Dario Castañé](http://dario.im).
|
Written by [Dario Castañé](http://dario.im).
|
||||||
|
|
||||||
|
## Top Contributors
|
||||||
|
|
||||||
|
[![0](https://sourcerer.io/fame/imdario/imdario/mergo/images/0)](https://sourcerer.io/fame/imdario/imdario/mergo/links/0)
|
||||||
|
[![1](https://sourcerer.io/fame/imdario/imdario/mergo/images/1)](https://sourcerer.io/fame/imdario/imdario/mergo/links/1)
|
||||||
|
[![2](https://sourcerer.io/fame/imdario/imdario/mergo/images/2)](https://sourcerer.io/fame/imdario/imdario/mergo/links/2)
|
||||||
|
[![3](https://sourcerer.io/fame/imdario/imdario/mergo/images/3)](https://sourcerer.io/fame/imdario/imdario/mergo/links/3)
|
||||||
|
[![4](https://sourcerer.io/fame/imdario/imdario/mergo/images/4)](https://sourcerer.io/fame/imdario/imdario/mergo/links/4)
|
||||||
|
[![5](https://sourcerer.io/fame/imdario/imdario/mergo/images/5)](https://sourcerer.io/fame/imdario/imdario/mergo/links/5)
|
||||||
|
[![6](https://sourcerer.io/fame/imdario/imdario/mergo/images/6)](https://sourcerer.io/fame/imdario/imdario/mergo/links/6)
|
||||||
|
[![7](https://sourcerer.io/fame/imdario/imdario/mergo/images/7)](https://sourcerer.io/fame/imdario/imdario/mergo/links/7)
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
|
[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
|
||||||
|
|
||||||
|
|
||||||
|
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_large)
|
||||||
|
|
|
@ -72,6 +72,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, conf
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
srcMap := src.Interface().(map[string]interface{})
|
srcMap := src.Interface().(map[string]interface{})
|
||||||
for key := range srcMap {
|
for key := range srcMap {
|
||||||
|
config.overwriteWithEmptyValue = true
|
||||||
srcValue := srcMap[key]
|
srcValue := srcMap[key]
|
||||||
fieldName := changeInitialCase(key, unicode.ToUpper)
|
fieldName := changeInitialCase(key, unicode.ToUpper)
|
||||||
dstElement := dst.FieldByName(fieldName)
|
dstElement := dst.FieldByName(fieldName)
|
||||||
|
|
|
@ -29,6 +29,7 @@ type Config struct {
|
||||||
Overwrite bool
|
Overwrite bool
|
||||||
AppendSlice bool
|
AppendSlice bool
|
||||||
Transformers Transformers
|
Transformers Transformers
|
||||||
|
overwriteWithEmptyValue bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Transformers interface {
|
type Transformers interface {
|
||||||
|
@ -40,6 +41,8 @@ type Transformers interface {
|
||||||
// short circuiting on recursive types.
|
// short circuiting on recursive types.
|
||||||
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
|
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
|
||||||
overwrite := config.Overwrite
|
overwrite := config.Overwrite
|
||||||
|
overwriteWithEmptySrc := config.overwriteWithEmptyValue
|
||||||
|
config.overwriteWithEmptyValue = false
|
||||||
|
|
||||||
if !src.IsValid() {
|
if !src.IsValid() {
|
||||||
return
|
return
|
||||||
|
@ -74,7 +77,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
|
if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) {
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,7 +128,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||||
dstSlice = reflect.ValueOf(dstElement.Interface())
|
dstSlice = reflect.ValueOf(dstElement.Interface())
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
|
if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
|
||||||
dstSlice = srcSlice
|
dstSlice = srcSlice
|
||||||
} else if config.AppendSlice {
|
} else if config.AppendSlice {
|
||||||
if srcSlice.Type() != dstSlice.Type() {
|
if srcSlice.Type() != dstSlice.Type() {
|
||||||
|
@ -136,7 +139,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||||
dst.SetMapIndex(key, dstSlice)
|
dst.SetMapIndex(key, dstSlice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if dstElement.IsValid() && reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map {
|
if dstElement.IsValid() && !isEmptyValue(dstElement) && (reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map || reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +154,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||||
if !dst.CanSet() {
|
if !dst.CanSet() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
|
if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
} else if config.AppendSlice {
|
} else if config.AppendSlice {
|
||||||
if src.Type() != dst.Type() {
|
if src.Type() != dst.Type() {
|
||||||
|
@ -191,7 +194,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
|
if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) {
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,6 @@ A high-performance 100% compatible drop-in replacement of "encoding/json"
|
||||||
|
|
||||||
You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go)
|
You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go)
|
||||||
|
|
||||||
```
|
|
||||||
Go开发者们请加入我们,滴滴出行平台技术部 taowen@didichuxing.com
|
|
||||||
```
|
|
||||||
|
|
||||||
# Benchmark
|
# Benchmark
|
||||||
|
|
||||||
![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png)
|
![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png)
|
||||||
|
|
|
@ -312,6 +312,10 @@ func (codec *directAnyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
|
|
||||||
func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
any := *(*Any)(ptr)
|
any := *(*Any)(ptr)
|
||||||
|
if any == nil {
|
||||||
|
stream.WriteNil()
|
||||||
|
return
|
||||||
|
}
|
||||||
any.WriteTo(stream)
|
any.WriteTo(stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,14 +77,12 @@ func (iter *Iterator) ReadFloat32() (ret float32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readPositiveFloat32() (ret float32) {
|
func (iter *Iterator) readPositiveFloat32() (ret float32) {
|
||||||
value := uint64(0)
|
|
||||||
c := byte(' ')
|
|
||||||
i := iter.head
|
i := iter.head
|
||||||
// first char
|
// first char
|
||||||
if i == iter.tail {
|
if i == iter.tail {
|
||||||
return iter.readFloat32SlowPath()
|
return iter.readFloat32SlowPath()
|
||||||
}
|
}
|
||||||
c = iter.buf[i]
|
c := iter.buf[i]
|
||||||
i++
|
i++
|
||||||
ind := floatDigits[c]
|
ind := floatDigits[c]
|
||||||
switch ind {
|
switch ind {
|
||||||
|
@ -107,7 +105,7 @@ func (iter *Iterator) readPositiveFloat32() (ret float32) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value = uint64(ind)
|
value := uint64(ind)
|
||||||
// chars before dot
|
// chars before dot
|
||||||
non_decimal_loop:
|
non_decimal_loop:
|
||||||
for ; i < iter.tail; i++ {
|
for ; i < iter.tail; i++ {
|
||||||
|
@ -145,9 +143,7 @@ non_decimal_loop:
|
||||||
}
|
}
|
||||||
// too many decimal places
|
// too many decimal places
|
||||||
return iter.readFloat32SlowPath()
|
return iter.readFloat32SlowPath()
|
||||||
case invalidCharForNumber:
|
case invalidCharForNumber, dotInNumber:
|
||||||
fallthrough
|
|
||||||
case dotInNumber:
|
|
||||||
return iter.readFloat32SlowPath()
|
return iter.readFloat32SlowPath()
|
||||||
}
|
}
|
||||||
decimalPlaces++
|
decimalPlaces++
|
||||||
|
@ -218,14 +214,12 @@ func (iter *Iterator) ReadFloat64() (ret float64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readPositiveFloat64() (ret float64) {
|
func (iter *Iterator) readPositiveFloat64() (ret float64) {
|
||||||
value := uint64(0)
|
|
||||||
c := byte(' ')
|
|
||||||
i := iter.head
|
i := iter.head
|
||||||
// first char
|
// first char
|
||||||
if i == iter.tail {
|
if i == iter.tail {
|
||||||
return iter.readFloat64SlowPath()
|
return iter.readFloat64SlowPath()
|
||||||
}
|
}
|
||||||
c = iter.buf[i]
|
c := iter.buf[i]
|
||||||
i++
|
i++
|
||||||
ind := floatDigits[c]
|
ind := floatDigits[c]
|
||||||
switch ind {
|
switch ind {
|
||||||
|
@ -248,7 +242,7 @@ func (iter *Iterator) readPositiveFloat64() (ret float64) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value = uint64(ind)
|
value := uint64(ind)
|
||||||
// chars before dot
|
// chars before dot
|
||||||
non_decimal_loop:
|
non_decimal_loop:
|
||||||
for ; i < iter.tail; i++ {
|
for ; i < iter.tail; i++ {
|
||||||
|
@ -286,9 +280,7 @@ non_decimal_loop:
|
||||||
}
|
}
|
||||||
// too many decimal places
|
// too many decimal places
|
||||||
return iter.readFloat64SlowPath()
|
return iter.readFloat64SlowPath()
|
||||||
case invalidCharForNumber:
|
case invalidCharForNumber, dotInNumber:
|
||||||
fallthrough
|
|
||||||
case dotInNumber:
|
|
||||||
return iter.readFloat64SlowPath()
|
return iter.readFloat64SlowPath()
|
||||||
}
|
}
|
||||||
decimalPlaces++
|
decimalPlaces++
|
||||||
|
|
|
@ -2,12 +2,22 @@
|
||||||
|
|
||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
func (iter *Iterator) skipNumber() {
|
func (iter *Iterator) skipNumber() {
|
||||||
if !iter.trySkipNumber() {
|
if !iter.trySkipNumber() {
|
||||||
iter.unreadByte()
|
iter.unreadByte()
|
||||||
iter.ReadFloat32()
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
iter.ReadFloat64()
|
||||||
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
iter.Error = nil
|
||||||
|
iter.ReadBigFloat()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -338,7 +338,7 @@ func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
|
||||||
for i := 0; i < structType.NumField(); i++ {
|
for i := 0; i < structType.NumField(); i++ {
|
||||||
field := structType.Field(i)
|
field := structType.Field(i)
|
||||||
tag, hastag := field.Tag().Lookup(ctx.getTagKey())
|
tag, hastag := field.Tag().Lookup(ctx.getTagKey())
|
||||||
if ctx.onlyTaggedField && !hastag {
|
if ctx.onlyTaggedField && !hastag && !field.Anonymous() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tagParts := strings.Split(tag, ",")
|
tagParts := strings.Split(tag, ",")
|
||||||
|
|
|
@ -64,14 +64,26 @@ func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
|
||||||
return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
|
return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
|
||||||
default:
|
default:
|
||||||
ptrType := reflect2.PtrTo(typ)
|
ptrType := reflect2.PtrTo(typ)
|
||||||
if ptrType.Implements(textMarshalerType) {
|
if ptrType.Implements(unmarshalerType) {
|
||||||
|
return &referenceDecoder{
|
||||||
|
&unmarshalerDecoder{
|
||||||
|
valType: ptrType,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if typ.Implements(unmarshalerType) {
|
||||||
|
return &unmarshalerDecoder{
|
||||||
|
valType: typ,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ptrType.Implements(textUnmarshalerType) {
|
||||||
return &referenceDecoder{
|
return &referenceDecoder{
|
||||||
&textUnmarshalerDecoder{
|
&textUnmarshalerDecoder{
|
||||||
valType: ptrType,
|
valType: ptrType,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if typ.Implements(textMarshalerType) {
|
if typ.Implements(textUnmarshalerType) {
|
||||||
return &textUnmarshalerDecoder{
|
return &textUnmarshalerDecoder{
|
||||||
valType: typ,
|
valType: typ,
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,8 +93,7 @@ func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteNil()
|
stream.WriteNil()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
marshaler := obj.(json.Marshaler)
|
bytes, err := json.Marshal(obj)
|
||||||
bytes, err := marshaler.MarshalJSON()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stream.Error = err
|
stream.Error = err
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -21,13 +22,17 @@ func isSpace(r rune) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func replaceEnv(s string) string {
|
func replaceEnv(getenv func(string) string, s string) string {
|
||||||
|
if getenv == nil {
|
||||||
|
getenv = os.Getenv
|
||||||
|
}
|
||||||
|
|
||||||
return envRe.ReplaceAllStringFunc(s, func(s string) string {
|
return envRe.ReplaceAllStringFunc(s, func(s string) string {
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
if s[0] == '{' {
|
if s[0] == '{' {
|
||||||
s = s[1 : len(s)-1]
|
s = s[1 : len(s)-1]
|
||||||
}
|
}
|
||||||
return os.Getenv(s)
|
return getenv(s)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,16 +40,24 @@ type Parser struct {
|
||||||
ParseEnv bool
|
ParseEnv bool
|
||||||
ParseBacktick bool
|
ParseBacktick bool
|
||||||
Position int
|
Position int
|
||||||
|
|
||||||
|
// If ParseEnv is true, use this for getenv.
|
||||||
|
// If nil, use os.Getenv.
|
||||||
|
Getenv func(string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewParser() *Parser {
|
func NewParser() *Parser {
|
||||||
return &Parser{ParseEnv, ParseBacktick, 0}
|
return &Parser{
|
||||||
|
ParseEnv: ParseEnv,
|
||||||
|
ParseBacktick: ParseBacktick,
|
||||||
|
Position: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) Parse(line string) ([]string, error) {
|
func (p *Parser) Parse(line string) ([]string, error) {
|
||||||
args := []string{}
|
args := []string{}
|
||||||
buf := ""
|
buf := ""
|
||||||
var escaped, doubleQuoted, singleQuoted, backQuote bool
|
var escaped, doubleQuoted, singleQuoted, backQuote, dollarQuote bool
|
||||||
backtick := ""
|
backtick := ""
|
||||||
|
|
||||||
pos := -1
|
pos := -1
|
||||||
|
@ -68,12 +81,12 @@ loop:
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSpace(r) {
|
if isSpace(r) {
|
||||||
if singleQuoted || doubleQuoted || backQuote {
|
if singleQuoted || doubleQuoted || backQuote || dollarQuote {
|
||||||
buf += string(r)
|
buf += string(r)
|
||||||
backtick += string(r)
|
backtick += string(r)
|
||||||
} else if got {
|
} else if got {
|
||||||
if p.ParseEnv {
|
if p.ParseEnv {
|
||||||
buf = replaceEnv(buf)
|
buf = replaceEnv(p.Getenv, buf)
|
||||||
}
|
}
|
||||||
args = append(args, buf)
|
args = append(args, buf)
|
||||||
buf = ""
|
buf = ""
|
||||||
|
@ -84,7 +97,7 @@ loop:
|
||||||
|
|
||||||
switch r {
|
switch r {
|
||||||
case '`':
|
case '`':
|
||||||
if !singleQuoted && !doubleQuoted {
|
if !singleQuoted && !doubleQuoted && !dollarQuote {
|
||||||
if p.ParseBacktick {
|
if p.ParseBacktick {
|
||||||
if backQuote {
|
if backQuote {
|
||||||
out, err := shellRun(backtick)
|
out, err := shellRun(backtick)
|
||||||
|
@ -100,18 +113,55 @@ loop:
|
||||||
backtick = ""
|
backtick = ""
|
||||||
backQuote = !backQuote
|
backQuote = !backQuote
|
||||||
}
|
}
|
||||||
|
case ')':
|
||||||
|
if !singleQuoted && !doubleQuoted && !backQuote {
|
||||||
|
if p.ParseBacktick {
|
||||||
|
if dollarQuote {
|
||||||
|
out, err := shellRun(backtick)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if r == ')' {
|
||||||
|
buf = buf[:len(buf)-len(backtick)-2] + out
|
||||||
|
} else {
|
||||||
|
buf = buf[:len(buf)-len(backtick)-1] + out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backtick = ""
|
||||||
|
dollarQuote = !dollarQuote
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
backtick = ""
|
||||||
|
dollarQuote = !dollarQuote
|
||||||
|
}
|
||||||
|
case '(':
|
||||||
|
if !singleQuoted && !doubleQuoted && !backQuote {
|
||||||
|
if !dollarQuote && strings.HasSuffix(buf, "$") {
|
||||||
|
dollarQuote = true
|
||||||
|
buf += "("
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("invalid command line string")
|
||||||
|
}
|
||||||
|
}
|
||||||
case '"':
|
case '"':
|
||||||
if !singleQuoted {
|
if !singleQuoted && !dollarQuote {
|
||||||
doubleQuoted = !doubleQuoted
|
doubleQuoted = !doubleQuoted
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
case '\'':
|
case '\'':
|
||||||
if !doubleQuoted {
|
if !doubleQuoted && !dollarQuote {
|
||||||
singleQuoted = !singleQuoted
|
singleQuoted = !singleQuoted
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
case ';', '&', '|', '<', '>':
|
case ';', '&', '|', '<', '>':
|
||||||
if !(escaped || singleQuoted || doubleQuoted || backQuote) {
|
if !(escaped || singleQuoted || doubleQuoted || backQuote) {
|
||||||
|
if r == '>' && len(buf) > 0 {
|
||||||
|
if c := buf[0]; '0' <= c && c <= '9' {
|
||||||
|
i -= 1
|
||||||
|
got = false
|
||||||
|
}
|
||||||
|
}
|
||||||
pos = i
|
pos = i
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
|
@ -119,19 +169,19 @@ loop:
|
||||||
|
|
||||||
got = true
|
got = true
|
||||||
buf += string(r)
|
buf += string(r)
|
||||||
if backQuote {
|
if backQuote || dollarQuote {
|
||||||
backtick += string(r)
|
backtick += string(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if got {
|
if got {
|
||||||
if p.ParseEnv {
|
if p.ParseEnv {
|
||||||
buf = replaceEnv(buf)
|
buf = replaceEnv(p.Getenv, buf)
|
||||||
}
|
}
|
||||||
args = append(args, buf)
|
args = append(args, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if escaped || singleQuoted || doubleQuoted || backQuote {
|
if escaped || singleQuoted || doubleQuoted || backQuote || dollarQuote {
|
||||||
return nil, errors.New("invalid command line string")
|
return nil, errors.New("invalid command line string")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
// +build !go1.6
|
||||||
|
|
||||||
|
package shellwords
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func shellRun(line string) (string, error) {
|
||||||
|
var b []byte
|
||||||
|
var err error
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
b, err = exec.Command(os.Getenv("COMSPEC"), "/c", line).Output()
|
||||||
|
} else {
|
||||||
|
b, err = exec.Command(os.Getenv("SHELL"), "-c", line).Output()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(string(b)), nil
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// +build !windows
|
// +build !windows,go1.6
|
||||||
|
|
||||||
package shellwords
|
package shellwords
|
||||||
|
|
||||||
|
@ -13,6 +13,9 @@ func shellRun(line string) (string, error) {
|
||||||
shell := os.Getenv("SHELL")
|
shell := os.Getenv("SHELL")
|
||||||
b, err := exec.Command(shell, "-c", line).Output()
|
b, err := exec.Command(shell, "-c", line).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if eerr, ok := err.(*exec.ExitError); ok {
|
||||||
|
b = eerr.Stderr
|
||||||
|
}
|
||||||
return "", errors.New(err.Error() + ":" + string(b))
|
return "", errors.New(err.Error() + ":" + string(b))
|
||||||
}
|
}
|
||||||
return strings.TrimSpace(string(b)), nil
|
return strings.TrimSpace(string(b)), nil
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build windows,go1.6
|
||||||
|
|
||||||
package shellwords
|
package shellwords
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -11,6 +13,9 @@ func shellRun(line string) (string, error) {
|
||||||
shell := os.Getenv("COMSPEC")
|
shell := os.Getenv("COMSPEC")
|
||||||
b, err := exec.Command(shell, "/c", line).Output()
|
b, err := exec.Command(shell, "/c", line).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if eerr, ok := err.(*exec.ExitError); ok {
|
||||||
|
b = eerr.Stderr
|
||||||
|
}
|
||||||
return "", errors.New(err.Error() + ":" + string(b))
|
return "", errors.New(err.Error() + ":" + string(b))
|
||||||
}
|
}
|
||||||
return strings.TrimSpace(string(b)), nil
|
return strings.TrimSpace(string(b)), nil
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors)
|
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
|
||||||
|
|
||||||
Package errors provides simple error handling primitives.
|
Package errors provides simple error handling primitives.
|
||||||
|
|
||||||
|
@ -47,6 +47,6 @@ We welcome pull requests, bug fixes and issue reports. With that said, the bar f
|
||||||
|
|
||||||
Before proposing a change, please discuss your change by raising an issue.
|
Before proposing a change, please discuss your change by raising an issue.
|
||||||
|
|
||||||
## Licence
|
## License
|
||||||
|
|
||||||
BSD-2-Clause
|
BSD-2-Clause
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// which applied recursively up the call stack results in error reports
|
// which when applied recursively up the call stack results in error reports
|
||||||
// without context or debugging information. The errors package allows
|
// without context or debugging information. The errors package allows
|
||||||
// programmers to add context to the failure path in their code in a way
|
// programmers to add context to the failure path in their code in a way
|
||||||
// that does not destroy the original value of the error.
|
// that does not destroy the original value of the error.
|
||||||
|
@ -15,16 +15,17 @@
|
||||||
//
|
//
|
||||||
// The errors.Wrap function returns a new error that adds context to the
|
// The errors.Wrap function returns a new error that adds context to the
|
||||||
// original error by recording a stack trace at the point Wrap is called,
|
// original error by recording a stack trace at the point Wrap is called,
|
||||||
// and the supplied message. For example
|
// together with the supplied message. For example
|
||||||
//
|
//
|
||||||
// _, err := ioutil.ReadAll(r)
|
// _, err := ioutil.ReadAll(r)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return errors.Wrap(err, "read failed")
|
// return errors.Wrap(err, "read failed")
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// If additional control is required the errors.WithStack and errors.WithMessage
|
// If additional control is required, the errors.WithStack and
|
||||||
// functions destructure errors.Wrap into its component operations of annotating
|
// errors.WithMessage functions destructure errors.Wrap into its component
|
||||||
// an error with a stack trace and an a message, respectively.
|
// operations: annotating an error with a stack trace and with a message,
|
||||||
|
// respectively.
|
||||||
//
|
//
|
||||||
// Retrieving the cause of an error
|
// Retrieving the cause of an error
|
||||||
//
|
//
|
||||||
|
@ -38,7 +39,7 @@
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
|
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
|
||||||
// the topmost error which does not implement causer, which is assumed to be
|
// the topmost error that does not implement causer, which is assumed to be
|
||||||
// the original cause. For example:
|
// the original cause. For example:
|
||||||
//
|
//
|
||||||
// switch err := errors.Cause(err).(type) {
|
// switch err := errors.Cause(err).(type) {
|
||||||
|
@ -48,16 +49,16 @@
|
||||||
// // unknown error
|
// // unknown error
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// causer interface is not exported by this package, but is considered a part
|
// Although the causer interface is not exported by this package, it is
|
||||||
// of stable public API.
|
// considered a part of its stable public interface.
|
||||||
//
|
//
|
||||||
// Formatted printing of errors
|
// Formatted printing of errors
|
||||||
//
|
//
|
||||||
// All error values returned from this package implement fmt.Formatter and can
|
// All error values returned from this package implement fmt.Formatter and can
|
||||||
// be formatted by the fmt package. The following verbs are supported
|
// be formatted by the fmt package. The following verbs are supported:
|
||||||
//
|
//
|
||||||
// %s print the error. If the error has a Cause it will be
|
// %s print the error. If the error has a Cause it will be
|
||||||
// printed recursively
|
// printed recursively.
|
||||||
// %v see %s
|
// %v see %s
|
||||||
// %+v extended format. Each Frame of the error's StackTrace will
|
// %+v extended format. Each Frame of the error's StackTrace will
|
||||||
// be printed in detail.
|
// be printed in detail.
|
||||||
|
@ -65,13 +66,13 @@
|
||||||
// Retrieving the stack trace of an error or wrapper
|
// Retrieving the stack trace of an error or wrapper
|
||||||
//
|
//
|
||||||
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
|
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
|
||||||
// invoked. This information can be retrieved with the following interface.
|
// invoked. This information can be retrieved with the following interface:
|
||||||
//
|
//
|
||||||
// type stackTracer interface {
|
// type stackTracer interface {
|
||||||
// StackTrace() errors.StackTrace
|
// StackTrace() errors.StackTrace
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Where errors.StackTrace is defined as
|
// The returned errors.StackTrace type is defined as
|
||||||
//
|
//
|
||||||
// type StackTrace []Frame
|
// type StackTrace []Frame
|
||||||
//
|
//
|
||||||
|
@ -85,8 +86,8 @@
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// stackTracer interface is not exported by this package, but is considered a part
|
// Although the stackTracer interface is not exported by this package, it is
|
||||||
// of stable public API.
|
// considered a part of its stable public interface.
|
||||||
//
|
//
|
||||||
// See the documentation for Frame.Format for more details.
|
// See the documentation for Frame.Format for more details.
|
||||||
package errors
|
package errors
|
||||||
|
@ -192,7 +193,7 @@ func Wrap(err error, message string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapf returns an error annotating err with a stack trace
|
// Wrapf returns an error annotating err with a stack trace
|
||||||
// at the point Wrapf is call, and the format specifier.
|
// at the point Wrapf is called, and the format specifier.
|
||||||
// If err is nil, Wrapf returns nil.
|
// If err is nil, Wrapf returns nil.
|
||||||
func Wrapf(err error, format string, args ...interface{}) error {
|
func Wrapf(err error, format string, args ...interface{}) error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -220,6 +221,18 @@ func WithMessage(err error, message string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithMessagef annotates err with the format specifier.
|
||||||
|
// If err is nil, WithMessagef returns nil.
|
||||||
|
func WithMessagef(err error, format string, args ...interface{}) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &withMessage{
|
||||||
|
cause: err,
|
||||||
|
msg: fmt.Sprintf(format, args...),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type withMessage struct {
|
type withMessage struct {
|
||||||
cause error
|
cause error
|
||||||
msg string
|
msg string
|
||||||
|
|
|
@ -46,7 +46,8 @@ func (f Frame) line() int {
|
||||||
//
|
//
|
||||||
// Format accepts flags that alter the printing of some verbs, as follows:
|
// Format accepts flags that alter the printing of some verbs, as follows:
|
||||||
//
|
//
|
||||||
// %+s path of source file relative to the compile time GOPATH
|
// %+s function name and path of source file relative to the compile time
|
||||||
|
// GOPATH separated by \n\t (<funcname>\n\t<path>)
|
||||||
// %+v equivalent to %+s:%d
|
// %+v equivalent to %+s:%d
|
||||||
func (f Frame) Format(s fmt.State, verb rune) {
|
func (f Frame) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
|
@ -79,6 +80,14 @@ func (f Frame) Format(s fmt.State, verb rune) {
|
||||||
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
|
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
|
||||||
type StackTrace []Frame
|
type StackTrace []Frame
|
||||||
|
|
||||||
|
// Format formats the stack of Frames according to the fmt.Formatter interface.
|
||||||
|
//
|
||||||
|
// %s lists source files for each Frame in the stack
|
||||||
|
// %v lists the source file and line number for each Frame in the stack
|
||||||
|
//
|
||||||
|
// Format accepts flags that alter the printing of some verbs, as follows:
|
||||||
|
//
|
||||||
|
// %+v Prints filename, function, and line number for each Frame in the stack.
|
||||||
func (st StackTrace) Format(s fmt.State, verb rune) {
|
func (st StackTrace) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 'v':
|
case 'v':
|
||||||
|
@ -136,43 +145,3 @@ func funcname(name string) string {
|
||||||
i = strings.Index(name, ".")
|
i = strings.Index(name, ".")
|
||||||
return name[i+1:]
|
return name[i+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func trimGOPATH(name, file string) string {
|
|
||||||
// Here we want to get the source file path relative to the compile time
|
|
||||||
// GOPATH. As of Go 1.6.x there is no direct way to know the compiled
|
|
||||||
// GOPATH at runtime, but we can infer the number of path segments in the
|
|
||||||
// GOPATH. We note that fn.Name() returns the function name qualified by
|
|
||||||
// the import path, which does not include the GOPATH. Thus we can trim
|
|
||||||
// segments from the beginning of the file path until the number of path
|
|
||||||
// separators remaining is one more than the number of path separators in
|
|
||||||
// the function name. For example, given:
|
|
||||||
//
|
|
||||||
// GOPATH /home/user
|
|
||||||
// file /home/user/src/pkg/sub/file.go
|
|
||||||
// fn.Name() pkg/sub.Type.Method
|
|
||||||
//
|
|
||||||
// We want to produce:
|
|
||||||
//
|
|
||||||
// pkg/sub/file.go
|
|
||||||
//
|
|
||||||
// From this we can easily see that fn.Name() has one less path separator
|
|
||||||
// than our desired output. We count separators from the end of the file
|
|
||||||
// path until it finds two more than in the function name and then move
|
|
||||||
// one character forward to preserve the initial path segment without a
|
|
||||||
// leading separator.
|
|
||||||
const sep = "/"
|
|
||||||
goal := strings.Count(name, sep) + 2
|
|
||||||
i := len(file)
|
|
||||||
for n := 0; n < goal; n++ {
|
|
||||||
i = strings.LastIndex(file[:i], sep)
|
|
||||||
if i == -1 {
|
|
||||||
// not enough separators found, set i so that the slice expression
|
|
||||||
// below leaves file unmodified
|
|
||||||
i = -len(sep)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// get back to 0 or trim the leading separator
|
|
||||||
file = file[i+len(sep):]
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue