until stable: pin-dependency, update-vendor, update-bazel, lint-dep

This commit is contained in:
monopole
2021-03-08 13:28:13 -08:00
parent 6c9460f0b4
commit ba39d22e39
420 changed files with 142058 additions and 6408 deletions

View File

@@ -1,20 +0,0 @@
# OSX leaves these everywhere on SMB shares
._*
# Eclipse files
.classpath
.project
.settings/**
# Emacs save files
*~
# Vim-related files
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
# Go test binaries
*.test

View File

@@ -1,7 +0,0 @@
language: go
go:
- 1.3
- 1.4
script:
- go test
- go build

View File

@@ -1,50 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Sam Ghods
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,121 +0,0 @@
# YAML marshaling and unmarshaling support for Go
[![Build Status](https://travis-ci.org/ghodss/yaml.svg)](https://travis-ci.org/ghodss/yaml)
## Introduction
A wrapper around [go-yaml](https://github.com/go-yaml/yaml) designed to enable a better way of handling YAML when marshaling to and from structs.
In short, this library first converts YAML to JSON using go-yaml and then uses `json.Marshal` and `json.Unmarshal` to convert to or from the struct. This means that it effectively reuses the JSON struct tags as well as the custom JSON methods `MarshalJSON` and `UnmarshalJSON` unlike go-yaml. For a detailed overview of the rationale behind this method, [see this blog post](http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang/).
## Compatibility
This package uses [go-yaml](https://github.com/go-yaml/yaml) and therefore supports [everything go-yaml supports](https://github.com/go-yaml/yaml#compatibility).
## Caveats
**Caveat #1:** When using `yaml.Marshal` and `yaml.Unmarshal`, binary data should NOT be preceded with the `!!binary` YAML tag. If you do, go-yaml will convert the binary data from base64 to native binary data, which is not compatible with JSON. You can still use binary in your YAML files though - just store them without the `!!binary` tag and decode the base64 in your code (e.g. in the custom JSON methods `MarshalJSON` and `UnmarshalJSON`). This also has the benefit that your YAML and your JSON binary data will be decoded exactly the same way. As an example:
```
BAD:
exampleKey: !!binary gIGC
GOOD:
exampleKey: gIGC
... and decode the base64 data in your code.
```
**Caveat #2:** When using `YAMLToJSON` directly, maps with keys that are maps will result in an error since this is not supported by JSON. This error will occur in `Unmarshal` as well since you can't unmarshal map keys anyways since struct fields can't be keys.
## Installation and usage
To install, run:
```
$ go get github.com/ghodss/yaml
```
And import using:
```
import "github.com/ghodss/yaml"
```
Usage is very similar to the JSON library:
```go
package main
import (
"fmt"
"github.com/ghodss/yaml"
)
type Person struct {
Name string `json:"name"` // Affects YAML field names too.
Age int `json:"age"`
}
func main() {
// Marshal a Person struct to YAML.
p := Person{"John", 30}
y, err := yaml.Marshal(p)
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
fmt.Println(string(y))
/* Output:
age: 30
name: John
*/
// Unmarshal the YAML back into a Person struct.
var p2 Person
err = yaml.Unmarshal(y, &p2)
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
fmt.Println(p2)
/* Output:
{John 30}
*/
}
```
`yaml.YAMLToJSON` and `yaml.JSONToYAML` methods are also available:
```go
package main
import (
"fmt"
"github.com/ghodss/yaml"
)
func main() {
j := []byte(`{"name": "John", "age": 30}`)
y, err := yaml.JSONToYAML(j)
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
fmt.Println(string(y))
/* Output:
name: John
age: 30
*/
j2, err := yaml.YAMLToJSON(y)
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
fmt.Println(string(j2))
/* Output:
{"age":30,"name":"John"}
*/
}
```

View File

@@ -1,501 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package yaml
import (
"bytes"
"encoding"
"encoding/json"
"reflect"
"sort"
"strings"
"sync"
"unicode"
"unicode/utf8"
)
// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
// if it encounters an Unmarshaler, indirect stops and returns that.
// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
func indirect(v reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
// If v is a named type and is addressable,
// start with its address, so that if the type has pointer methods,
// we find them.
if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
v = v.Addr()
}
for {
// Load value from interface, but only if the result will be
// usefully addressable.
if v.Kind() == reflect.Interface && !v.IsNil() {
e := v.Elem()
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
v = e
continue
}
}
if v.Kind() != reflect.Ptr {
break
}
if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
break
}
if v.IsNil() {
if v.CanSet() {
v.Set(reflect.New(v.Type().Elem()))
} else {
v = reflect.New(v.Type().Elem())
}
}
if v.Type().NumMethod() > 0 {
if u, ok := v.Interface().(json.Unmarshaler); ok {
return u, nil, reflect.Value{}
}
if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
return nil, u, reflect.Value{}
}
}
v = v.Elem()
}
return nil, nil, v
}
// A field represents a single field found in a struct.
type field struct {
name string
nameBytes []byte // []byte(name)
equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent
tag bool
index []int
typ reflect.Type
omitEmpty bool
quoted bool
}
func fillField(f field) field {
f.nameBytes = []byte(f.name)
f.equalFold = foldFunc(f.nameBytes)
return f
}
// byName sorts field by name, breaking ties with depth,
// then breaking ties with "name came from json tag", then
// breaking ties with index sequence.
type byName []field
func (x byName) Len() int { return len(x) }
func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byName) Less(i, j int) bool {
if x[i].name != x[j].name {
return x[i].name < x[j].name
}
if len(x[i].index) != len(x[j].index) {
return len(x[i].index) < len(x[j].index)
}
if x[i].tag != x[j].tag {
return x[i].tag
}
return byIndex(x).Less(i, j)
}
// byIndex sorts field by index sequence.
type byIndex []field
func (x byIndex) Len() int { return len(x) }
func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byIndex) Less(i, j int) bool {
for k, xik := range x[i].index {
if k >= len(x[j].index) {
return false
}
if xik != x[j].index[k] {
return xik < x[j].index[k]
}
}
return len(x[i].index) < len(x[j].index)
}
// typeFields returns a list of fields that JSON should recognize for the given type.
// The algorithm is breadth-first search over the set of structs to include - the top struct
// and then any reachable anonymous structs.
func typeFields(t reflect.Type) []field {
// Anonymous fields to explore at the current level and the next.
current := []field{}
next := []field{{typ: t}}
// Count of queued names for current level and the next.
count := map[reflect.Type]int{}
nextCount := map[reflect.Type]int{}
// Types already visited at an earlier level.
visited := map[reflect.Type]bool{}
// Fields found.
var fields []field
for len(next) > 0 {
current, next = next, current[:0]
count, nextCount = nextCount, map[reflect.Type]int{}
for _, f := range current {
if visited[f.typ] {
continue
}
visited[f.typ] = true
// Scan f.typ for fields to include.
for i := 0; i < f.typ.NumField(); i++ {
sf := f.typ.Field(i)
if sf.PkgPath != "" { // unexported
continue
}
tag := sf.Tag.Get("json")
if tag == "-" {
continue
}
name, opts := parseTag(tag)
if !isValidTag(name) {
name = ""
}
index := make([]int, len(f.index)+1)
copy(index, f.index)
index[len(f.index)] = i
ft := sf.Type
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
// Follow pointer.
ft = ft.Elem()
}
// Record found field and index sequence.
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
tagged := name != ""
if name == "" {
name = sf.Name
}
fields = append(fields, fillField(field{
name: name,
tag: tagged,
index: index,
typ: ft,
omitEmpty: opts.Contains("omitempty"),
quoted: opts.Contains("string"),
}))
if count[f.typ] > 1 {
// If there were multiple instances, add a second,
// so that the annihilation code will see a duplicate.
// It only cares about the distinction between 1 or 2,
// so don't bother generating any more copies.
fields = append(fields, fields[len(fields)-1])
}
continue
}
// Record new anonymous struct to explore in next round.
nextCount[ft]++
if nextCount[ft] == 1 {
next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft}))
}
}
}
}
sort.Sort(byName(fields))
// Delete all fields that are hidden by the Go rules for embedded fields,
// except that fields with JSON tags are promoted.
// The fields are sorted in primary order of name, secondary order
// of field index length. Loop over names; for each name, delete
// hidden fields by choosing the one dominant field that survives.
out := fields[:0]
for advance, i := 0, 0; i < len(fields); i += advance {
// One iteration per name.
// Find the sequence of fields with the name of this first field.
fi := fields[i]
name := fi.name
for advance = 1; i+advance < len(fields); advance++ {
fj := fields[i+advance]
if fj.name != name {
break
}
}
if advance == 1 { // Only one field with this name
out = append(out, fi)
continue
}
dominant, ok := dominantField(fields[i : i+advance])
if ok {
out = append(out, dominant)
}
}
fields = out
sort.Sort(byIndex(fields))
return fields
}
// dominantField looks through the fields, all of which are known to
// have the same name, to find the single field that dominates the
// others using Go's embedding rules, modified by the presence of
// JSON tags. If there are multiple top-level fields, the boolean
// will be false: This condition is an error in Go and we skip all
// the fields.
func dominantField(fields []field) (field, bool) {
// The fields are sorted in increasing index-length order. The winner
// must therefore be one with the shortest index length. Drop all
// longer entries, which is easy: just truncate the slice.
length := len(fields[0].index)
tagged := -1 // Index of first tagged field.
for i, f := range fields {
if len(f.index) > length {
fields = fields[:i]
break
}
if f.tag {
if tagged >= 0 {
// Multiple tagged fields at the same level: conflict.
// Return no field.
return field{}, false
}
tagged = i
}
}
if tagged >= 0 {
return fields[tagged], true
}
// All remaining fields have the same length. If there's more than one,
// we have a conflict (two fields named "X" at the same level) and we
// return no field.
if len(fields) > 1 {
return field{}, false
}
return fields[0], true
}
var fieldCache struct {
sync.RWMutex
m map[reflect.Type][]field
}
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
func cachedTypeFields(t reflect.Type) []field {
fieldCache.RLock()
f := fieldCache.m[t]
fieldCache.RUnlock()
if f != nil {
return f
}
// Compute fields without lock.
// Might duplicate effort but won't hold other computations back.
f = typeFields(t)
if f == nil {
f = []field{}
}
fieldCache.Lock()
if fieldCache.m == nil {
fieldCache.m = map[reflect.Type][]field{}
}
fieldCache.m[t] = f
fieldCache.Unlock()
return f
}
func isValidTag(s string) bool {
if s == "" {
return false
}
for _, c := range s {
switch {
case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
// Backslash and quote chars are reserved, but
// otherwise any punctuation chars are allowed
// in a tag name.
default:
if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
return false
}
}
}
return true
}
const (
caseMask = ^byte(0x20) // Mask to ignore case in ASCII.
kelvin = '\u212a'
smallLongEss = '\u017f'
)
// foldFunc returns one of four different case folding equivalence
// functions, from most general (and slow) to fastest:
//
// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
// 3) asciiEqualFold, no special, but includes non-letters (including _)
// 4) simpleLetterEqualFold, no specials, no non-letters.
//
// The letters S and K are special because they map to 3 runes, not just 2:
// * S maps to s and to U+017F 'ſ' Latin small letter long s
// * k maps to K and to U+212A '' Kelvin sign
// See http://play.golang.org/p/tTxjOc0OGo
//
// The returned function is specialized for matching against s and
// should only be given s. It's not curried for performance reasons.
func foldFunc(s []byte) func(s, t []byte) bool {
nonLetter := false
special := false // special letter
for _, b := range s {
if b >= utf8.RuneSelf {
return bytes.EqualFold
}
upper := b & caseMask
if upper < 'A' || upper > 'Z' {
nonLetter = true
} else if upper == 'K' || upper == 'S' {
// See above for why these letters are special.
special = true
}
}
if special {
return equalFoldRight
}
if nonLetter {
return asciiEqualFold
}
return simpleLetterEqualFold
}
// equalFoldRight is a specialization of bytes.EqualFold when s is
// known to be all ASCII (including punctuation), but contains an 's',
// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
// See comments on foldFunc.
func equalFoldRight(s, t []byte) bool {
for _, sb := range s {
if len(t) == 0 {
return false
}
tb := t[0]
if tb < utf8.RuneSelf {
if sb != tb {
sbUpper := sb & caseMask
if 'A' <= sbUpper && sbUpper <= 'Z' {
if sbUpper != tb&caseMask {
return false
}
} else {
return false
}
}
t = t[1:]
continue
}
// sb is ASCII and t is not. t must be either kelvin
// sign or long s; sb must be s, S, k, or K.
tr, size := utf8.DecodeRune(t)
switch sb {
case 's', 'S':
if tr != smallLongEss {
return false
}
case 'k', 'K':
if tr != kelvin {
return false
}
default:
return false
}
t = t[size:]
}
if len(t) > 0 {
return false
}
return true
}
// asciiEqualFold is a specialization of bytes.EqualFold for use when
// s is all ASCII (but may contain non-letters) and contains no
// special-folding letters.
// See comments on foldFunc.
func asciiEqualFold(s, t []byte) bool {
if len(s) != len(t) {
return false
}
for i, sb := range s {
tb := t[i]
if sb == tb {
continue
}
if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
if sb&caseMask != tb&caseMask {
return false
}
} else {
return false
}
}
return true
}
// simpleLetterEqualFold is a specialization of bytes.EqualFold for
// use when s is all ASCII letters (no underscores, etc) and also
// doesn't contain 'k', 'K', 's', or 'S'.
// See comments on foldFunc.
func simpleLetterEqualFold(s, t []byte) bool {
if len(s) != len(t) {
return false
}
for i, b := range s {
if b&caseMask != t[i]&caseMask {
return false
}
}
return true
}
// tagOptions is the string following a comma in a struct field's "json"
// tag, or the empty string. It does not include the leading comma.
type tagOptions string
// parseTag splits a struct field's json tag into its name and
// comma-separated options.
func parseTag(tag string) (string, tagOptions) {
if idx := strings.Index(tag, ","); idx != -1 {
return tag[:idx], tagOptions(tag[idx+1:])
}
return tag, tagOptions("")
}
// Contains reports whether a comma-separated list of options
// contains a particular substr flag. substr must be surrounded by a
// string boundary or commas.
func (o tagOptions) Contains(optionName string) bool {
if len(o) == 0 {
return false
}
s := string(o)
for s != "" {
var next string
i := strings.Index(s, ",")
if i >= 0 {
s, next = s[:i], s[i+1:]
}
if s == optionName {
return true
}
s = next
}
return false
}

277
vendor/github.com/ghodss/yaml/yaml.go generated vendored
View File

@@ -1,277 +0,0 @@
package yaml
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"strconv"
"gopkg.in/yaml.v2"
)
// Marshals the object into JSON then converts JSON to YAML and returns the
// YAML.
func Marshal(o interface{}) ([]byte, error) {
j, err := json.Marshal(o)
if err != nil {
return nil, fmt.Errorf("error marshaling into JSON: %v", err)
}
y, err := JSONToYAML(j)
if err != nil {
return nil, fmt.Errorf("error converting JSON to YAML: %v", err)
}
return y, nil
}
// Converts YAML to JSON then uses JSON to unmarshal into an object.
func Unmarshal(y []byte, o interface{}) error {
vo := reflect.ValueOf(o)
j, err := yamlToJSON(y, &vo)
if err != nil {
return fmt.Errorf("error converting YAML to JSON: %v", err)
}
err = json.Unmarshal(j, o)
if err != nil {
return fmt.Errorf("error unmarshaling JSON: %v", err)
}
return nil
}
// Convert JSON to YAML.
func JSONToYAML(j []byte) ([]byte, error) {
// Convert the JSON to an object.
var jsonObj interface{}
// We are using yaml.Unmarshal here (instead of json.Unmarshal) because the
// Go JSON library doesn't try to pick the right number type (int, float,
// etc.) when unmarshalling to interface{}, it just picks float64
// universally. go-yaml does go through the effort of picking the right
// number type, so we can preserve number type throughout this process.
err := yaml.Unmarshal(j, &jsonObj)
if err != nil {
return nil, err
}
// Marshal this object into YAML.
return yaml.Marshal(jsonObj)
}
// Convert YAML to JSON. Since JSON is a subset of YAML, passing JSON through
// this method should be a no-op.
//
// Things YAML can do that are not supported by JSON:
// * In YAML you can have binary and null keys in your maps. These are invalid
// in JSON. (int and float keys are converted to strings.)
// * Binary data in YAML with the !!binary tag is not supported. If you want to
// use binary data with this library, encode the data as base64 as usual but do
// not use the !!binary tag in your YAML. This will ensure the original base64
// encoded data makes it all the way through to the JSON.
func YAMLToJSON(y []byte) ([]byte, error) {
return yamlToJSON(y, nil)
}
func yamlToJSON(y []byte, jsonTarget *reflect.Value) ([]byte, error) {
// Convert the YAML to an object.
var yamlObj interface{}
err := yaml.Unmarshal(y, &yamlObj)
if err != nil {
return nil, err
}
// YAML objects are not completely compatible with JSON objects (e.g. you
// can have non-string keys in YAML). So, convert the YAML-compatible object
// to a JSON-compatible object, failing with an error if irrecoverable
// incompatibilties happen along the way.
jsonObj, err := convertToJSONableObject(yamlObj, jsonTarget)
if err != nil {
return nil, err
}
// Convert this object to JSON and return the data.
return json.Marshal(jsonObj)
}
func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (interface{}, error) {
var err error
// Resolve jsonTarget to a concrete value (i.e. not a pointer or an
// interface). We pass decodingNull as false because we're not actually
// decoding into the value, we're just checking if the ultimate target is a
// string.
if jsonTarget != nil {
ju, tu, pv := indirect(*jsonTarget, false)
// We have a JSON or Text Umarshaler at this level, so we can't be trying
// to decode into a string.
if ju != nil || tu != nil {
jsonTarget = nil
} else {
jsonTarget = &pv
}
}
// If yamlObj is a number or a boolean, check if jsonTarget is a string -
// if so, coerce. Else return normal.
// If yamlObj is a map or array, find the field that each key is
// unmarshaling to, and when you recurse pass the reflect.Value for that
// field back into this function.
switch typedYAMLObj := yamlObj.(type) {
case map[interface{}]interface{}:
// JSON does not support arbitrary keys in a map, so we must convert
// these keys to strings.
//
// From my reading of go-yaml v2 (specifically the resolve function),
// keys can only have the types string, int, int64, float64, binary
// (unsupported), or null (unsupported).
strMap := make(map[string]interface{})
for k, v := range typedYAMLObj {
// Resolve the key to a string first.
var keyString string
switch typedKey := k.(type) {
case string:
keyString = typedKey
case int:
keyString = strconv.Itoa(typedKey)
case int64:
// go-yaml will only return an int64 as a key if the system
// architecture is 32-bit and the key's value is between 32-bit
// and 64-bit. Otherwise the key type will simply be int.
keyString = strconv.FormatInt(typedKey, 10)
case float64:
// Stolen from go-yaml to use the same conversion to string as
// the go-yaml library uses to convert float to string when
// Marshaling.
s := strconv.FormatFloat(typedKey, 'g', -1, 32)
switch s {
case "+Inf":
s = ".inf"
case "-Inf":
s = "-.inf"
case "NaN":
s = ".nan"
}
keyString = s
case bool:
if typedKey {
keyString = "true"
} else {
keyString = "false"
}
default:
return nil, fmt.Errorf("Unsupported map key of type: %s, key: %+#v, value: %+#v",
reflect.TypeOf(k), k, v)
}
// jsonTarget should be a struct or a map. If it's a struct, find
// the field it's going to map to and pass its reflect.Value. If
// it's a map, find the element type of the map and pass the
// reflect.Value created from that type. If it's neither, just pass
// nil - JSON conversion will error for us if it's a real issue.
if jsonTarget != nil {
t := *jsonTarget
if t.Kind() == reflect.Struct {
keyBytes := []byte(keyString)
// Find the field that the JSON library would use.
var f *field
fields := cachedTypeFields(t.Type())
for i := range fields {
ff := &fields[i]
if bytes.Equal(ff.nameBytes, keyBytes) {
f = ff
break
}
// Do case-insensitive comparison.
if f == nil && ff.equalFold(ff.nameBytes, keyBytes) {
f = ff
}
}
if f != nil {
// Find the reflect.Value of the most preferential
// struct field.
jtf := t.Field(f.index[0])
strMap[keyString], err = convertToJSONableObject(v, &jtf)
if err != nil {
return nil, err
}
continue
}
} else if t.Kind() == reflect.Map {
// Create a zero value of the map's element type to use as
// the JSON target.
jtv := reflect.Zero(t.Type().Elem())
strMap[keyString], err = convertToJSONableObject(v, &jtv)
if err != nil {
return nil, err
}
continue
}
}
strMap[keyString], err = convertToJSONableObject(v, nil)
if err != nil {
return nil, err
}
}
return strMap, nil
case []interface{}:
// We need to recurse into arrays in case there are any
// map[interface{}]interface{}'s inside and to convert any
// numbers to strings.
// If jsonTarget is a slice (which it really should be), find the
// thing it's going to map to. If it's not a slice, just pass nil
// - JSON conversion will error for us if it's a real issue.
var jsonSliceElemValue *reflect.Value
if jsonTarget != nil {
t := *jsonTarget
if t.Kind() == reflect.Slice {
// By default slices point to nil, but we need a reflect.Value
// pointing to a value of the slice type, so we create one here.
ev := reflect.Indirect(reflect.New(t.Type().Elem()))
jsonSliceElemValue = &ev
}
}
// Make and use a new array.
arr := make([]interface{}, len(typedYAMLObj))
for i, v := range typedYAMLObj {
arr[i], err = convertToJSONableObject(v, jsonSliceElemValue)
if err != nil {
return nil, err
}
}
return arr, nil
default:
// If the target type is a string and the YAML type is a number,
// convert the YAML type to a string.
if jsonTarget != nil && (*jsonTarget).Kind() == reflect.String {
// Based on my reading of go-yaml, it may return int, int64,
// float64, or uint64.
var s string
switch typedVal := typedYAMLObj.(type) {
case int:
s = strconv.FormatInt(int64(typedVal), 10)
case int64:
s = strconv.FormatInt(typedVal, 10)
case float64:
s = strconv.FormatFloat(typedVal, 'g', -1, 32)
case uint64:
s = strconv.FormatUint(typedVal, 10)
case bool:
if typedVal {
s = "true"
} else {
s = "false"
}
}
if len(s) > 0 {
yamlObj = interface{}(s)
}
}
return yamlObj, nil
}
return nil, nil
}

5
vendor/github.com/go-errors/errors/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,5 @@
language: go
go:
- "1.8.x"
- "1.10.x"

7
vendor/github.com/go-errors/errors/LICENSE.MIT generated vendored Normal file
View File

@@ -0,0 +1,7 @@
Copyright (c) 2015 Conrad Irwin <conrad@bugsnag.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

66
vendor/github.com/go-errors/errors/README.md generated vendored Normal file
View File

@@ -0,0 +1,66 @@
go-errors/errors
================
[![Build Status](https://travis-ci.org/go-errors/errors.svg?branch=master)](https://travis-ci.org/go-errors/errors)
Package errors adds stacktrace support to errors in go.
This is particularly useful when you want to understand the state of execution
when an error was returned unexpectedly.
It provides the type \*Error which implements the standard golang error
interface, so you can use this library interchangably with code that is
expecting a normal error return.
Usage
-----
Full documentation is available on
[godoc](https://godoc.org/github.com/go-errors/errors), but here's a simple
example:
```go
package crashy
import "github.com/go-errors/errors"
var Crashed = errors.Errorf("oh dear")
func Crash() error {
return errors.New(Crashed)
}
```
This can be called as follows:
```go
package main
import (
"crashy"
"fmt"
"github.com/go-errors/errors"
)
func main() {
err := crashy.Crash()
if err != nil {
if errors.Is(err, crashy.Crashed) {
fmt.Println(err.(*errors.Error).ErrorStack())
} else {
panic(err)
}
}
}
```
Meta-fu
-------
This package was original written to allow reporting to
[Bugsnag](https://bugsnag.com/) from
[bugsnag-go](https://github.com/bugsnag/bugsnag-go), but after I found similar
packages by Facebook and Dropbox, it was moved to one canonical location so
everyone can benefit.
This package is licensed under the MIT license, see LICENSE.MIT for details.

89
vendor/github.com/go-errors/errors/cover.out generated vendored Normal file
View File

@@ -0,0 +1,89 @@
mode: set
github.com/go-errors/errors/stackframe.go:27.51,30.25 2 1
github.com/go-errors/errors/stackframe.go:33.2,38.8 3 1
github.com/go-errors/errors/stackframe.go:30.25,32.3 1 0
github.com/go-errors/errors/stackframe.go:43.47,44.31 1 1
github.com/go-errors/errors/stackframe.go:47.2,47.48 1 1
github.com/go-errors/errors/stackframe.go:44.31,46.3 1 1
github.com/go-errors/errors/stackframe.go:52.42,56.16 3 1
github.com/go-errors/errors/stackframe.go:60.2,60.60 1 1
github.com/go-errors/errors/stackframe.go:56.16,58.3 1 0
github.com/go-errors/errors/stackframe.go:64.55,67.16 2 1
github.com/go-errors/errors/stackframe.go:71.2,72.61 2 1
github.com/go-errors/errors/stackframe.go:76.2,76.66 1 1
github.com/go-errors/errors/stackframe.go:67.16,69.3 1 0
github.com/go-errors/errors/stackframe.go:72.61,74.3 1 0
github.com/go-errors/errors/stackframe.go:79.56,91.63 3 1
github.com/go-errors/errors/stackframe.go:95.2,95.53 1 1
github.com/go-errors/errors/stackframe.go:100.2,101.18 2 1
github.com/go-errors/errors/stackframe.go:91.63,94.3 2 1
github.com/go-errors/errors/stackframe.go:95.53,98.3 2 1
github.com/go-errors/errors/error.go:70.32,73.23 2 1
github.com/go-errors/errors/error.go:80.2,85.3 3 1
github.com/go-errors/errors/error.go:74.2,75.10 1 1
github.com/go-errors/errors/error.go:76.2,77.28 1 1
github.com/go-errors/errors/error.go:92.43,95.23 2 1
github.com/go-errors/errors/error.go:104.2,109.3 3 1
github.com/go-errors/errors/error.go:96.2,97.11 1 1
github.com/go-errors/errors/error.go:98.2,99.10 1 1
github.com/go-errors/errors/error.go:100.2,101.28 1 1
github.com/go-errors/errors/error.go:115.39,117.19 1 1
github.com/go-errors/errors/error.go:121.2,121.29 1 1
github.com/go-errors/errors/error.go:125.2,125.43 1 1
github.com/go-errors/errors/error.go:129.2,129.14 1 1
github.com/go-errors/errors/error.go:117.19,119.3 1 1
github.com/go-errors/errors/error.go:121.29,123.3 1 1
github.com/go-errors/errors/error.go:125.43,127.3 1 1
github.com/go-errors/errors/error.go:135.53,137.2 1 1
github.com/go-errors/errors/error.go:140.34,142.2 1 1
github.com/go-errors/errors/error.go:146.34,149.42 2 1
github.com/go-errors/errors/error.go:153.2,153.20 1 1
github.com/go-errors/errors/error.go:149.42,151.3 1 1
github.com/go-errors/errors/error.go:158.39,160.2 1 1
github.com/go-errors/errors/error.go:164.46,165.23 1 1
github.com/go-errors/errors/error.go:173.2,173.19 1 1
github.com/go-errors/errors/error.go:165.23,168.32 2 1
github.com/go-errors/errors/error.go:168.32,170.4 1 1
github.com/go-errors/errors/error.go:177.37,178.42 1 1
github.com/go-errors/errors/error.go:181.2,181.41 1 1
github.com/go-errors/errors/error.go:178.42,180.3 1 1
github.com/go-errors/errors/parse_panic.go:10.39,12.2 1 1
github.com/go-errors/errors/parse_panic.go:16.46,24.34 5 1
github.com/go-errors/errors/parse_panic.go:70.2,70.43 1 1
github.com/go-errors/errors/parse_panic.go:73.2,73.55 1 0
github.com/go-errors/errors/parse_panic.go:24.34,27.23 2 1
github.com/go-errors/errors/parse_panic.go:27.23,28.42 1 1
github.com/go-errors/errors/parse_panic.go:28.42,31.5 2 1
github.com/go-errors/errors/parse_panic.go:31.6,33.5 1 0
github.com/go-errors/errors/parse_panic.go:35.5,35.29 1 1
github.com/go-errors/errors/parse_panic.go:35.29,36.86 1 1
github.com/go-errors/errors/parse_panic.go:36.86,38.5 1 1
github.com/go-errors/errors/parse_panic.go:40.5,40.32 1 1
github.com/go-errors/errors/parse_panic.go:40.32,41.18 1 1
github.com/go-errors/errors/parse_panic.go:45.4,46.46 2 1
github.com/go-errors/errors/parse_panic.go:51.4,53.23 2 1
github.com/go-errors/errors/parse_panic.go:57.4,58.18 2 1
github.com/go-errors/errors/parse_panic.go:62.4,63.17 2 1
github.com/go-errors/errors/parse_panic.go:41.18,43.10 2 1
github.com/go-errors/errors/parse_panic.go:46.46,49.5 2 1
github.com/go-errors/errors/parse_panic.go:53.23,55.5 1 0
github.com/go-errors/errors/parse_panic.go:58.18,60.5 1 0
github.com/go-errors/errors/parse_panic.go:63.17,65.10 2 1
github.com/go-errors/errors/parse_panic.go:70.43,72.3 1 1
github.com/go-errors/errors/parse_panic.go:80.85,82.29 2 1
github.com/go-errors/errors/parse_panic.go:85.2,85.15 1 1
github.com/go-errors/errors/parse_panic.go:88.2,90.63 2 1
github.com/go-errors/errors/parse_panic.go:94.2,94.53 1 1
github.com/go-errors/errors/parse_panic.go:99.2,101.36 2 1
github.com/go-errors/errors/parse_panic.go:105.2,106.15 2 1
github.com/go-errors/errors/parse_panic.go:109.2,112.49 3 1
github.com/go-errors/errors/parse_panic.go:116.2,117.16 2 1
github.com/go-errors/errors/parse_panic.go:121.2,126.8 1 1
github.com/go-errors/errors/parse_panic.go:82.29,84.3 1 0
github.com/go-errors/errors/parse_panic.go:85.15,87.3 1 1
github.com/go-errors/errors/parse_panic.go:90.63,93.3 2 1
github.com/go-errors/errors/parse_panic.go:94.53,97.3 2 1
github.com/go-errors/errors/parse_panic.go:101.36,103.3 1 0
github.com/go-errors/errors/parse_panic.go:106.15,108.3 1 0
github.com/go-errors/errors/parse_panic.go:112.49,114.3 1 1
github.com/go-errors/errors/parse_panic.go:117.16,119.3 1 0

217
vendor/github.com/go-errors/errors/error.go generated vendored Normal file
View File

@@ -0,0 +1,217 @@
// Package errors provides errors that have stack-traces.
//
// This is particularly useful when you want to understand the
// state of execution when an error was returned unexpectedly.
//
// It provides the type *Error which implements the standard
// golang error interface, so you can use this library interchangably
// with code that is expecting a normal error return.
//
// For example:
//
// package crashy
//
// import "github.com/go-errors/errors"
//
// var Crashed = errors.Errorf("oh dear")
//
// func Crash() error {
// return errors.New(Crashed)
// }
//
// This can be called as follows:
//
// package main
//
// import (
// "crashy"
// "fmt"
// "github.com/go-errors/errors"
// )
//
// func main() {
// err := crashy.Crash()
// if err != nil {
// if errors.Is(err, crashy.Crashed) {
// fmt.Println(err.(*errors.Error).ErrorStack())
// } else {
// panic(err)
// }
// }
// }
//
// This package was original written to allow reporting to Bugsnag,
// but after I found similar packages by Facebook and Dropbox, it
// was moved to one canonical location so everyone can benefit.
package errors
import (
"bytes"
"fmt"
"reflect"
"runtime"
)
// The maximum number of stackframes on any error.
var MaxStackDepth = 50
// Error is an error with an attached stacktrace. It can be used
// wherever the builtin error interface is expected.
type Error struct {
Err error
stack []uintptr
frames []StackFrame
prefix string
}
// New makes an Error from the given value. If that value is already an
// error then it will be used directly, if not, it will be passed to
// fmt.Errorf("%v"). The stacktrace will point to the line of code that
// called New.
func New(e interface{}) *Error {
var err error
switch e := e.(type) {
case error:
err = e
default:
err = fmt.Errorf("%v", e)
}
stack := make([]uintptr, MaxStackDepth)
length := runtime.Callers(2, stack[:])
return &Error{
Err: err,
stack: stack[:length],
}
}
// Wrap makes an Error from the given value. If that value is already an
// error then it will be used directly, if not, it will be passed to
// fmt.Errorf("%v"). The skip parameter indicates how far up the stack
// to start the stacktrace. 0 is from the current call, 1 from its caller, etc.
func Wrap(e interface{}, skip int) *Error {
var err error
switch e := e.(type) {
case *Error:
return e
case error:
err = e
default:
err = fmt.Errorf("%v", e)
}
stack := make([]uintptr, MaxStackDepth)
length := runtime.Callers(2+skip, stack[:])
return &Error{
Err: err,
stack: stack[:length],
}
}
// WrapPrefix makes an Error from the given value. If that value is already an
// error then it will be used directly, if not, it will be passed to
// fmt.Errorf("%v"). The prefix parameter is used to add a prefix to the
// error message when calling Error(). The skip parameter indicates how far
// up the stack to start the stacktrace. 0 is from the current call,
// 1 from its caller, etc.
func WrapPrefix(e interface{}, prefix string, skip int) *Error {
err := Wrap(e, 1+skip)
if err.prefix != "" {
prefix = fmt.Sprintf("%s: %s", prefix, err.prefix)
}
return &Error{
Err: err.Err,
stack: err.stack,
prefix: prefix,
}
}
// Is detects whether the error is equal to a given error. Errors
// are considered equal by this function if they are the same object,
// or if they both contain the same error inside an errors.Error.
func Is(e error, original error) bool {
if e == original {
return true
}
if e, ok := e.(*Error); ok {
return Is(e.Err, original)
}
if original, ok := original.(*Error); ok {
return Is(e, original.Err)
}
return false
}
// Errorf creates a new error with the given message. You can use it
// as a drop-in replacement for fmt.Errorf() to provide descriptive
// errors in return values.
func Errorf(format string, a ...interface{}) *Error {
return Wrap(fmt.Errorf(format, a...), 1)
}
// Error returns the underlying error's message.
func (err *Error) Error() string {
msg := err.Err.Error()
if err.prefix != "" {
msg = fmt.Sprintf("%s: %s", err.prefix, msg)
}
return msg
}
// Stack returns the callstack formatted the same way that go does
// in runtime/debug.Stack()
func (err *Error) Stack() []byte {
buf := bytes.Buffer{}
for _, frame := range err.StackFrames() {
buf.WriteString(frame.String())
}
return buf.Bytes()
}
// Callers satisfies the bugsnag ErrorWithCallerS() interface
// so that the stack can be read out.
func (err *Error) Callers() []uintptr {
return err.stack
}
// ErrorStack returns a string that contains both the
// error message and the callstack.
func (err *Error) ErrorStack() string {
return err.TypeName() + " " + err.Error() + "\n" + string(err.Stack())
}
// StackFrames returns an array of frames containing information about the
// stack.
func (err *Error) StackFrames() []StackFrame {
if err.frames == nil {
err.frames = make([]StackFrame, len(err.stack))
for i, pc := range err.stack {
err.frames[i] = NewStackFrame(pc)
}
}
return err.frames
}
// TypeName returns the type this error. e.g. *errors.stringError.
func (err *Error) TypeName() string {
if _, ok := err.Err.(uncaughtPanic); ok {
return "panic"
}
return reflect.TypeOf(err.Err).String()
}

127
vendor/github.com/go-errors/errors/parse_panic.go generated vendored Normal file
View File

@@ -0,0 +1,127 @@
package errors
import (
"strconv"
"strings"
)
type uncaughtPanic struct{ message string }
func (p uncaughtPanic) Error() string {
return p.message
}
// ParsePanic allows you to get an error object from the output of a go program
// that panicked. This is particularly useful with https://github.com/mitchellh/panicwrap.
func ParsePanic(text string) (*Error, error) {
lines := strings.Split(text, "\n")
state := "start"
var message string
var stack []StackFrame
for i := 0; i < len(lines); i++ {
line := lines[i]
if state == "start" {
if strings.HasPrefix(line, "panic: ") {
message = strings.TrimPrefix(line, "panic: ")
state = "seek"
} else {
return nil, Errorf("bugsnag.panicParser: Invalid line (no prefix): %s", line)
}
} else if state == "seek" {
if strings.HasPrefix(line, "goroutine ") && strings.HasSuffix(line, "[running]:") {
state = "parsing"
}
} else if state == "parsing" {
if line == "" {
state = "done"
break
}
createdBy := false
if strings.HasPrefix(line, "created by ") {
line = strings.TrimPrefix(line, "created by ")
createdBy = true
}
i++
if i >= len(lines) {
return nil, Errorf("bugsnag.panicParser: Invalid line (unpaired): %s", line)
}
frame, err := parsePanicFrame(line, lines[i], createdBy)
if err != nil {
return nil, err
}
stack = append(stack, *frame)
if createdBy {
state = "done"
break
}
}
}
if state == "done" || state == "parsing" {
return &Error{Err: uncaughtPanic{message}, frames: stack}, nil
}
return nil, Errorf("could not parse panic: %v", text)
}
// The lines we're passing look like this:
//
// main.(*foo).destruct(0xc208067e98)
// /0/go/src/github.com/bugsnag/bugsnag-go/pan/main.go:22 +0x151
func parsePanicFrame(name string, line string, createdBy bool) (*StackFrame, error) {
idx := strings.LastIndex(name, "(")
if idx == -1 && !createdBy {
return nil, Errorf("bugsnag.panicParser: Invalid line (no call): %s", name)
}
if idx != -1 {
name = name[:idx]
}
pkg := ""
if lastslash := strings.LastIndex(name, "/"); lastslash >= 0 {
pkg += name[:lastslash] + "/"
name = name[lastslash+1:]
}
if period := strings.Index(name, "."); period >= 0 {
pkg += name[:period]
name = name[period+1:]
}
name = strings.Replace(name, "·", ".", -1)
if !strings.HasPrefix(line, "\t") {
return nil, Errorf("bugsnag.panicParser: Invalid line (no tab): %s", line)
}
idx = strings.LastIndex(line, ":")
if idx == -1 {
return nil, Errorf("bugsnag.panicParser: Invalid line (no line number): %s", line)
}
file := line[1:idx]
number := line[idx+1:]
if idx = strings.Index(number, " +"); idx > -1 {
number = number[:idx]
}
lno, err := strconv.ParseInt(number, 10, 32)
if err != nil {
return nil, Errorf("bugsnag.panicParser: Invalid line (bad line number): %s", line)
}
return &StackFrame{
File: file,
LineNumber: int(lno),
Package: pkg,
Name: name,
}, nil
}

102
vendor/github.com/go-errors/errors/stackframe.go generated vendored Normal file
View File

@@ -0,0 +1,102 @@
package errors
import (
"bytes"
"fmt"
"io/ioutil"
"runtime"
"strings"
)
// A StackFrame contains all necessary information about to generate a line
// in a callstack.
type StackFrame struct {
// The path to the file containing this ProgramCounter
File string
// The LineNumber in that file
LineNumber int
// The Name of the function that contains this ProgramCounter
Name string
// The Package that contains this function
Package string
// The underlying ProgramCounter
ProgramCounter uintptr
}
// NewStackFrame popoulates a stack frame object from the program counter.
func NewStackFrame(pc uintptr) (frame StackFrame) {
frame = StackFrame{ProgramCounter: pc}
if frame.Func() == nil {
return
}
frame.Package, frame.Name = packageAndName(frame.Func())
// pc -1 because the program counters we use are usually return addresses,
// and we want to show the line that corresponds to the function call
frame.File, frame.LineNumber = frame.Func().FileLine(pc - 1)
return
}
// Func returns the function that contained this frame.
func (frame *StackFrame) Func() *runtime.Func {
if frame.ProgramCounter == 0 {
return nil
}
return runtime.FuncForPC(frame.ProgramCounter)
}
// String returns the stackframe formatted in the same way as go does
// in runtime/debug.Stack()
func (frame *StackFrame) String() string {
str := fmt.Sprintf("%s:%d (0x%x)\n", frame.File, frame.LineNumber, frame.ProgramCounter)
source, err := frame.SourceLine()
if err != nil {
return str
}
return str + fmt.Sprintf("\t%s: %s\n", frame.Name, source)
}
// SourceLine gets the line of code (from File and Line) of the original source if possible.
func (frame *StackFrame) SourceLine() (string, error) {
data, err := ioutil.ReadFile(frame.File)
if err != nil {
return "", New(err)
}
lines := bytes.Split(data, []byte{'\n'})
if frame.LineNumber <= 0 || frame.LineNumber >= len(lines) {
return "???", nil
}
// -1 because line-numbers are 1 based, but our array is 0 based
return string(bytes.Trim(lines[frame.LineNumber-1], " \t")), nil
}
func packageAndName(fn *runtime.Func) (string, string) {
name := fn.Name()
pkg := ""
// The name includes the path name to the package, which is unnecessary
// since the file name is already included. Plus, it has center dots.
// That is, we see
// runtime/debug.*T·ptrmethod
// and want
// *T.ptrmethod
// Since the package path might contains dots (e.g. code.google.com/...),
// we first remove the path prefix if there is one.
if lastslash := strings.LastIndex(name, "/"); lastslash >= 0 {
pkg += name[:lastslash] + "/"
name = name[lastslash+1:]
}
if period := strings.Index(name, "."); period >= 0 {
pkg += name[:period]
name = name[period+1:]
}
name = strings.Replace(name, "·", ".", -1)
return pkg, name
}

View File

@@ -21,3 +21,8 @@ linters:
- lll
- gochecknoinits
- gochecknoglobals
- funlen
- godox
- gocognit
- whitespace
- wsl

File diff suppressed because one or more lines are too long

View File

@@ -452,11 +452,12 @@ func expandPathItem(pathItem *PathItem, resolver *schemaLoader, basePath string)
return err
}
if pathItem.Ref.String() != "" {
var err error
resolver, err = resolver.transitiveResolver(basePath, pathItem.Ref)
if resolver.shouldStopOnError(err) {
transitiveResolver, err := resolver.transitiveResolver(basePath, pathItem.Ref)
if transitiveResolver.shouldStopOnError(err) {
return err
}
basePath = transitiveResolver.updateBasePath(resolver, basePath)
resolver = transitiveResolver
}
pathItem.Ref = Ref{}

View File

@@ -4,14 +4,9 @@ require (
github.com/go-openapi/jsonpointer v0.19.3
github.com/go-openapi/jsonreference v0.19.2
github.com/go-openapi/swag v0.19.5
github.com/kr/pty v1.1.5 // indirect
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.3.0
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 // indirect
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f // indirect
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 // indirect
gopkg.in/yaml.v2 v2.2.2
gopkg.in/yaml.v2 v2.2.4
)
go 1.13

View File

@@ -1,5 +1,3 @@
github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
@@ -7,20 +5,12 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-openapi/jsonpointer v0.17.0 h1:nH6xp8XdXHx8dqveo0ZuJBluCO2qGrPbDNZ0dwoRHP0=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.0 h1:FTUMcX77w5rQkClIzDtTxvn6Bsa894CcrzNj2MMfeg8=
github.com/go-openapi/jsonpointer v0.19.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2 h1:A9+F4Dc/MCNB5jibxf6rRvOvR/iFgQdyNx9eIhnGqq0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.0 h1:BqWKpV1dFd+AuiKlgtddwVIFQsuMpxfBDBHGfM2yNpk=
github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi880=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2 h1:jvO6bCMBEilGwMfHhrd61zIID4oIFdwb76V17SM88dE=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
@@ -28,11 +18,8 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63 h1:nTT4s92Dgz2HlrB2NaMgvlfqHH39OgMhA7z3PK7PGD4=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
@@ -40,35 +27,23 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58 h1:otZG8yDCO4LVps5+9bxOeNiCvgmOyt96J3roHTYs7oE=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -68,10 +68,12 @@ func (r *Ref) IsValidURI(basepaths ...string) bool {
}
if r.HasFullURL {
//#nosec
rr, err := http.Get(v)
if err != nil {
return false
}
defer rr.Body.Close()
return rr.StatusCode/100 == 2
}

View File

@@ -86,12 +86,7 @@ func (r *schemaLoader) transitiveResolver(basePath string, ref Ref) (*schemaLoad
newOptions := r.options
newOptions.RelativeBase = rootURL.String()
debugLog("setting new root: %s", newOptions.RelativeBase)
resolver, err := defaultSchemaLoader(root, newOptions, r.cache, r.context)
if err != nil {
return nil, err
}
return resolver, nil
return defaultSchemaLoader(root, newOptions, r.cache, r.context)
}
func (r *schemaLoader) updateBasePath(transitive *schemaLoader, basePath string) string {

202
vendor/github.com/google/shlex/COPYING generated vendored Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

2
vendor/github.com/google/shlex/README generated vendored Normal file
View File

@@ -0,0 +1,2 @@
go-shlex is a simple lexer for go that supports shell-style quoting,
commenting, and escaping.

3
vendor/github.com/google/shlex/go.mod generated vendored Normal file
View File

@@ -0,0 +1,3 @@
module github.com/google/shlex
go 1.13

416
vendor/github.com/google/shlex/shlex.go generated vendored Normal file
View File

@@ -0,0 +1,416 @@
/*
Copyright 2012 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 shlex implements a simple lexer which splits input in to tokens using
shell-style rules for quoting and commenting.
The basic use case uses the default ASCII lexer to split a string into sub-strings:
shlex.Split("one \"two three\" four") -> []string{"one", "two three", "four"}
To process a stream of strings:
l := NewLexer(os.Stdin)
for ; token, err := l.Next(); err != nil {
// process token
}
To access the raw token stream (which includes tokens for comments):
t := NewTokenizer(os.Stdin)
for ; token, err := t.Next(); err != nil {
// process token
}
*/
package shlex
import (
"bufio"
"fmt"
"io"
"strings"
)
// TokenType is a top-level token classification: A word, space, comment, unknown.
type TokenType int
// runeTokenClass is the type of a UTF-8 character classification: A quote, space, escape.
type runeTokenClass int
// the internal state used by the lexer state machine
type lexerState int
// Token is a (type, value) pair representing a lexographical token.
type Token struct {
tokenType TokenType
value string
}
// Equal reports whether tokens a, and b, are equal.
// Two tokens are equal if both their types and values are equal. A nil token can
// never be equal to another token.
func (a *Token) Equal(b *Token) bool {
if a == nil || b == nil {
return false
}
if a.tokenType != b.tokenType {
return false
}
return a.value == b.value
}
// Named classes of UTF-8 runes
const (
spaceRunes = " \t\r\n"
escapingQuoteRunes = `"`
nonEscapingQuoteRunes = "'"
escapeRunes = `\`
commentRunes = "#"
)
// Classes of rune token
const (
unknownRuneClass runeTokenClass = iota
spaceRuneClass
escapingQuoteRuneClass
nonEscapingQuoteRuneClass
escapeRuneClass
commentRuneClass
eofRuneClass
)
// Classes of lexographic token
const (
UnknownToken TokenType = iota
WordToken
SpaceToken
CommentToken
)
// Lexer state machine states
const (
startState lexerState = iota // no runes have been seen
inWordState // processing regular runes in a word
escapingState // we have just consumed an escape rune; the next rune is literal
escapingQuotedState // we have just consumed an escape rune within a quoted string
quotingEscapingState // we are within a quoted string that supports escaping ("...")
quotingState // we are within a string that does not support escaping ('...')
commentState // we are within a comment (everything following an unquoted or unescaped #
)
// tokenClassifier is used for classifying rune characters.
type tokenClassifier map[rune]runeTokenClass
func (typeMap tokenClassifier) addRuneClass(runes string, tokenType runeTokenClass) {
for _, runeChar := range runes {
typeMap[runeChar] = tokenType
}
}
// newDefaultClassifier creates a new classifier for ASCII characters.
func newDefaultClassifier() tokenClassifier {
t := tokenClassifier{}
t.addRuneClass(spaceRunes, spaceRuneClass)
t.addRuneClass(escapingQuoteRunes, escapingQuoteRuneClass)
t.addRuneClass(nonEscapingQuoteRunes, nonEscapingQuoteRuneClass)
t.addRuneClass(escapeRunes, escapeRuneClass)
t.addRuneClass(commentRunes, commentRuneClass)
return t
}
// ClassifyRune classifiees a rune
func (t tokenClassifier) ClassifyRune(runeVal rune) runeTokenClass {
return t[runeVal]
}
// Lexer turns an input stream into a sequence of tokens. Whitespace and comments are skipped.
type Lexer Tokenizer
// NewLexer creates a new lexer from an input stream.
func NewLexer(r io.Reader) *Lexer {
return (*Lexer)(NewTokenizer(r))
}
// Next returns the next word, or an error. If there are no more words,
// the error will be io.EOF.
func (l *Lexer) Next() (string, error) {
for {
token, err := (*Tokenizer)(l).Next()
if err != nil {
return "", err
}
switch token.tokenType {
case WordToken:
return token.value, nil
case CommentToken:
// skip comments
default:
return "", fmt.Errorf("Unknown token type: %v", token.tokenType)
}
}
}
// Tokenizer turns an input stream into a sequence of typed tokens
type Tokenizer struct {
input bufio.Reader
classifier tokenClassifier
}
// NewTokenizer creates a new tokenizer from an input stream.
func NewTokenizer(r io.Reader) *Tokenizer {
input := bufio.NewReader(r)
classifier := newDefaultClassifier()
return &Tokenizer{
input: *input,
classifier: classifier}
}
// scanStream scans the stream for the next token using the internal state machine.
// It will panic if it encounters a rune which it does not know how to handle.
func (t *Tokenizer) scanStream() (*Token, error) {
state := startState
var tokenType TokenType
var value []rune
var nextRune rune
var nextRuneType runeTokenClass
var err error
for {
nextRune, _, err = t.input.ReadRune()
nextRuneType = t.classifier.ClassifyRune(nextRune)
if err == io.EOF {
nextRuneType = eofRuneClass
err = nil
} else if err != nil {
return nil, err
}
switch state {
case startState: // no runes read yet
{
switch nextRuneType {
case eofRuneClass:
{
return nil, io.EOF
}
case spaceRuneClass:
{
}
case escapingQuoteRuneClass:
{
tokenType = WordToken
state = quotingEscapingState
}
case nonEscapingQuoteRuneClass:
{
tokenType = WordToken
state = quotingState
}
case escapeRuneClass:
{
tokenType = WordToken
state = escapingState
}
case commentRuneClass:
{
tokenType = CommentToken
state = commentState
}
default:
{
tokenType = WordToken
value = append(value, nextRune)
state = inWordState
}
}
}
case inWordState: // in a regular word
{
switch nextRuneType {
case eofRuneClass:
{
token := &Token{
tokenType: tokenType,
value: string(value)}
return token, err
}
case spaceRuneClass:
{
token := &Token{
tokenType: tokenType,
value: string(value)}
return token, err
}
case escapingQuoteRuneClass:
{
state = quotingEscapingState
}
case nonEscapingQuoteRuneClass:
{
state = quotingState
}
case escapeRuneClass:
{
state = escapingState
}
default:
{
value = append(value, nextRune)
}
}
}
case escapingState: // the rune after an escape character
{
switch nextRuneType {
case eofRuneClass:
{
err = fmt.Errorf("EOF found after escape character")
token := &Token{
tokenType: tokenType,
value: string(value)}
return token, err
}
default:
{
state = inWordState
value = append(value, nextRune)
}
}
}
case escapingQuotedState: // the next rune after an escape character, in double quotes
{
switch nextRuneType {
case eofRuneClass:
{
err = fmt.Errorf("EOF found after escape character")
token := &Token{
tokenType: tokenType,
value: string(value)}
return token, err
}
default:
{
state = quotingEscapingState
value = append(value, nextRune)
}
}
}
case quotingEscapingState: // in escaping double quotes
{
switch nextRuneType {
case eofRuneClass:
{
err = fmt.Errorf("EOF found when expecting closing quote")
token := &Token{
tokenType: tokenType,
value: string(value)}
return token, err
}
case escapingQuoteRuneClass:
{
state = inWordState
}
case escapeRuneClass:
{
state = escapingQuotedState
}
default:
{
value = append(value, nextRune)
}
}
}
case quotingState: // in non-escaping single quotes
{
switch nextRuneType {
case eofRuneClass:
{
err = fmt.Errorf("EOF found when expecting closing quote")
token := &Token{
tokenType: tokenType,
value: string(value)}
return token, err
}
case nonEscapingQuoteRuneClass:
{
state = inWordState
}
default:
{
value = append(value, nextRune)
}
}
}
case commentState: // in a comment
{
switch nextRuneType {
case eofRuneClass:
{
token := &Token{
tokenType: tokenType,
value: string(value)}
return token, err
}
case spaceRuneClass:
{
if nextRune == '\n' {
state = startState
token := &Token{
tokenType: tokenType,
value: string(value)}
return token, err
} else {
value = append(value, nextRune)
}
}
default:
{
value = append(value, nextRune)
}
}
}
default:
{
return nil, fmt.Errorf("Unexpected state: %v", state)
}
}
}
}
// Next returns the next token in the stream.
func (t *Tokenizer) Next() (*Token, error) {
return t.scanStream()
}
// Split partitions a string into a slice of strings.
func Split(s string) ([]string, error) {
l := NewLexer(strings.NewReader(s))
subStrings := make([]string, 0)
for {
word, err := l.Next()
if err != nil {
if err == io.EOF {
return subStrings, nil
}
return subStrings, err
}
subStrings = append(subStrings, word)
}
}

View File

@@ -0,0 +1,6 @@
language: go
go:
- 1.14.x
- master
script:
- go test -v ./...

21
vendor/github.com/monochromegane/go-gitignore/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) [2015] [go-gitignore]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,95 @@
# go-gitignore [![Build Status](https://travis-ci.org/monochromegane/go-gitignore.svg)](https://travis-ci.org/monochromegane/go-gitignore)
A fast gitignore matching library for Go.
This library use simple tree index for matching, so keep fast if gitignore file has many pattern.
## Usage
```go
gitignore, _ := gitignore.NewGitIgnore("/path/to/gitignore")
path := "/path/to/file"
isDir := false
gitignore.Match(path, isDir)
```
### Specify base directory
go-gitignore treat `path` as a base directory.
If you want to specify other base (e.g. current directory and Global gitignore), you can like the following.
```go
gitignore, _ := gitignore.NewGitIgnore("/home/you/.gitignore", ".")
```
### From io.Reader
go-gitignore can initialize from io.Reader.
```go
gitignore, _ := gitignore.NewGitIgnoreFromReader(base, reader)
```
## Simple tree index
go-gitignore parse gitignore file, and generate a simple tree index for matching like the following.
```
.
├── accept
│   ├── absolute
│   │   └── depth
│   │   ├── initial
│   │   └── other
│   └── relative
│   └── depth
│   ├── initial
│   └── other
└── ignore
├── absolute
│   └── depth
│   ├── initial
│   └── other
└── relative
└── depth
├── initial
└── other
```
## Features
- Support absolute path (/path/to/ignore)
- Support relative path (path/to/ignore)
- Support accept pattern (!path/to/accept)
- Support directory pattern (path/to/directory/)
- Support glob pattern (path/to/\*.txt)
*note: glob pattern*
go-gitignore use [filepath.Match](https://golang.org/pkg/path/filepath/#Match) for matching meta char pattern, so not support recursive pattern (path/`**`/file).
## Installation
```sh
$ go get github.com/monochromegane/go-gitignore
```
## Contribution
1. Fork it
2. Create a feature branch
3. Commit your changes
4. Rebase your local changes against the master branch
5. Run test suite with the `go test ./...` command and confirm that it passes
6. Run `gofmt -s`
7. Create new Pull Request
## License
[MIT](https://github.com/monochromegane/go-gitignore/blob/master/LICENSE)
## Author
[monochromegane](https://github.com/monochromegane)

View File

@@ -0,0 +1,79 @@
package gitignore
import "strings"
const (
asc = iota
desc
)
type depthPatternHolder struct {
patterns depthPatterns
order int
}
func newDepthPatternHolder(order int) depthPatternHolder {
return depthPatternHolder{
patterns: depthPatterns{m: map[int]initialPatternHolder{}},
order: order,
}
}
func (h *depthPatternHolder) add(pattern string) {
count := strings.Count(strings.Trim(pattern, "/"), "/")
h.patterns.set(count+1, pattern)
}
func (h depthPatternHolder) match(path string, isDir bool) bool {
if h.patterns.size() == 0 {
return false
}
for depth := 1; ; depth++ {
var part string
var isLast, isDirCurrent bool
if h.order == asc {
part, isLast = cutN(path, depth)
if isLast {
isDirCurrent = isDir
} else {
isDirCurrent = false
}
} else {
part, isLast = cutLastN(path, depth)
isDirCurrent = isDir
}
if patterns, ok := h.patterns.get(depth); ok {
if patterns.match(part, isDirCurrent) {
return true
}
}
if isLast {
break
}
}
return false
}
type depthPatterns struct {
m map[int]initialPatternHolder
}
func (p *depthPatterns) set(depth int, pattern string) {
if ps, ok := p.m[depth]; ok {
ps.add(pattern)
} else {
holder := newInitialPatternHolder()
holder.add(pattern)
p.m[depth] = holder
}
}
func (p depthPatterns) get(depth int) (initialPatternHolder, bool) {
patterns, ok := p.m[depth]
return patterns, ok
}
func (p depthPatterns) size() int {
return len(p.m)
}

View File

@@ -0,0 +1,31 @@
package gitignore
import "strings"
// Only benchmark use
type fullScanPatterns struct {
absolute patterns
relative patterns
}
func newFullScanPatterns() *fullScanPatterns {
return &fullScanPatterns{
absolute: patterns{},
relative: patterns{},
}
}
func (ps *fullScanPatterns) add(pattern string) {
if strings.HasPrefix(pattern, "/") {
ps.absolute.add(newPattern(pattern))
} else {
ps.relative.add(newPattern(pattern))
}
}
func (ps fullScanPatterns) match(path string, isDir bool) bool {
if ps.absolute.match(path, isDir) {
return true
}
return ps.relative.match(path, isDir)
}

View File

@@ -0,0 +1,80 @@
package gitignore
import (
"bufio"
"io"
"os"
"path/filepath"
"strings"
)
type IgnoreMatcher interface {
Match(path string, isDir bool) bool
}
type DummyIgnoreMatcher bool
func (d DummyIgnoreMatcher) Match(path string, isDir bool) bool {
return bool(d)
}
type gitIgnore struct {
ignorePatterns scanStrategy
acceptPatterns scanStrategy
path string
}
func NewGitIgnore(gitignore string, base ...string) (IgnoreMatcher, error) {
var path string
if len(base) > 0 {
path = base[0]
} else {
path = filepath.Dir(gitignore)
}
file, err := os.Open(gitignore)
if err != nil {
return nil, err
}
defer file.Close()
return NewGitIgnoreFromReader(path, file), nil
}
func NewGitIgnoreFromReader(path string, r io.Reader) IgnoreMatcher {
g := gitIgnore{
ignorePatterns: newIndexScanPatterns(),
acceptPatterns: newIndexScanPatterns(),
path: path,
}
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := strings.Trim(scanner.Text(), " ")
if len(line) == 0 || strings.HasPrefix(line, "#") {
continue
}
if strings.HasPrefix(line, `\#`) {
line = strings.TrimPrefix(line, `\`)
}
if strings.HasPrefix(line, "!") {
g.acceptPatterns.add(strings.TrimPrefix(line, "!"))
} else {
g.ignorePatterns.add(line)
}
}
return g
}
func (g gitIgnore) Match(path string, isDir bool) bool {
relativePath, err := filepath.Rel(g.path, path)
if err != nil {
return false
}
relativePath = filepath.ToSlash(relativePath)
if g.acceptPatterns.match(relativePath, isDir) {
return false
}
return g.ignorePatterns.match(relativePath, isDir)
}

View File

@@ -0,0 +1,35 @@
package gitignore
import "strings"
type indexScanPatterns struct {
absolute depthPatternHolder
relative depthPatternHolder
}
func newIndexScanPatterns() *indexScanPatterns {
return &indexScanPatterns{
absolute: newDepthPatternHolder(asc),
relative: newDepthPatternHolder(desc),
}
}
func (ps *indexScanPatterns) add(pattern string) {
if strings.HasPrefix(pattern, "/") {
ps.absolute.add(pattern)
} else {
ps.relative.add(pattern)
}
}
func (ps indexScanPatterns) match(path string, isDir bool) bool {
if ps.absolute.match(path, isDir) {
return true
}
return ps.relative.match(path, isDir)
}
type scanStrategy interface {
add(pattern string)
match(path string, isDir bool) bool
}

View File

@@ -0,0 +1,62 @@
package gitignore
import "strings"
const initials = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ."
type initialPatternHolder struct {
patterns initialPatterns
otherPatterns *patterns
}
func newInitialPatternHolder() initialPatternHolder {
return initialPatternHolder{
patterns: initialPatterns{m: map[byte]*patterns{}},
otherPatterns: &patterns{},
}
}
func (h *initialPatternHolder) add(pattern string) {
trimedPattern := strings.TrimPrefix(pattern, "/")
if strings.IndexAny(trimedPattern[0:1], initials) != -1 {
h.patterns.set(trimedPattern[0], newPatternForEqualizedPath(pattern))
} else {
h.otherPatterns.add(newPatternForEqualizedPath(pattern))
}
}
func (h initialPatternHolder) match(path string, isDir bool) bool {
if h.patterns.size() == 0 && h.otherPatterns.size() == 0 {
return false
}
if patterns, ok := h.patterns.get(path[0]); ok {
if patterns.match(path, isDir) {
return true
}
}
return h.otherPatterns.match(path, isDir)
}
type initialPatterns struct {
m map[byte]*patterns
}
func (p *initialPatterns) set(initial byte, pattern pattern) {
if ps, ok := p.m[initial]; ok {
ps.add(pattern)
} else {
patterns := &patterns{}
patterns.add(pattern)
p.m[initial] = patterns
}
}
func (p initialPatterns) get(initial byte) (*patterns, bool) {
patterns, ok := p.m[initial]
return patterns, ok
}
func (p initialPatterns) size() int {
return len(p.m)
}

24
vendor/github.com/monochromegane/go-gitignore/match.go generated vendored Normal file
View File

@@ -0,0 +1,24 @@
package gitignore
import "path/filepath"
type pathMatcher interface {
match(path string) bool
}
type simpleMatcher struct {
path string
}
func (m simpleMatcher) match(path string) bool {
return m.path == path
}
type filepathMatcher struct {
path string
}
func (m filepathMatcher) match(path string) bool {
match, _ := filepath.Match(m.path, path)
return match
}

View File

@@ -0,0 +1,69 @@
package gitignore
import (
"path/filepath"
"strings"
)
var Separator = string(filepath.Separator)
type pattern struct {
hasRootPrefix bool
hasDirSuffix bool
pathDepth int
matcher pathMatcher
onlyEqualizedPath bool
}
func newPattern(path string) pattern {
hasRootPrefix := path[0] == '/'
hasDirSuffix := path[len(path)-1] == '/'
var pathDepth int
if !hasRootPrefix {
pathDepth = strings.Count(path, "/")
}
var matcher pathMatcher
matchingPath := strings.Trim(path, "/")
if hasMeta(path) {
matcher = filepathMatcher{path: matchingPath}
} else {
matcher = simpleMatcher{path: matchingPath}
}
return pattern{
hasRootPrefix: hasRootPrefix,
hasDirSuffix: hasDirSuffix,
pathDepth: pathDepth,
matcher: matcher,
}
}
func newPatternForEqualizedPath(path string) pattern {
pattern := newPattern(path)
pattern.onlyEqualizedPath = true
return pattern
}
func (p pattern) match(path string, isDir bool) bool {
if p.hasDirSuffix && !isDir {
return false
}
var targetPath string
if p.hasRootPrefix || p.onlyEqualizedPath {
// absolute pattern or only equalized path mode
targetPath = path
} else {
// relative pattern
targetPath = p.equalizeDepth(path)
}
return p.matcher.match(targetPath)
}
func (p pattern) equalizeDepth(path string) string {
equalizedPath, _ := cutLastN(path, p.pathDepth+1)
return equalizedPath
}

View File

@@ -0,0 +1,22 @@
package gitignore
type patterns struct {
patterns []pattern
}
func (ps *patterns) add(pattern pattern) {
ps.patterns = append(ps.patterns, pattern)
}
func (ps *patterns) size() int {
return len(ps.patterns)
}
func (ps patterns) match(path string, isDir bool) bool {
for _, p := range ps.patterns {
if match := p.match(path, isDir); match {
return true
}
}
return false
}

45
vendor/github.com/monochromegane/go-gitignore/util.go generated vendored Normal file
View File

@@ -0,0 +1,45 @@
package gitignore
import (
"os"
"strings"
)
func cutN(path string, n int) (string, bool) {
isLast := true
var i, count int
for i < len(path)-1 {
if os.IsPathSeparator(path[i]) {
count++
if count >= n {
isLast = false
break
}
}
i++
}
return path[:i+1], isLast
}
func cutLastN(path string, n int) (string, bool) {
isLast := true
i := len(path) - 1
var count int
for i >= 0 {
if os.IsPathSeparator(path[i]) {
count++
if count >= n {
isLast = false
break
}
}
i--
}
return path[i+1:], isLast
}
func hasMeta(path string) bool {
return strings.IndexAny(path, "*?[") >= 0
}

20
vendor/github.com/xlab/treeprint/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright © 2016 Maxim Kupriianov <max@kc.vc>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

128
vendor/github.com/xlab/treeprint/README.md generated vendored Normal file
View File

@@ -0,0 +1,128 @@
treeprint [![GoDoc](https://godoc.org/github.com/xlab/treeprint?status.svg)](https://godoc.org/github.com/xlab/treeprint) ![test coverage](https://img.shields.io/badge/coverage-68.6%25-green.svg)
=========
Package `treeprint` provides a simple ASCII tree composing tool.
<a href="https://upload.wikimedia.org/wikipedia/commons/5/58/ENC_SYSTEME_FIGURE.jpeg"><img alt="SYSTEME FIGURE" src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/ENC_SYSTEME_FIGURE.jpeg/896px-ENC_SYSTEME_FIGURE.jpeg" align="left" width="300"></a>
If you are familiar with the [tree](http://mama.indstate.edu/users/ice/tree/) utility that is a recursive directory listing command that produces a depth indented listing of files, then you have the idea of what it would look like.
On my system the command yields the following
```
$ tree
.
├── LICENSE
├── README.md
├── treeprint.go
└── treeprint_test.go
0 directories, 4 files
```
and I'd like to have the same format for my Go data structures when I print them.
## Installation
```
$ go get github.com/xlab/treeprint
```
## Concept of work
The general idea is that you initialise a new tree with `treeprint.New()` and then add nodes and
branches into it. Use `AddNode()` when you want add a node on the same level as the target or
use `AddBranch()` when you want to go a level deeper. So `tree.AddBranch().AddNode().AddNode()` would
create a new level with two distinct nodes on it. So `tree.AddNode().AddNode()` is a flat thing and
`tree.AddBranch().AddBranch().AddBranch()` is a high thing. Use `String()` or `Bytes()` on a branch
to render a subtree, or use it on the root to print the whole tree.
The utility will yield Unicode-friendly trees. The output is predictable and there is no platform-dependent exceptions, so if you have issues with displaying the tree in the console, all platform-related transformations can be done after the tree has been rendered: [an example](https://github.com/xlab/treeprint/issues/2#issuecomment-324944141) for Asian locales.
## Use cases
When you want to render a complex data structure:
```go
func main() {
tree := treeprint.New()
// create a new branch in the root
one := tree.AddBranch("one")
// add some nodes
one.AddNode("subnode1").AddNode("subnode2")
// create a new sub-branch
one.AddBranch("two").
AddNode("subnode1").AddNode("subnode2"). // add some nodes
AddBranch("three"). // add a new sub-branch
AddNode("subnode1").AddNode("subnode2") // add some nodes too
// add one more node that should surround the inner branch
one.AddNode("subnode3")
// add a new node to the root
tree.AddNode("outernode")
fmt.Println(tree.String())
}
```
Will give you:
```
.
├── one
│   ├── subnode1
│   ├── subnode2
│   ├── two
│   │   ├── subnode1
│   │   ├── subnode2
│   │   └── three
│   │   ├── subnode1
│   │   └── subnode2
│   └── subnode3
└── outernode
```
Another case, when you have to make a tree where any leaf may have some meta-data (as `tree` is capable of it):
```go
func main {
tree := treeprint.New()
tree.AddNode("Dockerfile")
tree.AddNode("Makefile")
tree.AddNode("aws.sh")
tree.AddMetaBranch(" 204", "bin").
AddNode("dbmaker").AddNode("someserver").AddNode("testtool")
tree.AddMetaBranch(" 374", "deploy").
AddNode("Makefile").AddNode("bootstrap.sh")
tree.AddMetaNode("122K", "testtool.a")
fmt.Println(tree.String())
}
```
Output:
```
.
├── Dockerfile
├── Makefile
├── aws.sh
├── [ 204] bin
│   ├── dbmaker
│   ├── someserver
│   └── testtool
├── [ 374] deploy
│   ├── Makefile
│   └── bootstrap.sh
└── [122K] testtool.a
```
Yay! So it works.
## License
MIT

47
vendor/github.com/xlab/treeprint/helpers.go generated vendored Normal file
View File

@@ -0,0 +1,47 @@
package treeprint
import (
"reflect"
"strings"
)
func isEmpty(v *reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
}
return false
}
func tagSpec(tag string) (name string, omit bool) {
parts := strings.Split(tag, ",")
if len(parts) < 2 {
return tag, false
}
if parts[1] == "omitempty" {
return parts[0], true
}
return parts[0], false
}
func filterTags(tag reflect.StructTag) string {
tags := strings.Split(string(tag), " ")
filtered := make([]string, 0, len(tags))
for i := range tags {
if strings.HasPrefix(tags[i], "tree:") {
continue
}
filtered = append(filtered, tags[i])
}
return strings.Join(filtered, " ")
}

322
vendor/github.com/xlab/treeprint/struct.go generated vendored Normal file
View File

@@ -0,0 +1,322 @@
package treeprint
import (
"fmt"
"reflect"
"strings"
)
type StructTreeOption int
const (
StructNameTree StructTreeOption = iota
StructValueTree
StructTagTree
StructTypeTree
StructTypeSizeTree
)
func FromStruct(v interface{}, opt ...StructTreeOption) (Tree, error) {
var treeOpt StructTreeOption
if len(opt) > 0 {
treeOpt = opt[0]
}
switch treeOpt {
case StructNameTree:
tree := New()
err := nameTree(tree, v)
return tree, err
case StructValueTree:
tree := New()
err := valueTree(tree, v)
return tree, err
case StructTagTree:
tree := New()
err := tagTree(tree, v)
return tree, err
case StructTypeTree:
tree := New()
err := typeTree(tree, v)
return tree, err
case StructTypeSizeTree:
tree := New()
err := typeSizeTree(tree, v)
return tree, err
default:
err := fmt.Errorf("treeprint: invalid StructTreeOption %v", treeOpt)
return nil, err
}
}
type FmtFunc func(name string, v interface{}) (string, bool)
func FromStructWithMeta(v interface{}, fmtFunc FmtFunc) (Tree, error) {
if fmtFunc == nil {
tree := New()
err := nameTree(tree, v)
return tree, err
}
tree := New()
err := metaTree(tree, v, fmtFunc)
return tree, err
}
func Repr(v interface{}) string {
tree := New()
vType := reflect.TypeOf(v)
vValue := reflect.ValueOf(v)
_, val, isStruct := getValue(vType, &vValue)
if !isStruct {
return fmt.Sprintf("%+v", val.Interface())
}
err := valueTree(tree, val.Interface())
if err != nil {
return err.Error()
}
return tree.String()
}
func nameTree(tree Tree, v interface{}) error {
typ, val, err := checkType(v)
if err != nil {
return err
}
fields := typ.NumField()
for i := 0; i < fields; i++ {
field := typ.Field(i)
fieldValue := val.Field(i)
name, skip, omit := getMeta(field.Name, field.Tag)
if skip || omit && isEmpty(&fieldValue) {
continue
}
typ, val, isStruct := getValue(field.Type, &fieldValue)
if !isStruct {
tree.AddNode(name)
continue
} else if subNum := typ.NumField(); subNum == 0 {
tree.AddNode(name)
continue
}
branch := tree.AddBranch(name)
if err := nameTree(branch, val.Interface()); err != nil {
err := fmt.Errorf("%v on struct branch %s", err, name)
return err
}
}
return nil
}
func getMeta(fieldName string, tag reflect.StructTag) (name string, skip, omit bool) {
if tagStr := tag.Get("tree"); len(tagStr) > 0 {
name, omit = tagSpec(tagStr)
}
if name == "-" {
return fieldName, true, omit
}
if len(name) == 0 {
name = fieldName
} else if trimmed := strings.TrimSpace(name); len(trimmed) == 0 {
name = fieldName
}
return
}
func valueTree(tree Tree, v interface{}) error {
typ, val, err := checkType(v)
if err != nil {
return err
}
fields := typ.NumField()
for i := 0; i < fields; i++ {
field := typ.Field(i)
fieldValue := val.Field(i)
name, skip, omit := getMeta(field.Name, field.Tag)
if skip || omit && isEmpty(&fieldValue) {
continue
}
typ, val, isStruct := getValue(field.Type, &fieldValue)
if !isStruct {
tree.AddMetaNode(val.Interface(), name)
continue
} else if subNum := typ.NumField(); subNum == 0 {
tree.AddMetaNode(val.Interface(), name)
continue
}
branch := tree.AddBranch(name)
if err := valueTree(branch, val.Interface()); err != nil {
err := fmt.Errorf("%v on struct branch %s", err, name)
return err
}
}
return nil
}
func tagTree(tree Tree, v interface{}) error {
typ, val, err := checkType(v)
if err != nil {
return err
}
fields := typ.NumField()
for i := 0; i < fields; i++ {
field := typ.Field(i)
fieldValue := val.Field(i)
name, skip, omit := getMeta(field.Name, field.Tag)
if skip || omit && isEmpty(&fieldValue) {
continue
}
filteredTag := filterTags(field.Tag)
typ, val, isStruct := getValue(field.Type, &fieldValue)
if !isStruct {
tree.AddMetaNode(filteredTag, name)
continue
} else if subNum := typ.NumField(); subNum == 0 {
tree.AddMetaNode(filteredTag, name)
continue
}
branch := tree.AddMetaBranch(filteredTag, name)
if err := tagTree(branch, val.Interface()); err != nil {
err := fmt.Errorf("%v on struct branch %s", err, name)
return err
}
}
return nil
}
func typeTree(tree Tree, v interface{}) error {
typ, val, err := checkType(v)
if err != nil {
return err
}
fields := typ.NumField()
for i := 0; i < fields; i++ {
field := typ.Field(i)
fieldValue := val.Field(i)
name, skip, omit := getMeta(field.Name, field.Tag)
if skip || omit && isEmpty(&fieldValue) {
continue
}
typ, val, isStruct := getValue(field.Type, &fieldValue)
typename := fmt.Sprintf("%T", val.Interface())
if !isStruct {
tree.AddMetaNode(typename, name)
continue
} else if subNum := typ.NumField(); subNum == 0 {
tree.AddMetaNode(typename, name)
continue
}
branch := tree.AddMetaBranch(typename, name)
if err := typeTree(branch, val.Interface()); err != nil {
err := fmt.Errorf("%v on struct branch %s", err, name)
return err
}
}
return nil
}
func typeSizeTree(tree Tree, v interface{}) error {
typ, val, err := checkType(v)
if err != nil {
return err
}
fields := typ.NumField()
for i := 0; i < fields; i++ {
field := typ.Field(i)
fieldValue := val.Field(i)
name, skip, omit := getMeta(field.Name, field.Tag)
if skip || omit && isEmpty(&fieldValue) {
continue
}
typ, val, isStruct := getValue(field.Type, &fieldValue)
typesize := typ.Size()
if !isStruct {
tree.AddMetaNode(typesize, name)
continue
} else if subNum := typ.NumField(); subNum == 0 {
tree.AddMetaNode(typesize, name)
continue
}
branch := tree.AddMetaBranch(typesize, name)
if err := typeSizeTree(branch, val.Interface()); err != nil {
err := fmt.Errorf("%v on struct branch %s", err, name)
return err
}
}
return nil
}
func metaTree(tree Tree, v interface{}, fmtFunc FmtFunc) error {
typ, val, err := checkType(v)
if err != nil {
return err
}
fields := typ.NumField()
for i := 0; i < fields; i++ {
field := typ.Field(i)
fieldValue := val.Field(i)
name, skip, omit := getMeta(field.Name, field.Tag)
if skip || omit && isEmpty(&fieldValue) {
continue
}
typ, val, isStruct := getValue(field.Type, &fieldValue)
formatted, show := fmtFunc(name, val.Interface())
if !isStruct {
if show {
tree.AddMetaNode(formatted, name)
continue
}
tree.AddNode(name)
continue
} else if subNum := typ.NumField(); subNum == 0 {
if show {
tree.AddMetaNode(formatted, name)
continue
}
tree.AddNode(name)
continue
}
var branch Tree
if show {
branch = tree.AddMetaBranch(formatted, name)
} else {
branch = tree.AddBranch(name)
}
if err := metaTree(branch, val.Interface(), fmtFunc); err != nil {
err := fmt.Errorf("%v on struct branch %s", err, name)
return err
}
}
return nil
}
func getValue(typ reflect.Type, val *reflect.Value) (reflect.Type, *reflect.Value, bool) {
switch typ.Kind() {
case reflect.Ptr:
typ = typ.Elem()
if typ.Kind() == reflect.Struct {
elem := val.Elem()
return typ, &elem, true
}
case reflect.Struct:
return typ, val, true
}
return typ, val, false
}
func checkType(v interface{}) (reflect.Type, *reflect.Value, error) {
typ := reflect.TypeOf(v)
val := reflect.ValueOf(v)
switch typ.Kind() {
case reflect.Ptr:
typ = typ.Elem()
if typ.Kind() != reflect.Struct {
err := fmt.Errorf("treeprint: %T is not a struct we could work with", v)
return nil, nil, err
}
val = val.Elem()
case reflect.Struct:
default:
err := fmt.Errorf("treeprint: %T is not a struct we could work with", v)
return nil, nil, err
}
return typ, &val, nil
}

215
vendor/github.com/xlab/treeprint/treeprint.go generated vendored Normal file
View File

@@ -0,0 +1,215 @@
// Package treeprint provides a simple ASCII tree composing tool.
package treeprint
import (
"bytes"
"fmt"
"io"
"reflect"
)
type Value interface{}
type MetaValue interface{}
// Tree represents a tree structure with leaf-nodes and branch-nodes.
type Tree interface {
// AddNode adds a new node to a branch.
AddNode(v Value) Tree
// AddMetaNode adds a new node with meta value provided to a branch.
AddMetaNode(meta MetaValue, v Value) Tree
// AddBranch adds a new branch node (a level deeper).
AddBranch(v Value) Tree
// AddMetaBranch adds a new branch node (a level deeper) with meta value provided.
AddMetaBranch(meta MetaValue, v Value) Tree
// Branch converts a leaf-node to a branch-node,
// applying this on a branch-node does no effect.
Branch() Tree
// FindByMeta finds a node whose meta value matches the provided one by reflect.DeepEqual,
// returns nil if not found.
FindByMeta(meta MetaValue) Tree
// FindByValue finds a node whose value matches the provided one by reflect.DeepEqual,
// returns nil if not found.
FindByValue(value Value) Tree
// returns the last node of a tree
FindLastNode() Tree
// String renders the tree or subtree as a string.
String() string
// Bytes renders the tree or subtree as byteslice.
Bytes() []byte
SetValue(value Value)
SetMetaValue(meta MetaValue)
}
type node struct {
Root *node
Meta MetaValue
Value Value
Nodes []*node
}
func (n *node) FindLastNode() Tree {
ns := n.Nodes
n = ns[len(ns)-1]
return n
}
func (n *node) AddNode(v Value) Tree {
n.Nodes = append(n.Nodes, &node{
Root: n,
Value: v,
})
if n.Root != nil {
return n.Root
}
return n
}
func (n *node) AddMetaNode(meta MetaValue, v Value) Tree {
n.Nodes = append(n.Nodes, &node{
Root: n,
Meta: meta,
Value: v,
})
if n.Root != nil {
return n.Root
}
return n
}
func (n *node) AddBranch(v Value) Tree {
branch := &node{
Value: v,
}
n.Nodes = append(n.Nodes, branch)
return branch
}
func (n *node) AddMetaBranch(meta MetaValue, v Value) Tree {
branch := &node{
Meta: meta,
Value: v,
}
n.Nodes = append(n.Nodes, branch)
return branch
}
func (n *node) Branch() Tree {
n.Root = nil
return n
}
func (n *node) FindByMeta(meta MetaValue) Tree {
for _, node := range n.Nodes {
if reflect.DeepEqual(node.Meta, meta) {
return node
}
if v := node.FindByMeta(meta); v != nil {
return v
}
}
return nil
}
func (n *node) FindByValue(value Value) Tree {
for _, node := range n.Nodes {
if reflect.DeepEqual(node.Value, value) {
return node
}
if v := node.FindByMeta(value); v != nil {
return v
}
}
return nil
}
func (n *node) Bytes() []byte {
buf := new(bytes.Buffer)
level := 0
var levelsEnded []int
if n.Root == nil {
if n.Meta != nil {
buf.WriteString(fmt.Sprintf("[%v] %v", n.Meta, n.Value))
} else {
buf.WriteString(fmt.Sprintf("%v",n.Value))
}
buf.WriteByte('\n')
} else {
edge := EdgeTypeMid
if len(n.Nodes) == 0 {
edge = EdgeTypeEnd
levelsEnded = append(levelsEnded, level)
}
printValues(buf, 0, levelsEnded, edge, n.Meta, n.Value)
}
if len(n.Nodes) > 0 {
printNodes(buf, level, levelsEnded, n.Nodes)
}
return buf.Bytes()
}
func (n *node) String() string {
return string(n.Bytes())
}
func (n *node) SetValue(value Value){
n.Value = value
}
func (n *node) SetMetaValue(meta MetaValue){
n.Meta = meta
}
func printNodes(wr io.Writer,
level int, levelsEnded []int, nodes []*node) {
for i, node := range nodes {
edge := EdgeTypeMid
if i == len(nodes)-1 {
levelsEnded = append(levelsEnded, level)
edge = EdgeTypeEnd
}
printValues(wr, level, levelsEnded, edge, node.Meta, node.Value)
if len(node.Nodes) > 0 {
printNodes(wr, level+1, levelsEnded, node.Nodes)
}
}
}
func printValues(wr io.Writer,
level int, levelsEnded []int, edge EdgeType, meta MetaValue, val Value) {
for i := 0; i < level; i++ {
if isEnded(levelsEnded, i) {
fmt.Fprint(wr, " ")
continue
}
fmt.Fprintf(wr, "%s   ", EdgeTypeLink)
}
if meta != nil {
fmt.Fprintf(wr, "%s [%v] %v\n", edge, meta, val)
return
}
fmt.Fprintf(wr, "%s %v\n", edge, val)
}
func isEnded(levelsEnded []int, level int) bool {
for _, l := range levelsEnded {
if l == level {
return true
}
}
return false
}
type EdgeType string
var (
EdgeTypeLink EdgeType = "│"
EdgeTypeMid EdgeType = "├──"
EdgeTypeEnd EdgeType = "└──"
)
func New() Tree {
return &node{Value: "."}
}