Fix failing issues with vendoring as well as compiling

Something within golang.org/x/sys messed up and it doesn't help that we
have three different projects using different versions.

This vendor update specifies a golang.org/x/sys as well as fixes the
previous compiling issues with Windows/Linux/macOS builds.

See issue:

```sh
gox -osarch="darwin/amd64 linux/amd64 linux/arm windows/amd64"
-output="bin/kompose-{{.OS}}-{{.Arch}}" -ldflags="-w -X
github.com/kubernetes/kompose/pkg/version.GITCOMMIT=42e7f0e"
Number of parallel builds: 1
-->   windows/amd64: github.com/kubernetes/kompose
-->     linux/amd64: github.com/kubernetes/kompose
-->    darwin/amd64: github.com/kubernetes/kompose
-->       linux/arm: github.com/kubernetes/kompose
1 errors occurred:
--> windows/amd64 error: exit status 2
Stderr: #
github.com/kubernetes/kompose/vendor/golang.org/x/crypto/ssh/terminal
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:42: undefined:
windows.ENABLE_ECHO_INPUT
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:42: undefined:
windows.ENABLE_PROCESSED_INPUT
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:42: undefined:
windows.ENABLE_LINE_INPUT
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:42: undefined:
windows.ENABLE_PROCESSED_OUTPUT
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:43: undefined:
windows.SetConsoleMode
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:62: undefined:
windows.SetConsoleMode
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:67: undefined:
windows.ConsoleScreenBufferInfo
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:68: undefined:
windows.GetConsoleScreenBufferInfo
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:91: undefined:
windows.ENABLE_ECHO_INPUT
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:92: undefined:
windows.ENABLE_PROCESSED_INPUT
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go:92: too many
errors
```
This commit is contained in:
Charlie Drage 2017-11-30 16:05:24 -05:00
parent 2f307b0f4e
commit 63e063818a
260 changed files with 67770 additions and 22015 deletions

50
glide.lock generated
View File

@ -1,5 +1,5 @@
hash: 0b7bed52681c512a3c15884363e1fd04ebc39efc52368cfa34ec4ef46f4eedc7 hash: 87294f197c8c1060ed67afa56f0b02c34785e9c1aa9e8e9096f7914350cc7283
updated: 2017-10-25T14:45:17.433498815+05:30 updated: 2017-11-30T15:50:41.408315905-05:00
imports: imports:
- name: cloud.google.com/go - name: cloud.google.com/go
version: 3b1ae45394a234c385be014e9a488f2bb6eef821 version: 3b1ae45394a234c385be014e9a488f2bb6eef821
@ -215,11 +215,11 @@ imports:
- name: github.com/evanphx/json-patch - name: github.com/evanphx/json-patch
version: 465937c80b3c07a7c7ad20cc934898646a91c1de version: 465937c80b3c07a7c7ad20cc934898646a91c1de
- name: github.com/fatih/structs - name: github.com/fatih/structs
version: dc3312cb1a4513a366c4c9e622ad55c32df12ed3 version: f5faa72e73092639913f5833b75e1ac1d6bc7a63
- name: github.com/flynn/go-shlex - name: github.com/flynn/go-shlex
version: 3f9db97f856818214da2e1057f8ad84803971cff version: 3f9db97f856818214da2e1057f8ad84803971cff
- name: github.com/fsnotify/fsnotify - name: github.com/fsnotify/fsnotify
version: 629574ca2a5df945712d3079857300b5e4da0236 version: 4da3e2cfbabc9f751898f250b49f2439785783a1
- name: github.com/fsouza/go-dockerclient - name: github.com/fsouza/go-dockerclient
version: bf97c77db7c945cbcdbf09d56c6f87a66f54537b version: bf97c77db7c945cbcdbf09d56c6f87a66f54537b
subpackages: subpackages:
@ -337,7 +337,7 @@ imports:
- runtime/internal - runtime/internal
- utilities - utilities
- name: github.com/hashicorp/hcl - name: github.com/hashicorp/hcl
version: 37ab263305aaeb501a60eb16863e808d426e37f2 version: 23c074d0eceb2b8a5bfdbb271ab780cde70f05a8
subpackages: subpackages:
- hcl/ast - hcl/ast
- hcl/parser - hcl/parser
@ -352,13 +352,13 @@ imports:
- name: github.com/inconshreveable/mousetrap - name: github.com/inconshreveable/mousetrap
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
- name: github.com/joho/godotenv - name: github.com/joho/godotenv
version: a79fa1e548e2c689c241d10173efd51e5d689d5b version: 6d367c18edf6ca7fd004efd6863e4c5728fa858e
- name: github.com/jonboulle/clockwork - name: github.com/jonboulle/clockwork
version: 3f831b65b61282ba6bece21b91beea2edc4c887a version: 3f831b65b61282ba6bece21b91beea2edc4c887a
- name: github.com/juju/ratelimit - name: github.com/juju/ratelimit
version: 77ed1c8a01217656d2080ad51981f6e99adaa177 version: 77ed1c8a01217656d2080ad51981f6e99adaa177
- name: github.com/magiconair/properties - name: github.com/magiconair/properties
version: be5ece7dd465ab0765a9682137865547526d1dfb version: 49d762b9817ba1c2e9d0c69183c2b4a8b8f1d934
- name: github.com/mattn/go-shellwords - name: github.com/mattn/go-shellwords
version: 95c860c1895b21b58903abdd1d9c591560b0601c version: 95c860c1895b21b58903abdd1d9c591560b0601c
- name: github.com/matttproud/golang_protobuf_extensions - name: github.com/matttproud/golang_protobuf_extensions
@ -366,7 +366,7 @@ imports:
subpackages: subpackages:
- pbutil - pbutil
- name: github.com/mitchellh/mapstructure - name: github.com/mitchellh/mapstructure
version: 5a0325d7fafaac12dda6e7fb8bd222ec1b69875e version: 06020f85339e21b2478f756a78e295255ffa4d6a
- name: github.com/novln/docker-parser - name: github.com/novln/docker-parser
version: 6030251119d652af8ead44ac7907444227b64d56 version: 6030251119d652af8ead44ac7907444227b64d56
subpackages: subpackages:
@ -376,7 +376,7 @@ imports:
- name: github.com/opencontainers/go-digest - name: github.com/opencontainers/go-digest
version: 279bed98673dd5bef374d3b6e4b09e2af76183bf version: 279bed98673dd5bef374d3b6e4b09e2af76183bf
- name: github.com/opencontainers/image-spec - name: github.com/opencontainers/image-spec
version: 7c889fafd04a893f5c5f50b7ab9963d5d64e5242 version: 577479e4dc273d3779f00c223c7e0dba4cd6b8b0
subpackages: subpackages:
- specs-go - specs-go
- specs-go/v1 - specs-go/v1
@ -426,12 +426,10 @@ imports:
- pkg/version - pkg/version
- name: github.com/pborman/uuid - name: github.com/pborman/uuid
version: ca53cad383cad2479bbba7f7a1a05797ec1386e4 version: ca53cad383cad2479bbba7f7a1a05797ec1386e4
- name: github.com/pelletier/go-buffruneio
version: c37440a7cf42ac63b919c752ca73a85067e05992
- name: github.com/pelletier/go-toml - name: github.com/pelletier/go-toml
version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a version: 4e9e0ee19b60b13eb79915933f44d8ed5f268bdd
- name: github.com/pkg/errors - name: github.com/pkg/errors
version: 645ef00459ed84a119197bfb8d8205042c6df63d version: f15c970de5b76fac0b59abb32d62c17cc7bed265
- name: github.com/prometheus/client_golang - name: github.com/prometheus/client_golang
version: e51041b3fa41cece0dca035740ba6411905be473 version: e51041b3fa41cece0dca035740ba6411905be473
subpackages: subpackages:
@ -448,26 +446,26 @@ imports:
- model - model
- name: github.com/prometheus/procfs - name: github.com/prometheus/procfs
version: 454a56f35412459b5e684fd5ec0f9211b94f002a version: 454a56f35412459b5e684fd5ec0f9211b94f002a
- name: github.com/Sirupsen/logrus
version: f006c2ac4710855cf0f916dd6b77acf6b048dc6e
repo: git@github.com:/sirupsen/logrus
vcs: git
- name: github.com/sirupsen/logrus - name: github.com/sirupsen/logrus
version: f006c2ac4710855cf0f916dd6b77acf6b048dc6e version: f006c2ac4710855cf0f916dd6b77acf6b048dc6e
- name: github.com/Sirupsen/logrus
version: aaf92c95712104318fc35409745f1533aa5ff327
subpackages:
- formatters/logstash
- name: github.com/spf13/afero - name: github.com/spf13/afero
version: 2f30b2a92c0e5700bcfe4715891adb1f2a7a406d version: 8d919cbe7e2627e417f3e45c3c0e489a5b7e2536
subpackages: subpackages:
- mem - mem
- name: github.com/spf13/cast - name: github.com/spf13/cast
version: 24b6558033ffe202bf42f0f3b870dcc798dd2ba8 version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
- name: github.com/spf13/cobra - name: github.com/spf13/cobra
version: 9495bc009a56819bdb0ddbc1a373e29c140bc674 version: 1be1d2841c773c01bee8289f55f7463b6e2c2539
- name: github.com/spf13/jwalterweatherman - name: github.com/spf13/jwalterweatherman
version: 33c24e77fb80341fe7130ee7c594256ff08ccc46 version: 12bd96e66386c1960ab0f74ced1362f66f552f7b
- name: github.com/spf13/pflag - name: github.com/spf13/pflag
version: 5ccb023bc27df288a957c5e994cd44fd19619465 version: 4c012f6dcd9546820e378d0bdda4d8fc772cdfea
- name: github.com/spf13/viper - name: github.com/spf13/viper
version: 651d9d916abc3c3d6a91a12549495caba5edffd2 version: 4dddf7c62e16bce5807744018f5b753bfe21bbd2
- name: github.com/ugorji/go - name: github.com/ugorji/go
version: f4485b318aadd133842532f841dc205a8e339d74 version: f4485b318aadd133842532f841dc205a8e339d74
subpackages: subpackages:
@ -479,7 +477,7 @@ imports:
- name: github.com/xeipuuv/gojsonschema - name: github.com/xeipuuv/gojsonschema
version: 93e72a773fade158921402d6a24c819b48aba29d version: 93e72a773fade158921402d6a24c819b48aba29d
- name: golang.org/x/crypto - name: golang.org/x/crypto
version: 81e90905daefcd6fd217b62423c0908922eadb30 version: 94eea52f7b742c7cbe0b03b22f0c4c8631ece122
subpackages: subpackages:
- ssh/terminal - ssh/terminal
- name: golang.org/x/net - name: golang.org/x/net
@ -505,7 +503,7 @@ imports:
- jws - jws
- jwt - jwt
- name: golang.org/x/sys - name: golang.org/x/sys
version: 833a04a10549a95dc34458c195cbad61bbb6cb4d version: ebfc5b4631820b793c9010c87fd8fef0f39eb082
subpackages: subpackages:
- unix - unix
- windows - windows
@ -548,7 +546,7 @@ imports:
- name: gopkg.in/inf.v0 - name: gopkg.in/inf.v0
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
- name: gopkg.in/yaml.v2 - name: gopkg.in/yaml.v2
version: a5b47d31c556af34a302ce5d659e6fea44d90de0 version: 287cf08546ab5e7e37d55a84f7ed3fd1db036de5
- name: k8s.io/client-go - name: k8s.io/client-go
version: d72c0e162789e1bbb33c33cfa26858a1375efe01 version: d72c0e162789e1bbb33c33cfa26858a1375efe01
subpackages: subpackages:

View File

@ -7,6 +7,9 @@ import:
- package: github.com/sirupsen/logrus - package: github.com/sirupsen/logrus
version: 1.0.3 version: 1.0.3
- package: golang.org/x/sys
version: ebfc5b4631820b793c9010c87fd8fef0f39eb082
- package: github.com/xeipuuv/gojsonschema - package: github.com/xeipuuv/gojsonschema
version: 93e72a773fade158921402d6a24c819b48aba29d version: 93e72a773fade158921402d6a24c819b48aba29d

View File

@ -530,15 +530,22 @@ func (s *Struct) nested(val reflect.Value) interface{} {
finalVal = m finalVal = m
} }
case reflect.Map: case reflect.Map:
v := val.Type().Elem() // get the element type of the map
if v.Kind() == reflect.Ptr { mapElem := val.Type()
v = v.Elem() switch val.Type().Kind() {
case reflect.Ptr, reflect.Array, reflect.Map,
reflect.Slice, reflect.Chan:
mapElem = val.Type().Elem()
if mapElem.Kind() == reflect.Ptr {
mapElem = mapElem.Elem()
}
} }
// only iterate over struct types, ie: map[string]StructType, // only iterate over struct types, ie: map[string]StructType,
// map[string][]StructType, // map[string][]StructType,
if v.Kind() == reflect.Struct || if mapElem.Kind() == reflect.Struct ||
(v.Kind() == reflect.Slice && v.Elem().Kind() == reflect.Struct) { (mapElem.Kind() == reflect.Slice &&
mapElem.Elem().Kind() == reflect.Struct) {
m := make(map[string]interface{}, val.Len()) m := make(map[string]interface{}, val.Len())
for _, k := range val.MapKeys() { for _, k := range val.MapKeys() {
m[k.String()] = s.nested(val.MapIndex(k)) m[k.String()] = s.nested(val.MapIndex(k))

View File

@ -5,7 +5,7 @@ import "strings"
// tagOptions contains a slice of tag options // tagOptions contains a slice of tag options
type tagOptions []string type tagOptions []string
// Has returns true if the given optiton is available in tagOptions // Has returns true if the given option is available in tagOptions
func (t tagOptions) Has(opt string) bool { func (t tagOptions) Has(opt string) bool {
for _, tagOpt := range t { for _, tagOpt := range t {
if tagOpt == opt { if tagOpt == opt {

View File

@ -9,6 +9,7 @@ package fsnotify
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
) )
@ -60,3 +61,6 @@ func (op Op) String() string {
func (e Event) String() string { func (e Event) String() string {
return fmt.Sprintf("%q: %s", e.Name, e.Op.String()) return fmt.Sprintf("%q: %s", e.Name, e.Op.String())
} }
// Common errors that can be reported by a watcher
var ErrEventOverflow = errors.New("fsnotify queue overflow")

View File

@ -24,7 +24,6 @@ type Watcher struct {
Events chan Event Events chan Event
Errors chan error Errors chan error
mu sync.Mutex // Map access mu sync.Mutex // Map access
cv *sync.Cond // sync removing on rm_watch with IN_IGNORE
fd int fd int
poller *fdPoller poller *fdPoller
watches map[string]*watch // Map of inotify watches (key: path) watches map[string]*watch // Map of inotify watches (key: path)
@ -56,7 +55,6 @@ func NewWatcher() (*Watcher, error) {
done: make(chan struct{}), done: make(chan struct{}),
doneResp: make(chan struct{}), doneResp: make(chan struct{}),
} }
w.cv = sync.NewCond(&w.mu)
go w.readEvents() go w.readEvents()
return w, nil return w, nil
@ -103,21 +101,23 @@ func (w *Watcher) Add(name string) error {
var flags uint32 = agnosticEvents var flags uint32 = agnosticEvents
w.mu.Lock() w.mu.Lock()
watchEntry, found := w.watches[name] defer w.mu.Unlock()
w.mu.Unlock() watchEntry := w.watches[name]
if found { if watchEntry != nil {
watchEntry.flags |= flags flags |= watchEntry.flags | unix.IN_MASK_ADD
flags |= unix.IN_MASK_ADD
} }
wd, errno := unix.InotifyAddWatch(w.fd, name, flags) wd, errno := unix.InotifyAddWatch(w.fd, name, flags)
if wd == -1 { if wd == -1 {
return errno return errno
} }
w.mu.Lock() if watchEntry == nil {
w.watches[name] = &watch{wd: uint32(wd), flags: flags} w.watches[name] = &watch{wd: uint32(wd), flags: flags}
w.paths[wd] = name w.paths[wd] = name
w.mu.Unlock() } else {
watchEntry.wd = uint32(wd)
watchEntry.flags = flags
}
return nil return nil
} }
@ -135,6 +135,13 @@ func (w *Watcher) Remove(name string) error {
if !ok { if !ok {
return fmt.Errorf("can't remove non-existent inotify watch for: %s", name) return fmt.Errorf("can't remove non-existent inotify watch for: %s", name)
} }
// We successfully removed the watch if InotifyRmWatch doesn't return an
// error, we need to clean up our internal state to ensure it matches
// inotify's kernel state.
delete(w.paths, int(watch.wd))
delete(w.watches, name)
// inotify_rm_watch will return EINVAL if the file has been deleted; // inotify_rm_watch will return EINVAL if the file has been deleted;
// the inotify will already have been removed. // the inotify will already have been removed.
// watches and pathes are deleted in ignoreLinux() implicitly and asynchronously // watches and pathes are deleted in ignoreLinux() implicitly and asynchronously
@ -152,13 +159,6 @@ func (w *Watcher) Remove(name string) error {
return errno return errno
} }
// wait until ignoreLinux() deleting maps
exists := true
for exists {
w.cv.Wait()
_, exists = w.watches[name]
}
return nil return nil
} }
@ -245,13 +245,31 @@ func (w *Watcher) readEvents() {
mask := uint32(raw.Mask) mask := uint32(raw.Mask)
nameLen := uint32(raw.Len) nameLen := uint32(raw.Len)
if mask&unix.IN_Q_OVERFLOW != 0 {
select {
case w.Errors <- ErrEventOverflow:
case <-w.done:
return
}
}
// If the event happened to the watched directory or the watched file, the kernel // If the event happened to the watched directory or the watched file, the kernel
// doesn't append the filename to the event, but we would like to always fill the // doesn't append the filename to the event, but we would like to always fill the
// the "Name" field with a valid filename. We retrieve the path of the watch from // the "Name" field with a valid filename. We retrieve the path of the watch from
// the "paths" map. // the "paths" map.
w.mu.Lock() w.mu.Lock()
name := w.paths[int(raw.Wd)] name, ok := w.paths[int(raw.Wd)]
// IN_DELETE_SELF occurs when the file/directory being watched is removed.
// This is a sign to clean up the maps, otherwise we are no longer in sync
// with the inotify kernel state which has already deleted the watch
// automatically.
if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
delete(w.paths, int(raw.Wd))
delete(w.watches, name)
}
w.mu.Unlock() w.mu.Unlock()
if nameLen > 0 { if nameLen > 0 {
// Point "bytes" at the first byte of the filename // Point "bytes" at the first byte of the filename
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent])) bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))
@ -262,7 +280,7 @@ func (w *Watcher) readEvents() {
event := newEvent(name, mask) event := newEvent(name, mask)
// Send the events that are not ignored on the events channel // Send the events that are not ignored on the events channel
if !event.ignoreLinux(w, raw.Wd, mask) { if !event.ignoreLinux(mask) {
select { select {
case w.Events <- event: case w.Events <- event:
case <-w.done: case <-w.done:
@ -279,15 +297,9 @@ func (w *Watcher) readEvents() {
// Certain types of events can be "ignored" and not sent over the Events // Certain types of events can be "ignored" and not sent over the Events
// channel. Such as events marked ignore by the kernel, or MODIFY events // channel. Such as events marked ignore by the kernel, or MODIFY events
// against files that do not exist. // against files that do not exist.
func (e *Event) ignoreLinux(w *Watcher, wd int32, mask uint32) bool { func (e *Event) ignoreLinux(mask uint32) bool {
// Ignore anything the inotify API says to ignore // Ignore anything the inotify API says to ignore
if mask&unix.IN_IGNORED == unix.IN_IGNORED { if mask&unix.IN_IGNORED == unix.IN_IGNORED {
w.mu.Lock()
defer w.mu.Unlock()
name := w.paths[int(wd)]
delete(w.paths, int(wd))
delete(w.watches, name)
w.cv.Broadcast()
return true return true
} }

View File

@ -89,7 +89,7 @@ func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error
switch k.Kind() { switch k.Kind() {
case reflect.Bool: case reflect.Bool:
return d.decodeBool(name, node, result) return d.decodeBool(name, node, result)
case reflect.Float64: case reflect.Float32, reflect.Float64:
return d.decodeFloat(name, node, result) return d.decodeFloat(name, node, result)
case reflect.Int, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int32, reflect.Int64:
return d.decodeInt(name, node, result) return d.decodeInt(name, node, result)
@ -137,13 +137,13 @@ func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) e
func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error { func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error {
switch n := node.(type) { switch n := node.(type) {
case *ast.LiteralType: case *ast.LiteralType:
if n.Token.Type == token.FLOAT { if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER {
v, err := strconv.ParseFloat(n.Token.Text, 64) v, err := strconv.ParseFloat(n.Token.Text, 64)
if err != nil { if err != nil {
return err return err
} }
result.Set(reflect.ValueOf(v)) result.Set(reflect.ValueOf(v).Convert(result.Type()))
return nil return nil
} }
} }
@ -573,7 +573,11 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
// Compile the list of all the fields that we're going to be decoding // Compile the list of all the fields that we're going to be decoding
// from all the structs. // from all the structs.
fields := make(map[*reflect.StructField]reflect.Value) type field struct {
field reflect.StructField
val reflect.Value
}
fields := []field{}
for len(structs) > 0 { for len(structs) > 0 {
structVal := structs[0] structVal := structs[0]
structs = structs[1:] structs = structs[1:]
@ -616,7 +620,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
} }
// Normal struct field, store it away // Normal struct field, store it away
fields[&fieldType] = structVal.Field(i) fields = append(fields, field{fieldType, structVal.Field(i)})
} }
} }
@ -624,26 +628,27 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
decodedFields := make([]string, 0, len(fields)) decodedFields := make([]string, 0, len(fields))
decodedFieldsVal := make([]reflect.Value, 0) decodedFieldsVal := make([]reflect.Value, 0)
unusedKeysVal := make([]reflect.Value, 0) unusedKeysVal := make([]reflect.Value, 0)
for fieldType, field := range fields { for _, f := range fields {
if !field.IsValid() { field, fieldValue := f.field, f.val
if !fieldValue.IsValid() {
// This should never happen // This should never happen
panic("field is not valid") panic("field is not valid")
} }
// If we can't set the field, then it is unexported or something, // If we can't set the field, then it is unexported or something,
// and we just continue onwards. // and we just continue onwards.
if !field.CanSet() { if !fieldValue.CanSet() {
continue continue
} }
fieldName := fieldType.Name fieldName := field.Name
tagValue := fieldType.Tag.Get(tagName) tagValue := field.Tag.Get(tagName)
tagParts := strings.SplitN(tagValue, ",", 2) tagParts := strings.SplitN(tagValue, ",", 2)
if len(tagParts) >= 2 { if len(tagParts) >= 2 {
switch tagParts[1] { switch tagParts[1] {
case "decodedFields": case "decodedFields":
decodedFieldsVal = append(decodedFieldsVal, field) decodedFieldsVal = append(decodedFieldsVal, fieldValue)
continue continue
case "key": case "key":
if item == nil { if item == nil {
@ -654,10 +659,10 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
} }
} }
field.SetString(item.Keys[0].Token.Value().(string)) fieldValue.SetString(item.Keys[0].Token.Value().(string))
continue continue
case "unusedKeys": case "unusedKeys":
unusedKeysVal = append(unusedKeysVal, field) unusedKeysVal = append(unusedKeysVal, fieldValue)
continue continue
} }
} }
@ -684,7 +689,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
// because we actually want the value. // because we actually want the value.
fieldName = fmt.Sprintf("%s.%s", name, fieldName) fieldName = fmt.Sprintf("%s.%s", name, fieldName)
if len(prefixMatches.Items) > 0 { if len(prefixMatches.Items) > 0 {
if err := d.decode(fieldName, prefixMatches, field); err != nil { if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil {
return err return err
} }
} }
@ -694,12 +699,12 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
decodeNode = &ast.ObjectList{Items: ot.List.Items} decodeNode = &ast.ObjectList{Items: ot.List.Items}
} }
if err := d.decode(fieldName, decodeNode, field); err != nil { if err := d.decode(fieldName, decodeNode, fieldValue); err != nil {
return err return err
} }
} }
decodedFields = append(decodedFields, fieldType.Name) decodedFields = append(decodedFields, field.Name)
} }
if len(decodedFieldsVal) > 0 { if len(decodedFieldsVal) > 0 {

View File

@ -3,6 +3,7 @@
package parser package parser
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"strings" "strings"
@ -36,6 +37,11 @@ func newParser(src []byte) *Parser {
// Parse returns the fully parsed source and returns the abstract syntax tree. // Parse returns the fully parsed source and returns the abstract syntax tree.
func Parse(src []byte) (*ast.File, error) { func Parse(src []byte) (*ast.File, error) {
// normalize all line endings
// since the scanner and output only work with "\n" line endings, we may
// end up with dangling "\r" characters in the parsed data.
src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1)
p := newParser(src) p := newParser(src)
return p.Parse() return p.Parse()
} }
@ -191,9 +197,12 @@ func (p *Parser) objectItem() (*ast.ObjectItem, error) {
keyStr = append(keyStr, k.Token.Text) keyStr = append(keyStr, k.Token.Text)
} }
return nil, fmt.Errorf( return nil, &PosError{
"key '%s' expected start of object ('{') or assignment ('=')", Pos: p.tok.Pos,
strings.Join(keyStr, " ")) Err: fmt.Errorf(
"key '%s' expected start of object ('{') or assignment ('=')",
strings.Join(keyStr, " ")),
}
} }
// do a look-ahead for line comment // do a look-ahead for line comment
@ -313,7 +322,10 @@ func (p *Parser) objectType() (*ast.ObjectType, error) {
// No error, scan and expect the ending to be a brace // No error, scan and expect the ending to be a brace
if tok := p.scan(); tok.Type != token.RBRACE { if tok := p.scan(); tok.Type != token.RBRACE {
return nil, fmt.Errorf("object expected closing RBRACE got: %s", tok.Type) return nil, &PosError{
Pos: tok.Pos,
Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type),
}
} }
o.List = l o.List = l
@ -346,7 +358,7 @@ func (p *Parser) listType() (*ast.ListType, error) {
} }
} }
switch tok.Type { switch tok.Type {
case token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC: case token.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC:
node, err := p.literalType() node, err := p.literalType()
if err != nil { if err != nil {
return nil, err return nil, err
@ -388,12 +400,16 @@ func (p *Parser) listType() (*ast.ListType, error) {
} }
l.Add(node) l.Add(node)
needComma = true needComma = true
case token.BOOL:
// TODO(arslan) should we support? not supported by HCL yet
case token.LBRACK: case token.LBRACK:
// TODO(arslan) should we support nested lists? Even though it's node, err := p.listType()
// written in README of HCL, it's not a part of the grammar if err != nil {
// (not defined in parse.y) return nil, &PosError{
Pos: tok.Pos,
Err: fmt.Errorf(
"error while trying to parse list within list: %s", err),
}
}
l.Add(node)
case token.RBRACK: case token.RBRACK:
// finished // finished
l.Rbrack = p.tok.Pos l.Rbrack = p.tok.Pos

View File

@ -351,7 +351,7 @@ func (s *Scanner) scanNumber(ch rune) token.Type {
return token.NUMBER return token.NUMBER
} }
// scanMantissa scans the mantissa begining from the rune. It returns the next // scanMantissa scans the mantissa beginning from the rune. It returns the next
// non decimal rune. It's used to determine wheter it's a fraction or exponent. // non decimal rune. It's used to determine wheter it's a fraction or exponent.
func (s *Scanner) scanMantissa(ch rune) rune { func (s *Scanner) scanMantissa(ch rune) rune {
scanned := false scanned := false

View File

@ -147,7 +147,7 @@ func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
// Done // Done
return keys, nil return keys, nil
case token.ILLEGAL: case token.ILLEGAL:
fmt.Println("illegal") return nil, errors.New("illegal")
default: default:
return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
} }

View File

@ -246,7 +246,7 @@ func (s *Scanner) scanNumber(ch rune) token.Type {
return token.NUMBER return token.NUMBER
} }
// scanMantissa scans the mantissa begining from the rune. It returns the next // scanMantissa scans the mantissa beginning from the rune. It returns the next
// non decimal rune. It's used to determine wheter it's a fraction or exponent. // non decimal rune. It's used to determine wheter it's a fraction or exponent.
func (s *Scanner) scanMantissa(ch rune) rune { func (s *Scanner) scanMantissa(ch rune) rune {
scanned := false scanned := false

View File

@ -196,9 +196,8 @@ func lexBeforeKey(l *lexer) stateFn {
return lexComment return lexComment
case isWhitespace(r): case isWhitespace(r):
l.acceptRun(whitespace)
l.ignore() l.ignore()
return lexKey return lexBeforeKey
default: default:
l.backup() l.backup()

View File

@ -511,6 +511,9 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
if p.DisableExpansion { if p.DisableExpansion {
prev, ok = p.Get(key) prev, ok = p.Get(key)
p.m[key] = value p.m[key] = value
if !ok {
p.k = append(p.k, key)
}
return prev, ok, nil return prev, ok, nil
} }

View File

@ -38,12 +38,6 @@ func DecodeHookExec(
raw DecodeHookFunc, raw DecodeHookFunc,
from reflect.Type, to reflect.Type, from reflect.Type, to reflect.Type,
data interface{}) (interface{}, error) { data interface{}) (interface{}, error) {
// Build our arguments that reflect expects
argVals := make([]reflect.Value, 3)
argVals[0] = reflect.ValueOf(from)
argVals[1] = reflect.ValueOf(to)
argVals[2] = reflect.ValueOf(data)
switch f := typedDecodeHook(raw).(type) { switch f := typedDecodeHook(raw).(type) {
case DecodeHookFuncType: case DecodeHookFuncType:
return f(from, to, data) return f(from, to, data)
@ -121,6 +115,11 @@ func StringToTimeDurationHookFunc() DecodeHookFunc {
} }
} }
// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
// the decoder.
//
// Note that this is significantly different from the WeaklyTypedInput option
// of the DecoderConfig.
func WeaklyTypedHook( func WeaklyTypedHook(
f reflect.Kind, f reflect.Kind,
t reflect.Kind, t reflect.Kind,
@ -132,9 +131,8 @@ func WeaklyTypedHook(
case reflect.Bool: case reflect.Bool:
if dataVal.Bool() { if dataVal.Bool() {
return "1", nil return "1", nil
} else {
return "0", nil
} }
return "0", nil
case reflect.Float32: case reflect.Float32:
return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
case reflect.Int: case reflect.Int:

View File

@ -1,5 +1,5 @@
// The mapstructure package exposes functionality to convert an // Package mapstructure exposes functionality to convert an arbitrary
// arbitrary map[string]interface{} into a native Go structure. // map[string]interface{} into a native Go structure.
// //
// The Go structure can be arbitrarily complex, containing slices, // The Go structure can be arbitrarily complex, containing slices,
// other structs, etc. and the decoder will properly decode nested // other structs, etc. and the decoder will properly decode nested
@ -32,7 +32,12 @@ import (
// both. // both.
type DecodeHookFunc interface{} type DecodeHookFunc interface{}
// DecodeHookFuncType is a DecodeHookFunc which has complete information about
// the source and target types.
type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
// source and target types.
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
// DecoderConfig is the configuration that is used to create a new decoder // DecoderConfig is the configuration that is used to create a new decoder
@ -69,6 +74,9 @@ type DecoderConfig struct {
// - empty array = empty map and vice versa // - empty array = empty map and vice versa
// - negative numbers to overflowed uint values (base 10) // - negative numbers to overflowed uint values (base 10)
// - slice of maps to a merged map // - slice of maps to a merged map
// - single values are converted to slices if required. Each
// element is weakly decoded. For example: "4" can become []int{4}
// if the target type is an int slice.
// //
WeaklyTypedInput bool WeaklyTypedInput bool
@ -202,7 +210,7 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error
d.config.DecodeHook, d.config.DecodeHook,
dataVal.Type(), val.Type(), data) dataVal.Type(), val.Type(), data)
if err != nil { if err != nil {
return err return fmt.Errorf("error decoding '%s': %s", name, err)
} }
} }
@ -229,6 +237,8 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error
err = d.decodePtr(name, data, val) err = d.decodePtr(name, data, val)
case reflect.Slice: case reflect.Slice:
err = d.decodeSlice(name, data, val) err = d.decodeSlice(name, data, val)
case reflect.Func:
err = d.decodeFunc(name, data, val)
default: default:
// If we reached this point then we weren't able to decode it // If we reached this point then we weren't able to decode it
return fmt.Errorf("%s: unsupported type: %s", name, dataKind) return fmt.Errorf("%s: unsupported type: %s", name, dataKind)
@ -431,7 +441,7 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
case dataKind == reflect.Uint: case dataKind == reflect.Uint:
val.SetFloat(float64(dataVal.Uint())) val.SetFloat(float64(dataVal.Uint()))
case dataKind == reflect.Float32: case dataKind == reflect.Float32:
val.SetFloat(float64(dataVal.Float())) val.SetFloat(dataVal.Float())
case dataKind == reflect.Bool && d.config.WeaklyTypedInput: case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
if dataVal.Bool() { if dataVal.Bool() {
val.SetFloat(1) val.SetFloat(1)
@ -546,7 +556,12 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) er
// into that. Then set the value of the pointer to this type. // into that. Then set the value of the pointer to this type.
valType := val.Type() valType := val.Type()
valElemType := valType.Elem() valElemType := valType.Elem()
realVal := reflect.New(valElemType)
realVal := val
if realVal.IsNil() || d.config.ZeroFields {
realVal = reflect.New(valElemType)
}
if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil {
return err return err
} }
@ -555,6 +570,19 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) er
return nil return nil
} }
func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
// Create an element of the concrete (non pointer) type and decode
// into that. Then set the value of the pointer to this type.
dataVal := reflect.Indirect(reflect.ValueOf(data))
if val.Type() != dataVal.Type() {
return fmt.Errorf(
"'%s' expected type '%s', got unconvertible type '%s'",
name, val.Type(), dataVal.Type())
}
val.Set(dataVal)
return nil
}
func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data)) dataVal := reflect.Indirect(reflect.ValueOf(data))
dataValKind := dataVal.Kind() dataValKind := dataVal.Kind()
@ -562,26 +590,44 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
valElemType := valType.Elem() valElemType := valType.Elem()
sliceType := reflect.SliceOf(valElemType) sliceType := reflect.SliceOf(valElemType)
// Check input type valSlice := val
if dataValKind != reflect.Array && dataValKind != reflect.Slice { if valSlice.IsNil() || d.config.ZeroFields {
// Accept empty map instead of array/slice in weakly typed mode // Check input type
if d.config.WeaklyTypedInput && dataVal.Kind() == reflect.Map && dataVal.Len() == 0 { if dataValKind != reflect.Array && dataValKind != reflect.Slice {
val.Set(reflect.MakeSlice(sliceType, 0, 0)) if d.config.WeaklyTypedInput {
return nil switch {
} else { // Empty maps turn into empty slices
case dataValKind == reflect.Map:
if dataVal.Len() == 0 {
val.Set(reflect.MakeSlice(sliceType, 0, 0))
return nil
}
// All other types we try to convert to the slice type
// and "lift" it into it. i.e. a string becomes a string slice.
default:
// Just re-try this function with data as a slice.
return d.decodeSlice(name, []interface{}{data}, val)
}
}
return fmt.Errorf( return fmt.Errorf(
"'%s': source data must be an array or slice, got %s", name, dataValKind) "'%s': source data must be an array or slice, got %s", name, dataValKind)
}
}
// Make a new slice to hold our result, same size as the original data. }
valSlice := reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
// Make a new slice to hold our result, same size as the original data.
valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
}
// Accumulate any errors // Accumulate any errors
errors := make([]string, 0) errors := make([]string, 0)
for i := 0; i < dataVal.Len(); i++ { for i := 0; i < dataVal.Len(); i++ {
currentData := dataVal.Index(i).Interface() currentData := dataVal.Index(i).Interface()
for valSlice.Len() <= i {
valSlice = reflect.Append(valSlice, reflect.Zero(valElemType))
}
currentField := valSlice.Index(i) currentField := valSlice.Index(i)
fieldName := fmt.Sprintf("%s[%d]", name, i) fieldName := fmt.Sprintf("%s[%d]", name, i)
@ -640,7 +686,11 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
// Compile the list of all the fields that we're going to be decoding // Compile the list of all the fields that we're going to be decoding
// from all the structs. // from all the structs.
fields := make(map[*reflect.StructField]reflect.Value) type field struct {
field reflect.StructField
val reflect.Value
}
fields := []field{}
for len(structs) > 0 { for len(structs) > 0 {
structVal := structs[0] structVal := structs[0]
structs = structs[1:] structs = structs[1:]
@ -672,14 +722,16 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
} }
// Normal struct field, store it away // Normal struct field, store it away
fields[&fieldType] = structVal.Field(i) fields = append(fields, field{fieldType, structVal.Field(i)})
} }
} }
for fieldType, field := range fields { // for fieldType, field := range fields {
fieldName := fieldType.Name for _, f := range fields {
field, fieldValue := f.field, f.val
fieldName := field.Name
tagValue := fieldType.Tag.Get(d.config.TagName) tagValue := field.Tag.Get(d.config.TagName)
tagValue = strings.SplitN(tagValue, ",", 2)[0] tagValue = strings.SplitN(tagValue, ",", 2)[0]
if tagValue != "" { if tagValue != "" {
fieldName = tagValue fieldName = tagValue
@ -714,14 +766,14 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
// Delete the key we're using from the unused map so we stop tracking // Delete the key we're using from the unused map so we stop tracking
delete(dataValKeysUnused, rawMapKey.Interface()) delete(dataValKeysUnused, rawMapKey.Interface())
if !field.IsValid() { if !fieldValue.IsValid() {
// This should never happen // This should never happen
panic("field is not valid") panic("field is not valid")
} }
// If we can't set the field, then it is unexported or something, // If we can't set the field, then it is unexported or something,
// and we just continue onwards. // and we just continue onwards.
if !field.CanSet() { if !fieldValue.CanSet() {
continue continue
} }
@ -731,7 +783,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
fieldName = fmt.Sprintf("%s.%s", name, fieldName) fieldName = fmt.Sprintf("%s.%s", name, fieldName)
} }
if err := d.decode(fieldName, rawMapVal.Interface(), field); err != nil { if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil {
errors = appendErrors(errors, err) errors = appendErrors(errors, err)
} }
} }

View File

@ -1,117 +0,0 @@
// Package buffruneio is a wrapper around bufio to provide buffered runes access with unlimited unreads.
package buffruneio
import (
"bufio"
"container/list"
"errors"
"io"
)
// Rune to indicate end of file.
const (
EOF = -(iota + 1)
)
// ErrNoRuneToUnread is returned by UnreadRune() when the read index is already at the beginning of the buffer.
var ErrNoRuneToUnread = errors.New("no rune to unwind")
// Reader implements runes buffering for an io.Reader object.
type Reader struct {
buffer *list.List
current *list.Element
input *bufio.Reader
}
// NewReader returns a new Reader.
func NewReader(rd io.Reader) *Reader {
return &Reader{
buffer: list.New(),
input: bufio.NewReader(rd),
}
}
type runeWithSize struct {
r rune
size int
}
func (rd *Reader) feedBuffer() error {
r, size, err := rd.input.ReadRune()
if err != nil {
if err != io.EOF {
return err
}
r = EOF
}
newRuneWithSize := runeWithSize{r, size}
rd.buffer.PushBack(newRuneWithSize)
if rd.current == nil {
rd.current = rd.buffer.Back()
}
return nil
}
// ReadRune reads the next rune from buffer, or from the underlying reader if needed.
func (rd *Reader) ReadRune() (rune, int, error) {
if rd.current == rd.buffer.Back() || rd.current == nil {
err := rd.feedBuffer()
if err != nil {
return EOF, 0, err
}
}
runeWithSize := rd.current.Value.(runeWithSize)
rd.current = rd.current.Next()
return runeWithSize.r, runeWithSize.size, nil
}
// UnreadRune pushes back the previously read rune in the buffer, extending it if needed.
func (rd *Reader) UnreadRune() error {
if rd.current == rd.buffer.Front() {
return ErrNoRuneToUnread
}
if rd.current == nil {
rd.current = rd.buffer.Back()
} else {
rd.current = rd.current.Prev()
}
return nil
}
// Forget removes runes stored before the current stream position index.
func (rd *Reader) Forget() {
if rd.current == nil {
rd.current = rd.buffer.Back()
}
for ; rd.current != rd.buffer.Front(); rd.buffer.Remove(rd.current.Prev()) {
}
}
// PeekRune returns at most the next n runes, reading from the uderlying source if
// needed. Does not move the current index. It includes EOF if reached.
func (rd *Reader) PeekRunes(n int) []rune {
res := make([]rune, 0, n)
cursor := rd.current
for i := 0; i < n; i++ {
if cursor == nil {
err := rd.feedBuffer()
if err != nil {
return res
}
cursor = rd.buffer.Back()
}
if cursor != nil {
r := cursor.Value.(runeWithSize).r
res = append(res, r)
if r == EOF {
return res
}
cursor = cursor.Next()
}
}
return res
}

View File

@ -1,250 +1,23 @@
// Package toml is a TOML markup language parser. // Package toml is a TOML parser and manipulation library.
// //
// This version supports the specification as described in // This version supports the specification as described in
// https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md // https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md
// //
// TOML Parsing // Marshaling
// //
// TOML data may be parsed in two ways: by file, or by string. // Go-toml can marshal and unmarshal TOML documents from and to data
// structures.
// //
// // load TOML data by filename // TOML document as a tree
// tree, err := toml.LoadFile("filename.toml")
// //
// // load TOML data stored in a string // Go-toml can operate on a TOML document as a tree. Use one of the Load*
// tree, err := toml.Load(stringContainingTomlData) // functions to parse TOML data and obtain a Tree instance, then one of its
// methods to manipulate the tree.
// //
// Either way, the result is a TomlTree object that can be used to navigate the // JSONPath-like queries
// structure and data within the original document.
// //
// // The package github.com/pelletier/go-toml/query implements a system
// Getting data from the TomlTree // similar to JSONPath to quickly retrieve elements of a TOML document using a
// // single expression. See the package documentation for more information.
// After parsing TOML data with Load() or LoadFile(), use the Has() and Get()
// methods on the returned TomlTree, to find your way through the document data.
//
// if tree.Has("foo") {
// fmt.Println("foo is:", tree.Get("foo"))
// }
//
// Working with Paths
//
// Go-toml has support for basic dot-separated key paths on the Has(), Get(), Set()
// and GetDefault() methods. These are the same kind of key paths used within the
// TOML specification for struct tames.
//
// // looks for a key named 'baz', within struct 'bar', within struct 'foo'
// tree.Has("foo.bar.baz")
//
// // returns the key at this path, if it is there
// tree.Get("foo.bar.baz")
//
// TOML allows keys to contain '.', which can cause this syntax to be problematic
// for some documents. In such cases, use the GetPath(), HasPath(), and SetPath(),
// methods to explicitly define the path. This form is also faster, since
// it avoids having to parse the passed key for '.' delimiters.
//
// // looks for a key named 'baz', within struct 'bar', within struct 'foo'
// tree.HasPath([]string{"foo","bar","baz"})
//
// // returns the key at this path, if it is there
// tree.GetPath([]string{"foo","bar","baz"})
//
// Note that this is distinct from the heavyweight query syntax supported by
// TomlTree.Query() and the Query() struct (see below).
//
// Position Support
//
// Each element within the TomlTree is stored with position metadata, which is
// invaluable for providing semantic feedback to a user. This helps in
// situations where the TOML file parses correctly, but contains data that is
// not correct for the application. In such cases, an error message can be
// generated that indicates the problem line and column number in the source
// TOML document.
//
// // load TOML data
// tree, _ := toml.Load("filename.toml")
//
// // get an entry and report an error if it's the wrong type
// element := tree.Get("foo")
// if value, ok := element.(int64); !ok {
// return fmt.Errorf("%v: Element 'foo' must be an integer", tree.GetPosition("foo"))
// }
//
// // report an error if an expected element is missing
// if !tree.Has("bar") {
// return fmt.Errorf("%v: Expected 'bar' element", tree.GetPosition(""))
// }
//
// Query Support
//
// The TOML query path implementation is based loosely on the JSONPath specification:
// http://goessner.net/articles/JsonPath/
//
// The idea behind a query path is to allow quick access to any element, or set
// of elements within TOML document, with a single expression.
//
// result, err := tree.Query("$.foo.bar.baz")
//
// This is roughly equivalent to:
//
// next := tree.Get("foo")
// if next != nil {
// next = next.Get("bar")
// if next != nil {
// next = next.Get("baz")
// }
// }
// result := next
//
// err is nil if any parsing exception occurs.
//
// If no node in the tree matches the query, result will simply contain an empty list of
// items.
//
// As illustrated above, the query path is much more efficient, especially since
// the structure of the TOML file can vary. Rather than making assumptions about
// a document's structure, a query allows the programmer to make structured
// requests into the document, and get zero or more values as a result.
//
// The syntax of a query begins with a root token, followed by any number
// sub-expressions:
//
// $
// Root of the TOML tree. This must always come first.
// .name
// Selects child of this node, where 'name' is a TOML key
// name.
// ['name']
// Selects child of this node, where 'name' is a string
// containing a TOML key name.
// [index]
// Selcts child array element at 'index'.
// ..expr
// Recursively selects all children, filtered by an a union,
// index, or slice expression.
// ..*
// Recursive selection of all nodes at this point in the
// tree.
// .*
// Selects all children of the current node.
// [expr,expr]
// Union operator - a logical 'or' grouping of two or more
// sub-expressions: index, key name, or filter.
// [start:end:step]
// Slice operator - selects array elements from start to
// end-1, at the given step. All three arguments are
// optional.
// [?(filter)]
// Named filter expression - the function 'filter' is
// used to filter children at this node.
//
// Query Indexes And Slices
//
// Index expressions perform no bounds checking, and will contribute no
// values to the result set if the provided index or index range is invalid.
// Negative indexes represent values from the end of the array, counting backwards.
//
// // select the last index of the array named 'foo'
// tree.Query("$.foo[-1]")
//
// Slice expressions are supported, by using ':' to separate a start/end index pair.
//
// // select up to the first five elements in the array
// tree.Query("$.foo[0:5]")
//
// Slice expressions also allow negative indexes for the start and stop
// arguments.
//
// // select all array elements.
// tree.Query("$.foo[0:-1]")
//
// Slice expressions may have an optional stride/step parameter:
//
// // select every other element
// tree.Query("$.foo[0:-1:2]")
//
// Slice start and end parameters are also optional:
//
// // these are all equivalent and select all the values in the array
// tree.Query("$.foo[:]")
// tree.Query("$.foo[0:]")
// tree.Query("$.foo[:-1]")
// tree.Query("$.foo[0:-1:]")
// tree.Query("$.foo[::1]")
// tree.Query("$.foo[0::1]")
// tree.Query("$.foo[:-1:1]")
// tree.Query("$.foo[0:-1:1]")
//
// Query Filters
//
// Query filters are used within a Union [,] or single Filter [] expression.
// A filter only allows nodes that qualify through to the next expression,
// and/or into the result set.
//
// // returns children of foo that are permitted by the 'bar' filter.
// tree.Query("$.foo[?(bar)]")
//
// There are several filters provided with the library:
//
// tree
// Allows nodes of type TomlTree.
// int
// Allows nodes of type int64.
// float
// Allows nodes of type float64.
// string
// Allows nodes of type string.
// time
// Allows nodes of type time.Time.
// bool
// Allows nodes of type bool.
//
// Query Results
//
// An executed query returns a QueryResult object. This contains the nodes
// in the TOML tree that qualify the query expression. Position information
// is also available for each value in the set.
//
// // display the results of a query
// results := tree.Query("$.foo.bar.baz")
// for idx, value := results.Values() {
// fmt.Println("%v: %v", results.Positions()[idx], value)
// }
//
// Compiled Queries
//
// Queries may be executed directly on a TomlTree object, or compiled ahead
// of time and executed discretely. The former is more convienent, but has the
// penalty of having to recompile the query expression each time.
//
// // basic query
// results := tree.Query("$.foo.bar.baz")
//
// // compiled query
// query := toml.CompileQuery("$.foo.bar.baz")
// results := query.Execute(tree)
//
// // run the compiled query again on a different tree
// moreResults := query.Execute(anotherTree)
//
// User Defined Query Filters
//
// Filter expressions may also be user defined by using the SetFilter()
// function on the Query object. The function must return true/false, which
// signifies if the passed node is kept or discarded, respectively.
//
// // create a query that references a user-defined filter
// query, _ := CompileQuery("$[?(bazOnly)]")
//
// // define the filter, and assign it to the query
// query.SetFilter("bazOnly", func(node interface{}) bool{
// if tree, ok := node.(*TomlTree); ok {
// return tree.Has("baz")
// }
// return false // reject all other node types
// })
//
// // run the query
// query.Execute(tree)
// //
package toml package toml

31
vendor/github.com/pelletier/go-toml/fuzz.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
// +build gofuzz
package toml
func Fuzz(data []byte) int {
tree, err := LoadBytes(data)
if err != nil {
if tree != nil {
panic("tree must be nil if there is an error")
}
return 0
}
str, err := tree.ToTomlString()
if err != nil {
if str != "" {
panic(`str must be "" if there is an error`)
}
panic(err)
}
tree, err = Load(str)
if err != nil {
if tree != nil {
panic("tree must be nil if there is an error")
}
return 0
}
return 1
}

View File

@ -6,15 +6,37 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"strconv"
"unicode" "unicode"
) )
var escapeSequenceMap = map[rune]rune{
'b': '\b',
't': '\t',
'n': '\n',
'f': '\f',
'r': '\r',
'"': '"',
'\\': '\\',
}
type parseKeyState int
const (
BARE parseKeyState = iota
BASIC
LITERAL
ESC
UNICODE_4
UNICODE_8
)
func parseKey(key string) ([]string, error) { func parseKey(key string) ([]string, error) {
groups := []string{} groups := []string{}
var buffer bytes.Buffer var buffer bytes.Buffer
inQuotes := false var hex bytes.Buffer
state := BARE
wasInQuotes := false wasInQuotes := false
escapeNext := false
ignoreSpace := true ignoreSpace := true
expectDot := false expectDot := false
@ -25,25 +47,67 @@ func parseKey(key string) ([]string, error) {
} }
ignoreSpace = false ignoreSpace = false
} }
if escapeNext {
buffer.WriteRune(char) if state == ESC {
escapeNext = false if char == 'u' {
state = UNICODE_4
hex.Reset()
} else if char == 'U' {
state = UNICODE_8
hex.Reset()
} else if newChar, ok := escapeSequenceMap[char]; ok {
buffer.WriteRune(newChar)
state = BASIC
} else {
return nil, fmt.Errorf(`invalid escape sequence \%c`, char)
}
continue continue
} }
if state == UNICODE_4 || state == UNICODE_8 {
if isHexDigit(char) {
hex.WriteRune(char)
}
if (state == UNICODE_4 && hex.Len() == 4) || (state == UNICODE_8 && hex.Len() == 8) {
if value, err := strconv.ParseInt(hex.String(), 16, 32); err == nil {
buffer.WriteRune(rune(value))
} else {
return nil, err
}
state = BASIC
}
continue
}
switch char { switch char {
case '\\': case '\\':
escapeNext = true if state == BASIC {
continue state = ESC
case '"': } else if state == LITERAL {
if inQuotes { buffer.WriteRune(char)
}
case '\'':
if state == BARE {
state = LITERAL
} else if state == LITERAL {
groups = append(groups, buffer.String()) groups = append(groups, buffer.String())
buffer.Reset() buffer.Reset()
wasInQuotes = true wasInQuotes = true
state = BARE
}
expectDot = false
case '"':
if state == BARE {
state = BASIC
} else if state == BASIC {
groups = append(groups, buffer.String())
buffer.Reset()
state = BARE
wasInQuotes = true
} }
inQuotes = !inQuotes
expectDot = false expectDot = false
case '.': case '.':
if inQuotes { if state != BARE {
buffer.WriteRune(char) buffer.WriteRune(char)
} else { } else {
if !wasInQuotes { if !wasInQuotes {
@ -58,28 +122,31 @@ func parseKey(key string) ([]string, error) {
wasInQuotes = false wasInQuotes = false
} }
case ' ': case ' ':
if inQuotes { if state == BASIC {
buffer.WriteRune(char) buffer.WriteRune(char)
} else { } else {
expectDot = true expectDot = true
} }
default: default:
if !inQuotes && !isValidBareChar(char) { if state == BARE {
return nil, fmt.Errorf("invalid bare character: %c", char) if !isValidBareChar(char) {
} return nil, fmt.Errorf("invalid bare character: %c", char)
if !inQuotes && expectDot { } else if expectDot {
return nil, errors.New("what?") return nil, errors.New("what?")
}
} }
buffer.WriteRune(char) buffer.WriteRune(char)
expectDot = false expectDot = false
} }
} }
if inQuotes {
// state must be BARE at the end
if state == ESC {
return nil, errors.New("unfinished escape sequence")
} else if state != BARE {
return nil, errors.New("mismatched quotes") return nil, errors.New("mismatched quotes")
} }
if escapeNext {
return nil, errors.New("unfinished escape sequence")
}
if buffer.Len() > 0 { if buffer.Len() > 0 {
groups = append(groups, buffer.String()) groups = append(groups, buffer.String())
} }

View File

@ -6,14 +6,12 @@
package toml package toml
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"io"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"github.com/pelletier/go-buffruneio"
) )
var dateRegexp *regexp.Regexp var dateRegexp *regexp.Regexp
@ -23,29 +21,29 @@ type tomlLexStateFn func() tomlLexStateFn
// Define lexer // Define lexer
type tomlLexer struct { type tomlLexer struct {
input *buffruneio.Reader // Textual source inputIdx int
buffer []rune // Runes composing the current token input []rune // Textual source
tokens chan token currentTokenStart int
depth int currentTokenStop int
line int tokens []token
col int depth int
endbufferLine int line int
endbufferCol int col int
endbufferLine int
endbufferCol int
} }
// Basic read operations on input // Basic read operations on input
func (l *tomlLexer) read() rune { func (l *tomlLexer) read() rune {
r, _, err := l.input.ReadRune() r := l.peek()
if err != nil {
panic(err)
}
if r == '\n' { if r == '\n' {
l.endbufferLine++ l.endbufferLine++
l.endbufferCol = 1 l.endbufferCol = 1
} else { } else {
l.endbufferCol++ l.endbufferCol++
} }
l.inputIdx++
return r return r
} }
@ -53,13 +51,13 @@ func (l *tomlLexer) next() rune {
r := l.read() r := l.read()
if r != eof { if r != eof {
l.buffer = append(l.buffer, r) l.currentTokenStop++
} }
return r return r
} }
func (l *tomlLexer) ignore() { func (l *tomlLexer) ignore() {
l.buffer = make([]rune, 0) l.currentTokenStart = l.currentTokenStop
l.line = l.endbufferLine l.line = l.endbufferLine
l.col = l.endbufferCol l.col = l.endbufferCol
} }
@ -76,49 +74,46 @@ func (l *tomlLexer) fastForward(n int) {
} }
func (l *tomlLexer) emitWithValue(t tokenType, value string) { func (l *tomlLexer) emitWithValue(t tokenType, value string) {
l.tokens <- token{ l.tokens = append(l.tokens, token{
Position: Position{l.line, l.col}, Position: Position{l.line, l.col},
typ: t, typ: t,
val: value, val: value,
} })
l.ignore() l.ignore()
} }
func (l *tomlLexer) emit(t tokenType) { func (l *tomlLexer) emit(t tokenType) {
l.emitWithValue(t, string(l.buffer)) l.emitWithValue(t, string(l.input[l.currentTokenStart:l.currentTokenStop]))
} }
func (l *tomlLexer) peek() rune { func (l *tomlLexer) peek() rune {
r, _, err := l.input.ReadRune() if l.inputIdx >= len(l.input) {
if err != nil { return eof
panic(err)
} }
l.input.UnreadRune() return l.input[l.inputIdx]
return r }
func (l *tomlLexer) peekString(size int) string {
maxIdx := len(l.input)
upperIdx := l.inputIdx + size // FIXME: potential overflow
if upperIdx > maxIdx {
upperIdx = maxIdx
}
return string(l.input[l.inputIdx:upperIdx])
} }
func (l *tomlLexer) follow(next string) bool { func (l *tomlLexer) follow(next string) bool {
for _, expectedRune := range next { return next == l.peekString(len(next))
r, _, err := l.input.ReadRune()
defer l.input.UnreadRune()
if err != nil {
panic(err)
}
if expectedRune != r {
return false
}
}
return true
} }
// Error management // Error management
func (l *tomlLexer) errorf(format string, args ...interface{}) tomlLexStateFn { func (l *tomlLexer) errorf(format string, args ...interface{}) tomlLexStateFn {
l.tokens <- token{ l.tokens = append(l.tokens, token{
Position: Position{l.line, l.col}, Position: Position{l.line, l.col},
typ: tokenError, typ: tokenError,
val: fmt.Sprintf(format, args...), val: fmt.Sprintf(format, args...),
} })
return nil return nil
} }
@ -219,7 +214,7 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn {
break break
} }
possibleDate := string(l.input.PeekRunes(35)) possibleDate := l.peekString(35)
dateMatch := dateRegexp.FindString(possibleDate) dateMatch := dateRegexp.FindString(possibleDate)
if dateMatch != "" { if dateMatch != "" {
l.fastForward(len(dateMatch)) l.fastForward(len(dateMatch))
@ -536,7 +531,7 @@ func (l *tomlLexer) lexInsideTableArrayKey() tomlLexStateFn {
for r := l.peek(); r != eof; r = l.peek() { for r := l.peek(); r != eof; r = l.peek() {
switch r { switch r {
case ']': case ']':
if len(l.buffer) > 0 { if l.currentTokenStop > l.currentTokenStart {
l.emit(tokenKeyGroupArray) l.emit(tokenKeyGroupArray)
} }
l.next() l.next()
@ -559,7 +554,7 @@ func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn {
for r := l.peek(); r != eof; r = l.peek() { for r := l.peek(); r != eof; r = l.peek() {
switch r { switch r {
case ']': case ']':
if len(l.buffer) > 0 { if l.currentTokenStop > l.currentTokenStart {
l.emit(tokenKeyGroup) l.emit(tokenKeyGroup)
} }
l.next() l.next()
@ -634,7 +629,6 @@ func (l *tomlLexer) run() {
for state := l.lexVoid; state != nil; { for state := l.lexVoid; state != nil; {
state = state() state = state()
} }
close(l.tokens)
} }
func init() { func init() {
@ -642,16 +636,16 @@ func init() {
} }
// Entry point // Entry point
func lexToml(input io.Reader) chan token { func lexToml(inputBytes []byte) []token {
bufferedInput := buffruneio.NewReader(input) runes := bytes.Runes(inputBytes)
l := &tomlLexer{ l := &tomlLexer{
input: bufferedInput, input: runes,
tokens: make(chan token), tokens: make([]token, 0, 256),
line: 1, line: 1,
col: 1, col: 1,
endbufferLine: 1, endbufferLine: 1,
endbufferCol: 1, endbufferCol: 1,
} }
go l.run() l.run()
return l.tokens return l.tokens
} }

621
vendor/github.com/pelletier/go-toml/marshal.go generated vendored Normal file
View File

@ -0,0 +1,621 @@
package toml
import (
"bytes"
"errors"
"fmt"
"io"
"reflect"
"strconv"
"strings"
"time"
)
type tomlOpts struct {
name string
comment string
commented bool
include bool
omitempty bool
}
type encOpts struct {
quoteMapKeys bool
}
var encOptsDefaults = encOpts{
quoteMapKeys: false,
}
var timeType = reflect.TypeOf(time.Time{})
var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
// Check if the given marshall type maps to a Tree primitive
func isPrimitive(mtype reflect.Type) bool {
switch mtype.Kind() {
case reflect.Ptr:
return isPrimitive(mtype.Elem())
case reflect.Bool:
return true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return true
case reflect.Float32, reflect.Float64:
return true
case reflect.String:
return true
case reflect.Struct:
return mtype == timeType || isCustomMarshaler(mtype)
default:
return false
}
}
// Check if the given marshall type maps to a Tree slice
func isTreeSlice(mtype reflect.Type) bool {
switch mtype.Kind() {
case reflect.Slice:
return !isOtherSlice(mtype)
default:
return false
}
}
// Check if the given marshall type maps to a non-Tree slice
func isOtherSlice(mtype reflect.Type) bool {
switch mtype.Kind() {
case reflect.Ptr:
return isOtherSlice(mtype.Elem())
case reflect.Slice:
return isPrimitive(mtype.Elem()) || isOtherSlice(mtype.Elem())
default:
return false
}
}
// Check if the given marshall type maps to a Tree
func isTree(mtype reflect.Type) bool {
switch mtype.Kind() {
case reflect.Map:
return true
case reflect.Struct:
return !isPrimitive(mtype)
default:
return false
}
}
func isCustomMarshaler(mtype reflect.Type) bool {
return mtype.Implements(marshalerType)
}
func callCustomMarshaler(mval reflect.Value) ([]byte, error) {
return mval.Interface().(Marshaler).MarshalTOML()
}
// Marshaler is the interface implemented by types that
// can marshal themselves into valid TOML.
type Marshaler interface {
MarshalTOML() ([]byte, error)
}
/*
Marshal returns the TOML encoding of v. Behavior is similar to the Go json
encoder, except that there is no concept of a Marshaler interface or MarshalTOML
function for sub-structs, and currently only definite types can be marshaled
(i.e. no `interface{}`).
The following struct annotations are supported:
toml:"Field" Overrides the field's name to output.
omitempty When set, empty values and groups are not emitted.
comment:"comment" Emits a # comment on the same line. This supports new lines.
commented:"true" Emits the value as commented.
Note that pointers are automatically assigned the "omitempty" option, as TOML
explicitly does not handle null values (saying instead the label should be
dropped).
Tree structural types and corresponding marshal types:
*Tree (*)struct, (*)map[string]interface{}
[]*Tree (*)[](*)struct, (*)[](*)map[string]interface{}
[]interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{})
interface{} (*)primitive
Tree primitive types and corresponding marshal types:
uint64 uint, uint8-uint64, pointers to same
int64 int, int8-uint64, pointers to same
float64 float32, float64, pointers to same
string string, pointers to same
bool bool, pointers to same
time.Time time.Time{}, pointers to same
*/
func Marshal(v interface{}) ([]byte, error) {
return NewEncoder(nil).marshal(v)
}
// Encoder writes TOML values to an output stream.
type Encoder struct {
w io.Writer
encOpts
}
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{
w: w,
encOpts: encOptsDefaults,
}
}
// Encode writes the TOML encoding of v to the stream.
//
// See the documentation for Marshal for details.
func (e *Encoder) Encode(v interface{}) error {
b, err := e.marshal(v)
if err != nil {
return err
}
if _, err := e.w.Write(b); err != nil {
return err
}
return nil
}
// QuoteMapKeys sets up the encoder to encode
// maps with string type keys with quoted TOML keys.
//
// This relieves the character limitations on map keys.
func (e *Encoder) QuoteMapKeys(v bool) *Encoder {
e.quoteMapKeys = v
return e
}
func (e *Encoder) marshal(v interface{}) ([]byte, error) {
mtype := reflect.TypeOf(v)
if mtype.Kind() != reflect.Struct {
return []byte{}, errors.New("Only a struct can be marshaled to TOML")
}
sval := reflect.ValueOf(v)
if isCustomMarshaler(mtype) {
return callCustomMarshaler(sval)
}
t, err := e.valueToTree(mtype, sval)
if err != nil {
return []byte{}, err
}
s, err := t.ToTomlString()
return []byte(s), err
}
// Convert given marshal struct or map value to toml tree
func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) {
if mtype.Kind() == reflect.Ptr {
return e.valueToTree(mtype.Elem(), mval.Elem())
}
tval := newTree()
switch mtype.Kind() {
case reflect.Struct:
for i := 0; i < mtype.NumField(); i++ {
mtypef, mvalf := mtype.Field(i), mval.Field(i)
opts := tomlOptions(mtypef)
if opts.include && (!opts.omitempty || !isZero(mvalf)) {
val, err := e.valueToToml(mtypef.Type, mvalf)
if err != nil {
return nil, err
}
tval.Set(opts.name, opts.comment, opts.commented, val)
}
}
case reflect.Map:
for _, key := range mval.MapKeys() {
mvalf := mval.MapIndex(key)
val, err := e.valueToToml(mtype.Elem(), mvalf)
if err != nil {
return nil, err
}
if e.quoteMapKeys {
keyStr, err := tomlValueStringRepresentation(key.String())
if err != nil {
return nil, err
}
tval.SetPath([]string{keyStr}, "", false, val)
} else {
tval.Set(key.String(), "", false, val)
}
}
}
return tval, nil
}
// Convert given marshal slice to slice of Toml trees
func (e *Encoder) valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) {
tval := make([]*Tree, mval.Len(), mval.Len())
for i := 0; i < mval.Len(); i++ {
val, err := e.valueToTree(mtype.Elem(), mval.Index(i))
if err != nil {
return nil, err
}
tval[i] = val
}
return tval, nil
}
// Convert given marshal slice to slice of toml values
func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
tval := make([]interface{}, mval.Len(), mval.Len())
for i := 0; i < mval.Len(); i++ {
val, err := e.valueToToml(mtype.Elem(), mval.Index(i))
if err != nil {
return nil, err
}
tval[i] = val
}
return tval, nil
}
// Convert given marshal value to toml value
func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
if mtype.Kind() == reflect.Ptr {
return e.valueToToml(mtype.Elem(), mval.Elem())
}
switch {
case isCustomMarshaler(mtype):
return callCustomMarshaler(mval)
case isTree(mtype):
return e.valueToTree(mtype, mval)
case isTreeSlice(mtype):
return e.valueToTreeSlice(mtype, mval)
case isOtherSlice(mtype):
return e.valueToOtherSlice(mtype, mval)
default:
switch mtype.Kind() {
case reflect.Bool:
return mval.Bool(), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return mval.Int(), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return mval.Uint(), nil
case reflect.Float32, reflect.Float64:
return mval.Float(), nil
case reflect.String:
return mval.String(), nil
case reflect.Struct:
return mval.Interface().(time.Time), nil
default:
return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind())
}
}
}
// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v.
// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
// sub-structs, and only definite types can be unmarshaled.
func (t *Tree) Unmarshal(v interface{}) error {
d := Decoder{tval: t}
return d.unmarshal(v)
}
// Marshal returns the TOML encoding of Tree.
// See Marshal() documentation for types mapping table.
func (t *Tree) Marshal() ([]byte, error) {
var buf bytes.Buffer
err := NewEncoder(&buf).Encode(t)
return buf.Bytes(), err
}
// Unmarshal parses the TOML-encoded data and stores the result in the value
// pointed to by v. Behavior is similar to the Go json encoder, except that there
// is no concept of an Unmarshaler interface or UnmarshalTOML function for
// sub-structs, and currently only definite types can be unmarshaled to (i.e. no
// `interface{}`).
//
// The following struct annotations are supported:
//
// toml:"Field" Overrides the field's name to map to.
//
// See Marshal() documentation for types mapping table.
func Unmarshal(data []byte, v interface{}) error {
t, err := LoadReader(bytes.NewReader(data))
if err != nil {
return err
}
return t.Unmarshal(v)
}
// Decoder reads and decodes TOML values from an input stream.
type Decoder struct {
r io.Reader
tval *Tree
encOpts
}
// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{
r: r,
encOpts: encOptsDefaults,
}
}
// Decode reads a TOML-encoded value from it's input
// and unmarshals it in the value pointed at by v.
//
// See the documentation for Marshal for details.
func (d *Decoder) Decode(v interface{}) error {
var err error
d.tval, err = LoadReader(d.r)
if err != nil {
return err
}
return d.unmarshal(v)
}
func (d *Decoder) unmarshal(v interface{}) error {
mtype := reflect.TypeOf(v)
if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct {
return errors.New("Only a pointer to struct can be unmarshaled from TOML")
}
sval, err := d.valueFromTree(mtype.Elem(), d.tval)
if err != nil {
return err
}
reflect.ValueOf(v).Elem().Set(sval)
return nil
}
// Convert toml tree to marshal struct or map, using marshal type
func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, error) {
if mtype.Kind() == reflect.Ptr {
return d.unwrapPointer(mtype, tval)
}
var mval reflect.Value
switch mtype.Kind() {
case reflect.Struct:
mval = reflect.New(mtype).Elem()
for i := 0; i < mtype.NumField(); i++ {
mtypef := mtype.Field(i)
opts := tomlOptions(mtypef)
if opts.include {
baseKey := opts.name
keysToTry := []string{baseKey, strings.ToLower(baseKey), strings.ToTitle(baseKey)}
for _, key := range keysToTry {
exists := tval.Has(key)
if !exists {
continue
}
val := tval.Get(key)
mvalf, err := d.valueFromToml(mtypef.Type, val)
if err != nil {
return mval, formatError(err, tval.GetPosition(key))
}
mval.Field(i).Set(mvalf)
break
}
}
}
case reflect.Map:
mval = reflect.MakeMap(mtype)
for _, key := range tval.Keys() {
// TODO: path splits key
val := tval.GetPath([]string{key})
mvalf, err := d.valueFromToml(mtype.Elem(), val)
if err != nil {
return mval, formatError(err, tval.GetPosition(key))
}
mval.SetMapIndex(reflect.ValueOf(key), mvalf)
}
}
return mval, nil
}
// Convert toml value to marshal struct/map slice, using marshal type
func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) {
mval := reflect.MakeSlice(mtype, len(tval), len(tval))
for i := 0; i < len(tval); i++ {
val, err := d.valueFromTree(mtype.Elem(), tval[i])
if err != nil {
return mval, err
}
mval.Index(i).Set(val)
}
return mval, nil
}
// Convert toml value to marshal primitive slice, using marshal type
func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) {
mval := reflect.MakeSlice(mtype, len(tval), len(tval))
for i := 0; i < len(tval); i++ {
val, err := d.valueFromToml(mtype.Elem(), tval[i])
if err != nil {
return mval, err
}
mval.Index(i).Set(val)
}
return mval, nil
}
// Convert toml value to marshal value, using marshal type
func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
if mtype.Kind() == reflect.Ptr {
return d.unwrapPointer(mtype, tval)
}
switch tval.(type) {
case *Tree:
if isTree(mtype) {
return d.valueFromTree(mtype, tval.(*Tree))
} else {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval)
}
case []*Tree:
if isTreeSlice(mtype) {
return d.valueFromTreeSlice(mtype, tval.([]*Tree))
} else {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval)
}
case []interface{}:
if isOtherSlice(mtype) {
return d.valueFromOtherSlice(mtype, tval.([]interface{}))
} else {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval)
}
default:
switch mtype.Kind() {
case reflect.Bool:
val, ok := tval.(bool)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to bool", tval, tval)
}
return reflect.ValueOf(val), nil
case reflect.Int:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to int", tval, tval)
}
return reflect.ValueOf(int(val)), nil
case reflect.Int8:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to int", tval, tval)
}
return reflect.ValueOf(int8(val)), nil
case reflect.Int16:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to int", tval, tval)
}
return reflect.ValueOf(int16(val)), nil
case reflect.Int32:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to int", tval, tval)
}
return reflect.ValueOf(int32(val)), nil
case reflect.Int64:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to int", tval, tval)
}
return reflect.ValueOf(val), nil
case reflect.Uint:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to uint", tval, tval)
}
return reflect.ValueOf(uint(val)), nil
case reflect.Uint8:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to uint", tval, tval)
}
return reflect.ValueOf(uint8(val)), nil
case reflect.Uint16:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to uint", tval, tval)
}
return reflect.ValueOf(uint16(val)), nil
case reflect.Uint32:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to uint", tval, tval)
}
return reflect.ValueOf(uint32(val)), nil
case reflect.Uint64:
val, ok := tval.(int64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to uint", tval, tval)
}
return reflect.ValueOf(uint64(val)), nil
case reflect.Float32:
val, ok := tval.(float64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to float", tval, tval)
}
return reflect.ValueOf(float32(val)), nil
case reflect.Float64:
val, ok := tval.(float64)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to float", tval, tval)
}
return reflect.ValueOf(val), nil
case reflect.String:
val, ok := tval.(string)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to string", tval, tval)
}
return reflect.ValueOf(val), nil
case reflect.Struct:
val, ok := tval.(time.Time)
if !ok {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to time", tval, tval)
}
return reflect.ValueOf(val), nil
default:
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind())
}
}
}
func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
val, err := d.valueFromToml(mtype.Elem(), tval)
if err != nil {
return reflect.ValueOf(nil), err
}
mval := reflect.New(mtype.Elem())
mval.Elem().Set(val)
return mval, nil
}
func tomlOptions(vf reflect.StructField) tomlOpts {
tag := vf.Tag.Get("toml")
parse := strings.Split(tag, ",")
var comment string
if c := vf.Tag.Get("comment"); c != "" {
comment = c
}
commented, _ := strconv.ParseBool(vf.Tag.Get("commented"))
result := tomlOpts{name: vf.Name, comment: comment, commented: commented, include: true, omitempty: false}
if parse[0] != "" {
if parse[0] == "-" && len(parse) == 1 {
result.include = false
} else {
result.name = strings.Trim(parse[0], " ")
}
}
if vf.PkgPath != "" {
result.include = false
}
if len(parse) > 1 && strings.Trim(parse[1], " ") == "omitempty" {
result.omitempty = true
}
if vf.Type.Kind() == reflect.Ptr {
result.omitempty = true
}
return result
}
func isZero(val reflect.Value) bool {
switch val.Type().Kind() {
case reflect.Map:
fallthrough
case reflect.Array:
fallthrough
case reflect.Slice:
return val.Len() == 0
default:
return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface())
}
}
func formatError(err error, pos Position) error {
if err.Error()[0] == '(' { // Error already contains position information
return err
}
return fmt.Errorf("%s: %s", pos, err)
}

View File

@ -1,234 +0,0 @@
package toml
import (
"fmt"
)
// support function to set positions for tomlValues
// NOTE: this is done to allow ctx.lastPosition to indicate the start of any
// values returned by the query engines
func tomlValueCheck(node interface{}, ctx *queryContext) interface{} {
switch castNode := node.(type) {
case *tomlValue:
ctx.lastPosition = castNode.position
return castNode.value
case []*TomlTree:
if len(castNode) > 0 {
ctx.lastPosition = castNode[0].position
}
return node
default:
return node
}
}
// base match
type matchBase struct {
next pathFn
}
func (f *matchBase) setNext(next pathFn) {
f.next = next
}
// terminating functor - gathers results
type terminatingFn struct {
// empty
}
func newTerminatingFn() *terminatingFn {
return &terminatingFn{}
}
func (f *terminatingFn) setNext(next pathFn) {
// do nothing
}
func (f *terminatingFn) call(node interface{}, ctx *queryContext) {
switch castNode := node.(type) {
case *TomlTree:
ctx.result.appendResult(node, castNode.position)
case *tomlValue:
ctx.result.appendResult(node, castNode.position)
default:
// use last position for scalars
ctx.result.appendResult(node, ctx.lastPosition)
}
}
// match single key
type matchKeyFn struct {
matchBase
Name string
}
func newMatchKeyFn(name string) *matchKeyFn {
return &matchKeyFn{Name: name}
}
func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
if array, ok := node.([]*TomlTree); ok {
for _, tree := range array {
item := tree.values[f.Name]
if item != nil {
f.next.call(item, ctx)
}
}
} else if tree, ok := node.(*TomlTree); ok {
item := tree.values[f.Name]
if item != nil {
f.next.call(item, ctx)
}
}
}
// match single index
type matchIndexFn struct {
matchBase
Idx int
}
func newMatchIndexFn(idx int) *matchIndexFn {
return &matchIndexFn{Idx: idx}
}
func (f *matchIndexFn) call(node interface{}, ctx *queryContext) {
if arr, ok := tomlValueCheck(node, ctx).([]interface{}); ok {
if f.Idx < len(arr) && f.Idx >= 0 {
f.next.call(arr[f.Idx], ctx)
}
}
}
// filter by slicing
type matchSliceFn struct {
matchBase
Start, End, Step int
}
func newMatchSliceFn(start, end, step int) *matchSliceFn {
return &matchSliceFn{Start: start, End: end, Step: step}
}
func (f *matchSliceFn) call(node interface{}, ctx *queryContext) {
if arr, ok := tomlValueCheck(node, ctx).([]interface{}); ok {
// adjust indexes for negative values, reverse ordering
realStart, realEnd := f.Start, f.End
if realStart < 0 {
realStart = len(arr) + realStart
}
if realEnd < 0 {
realEnd = len(arr) + realEnd
}
if realEnd < realStart {
realEnd, realStart = realStart, realEnd // swap
}
// loop and gather
for idx := realStart; idx < realEnd; idx += f.Step {
f.next.call(arr[idx], ctx)
}
}
}
// match anything
type matchAnyFn struct {
matchBase
}
func newMatchAnyFn() *matchAnyFn {
return &matchAnyFn{}
}
func (f *matchAnyFn) call(node interface{}, ctx *queryContext) {
if tree, ok := node.(*TomlTree); ok {
for _, v := range tree.values {
f.next.call(v, ctx)
}
}
}
// filter through union
type matchUnionFn struct {
Union []pathFn
}
func (f *matchUnionFn) setNext(next pathFn) {
for _, fn := range f.Union {
fn.setNext(next)
}
}
func (f *matchUnionFn) call(node interface{}, ctx *queryContext) {
for _, fn := range f.Union {
fn.call(node, ctx)
}
}
// match every single last node in the tree
type matchRecursiveFn struct {
matchBase
}
func newMatchRecursiveFn() *matchRecursiveFn {
return &matchRecursiveFn{}
}
func (f *matchRecursiveFn) call(node interface{}, ctx *queryContext) {
if tree, ok := node.(*TomlTree); ok {
var visit func(tree *TomlTree)
visit = func(tree *TomlTree) {
for _, v := range tree.values {
f.next.call(v, ctx)
switch node := v.(type) {
case *TomlTree:
visit(node)
case []*TomlTree:
for _, subtree := range node {
visit(subtree)
}
}
}
}
f.next.call(tree, ctx)
visit(tree)
}
}
// match based on an externally provided functional filter
type matchFilterFn struct {
matchBase
Pos Position
Name string
}
func newMatchFilterFn(name string, pos Position) *matchFilterFn {
return &matchFilterFn{Name: name, Pos: pos}
}
func (f *matchFilterFn) call(node interface{}, ctx *queryContext) {
fn, ok := (*ctx.filters)[f.Name]
if !ok {
panic(fmt.Sprintf("%s: query context does not have filter '%s'",
f.Pos.String(), f.Name))
}
switch castNode := tomlValueCheck(node, ctx).(type) {
case *TomlTree:
for _, v := range castNode.values {
if tv, ok := v.(*tomlValue); ok {
if fn(tv.value) {
f.next.call(v, ctx)
}
} else {
if fn(v) {
f.next.call(v, ctx)
}
}
}
case []interface{}:
for _, v := range castNode {
if fn(v) {
f.next.call(v, ctx)
}
}
}
}

View File

@ -13,9 +13,9 @@ import (
) )
type tomlParser struct { type tomlParser struct {
flow chan token flowIdx int
tree *TomlTree flow []token
tokensBuffer []token tree *Tree
currentTable []string currentTable []string
seenTableKeys []string seenTableKeys []string
} }
@ -34,16 +34,10 @@ func (p *tomlParser) run() {
} }
func (p *tomlParser) peek() *token { func (p *tomlParser) peek() *token {
if len(p.tokensBuffer) != 0 { if p.flowIdx >= len(p.flow) {
return &(p.tokensBuffer[0])
}
tok, ok := <-p.flow
if !ok {
return nil return nil
} }
p.tokensBuffer = append(p.tokensBuffer, tok) return &p.flow[p.flowIdx]
return &tok
} }
func (p *tomlParser) assume(typ tokenType) { func (p *tomlParser) assume(typ tokenType) {
@ -57,16 +51,12 @@ func (p *tomlParser) assume(typ tokenType) {
} }
func (p *tomlParser) getToken() *token { func (p *tomlParser) getToken() *token {
if len(p.tokensBuffer) != 0 { tok := p.peek()
tok := p.tokensBuffer[0] if tok == nil {
p.tokensBuffer = p.tokensBuffer[1:]
return &tok
}
tok, ok := <-p.flow
if !ok {
return nil return nil
} }
return &tok p.flowIdx++
return tok
} }
func (p *tomlParser) parseStart() tomlParserStateFn { func (p *tomlParser) parseStart() tomlParserStateFn {
@ -106,21 +96,21 @@ func (p *tomlParser) parseGroupArray() tomlParserStateFn {
} }
p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries
destTree := p.tree.GetPath(keys) destTree := p.tree.GetPath(keys)
var array []*TomlTree var array []*Tree
if destTree == nil { if destTree == nil {
array = make([]*TomlTree, 0) array = make([]*Tree, 0)
} else if target, ok := destTree.([]*TomlTree); ok && target != nil { } else if target, ok := destTree.([]*Tree); ok && target != nil {
array = destTree.([]*TomlTree) array = destTree.([]*Tree)
} else { } else {
p.raiseError(key, "key %s is already assigned and not of type table array", key) p.raiseError(key, "key %s is already assigned and not of type table array", key)
} }
p.currentTable = keys p.currentTable = keys
// add a new tree to the end of the table array // add a new tree to the end of the table array
newTree := newTomlTree() newTree := newTree()
newTree.position = startToken.Position newTree.position = startToken.Position
array = append(array, newTree) array = append(array, newTree)
p.tree.SetPath(p.currentTable, array) p.tree.SetPath(p.currentTable, "", false, array)
// remove all keys that were children of this table array // remove all keys that were children of this table array
prefix := key.val + "." prefix := key.val + "."
@ -183,11 +173,11 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
} }
// find the table to assign, looking out for arrays of tables // find the table to assign, looking out for arrays of tables
var targetNode *TomlTree var targetNode *Tree
switch node := p.tree.GetPath(tableKey).(type) { switch node := p.tree.GetPath(tableKey).(type) {
case []*TomlTree: case []*Tree:
targetNode = node[len(node)-1] targetNode = node[len(node)-1]
case *TomlTree: case *Tree:
targetNode = node targetNode = node
default: default:
p.raiseError(key, "Unknown table type for path: %s", p.raiseError(key, "Unknown table type for path: %s",
@ -212,10 +202,10 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
var toInsert interface{} var toInsert interface{}
switch value.(type) { switch value.(type) {
case *TomlTree, []*TomlTree: case *Tree, []*Tree:
toInsert = value toInsert = value
default: default:
toInsert = &tomlValue{value, key.Position} toInsert = &tomlValue{value: value, position: key.Position}
} }
targetNode.values[keyVal] = toInsert targetNode.values[keyVal] = toInsert
return p.parseStart return p.parseStart
@ -289,8 +279,8 @@ func tokenIsComma(t *token) bool {
return t != nil && t.typ == tokenComma return t != nil && t.typ == tokenComma
} }
func (p *tomlParser) parseInlineTable() *TomlTree { func (p *tomlParser) parseInlineTable() *Tree {
tree := newTomlTree() tree := newTree()
var previous *token var previous *token
Loop: Loop:
for { for {
@ -309,7 +299,7 @@ Loop:
key := p.getToken() key := p.getToken()
p.assume(tokenEqual) p.assume(tokenEqual)
value := p.parseRvalue() value := p.parseRvalue()
tree.Set(key.val, value) tree.Set(key.val, "", false, value)
case tokenComma: case tokenComma:
if previous == nil { if previous == nil {
p.raiseError(follow, "inline table cannot start with a comma") p.raiseError(follow, "inline table cannot start with a comma")
@ -360,27 +350,27 @@ func (p *tomlParser) parseArray() interface{} {
p.getToken() p.getToken()
} }
} }
// An array of TomlTrees is actually an array of inline // An array of Trees is actually an array of inline
// tables, which is a shorthand for a table array. If the // tables, which is a shorthand for a table array. If the
// array was not converted from []interface{} to []*TomlTree, // array was not converted from []interface{} to []*Tree,
// the two notations would not be equivalent. // the two notations would not be equivalent.
if arrayType == reflect.TypeOf(newTomlTree()) { if arrayType == reflect.TypeOf(newTree()) {
tomlArray := make([]*TomlTree, len(array)) tomlArray := make([]*Tree, len(array))
for i, v := range array { for i, v := range array {
tomlArray[i] = v.(*TomlTree) tomlArray[i] = v.(*Tree)
} }
return tomlArray return tomlArray
} }
return array return array
} }
func parseToml(flow chan token) *TomlTree { func parseToml(flow []token) *Tree {
result := newTomlTree() result := newTree()
result.position = Position{1, 1} result.position = Position{1, 1}
parser := &tomlParser{ parser := &tomlParser{
flowIdx: 0,
flow: flow, flow: flow,
tree: result, tree: result,
tokensBuffer: make([]token, 0),
currentTable: make([]string, 0), currentTable: make([]string, 0),
seenTableKeys: make([]string, 0), seenTableKeys: make([]string, 0),
} }

View File

@ -1,153 +0,0 @@
package toml
import (
"time"
)
// NodeFilterFn represents a user-defined filter function, for use with
// Query.SetFilter().
//
// The return value of the function must indicate if 'node' is to be included
// at this stage of the TOML path. Returning true will include the node, and
// returning false will exclude it.
//
// NOTE: Care should be taken to write script callbacks such that they are safe
// to use from multiple goroutines.
type NodeFilterFn func(node interface{}) bool
// QueryResult is the result of Executing a Query.
type QueryResult struct {
items []interface{}
positions []Position
}
// appends a value/position pair to the result set.
func (r *QueryResult) appendResult(node interface{}, pos Position) {
r.items = append(r.items, node)
r.positions = append(r.positions, pos)
}
// Values is a set of values within a QueryResult. The order of values is not
// guaranteed to be in document order, and may be different each time a query is
// executed.
func (r QueryResult) Values() []interface{} {
values := make([]interface{}, len(r.items))
for i, v := range r.items {
o, ok := v.(*tomlValue)
if ok {
values[i] = o.value
} else {
values[i] = v
}
}
return values
}
// Positions is a set of positions for values within a QueryResult. Each index
// in Positions() corresponds to the entry in Value() of the same index.
func (r QueryResult) Positions() []Position {
return r.positions
}
// runtime context for executing query paths
type queryContext struct {
result *QueryResult
filters *map[string]NodeFilterFn
lastPosition Position
}
// generic path functor interface
type pathFn interface {
setNext(next pathFn)
call(node interface{}, ctx *queryContext)
}
// A Query is the representation of a compiled TOML path. A Query is safe
// for concurrent use by multiple goroutines.
type Query struct {
root pathFn
tail pathFn
filters *map[string]NodeFilterFn
}
func newQuery() *Query {
return &Query{
root: nil,
tail: nil,
filters: &defaultFilterFunctions,
}
}
func (q *Query) appendPath(next pathFn) {
if q.root == nil {
q.root = next
} else {
q.tail.setNext(next)
}
q.tail = next
next.setNext(newTerminatingFn()) // init the next functor
}
// CompileQuery compiles a TOML path expression. The returned Query can be used
// to match elements within a TomlTree and its descendants.
func CompileQuery(path string) (*Query, error) {
return parseQuery(lexQuery(path))
}
// Execute executes a query against a TomlTree, and returns the result of the query.
func (q *Query) Execute(tree *TomlTree) *QueryResult {
result := &QueryResult{
items: []interface{}{},
positions: []Position{},
}
if q.root == nil {
result.appendResult(tree, tree.GetPosition(""))
} else {
ctx := &queryContext{
result: result,
filters: q.filters,
}
q.root.call(tree, ctx)
}
return result
}
// SetFilter sets a user-defined filter function. These may be used inside
// "?(..)" query expressions to filter TOML document elements within a query.
func (q *Query) SetFilter(name string, fn NodeFilterFn) {
if q.filters == &defaultFilterFunctions {
// clone the static table
q.filters = &map[string]NodeFilterFn{}
for k, v := range defaultFilterFunctions {
(*q.filters)[k] = v
}
}
(*q.filters)[name] = fn
}
var defaultFilterFunctions = map[string]NodeFilterFn{
"tree": func(node interface{}) bool {
_, ok := node.(*TomlTree)
return ok
},
"int": func(node interface{}) bool {
_, ok := node.(int64)
return ok
},
"float": func(node interface{}) bool {
_, ok := node.(float64)
return ok
},
"string": func(node interface{}) bool {
_, ok := node.(string)
return ok
},
"time": func(node interface{}) bool {
_, ok := node.(time.Time)
return ok
},
"bool": func(node interface{}) bool {
_, ok := node.(bool)
return ok
},
}

View File

@ -1,356 +0,0 @@
// TOML JSONPath lexer.
//
// Written using the principles developed by Rob Pike in
// http://www.youtube.com/watch?v=HxaD_trXwRE
package toml
import (
"fmt"
"strconv"
"strings"
"unicode/utf8"
)
// Lexer state function
type queryLexStateFn func() queryLexStateFn
// Lexer definition
type queryLexer struct {
input string
start int
pos int
width int
tokens chan token
depth int
line int
col int
stringTerm string
}
func (l *queryLexer) run() {
for state := l.lexVoid; state != nil; {
state = state()
}
close(l.tokens)
}
func (l *queryLexer) nextStart() {
// iterate by runes (utf8 characters)
// search for newlines and advance line/col counts
for i := l.start; i < l.pos; {
r, width := utf8.DecodeRuneInString(l.input[i:])
if r == '\n' {
l.line++
l.col = 1
} else {
l.col++
}
i += width
}
// advance start position to next token
l.start = l.pos
}
func (l *queryLexer) emit(t tokenType) {
l.tokens <- token{
Position: Position{l.line, l.col},
typ: t,
val: l.input[l.start:l.pos],
}
l.nextStart()
}
func (l *queryLexer) emitWithValue(t tokenType, value string) {
l.tokens <- token{
Position: Position{l.line, l.col},
typ: t,
val: value,
}
l.nextStart()
}
func (l *queryLexer) next() rune {
if l.pos >= len(l.input) {
l.width = 0
return eof
}
var r rune
r, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
l.pos += l.width
return r
}
func (l *queryLexer) ignore() {
l.nextStart()
}
func (l *queryLexer) backup() {
l.pos -= l.width
}
func (l *queryLexer) errorf(format string, args ...interface{}) queryLexStateFn {
l.tokens <- token{
Position: Position{l.line, l.col},
typ: tokenError,
val: fmt.Sprintf(format, args...),
}
return nil
}
func (l *queryLexer) peek() rune {
r := l.next()
l.backup()
return r
}
func (l *queryLexer) accept(valid string) bool {
if strings.ContainsRune(valid, l.next()) {
return true
}
l.backup()
return false
}
func (l *queryLexer) follow(next string) bool {
return strings.HasPrefix(l.input[l.pos:], next)
}
func (l *queryLexer) lexVoid() queryLexStateFn {
for {
next := l.peek()
switch next {
case '$':
l.pos++
l.emit(tokenDollar)
continue
case '.':
if l.follow("..") {
l.pos += 2
l.emit(tokenDotDot)
} else {
l.pos++
l.emit(tokenDot)
}
continue
case '[':
l.pos++
l.emit(tokenLeftBracket)
continue
case ']':
l.pos++
l.emit(tokenRightBracket)
continue
case ',':
l.pos++
l.emit(tokenComma)
continue
case '*':
l.pos++
l.emit(tokenStar)
continue
case '(':
l.pos++
l.emit(tokenLeftParen)
continue
case ')':
l.pos++
l.emit(tokenRightParen)
continue
case '?':
l.pos++
l.emit(tokenQuestion)
continue
case ':':
l.pos++
l.emit(tokenColon)
continue
case '\'':
l.ignore()
l.stringTerm = string(next)
return l.lexString
case '"':
l.ignore()
l.stringTerm = string(next)
return l.lexString
}
if isSpace(next) {
l.next()
l.ignore()
continue
}
if isAlphanumeric(next) {
return l.lexKey
}
if next == '+' || next == '-' || isDigit(next) {
return l.lexNumber
}
if l.next() == eof {
break
}
return l.errorf("unexpected char: '%v'", next)
}
l.emit(tokenEOF)
return nil
}
func (l *queryLexer) lexKey() queryLexStateFn {
for {
next := l.peek()
if !isAlphanumeric(next) {
l.emit(tokenKey)
return l.lexVoid
}
if l.next() == eof {
break
}
}
l.emit(tokenEOF)
return nil
}
func (l *queryLexer) lexString() queryLexStateFn {
l.pos++
l.ignore()
growingString := ""
for {
if l.follow(l.stringTerm) {
l.emitWithValue(tokenString, growingString)
l.pos++
l.ignore()
return l.lexVoid
}
if l.follow("\\\"") {
l.pos++
growingString += "\""
} else if l.follow("\\'") {
l.pos++
growingString += "'"
} else if l.follow("\\n") {
l.pos++
growingString += "\n"
} else if l.follow("\\b") {
l.pos++
growingString += "\b"
} else if l.follow("\\f") {
l.pos++
growingString += "\f"
} else if l.follow("\\/") {
l.pos++
growingString += "/"
} else if l.follow("\\t") {
l.pos++
growingString += "\t"
} else if l.follow("\\r") {
l.pos++
growingString += "\r"
} else if l.follow("\\\\") {
l.pos++
growingString += "\\"
} else if l.follow("\\u") {
l.pos += 2
code := ""
for i := 0; i < 4; i++ {
c := l.peek()
l.pos++
if !isHexDigit(c) {
return l.errorf("unfinished unicode escape")
}
code = code + string(c)
}
l.pos--
intcode, err := strconv.ParseInt(code, 16, 32)
if err != nil {
return l.errorf("invalid unicode escape: \\u" + code)
}
growingString += string(rune(intcode))
} else if l.follow("\\U") {
l.pos += 2
code := ""
for i := 0; i < 8; i++ {
c := l.peek()
l.pos++
if !isHexDigit(c) {
return l.errorf("unfinished unicode escape")
}
code = code + string(c)
}
l.pos--
intcode, err := strconv.ParseInt(code, 16, 32)
if err != nil {
return l.errorf("invalid unicode escape: \\u" + code)
}
growingString += string(rune(intcode))
} else if l.follow("\\") {
l.pos++
return l.errorf("invalid escape sequence: \\" + string(l.peek()))
} else {
growingString += string(l.peek())
}
if l.next() == eof {
break
}
}
return l.errorf("unclosed string")
}
func (l *queryLexer) lexNumber() queryLexStateFn {
l.ignore()
if !l.accept("+") {
l.accept("-")
}
pointSeen := false
digitSeen := false
for {
next := l.next()
if next == '.' {
if pointSeen {
return l.errorf("cannot have two dots in one float")
}
if !isDigit(l.peek()) {
return l.errorf("float cannot end with a dot")
}
pointSeen = true
} else if isDigit(next) {
digitSeen = true
} else {
l.backup()
break
}
if pointSeen && !digitSeen {
return l.errorf("cannot start float with a dot")
}
}
if !digitSeen {
return l.errorf("no digit in that number")
}
if pointSeen {
l.emit(tokenFloat)
} else {
l.emit(tokenInteger)
}
return l.lexVoid
}
// Entry point
func lexQuery(input string) chan token {
l := &queryLexer{
input: input,
tokens: make(chan token),
line: 1,
col: 1,
}
go l.run()
return l.tokens
}

View File

@ -1,275 +0,0 @@
/*
Based on the "jsonpath" spec/concept.
http://goessner.net/articles/JsonPath/
https://code.google.com/p/json-path/
*/
package toml
import (
"fmt"
)
const maxInt = int(^uint(0) >> 1)
type queryParser struct {
flow chan token
tokensBuffer []token
query *Query
union []pathFn
err error
}
type queryParserStateFn func() queryParserStateFn
// Formats and panics an error message based on a token
func (p *queryParser) parseError(tok *token, msg string, args ...interface{}) queryParserStateFn {
p.err = fmt.Errorf(tok.Position.String()+": "+msg, args...)
return nil // trigger parse to end
}
func (p *queryParser) run() {
for state := p.parseStart; state != nil; {
state = state()
}
}
func (p *queryParser) backup(tok *token) {
p.tokensBuffer = append(p.tokensBuffer, *tok)
}
func (p *queryParser) peek() *token {
if len(p.tokensBuffer) != 0 {
return &(p.tokensBuffer[0])
}
tok, ok := <-p.flow
if !ok {
return nil
}
p.backup(&tok)
return &tok
}
func (p *queryParser) lookahead(types ...tokenType) bool {
result := true
buffer := []token{}
for _, typ := range types {
tok := p.getToken()
if tok == nil {
result = false
break
}
buffer = append(buffer, *tok)
if tok.typ != typ {
result = false
break
}
}
// add the tokens back to the buffer, and return
p.tokensBuffer = append(p.tokensBuffer, buffer...)
return result
}
func (p *queryParser) getToken() *token {
if len(p.tokensBuffer) != 0 {
tok := p.tokensBuffer[0]
p.tokensBuffer = p.tokensBuffer[1:]
return &tok
}
tok, ok := <-p.flow
if !ok {
return nil
}
return &tok
}
func (p *queryParser) parseStart() queryParserStateFn {
tok := p.getToken()
if tok == nil || tok.typ == tokenEOF {
return nil
}
if tok.typ != tokenDollar {
return p.parseError(tok, "Expected '$' at start of expression")
}
return p.parseMatchExpr
}
// handle '.' prefix, '[]', and '..'
func (p *queryParser) parseMatchExpr() queryParserStateFn {
tok := p.getToken()
switch tok.typ {
case tokenDotDot:
p.query.appendPath(&matchRecursiveFn{})
// nested parse for '..'
tok := p.getToken()
switch tok.typ {
case tokenKey:
p.query.appendPath(newMatchKeyFn(tok.val))
return p.parseMatchExpr
case tokenLeftBracket:
return p.parseBracketExpr
case tokenStar:
// do nothing - the recursive predicate is enough
return p.parseMatchExpr
}
case tokenDot:
// nested parse for '.'
tok := p.getToken()
switch tok.typ {
case tokenKey:
p.query.appendPath(newMatchKeyFn(tok.val))
return p.parseMatchExpr
case tokenStar:
p.query.appendPath(&matchAnyFn{})
return p.parseMatchExpr
}
case tokenLeftBracket:
return p.parseBracketExpr
case tokenEOF:
return nil // allow EOF at this stage
}
return p.parseError(tok, "expected match expression")
}
func (p *queryParser) parseBracketExpr() queryParserStateFn {
if p.lookahead(tokenInteger, tokenColon) {
return p.parseSliceExpr
}
if p.peek().typ == tokenColon {
return p.parseSliceExpr
}
return p.parseUnionExpr
}
func (p *queryParser) parseUnionExpr() queryParserStateFn {
var tok *token
// this state can be traversed after some sub-expressions
// so be careful when setting up state in the parser
if p.union == nil {
p.union = []pathFn{}
}
loop: // labeled loop for easy breaking
for {
if len(p.union) > 0 {
// parse delimiter or terminator
tok = p.getToken()
switch tok.typ {
case tokenComma:
// do nothing
case tokenRightBracket:
break loop
default:
return p.parseError(tok, "expected ',' or ']', not '%s'", tok.val)
}
}
// parse sub expression
tok = p.getToken()
switch tok.typ {
case tokenInteger:
p.union = append(p.union, newMatchIndexFn(tok.Int()))
case tokenKey:
p.union = append(p.union, newMatchKeyFn(tok.val))
case tokenString:
p.union = append(p.union, newMatchKeyFn(tok.val))
case tokenQuestion:
return p.parseFilterExpr
default:
return p.parseError(tok, "expected union sub expression, not '%s', %d", tok.val, len(p.union))
}
}
// if there is only one sub-expression, use that instead
if len(p.union) == 1 {
p.query.appendPath(p.union[0])
} else {
p.query.appendPath(&matchUnionFn{p.union})
}
p.union = nil // clear out state
return p.parseMatchExpr
}
func (p *queryParser) parseSliceExpr() queryParserStateFn {
// init slice to grab all elements
start, end, step := 0, maxInt, 1
// parse optional start
tok := p.getToken()
if tok.typ == tokenInteger {
start = tok.Int()
tok = p.getToken()
}
if tok.typ != tokenColon {
return p.parseError(tok, "expected ':'")
}
// parse optional end
tok = p.getToken()
if tok.typ == tokenInteger {
end = tok.Int()
tok = p.getToken()
}
if tok.typ == tokenRightBracket {
p.query.appendPath(newMatchSliceFn(start, end, step))
return p.parseMatchExpr
}
if tok.typ != tokenColon {
return p.parseError(tok, "expected ']' or ':'")
}
// parse optional step
tok = p.getToken()
if tok.typ == tokenInteger {
step = tok.Int()
if step < 0 {
return p.parseError(tok, "step must be a positive value")
}
tok = p.getToken()
}
if tok.typ != tokenRightBracket {
return p.parseError(tok, "expected ']'")
}
p.query.appendPath(newMatchSliceFn(start, end, step))
return p.parseMatchExpr
}
func (p *queryParser) parseFilterExpr() queryParserStateFn {
tok := p.getToken()
if tok.typ != tokenLeftParen {
return p.parseError(tok, "expected left-parenthesis for filter expression")
}
tok = p.getToken()
if tok.typ != tokenKey && tok.typ != tokenString {
return p.parseError(tok, "expected key or string for filter funciton name")
}
name := tok.val
tok = p.getToken()
if tok.typ != tokenRightParen {
return p.parseError(tok, "expected right-parenthesis for filter expression")
}
p.union = append(p.union, newMatchFilterFn(name, tok.Position))
return p.parseUnionExpr
}
func parseQuery(flow chan token) (*Query, error) {
parser := &queryParser{
flow: flow,
tokensBuffer: []token{},
query: newQuery(),
}
parser.run()
return parser.query, parser.err
}

View File

@ -135,5 +135,6 @@ func isDigit(r rune) bool {
func isHexDigit(r rune) bool { func isHexDigit(r rune) bool {
return isDigit(r) || return isDigit(r) ||
r == 'A' || r == 'B' || r == 'C' || r == 'D' || r == 'E' || r == 'F' (r >= 'a' && r <= 'f') ||
(r >= 'A' && r <= 'F')
} }

View File

@ -4,38 +4,50 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"os" "os"
"runtime" "runtime"
"strings" "strings"
) )
type tomlValue struct { type tomlValue struct {
value interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list value interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list
position Position comment string
commented bool
position Position
} }
// TomlTree is the result of the parsing of a TOML file. // Tree is the result of the parsing of a TOML file.
type TomlTree struct { type Tree struct {
values map[string]interface{} // string -> *tomlValue, *TomlTree, []*TomlTree values map[string]interface{} // string -> *tomlValue, *Tree, []*Tree
position Position comment string
commented bool
position Position
} }
func newTomlTree() *TomlTree { func newTree() *Tree {
return &TomlTree{ return &Tree{
values: make(map[string]interface{}), values: make(map[string]interface{}),
position: Position{}, position: Position{},
} }
} }
// TreeFromMap initializes a new TomlTree object using the given map. // TreeFromMap initializes a new Tree object using the given map.
func TreeFromMap(m map[string]interface{}) *TomlTree { func TreeFromMap(m map[string]interface{}) (*Tree, error) {
return &TomlTree{ result, err := toTree(m)
values: m, if err != nil {
return nil, err
} }
return result.(*Tree), nil
}
// Position returns the position of the tree.
func (t *Tree) Position() Position {
return t.position
} }
// Has returns a boolean indicating if the given key exists. // Has returns a boolean indicating if the given key exists.
func (t *TomlTree) Has(key string) bool { func (t *Tree) Has(key string) bool {
if key == "" { if key == "" {
return false return false
} }
@ -43,25 +55,26 @@ func (t *TomlTree) Has(key string) bool {
} }
// HasPath returns true if the given path of keys exists, false otherwise. // HasPath returns true if the given path of keys exists, false otherwise.
func (t *TomlTree) HasPath(keys []string) bool { func (t *Tree) HasPath(keys []string) bool {
return t.GetPath(keys) != nil return t.GetPath(keys) != nil
} }
// Keys returns the keys of the toplevel tree. // Keys returns the keys of the toplevel tree (does not recurse).
// Warning: this is a costly operation. func (t *Tree) Keys() []string {
func (t *TomlTree) Keys() []string { keys := make([]string, len(t.values))
var keys []string i := 0
for k := range t.values { for k := range t.values {
keys = append(keys, k) keys[i] = k
i++
} }
return keys return keys
} }
// Get the value at key in the TomlTree. // Get the value at key in the Tree.
// Key is a dot-separated path (e.g. a.b.c). // Key is a dot-separated path (e.g. a.b.c).
// Returns nil if the path does not exist in the tree. // Returns nil if the path does not exist in the tree.
// If keys is of length zero, the current tree is returned. // If keys is of length zero, the current tree is returned.
func (t *TomlTree) Get(key string) interface{} { func (t *Tree) Get(key string) interface{} {
if key == "" { if key == "" {
return t return t
} }
@ -74,7 +87,7 @@ func (t *TomlTree) Get(key string) interface{} {
// GetPath returns the element in the tree indicated by 'keys'. // GetPath returns the element in the tree indicated by 'keys'.
// If keys is of length zero, the current tree is returned. // If keys is of length zero, the current tree is returned.
func (t *TomlTree) GetPath(keys []string) interface{} { func (t *Tree) GetPath(keys []string) interface{} {
if len(keys) == 0 { if len(keys) == 0 {
return t return t
} }
@ -85,9 +98,9 @@ func (t *TomlTree) GetPath(keys []string) interface{} {
return nil return nil
} }
switch node := value.(type) { switch node := value.(type) {
case *TomlTree: case *Tree:
subtree = node subtree = node
case []*TomlTree: case []*Tree:
// go to most recent element // go to most recent element
if len(node) == 0 { if len(node) == 0 {
return nil return nil
@ -107,7 +120,7 @@ func (t *TomlTree) GetPath(keys []string) interface{} {
} }
// GetPosition returns the position of the given key. // GetPosition returns the position of the given key.
func (t *TomlTree) GetPosition(key string) Position { func (t *Tree) GetPosition(key string) Position {
if key == "" { if key == "" {
return t.position return t.position
} }
@ -116,7 +129,7 @@ func (t *TomlTree) GetPosition(key string) Position {
// GetPositionPath returns the element in the tree indicated by 'keys'. // GetPositionPath returns the element in the tree indicated by 'keys'.
// If keys is of length zero, the current tree is returned. // If keys is of length zero, the current tree is returned.
func (t *TomlTree) GetPositionPath(keys []string) Position { func (t *Tree) GetPositionPath(keys []string) Position {
if len(keys) == 0 { if len(keys) == 0 {
return t.position return t.position
} }
@ -127,9 +140,9 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
return Position{0, 0} return Position{0, 0}
} }
switch node := value.(type) { switch node := value.(type) {
case *TomlTree: case *Tree:
subtree = node subtree = node
case []*TomlTree: case []*Tree:
// go to most recent element // go to most recent element
if len(node) == 0 { if len(node) == 0 {
return Position{0, 0} return Position{0, 0}
@ -143,9 +156,9 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
switch node := subtree.values[keys[len(keys)-1]].(type) { switch node := subtree.values[keys[len(keys)-1]].(type) {
case *tomlValue: case *tomlValue:
return node.position return node.position
case *TomlTree: case *Tree:
return node.position return node.position
case []*TomlTree: case []*Tree:
// go to most recent element // go to most recent element
if len(node) == 0 { if len(node) == 0 {
return Position{0, 0} return Position{0, 0}
@ -157,7 +170,7 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
} }
// GetDefault works like Get but with a default value // GetDefault works like Get but with a default value
func (t *TomlTree) GetDefault(key string, def interface{}) interface{} { func (t *Tree) GetDefault(key string, def interface{}) interface{} {
val := t.Get(key) val := t.Get(key)
if val == nil { if val == nil {
return def return def
@ -167,30 +180,30 @@ func (t *TomlTree) GetDefault(key string, def interface{}) interface{} {
// Set an element in the tree. // Set an element in the tree.
// Key is a dot-separated path (e.g. a.b.c). // Key is a dot-separated path (e.g. a.b.c).
// Creates all necessary intermediates trees, if needed. // Creates all necessary intermediate trees, if needed.
func (t *TomlTree) Set(key string, value interface{}) { func (t *Tree) Set(key string, comment string, commented bool, value interface{}) {
t.SetPath(strings.Split(key, "."), value) t.SetPath(strings.Split(key, "."), comment, commented, value)
} }
// SetPath sets an element in the tree. // SetPath sets an element in the tree.
// Keys is an array of path elements (e.g. {"a","b","c"}). // Keys is an array of path elements (e.g. {"a","b","c"}).
// Creates all necessary intermediates trees, if needed. // Creates all necessary intermediate trees, if needed.
func (t *TomlTree) SetPath(keys []string, value interface{}) { func (t *Tree) SetPath(keys []string, comment string, commented bool, value interface{}) {
subtree := t subtree := t
for _, intermediateKey := range keys[:len(keys)-1] { for _, intermediateKey := range keys[:len(keys)-1] {
nextTree, exists := subtree.values[intermediateKey] nextTree, exists := subtree.values[intermediateKey]
if !exists { if !exists {
nextTree = newTomlTree() nextTree = newTree()
subtree.values[intermediateKey] = nextTree // add new element here subtree.values[intermediateKey] = nextTree // add new element here
} }
switch node := nextTree.(type) { switch node := nextTree.(type) {
case *TomlTree: case *Tree:
subtree = node subtree = node
case []*TomlTree: case []*Tree:
// go to most recent element // go to most recent element
if len(node) == 0 { if len(node) == 0 {
// create element if it does not exist // create element if it does not exist
subtree.values[intermediateKey] = append(node, newTomlTree()) subtree.values[intermediateKey] = append(node, newTree())
} }
subtree = node[len(node)-1] subtree = node[len(node)-1]
} }
@ -199,14 +212,18 @@ func (t *TomlTree) SetPath(keys []string, value interface{}) {
var toInsert interface{} var toInsert interface{}
switch value.(type) { switch value.(type) {
case *TomlTree: case *Tree:
tt := value.(*Tree)
tt.comment = comment
toInsert = value toInsert = value
case []*TomlTree: case []*Tree:
toInsert = value toInsert = value
case *tomlValue: case *tomlValue:
toInsert = value tt := value.(*tomlValue)
tt.comment = comment
toInsert = tt
default: default:
toInsert = &tomlValue{value: value} toInsert = &tomlValue{value: value, comment: comment, commented: commented}
} }
subtree.values[keys[len(keys)-1]] = toInsert subtree.values[keys[len(keys)-1]] = toInsert
@ -219,21 +236,21 @@ func (t *TomlTree) SetPath(keys []string, value interface{}) {
// and tree[a][b][c] // and tree[a][b][c]
// //
// Returns nil on success, error object on failure // Returns nil on success, error object on failure
func (t *TomlTree) createSubTree(keys []string, pos Position) error { func (t *Tree) createSubTree(keys []string, pos Position) error {
subtree := t subtree := t
for _, intermediateKey := range keys { for _, intermediateKey := range keys {
nextTree, exists := subtree.values[intermediateKey] nextTree, exists := subtree.values[intermediateKey]
if !exists { if !exists {
tree := newTomlTree() tree := newTree()
tree.position = pos tree.position = pos
subtree.values[intermediateKey] = tree subtree.values[intermediateKey] = tree
nextTree = tree nextTree = tree
} }
switch node := nextTree.(type) { switch node := nextTree.(type) {
case []*TomlTree: case []*Tree:
subtree = node[len(node)-1] subtree = node[len(node)-1]
case *TomlTree: case *Tree:
subtree = node subtree = node
default: default:
return fmt.Errorf("unknown type for path %s (%s): %T (%#v)", return fmt.Errorf("unknown type for path %s (%s): %T (%#v)",
@ -243,17 +260,8 @@ func (t *TomlTree) createSubTree(keys []string, pos Position) error {
return nil return nil
} }
// Query compiles and executes a query on a tree and returns the query result. // LoadBytes creates a Tree from a []byte.
func (t *TomlTree) Query(query string) (*QueryResult, error) { func LoadBytes(b []byte) (tree *Tree, err error) {
q, err := CompileQuery(query)
if err != nil {
return nil, err
}
return q.Execute(t), nil
}
// LoadReader creates a TomlTree from any io.Reader.
func LoadReader(reader io.Reader) (tree *TomlTree, err error) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok { if _, ok := r.(runtime.Error); ok {
@ -262,17 +270,27 @@ func LoadReader(reader io.Reader) (tree *TomlTree, err error) {
err = errors.New(r.(string)) err = errors.New(r.(string))
} }
}() }()
tree = parseToml(lexToml(reader)) tree = parseToml(lexToml(b))
return return
} }
// Load creates a TomlTree from a string. // LoadReader creates a Tree from any io.Reader.
func Load(content string) (tree *TomlTree, err error) { func LoadReader(reader io.Reader) (tree *Tree, err error) {
return LoadReader(strings.NewReader(content)) inputBytes, err := ioutil.ReadAll(reader)
if err != nil {
return
}
tree, err = LoadBytes(inputBytes)
return
} }
// LoadFile creates a TomlTree from a file. // Load creates a Tree from a string.
func LoadFile(path string) (tree *TomlTree, err error) { func Load(content string) (tree *Tree, err error) {
return LoadBytes([]byte(content))
}
// LoadFile creates a Tree from a file.
func LoadFile(path string) (tree *Tree, err error) {
file, err := os.Open(path) file, err := os.Open(path)
if err != nil { if err != nil {
return nil, err return nil, err

142
vendor/github.com/pelletier/go-toml/tomltree_create.go generated vendored Normal file
View File

@ -0,0 +1,142 @@
package toml
import (
"fmt"
"reflect"
"time"
)
var kindToType = [reflect.String + 1]reflect.Type{
reflect.Bool: reflect.TypeOf(true),
reflect.String: reflect.TypeOf(""),
reflect.Float32: reflect.TypeOf(float64(1)),
reflect.Float64: reflect.TypeOf(float64(1)),
reflect.Int: reflect.TypeOf(int64(1)),
reflect.Int8: reflect.TypeOf(int64(1)),
reflect.Int16: reflect.TypeOf(int64(1)),
reflect.Int32: reflect.TypeOf(int64(1)),
reflect.Int64: reflect.TypeOf(int64(1)),
reflect.Uint: reflect.TypeOf(uint64(1)),
reflect.Uint8: reflect.TypeOf(uint64(1)),
reflect.Uint16: reflect.TypeOf(uint64(1)),
reflect.Uint32: reflect.TypeOf(uint64(1)),
reflect.Uint64: reflect.TypeOf(uint64(1)),
}
// typeFor returns a reflect.Type for a reflect.Kind, or nil if none is found.
// supported values:
// string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32
func typeFor(k reflect.Kind) reflect.Type {
if k > 0 && int(k) < len(kindToType) {
return kindToType[k]
}
return nil
}
func simpleValueCoercion(object interface{}) (interface{}, error) {
switch original := object.(type) {
case string, bool, int64, uint64, float64, time.Time:
return original, nil
case int:
return int64(original), nil
case int8:
return int64(original), nil
case int16:
return int64(original), nil
case int32:
return int64(original), nil
case uint:
return uint64(original), nil
case uint8:
return uint64(original), nil
case uint16:
return uint64(original), nil
case uint32:
return uint64(original), nil
case float32:
return float64(original), nil
case fmt.Stringer:
return original.String(), nil
default:
return nil, fmt.Errorf("cannot convert type %T to Tree", object)
}
}
func sliceToTree(object interface{}) (interface{}, error) {
// arrays are a bit tricky, since they can represent either a
// collection of simple values, which is represented by one
// *tomlValue, or an array of tables, which is represented by an
// array of *Tree.
// holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice
value := reflect.ValueOf(object)
insideType := value.Type().Elem()
length := value.Len()
if length > 0 {
insideType = reflect.ValueOf(value.Index(0).Interface()).Type()
}
if insideType.Kind() == reflect.Map {
// this is considered as an array of tables
tablesArray := make([]*Tree, 0, length)
for i := 0; i < length; i++ {
table := value.Index(i)
tree, err := toTree(table.Interface())
if err != nil {
return nil, err
}
tablesArray = append(tablesArray, tree.(*Tree))
}
return tablesArray, nil
}
sliceType := typeFor(insideType.Kind())
if sliceType == nil {
sliceType = insideType
}
arrayValue := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length)
for i := 0; i < length; i++ {
val := value.Index(i).Interface()
simpleValue, err := simpleValueCoercion(val)
if err != nil {
return nil, err
}
arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue))
}
return &tomlValue{value: arrayValue.Interface(), position: Position{}}, nil
}
func toTree(object interface{}) (interface{}, error) {
value := reflect.ValueOf(object)
if value.Kind() == reflect.Map {
values := map[string]interface{}{}
keys := value.MapKeys()
for _, key := range keys {
if key.Kind() != reflect.String {
if _, ok := key.Interface().(string); !ok {
return nil, fmt.Errorf("map key needs to be a string, not %T (%v)", key.Interface(), key.Kind())
}
}
v := value.MapIndex(key)
newValue, err := toTree(v.Interface())
if err != nil {
return nil, err
}
values[key.String()] = newValue
}
return &Tree{values: values, position: Position{}}, nil
}
if value.Kind() == reflect.Array || value.Kind() == reflect.Slice {
return sliceToTree(object)
}
simpleValue, err := simpleValueCoercion(object)
if err != nil {
return nil, err
}
return &tomlValue{value: simpleValue, position: Position{}}, nil
}

View File

@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"math"
"reflect"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -12,33 +14,34 @@ import (
// encodes a string to a TOML-compliant string value // encodes a string to a TOML-compliant string value
func encodeTomlString(value string) string { func encodeTomlString(value string) string {
result := "" var b bytes.Buffer
for _, rr := range value { for _, rr := range value {
switch rr { switch rr {
case '\b': case '\b':
result += "\\b" b.WriteString(`\b`)
case '\t': case '\t':
result += "\\t" b.WriteString(`\t`)
case '\n': case '\n':
result += "\\n" b.WriteString(`\n`)
case '\f': case '\f':
result += "\\f" b.WriteString(`\f`)
case '\r': case '\r':
result += "\\r" b.WriteString(`\r`)
case '"': case '"':
result += "\\\"" b.WriteString(`\"`)
case '\\': case '\\':
result += "\\\\" b.WriteString(`\\`)
default: default:
intRr := uint16(rr) intRr := uint16(rr)
if intRr < 0x001F { if intRr < 0x001F {
result += fmt.Sprintf("\\u%0.4X", intRr) b.WriteString(fmt.Sprintf("\\u%0.4X", intRr))
} else { } else {
result += string(rr) b.WriteRune(rr)
} }
} }
} }
return result return b.String()
} }
func tomlValueStringRepresentation(v interface{}) (string, error) { func tomlValueStringRepresentation(v interface{}) (string, error) {
@ -48,9 +51,17 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
case int64: case int64:
return strconv.FormatInt(value, 10), nil return strconv.FormatInt(value, 10), nil
case float64: case float64:
// Ensure a round float does contain a decimal point. Otherwise feeding
// the output back to the parser would convert to an integer.
if math.Trunc(value) == value {
return strconv.FormatFloat(value, 'f', 1, 32), nil
}
return strconv.FormatFloat(value, 'f', -1, 32), nil return strconv.FormatFloat(value, 'f', -1, 32), nil
case string: case string:
return "\"" + encodeTomlString(value) + "\"", nil return "\"" + encodeTomlString(value) + "\"", nil
case []byte:
b, _ := v.([]byte)
return tomlValueStringRepresentation(string(b))
case bool: case bool:
if value { if value {
return "true", nil return "true", nil
@ -60,9 +71,14 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
return value.Format(time.RFC3339), nil return value.Format(time.RFC3339), nil
case nil: case nil:
return "", nil return "", nil
case []interface{}: }
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Slice {
values := []string{} values := []string{}
for _, item := range value { for i := 0; i < rv.Len(); i++ {
item := rv.Index(i).Interface()
itemRepr, err := tomlValueStringRepresentation(item) itemRepr, err := tomlValueStringRepresentation(item)
if err != nil { if err != nil {
return "", err return "", err
@ -70,19 +86,18 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
values = append(values, itemRepr) values = append(values, itemRepr)
} }
return "[" + strings.Join(values, ",") + "]", nil return "[" + strings.Join(values, ",") + "]", nil
default:
return "", fmt.Errorf("unsupported value type %T: %v", value, value)
} }
return "", fmt.Errorf("unsupported value type %T: %v", v, v)
} }
func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (int64, error) { func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (int64, error) {
simpleValuesKeys := make([]string, 0) simpleValuesKeys := make([]string, 0)
complexValuesKeys := make([]string, 0) complexValuesKeys := make([]string, 0)
for k := range t.values { for k := range t.values {
v := t.values[k] v := t.values[k]
switch v.(type) { switch v.(type) {
case *TomlTree, []*TomlTree: case *Tree, []*Tree:
complexValuesKeys = append(complexValuesKeys, k) complexValuesKeys = append(complexValuesKeys, k)
default: default:
simpleValuesKeys = append(simpleValuesKeys, k) simpleValuesKeys = append(simpleValuesKeys, k)
@ -95,7 +110,7 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
for _, k := range simpleValuesKeys { for _, k := range simpleValuesKeys {
v, ok := t.values[k].(*tomlValue) v, ok := t.values[k].(*tomlValue)
if !ok { if !ok {
return bytesCount, fmt.Errorf("invalid key type at %s: %T", k, t.values[k]) return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
} }
repr, err := tomlValueStringRepresentation(v.value) repr, err := tomlValueStringRepresentation(v.value)
@ -103,8 +118,24 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
return bytesCount, err return bytesCount, err
} }
kvRepr := fmt.Sprintf("%s%s = %s\n", indent, k, repr) if v.comment != "" {
writtenBytesCount, err := w.Write([]byte(kvRepr)) comment := strings.Replace(v.comment, "\n", "\n"+indent+"#", -1)
start := "# "
if strings.HasPrefix(comment, "#") {
start = ""
}
writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment, "\n")
bytesCount += int64(writtenBytesCountComment)
if errc != nil {
return bytesCount, errc
}
}
var commented string
if v.commented {
commented = "# "
}
writtenBytesCount, err := writeStrings(w, indent, commented, k, " = ", repr, "\n")
bytesCount += int64(writtenBytesCount) bytesCount += int64(writtenBytesCount)
if err != nil { if err != nil {
return bytesCount, err return bytesCount, err
@ -118,12 +149,31 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
if keyspace != "" { if keyspace != "" {
combinedKey = keyspace + "." + combinedKey combinedKey = keyspace + "." + combinedKey
} }
var commented string
if t.commented {
commented = "# "
}
switch node := v.(type) { switch node := v.(type) {
// node has to be of those two types given how keys are sorted above // node has to be of those two types given how keys are sorted above
case *TomlTree: case *Tree:
tableName := fmt.Sprintf("\n%s[%s]\n", indent, combinedKey) tv, ok := t.values[k].(*Tree)
writtenBytesCount, err := w.Write([]byte(tableName)) if !ok {
return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
}
if tv.comment != "" {
comment := strings.Replace(tv.comment, "\n", "\n"+indent+"#", -1)
start := "# "
if strings.HasPrefix(comment, "#") {
start = ""
}
writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment)
bytesCount += int64(writtenBytesCountComment)
if errc != nil {
return bytesCount, errc
}
}
writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n")
bytesCount += int64(writtenBytesCount) bytesCount += int64(writtenBytesCount)
if err != nil { if err != nil {
return bytesCount, err return bytesCount, err
@ -132,20 +182,17 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
if err != nil { if err != nil {
return bytesCount, err return bytesCount, err
} }
case []*TomlTree: case []*Tree:
for _, subTree := range node { for _, subTree := range node {
if len(subTree.values) > 0 { writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n")
tableArrayName := fmt.Sprintf("\n%s[[%s]]\n", indent, combinedKey) bytesCount += int64(writtenBytesCount)
writtenBytesCount, err := w.Write([]byte(tableArrayName)) if err != nil {
bytesCount += int64(writtenBytesCount) return bytesCount, err
if err != nil { }
return bytesCount, err
}
bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount) bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount)
if err != nil { if err != nil {
return bytesCount, err return bytesCount, err
}
} }
} }
} }
@ -154,16 +201,28 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
return bytesCount, nil return bytesCount, nil
} }
// WriteTo encode the TomlTree as Toml and writes it to the writer w. func writeStrings(w io.Writer, s ...string) (int, error) {
var n int
for i := range s {
b, err := io.WriteString(w, s[i])
n += b
if err != nil {
return n, err
}
}
return n, nil
}
// WriteTo encode the Tree as Toml and writes it to the writer w.
// Returns the number of bytes written in case of success, or an error if anything happened. // Returns the number of bytes written in case of success, or an error if anything happened.
func (t *TomlTree) WriteTo(w io.Writer) (int64, error) { func (t *Tree) WriteTo(w io.Writer) (int64, error) {
return t.writeTo(w, "", "", 0) return t.writeTo(w, "", "", 0)
} }
// ToTomlString generates a human-readable representation of the current tree. // ToTomlString generates a human-readable representation of the current tree.
// Output spans multiple lines, and is suitable for ingest by a TOML parser. // Output spans multiple lines, and is suitable for ingest by a TOML parser.
// If the conversion cannot be performed, ToString returns a non-nil error. // If the conversion cannot be performed, ToString returns a non-nil error.
func (t *TomlTree) ToTomlString() (string, error) { func (t *Tree) ToTomlString() (string, error) {
var buf bytes.Buffer var buf bytes.Buffer
_, err := t.WriteTo(&buf) _, err := t.WriteTo(&buf)
if err != nil { if err != nil {
@ -174,36 +233,35 @@ func (t *TomlTree) ToTomlString() (string, error) {
// String generates a human-readable representation of the current tree. // String generates a human-readable representation of the current tree.
// Alias of ToString. Present to implement the fmt.Stringer interface. // Alias of ToString. Present to implement the fmt.Stringer interface.
func (t *TomlTree) String() string { func (t *Tree) String() string {
result, _ := t.ToTomlString() result, _ := t.ToTomlString()
return result return result
} }
// ToMap recursively generates a representation of the tree using Go built-in structures. // ToMap recursively generates a representation of the tree using Go built-in structures.
// The following types are used: // The following types are used:
// * uint64 //
// * int64 // * bool
// * bool // * float64
// * string // * int64
// * time.Time // * string
// * map[string]interface{} (where interface{} is any of this list) // * uint64
// * []interface{} (where interface{} is any of this list) // * time.Time
func (t *TomlTree) ToMap() map[string]interface{} { // * map[string]interface{} (where interface{} is any of this list)
// * []interface{} (where interface{} is any of this list)
func (t *Tree) ToMap() map[string]interface{} {
result := map[string]interface{}{} result := map[string]interface{}{}
for k, v := range t.values { for k, v := range t.values {
switch node := v.(type) { switch node := v.(type) {
case []*TomlTree: case []*Tree:
var array []interface{} var array []interface{}
for _, item := range node { for _, item := range node {
array = append(array, item.ToMap()) array = append(array, item.ToMap())
} }
result[k] = array result[k] = array
case *TomlTree: case *Tree:
result[k] = node.ToMap() result[k] = node.ToMap()
case map[string]interface{}:
sub := TreeFromMap(node)
result[k] = sub.ToMap()
case *tomlValue: case *tomlValue:
result[k] = node.value result[k] = node.value
} }

View File

@ -79,6 +79,14 @@ func (f Frame) Format(s fmt.State, verb rune) {
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). // StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
type StackTrace []Frame type StackTrace []Frame
// Format formats the stack of Frames according to the fmt.Formatter interface.
//
// %s lists source files for each Frame in the stack
// %v lists the source file and line number for each Frame in the stack
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+v Prints filename, function, and line number for each Frame in the stack.
func (st StackTrace) Format(s fmt.State, verb rune) { func (st StackTrace) Format(s fmt.State, verb rune) {
switch verb { switch verb {
case 'v': case 'v':

View File

@ -52,7 +52,7 @@ func validateBasePathName(name string) error {
// On Windows a common mistake would be to provide an absolute OS path // On Windows a common mistake would be to provide an absolute OS path
// We could strip out the base part, but that would not be very portable. // We could strip out the base part, but that would not be very portable.
if filepath.IsAbs(name) { if filepath.IsAbs(name) {
return &os.PathError{"realPath", name, errors.New("got a real OS path instead of a virtual")} return &os.PathError{Op: "realPath", Path: name, Err: errors.New("got a real OS path instead of a virtual")}
} }
return nil return nil
@ -60,14 +60,14 @@ func validateBasePathName(name string) error {
func (b *BasePathFs) Chtimes(name string, atime, mtime time.Time) (err error) { func (b *BasePathFs) Chtimes(name string, atime, mtime time.Time) (err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return &os.PathError{"chtimes", name, err} return &os.PathError{Op: "chtimes", Path: name, Err: err}
} }
return b.source.Chtimes(name, atime, mtime) return b.source.Chtimes(name, atime, mtime)
} }
func (b *BasePathFs) Chmod(name string, mode os.FileMode) (err error) { func (b *BasePathFs) Chmod(name string, mode os.FileMode) (err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return &os.PathError{"chmod", name, err} return &os.PathError{Op: "chmod", Path: name, Err: err}
} }
return b.source.Chmod(name, mode) return b.source.Chmod(name, mode)
} }
@ -78,66 +78,66 @@ func (b *BasePathFs) Name() string {
func (b *BasePathFs) Stat(name string) (fi os.FileInfo, err error) { func (b *BasePathFs) Stat(name string) (fi os.FileInfo, err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return nil, &os.PathError{"stat", name, err} return nil, &os.PathError{Op: "stat", Path: name, Err: err}
} }
return b.source.Stat(name) return b.source.Stat(name)
} }
func (b *BasePathFs) Rename(oldname, newname string) (err error) { func (b *BasePathFs) Rename(oldname, newname string) (err error) {
if oldname, err = b.RealPath(oldname); err != nil { if oldname, err = b.RealPath(oldname); err != nil {
return &os.PathError{"rename", oldname, err} return &os.PathError{Op: "rename", Path: oldname, Err: err}
} }
if newname, err = b.RealPath(newname); err != nil { if newname, err = b.RealPath(newname); err != nil {
return &os.PathError{"rename", newname, err} return &os.PathError{Op: "rename", Path: newname, Err: err}
} }
return b.source.Rename(oldname, newname) return b.source.Rename(oldname, newname)
} }
func (b *BasePathFs) RemoveAll(name string) (err error) { func (b *BasePathFs) RemoveAll(name string) (err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return &os.PathError{"remove_all", name, err} return &os.PathError{Op: "remove_all", Path: name, Err: err}
} }
return b.source.RemoveAll(name) return b.source.RemoveAll(name)
} }
func (b *BasePathFs) Remove(name string) (err error) { func (b *BasePathFs) Remove(name string) (err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return &os.PathError{"remove", name, err} return &os.PathError{Op: "remove", Path: name, Err: err}
} }
return b.source.Remove(name) return b.source.Remove(name)
} }
func (b *BasePathFs) OpenFile(name string, flag int, mode os.FileMode) (f File, err error) { func (b *BasePathFs) OpenFile(name string, flag int, mode os.FileMode) (f File, err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return nil, &os.PathError{"openfile", name, err} return nil, &os.PathError{Op: "openfile", Path: name, Err: err}
} }
return b.source.OpenFile(name, flag, mode) return b.source.OpenFile(name, flag, mode)
} }
func (b *BasePathFs) Open(name string) (f File, err error) { func (b *BasePathFs) Open(name string) (f File, err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return nil, &os.PathError{"open", name, err} return nil, &os.PathError{Op: "open", Path: name, Err: err}
} }
return b.source.Open(name) return b.source.Open(name)
} }
func (b *BasePathFs) Mkdir(name string, mode os.FileMode) (err error) { func (b *BasePathFs) Mkdir(name string, mode os.FileMode) (err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return &os.PathError{"mkdir", name, err} return &os.PathError{Op: "mkdir", Path: name, Err: err}
} }
return b.source.Mkdir(name, mode) return b.source.Mkdir(name, mode)
} }
func (b *BasePathFs) MkdirAll(name string, mode os.FileMode) (err error) { func (b *BasePathFs) MkdirAll(name string, mode os.FileMode) (err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return &os.PathError{"mkdir", name, err} return &os.PathError{Op: "mkdir", Path: name, Err: err}
} }
return b.source.MkdirAll(name, mode) return b.source.MkdirAll(name, mode)
} }
func (b *BasePathFs) Create(name string) (f File, err error) { func (b *BasePathFs) Create(name string) (f File, err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return nil, &os.PathError{"create", name, err} return nil, &os.PathError{Op: "create", Path: name, Err: err}
} }
return b.source.Create(name) return b.source.Create(name)
} }

View File

@ -64,15 +64,10 @@ func (u *CacheOnReadFs) cacheStatus(name string) (state cacheState, fi os.FileIn
return cacheHit, lfi, nil return cacheHit, lfi, nil
} }
if err == syscall.ENOENT { if err == syscall.ENOENT || os.IsNotExist(err) {
return cacheMiss, nil, nil return cacheMiss, nil, nil
} }
var ok bool
if err, ok = err.(*os.PathError); ok {
if err == os.ErrNotExist {
return cacheMiss, nil, nil
}
}
return cacheMiss, nil, err return cacheMiss, nil, err
} }

View File

@ -80,7 +80,7 @@ func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) {
if e, ok := err.(*os.PathError); ok { if e, ok := err.(*os.PathError); ok {
err = e.Err err = e.Err
} }
if err == syscall.ENOENT || err == syscall.ENOTDIR { if err == os.ErrNotExist || err == syscall.ENOENT || err == syscall.ENOTDIR {
return u.base.Stat(name) return u.base.Stat(name)
} }
return nil, origErr return nil, origErr

110
vendor/github.com/spf13/afero/match.go generated vendored Normal file
View File

@ -0,0 +1,110 @@
// Copyright © 2014 Steve Francia <spf@spf13.com>.
// Copyright 2009 The Go Authors. 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 afero
import (
"path/filepath"
"sort"
"strings"
)
// Glob returns the names of all files matching pattern or nil
// if there is no matching file. The syntax of patterns is the same
// as in Match. The pattern may describe hierarchical names such as
// /usr/*/bin/ed (assuming the Separator is '/').
//
// Glob ignores file system errors such as I/O errors reading directories.
// The only possible returned error is ErrBadPattern, when pattern
// is malformed.
//
// This was adapted from (http://golang.org/pkg/path/filepath) and uses several
// built-ins from that package.
func Glob(fs Fs, pattern string) (matches []string, err error) {
if !hasMeta(pattern) {
// afero does not support Lstat directly.
if _, err = lstatIfOs(fs, pattern); err != nil {
return nil, nil
}
return []string{pattern}, nil
}
dir, file := filepath.Split(pattern)
switch dir {
case "":
dir = "."
case string(filepath.Separator):
// nothing
default:
dir = dir[0 : len(dir)-1] // chop off trailing separator
}
if !hasMeta(dir) {
return glob(fs, dir, file, nil)
}
var m []string
m, err = Glob(fs, dir)
if err != nil {
return
}
for _, d := range m {
matches, err = glob(fs, d, file, matches)
if err != nil {
return
}
}
return
}
// glob searches for files matching pattern in the directory dir
// and appends them to matches. If the directory cannot be
// opened, it returns the existing matches. New matches are
// added in lexicographical order.
func glob(fs Fs, dir, pattern string, matches []string) (m []string, e error) {
m = matches
fi, err := fs.Stat(dir)
if err != nil {
return
}
if !fi.IsDir() {
return
}
d, err := fs.Open(dir)
if err != nil {
return
}
defer d.Close()
names, _ := d.Readdirnames(-1)
sort.Strings(names)
for _, n := range names {
matched, err := filepath.Match(pattern, n)
if err != nil {
return m, err
}
if matched {
m = append(m, filepath.Join(dir, n))
}
}
return
}
// hasMeta reports whether path contains any of the magic characters
// recognized by Match.
func hasMeta(path string) bool {
// TODO(niemeyer): Should other magic characters be added here?
return strings.IndexAny(path, "*?[") >= 0
}

View File

@ -74,14 +74,24 @@ func CreateDir(name string) *FileData {
} }
func ChangeFileName(f *FileData, newname string) { func ChangeFileName(f *FileData, newname string) {
f.Lock()
f.name = newname f.name = newname
f.Unlock()
} }
func SetMode(f *FileData, mode os.FileMode) { func SetMode(f *FileData, mode os.FileMode) {
f.Lock()
f.mode = mode f.mode = mode
f.Unlock()
} }
func SetModTime(f *FileData, mtime time.Time) { func SetModTime(f *FileData, mtime time.Time) {
f.Lock()
setModTime(f, mtime)
f.Unlock()
}
func setModTime(f *FileData, mtime time.Time) {
f.modtime = mtime f.modtime = mtime
} }
@ -102,7 +112,7 @@ func (f *File) Close() error {
f.fileData.Lock() f.fileData.Lock()
f.closed = true f.closed = true
if !f.readOnly { if !f.readOnly {
SetModTime(f.fileData, time.Now()) setModTime(f.fileData, time.Now())
} }
f.fileData.Unlock() f.fileData.Unlock()
return nil return nil
@ -186,7 +196,7 @@ func (f *File) Truncate(size int64) error {
return ErrFileClosed return ErrFileClosed
} }
if f.readOnly { if f.readOnly {
return &os.PathError{"truncate", f.fileData.name, errors.New("file handle is read only")} return &os.PathError{Op: "truncate", Path: f.fileData.name, Err: errors.New("file handle is read only")}
} }
if size < 0 { if size < 0 {
return ErrOutOfRange return ErrOutOfRange
@ -197,7 +207,7 @@ func (f *File) Truncate(size int64) error {
} else { } else {
f.fileData.data = f.fileData.data[0:size] f.fileData.data = f.fileData.data[0:size]
} }
SetModTime(f.fileData, time.Now()) setModTime(f.fileData, time.Now())
return nil return nil
} }
@ -218,7 +228,7 @@ func (f *File) Seek(offset int64, whence int) (int64, error) {
func (f *File) Write(b []byte) (n int, err error) { func (f *File) Write(b []byte) (n int, err error) {
if f.readOnly { if f.readOnly {
return 0, &os.PathError{"write", f.fileData.name, errors.New("file handle is read only")} return 0, &os.PathError{Op: "write", Path: f.fileData.name, Err: errors.New("file handle is read only")}
} }
n = len(b) n = len(b)
cur := atomic.LoadInt64(&f.at) cur := atomic.LoadInt64(&f.at)
@ -236,7 +246,7 @@ func (f *File) Write(b []byte) (n int, err error) {
f.fileData.data = append(f.fileData.data[:cur], b...) f.fileData.data = append(f.fileData.data[:cur], b...)
f.fileData.data = append(f.fileData.data, tail...) f.fileData.data = append(f.fileData.data, tail...)
} }
SetModTime(f.fileData, time.Now()) setModTime(f.fileData, time.Now())
atomic.StoreInt64(&f.at, int64(len(f.fileData.data))) atomic.StoreInt64(&f.at, int64(len(f.fileData.data)))
return return
@ -261,17 +271,33 @@ type FileInfo struct {
// Implements os.FileInfo // Implements os.FileInfo
func (s *FileInfo) Name() string { func (s *FileInfo) Name() string {
s.Lock()
_, name := filepath.Split(s.name) _, name := filepath.Split(s.name)
s.Unlock()
return name return name
} }
func (s *FileInfo) Mode() os.FileMode { return s.mode } func (s *FileInfo) Mode() os.FileMode {
func (s *FileInfo) ModTime() time.Time { return s.modtime } s.Lock()
func (s *FileInfo) IsDir() bool { return s.dir } defer s.Unlock()
func (s *FileInfo) Sys() interface{} { return nil } return s.mode
}
func (s *FileInfo) ModTime() time.Time {
s.Lock()
defer s.Unlock()
return s.modtime
}
func (s *FileInfo) IsDir() bool {
s.Lock()
defer s.Unlock()
return s.dir
}
func (s *FileInfo) Sys() interface{} { return nil }
func (s *FileInfo) Size() int64 { func (s *FileInfo) Size() int64 {
if s.IsDir() { if s.IsDir() {
return int64(42) return int64(42)
} }
s.Lock()
defer s.Unlock()
return int64(len(s.data)) return int64(len(s.data))
} }

View File

@ -45,7 +45,7 @@ func (m *MemMapFs) getData() map[string]*mem.FileData {
return m.data return m.data
} }
func (MemMapFs) Name() string { return "MemMapFS" } func (*MemMapFs) Name() string { return "MemMapFS" }
func (m *MemMapFs) Create(name string) (File, error) { func (m *MemMapFs) Create(name string) (File, error) {
name = normalizePath(name) name = normalizePath(name)
@ -66,7 +66,10 @@ func (m *MemMapFs) unRegisterWithParent(fileName string) error {
if parent == nil { if parent == nil {
log.Panic("parent of ", f.Name(), " is nil") log.Panic("parent of ", f.Name(), " is nil")
} }
parent.Lock()
mem.RemoveFromMemDir(parent, f) mem.RemoveFromMemDir(parent, f)
parent.Unlock()
return nil return nil
} }
@ -99,8 +102,10 @@ func (m *MemMapFs) registerWithParent(f *mem.FileData) {
} }
} }
parent.Lock()
mem.InitializeDir(parent) mem.InitializeDir(parent)
mem.AddToMemDir(parent, f) mem.AddToMemDir(parent, f)
parent.Unlock()
} }
func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error { func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
@ -108,7 +113,7 @@ func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
x, ok := m.getData()[name] x, ok := m.getData()[name]
if ok { if ok {
// Only return ErrFileExists if it's a file, not a directory. // Only return ErrFileExists if it's a file, not a directory.
i := mem.FileInfo{x} i := mem.FileInfo{FileData: x}
if !i.IsDir() { if !i.IsDir() {
return ErrFileExists return ErrFileExists
} }
@ -127,15 +132,17 @@ func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
_, ok := m.getData()[name] _, ok := m.getData()[name]
m.mu.RUnlock() m.mu.RUnlock()
if ok { if ok {
return &os.PathError{"mkdir", name, ErrFileExists} return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
} else {
m.mu.Lock()
item := mem.CreateDir(name)
m.getData()[name] = item
m.registerWithParent(item)
m.mu.Unlock()
m.Chmod(name, perm)
} }
m.mu.Lock()
item := mem.CreateDir(name)
m.getData()[name] = item
m.registerWithParent(item)
m.mu.Unlock()
m.Chmod(name, perm|os.ModeDir)
return nil return nil
} }
@ -144,9 +151,8 @@ func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
if err != nil { if err != nil {
if err.(*os.PathError).Err == ErrFileExists { if err.(*os.PathError).Err == ErrFileExists {
return nil return nil
} else {
return err
} }
return err
} }
return nil return nil
} }
@ -188,7 +194,7 @@ func (m *MemMapFs) open(name string) (*mem.FileData, error) {
f, ok := m.getData()[name] f, ok := m.getData()[name]
m.mu.RUnlock() m.mu.RUnlock()
if !ok { if !ok {
return nil, &os.PathError{"open", name, ErrFileNotFound} return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileNotFound}
} }
return f, nil return f, nil
} }
@ -245,11 +251,11 @@ func (m *MemMapFs) Remove(name string) error {
if _, ok := m.getData()[name]; ok { if _, ok := m.getData()[name]; ok {
err := m.unRegisterWithParent(name) err := m.unRegisterWithParent(name)
if err != nil { if err != nil {
return &os.PathError{"remove", name, err} return &os.PathError{Op: "remove", Path: name, Err: err}
} }
delete(m.getData(), name) delete(m.getData(), name)
} else { } else {
return &os.PathError{"remove", name, os.ErrNotExist} return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist}
} }
return nil return nil
} }
@ -297,7 +303,7 @@ func (m *MemMapFs) Rename(oldname, newname string) error {
m.mu.Unlock() m.mu.Unlock()
m.mu.RLock() m.mu.RLock()
} else { } else {
return &os.PathError{"rename", oldname, ErrFileNotFound} return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
} }
return nil return nil
} }
@ -313,9 +319,12 @@ func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
func (m *MemMapFs) Chmod(name string, mode os.FileMode) error { func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
name = normalizePath(name) name = normalizePath(name)
m.mu.RLock()
f, ok := m.getData()[name] f, ok := m.getData()[name]
m.mu.RUnlock()
if !ok { if !ok {
return &os.PathError{"chmod", name, ErrFileNotFound} return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
} }
m.mu.Lock() m.mu.Lock()
@ -327,9 +336,12 @@ func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error { func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
name = normalizePath(name) name = normalizePath(name)
m.mu.RLock()
f, ok := m.getData()[name] f, ok := m.getData()[name]
m.mu.RUnlock()
if !ok { if !ok {
return &os.PathError{"chtimes", name, ErrFileNotFound} return &os.PathError{Op: "chtimes", Path: name, Err: ErrFileNotFound}
} }
m.mu.Lock() m.mu.Lock()
@ -341,7 +353,7 @@ func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error
func (m *MemMapFs) List() { func (m *MemMapFs) List() {
for _, x := range m.data { for _, x := range m.data {
y := mem.FileInfo{x} y := mem.FileInfo{FileData: x}
fmt.Println(x.Name(), y.Size()) fmt.Println(x.Name(), y.Size())
} }
} }

View File

@ -1,14 +0,0 @@
// Copyright © 2014 Steve Francia <spf@spf13.com>.
//
// 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 afero

View File

@ -157,7 +157,7 @@ func UnicodeSanitize(s string) string {
return string(target) return string(target)
} }
// Transform characters with accents into plan forms // Transform characters with accents into plain forms.
func NeuterAccents(s string) string { func NeuterAccents(s string) string {
t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC) t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC)
result, _, _ := transform.String(t, string(s)) result, _, _ := transform.String(t, string(s))

76
vendor/github.com/spf13/cast/cast.go generated vendored
View File

@ -3,81 +3,157 @@
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package cast provides easy and safe casting in Go.
package cast package cast
import "time" import "time"
// ToBool casts an interface to a bool type.
func ToBool(i interface{}) bool { func ToBool(i interface{}) bool {
v, _ := ToBoolE(i) v, _ := ToBoolE(i)
return v return v
} }
// ToTime casts an interface to a time.Time type.
func ToTime(i interface{}) time.Time { func ToTime(i interface{}) time.Time {
v, _ := ToTimeE(i) v, _ := ToTimeE(i)
return v return v
} }
// ToDuration casts an interface to a time.Duration type.
func ToDuration(i interface{}) time.Duration { func ToDuration(i interface{}) time.Duration {
v, _ := ToDurationE(i) v, _ := ToDurationE(i)
return v return v
} }
// ToFloat64 casts an interface to a float64 type.
func ToFloat64(i interface{}) float64 { func ToFloat64(i interface{}) float64 {
v, _ := ToFloat64E(i) v, _ := ToFloat64E(i)
return v return v
} }
// ToFloat32 casts an interface to a float32 type.
func ToFloat32(i interface{}) float32 {
v, _ := ToFloat32E(i)
return v
}
// ToInt64 casts an interface to an int64 type.
func ToInt64(i interface{}) int64 { func ToInt64(i interface{}) int64 {
v, _ := ToInt64E(i) v, _ := ToInt64E(i)
return v return v
} }
// ToInt32 casts an interface to an int32 type.
func ToInt32(i interface{}) int32 {
v, _ := ToInt32E(i)
return v
}
// ToInt16 casts an interface to an int16 type.
func ToInt16(i interface{}) int16 {
v, _ := ToInt16E(i)
return v
}
// ToInt8 casts an interface to an int8 type.
func ToInt8(i interface{}) int8 {
v, _ := ToInt8E(i)
return v
}
// ToInt casts an interface to an int type.
func ToInt(i interface{}) int { func ToInt(i interface{}) int {
v, _ := ToIntE(i) v, _ := ToIntE(i)
return v return v
} }
// ToUint casts an interface to a uint type.
func ToUint(i interface{}) uint {
v, _ := ToUintE(i)
return v
}
// ToUint64 casts an interface to a uint64 type.
func ToUint64(i interface{}) uint64 {
v, _ := ToUint64E(i)
return v
}
// ToUint32 casts an interface to a uint32 type.
func ToUint32(i interface{}) uint32 {
v, _ := ToUint32E(i)
return v
}
// ToUint16 casts an interface to a uint16 type.
func ToUint16(i interface{}) uint16 {
v, _ := ToUint16E(i)
return v
}
// ToUint8 casts an interface to a uint8 type.
func ToUint8(i interface{}) uint8 {
v, _ := ToUint8E(i)
return v
}
// ToString casts an interface to a string type.
func ToString(i interface{}) string { func ToString(i interface{}) string {
v, _ := ToStringE(i) v, _ := ToStringE(i)
return v return v
} }
// ToStringMapString casts an interface to a map[string]string type.
func ToStringMapString(i interface{}) map[string]string { func ToStringMapString(i interface{}) map[string]string {
v, _ := ToStringMapStringE(i) v, _ := ToStringMapStringE(i)
return v return v
} }
// ToStringMapStringSlice casts an interface to a map[string][]string type.
func ToStringMapStringSlice(i interface{}) map[string][]string { func ToStringMapStringSlice(i interface{}) map[string][]string {
v, _ := ToStringMapStringSliceE(i) v, _ := ToStringMapStringSliceE(i)
return v return v
} }
// ToStringMapBool casts an interface to a map[string]bool type.
func ToStringMapBool(i interface{}) map[string]bool { func ToStringMapBool(i interface{}) map[string]bool {
v, _ := ToStringMapBoolE(i) v, _ := ToStringMapBoolE(i)
return v return v
} }
// ToStringMap casts an interface to a map[string]interface{} type.
func ToStringMap(i interface{}) map[string]interface{} { func ToStringMap(i interface{}) map[string]interface{} {
v, _ := ToStringMapE(i) v, _ := ToStringMapE(i)
return v return v
} }
// ToSlice casts an interface to a []interface{} type.
func ToSlice(i interface{}) []interface{} { func ToSlice(i interface{}) []interface{} {
v, _ := ToSliceE(i) v, _ := ToSliceE(i)
return v return v
} }
// ToBoolSlice casts an interface to a []bool type.
func ToBoolSlice(i interface{}) []bool { func ToBoolSlice(i interface{}) []bool {
v, _ := ToBoolSliceE(i) v, _ := ToBoolSliceE(i)
return v return v
} }
// ToStringSlice casts an interface to a []string type.
func ToStringSlice(i interface{}) []string { func ToStringSlice(i interface{}) []string {
v, _ := ToStringSliceE(i) v, _ := ToStringSliceE(i)
return v return v
} }
// ToIntSlice casts an interface to a []int type.
func ToIntSlice(i interface{}) []int { func ToIntSlice(i interface{}) []int {
v, _ := ToIntSliceE(i) v, _ := ToIntSliceE(i)
return v return v
} }
// ToDurationSlice casts an interface to a []time.Duration type.
func ToDurationSlice(i interface{}) []time.Duration {
v, _ := ToDurationSliceE(i)
return v
}

783
vendor/github.com/spf13/cast/caste.go generated vendored

File diff suppressed because it is too large Load Diff

89
vendor/github.com/spf13/cobra/args.go generated vendored Normal file
View File

@ -0,0 +1,89 @@
package cobra
import (
"fmt"
)
type PositionalArgs func(cmd *Command, args []string) error
// Legacy arg validation has the following behaviour:
// - root commands with no subcommands can take arbitrary arguments
// - root commands with subcommands will do subcommand validity checking
// - subcommands will always accept arbitrary arguments
func legacyArgs(cmd *Command, args []string) error {
// no subcommand, always take args
if !cmd.HasSubCommands() {
return nil
}
// root command with subcommands, do subcommand checking.
if !cmd.HasParent() && len(args) > 0 {
return fmt.Errorf("unknown command %q for %q%s", args[0], cmd.CommandPath(), cmd.findSuggestions(args[0]))
}
return nil
}
// NoArgs returns an error if any args are included.
func NoArgs(cmd *Command, args []string) error {
if len(args) > 0 {
return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath())
}
return nil
}
// OnlyValidArgs returns an error if any args are not in the list of ValidArgs.
func OnlyValidArgs(cmd *Command, args []string) error {
if len(cmd.ValidArgs) > 0 {
for _, v := range args {
if !stringInSlice(v, cmd.ValidArgs) {
return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0]))
}
}
}
return nil
}
// ArbitraryArgs never returns an error.
func ArbitraryArgs(cmd *Command, args []string) error {
return nil
}
// MinimumNArgs returns an error if there is not at least N args.
func MinimumNArgs(n int) PositionalArgs {
return func(cmd *Command, args []string) error {
if len(args) < n {
return fmt.Errorf("requires at least %d arg(s), only received %d", n, len(args))
}
return nil
}
}
// MaximumNArgs returns an error if there are more than N args.
func MaximumNArgs(n int) PositionalArgs {
return func(cmd *Command, args []string) error {
if len(args) > n {
return fmt.Errorf("accepts at most %d arg(s), received %d", n, len(args))
}
return nil
}
}
// ExactArgs returns an error if there are not exactly n args.
func ExactArgs(n int) PositionalArgs {
return func(cmd *Command, args []string) error {
if len(args) != n {
return fmt.Errorf("accepts %d arg(s), received %d", n, len(args))
}
return nil
}
}
// RangeArgs returns an error if the number of args is not within the expected range.
func RangeArgs(min int, max int) PositionalArgs {
return func(cmd *Command, args []string) error {
if len(args) < min || len(args) > max {
return fmt.Errorf("accepts between %d and %d arg(s), received %d", min, max, len(args))
}
return nil
}
}

View File

@ -1,6 +1,7 @@
package cobra package cobra
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -10,6 +11,7 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
// Annotations for Bash completion.
const ( const (
BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions" BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions"
BashCompCustom = "cobra_annotation_bash_completion_custom" BashCompCustom = "cobra_annotation_bash_completion_custom"
@ -17,12 +19,9 @@ const (
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir" BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
) )
func preamble(out io.Writer, name string) error { func writePreamble(buf *bytes.Buffer, name string) {
_, err := fmt.Fprintf(out, "# bash completion for %-36s -*- shell-script -*-\n", name) buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
if err != nil { buf.WriteString(`
return err
}
_, err = fmt.Fprint(out, `
__debug() __debug()
{ {
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
@ -87,13 +86,13 @@ __handle_reply()
local index flag local index flag
flag="${cur%%=*}" flag="${cur%%=*}"
__index_of_word "${flag}" "${flags_with_completion[@]}" __index_of_word "${flag}" "${flags_with_completion[@]}"
COMPREPLY=()
if [[ ${index} -ge 0 ]]; then if [[ ${index} -ge 0 ]]; then
COMPREPLY=()
PREFIX="" PREFIX=""
cur="${cur#*=}" cur="${cur#*=}"
${flags_completion[${index}]} ${flags_completion[${index}]}
if [ -n "${ZSH_VERSION}" ]; then if [ -n "${ZSH_VERSION}" ]; then
# zfs completion needs --flag= prefix # zsh completion needs --flag= prefix
eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )" eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )"
fi fi
fi fi
@ -133,7 +132,10 @@ __handle_reply()
declare -F __custom_func >/dev/null && __custom_func declare -F __custom_func >/dev/null && __custom_func
fi fi
__ltrim_colon_completions "$cur" # available in bash-completion >= 2, not always present on macOS
if declare -F __ltrim_colon_completions >/dev/null; then
__ltrim_colon_completions "$cur"
fi
} }
# The arguments should be in the form "ext1|ext2|extn" # The arguments should be in the form "ext1|ext2|extn"
@ -224,7 +226,7 @@ __handle_command()
fi fi
c=$((c+1)) c=$((c+1))
__debug "${FUNCNAME[0]}: looking for ${next_command}" __debug "${FUNCNAME[0]}: looking for ${next_command}"
declare -F $next_command >/dev/null && $next_command declare -F "$next_command" >/dev/null && $next_command
} }
__handle_word() __handle_word()
@ -247,16 +249,12 @@ __handle_word()
} }
`) `)
return err
} }
func postscript(w io.Writer, name string) error { func writePostscript(buf *bytes.Buffer, name string) {
name = strings.Replace(name, ":", "__", -1) name = strings.Replace(name, ":", "__", -1)
_, err := fmt.Fprintf(w, "__start_%s()\n", name) buf.WriteString(fmt.Sprintf("__start_%s()\n", name))
if err != nil { buf.WriteString(fmt.Sprintf(`{
return err
}
_, err = fmt.Fprintf(w, `{
local cur prev words cword local cur prev words cword
declare -A flaghash 2>/dev/null || : declare -A flaghash 2>/dev/null || :
if declare -F _init_completion >/dev/null 2>&1; then if declare -F _init_completion >/dev/null 2>&1; then
@ -280,197 +278,132 @@ func postscript(w io.Writer, name string) error {
__handle_word __handle_word
} }
`, name) `, name))
if err != nil { buf.WriteString(fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then
return err
}
_, err = fmt.Fprintf(w, `if [[ $(type -t compopt) = "builtin" ]]; then
complete -o default -F __start_%s %s complete -o default -F __start_%s %s
else else
complete -o default -o nospace -F __start_%s %s complete -o default -o nospace -F __start_%s %s
fi fi
`, name, name, name, name) `, name, name, name, name))
if err != nil { buf.WriteString("# ex: ts=4 sw=4 et filetype=sh\n")
return err
}
_, err = fmt.Fprintf(w, "# ex: ts=4 sw=4 et filetype=sh\n")
return err
} }
func writeCommands(cmd *Command, w io.Writer) error { func writeCommands(buf *bytes.Buffer, cmd *Command) {
if _, err := fmt.Fprintf(w, " commands=()\n"); err != nil { buf.WriteString(" commands=()\n")
return err
}
for _, c := range cmd.Commands() { for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() || c == cmd.helpCommand { if !c.IsAvailableCommand() || c == cmd.helpCommand {
continue continue
} }
if _, err := fmt.Fprintf(w, " commands+=(%q)\n", c.Name()); err != nil { buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name()))
return err
}
} }
_, err := fmt.Fprintf(w, "\n") buf.WriteString("\n")
return err
} }
func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) error { func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string) {
for key, value := range annotations { for key, value := range annotations {
switch key { switch key {
case BashCompFilenameExt: case BashCompFilenameExt:
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
if err != nil {
return err
}
var ext string
if len(value) > 0 { if len(value) > 0 {
ext := "__handle_filename_extension_flag " + strings.Join(value, "|") ext = "__handle_filename_extension_flag " + strings.Join(value, "|")
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
} else { } else {
ext := "_filedir" ext = "_filedir"
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
}
if err != nil {
return err
} }
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext))
case BashCompCustom: case BashCompCustom:
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
if err != nil {
return err
}
if len(value) > 0 { if len(value) > 0 {
handlers := strings.Join(value, "; ") handlers := strings.Join(value, "; ")
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", handlers) buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", handlers))
} else { } else {
_, err = fmt.Fprintf(w, " flags_completion+=(:)\n") buf.WriteString(" flags_completion+=(:)\n")
}
if err != nil {
return err
} }
case BashCompSubdirsInDir: case BashCompSubdirsInDir:
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
var ext string
if len(value) == 1 { if len(value) == 1 {
ext := "__handle_subdirs_in_dir_flag " + value[0] ext = "__handle_subdirs_in_dir_flag " + value[0]
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
} else { } else {
ext := "_filedir -d" ext = "_filedir -d"
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
}
if err != nil {
return err
} }
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext))
} }
} }
return nil
} }
func writeShortFlag(flag *pflag.Flag, w io.Writer) error { func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag) {
b := (len(flag.NoOptDefVal) > 0)
name := flag.Shorthand name := flag.Shorthand
format := " " format := " "
if !b { if len(flag.NoOptDefVal) == 0 {
format += "two_word_" format += "two_word_"
} }
format += "flags+=(\"-%s\")\n" format += "flags+=(\"-%s\")\n"
if _, err := fmt.Fprintf(w, format, name); err != nil { buf.WriteString(fmt.Sprintf(format, name))
return err writeFlagHandler(buf, "-"+name, flag.Annotations)
}
return writeFlagHandler("-"+name, flag.Annotations, w)
} }
func writeFlag(flag *pflag.Flag, w io.Writer) error { func writeFlag(buf *bytes.Buffer, flag *pflag.Flag) {
b := (len(flag.NoOptDefVal) > 0)
name := flag.Name name := flag.Name
format := " flags+=(\"--%s" format := " flags+=(\"--%s"
if !b { if len(flag.NoOptDefVal) == 0 {
format += "=" format += "="
} }
format += "\")\n" format += "\")\n"
if _, err := fmt.Fprintf(w, format, name); err != nil { buf.WriteString(fmt.Sprintf(format, name))
return err writeFlagHandler(buf, "--"+name, flag.Annotations)
}
return writeFlagHandler("--"+name, flag.Annotations, w)
} }
func writeLocalNonPersistentFlag(flag *pflag.Flag, w io.Writer) error { func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) {
b := (len(flag.NoOptDefVal) > 0)
name := flag.Name name := flag.Name
format := " local_nonpersistent_flags+=(\"--%s" format := " local_nonpersistent_flags+=(\"--%s"
if !b { if len(flag.NoOptDefVal) == 0 {
format += "=" format += "="
} }
format += "\")\n" format += "\")\n"
_, err := fmt.Fprintf(w, format, name) buf.WriteString(fmt.Sprintf(format, name))
return err
} }
func writeFlags(cmd *Command, w io.Writer) error { func writeFlags(buf *bytes.Buffer, cmd *Command) {
_, err := fmt.Fprintf(w, ` flags=() buf.WriteString(` flags=()
two_word_flags=() two_word_flags=()
local_nonpersistent_flags=() local_nonpersistent_flags=()
flags_with_completion=() flags_with_completion=()
flags_completion=() flags_completion=()
`) `)
if err != nil {
return err
}
localNonPersistentFlags := cmd.LocalNonPersistentFlags() localNonPersistentFlags := cmd.LocalNonPersistentFlags()
var visitErr error
cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
if nonCompletableFlag(flag) { if nonCompletableFlag(flag) {
return return
} }
if err := writeFlag(flag, w); err != nil { writeFlag(buf, flag)
visitErr = err
return
}
if len(flag.Shorthand) > 0 { if len(flag.Shorthand) > 0 {
if err := writeShortFlag(flag, w); err != nil { writeShortFlag(buf, flag)
visitErr = err
return
}
} }
if localNonPersistentFlags.Lookup(flag.Name) != nil { if localNonPersistentFlags.Lookup(flag.Name) != nil {
if err := writeLocalNonPersistentFlag(flag, w); err != nil { writeLocalNonPersistentFlag(buf, flag)
visitErr = err
return
}
} }
}) })
if visitErr != nil {
return visitErr
}
cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
if nonCompletableFlag(flag) { if nonCompletableFlag(flag) {
return return
} }
if err := writeFlag(flag, w); err != nil { writeFlag(buf, flag)
visitErr = err
return
}
if len(flag.Shorthand) > 0 { if len(flag.Shorthand) > 0 {
if err := writeShortFlag(flag, w); err != nil { writeShortFlag(buf, flag)
visitErr = err
return
}
} }
}) })
if visitErr != nil {
return visitErr
}
_, err = fmt.Fprintf(w, "\n") buf.WriteString("\n")
return err
} }
func writeRequiredFlag(cmd *Command, w io.Writer) error { func writeRequiredFlag(buf *bytes.Buffer, cmd *Command) {
if _, err := fmt.Fprintf(w, " must_have_one_flag=()\n"); err != nil { buf.WriteString(" must_have_one_flag=()\n")
return err
}
flags := cmd.NonInheritedFlags() flags := cmd.NonInheritedFlags()
var visitErr error
flags.VisitAll(func(flag *pflag.Flag) { flags.VisitAll(func(flag *pflag.Flag) {
if nonCompletableFlag(flag) { if nonCompletableFlag(flag) {
return return
@ -479,130 +412,93 @@ func writeRequiredFlag(cmd *Command, w io.Writer) error {
switch key { switch key {
case BashCompOneRequiredFlag: case BashCompOneRequiredFlag:
format := " must_have_one_flag+=(\"--%s" format := " must_have_one_flag+=(\"--%s"
b := (flag.Value.Type() == "bool") if flag.Value.Type() != "bool" {
if !b {
format += "=" format += "="
} }
format += "\")\n" format += "\")\n"
if _, err := fmt.Fprintf(w, format, flag.Name); err != nil { buf.WriteString(fmt.Sprintf(format, flag.Name))
visitErr = err
return
}
if len(flag.Shorthand) > 0 { if len(flag.Shorthand) > 0 {
if _, err := fmt.Fprintf(w, " must_have_one_flag+=(\"-%s\")\n", flag.Shorthand); err != nil { buf.WriteString(fmt.Sprintf(" must_have_one_flag+=(\"-%s\")\n", flag.Shorthand))
visitErr = err
return
}
} }
} }
} }
}) })
return visitErr
} }
func writeRequiredNouns(cmd *Command, w io.Writer) error { func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) {
if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil { buf.WriteString(" must_have_one_noun=()\n")
return err
}
sort.Sort(sort.StringSlice(cmd.ValidArgs)) sort.Sort(sort.StringSlice(cmd.ValidArgs))
for _, value := range cmd.ValidArgs { for _, value := range cmd.ValidArgs {
if _, err := fmt.Fprintf(w, " must_have_one_noun+=(%q)\n", value); err != nil { buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value))
return err
}
} }
return nil
} }
func writeArgAliases(cmd *Command, w io.Writer) error { func writeArgAliases(buf *bytes.Buffer, cmd *Command) {
if _, err := fmt.Fprintf(w, " noun_aliases=()\n"); err != nil { buf.WriteString(" noun_aliases=()\n")
return err
}
sort.Sort(sort.StringSlice(cmd.ArgAliases)) sort.Sort(sort.StringSlice(cmd.ArgAliases))
for _, value := range cmd.ArgAliases { for _, value := range cmd.ArgAliases {
if _, err := fmt.Fprintf(w, " noun_aliases+=(%q)\n", value); err != nil { buf.WriteString(fmt.Sprintf(" noun_aliases+=(%q)\n", value))
return err
}
} }
return nil
} }
func gen(cmd *Command, w io.Writer) error { func gen(buf *bytes.Buffer, cmd *Command) {
for _, c := range cmd.Commands() { for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() || c == cmd.helpCommand { if !c.IsAvailableCommand() || c == cmd.helpCommand {
continue continue
} }
if err := gen(c, w); err != nil { gen(buf, c)
return err
}
} }
commandName := cmd.CommandPath() commandName := cmd.CommandPath()
commandName = strings.Replace(commandName, " ", "_", -1) commandName = strings.Replace(commandName, " ", "_", -1)
commandName = strings.Replace(commandName, ":", "__", -1) commandName = strings.Replace(commandName, ":", "__", -1)
if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil { buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName))
return err buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName))
} writeCommands(buf, cmd)
if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil { writeFlags(buf, cmd)
return err writeRequiredFlag(buf, cmd)
} writeRequiredNouns(buf, cmd)
if err := writeCommands(cmd, w); err != nil { writeArgAliases(buf, cmd)
return err buf.WriteString("}\n\n")
}
if err := writeFlags(cmd, w); err != nil {
return err
}
if err := writeRequiredFlag(cmd, w); err != nil {
return err
}
if err := writeRequiredNouns(cmd, w); err != nil {
return err
}
if err := writeArgAliases(cmd, w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, "}\n\n"); err != nil {
return err
}
return nil
} }
func (cmd *Command) GenBashCompletion(w io.Writer) error { // GenBashCompletion generates bash completion file and writes to the passed writer.
if err := preamble(w, cmd.Name()); err != nil { func (c *Command) GenBashCompletion(w io.Writer) error {
return err buf := new(bytes.Buffer)
writePreamble(buf, c.Name())
if len(c.BashCompletionFunction) > 0 {
buf.WriteString(c.BashCompletionFunction + "\n")
} }
if len(cmd.BashCompletionFunction) > 0 { gen(buf, c)
if _, err := fmt.Fprintf(w, "%s\n", cmd.BashCompletionFunction); err != nil { writePostscript(buf, c.Name())
return err
} _, err := buf.WriteTo(w)
} return err
if err := gen(cmd, w); err != nil {
return err
}
return postscript(w, cmd.Name())
} }
func nonCompletableFlag(flag *pflag.Flag) bool { func nonCompletableFlag(flag *pflag.Flag) bool {
return flag.Hidden || len(flag.Deprecated) > 0 return flag.Hidden || len(flag.Deprecated) > 0
} }
func (cmd *Command) GenBashCompletionFile(filename string) error { // GenBashCompletionFile generates bash completion file.
func (c *Command) GenBashCompletionFile(filename string) error {
outFile, err := os.Create(filename) outFile, err := os.Create(filename)
if err != nil { if err != nil {
return err return err
} }
defer outFile.Close() defer outFile.Close()
return cmd.GenBashCompletion(outFile) return c.GenBashCompletion(outFile)
} }
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists. // MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists.
func (cmd *Command) MarkFlagRequired(name string) error { func (c *Command) MarkFlagRequired(name string) error {
return MarkFlagRequired(cmd.Flags(), name) return MarkFlagRequired(c.Flags(), name)
} }
// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag, if it exists. // MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag, if it exists.
func (cmd *Command) MarkPersistentFlagRequired(name string) error { func (c *Command) MarkPersistentFlagRequired(name string) error {
return MarkFlagRequired(cmd.PersistentFlags(), name) return MarkFlagRequired(c.PersistentFlags(), name)
} }
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists. // MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists.
@ -612,20 +508,20 @@ func MarkFlagRequired(flags *pflag.FlagSet, name string) error {
// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists. // MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists.
// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. // Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.
func (cmd *Command) MarkFlagFilename(name string, extensions ...string) error { func (c *Command) MarkFlagFilename(name string, extensions ...string) error {
return MarkFlagFilename(cmd.Flags(), name, extensions...) return MarkFlagFilename(c.Flags(), name, extensions...)
} }
// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. // MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists.
// Generated bash autocompletion will call the bash function f for the flag. // Generated bash autocompletion will call the bash function f for the flag.
func (cmd *Command) MarkFlagCustom(name string, f string) error { func (c *Command) MarkFlagCustom(name string, f string) error {
return MarkFlagCustom(cmd.Flags(), name, f) return MarkFlagCustom(c.Flags(), name, f)
} }
// MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists. // MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists.
// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. // Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.
func (cmd *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { func (c *Command) MarkPersistentFlagFilename(name string, extensions ...string) error {
return MarkFlagFilename(cmd.PersistentFlags(), name, extensions...) return MarkFlagFilename(c.PersistentFlags(), name, extensions...)
} }
// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists. // MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists.

View File

@ -27,17 +27,19 @@ import (
) )
var templateFuncs = template.FuncMap{ var templateFuncs = template.FuncMap{
"trim": strings.TrimSpace, "trim": strings.TrimSpace,
"trimRightSpace": trimRightSpace, "trimRightSpace": trimRightSpace,
"appendIfNotPresent": appendIfNotPresent, "trimTrailingWhitespaces": trimRightSpace,
"rpad": rpad, "appendIfNotPresent": appendIfNotPresent,
"gt": Gt, "rpad": rpad,
"eq": Eq, "gt": Gt,
"eq": Eq,
} }
var initializers []func() var initializers []func()
// Automatic prefix matching can be a dangerous thing to automatically enable in CLI tools. // EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing
// to automatically enable in CLI tools.
// Set this to true to enable it. // Set this to true to enable it.
var EnablePrefixMatching = false var EnablePrefixMatching = false
@ -45,13 +47,22 @@ var EnablePrefixMatching = false
// To disable sorting, set it to false. // To disable sorting, set it to false.
var EnableCommandSorting = true var EnableCommandSorting = true
// MousetrapHelpText enables an information splash screen on Windows
// if the CLI is started from explorer.exe.
// To disable the mousetrap, just set this variable to blank string ("").
// Works only on Microsoft Windows.
var MousetrapHelpText string = `This is a command line tool.
You need to open cmd.exe and run it from there.
`
// AddTemplateFunc adds a template function that's available to Usage and Help // AddTemplateFunc adds a template function that's available to Usage and Help
// template generation. // template generation.
func AddTemplateFunc(name string, tmplFunc interface{}) { func AddTemplateFunc(name string, tmplFunc interface{}) {
templateFuncs[name] = tmplFunc templateFuncs[name] = tmplFunc
} }
// AddTemplateFuncs adds multiple template functions availalble to Usage and // AddTemplateFuncs adds multiple template functions that are available to Usage and
// Help template generation. // Help template generation.
func AddTemplateFuncs(tmplFuncs template.FuncMap) { func AddTemplateFuncs(tmplFuncs template.FuncMap) {
for k, v := range tmplFuncs { for k, v := range tmplFuncs {
@ -64,6 +75,8 @@ func OnInitialize(y ...func()) {
initializers = append(initializers, y...) initializers = append(initializers, y...)
} }
// FIXME Gt is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra.
// Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans, // Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans,
// Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as // Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as
// ints and then compared. // ints and then compared.
@ -94,6 +107,8 @@ func Gt(a interface{}, b interface{}) bool {
return left > right return left > right
} }
// FIXME Eq is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra.
// Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic. // Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic.
func Eq(a interface{}, b interface{}) bool { func Eq(a interface{}, b interface{}) bool {
av := reflect.ValueOf(a) av := reflect.ValueOf(a)
@ -114,6 +129,8 @@ func trimRightSpace(s string) string {
return strings.TrimRightFunc(s, unicode.IsSpace) return strings.TrimRightFunc(s, unicode.IsSpace)
} }
// FIXME appendIfNotPresent is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra.
// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s. // appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s.
func appendIfNotPresent(s, stringToAppend string) string { func appendIfNotPresent(s, stringToAppend string) string {
if strings.Contains(s, stringToAppend) { if strings.Contains(s, stringToAppend) {
@ -171,3 +188,12 @@ func ld(s, t string, ignoreCase bool) int {
} }
return d[len(s)][len(t)] return d[len(s)][len(t)]
} }
func stringInSlice(a string, list []string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}

File diff suppressed because it is too large Load Diff

View File

@ -11,14 +11,8 @@ import (
var preExecHookFn = preExecHook var preExecHookFn = preExecHook
// enables an information splash screen on Windows if the CLI is started from explorer.exe.
var MousetrapHelpText string = `This is a command line tool
You need to open cmd.exe and run it from there.
`
func preExecHook(c *Command) { func preExecHook(c *Command) {
if mousetrap.StartedByExplorer() { if MousetrapHelpText != "" && mousetrap.StartedByExplorer() {
c.Print(MousetrapHelpText) c.Print(MousetrapHelpText)
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
os.Exit(1) os.Exit(1)

126
vendor/github.com/spf13/cobra/zsh_completions.go generated vendored Normal file
View File

@ -0,0 +1,126 @@
package cobra
import (
"bytes"
"fmt"
"io"
"os"
"strings"
)
// GenZshCompletionFile generates zsh completion file.
func (c *Command) GenZshCompletionFile(filename string) error {
outFile, err := os.Create(filename)
if err != nil {
return err
}
defer outFile.Close()
return c.GenZshCompletion(outFile)
}
// GenZshCompletion generates a zsh completion file and writes to the passed writer.
func (c *Command) GenZshCompletion(w io.Writer) error {
buf := new(bytes.Buffer)
writeHeader(buf, c)
maxDepth := maxDepth(c)
writeLevelMapping(buf, maxDepth)
writeLevelCases(buf, maxDepth, c)
_, err := buf.WriteTo(w)
return err
}
func writeHeader(w io.Writer, cmd *Command) {
fmt.Fprintf(w, "#compdef %s\n\n", cmd.Name())
}
func maxDepth(c *Command) int {
if len(c.Commands()) == 0 {
return 0
}
maxDepthSub := 0
for _, s := range c.Commands() {
subDepth := maxDepth(s)
if subDepth > maxDepthSub {
maxDepthSub = subDepth
}
}
return 1 + maxDepthSub
}
func writeLevelMapping(w io.Writer, numLevels int) {
fmt.Fprintln(w, `_arguments \`)
for i := 1; i <= numLevels; i++ {
fmt.Fprintf(w, ` '%d: :->level%d' \`, i, i)
fmt.Fprintln(w)
}
fmt.Fprintf(w, ` '%d: :%s'`, numLevels+1, "_files")
fmt.Fprintln(w)
}
func writeLevelCases(w io.Writer, maxDepth int, root *Command) {
fmt.Fprintln(w, "case $state in")
defer fmt.Fprintln(w, "esac")
for i := 1; i <= maxDepth; i++ {
fmt.Fprintf(w, " level%d)\n", i)
writeLevel(w, root, i)
fmt.Fprintln(w, " ;;")
}
fmt.Fprintln(w, " *)")
fmt.Fprintln(w, " _arguments '*: :_files'")
fmt.Fprintln(w, " ;;")
}
func writeLevel(w io.Writer, root *Command, i int) {
fmt.Fprintf(w, " case $words[%d] in\n", i)
defer fmt.Fprintln(w, " esac")
commands := filterByLevel(root, i)
byParent := groupByParent(commands)
for p, c := range byParent {
names := names(c)
fmt.Fprintf(w, " %s)\n", p)
fmt.Fprintf(w, " _arguments '%d: :(%s)'\n", i, strings.Join(names, " "))
fmt.Fprintln(w, " ;;")
}
fmt.Fprintln(w, " *)")
fmt.Fprintln(w, " _arguments '*: :_files'")
fmt.Fprintln(w, " ;;")
}
func filterByLevel(c *Command, l int) []*Command {
cs := make([]*Command, 0)
if l == 0 {
cs = append(cs, c)
return cs
}
for _, s := range c.Commands() {
cs = append(cs, filterByLevel(s, l-1)...)
}
return cs
}
func groupByParent(commands []*Command) map[string][]*Command {
m := make(map[string][]*Command)
for _, c := range commands {
parent := c.Parent()
if parent == nil {
continue
}
m[parent.Name()] = append(m[parent.Name()], c)
}
return m
}
func names(commands []*Command) []string {
ns := make([]string, len(commands))
for i, c := range commands {
ns[i] = c.Name()
}
return ns
}

View File

@ -0,0 +1,113 @@
// Copyright © 2016 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package jwalterweatherman
import (
"io"
"io/ioutil"
"log"
"os"
)
var (
TRACE *log.Logger
DEBUG *log.Logger
INFO *log.Logger
WARN *log.Logger
ERROR *log.Logger
CRITICAL *log.Logger
FATAL *log.Logger
LOG *log.Logger
FEEDBACK *Feedback
defaultNotepad *Notepad
)
func reloadDefaultNotepad() {
TRACE = defaultNotepad.TRACE
DEBUG = defaultNotepad.DEBUG
INFO = defaultNotepad.INFO
WARN = defaultNotepad.WARN
ERROR = defaultNotepad.ERROR
CRITICAL = defaultNotepad.CRITICAL
FATAL = defaultNotepad.FATAL
LOG = defaultNotepad.LOG
FEEDBACK = defaultNotepad.FEEDBACK
}
func init() {
defaultNotepad = NewNotepad(LevelError, LevelWarn, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime)
reloadDefaultNotepad()
}
// SetLogThreshold set the log threshold for the default notepad. Trace by default.
func SetLogThreshold(threshold Threshold) {
defaultNotepad.SetLogThreshold(threshold)
reloadDefaultNotepad()
}
// SetLogOutput set the log output for the default notepad. Discarded by default.
func SetLogOutput(handle io.Writer) {
defaultNotepad.SetLogOutput(handle)
reloadDefaultNotepad()
}
// SetStdoutThreshold set the standard output threshold for the default notepad.
// Info by default.
func SetStdoutThreshold(threshold Threshold) {
defaultNotepad.SetStdoutThreshold(threshold)
reloadDefaultNotepad()
}
// SetPrefix set the prefix for the default logger. Empty by default.
func SetPrefix(prefix string) {
defaultNotepad.SetPrefix(prefix)
reloadDefaultNotepad()
}
// SetFlags set the flags for the default logger. "log.Ldate | log.Ltime" by default.
func SetFlags(flags int) {
defaultNotepad.SetFlags(flags)
reloadDefaultNotepad()
}
// Level returns the current global log threshold.
func LogThreshold() Threshold {
return defaultNotepad.logThreshold
}
// Level returns the current global output threshold.
func StdoutThreshold() Threshold {
return defaultNotepad.stdoutThreshold
}
// GetStdoutThreshold returns the defined Treshold for the log logger.
func GetLogThreshold() Threshold {
return defaultNotepad.GetLogThreshold()
}
// GetStdoutThreshold returns the Treshold for the stdout logger.
func GetStdoutThreshold() Threshold {
return defaultNotepad.GetStdoutThreshold()
}
// LogCountForLevel returns the number of log invocations for a given threshold.
func LogCountForLevel(l Threshold) uint64 {
return defaultNotepad.LogCountForLevel(l)
}
// LogCountForLevelsGreaterThanorEqualTo returns the number of log invocations
// greater than or equal to a given threshold.
func LogCountForLevelsGreaterThanorEqualTo(threshold Threshold) uint64 {
return defaultNotepad.LogCountForLevelsGreaterThanorEqualTo(threshold)
}
// ResetLogCounters resets the invocation counters for all levels.
func ResetLogCounters() {
defaultNotepad.ResetLogCounters()
}

View File

@ -0,0 +1,55 @@
// Copyright © 2016 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package jwalterweatherman
import (
"sync/atomic"
)
type logCounter struct {
counter uint64
}
func (c *logCounter) incr() {
atomic.AddUint64(&c.counter, 1)
}
func (c *logCounter) resetCounter() {
atomic.StoreUint64(&c.counter, 0)
}
func (c *logCounter) getCount() uint64 {
return atomic.LoadUint64(&c.counter)
}
func (c *logCounter) Write(p []byte) (n int, err error) {
c.incr()
return len(p), nil
}
// LogCountForLevel returns the number of log invocations for a given threshold.
func (n *Notepad) LogCountForLevel(l Threshold) uint64 {
return n.logCounters[l].getCount()
}
// LogCountForLevelsGreaterThanorEqualTo returns the number of log invocations
// greater than or equal to a given threshold.
func (n *Notepad) LogCountForLevelsGreaterThanorEqualTo(threshold Threshold) uint64 {
var cnt uint64
for i := int(threshold); i < len(n.logCounters); i++ {
cnt += n.LogCountForLevel(Threshold(i))
}
return cnt
}
// ResetLogCounters resets the invocation counters for all levels.
func (n *Notepad) ResetLogCounters() {
for _, np := range n.logCounters {
np.resetCounter()
}
}

194
vendor/github.com/spf13/jwalterweatherman/notepad.go generated vendored Normal file
View File

@ -0,0 +1,194 @@
// Copyright © 2016 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package jwalterweatherman
import (
"fmt"
"io"
"log"
)
type Threshold int
func (t Threshold) String() string {
return prefixes[t]
}
const (
LevelTrace Threshold = iota
LevelDebug
LevelInfo
LevelWarn
LevelError
LevelCritical
LevelFatal
)
var prefixes map[Threshold]string = map[Threshold]string{
LevelTrace: "TRACE",
LevelDebug: "DEBUG",
LevelInfo: "INFO",
LevelWarn: "WARN",
LevelError: "ERROR",
LevelCritical: "CRITICAL",
LevelFatal: "FATAL",
}
// Notepad is where you leave a note!
type Notepad struct {
TRACE *log.Logger
DEBUG *log.Logger
INFO *log.Logger
WARN *log.Logger
ERROR *log.Logger
CRITICAL *log.Logger
FATAL *log.Logger
LOG *log.Logger
FEEDBACK *Feedback
loggers [7]**log.Logger
logHandle io.Writer
outHandle io.Writer
logThreshold Threshold
stdoutThreshold Threshold
prefix string
flags int
// One per Threshold
logCounters [7]*logCounter
}
// NewNotepad create a new notepad.
func NewNotepad(outThreshold Threshold, logThreshold Threshold, outHandle, logHandle io.Writer, prefix string, flags int) *Notepad {
n := &Notepad{}
n.loggers = [7]**log.Logger{&n.TRACE, &n.DEBUG, &n.INFO, &n.WARN, &n.ERROR, &n.CRITICAL, &n.FATAL}
n.outHandle = outHandle
n.logHandle = logHandle
n.stdoutThreshold = outThreshold
n.logThreshold = logThreshold
if len(prefix) != 0 {
n.prefix = "[" + prefix + "] "
} else {
n.prefix = ""
}
n.flags = flags
n.LOG = log.New(n.logHandle,
"LOG: ",
n.flags)
n.FEEDBACK = &Feedback{out: log.New(outHandle, "", 0), log: n.LOG}
n.init()
return n
}
// init creates the loggers for each level depending on the notepad thresholds.
func (n *Notepad) init() {
logAndOut := io.MultiWriter(n.outHandle, n.logHandle)
for t, logger := range n.loggers {
threshold := Threshold(t)
counter := &logCounter{}
n.logCounters[t] = counter
prefix := n.prefix + threshold.String() + " "
switch {
case threshold >= n.logThreshold && threshold >= n.stdoutThreshold:
*logger = log.New(io.MultiWriter(counter, logAndOut), prefix, n.flags)
case threshold >= n.logThreshold:
*logger = log.New(io.MultiWriter(counter, n.logHandle), prefix, n.flags)
case threshold >= n.stdoutThreshold:
*logger = log.New(io.MultiWriter(counter, n.outHandle), prefix, n.flags)
default:
// counter doesn't care about prefix and flags, so don't use them
// for performance.
*logger = log.New(counter, "", 0)
}
}
}
// SetLogThreshold changes the threshold above which messages are written to the
// log file.
func (n *Notepad) SetLogThreshold(threshold Threshold) {
n.logThreshold = threshold
n.init()
}
// SetLogOutput changes the file where log messages are written.
func (n *Notepad) SetLogOutput(handle io.Writer) {
n.logHandle = handle
n.init()
}
// GetStdoutThreshold returns the defined Treshold for the log logger.
func (n *Notepad) GetLogThreshold() Threshold {
return n.logThreshold
}
// SetStdoutThreshold changes the threshold above which messages are written to the
// standard output.
func (n *Notepad) SetStdoutThreshold(threshold Threshold) {
n.stdoutThreshold = threshold
n.init()
}
// GetStdoutThreshold returns the Treshold for the stdout logger.
func (n *Notepad) GetStdoutThreshold() Threshold {
return n.stdoutThreshold
}
// SetPrefix changes the prefix used by the notepad. Prefixes are displayed between
// brackets at the beginning of the line. An empty prefix won't be displayed at all.
func (n *Notepad) SetPrefix(prefix string) {
if len(prefix) != 0 {
n.prefix = "[" + prefix + "] "
} else {
n.prefix = ""
}
n.init()
}
// SetFlags choose which flags the logger will display (after prefix and message
// level). See the package log for more informations on this.
func (n *Notepad) SetFlags(flags int) {
n.flags = flags
n.init()
}
// Feedback writes plainly to the outHandle while
// logging with the standard extra information (date, file, etc).
type Feedback struct {
out *log.Logger
log *log.Logger
}
func (fb *Feedback) Println(v ...interface{}) {
fb.output(fmt.Sprintln(v...))
}
func (fb *Feedback) Printf(format string, v ...interface{}) {
fb.output(fmt.Sprintf(format, v...))
}
func (fb *Feedback) Print(v ...interface{}) {
fb.output(fmt.Sprint(v...))
}
func (fb *Feedback) output(s string) {
if fb.out != nil {
fb.out.Output(2, s)
}
if fb.log != nil {
fb.log.Output(2, s)
}
}

View File

@ -1,256 +0,0 @@
// Copyright © 2016 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package jwalterweatherman
import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
"sync/atomic"
)
// Level describes the chosen log level between
// debug and critical.
type Level int
type NotePad struct {
Handle io.Writer
Level Level
Prefix string
Logger **log.Logger
counter uint64
}
func (n *NotePad) incr() {
atomic.AddUint64(&n.counter, 1)
}
func (n *NotePad) resetCounter() {
atomic.StoreUint64(&n.counter, 0)
}
func (n *NotePad) getCount() uint64 {
return atomic.LoadUint64(&n.counter)
}
type countingWriter struct {
incrFunc func()
}
func (cw *countingWriter) Write(p []byte) (n int, err error) {
cw.incrFunc()
return 0, nil
}
// Feedback is special. It writes plainly to the output while
// logging with the standard extra information (date, file, etc)
// Only Println and Printf are currently provided for this
type Feedback struct{}
const (
LevelTrace Level = iota
LevelDebug
LevelInfo
LevelWarn
LevelError
LevelCritical
LevelFatal
DefaultLogThreshold = LevelWarn
DefaultStdoutThreshold = LevelError
)
var (
TRACE *log.Logger
DEBUG *log.Logger
INFO *log.Logger
WARN *log.Logger
ERROR *log.Logger
CRITICAL *log.Logger
FATAL *log.Logger
LOG *log.Logger
FEEDBACK Feedback
LogHandle io.Writer = ioutil.Discard
OutHandle io.Writer = os.Stdout
BothHandle io.Writer = io.MultiWriter(LogHandle, OutHandle)
NotePads []*NotePad = []*NotePad{trace, debug, info, warn, err, critical, fatal}
trace *NotePad = &NotePad{Level: LevelTrace, Handle: os.Stdout, Logger: &TRACE, Prefix: "TRACE: "}
debug *NotePad = &NotePad{Level: LevelDebug, Handle: os.Stdout, Logger: &DEBUG, Prefix: "DEBUG: "}
info *NotePad = &NotePad{Level: LevelInfo, Handle: os.Stdout, Logger: &INFO, Prefix: "INFO: "}
warn *NotePad = &NotePad{Level: LevelWarn, Handle: os.Stdout, Logger: &WARN, Prefix: "WARN: "}
err *NotePad = &NotePad{Level: LevelError, Handle: os.Stdout, Logger: &ERROR, Prefix: "ERROR: "}
critical *NotePad = &NotePad{Level: LevelCritical, Handle: os.Stdout, Logger: &CRITICAL, Prefix: "CRITICAL: "}
fatal *NotePad = &NotePad{Level: LevelFatal, Handle: os.Stdout, Logger: &FATAL, Prefix: "FATAL: "}
logThreshold Level = DefaultLogThreshold
outputThreshold Level = DefaultStdoutThreshold
)
const (
DATE = log.Ldate
TIME = log.Ltime
SFILE = log.Lshortfile
LFILE = log.Llongfile
MSEC = log.Lmicroseconds
)
var logFlags = DATE | TIME | SFILE
func init() {
SetStdoutThreshold(DefaultStdoutThreshold)
}
// initialize will setup the jWalterWeatherman standard approach of providing the user
// some feedback and logging a potentially different amount based on independent log and output thresholds.
// By default the output has a lower threshold than logged
// Don't use if you have manually set the Handles of the different levels as it will overwrite them.
func initialize() {
BothHandle = io.MultiWriter(LogHandle, OutHandle)
for _, n := range NotePads {
if n.Level < outputThreshold && n.Level < logThreshold {
n.Handle = ioutil.Discard
} else if n.Level >= outputThreshold && n.Level >= logThreshold {
n.Handle = BothHandle
} else if n.Level >= outputThreshold && n.Level < logThreshold {
n.Handle = OutHandle
} else {
n.Handle = LogHandle
}
}
for _, n := range NotePads {
n.Handle = io.MultiWriter(n.Handle, &countingWriter{n.incr})
*n.Logger = log.New(n.Handle, n.Prefix, logFlags)
}
LOG = log.New(LogHandle,
"LOG: ",
logFlags)
}
// Set the log Flags (Available flag: DATE, TIME, SFILE, LFILE and MSEC)
func SetLogFlag(flags int) {
logFlags = flags
initialize()
}
// Level returns the current global log threshold.
func LogThreshold() Level {
return logThreshold
}
// Level returns the current global output threshold.
func StdoutThreshold() Level {
return outputThreshold
}
// Ensures that the level provided is within the bounds of available levels
func levelCheck(level Level) Level {
switch {
case level <= LevelTrace:
return LevelTrace
case level >= LevelFatal:
return LevelFatal
default:
return level
}
}
// Establishes a threshold where anything matching or above will be logged
func SetLogThreshold(level Level) {
logThreshold = levelCheck(level)
initialize()
}
// Establishes a threshold where anything matching or above will be output
func SetStdoutThreshold(level Level) {
outputThreshold = levelCheck(level)
initialize()
}
// Conveniently Sets the Log Handle to a io.writer created for the file behind the given filepath
// Will only append to this file
func SetLogFile(path string) {
file, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
CRITICAL.Println("Failed to open log file:", path, err)
os.Exit(-1)
}
INFO.Println("Logging to", file.Name())
LogHandle = file
initialize()
}
// Conveniently Creates a temporary file and sets the Log Handle to a io.writer created for it
func UseTempLogFile(prefix string) {
file, err := ioutil.TempFile(os.TempDir(), prefix)
if err != nil {
CRITICAL.Println(err)
}
INFO.Println("Logging to", file.Name())
LogHandle = file
initialize()
}
// LogCountForLevel returns the number of log invocations for a given level.
func LogCountForLevel(l Level) uint64 {
for _, np := range NotePads {
if np.Level == l {
return np.getCount()
}
}
return 0
}
// LogCountForLevelsGreaterThanorEqualTo returns the number of log invocations
// greater than or equal to a given level threshold.
func LogCountForLevelsGreaterThanorEqualTo(threshold Level) uint64 {
var cnt uint64
for _, np := range NotePads {
if np.Level >= threshold {
cnt += np.getCount()
}
}
return cnt
}
// ResetLogCounters resets the invocation counters for all levels.
func ResetLogCounters() {
for _, np := range NotePads {
np.resetCounter()
}
}
// Disables logging for the entire JWW system
func DiscardLogging() {
LogHandle = ioutil.Discard
initialize()
}
// Feedback is special. It writes plainly to the output while
// logging with the standard extra information (date, file, etc)
// Only Println and Printf are currently provided for this
func (fb *Feedback) Println(v ...interface{}) {
s := fmt.Sprintln(v...)
fmt.Print(s)
LOG.Output(2, s)
}
// Feedback is special. It writes plainly to the output while
// logging with the standard extra information (date, file, etc)
// Only Println and Printf are currently provided for this
func (fb *Feedback) Printf(format string, v ...interface{}) {
s := fmt.Sprintf(format, v...)
fmt.Print(s)
LOG.Output(2, s)
}

147
vendor/github.com/spf13/pflag/bool_slice.go generated vendored Normal file
View File

@ -0,0 +1,147 @@
package pflag
import (
"io"
"strconv"
"strings"
)
// -- boolSlice Value
type boolSliceValue struct {
value *[]bool
changed bool
}
func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue {
bsv := new(boolSliceValue)
bsv.value = p
*bsv.value = val
return bsv
}
// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag.
// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended.
func (s *boolSliceValue) Set(val string) error {
// remove all quote characters
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
// read flag arguments with CSV parser
boolStrSlice, err := readAsCSV(rmQuote.Replace(val))
if err != nil && err != io.EOF {
return err
}
// parse boolean values into slice
out := make([]bool, 0, len(boolStrSlice))
for _, boolStr := range boolStrSlice {
b, err := strconv.ParseBool(strings.TrimSpace(boolStr))
if err != nil {
return err
}
out = append(out, b)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
// Type returns a string that uniquely represents this flag's type.
func (s *boolSliceValue) Type() string {
return "boolSlice"
}
// String defines a "native" format for this boolean slice flag value.
func (s *boolSliceValue) String() string {
boolStrSlice := make([]string, len(*s.value))
for i, b := range *s.value {
boolStrSlice[i] = strconv.FormatBool(b)
}
out, _ := writeAsCSV(boolStrSlice)
return "[" + out + "]"
}
func boolSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []bool{}, nil
}
ss := strings.Split(val, ",")
out := make([]bool, len(ss))
for i, t := range ss {
var err error
out[i], err = strconv.ParseBool(t)
if err != nil {
return nil, err
}
}
return out, nil
}
// GetBoolSlice returns the []bool value of a flag with the given name.
func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) {
val, err := f.getFlagType(name, "boolSlice", boolSliceConv)
if err != nil {
return []bool{}, err
}
return val.([]bool), nil
}
// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string.
// The argument p points to a []bool variable in which to store the value of the flag.
func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
f.VarP(newBoolSliceValue(value, p), name, "", usage)
}
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
f.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
}
// BoolSliceVar defines a []bool flag with specified name, default value, and usage string.
// The argument p points to a []bool variable in which to store the value of the flag.
func BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage)
}
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
}
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
// The return value is the address of a []bool variable that stores the value of the flag.
func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool {
p := []bool{}
f.BoolSliceVarP(&p, name, "", value, usage)
return &p
}
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
p := []bool{}
f.BoolSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
// The return value is the address of a []bool variable that stores the value of the flag.
func BoolSlice(name string, value []bool, usage string) *[]bool {
return CommandLine.BoolSliceP(name, "", value, usage)
}
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
return CommandLine.BoolSliceP(name, shorthand, value, usage)
}

View File

@ -11,13 +11,13 @@ func newCountValue(val int, p *int) *countValue {
} }
func (i *countValue) Set(s string) error { func (i *countValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64) // "+1" means that no specific value was passed, so increment
// -1 means that no specific value was passed, so increment if s == "+1" {
if v == -1 {
*i = countValue(*i + 1) *i = countValue(*i + 1)
} else { return nil
*i = countValue(v)
} }
v, err := strconv.ParseInt(s, 0, 0)
*i = countValue(v)
return err return err
} }
@ -54,7 +54,7 @@ func (f *FlagSet) CountVar(p *int, name string, usage string) {
// CountVarP is like CountVar only take a shorthand for the flag name. // CountVarP is like CountVar only take a shorthand for the flag name.
func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) { func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) {
flag := f.VarPF(newCountValue(0, p), name, shorthand, usage) flag := f.VarPF(newCountValue(0, p), name, shorthand, usage)
flag.NoOptDefVal = "-1" flag.NoOptDefVal = "+1"
} }
// CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set // CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set
@ -83,7 +83,9 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int {
return p return p
} }
// Count like Count only the flag is placed on the CommandLine isntead of a given flag set // Count defines a count flag with specified name, default value, and usage string.
// The return value is the address of an int variable that stores the value of the flag.
// A count flag will add 1 to its value evey time it is found on the command line
func Count(name string, usage string) *int { func Count(name string, usage string) *int {
return CommandLine.CountP(name, "", usage) return CommandLine.CountP(name, "", usage)
} }

406
vendor/github.com/spf13/pflag/flag.go generated vendored
View File

@ -16,9 +16,9 @@ pflag is a drop-in replacement of Go's native flag package. If you import
pflag under the name "flag" then all code should continue to function pflag under the name "flag" then all code should continue to function
with no changes. with no changes.
import flag "github.com/ogier/pflag" import flag "github.com/spf13/pflag"
There is one exception to this: if you directly instantiate the Flag struct There is one exception to this: if you directly instantiate the Flag struct
there is one more field "Shorthand" that you will need to set. there is one more field "Shorthand" that you will need to set.
Most code never instantiates this struct directly, and instead uses Most code never instantiates this struct directly, and instead uses
functions such as String(), BoolVar(), and Var(), and is therefore functions such as String(), BoolVar(), and Var(), and is therefore
@ -134,14 +134,21 @@ type FlagSet struct {
// a custom error handler. // a custom error handler.
Usage func() Usage func()
// SortFlags is used to indicate, if user wants to have sorted flags in
// help/usage messages.
SortFlags bool
name string name string
parsed bool parsed bool
actual map[NormalizedName]*Flag actual map[NormalizedName]*Flag
orderedActual []*Flag
sortedActual []*Flag
formal map[NormalizedName]*Flag formal map[NormalizedName]*Flag
orderedFormal []*Flag
sortedFormal []*Flag
shorthands map[byte]*Flag shorthands map[byte]*Flag
args []string // arguments after flags args []string // arguments after flags
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
exitOnError bool // does the program exit if there's an error?
errorHandling ErrorHandling errorHandling ErrorHandling
output io.Writer // nil means stderr; use out() accessor output io.Writer // nil means stderr; use out() accessor
interspersed bool // allow interspersed option/non-option args interspersed bool // allow interspersed option/non-option args
@ -156,7 +163,7 @@ type Flag struct {
Value Value // value as set Value Value // value as set
DefValue string // default value (as text); for usage message DefValue string // default value (as text); for usage message
Changed bool // If the user set the value (or if left to default) Changed bool // If the user set the value (or if left to default)
NoOptDefVal string //default value (as text); if the flag is on the command line without any options NoOptDefVal string // default value (as text); if the flag is on the command line without any options
Deprecated string // If this flag is deprecated, this string is the new or now thing to use Deprecated string // If this flag is deprecated, this string is the new or now thing to use
Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text
ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use
@ -194,11 +201,19 @@ func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
// "--getUrl" which may also be translated to "geturl" and everything will work. // "--getUrl" which may also be translated to "geturl" and everything will work.
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) { func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
f.normalizeNameFunc = n f.normalizeNameFunc = n
for k, v := range f.formal { f.sortedFormal = f.sortedFormal[:0]
delete(f.formal, k) for fname, flag := range f.formal {
nname := f.normalizeFlagName(string(k)) nname := f.normalizeFlagName(flag.Name)
f.formal[nname] = v if fname == nname {
v.Name = string(nname) continue
}
flag.Name = string(nname)
delete(f.formal, fname)
f.formal[nname] = flag
if _, set := f.actual[fname]; set {
delete(f.actual, fname)
f.actual[nname] = flag
}
} }
} }
@ -229,10 +244,25 @@ func (f *FlagSet) SetOutput(output io.Writer) {
f.output = output f.output = output
} }
// VisitAll visits the flags in lexicographical order, calling fn for each. // VisitAll visits the flags in lexicographical order or
// in primordial order if f.SortFlags is false, calling fn for each.
// It visits all flags, even those not set. // It visits all flags, even those not set.
func (f *FlagSet) VisitAll(fn func(*Flag)) { func (f *FlagSet) VisitAll(fn func(*Flag)) {
for _, flag := range sortFlags(f.formal) { if len(f.formal) == 0 {
return
}
var flags []*Flag
if f.SortFlags {
if len(f.formal) != len(f.sortedFormal) {
f.sortedFormal = sortFlags(f.formal)
}
flags = f.sortedFormal
} else {
flags = f.orderedFormal
}
for _, flag := range flags {
fn(flag) fn(flag)
} }
} }
@ -253,22 +283,39 @@ func (f *FlagSet) HasAvailableFlags() bool {
return false return false
} }
// VisitAll visits the command-line flags in lexicographical order, calling // VisitAll visits the command-line flags in lexicographical order or
// fn for each. It visits all flags, even those not set. // in primordial order if f.SortFlags is false, calling fn for each.
// It visits all flags, even those not set.
func VisitAll(fn func(*Flag)) { func VisitAll(fn func(*Flag)) {
CommandLine.VisitAll(fn) CommandLine.VisitAll(fn)
} }
// Visit visits the flags in lexicographical order, calling fn for each. // Visit visits the flags in lexicographical order or
// in primordial order if f.SortFlags is false, calling fn for each.
// It visits only those flags that have been set. // It visits only those flags that have been set.
func (f *FlagSet) Visit(fn func(*Flag)) { func (f *FlagSet) Visit(fn func(*Flag)) {
for _, flag := range sortFlags(f.actual) { if len(f.actual) == 0 {
return
}
var flags []*Flag
if f.SortFlags {
if len(f.actual) != len(f.sortedActual) {
f.sortedActual = sortFlags(f.actual)
}
flags = f.sortedActual
} else {
flags = f.orderedActual
}
for _, flag := range flags {
fn(flag) fn(flag)
} }
} }
// Visit visits the command-line flags in lexicographical order, calling fn // Visit visits the command-line flags in lexicographical order or
// for each. It visits only those flags that have been set. // in primordial order if f.SortFlags is false, calling fn for each.
// It visits only those flags that have been set.
func Visit(fn func(*Flag)) { func Visit(fn func(*Flag)) {
CommandLine.Visit(fn) CommandLine.Visit(fn)
} }
@ -278,6 +325,22 @@ func (f *FlagSet) Lookup(name string) *Flag {
return f.lookup(f.normalizeFlagName(name)) return f.lookup(f.normalizeFlagName(name))
} }
// ShorthandLookup returns the Flag structure of the short handed flag,
// returning nil if none exists.
// It panics, if len(name) > 1.
func (f *FlagSet) ShorthandLookup(name string) *Flag {
if name == "" {
return nil
}
if len(name) > 1 {
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
fmt.Fprintf(f.out(), msg)
panic(msg)
}
c := name[0]
return f.shorthands[c]
}
// lookup returns the Flag structure of the named flag, returning nil if none exists. // lookup returns the Flag structure of the named flag, returning nil if none exists.
func (f *FlagSet) lookup(name NormalizedName) *Flag { func (f *FlagSet) lookup(name NormalizedName) *Flag {
return f.formal[name] return f.formal[name]
@ -319,7 +382,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
if flag == nil { if flag == nil {
return fmt.Errorf("flag %q does not exist", name) return fmt.Errorf("flag %q does not exist", name)
} }
if len(usageMessage) == 0 { if usageMessage == "" {
return fmt.Errorf("deprecated message for flag %q must be set", name) return fmt.Errorf("deprecated message for flag %q must be set", name)
} }
flag.Deprecated = usageMessage flag.Deprecated = usageMessage
@ -334,7 +397,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro
if flag == nil { if flag == nil {
return fmt.Errorf("flag %q does not exist", name) return fmt.Errorf("flag %q does not exist", name)
} }
if len(usageMessage) == 0 { if usageMessage == "" {
return fmt.Errorf("deprecated message for flag %q must be set", name) return fmt.Errorf("deprecated message for flag %q must be set", name)
} }
flag.ShorthandDeprecated = usageMessage flag.ShorthandDeprecated = usageMessage
@ -358,6 +421,12 @@ func Lookup(name string) *Flag {
return CommandLine.Lookup(name) return CommandLine.Lookup(name)
} }
// ShorthandLookup returns the Flag structure of the short handed flag,
// returning nil if none exists.
func ShorthandLookup(name string) *Flag {
return CommandLine.ShorthandLookup(name)
}
// Set sets the value of the named flag. // Set sets the value of the named flag.
func (f *FlagSet) Set(name, value string) error { func (f *FlagSet) Set(name, value string) error {
normalName := f.normalizeFlagName(name) normalName := f.normalizeFlagName(name)
@ -365,17 +434,30 @@ func (f *FlagSet) Set(name, value string) error {
if !ok { if !ok {
return fmt.Errorf("no such flag -%v", name) return fmt.Errorf("no such flag -%v", name)
} }
err := flag.Value.Set(value) err := flag.Value.Set(value)
if err != nil { if err != nil {
return err var flagName string
if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
} else {
flagName = fmt.Sprintf("--%s", flag.Name)
}
return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
} }
if f.actual == nil {
f.actual = make(map[NormalizedName]*Flag) if !flag.Changed {
if f.actual == nil {
f.actual = make(map[NormalizedName]*Flag)
}
f.actual[normalName] = flag
f.orderedActual = append(f.orderedActual, flag)
flag.Changed = true
} }
f.actual[normalName] = flag
flag.Changed = true if flag.Deprecated != "" {
if len(flag.Deprecated) > 0 { fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
} }
return nil return nil
} }
@ -482,36 +564,111 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
name = "int" name = "int"
case "uint64": case "uint64":
name = "uint" name = "uint"
case "stringSlice":
name = "strings"
case "intSlice":
name = "ints"
case "uintSlice":
name = "uints"
case "boolSlice":
name = "bools"
} }
return return
} }
// FlagUsages Returns a string containing the usage information for all flags in // Splits the string `s` on whitespace into an initial substring up to
// the FlagSet // `i` runes in length and the remainder. Will go `slop` over `i` if
func (f *FlagSet) FlagUsages() string { // that encompasses the entire string (which allows the caller to
x := new(bytes.Buffer) // avoid short orphan words on the final line).
func wrapN(i, slop int, s string) (string, string) {
if i+slop > len(s) {
return s, ""
}
w := strings.LastIndexAny(s[:i], " \t")
if w <= 0 {
return s, ""
}
return s[:w], s[w+1:]
}
// Wraps the string `s` to a maximum width `w` with leading indent
// `i`. The first line is not indented (this is assumed to be done by
// caller). Pass `w` == 0 to do no wrapping
func wrap(i, w int, s string) string {
if w == 0 {
return s
}
// space between indent i and end of line width w into which
// we should wrap the text.
wrap := w - i
var r, l string
// Not enough space for sensible wrapping. Wrap as a block on
// the next line instead.
if wrap < 24 {
i = 16
wrap = w - i
r += "\n" + strings.Repeat(" ", i)
}
// If still not enough space then don't even try to wrap.
if wrap < 24 {
return s
}
// Try to avoid short orphan words on the final line, by
// allowing wrapN to go a bit over if that would fit in the
// remainder of the line.
slop := 5
wrap = wrap - slop
// Handle first line, which is indented by the caller (or the
// special case above)
l, s = wrapN(wrap, slop, s)
r = r + l
// Now wrap the rest
for s != "" {
var t string
t, s = wrapN(wrap, slop, s)
r = r + "\n" + strings.Repeat(" ", i) + t
}
return r
}
// FlagUsagesWrapped returns a string containing the usage information
// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no
// wrapping)
func (f *FlagSet) FlagUsagesWrapped(cols int) string {
buf := new(bytes.Buffer)
lines := make([]string, 0, len(f.formal)) lines := make([]string, 0, len(f.formal))
maxlen := 0 maxlen := 0
f.VisitAll(func(flag *Flag) { f.VisitAll(func(flag *Flag) {
if len(flag.Deprecated) > 0 || flag.Hidden { if flag.Deprecated != "" || flag.Hidden {
return return
} }
line := "" line := ""
if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 { if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name) line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name)
} else { } else {
line = fmt.Sprintf(" --%s", flag.Name) line = fmt.Sprintf(" --%s", flag.Name)
} }
varname, usage := UnquoteUsage(flag) varname, usage := UnquoteUsage(flag)
if len(varname) > 0 { if varname != "" {
line += " " + varname line += " " + varname
} }
if len(flag.NoOptDefVal) > 0 { if flag.NoOptDefVal != "" {
switch flag.Value.Type() { switch flag.Value.Type() {
case "string": case "string":
line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal) line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
@ -519,6 +676,10 @@ func (f *FlagSet) FlagUsages() string {
if flag.NoOptDefVal != "true" { if flag.NoOptDefVal != "true" {
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
} }
case "count":
if flag.NoOptDefVal != "+1" {
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
}
default: default:
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
} }
@ -534,7 +695,7 @@ func (f *FlagSet) FlagUsages() string {
line += usage line += usage
if !flag.defaultIsZeroValue() { if !flag.defaultIsZeroValue() {
if flag.Value.Type() == "string" { if flag.Value.Type() == "string" {
line += fmt.Sprintf(" (default \"%s\")", flag.DefValue) line += fmt.Sprintf(" (default %q)", flag.DefValue)
} else { } else {
line += fmt.Sprintf(" (default %s)", flag.DefValue) line += fmt.Sprintf(" (default %s)", flag.DefValue)
} }
@ -546,10 +707,17 @@ func (f *FlagSet) FlagUsages() string {
for _, line := range lines { for _, line := range lines {
sidx := strings.Index(line, "\x00") sidx := strings.Index(line, "\x00")
spacing := strings.Repeat(" ", maxlen-sidx) spacing := strings.Repeat(" ", maxlen-sidx)
fmt.Fprintln(x, line[:sidx], spacing, line[sidx+1:]) // maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx
fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
} }
return x.String() return buf.String()
}
// FlagUsages returns a string containing the usage information for all flags in
// the FlagSet
func (f *FlagSet) FlagUsages() string {
return f.FlagUsagesWrapped(0)
} }
// PrintDefaults prints to standard error the default values of all defined command-line flags. // PrintDefaults prints to standard error the default values of all defined command-line flags.
@ -635,16 +803,15 @@ func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag {
// VarP is like Var, but accepts a shorthand letter that can be used after a single dash. // VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {
_ = f.VarPF(value, name, shorthand, usage) f.VarPF(value, name, shorthand, usage)
} }
// AddFlag will add the flag to the FlagSet // AddFlag will add the flag to the FlagSet
func (f *FlagSet) AddFlag(flag *Flag) { func (f *FlagSet) AddFlag(flag *Flag) {
// Call normalizeFlagName function only once
normalizedFlagName := f.normalizeFlagName(flag.Name) normalizedFlagName := f.normalizeFlagName(flag.Name)
_, alreadythere := f.formal[normalizedFlagName] _, alreadyThere := f.formal[normalizedFlagName]
if alreadythere { if alreadyThere {
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
fmt.Fprintln(f.out(), msg) fmt.Fprintln(f.out(), msg)
panic(msg) // Happens only if flags are declared with identical names panic(msg) // Happens only if flags are declared with identical names
@ -655,28 +822,31 @@ func (f *FlagSet) AddFlag(flag *Flag) {
flag.Name = string(normalizedFlagName) flag.Name = string(normalizedFlagName)
f.formal[normalizedFlagName] = flag f.formal[normalizedFlagName] = flag
f.orderedFormal = append(f.orderedFormal, flag)
if len(flag.Shorthand) == 0 { if flag.Shorthand == "" {
return return
} }
if len(flag.Shorthand) > 1 { if len(flag.Shorthand) > 1 {
fmt.Fprintf(f.out(), "%s shorthand more than ASCII character: %s\n", f.name, flag.Shorthand) msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
panic("shorthand is more than one character") fmt.Fprintf(f.out(), msg)
panic(msg)
} }
if f.shorthands == nil { if f.shorthands == nil {
f.shorthands = make(map[byte]*Flag) f.shorthands = make(map[byte]*Flag)
} }
c := flag.Shorthand[0] c := flag.Shorthand[0]
old, alreadythere := f.shorthands[c] used, alreadyThere := f.shorthands[c]
if alreadythere { if alreadyThere {
fmt.Fprintf(f.out(), "%s shorthand reused: %q for %s already used for %s\n", f.name, c, flag.Name, old.Name) msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
panic("shorthand redefinition") fmt.Fprintf(f.out(), msg)
panic(msg)
} }
f.shorthands[c] = flag f.shorthands[c] = flag
} }
// AddFlagSet adds one FlagSet to another. If a flag is already present in f // AddFlagSet adds one FlagSet to another. If a flag is already present in f
// the flag from newSet will be ignored // the flag from newSet will be ignored.
func (f *FlagSet) AddFlagSet(newSet *FlagSet) { func (f *FlagSet) AddFlagSet(newSet *FlagSet) {
if newSet == nil { if newSet == nil {
return return
@ -707,8 +877,10 @@ func VarP(value Value, name, shorthand, usage string) {
// returns the error. // returns the error.
func (f *FlagSet) failf(format string, a ...interface{}) error { func (f *FlagSet) failf(format string, a ...interface{}) error {
err := fmt.Errorf(format, a...) err := fmt.Errorf(format, a...)
fmt.Fprintln(f.out(), err) if f.errorHandling != ContinueOnError {
f.usage() fmt.Fprintln(f.out(), err)
f.usage()
}
return err return err
} }
@ -724,45 +896,18 @@ func (f *FlagSet) usage() {
} }
} }
func (f *FlagSet) setFlag(flag *Flag, value string, origArg string) error { func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
if err := flag.Value.Set(value); err != nil {
return f.failf("invalid argument %q for %s: %v", value, origArg, err)
}
// mark as visited for Visit()
if f.actual == nil {
f.actual = make(map[NormalizedName]*Flag)
}
f.actual[f.normalizeFlagName(flag.Name)] = flag
flag.Changed = true
if len(flag.Deprecated) > 0 {
fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
}
if len(flag.ShorthandDeprecated) > 0 && containsShorthand(origArg, flag.Shorthand) {
fmt.Fprintf(os.Stderr, "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
}
return nil
}
func containsShorthand(arg, shorthand string) bool {
// filter out flags --<flag_name>
if strings.HasPrefix(arg, "-") {
return false
}
arg = strings.SplitN(arg, "=", 2)[0]
return strings.Contains(arg, shorthand)
}
func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) {
a = args a = args
name := s[2:] name := s[2:]
if len(name) == 0 || name[0] == '-' || name[0] == '=' { if len(name) == 0 || name[0] == '-' || name[0] == '=' {
err = f.failf("bad flag syntax: %s", s) err = f.failf("bad flag syntax: %s", s)
return return
} }
split := strings.SplitN(name, "=", 2) split := strings.SplitN(name, "=", 2)
name = split[0] name = split[0]
flag, alreadythere := f.formal[f.normalizeFlagName(name)] flag, exists := f.formal[f.normalizeFlagName(name)]
if !alreadythere { if !exists {
if name == "help" { // special case for nice help message. if name == "help" { // special case for nice help message.
f.usage() f.usage()
return a, ErrHelp return a, ErrHelp
@ -770,11 +915,12 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error)
err = f.failf("unknown flag: --%s", name) err = f.failf("unknown flag: --%s", name)
return return
} }
var value string var value string
if len(split) == 2 { if len(split) == 2 {
// '--flag=arg' // '--flag=arg'
value = split[1] value = split[1]
} else if len(flag.NoOptDefVal) > 0 { } else if flag.NoOptDefVal != "" {
// '--flag' (arg was optional) // '--flag' (arg was optional)
value = flag.NoOptDefVal value = flag.NoOptDefVal
} else if len(a) > 0 { } else if len(a) > 0 {
@ -786,55 +932,74 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error)
err = f.failf("flag needs an argument: %s", s) err = f.failf("flag needs an argument: %s", s)
return return
} }
err = f.setFlag(flag, value, s)
err = fn(flag, value)
if err != nil {
f.failf(err.Error())
}
return return
} }
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShorts string, outArgs []string, err error) { func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
if strings.HasPrefix(shorthands, "test.") { if strings.HasPrefix(shorthands, "test.") {
return return
} }
outArgs = args outArgs = args
outShorts = shorthands[1:] outShorts = shorthands[1:]
c := shorthands[0] c := shorthands[0]
flag, alreadythere := f.shorthands[c] flag, exists := f.shorthands[c]
if !alreadythere { if !exists {
if c == 'h' { // special case for nice help message. if c == 'h' { // special case for nice help message.
f.usage() f.usage()
err = ErrHelp err = ErrHelp
return return
} }
//TODO continue on error
err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands) err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
return return
} }
var value string var value string
if len(shorthands) > 2 && shorthands[1] == '=' { if len(shorthands) > 2 && shorthands[1] == '=' {
// '-f=arg'
value = shorthands[2:] value = shorthands[2:]
outShorts = "" outShorts = ""
} else if len(flag.NoOptDefVal) > 0 { } else if flag.NoOptDefVal != "" {
// '-f' (arg was optional)
value = flag.NoOptDefVal value = flag.NoOptDefVal
} else if len(shorthands) > 1 { } else if len(shorthands) > 1 {
// '-farg'
value = shorthands[1:] value = shorthands[1:]
outShorts = "" outShorts = ""
} else if len(args) > 0 { } else if len(args) > 0 {
// '-f arg'
value = args[0] value = args[0]
outArgs = args[1:] outArgs = args[1:]
} else { } else {
// '-f' (arg was required)
err = f.failf("flag needs an argument: %q in -%s", c, shorthands) err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
return return
} }
err = f.setFlag(flag, value, shorthands)
if flag.ShorthandDeprecated != "" {
fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
}
err = fn(flag, value)
if err != nil {
f.failf(err.Error())
}
return return
} }
func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) { func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) {
a = args a = args
shorthands := s[1:] shorthands := s[1:]
// "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv").
for len(shorthands) > 0 { for len(shorthands) > 0 {
shorthands, a, err = f.parseSingleShortArg(shorthands, args) shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
if err != nil { if err != nil {
return return
} }
@ -843,7 +1008,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error)
return return
} }
func (f *FlagSet) parseArgs(args []string) (err error) { func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
for len(args) > 0 { for len(args) > 0 {
s := args[0] s := args[0]
args = args[1:] args = args[1:]
@ -863,9 +1028,9 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
f.args = append(f.args, args...) f.args = append(f.args, args...)
break break
} }
args, err = f.parseLongArg(s, args) args, err = f.parseLongArg(s, args, fn)
} else { } else {
args, err = f.parseShortArg(s, args) args, err = f.parseShortArg(s, args, fn)
} }
if err != nil { if err != nil {
return return
@ -880,8 +1045,44 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
// The return value will be ErrHelp if -help was set but not defined. // The return value will be ErrHelp if -help was set but not defined.
func (f *FlagSet) Parse(arguments []string) error { func (f *FlagSet) Parse(arguments []string) error {
f.parsed = true f.parsed = true
if len(arguments) < 0 {
return nil
}
f.args = make([]string, 0, len(arguments)) f.args = make([]string, 0, len(arguments))
err := f.parseArgs(arguments)
set := func(flag *Flag, value string) error {
return f.Set(flag.Name, value)
}
err := f.parseArgs(arguments, set)
if err != nil {
switch f.errorHandling {
case ContinueOnError:
return err
case ExitOnError:
fmt.Println(err)
os.Exit(2)
case PanicOnError:
panic(err)
}
}
return nil
}
type parseFunc func(flag *Flag, value string) error
// ParseAll parses flag definitions from the argument list, which should not
// include the command name. The arguments for fn are flag and value. Must be
// called after all flags in the FlagSet are defined and before flags are
// accessed by the program. The return value will be ErrHelp if -help was set
// but not defined.
func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error {
f.parsed = true
f.args = make([]string, 0, len(arguments))
err := f.parseArgs(arguments, fn)
if err != nil { if err != nil {
switch f.errorHandling { switch f.errorHandling {
case ContinueOnError: case ContinueOnError:
@ -907,6 +1108,14 @@ func Parse() {
CommandLine.Parse(os.Args[1:]) CommandLine.Parse(os.Args[1:])
} }
// ParseAll parses the command-line flags from os.Args[1:] and called fn for each.
// The arguments for fn are flag and value. Must be called after all flags are
// defined and before flags are accessed by the program.
func ParseAll(fn func(flag *Flag, value string) error) {
// Ignore errors; CommandLine is set for ExitOnError.
CommandLine.ParseAll(os.Args[1:], fn)
}
// SetInterspersed sets whether to support interspersed option/non-option arguments. // SetInterspersed sets whether to support interspersed option/non-option arguments.
func SetInterspersed(interspersed bool) { func SetInterspersed(interspersed bool) {
CommandLine.SetInterspersed(interspersed) CommandLine.SetInterspersed(interspersed)
@ -920,14 +1129,15 @@ func Parsed() bool {
// CommandLine is the default set of command-line flags, parsed from os.Args. // CommandLine is the default set of command-line flags, parsed from os.Args.
var CommandLine = NewFlagSet(os.Args[0], ExitOnError) var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
// NewFlagSet returns a new, empty flag set with the specified name and // NewFlagSet returns a new, empty flag set with the specified name,
// error handling property. // error handling property and SortFlags set to true.
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
f := &FlagSet{ f := &FlagSet{
name: name, name: name,
errorHandling: errorHandling, errorHandling: errorHandling,
argsLenAtDash: -1, argsLenAtDash: -1,
interspersed: true, interspersed: true,
SortFlags: true,
} }
return f return f
} }

View File

@ -6,13 +6,10 @@ package pflag
import ( import (
goflag "flag" goflag "flag"
"fmt"
"reflect" "reflect"
"strings" "strings"
) )
var _ = fmt.Print
// flagValueWrapper implements pflag.Value around a flag.Value. The main // flagValueWrapper implements pflag.Value around a flag.Value. The main
// difference here is the addition of the Type method that returns a string // difference here is the addition of the Type method that returns a string
// name of the type. As this is generally unknown, we approximate that with // name of the type. As this is generally unknown, we approximate that with

88
vendor/github.com/spf13/pflag/int16.go generated vendored Normal file
View File

@ -0,0 +1,88 @@
package pflag
import "strconv"
// -- int16 Value
type int16Value int16
func newInt16Value(val int16, p *int16) *int16Value {
*p = val
return (*int16Value)(p)
}
func (i *int16Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 16)
*i = int16Value(v)
return err
}
func (i *int16Value) Type() string {
return "int16"
}
func (i *int16Value) String() string { return strconv.FormatInt(int64(*i), 10) }
func int16Conv(sval string) (interface{}, error) {
v, err := strconv.ParseInt(sval, 0, 16)
if err != nil {
return 0, err
}
return int16(v), nil
}
// GetInt16 returns the int16 value of a flag with the given name
func (f *FlagSet) GetInt16(name string) (int16, error) {
val, err := f.getFlagType(name, "int16", int16Conv)
if err != nil {
return 0, err
}
return val.(int16), nil
}
// Int16Var defines an int16 flag with specified name, default value, and usage string.
// The argument p points to an int16 variable in which to store the value of the flag.
func (f *FlagSet) Int16Var(p *int16, name string, value int16, usage string) {
f.VarP(newInt16Value(value, p), name, "", usage)
}
// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int16VarP(p *int16, name, shorthand string, value int16, usage string) {
f.VarP(newInt16Value(value, p), name, shorthand, usage)
}
// Int16Var defines an int16 flag with specified name, default value, and usage string.
// The argument p points to an int16 variable in which to store the value of the flag.
func Int16Var(p *int16, name string, value int16, usage string) {
CommandLine.VarP(newInt16Value(value, p), name, "", usage)
}
// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash.
func Int16VarP(p *int16, name, shorthand string, value int16, usage string) {
CommandLine.VarP(newInt16Value(value, p), name, shorthand, usage)
}
// Int16 defines an int16 flag with specified name, default value, and usage string.
// The return value is the address of an int16 variable that stores the value of the flag.
func (f *FlagSet) Int16(name string, value int16, usage string) *int16 {
p := new(int16)
f.Int16VarP(p, name, "", value, usage)
return p
}
// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int16P(name, shorthand string, value int16, usage string) *int16 {
p := new(int16)
f.Int16VarP(p, name, shorthand, value, usage)
return p
}
// Int16 defines an int16 flag with specified name, default value, and usage string.
// The return value is the address of an int16 variable that stores the value of the flag.
func Int16(name string, value int16, usage string) *int16 {
return CommandLine.Int16P(name, "", value, usage)
}
// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash.
func Int16P(name, shorthand string, value int16, usage string) *int16 {
return CommandLine.Int16P(name, shorthand, value, usage)
}

View File

@ -6,8 +6,6 @@ import (
"strings" "strings"
) )
var _ = strings.TrimSpace
// -- net.IP value // -- net.IP value
type ipValue net.IP type ipValue net.IP

148
vendor/github.com/spf13/pflag/ip_slice.go generated vendored Normal file
View File

@ -0,0 +1,148 @@
package pflag
import (
"fmt"
"io"
"net"
"strings"
)
// -- ipSlice Value
type ipSliceValue struct {
value *[]net.IP
changed bool
}
func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue {
ipsv := new(ipSliceValue)
ipsv.value = p
*ipsv.value = val
return ipsv
}
// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag.
// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended.
func (s *ipSliceValue) Set(val string) error {
// remove all quote characters
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
// read flag arguments with CSV parser
ipStrSlice, err := readAsCSV(rmQuote.Replace(val))
if err != nil && err != io.EOF {
return err
}
// parse ip values into slice
out := make([]net.IP, 0, len(ipStrSlice))
for _, ipStr := range ipStrSlice {
ip := net.ParseIP(strings.TrimSpace(ipStr))
if ip == nil {
return fmt.Errorf("invalid string being converted to IP address: %s", ipStr)
}
out = append(out, ip)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
// Type returns a string that uniquely represents this flag's type.
func (s *ipSliceValue) Type() string {
return "ipSlice"
}
// String defines a "native" format for this net.IP slice flag value.
func (s *ipSliceValue) String() string {
ipStrSlice := make([]string, len(*s.value))
for i, ip := range *s.value {
ipStrSlice[i] = ip.String()
}
out, _ := writeAsCSV(ipStrSlice)
return "[" + out + "]"
}
func ipSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Emtpy string would cause a slice with one (empty) entry
if len(val) == 0 {
return []net.IP{}, nil
}
ss := strings.Split(val, ",")
out := make([]net.IP, len(ss))
for i, sval := range ss {
ip := net.ParseIP(strings.TrimSpace(sval))
if ip == nil {
return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval)
}
out[i] = ip
}
return out, nil
}
// GetIPSlice returns the []net.IP value of a flag with the given name
func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) {
val, err := f.getFlagType(name, "ipSlice", ipSliceConv)
if err != nil {
return []net.IP{}, err
}
return val.([]net.IP), nil
}
// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string.
// The argument p points to a []net.IP variable in which to store the value of the flag.
func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
f.VarP(newIPSliceValue(value, p), name, "", usage)
}
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
f.VarP(newIPSliceValue(value, p), name, shorthand, usage)
}
// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string.
// The argument p points to a []net.IP variable in which to store the value of the flag.
func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
CommandLine.VarP(newIPSliceValue(value, p), name, "", usage)
}
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage)
}
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
// The return value is the address of a []net.IP variable that stores the value of that flag.
func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP {
p := []net.IP{}
f.IPSliceVarP(&p, name, "", value, usage)
return &p
}
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
p := []net.IP{}
f.IPSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
// The return value is the address of a []net.IP variable that stores the value of the flag.
func IPSlice(name string, value []net.IP, usage string) *[]net.IP {
return CommandLine.IPSliceP(name, "", value, usage)
}
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
return CommandLine.IPSliceP(name, shorthand, value, usage)
}

View File

@ -27,8 +27,6 @@ func (*ipNetValue) Type() string {
return "ipNet" return "ipNet"
} }
var _ = strings.TrimSpace
func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue { func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {
*p = val *p = val
return (*ipNetValue)(p) return (*ipNetValue)(p)

View File

@ -1,11 +1,5 @@
package pflag package pflag
import (
"fmt"
)
var _ = fmt.Fprint
// -- stringArray Value // -- stringArray Value
type stringArrayValue struct { type stringArrayValue struct {
value *[]string value *[]string

View File

@ -3,12 +3,9 @@ package pflag
import ( import (
"bytes" "bytes"
"encoding/csv" "encoding/csv"
"fmt"
"strings" "strings"
) )
var _ = fmt.Fprint
// -- stringSlice Value // -- stringSlice Value
type stringSliceValue struct { type stringSliceValue struct {
value *[]string value *[]string
@ -39,7 +36,7 @@ func writeAsCSV(vals []string) (string, error) {
return "", err return "", err
} }
w.Flush() w.Flush()
return strings.TrimSuffix(b.String(), fmt.Sprintln()), nil return strings.TrimSuffix(b.String(), "\n"), nil
} }
func (s *stringSliceValue) Set(val string) error { func (s *stringSliceValue) Set(val string) error {

126
vendor/github.com/spf13/pflag/uint_slice.go generated vendored Normal file
View File

@ -0,0 +1,126 @@
package pflag
import (
"fmt"
"strconv"
"strings"
)
// -- uintSlice Value
type uintSliceValue struct {
value *[]uint
changed bool
}
func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue {
uisv := new(uintSliceValue)
uisv.value = p
*uisv.value = val
return uisv
}
func (s *uintSliceValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make([]uint, len(ss))
for i, d := range ss {
u, err := strconv.ParseUint(d, 10, 0)
if err != nil {
return err
}
out[i] = uint(u)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
func (s *uintSliceValue) Type() string {
return "uintSlice"
}
func (s *uintSliceValue) String() string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%d", d)
}
return "[" + strings.Join(out, ",") + "]"
}
func uintSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []uint{}, nil
}
ss := strings.Split(val, ",")
out := make([]uint, len(ss))
for i, d := range ss {
u, err := strconv.ParseUint(d, 10, 0)
if err != nil {
return nil, err
}
out[i] = uint(u)
}
return out, nil
}
// GetUintSlice returns the []uint value of a flag with the given name.
func (f *FlagSet) GetUintSlice(name string) ([]uint, error) {
val, err := f.getFlagType(name, "uintSlice", uintSliceConv)
if err != nil {
return []uint{}, err
}
return val.([]uint), nil
}
// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string.
// The argument p points to a []uint variable in which to store the value of the flag.
func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) {
f.VarP(newUintSliceValue(value, p), name, "", usage)
}
// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
f.VarP(newUintSliceValue(value, p), name, shorthand, usage)
}
// UintSliceVar defines a uint[] flag with specified name, default value, and usage string.
// The argument p points to a uint[] variable in which to store the value of the flag.
func UintSliceVar(p *[]uint, name string, value []uint, usage string) {
CommandLine.VarP(newUintSliceValue(value, p), name, "", usage)
}
// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage)
}
// UintSlice defines a []uint flag with specified name, default value, and usage string.
// The return value is the address of a []uint variable that stores the value of the flag.
func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint {
p := []uint{}
f.UintSliceVarP(&p, name, "", value, usage)
return &p
}
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
p := []uint{}
f.UintSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// UintSlice defines a []uint flag with specified name, default value, and usage string.
// The return value is the address of a []uint variable that stores the value of the flag.
func UintSlice(name string, value []uint, usage string) *[]uint {
return CommandLine.UintSliceP(name, "", value, usage)
}
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
return CommandLine.UintSliceP(name, shorthand, value, usage)
}

View File

@ -24,6 +24,7 @@ import (
"github.com/hashicorp/hcl" "github.com/hashicorp/hcl"
"github.com/magiconair/properties" "github.com/magiconair/properties"
toml "github.com/pelletier/go-toml" toml "github.com/pelletier/go-toml"
"github.com/spf13/afero"
"github.com/spf13/cast" "github.com/spf13/cast"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
@ -121,8 +122,8 @@ func absPathify(inPath string) string {
} }
// Check if File / Directory Exists // Check if File / Directory Exists
func exists(path string) (bool, error) { func exists(fs afero.Fs, path string) (bool, error) {
_, err := v.fs.Stat(path) _, err := fs.Stat(path)
if err == nil { if err == nil {
return true, nil return true, nil
} }

View File

@ -21,6 +21,7 @@ package viper
import ( import (
"bytes" "bytes"
"encoding/csv"
"fmt" "fmt"
"io" "io"
"log" "log"
@ -40,6 +41,11 @@ import (
var v *Viper var v *Viper
type RemoteResponse struct {
Value []byte
Error error
}
func init() { func init() {
v = New() v = New()
} }
@ -47,6 +53,7 @@ func init() {
type remoteConfigFactory interface { type remoteConfigFactory interface {
Get(rp RemoteProvider) (io.Reader, error) Get(rp RemoteProvider) (io.Reader, error)
Watch(rp RemoteProvider) (io.Reader, error) Watch(rp RemoteProvider) (io.Reader, error)
WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
} }
// RemoteConfig is optional, see the remote package // RemoteConfig is optional, see the remote package
@ -62,8 +69,7 @@ func (str UnsupportedConfigError) Error() string {
} }
// UnsupportedRemoteProviderError denotes encountering an unsupported remote // UnsupportedRemoteProviderError denotes encountering an unsupported remote
// provider. Currently only etcd and Consul are // provider. Currently only etcd and Consul are supported.
// supported.
type UnsupportedRemoteProviderError string type UnsupportedRemoteProviderError string
// Error returns the formatted remote provider error. // Error returns the formatted remote provider error.
@ -276,8 +282,8 @@ func (v *Viper) WatchConfig() {
}() }()
} }
// SetConfigFile explicitly defines the path, name and extension of the config file // SetConfigFile explicitly defines the path, name and extension of the config file.
// Viper will use this and not check any of the config paths // Viper will use this and not check any of the config paths.
func SetConfigFile(in string) { v.SetConfigFile(in) } func SetConfigFile(in string) { v.SetConfigFile(in) }
func (v *Viper) SetConfigFile(in string) { func (v *Viper) SetConfigFile(in string) {
if in != "" { if in != "" {
@ -286,8 +292,8 @@ func (v *Viper) SetConfigFile(in string) {
} }
// SetEnvPrefix defines a prefix that ENVIRONMENT variables will use. // SetEnvPrefix defines a prefix that ENVIRONMENT variables will use.
// E.g. if your prefix is "spf", the env registry // E.g. if your prefix is "spf", the env registry will look for env
// will look for env. variables that start with "SPF_" // variables that start with "SPF_".
func SetEnvPrefix(in string) { v.SetEnvPrefix(in) } func SetEnvPrefix(in string) { v.SetEnvPrefix(in) }
func (v *Viper) SetEnvPrefix(in string) { func (v *Viper) SetEnvPrefix(in string) {
if in != "" { if in != "" {
@ -305,11 +311,11 @@ func (v *Viper) mergeWithEnvPrefix(in string) string {
// TODO: should getEnv logic be moved into find(). Can generalize the use of // TODO: should getEnv logic be moved into find(). Can generalize the use of
// rewriting keys many things, Ex: Get('someKey') -> some_key // rewriting keys many things, Ex: Get('someKey') -> some_key
// (cammel case to snake case for JSON keys perhaps) // (camel case to snake case for JSON keys perhaps)
// getEnv is a wrapper around os.Getenv which replaces characters in the original // getEnv is a wrapper around os.Getenv which replaces characters in the original
// key. This allows env vars which have different keys then the config object // key. This allows env vars which have different keys than the config object
// keys // keys.
func (v *Viper) getEnv(key string) string { func (v *Viper) getEnv(key string) string {
if v.envKeyReplacer != nil { if v.envKeyReplacer != nil {
key = v.envKeyReplacer.Replace(key) key = v.envKeyReplacer.Replace(key)
@ -317,7 +323,7 @@ func (v *Viper) getEnv(key string) string {
return os.Getenv(key) return os.Getenv(key)
} }
// ConfigFileUsed returns the file used to populate the config registry // ConfigFileUsed returns the file used to populate the config registry.
func ConfigFileUsed() string { return v.ConfigFileUsed() } func ConfigFileUsed() string { return v.ConfigFileUsed() }
func (v *Viper) ConfigFileUsed() string { return v.configFile } func (v *Viper) ConfigFileUsed() string { return v.configFile }
@ -590,32 +596,33 @@ func (v *Viper) Get(key string) interface{} {
return nil return nil
} }
valType := val
if v.typeByDefValue { if v.typeByDefValue {
// TODO(bep) this branch isn't covered by a single test. // TODO(bep) this branch isn't covered by a single test.
valType := val
path := strings.Split(lcaseKey, v.keyDelim) path := strings.Split(lcaseKey, v.keyDelim)
defVal := v.searchMap(v.defaults, path) defVal := v.searchMap(v.defaults, path)
if defVal != nil { if defVal != nil {
valType = defVal valType = defVal
} }
switch valType.(type) {
case bool:
return cast.ToBool(val)
case string:
return cast.ToString(val)
case int64, int32, int16, int8, int:
return cast.ToInt(val)
case float64, float32:
return cast.ToFloat64(val)
case time.Time:
return cast.ToTime(val)
case time.Duration:
return cast.ToDuration(val)
case []string:
return cast.ToStringSlice(val)
}
} }
switch valType.(type) {
case bool:
return cast.ToBool(val)
case string:
return cast.ToString(val)
case int64, int32, int16, int8, int:
return cast.ToInt(val)
case float64, float32:
return cast.ToFloat64(val)
case time.Time:
return cast.ToTime(val)
case time.Duration:
return cast.ToDuration(val)
case []string:
return cast.ToStringSlice(val)
}
return val return val
} }
@ -713,7 +720,15 @@ func (v *Viper) GetSizeInBytes(key string) uint {
// UnmarshalKey takes a single key and unmarshals it into a Struct. // UnmarshalKey takes a single key and unmarshals it into a Struct.
func UnmarshalKey(key string, rawVal interface{}) error { return v.UnmarshalKey(key, rawVal) } func UnmarshalKey(key string, rawVal interface{}) error { return v.UnmarshalKey(key, rawVal) }
func (v *Viper) UnmarshalKey(key string, rawVal interface{}) error { func (v *Viper) UnmarshalKey(key string, rawVal interface{}) error {
return mapstructure.Decode(v.Get(key), rawVal) err := decode(v.Get(key), defaultDecoderConfig(rawVal))
if err != nil {
return err
}
v.insensitiviseMaps()
return nil
} }
// Unmarshal unmarshals the config into a Struct. Make sure that the tags // Unmarshal unmarshals the config into a Struct. Make sure that the tags
@ -732,13 +747,16 @@ func (v *Viper) Unmarshal(rawVal interface{}) error {
} }
// defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot // defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot
// of time.Duration values // of time.Duration values & string slices
func defaultDecoderConfig(output interface{}) *mapstructure.DecoderConfig { func defaultDecoderConfig(output interface{}) *mapstructure.DecoderConfig {
return &mapstructure.DecoderConfig{ return &mapstructure.DecoderConfig{
Metadata: nil, Metadata: nil,
Result: output, Result: output,
WeaklyTypedInput: true, WeaklyTypedInput: true,
DecodeHook: mapstructure.StringToTimeDurationHookFunc(), DecodeHook: mapstructure.ComposeDecodeHookFunc(
mapstructure.StringToTimeDurationHookFunc(),
mapstructure.StringToSliceHookFunc(","),
),
} }
} }
@ -799,7 +817,7 @@ func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) {
} }
// BindFlagValue binds a specific key to a FlagValue. // BindFlagValue binds a specific key to a FlagValue.
// Example(where serverCmd is a Cobra instance): // Example (where serverCmd is a Cobra instance):
// //
// serverCmd.Flags().Int("port", 1138, "Port to run Application server on") // serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
// Viper.BindFlagValue("port", serverCmd.Flags().Lookup("port")) // Viper.BindFlagValue("port", serverCmd.Flags().Lookup("port"))
@ -880,7 +898,9 @@ func (v *Viper) find(lcaseKey string) interface{} {
return cast.ToBool(flag.ValueString()) return cast.ToBool(flag.ValueString())
case "stringSlice": case "stringSlice":
s := strings.TrimPrefix(flag.ValueString(), "[") s := strings.TrimPrefix(flag.ValueString(), "[")
return strings.TrimSuffix(s, "]") s = strings.TrimSuffix(s, "]")
res, _ := readAsCSV(s)
return res
default: default:
return flag.ValueString() return flag.ValueString()
} }
@ -947,7 +967,9 @@ func (v *Viper) find(lcaseKey string) interface{} {
return cast.ToBool(flag.ValueString()) return cast.ToBool(flag.ValueString())
case "stringSlice": case "stringSlice":
s := strings.TrimPrefix(flag.ValueString(), "[") s := strings.TrimPrefix(flag.ValueString(), "[")
return strings.TrimSuffix(s, "]") s = strings.TrimSuffix(s, "]")
res, _ := readAsCSV(s)
return res
default: default:
return flag.ValueString() return flag.ValueString()
} }
@ -957,6 +979,15 @@ func (v *Viper) find(lcaseKey string) interface{} {
return nil return nil
} }
func readAsCSV(val string) ([]string, error) {
if val == "" {
return []string{}, nil
}
stringReader := strings.NewReader(val)
csvReader := csv.NewReader(stringReader)
return csvReader.Read()
}
// IsSet checks to see if the key has been set in any of the data locations. // IsSet checks to see if the key has been set in any of the data locations.
// IsSet is case-insensitive for a key. // IsSet is case-insensitive for a key.
func IsSet(key string) bool { return v.IsSet(key) } func IsSet(key string) bool { return v.IsSet(key) }
@ -1093,24 +1124,30 @@ func (v *Viper) ReadInConfig() error {
return err return err
} }
v.config = make(map[string]interface{}) config := make(map[string]interface{})
return v.unmarshalReader(bytes.NewReader(file), v.config) err = v.unmarshalReader(bytes.NewReader(file), config)
if err != nil {
return err
}
v.config = config
return nil
} }
// MergeInConfig merges a new configuration with an existing config. // MergeInConfig merges a new configuration with an existing config.
func MergeInConfig() error { return v.MergeInConfig() } func MergeInConfig() error { return v.MergeInConfig() }
func (v *Viper) MergeInConfig() error { func (v *Viper) MergeInConfig() error {
jww.INFO.Println("Attempting to merge in config file") jww.INFO.Println("Attempting to merge in config file")
if !stringInSlice(v.getConfigType(), SupportedExts) {
return UnsupportedConfigError(v.getConfigType())
}
filename, err := v.getConfigFile() filename, err := v.getConfigFile()
if err != nil { if err != nil {
return err return err
} }
if !stringInSlice(v.getConfigType(), SupportedExts) {
return UnsupportedConfigError(v.getConfigType())
}
file, err := afero.ReadFile(v.fs, filename) file, err := afero.ReadFile(v.fs, filename)
if err != nil { if err != nil {
return err return err
@ -1249,7 +1286,11 @@ func (v *Viper) WatchRemoteConfig() error {
return v.watchKeyValueConfig() return v.watchKeyValueConfig()
} }
// Unmarshall a Reader into a map. func (v *Viper) WatchRemoteConfigOnChannel() error {
return v.watchKeyValueConfigOnChannel()
}
// Unmarshal a Reader into a map.
// Should probably be an unexported function. // Should probably be an unexported function.
func unmarshalReader(in io.Reader, c map[string]interface{}) error { func unmarshalReader(in io.Reader, c map[string]interface{}) error {
return v.unmarshalReader(in, c) return v.unmarshalReader(in, c)
@ -1292,6 +1333,23 @@ func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]interface{}
return v.kvstore, err return v.kvstore, err
} }
// Retrieve the first found remote configuration.
func (v *Viper) watchKeyValueConfigOnChannel() error {
for _, rp := range v.remoteProviders {
respc, _ := RemoteConfig.WatchChannel(rp)
//Todo: Add quit channel
go func(rc <-chan *RemoteResponse) {
for {
b := <-rc
reader := bytes.NewReader(b.Value)
v.unmarshalReader(reader, v.kvstore)
}
}(respc)
return nil
}
return RemoteConfigError("No Files Found")
}
// Retrieve the first found remote configuration. // Retrieve the first found remote configuration.
func (v *Viper) watchKeyValueConfig() error { func (v *Viper) watchKeyValueConfig() error {
for _, rp := range v.remoteProviders { for _, rp := range v.remoteProviders {
@ -1479,7 +1537,7 @@ func (v *Viper) searchInPath(in string) (filename string) {
jww.DEBUG.Println("Searching for config in ", in) jww.DEBUG.Println("Searching for config in ", in)
for _, ext := range SupportedExts { for _, ext := range SupportedExts {
jww.DEBUG.Println("Checking for", filepath.Join(in, v.configName+"."+ext)) jww.DEBUG.Println("Checking for", filepath.Join(in, v.configName+"."+ext))
if b, _ := exists(filepath.Join(in, v.configName+"."+ext)); b { if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
jww.DEBUG.Println("Found: ", filepath.Join(in, v.configName+"."+ext)) jww.DEBUG.Println("Found: ", filepath.Join(in, v.configName+"."+ext))
return filepath.Join(in, v.configName+"."+ext) return filepath.Join(in, v.configName+"."+ext)
} }
@ -1491,7 +1549,6 @@ func (v *Viper) searchInPath(in string) (filename string) {
// Search all configPaths for any config file. // Search all configPaths for any config file.
// Returns the first path that exists (and is a config file). // Returns the first path that exists (and is a config file).
func (v *Viper) findConfigFile() (string, error) { func (v *Viper) findConfigFile() (string, error) {
jww.INFO.Println("Searching for config in ", v.configPaths) jww.INFO.Println("Searching for config in ", v.configPaths)
for _, cp := range v.configPaths { for _, cp := range v.configPaths {

View File

@ -617,7 +617,7 @@ func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) {
if _, err = w.Write(crlf); err != nil { if _, err = w.Write(crlf); err != nil {
return n, err return n, err
} }
n += 1 n++
buf = buf[1:] buf = buf[1:]
} }
} }

View File

@ -17,44 +17,41 @@
package terminal // import "golang.org/x/crypto/ssh/terminal" package terminal // import "golang.org/x/crypto/ssh/terminal"
import ( import (
"syscall"
"unsafe"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
// State contains the state of a terminal. // State contains the state of a terminal.
type State struct { type State struct {
termios syscall.Termios termios unix.Termios
} }
// IsTerminal returns true if the given file descriptor is a terminal. // IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool { func IsTerminal(fd int) bool {
var termios syscall.Termios _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) return err == nil
return err == 0
} }
// MakeRaw put the terminal connected to the given file descriptor into raw // MakeRaw put the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be // mode and returns the previous state of the terminal so that it can be
// restored. // restored.
func MakeRaw(fd int) (*State, error) { func MakeRaw(fd int) (*State, error) {
var oldState State termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { if err != nil {
return nil, err return nil, err
} }
newState := oldState.termios oldState := State{termios: *termios}
// This attempts to replicate the behaviour documented for cfmakeraw in // This attempts to replicate the behaviour documented for cfmakeraw in
// the termios(3) manpage. // the termios(3) manpage.
newState.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
newState.Oflag &^= syscall.OPOST termios.Oflag &^= unix.OPOST
newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
newState.Cflag &^= syscall.CSIZE | syscall.PARENB termios.Cflag &^= unix.CSIZE | unix.PARENB
newState.Cflag |= syscall.CS8 termios.Cflag |= unix.CS8
newState.Cc[unix.VMIN] = 1 termios.Cc[unix.VMIN] = 1
newState.Cc[unix.VTIME] = 0 termios.Cc[unix.VTIME] = 0
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
return nil, err return nil, err
} }
@ -64,59 +61,55 @@ func MakeRaw(fd int) (*State, error) {
// GetState returns the current state of a terminal which may be useful to // GetState returns the current state of a terminal which may be useful to
// restore the terminal after a signal. // restore the terminal after a signal.
func GetState(fd int) (*State, error) { func GetState(fd int) (*State, error) {
var oldState State termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { if err != nil {
return nil, err return nil, err
} }
return &oldState, nil return &State{termios: *termios}, nil
} }
// Restore restores the terminal connected to the given file descriptor to a // Restore restores the terminal connected to the given file descriptor to a
// previous state. // previous state.
func Restore(fd int, state *State) error { func Restore(fd int, state *State) error {
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0); err != 0 { return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
return err
}
return nil
} }
// GetSize returns the dimensions of the given terminal. // GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (width, height int, err error) { func GetSize(fd int) (width, height int, err error) {
var dimensions [4]uint16 ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
if err != nil {
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
return -1, -1, err return -1, -1, err
} }
return int(dimensions[1]), int(dimensions[0]), nil return int(ws.Col), int(ws.Row), nil
} }
// passwordReader is an io.Reader that reads from a specific file descriptor. // passwordReader is an io.Reader that reads from a specific file descriptor.
type passwordReader int type passwordReader int
func (r passwordReader) Read(buf []byte) (int, error) { func (r passwordReader) Read(buf []byte) (int, error) {
return syscall.Read(int(r), buf) return unix.Read(int(r), buf)
} }
// ReadPassword reads a line of input from a terminal without local echo. This // ReadPassword reads a line of input from a terminal without local echo. This
// is commonly used for inputting passwords and other sensitive data. The slice // is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n. // returned does not include the \n.
func ReadPassword(fd int) ([]byte, error) { func ReadPassword(fd int) ([]byte, error) {
var oldState syscall.Termios termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 { if err != nil {
return nil, err return nil, err
} }
newState := oldState newState := *termios
newState.Lflag &^= syscall.ECHO newState.Lflag &^= unix.ECHO
newState.Lflag |= syscall.ICANON | syscall.ISIG newState.Lflag |= unix.ICANON | unix.ISIG
newState.Iflag |= syscall.ICRNL newState.Iflag |= unix.ICRNL
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
return nil, err return nil, err
} }
defer func() { defer func() {
syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0) unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
}() }()
return readPasswordLine(passwordReader(fd)) return readPasswordLine(passwordReader(fd))

View File

@ -17,6 +17,8 @@
package terminal package terminal
import ( import (
"os"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
@ -71,13 +73,6 @@ func GetSize(fd int) (width, height int, err error) {
return int(info.Size.X), int(info.Size.Y), nil return int(info.Size.X), int(info.Size.Y), nil
} }
// passwordReader is an io.Reader that reads from a specific Windows HANDLE.
type passwordReader int
func (r passwordReader) Read(buf []byte) (int, error) {
return windows.Read(windows.Handle(r), buf)
}
// ReadPassword reads a line of input from a terminal without local echo. This // ReadPassword reads a line of input from a terminal without local echo. This
// is commonly used for inputting passwords and other sensitive data. The slice // is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n. // returned does not include the \n.
@ -98,5 +93,5 @@ func ReadPassword(fd int) ([]byte, error) {
windows.SetConsoleMode(windows.Handle(fd), old) windows.SetConsoleMode(windows.Handle(fd), old)
}() }()
return readPasswordLine(passwordReader(fd)) return readPasswordLine(os.NewFile(uintptr(fd), "stdin"))
} }

10
vendor/golang.org/x/sys/unix/asm.s generated vendored
View File

@ -1,10 +0,0 @@
// Copyright 2014 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.
// +build !gccgo
#include "textflag.h"
TEXT ·use(SB),NOSPLIT,$0
RET

View File

@ -1,29 +1,28 @@
// Copyright 2009 The Go Authors. All rights reserved. // Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux
// +build mips64 mips64le
// +build !gccgo // +build !gccgo
#include "textflag.h" #include "textflag.h"
// //
// System call support for 386, FreeBSD // System calls for mips64, Linux
// //
// Just jump to package syscall's implementation for all these functions. // Just jump to package syscall's implementation for all these functions.
// The runtime may know about them. // The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-32 TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall(SB) JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-44 TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP syscall·Syscall6(SB) JMP syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-56 TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-32
JMP syscall·RawSyscall(SB) JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-44 TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB) JMP syscall·RawSyscall6(SB)

31
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s generated vendored Normal file
View File

@ -0,0 +1,31 @@
// Copyright 2016 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.
// +build linux
// +build mips mipsle
// +build !gccgo
#include "textflag.h"
//
// System calls for mips, Linux
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-28
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-40
JMP syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-52
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
JMP syscall·RawSyscall6(SB)

28
vendor/golang.org/x/sys/unix/asm_linux_s390x.s generated vendored Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2016 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.
// +build s390x
// +build linux
// +build !gccgo
#include "textflag.h"
//
// System calls for s390x, Linux
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
BR syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
BR syscall·Syscall6(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
BR syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
BR syscall·RawSyscall6(SB)

29
vendor/golang.org/x/sys/unix/asm_openbsd_arm.s generated vendored Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2017 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.
// +build !gccgo
#include "textflag.h"
//
// System call support for ARM, OpenBSD
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-28
B syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-40
B syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-52
B syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
B syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
B syscall·RawSyscall6(SB)

View File

@ -10,8 +10,8 @@
// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go // System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go
// //
TEXT ·sysvicall6(SB),NOSPLIT,$0-64 TEXT ·sysvicall6(SB),NOSPLIT,$0-88
JMP syscall·sysvicall6(SB) JMP syscall·sysvicall6(SB)
TEXT ·rawSysvicall6(SB),NOSPLIT,$0-64 TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
JMP syscall·rawSysvicall6(SB) JMP syscall·rawSysvicall6(SB)

35
vendor/golang.org/x/sys/unix/bluetooth_linux.go generated vendored Normal file
View File

@ -0,0 +1,35 @@
// Copyright 2016 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.
// Bluetooth sockets and messages
package unix
// Bluetooth Protocols
const (
BTPROTO_L2CAP = 0
BTPROTO_HCI = 1
BTPROTO_SCO = 2
BTPROTO_RFCOMM = 3
BTPROTO_BNEP = 4
BTPROTO_CMTP = 5
BTPROTO_HIDP = 6
BTPROTO_AVDTP = 7
)
const (
HCI_CHANNEL_RAW = 0
HCI_CHANNEL_USER = 1
HCI_CHANNEL_MONITOR = 2
HCI_CHANNEL_CONTROL = 3
)
// Socketoption Level
const (
SOL_BLUETOOTH = 0x112
SOL_HCI = 0x0
SOL_L2CAP = 0x6
SOL_RFCOMM = 0x12
SOL_SCO = 0x11
)

195
vendor/golang.org/x/sys/unix/cap_freebsd.go generated vendored Normal file
View File

@ -0,0 +1,195 @@
// Copyright 2017 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.
// +build freebsd
package unix
import (
errorspkg "errors"
"fmt"
)
// Go implementation of C mostly found in /usr/src/sys/kern/subr_capability.c
const (
// This is the version of CapRights this package understands. See C implementation for parallels.
capRightsGoVersion = CAP_RIGHTS_VERSION_00
capArSizeMin = CAP_RIGHTS_VERSION_00 + 2
capArSizeMax = capRightsGoVersion + 2
)
var (
bit2idx = []int{
-1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
}
)
func capidxbit(right uint64) int {
return int((right >> 57) & 0x1f)
}
func rightToIndex(right uint64) (int, error) {
idx := capidxbit(right)
if idx < 0 || idx >= len(bit2idx) {
return -2, fmt.Errorf("index for right 0x%x out of range", right)
}
return bit2idx[idx], nil
}
func caprver(right uint64) int {
return int(right >> 62)
}
func capver(rights *CapRights) int {
return caprver(rights.Rights[0])
}
func caparsize(rights *CapRights) int {
return capver(rights) + 2
}
// CapRightsSet sets the permissions in setrights in rights.
func CapRightsSet(rights *CapRights, setrights []uint64) error {
// This is essentially a copy of cap_rights_vset()
if capver(rights) != CAP_RIGHTS_VERSION_00 {
return fmt.Errorf("bad rights version %d", capver(rights))
}
n := caparsize(rights)
if n < capArSizeMin || n > capArSizeMax {
return errorspkg.New("bad rights size")
}
for _, right := range setrights {
if caprver(right) != CAP_RIGHTS_VERSION_00 {
return errorspkg.New("bad right version")
}
i, err := rightToIndex(right)
if err != nil {
return err
}
if i >= n {
return errorspkg.New("index overflow")
}
if capidxbit(rights.Rights[i]) != capidxbit(right) {
return errorspkg.New("index mismatch")
}
rights.Rights[i] |= right
if capidxbit(rights.Rights[i]) != capidxbit(right) {
return errorspkg.New("index mismatch (after assign)")
}
}
return nil
}
// CapRightsClear clears the permissions in clearrights from rights.
func CapRightsClear(rights *CapRights, clearrights []uint64) error {
// This is essentially a copy of cap_rights_vclear()
if capver(rights) != CAP_RIGHTS_VERSION_00 {
return fmt.Errorf("bad rights version %d", capver(rights))
}
n := caparsize(rights)
if n < capArSizeMin || n > capArSizeMax {
return errorspkg.New("bad rights size")
}
for _, right := range clearrights {
if caprver(right) != CAP_RIGHTS_VERSION_00 {
return errorspkg.New("bad right version")
}
i, err := rightToIndex(right)
if err != nil {
return err
}
if i >= n {
return errorspkg.New("index overflow")
}
if capidxbit(rights.Rights[i]) != capidxbit(right) {
return errorspkg.New("index mismatch")
}
rights.Rights[i] &= ^(right & 0x01FFFFFFFFFFFFFF)
if capidxbit(rights.Rights[i]) != capidxbit(right) {
return errorspkg.New("index mismatch (after assign)")
}
}
return nil
}
// CapRightsIsSet checks whether all the permissions in setrights are present in rights.
func CapRightsIsSet(rights *CapRights, setrights []uint64) (bool, error) {
// This is essentially a copy of cap_rights_is_vset()
if capver(rights) != CAP_RIGHTS_VERSION_00 {
return false, fmt.Errorf("bad rights version %d", capver(rights))
}
n := caparsize(rights)
if n < capArSizeMin || n > capArSizeMax {
return false, errorspkg.New("bad rights size")
}
for _, right := range setrights {
if caprver(right) != CAP_RIGHTS_VERSION_00 {
return false, errorspkg.New("bad right version")
}
i, err := rightToIndex(right)
if err != nil {
return false, err
}
if i >= n {
return false, errorspkg.New("index overflow")
}
if capidxbit(rights.Rights[i]) != capidxbit(right) {
return false, errorspkg.New("index mismatch")
}
if (rights.Rights[i] & right) != right {
return false, nil
}
}
return true, nil
}
func capright(idx uint64, bit uint64) uint64 {
return ((1 << (57 + idx)) | bit)
}
// CapRightsInit returns a pointer to an initialised CapRights structure filled with rights.
// See man cap_rights_init(3) and rights(4).
func CapRightsInit(rights []uint64) (*CapRights, error) {
var r CapRights
r.Rights[0] = (capRightsGoVersion << 62) | capright(0, 0)
r.Rights[1] = capright(1, 0)
err := CapRightsSet(&r, rights)
if err != nil {
return nil, err
}
return &r, nil
}
// CapRightsLimit reduces the operations permitted on fd to at most those contained in rights.
// The capability rights on fd can never be increased by CapRightsLimit.
// See man cap_rights_limit(2) and rights(4).
func CapRightsLimit(fd uintptr, rights *CapRights) error {
return capRightsLimit(int(fd), rights)
}
// CapRightsGet returns a CapRights structure containing the operations permitted on fd.
// See man cap_rights_get(3) and rights(4).
func CapRightsGet(fd uintptr) (*CapRights, error) {
r, err := CapRightsInit(nil)
if err != nil {
return nil, err
}
err = capRightsGet(capRightsGoVersion, int(fd), r)
if err != nil {
return nil, err
}
return r, nil
}

24
vendor/golang.org/x/sys/unix/dev_darwin.go generated vendored Normal file
View File

@ -0,0 +1,24 @@
// Copyright 2017 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.
// Functions to access/create device major and minor numbers matching the
// encoding used in Darwin's sys/types.h header.
package unix
// Major returns the major component of a Darwin device number.
func Major(dev uint64) uint32 {
return uint32((dev >> 24) & 0xff)
}
// Minor returns the minor component of a Darwin device number.
func Minor(dev uint64) uint32 {
return uint32(dev & 0xffffff)
}
// Mkdev returns a Darwin device number generated from the given major and minor
// components.
func Mkdev(major, minor uint32) uint64 {
return (uint64(major) << 24) | uint64(minor)
}

30
vendor/golang.org/x/sys/unix/dev_dragonfly.go generated vendored Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2017 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.
// Functions to access/create device major and minor numbers matching the
// encoding used in Dragonfly's sys/types.h header.
//
// The information below is extracted and adapted from sys/types.h:
//
// Minor gives a cookie instead of an index since in order to avoid changing the
// meanings of bits 0-15 or wasting time and space shifting bits 16-31 for
// devices that don't use them.
package unix
// Major returns the major component of a DragonFlyBSD device number.
func Major(dev uint64) uint32 {
return uint32((dev >> 8) & 0xff)
}
// Minor returns the minor component of a DragonFlyBSD device number.
func Minor(dev uint64) uint32 {
return uint32(dev & 0xffff00ff)
}
// Mkdev returns a DragonFlyBSD device number generated from the given major and
// minor components.
func Mkdev(major, minor uint32) uint64 {
return (uint64(major) << 8) | uint64(minor)
}

30
vendor/golang.org/x/sys/unix/dev_freebsd.go generated vendored Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2017 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.
// Functions to access/create device major and minor numbers matching the
// encoding used in FreeBSD's sys/types.h header.
//
// The information below is extracted and adapted from sys/types.h:
//
// Minor gives a cookie instead of an index since in order to avoid changing the
// meanings of bits 0-15 or wasting time and space shifting bits 16-31 for
// devices that don't use them.
package unix
// Major returns the major component of a FreeBSD device number.
func Major(dev uint64) uint32 {
return uint32((dev >> 8) & 0xff)
}
// Minor returns the minor component of a FreeBSD device number.
func Minor(dev uint64) uint32 {
return uint32(dev & 0xffff00ff)
}
// Mkdev returns a FreeBSD device number generated from the given major and
// minor components.
func Mkdev(major, minor uint32) uint64 {
return (uint64(major) << 8) | uint64(minor)
}

42
vendor/golang.org/x/sys/unix/dev_linux.go generated vendored Normal file
View File

@ -0,0 +1,42 @@
// Copyright 2017 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.
// Functions to access/create device major and minor numbers matching the
// encoding used by the Linux kernel and glibc.
//
// The information below is extracted and adapted from bits/sysmacros.h in the
// glibc sources:
//
// dev_t in glibc is 64-bit, with 32-bit major and minor numbers. glibc's
// default encoding is MMMM Mmmm mmmM MMmm, where M is a hex digit of the major
// number and m is a hex digit of the minor number. This is backward compatible
// with legacy systems where dev_t is 16 bits wide, encoded as MMmm. It is also
// backward compatible with the Linux kernel, which for some architectures uses
// 32-bit dev_t, encoded as mmmM MMmm.
package unix
// Major returns the major component of a Linux device number.
func Major(dev uint64) uint32 {
major := uint32((dev & 0x00000000000fff00) >> 8)
major |= uint32((dev & 0xfffff00000000000) >> 32)
return major
}
// Minor returns the minor component of a Linux device number.
func Minor(dev uint64) uint32 {
minor := uint32((dev & 0x00000000000000ff) >> 0)
minor |= uint32((dev & 0x00000ffffff00000) >> 12)
return minor
}
// Mkdev returns a Linux device number generated from the given major and minor
// components.
func Mkdev(major, minor uint32) uint64 {
dev := (uint64(major) & 0x00000fff) << 8
dev |= (uint64(major) & 0xfffff000) << 32
dev |= (uint64(minor) & 0x000000ff) << 0
dev |= (uint64(minor) & 0xffffff00) << 12
return dev
}

29
vendor/golang.org/x/sys/unix/dev_netbsd.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2017 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.
// Functions to access/create device major and minor numbers matching the
// encoding used in NetBSD's sys/types.h header.
package unix
// Major returns the major component of a NetBSD device number.
func Major(dev uint64) uint32 {
return uint32((dev & 0x000fff00) >> 8)
}
// Minor returns the minor component of a NetBSD device number.
func Minor(dev uint64) uint32 {
minor := uint32((dev & 0x000000ff) >> 0)
minor |= uint32((dev & 0xfff00000) >> 12)
return minor
}
// Mkdev returns a NetBSD device number generated from the given major and minor
// components.
func Mkdev(major, minor uint32) uint64 {
dev := (uint64(major) << 8) & 0x000fff00
dev |= (uint64(minor) << 12) & 0xfff00000
dev |= (uint64(minor) << 0) & 0x000000ff
return dev
}

29
vendor/golang.org/x/sys/unix/dev_openbsd.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2017 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.
// Functions to access/create device major and minor numbers matching the
// encoding used in OpenBSD's sys/types.h header.
package unix
// Major returns the major component of an OpenBSD device number.
func Major(dev uint64) uint32 {
return uint32((dev & 0x0000ff00) >> 8)
}
// Minor returns the minor component of an OpenBSD device number.
func Minor(dev uint64) uint32 {
minor := uint32((dev & 0x000000ff) >> 0)
minor |= uint32((dev & 0xffff0000) >> 8)
return minor
}
// Mkdev returns an OpenBSD device number generated from the given major and minor
// components.
func Mkdev(major, minor uint32) uint64 {
dev := (uint64(major) << 8) & 0x0000ff00
dev |= (uint64(minor) << 8) & 0xffff0000
dev |= (uint64(minor) << 0) & 0x000000ff
return dev
}

102
vendor/golang.org/x/sys/unix/dirent.go generated vendored Normal file
View File

@ -0,0 +1,102 @@
// Copyright 2009 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.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package unix
import "unsafe"
// readInt returns the size-bytes unsigned integer in native byte order at offset off.
func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
if len(b) < int(off+size) {
return 0, false
}
if isBigEndian {
return readIntBE(b[off:], size), true
}
return readIntLE(b[off:], size), true
}
func readIntBE(b []byte, size uintptr) uint64 {
switch size {
case 1:
return uint64(b[0])
case 2:
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[1]) | uint64(b[0])<<8
case 4:
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
case 8:
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
default:
panic("syscall: readInt with unsupported size")
}
}
func readIntLE(b []byte, size uintptr) uint64 {
switch size {
case 1:
return uint64(b[0])
case 2:
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8
case 4:
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
case 8:
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
default:
panic("syscall: readInt with unsupported size")
}
}
// ParseDirent parses up to max directory entries in buf,
// appending the names to names. It returns the number of
// bytes consumed from buf, the number of entries added
// to names, and the new names slice.
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
origlen := len(buf)
count = 0
for max != 0 && len(buf) > 0 {
reclen, ok := direntReclen(buf)
if !ok || reclen > uint64(len(buf)) {
return origlen, count, names
}
rec := buf[:reclen]
buf = buf[reclen:]
ino, ok := direntIno(rec)
if !ok {
break
}
if ino == 0 { // File absent in directory.
continue
}
const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
namlen, ok := direntNamlen(rec)
if !ok || namoff+namlen > uint64(len(rec)) {
break
}
name := rec[namoff : namoff+namlen]
for i, c := range name {
if c == 0 {
name = name[:i]
break
}
}
// Check for useless names before allocating a string.
if string(name) == "." || string(name) == ".." {
continue
}
max--
count++
names = append(names, string(name))
}
return origlen - len(buf), count, names
}

9
vendor/golang.org/x/sys/unix/endian_big.go generated vendored Normal file
View File

@ -0,0 +1,9 @@
// Copyright 2016 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.
//
// +build ppc64 s390x mips mips64
package unix
const isBigEndian = true

9
vendor/golang.org/x/sys/unix/endian_little.go generated vendored Normal file
View File

@ -0,0 +1,9 @@
// Copyright 2016 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.
//
// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le
package unix
const isBigEndian = false

227
vendor/golang.org/x/sys/unix/errors_freebsd_386.go generated vendored Normal file
View File

@ -0,0 +1,227 @@
// Copyright 2017 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.
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
// them here for backwards compatibility.
package unix
const (
IFF_SMART = 0x20
IFT_1822 = 0x2
IFT_A12MPPSWITCH = 0x82
IFT_AAL2 = 0xbb
IFT_AAL5 = 0x31
IFT_ADSL = 0x5e
IFT_AFLANE8023 = 0x3b
IFT_AFLANE8025 = 0x3c
IFT_ARAP = 0x58
IFT_ARCNET = 0x23
IFT_ARCNETPLUS = 0x24
IFT_ASYNC = 0x54
IFT_ATM = 0x25
IFT_ATMDXI = 0x69
IFT_ATMFUNI = 0x6a
IFT_ATMIMA = 0x6b
IFT_ATMLOGICAL = 0x50
IFT_ATMRADIO = 0xbd
IFT_ATMSUBINTERFACE = 0x86
IFT_ATMVCIENDPT = 0xc2
IFT_ATMVIRTUAL = 0x95
IFT_BGPPOLICYACCOUNTING = 0xa2
IFT_BSC = 0x53
IFT_CCTEMUL = 0x3d
IFT_CEPT = 0x13
IFT_CES = 0x85
IFT_CHANNEL = 0x46
IFT_CNR = 0x55
IFT_COFFEE = 0x84
IFT_COMPOSITELINK = 0x9b
IFT_DCN = 0x8d
IFT_DIGITALPOWERLINE = 0x8a
IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
IFT_DLSW = 0x4a
IFT_DOCSCABLEDOWNSTREAM = 0x80
IFT_DOCSCABLEMACLAYER = 0x7f
IFT_DOCSCABLEUPSTREAM = 0x81
IFT_DS0 = 0x51
IFT_DS0BUNDLE = 0x52
IFT_DS1FDL = 0xaa
IFT_DS3 = 0x1e
IFT_DTM = 0x8c
IFT_DVBASILN = 0xac
IFT_DVBASIOUT = 0xad
IFT_DVBRCCDOWNSTREAM = 0x93
IFT_DVBRCCMACLAYER = 0x92
IFT_DVBRCCUPSTREAM = 0x94
IFT_ENC = 0xf4
IFT_EON = 0x19
IFT_EPLRS = 0x57
IFT_ESCON = 0x49
IFT_ETHER = 0x6
IFT_FAITH = 0xf2
IFT_FAST = 0x7d
IFT_FASTETHER = 0x3e
IFT_FASTETHERFX = 0x45
IFT_FDDI = 0xf
IFT_FIBRECHANNEL = 0x38
IFT_FRAMERELAYINTERCONNECT = 0x3a
IFT_FRAMERELAYMPI = 0x5c
IFT_FRDLCIENDPT = 0xc1
IFT_FRELAY = 0x20
IFT_FRELAYDCE = 0x2c
IFT_FRF16MFRBUNDLE = 0xa3
IFT_FRFORWARD = 0x9e
IFT_G703AT2MB = 0x43
IFT_G703AT64K = 0x42
IFT_GIF = 0xf0
IFT_GIGABITETHERNET = 0x75
IFT_GR303IDT = 0xb2
IFT_GR303RDT = 0xb1
IFT_H323GATEKEEPER = 0xa4
IFT_H323PROXY = 0xa5
IFT_HDH1822 = 0x3
IFT_HDLC = 0x76
IFT_HDSL2 = 0xa8
IFT_HIPERLAN2 = 0xb7
IFT_HIPPI = 0x2f
IFT_HIPPIINTERFACE = 0x39
IFT_HOSTPAD = 0x5a
IFT_HSSI = 0x2e
IFT_HY = 0xe
IFT_IBM370PARCHAN = 0x48
IFT_IDSL = 0x9a
IFT_IEEE80211 = 0x47
IFT_IEEE80212 = 0x37
IFT_IEEE8023ADLAG = 0xa1
IFT_IFGSN = 0x91
IFT_IMT = 0xbe
IFT_INTERLEAVE = 0x7c
IFT_IP = 0x7e
IFT_IPFORWARD = 0x8e
IFT_IPOVERATM = 0x72
IFT_IPOVERCDLC = 0x6d
IFT_IPOVERCLAW = 0x6e
IFT_IPSWITCH = 0x4e
IFT_IPXIP = 0xf9
IFT_ISDN = 0x3f
IFT_ISDNBASIC = 0x14
IFT_ISDNPRIMARY = 0x15
IFT_ISDNS = 0x4b
IFT_ISDNU = 0x4c
IFT_ISO88022LLC = 0x29
IFT_ISO88023 = 0x7
IFT_ISO88024 = 0x8
IFT_ISO88025 = 0x9
IFT_ISO88025CRFPINT = 0x62
IFT_ISO88025DTR = 0x56
IFT_ISO88025FIBER = 0x73
IFT_ISO88026 = 0xa
IFT_ISUP = 0xb3
IFT_L3IPXVLAN = 0x89
IFT_LAPB = 0x10
IFT_LAPD = 0x4d
IFT_LAPF = 0x77
IFT_LOCALTALK = 0x2a
IFT_LOOP = 0x18
IFT_MEDIAMAILOVERIP = 0x8b
IFT_MFSIGLINK = 0xa7
IFT_MIOX25 = 0x26
IFT_MODEM = 0x30
IFT_MPC = 0x71
IFT_MPLS = 0xa6
IFT_MPLSTUNNEL = 0x96
IFT_MSDSL = 0x8f
IFT_MVL = 0xbf
IFT_MYRINET = 0x63
IFT_NFAS = 0xaf
IFT_NSIP = 0x1b
IFT_OPTICALCHANNEL = 0xc3
IFT_OPTICALTRANSPORT = 0xc4
IFT_OTHER = 0x1
IFT_P10 = 0xc
IFT_P80 = 0xd
IFT_PARA = 0x22
IFT_PFLOG = 0xf6
IFT_PFSYNC = 0xf7
IFT_PLC = 0xae
IFT_POS = 0xab
IFT_PPPMULTILINKBUNDLE = 0x6c
IFT_PROPBWAP2MP = 0xb8
IFT_PROPCNLS = 0x59
IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
IFT_PROPMUX = 0x36
IFT_PROPWIRELESSP2P = 0x9d
IFT_PTPSERIAL = 0x16
IFT_PVC = 0xf1
IFT_QLLC = 0x44
IFT_RADIOMAC = 0xbc
IFT_RADSL = 0x5f
IFT_REACHDSL = 0xc0
IFT_RFC1483 = 0x9f
IFT_RS232 = 0x21
IFT_RSRB = 0x4f
IFT_SDLC = 0x11
IFT_SDSL = 0x60
IFT_SHDSL = 0xa9
IFT_SIP = 0x1f
IFT_SLIP = 0x1c
IFT_SMDSDXI = 0x2b
IFT_SMDSICIP = 0x34
IFT_SONET = 0x27
IFT_SONETOVERHEADCHANNEL = 0xb9
IFT_SONETPATH = 0x32
IFT_SONETVT = 0x33
IFT_SRP = 0x97
IFT_SS7SIGLINK = 0x9c
IFT_STACKTOSTACK = 0x6f
IFT_STARLAN = 0xb
IFT_STF = 0xd7
IFT_T1 = 0x12
IFT_TDLC = 0x74
IFT_TERMPAD = 0x5b
IFT_TR008 = 0xb0
IFT_TRANSPHDLC = 0x7b
IFT_TUNNEL = 0x83
IFT_ULTRA = 0x1d
IFT_USB = 0xa0
IFT_V11 = 0x40
IFT_V35 = 0x2d
IFT_V36 = 0x41
IFT_V37 = 0x78
IFT_VDSL = 0x61
IFT_VIRTUALIPADDRESS = 0x70
IFT_VOICEEM = 0x64
IFT_VOICEENCAP = 0x67
IFT_VOICEFXO = 0x65
IFT_VOICEFXS = 0x66
IFT_VOICEOVERATM = 0x98
IFT_VOICEOVERFRAMERELAY = 0x99
IFT_VOICEOVERIP = 0x68
IFT_X213 = 0x5d
IFT_X25 = 0x5
IFT_X25DDN = 0x4
IFT_X25HUNTGROUP = 0x7a
IFT_X25MLP = 0x79
IFT_X25PLE = 0x28
IFT_XETHER = 0x1a
IPPROTO_MAXID = 0x34
IPV6_FAITH = 0x1d
IP_FAITH = 0x16
MAP_NORESERVE = 0x40
MAP_RENAME = 0x20
NET_RT_MAXID = 0x6
RTF_PRCLONING = 0x10000
RTM_OLDADD = 0x9
RTM_OLDDEL = 0xa
SIOCADDRT = 0x8030720a
SIOCALIFADDR = 0x8118691b
SIOCDELRT = 0x8030720b
SIOCDLIFADDR = 0x8118691d
SIOCGLIFADDR = 0xc118691c
SIOCGLIFPHYADDR = 0xc118694b
SIOCSLIFPHYADDR = 0x8118694a
)

227
vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go generated vendored Normal file
View File

@ -0,0 +1,227 @@
// Copyright 2017 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.
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
// them here for backwards compatibility.
package unix
const (
IFF_SMART = 0x20
IFT_1822 = 0x2
IFT_A12MPPSWITCH = 0x82
IFT_AAL2 = 0xbb
IFT_AAL5 = 0x31
IFT_ADSL = 0x5e
IFT_AFLANE8023 = 0x3b
IFT_AFLANE8025 = 0x3c
IFT_ARAP = 0x58
IFT_ARCNET = 0x23
IFT_ARCNETPLUS = 0x24
IFT_ASYNC = 0x54
IFT_ATM = 0x25
IFT_ATMDXI = 0x69
IFT_ATMFUNI = 0x6a
IFT_ATMIMA = 0x6b
IFT_ATMLOGICAL = 0x50
IFT_ATMRADIO = 0xbd
IFT_ATMSUBINTERFACE = 0x86
IFT_ATMVCIENDPT = 0xc2
IFT_ATMVIRTUAL = 0x95
IFT_BGPPOLICYACCOUNTING = 0xa2
IFT_BSC = 0x53
IFT_CCTEMUL = 0x3d
IFT_CEPT = 0x13
IFT_CES = 0x85
IFT_CHANNEL = 0x46
IFT_CNR = 0x55
IFT_COFFEE = 0x84
IFT_COMPOSITELINK = 0x9b
IFT_DCN = 0x8d
IFT_DIGITALPOWERLINE = 0x8a
IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
IFT_DLSW = 0x4a
IFT_DOCSCABLEDOWNSTREAM = 0x80
IFT_DOCSCABLEMACLAYER = 0x7f
IFT_DOCSCABLEUPSTREAM = 0x81
IFT_DS0 = 0x51
IFT_DS0BUNDLE = 0x52
IFT_DS1FDL = 0xaa
IFT_DS3 = 0x1e
IFT_DTM = 0x8c
IFT_DVBASILN = 0xac
IFT_DVBASIOUT = 0xad
IFT_DVBRCCDOWNSTREAM = 0x93
IFT_DVBRCCMACLAYER = 0x92
IFT_DVBRCCUPSTREAM = 0x94
IFT_ENC = 0xf4
IFT_EON = 0x19
IFT_EPLRS = 0x57
IFT_ESCON = 0x49
IFT_ETHER = 0x6
IFT_FAITH = 0xf2
IFT_FAST = 0x7d
IFT_FASTETHER = 0x3e
IFT_FASTETHERFX = 0x45
IFT_FDDI = 0xf
IFT_FIBRECHANNEL = 0x38
IFT_FRAMERELAYINTERCONNECT = 0x3a
IFT_FRAMERELAYMPI = 0x5c
IFT_FRDLCIENDPT = 0xc1
IFT_FRELAY = 0x20
IFT_FRELAYDCE = 0x2c
IFT_FRF16MFRBUNDLE = 0xa3
IFT_FRFORWARD = 0x9e
IFT_G703AT2MB = 0x43
IFT_G703AT64K = 0x42
IFT_GIF = 0xf0
IFT_GIGABITETHERNET = 0x75
IFT_GR303IDT = 0xb2
IFT_GR303RDT = 0xb1
IFT_H323GATEKEEPER = 0xa4
IFT_H323PROXY = 0xa5
IFT_HDH1822 = 0x3
IFT_HDLC = 0x76
IFT_HDSL2 = 0xa8
IFT_HIPERLAN2 = 0xb7
IFT_HIPPI = 0x2f
IFT_HIPPIINTERFACE = 0x39
IFT_HOSTPAD = 0x5a
IFT_HSSI = 0x2e
IFT_HY = 0xe
IFT_IBM370PARCHAN = 0x48
IFT_IDSL = 0x9a
IFT_IEEE80211 = 0x47
IFT_IEEE80212 = 0x37
IFT_IEEE8023ADLAG = 0xa1
IFT_IFGSN = 0x91
IFT_IMT = 0xbe
IFT_INTERLEAVE = 0x7c
IFT_IP = 0x7e
IFT_IPFORWARD = 0x8e
IFT_IPOVERATM = 0x72
IFT_IPOVERCDLC = 0x6d
IFT_IPOVERCLAW = 0x6e
IFT_IPSWITCH = 0x4e
IFT_IPXIP = 0xf9
IFT_ISDN = 0x3f
IFT_ISDNBASIC = 0x14
IFT_ISDNPRIMARY = 0x15
IFT_ISDNS = 0x4b
IFT_ISDNU = 0x4c
IFT_ISO88022LLC = 0x29
IFT_ISO88023 = 0x7
IFT_ISO88024 = 0x8
IFT_ISO88025 = 0x9
IFT_ISO88025CRFPINT = 0x62
IFT_ISO88025DTR = 0x56
IFT_ISO88025FIBER = 0x73
IFT_ISO88026 = 0xa
IFT_ISUP = 0xb3
IFT_L3IPXVLAN = 0x89
IFT_LAPB = 0x10
IFT_LAPD = 0x4d
IFT_LAPF = 0x77
IFT_LOCALTALK = 0x2a
IFT_LOOP = 0x18
IFT_MEDIAMAILOVERIP = 0x8b
IFT_MFSIGLINK = 0xa7
IFT_MIOX25 = 0x26
IFT_MODEM = 0x30
IFT_MPC = 0x71
IFT_MPLS = 0xa6
IFT_MPLSTUNNEL = 0x96
IFT_MSDSL = 0x8f
IFT_MVL = 0xbf
IFT_MYRINET = 0x63
IFT_NFAS = 0xaf
IFT_NSIP = 0x1b
IFT_OPTICALCHANNEL = 0xc3
IFT_OPTICALTRANSPORT = 0xc4
IFT_OTHER = 0x1
IFT_P10 = 0xc
IFT_P80 = 0xd
IFT_PARA = 0x22
IFT_PFLOG = 0xf6
IFT_PFSYNC = 0xf7
IFT_PLC = 0xae
IFT_POS = 0xab
IFT_PPPMULTILINKBUNDLE = 0x6c
IFT_PROPBWAP2MP = 0xb8
IFT_PROPCNLS = 0x59
IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
IFT_PROPMUX = 0x36
IFT_PROPWIRELESSP2P = 0x9d
IFT_PTPSERIAL = 0x16
IFT_PVC = 0xf1
IFT_QLLC = 0x44
IFT_RADIOMAC = 0xbc
IFT_RADSL = 0x5f
IFT_REACHDSL = 0xc0
IFT_RFC1483 = 0x9f
IFT_RS232 = 0x21
IFT_RSRB = 0x4f
IFT_SDLC = 0x11
IFT_SDSL = 0x60
IFT_SHDSL = 0xa9
IFT_SIP = 0x1f
IFT_SLIP = 0x1c
IFT_SMDSDXI = 0x2b
IFT_SMDSICIP = 0x34
IFT_SONET = 0x27
IFT_SONETOVERHEADCHANNEL = 0xb9
IFT_SONETPATH = 0x32
IFT_SONETVT = 0x33
IFT_SRP = 0x97
IFT_SS7SIGLINK = 0x9c
IFT_STACKTOSTACK = 0x6f
IFT_STARLAN = 0xb
IFT_STF = 0xd7
IFT_T1 = 0x12
IFT_TDLC = 0x74
IFT_TERMPAD = 0x5b
IFT_TR008 = 0xb0
IFT_TRANSPHDLC = 0x7b
IFT_TUNNEL = 0x83
IFT_ULTRA = 0x1d
IFT_USB = 0xa0
IFT_V11 = 0x40
IFT_V35 = 0x2d
IFT_V36 = 0x41
IFT_V37 = 0x78
IFT_VDSL = 0x61
IFT_VIRTUALIPADDRESS = 0x70
IFT_VOICEEM = 0x64
IFT_VOICEENCAP = 0x67
IFT_VOICEFXO = 0x65
IFT_VOICEFXS = 0x66
IFT_VOICEOVERATM = 0x98
IFT_VOICEOVERFRAMERELAY = 0x99
IFT_VOICEOVERIP = 0x68
IFT_X213 = 0x5d
IFT_X25 = 0x5
IFT_X25DDN = 0x4
IFT_X25HUNTGROUP = 0x7a
IFT_X25MLP = 0x79
IFT_X25PLE = 0x28
IFT_XETHER = 0x1a
IPPROTO_MAXID = 0x34
IPV6_FAITH = 0x1d
IP_FAITH = 0x16
MAP_NORESERVE = 0x40
MAP_RENAME = 0x20
NET_RT_MAXID = 0x6
RTF_PRCLONING = 0x10000
RTM_OLDADD = 0x9
RTM_OLDDEL = 0xa
SIOCADDRT = 0x8040720a
SIOCALIFADDR = 0x8118691b
SIOCDELRT = 0x8040720b
SIOCDLIFADDR = 0x8118691d
SIOCGLIFADDR = 0xc118691c
SIOCGLIFPHYADDR = 0xc118694b
SIOCSLIFPHYADDR = 0x8118694a
)

226
vendor/golang.org/x/sys/unix/errors_freebsd_arm.go generated vendored Normal file
View File

@ -0,0 +1,226 @@
// Copyright 2017 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 unix
const (
IFT_1822 = 0x2
IFT_A12MPPSWITCH = 0x82
IFT_AAL2 = 0xbb
IFT_AAL5 = 0x31
IFT_ADSL = 0x5e
IFT_AFLANE8023 = 0x3b
IFT_AFLANE8025 = 0x3c
IFT_ARAP = 0x58
IFT_ARCNET = 0x23
IFT_ARCNETPLUS = 0x24
IFT_ASYNC = 0x54
IFT_ATM = 0x25
IFT_ATMDXI = 0x69
IFT_ATMFUNI = 0x6a
IFT_ATMIMA = 0x6b
IFT_ATMLOGICAL = 0x50
IFT_ATMRADIO = 0xbd
IFT_ATMSUBINTERFACE = 0x86
IFT_ATMVCIENDPT = 0xc2
IFT_ATMVIRTUAL = 0x95
IFT_BGPPOLICYACCOUNTING = 0xa2
IFT_BSC = 0x53
IFT_CCTEMUL = 0x3d
IFT_CEPT = 0x13
IFT_CES = 0x85
IFT_CHANNEL = 0x46
IFT_CNR = 0x55
IFT_COFFEE = 0x84
IFT_COMPOSITELINK = 0x9b
IFT_DCN = 0x8d
IFT_DIGITALPOWERLINE = 0x8a
IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
IFT_DLSW = 0x4a
IFT_DOCSCABLEDOWNSTREAM = 0x80
IFT_DOCSCABLEMACLAYER = 0x7f
IFT_DOCSCABLEUPSTREAM = 0x81
IFT_DS0 = 0x51
IFT_DS0BUNDLE = 0x52
IFT_DS1FDL = 0xaa
IFT_DS3 = 0x1e
IFT_DTM = 0x8c
IFT_DVBASILN = 0xac
IFT_DVBASIOUT = 0xad
IFT_DVBRCCDOWNSTREAM = 0x93
IFT_DVBRCCMACLAYER = 0x92
IFT_DVBRCCUPSTREAM = 0x94
IFT_ENC = 0xf4
IFT_EON = 0x19
IFT_EPLRS = 0x57
IFT_ESCON = 0x49
IFT_ETHER = 0x6
IFT_FAST = 0x7d
IFT_FASTETHER = 0x3e
IFT_FASTETHERFX = 0x45
IFT_FDDI = 0xf
IFT_FIBRECHANNEL = 0x38
IFT_FRAMERELAYINTERCONNECT = 0x3a
IFT_FRAMERELAYMPI = 0x5c
IFT_FRDLCIENDPT = 0xc1
IFT_FRELAY = 0x20
IFT_FRELAYDCE = 0x2c
IFT_FRF16MFRBUNDLE = 0xa3
IFT_FRFORWARD = 0x9e
IFT_G703AT2MB = 0x43
IFT_G703AT64K = 0x42
IFT_GIF = 0xf0
IFT_GIGABITETHERNET = 0x75
IFT_GR303IDT = 0xb2
IFT_GR303RDT = 0xb1
IFT_H323GATEKEEPER = 0xa4
IFT_H323PROXY = 0xa5
IFT_HDH1822 = 0x3
IFT_HDLC = 0x76
IFT_HDSL2 = 0xa8
IFT_HIPERLAN2 = 0xb7
IFT_HIPPI = 0x2f
IFT_HIPPIINTERFACE = 0x39
IFT_HOSTPAD = 0x5a
IFT_HSSI = 0x2e
IFT_HY = 0xe
IFT_IBM370PARCHAN = 0x48
IFT_IDSL = 0x9a
IFT_IEEE80211 = 0x47
IFT_IEEE80212 = 0x37
IFT_IEEE8023ADLAG = 0xa1
IFT_IFGSN = 0x91
IFT_IMT = 0xbe
IFT_INTERLEAVE = 0x7c
IFT_IP = 0x7e
IFT_IPFORWARD = 0x8e
IFT_IPOVERATM = 0x72
IFT_IPOVERCDLC = 0x6d
IFT_IPOVERCLAW = 0x6e
IFT_IPSWITCH = 0x4e
IFT_ISDN = 0x3f
IFT_ISDNBASIC = 0x14
IFT_ISDNPRIMARY = 0x15
IFT_ISDNS = 0x4b
IFT_ISDNU = 0x4c
IFT_ISO88022LLC = 0x29
IFT_ISO88023 = 0x7
IFT_ISO88024 = 0x8
IFT_ISO88025 = 0x9
IFT_ISO88025CRFPINT = 0x62
IFT_ISO88025DTR = 0x56
IFT_ISO88025FIBER = 0x73
IFT_ISO88026 = 0xa
IFT_ISUP = 0xb3
IFT_L3IPXVLAN = 0x89
IFT_LAPB = 0x10
IFT_LAPD = 0x4d
IFT_LAPF = 0x77
IFT_LOCALTALK = 0x2a
IFT_LOOP = 0x18
IFT_MEDIAMAILOVERIP = 0x8b
IFT_MFSIGLINK = 0xa7
IFT_MIOX25 = 0x26
IFT_MODEM = 0x30
IFT_MPC = 0x71
IFT_MPLS = 0xa6
IFT_MPLSTUNNEL = 0x96
IFT_MSDSL = 0x8f
IFT_MVL = 0xbf
IFT_MYRINET = 0x63
IFT_NFAS = 0xaf
IFT_NSIP = 0x1b
IFT_OPTICALCHANNEL = 0xc3
IFT_OPTICALTRANSPORT = 0xc4
IFT_OTHER = 0x1
IFT_P10 = 0xc
IFT_P80 = 0xd
IFT_PARA = 0x22
IFT_PFLOG = 0xf6
IFT_PFSYNC = 0xf7
IFT_PLC = 0xae
IFT_POS = 0xab
IFT_PPPMULTILINKBUNDLE = 0x6c
IFT_PROPBWAP2MP = 0xb8
IFT_PROPCNLS = 0x59
IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
IFT_PROPMUX = 0x36
IFT_PROPWIRELESSP2P = 0x9d
IFT_PTPSERIAL = 0x16
IFT_PVC = 0xf1
IFT_QLLC = 0x44
IFT_RADIOMAC = 0xbc
IFT_RADSL = 0x5f
IFT_REACHDSL = 0xc0
IFT_RFC1483 = 0x9f
IFT_RS232 = 0x21
IFT_RSRB = 0x4f
IFT_SDLC = 0x11
IFT_SDSL = 0x60
IFT_SHDSL = 0xa9
IFT_SIP = 0x1f
IFT_SLIP = 0x1c
IFT_SMDSDXI = 0x2b
IFT_SMDSICIP = 0x34
IFT_SONET = 0x27
IFT_SONETOVERHEADCHANNEL = 0xb9
IFT_SONETPATH = 0x32
IFT_SONETVT = 0x33
IFT_SRP = 0x97
IFT_SS7SIGLINK = 0x9c
IFT_STACKTOSTACK = 0x6f
IFT_STARLAN = 0xb
IFT_STF = 0xd7
IFT_T1 = 0x12
IFT_TDLC = 0x74
IFT_TERMPAD = 0x5b
IFT_TR008 = 0xb0
IFT_TRANSPHDLC = 0x7b
IFT_TUNNEL = 0x83
IFT_ULTRA = 0x1d
IFT_USB = 0xa0
IFT_V11 = 0x40
IFT_V35 = 0x2d
IFT_V36 = 0x41
IFT_V37 = 0x78
IFT_VDSL = 0x61
IFT_VIRTUALIPADDRESS = 0x70
IFT_VOICEEM = 0x64
IFT_VOICEENCAP = 0x67
IFT_VOICEFXO = 0x65
IFT_VOICEFXS = 0x66
IFT_VOICEOVERATM = 0x98
IFT_VOICEOVERFRAMERELAY = 0x99
IFT_VOICEOVERIP = 0x68
IFT_X213 = 0x5d
IFT_X25 = 0x5
IFT_X25DDN = 0x4
IFT_X25HUNTGROUP = 0x7a
IFT_X25MLP = 0x79
IFT_X25PLE = 0x28
IFT_XETHER = 0x1a
// missing constants on FreeBSD-11.1-RELEASE, copied from old values in ztypes_freebsd_arm.go
IFF_SMART = 0x20
IFT_FAITH = 0xf2
IFT_IPXIP = 0xf9
IPPROTO_MAXID = 0x34
IPV6_FAITH = 0x1d
IP_FAITH = 0x16
MAP_NORESERVE = 0x40
MAP_RENAME = 0x20
NET_RT_MAXID = 0x6
RTF_PRCLONING = 0x10000
RTM_OLDADD = 0x9
RTM_OLDDEL = 0xa
SIOCADDRT = 0x8030720a
SIOCALIFADDR = 0x8118691b
SIOCDELRT = 0x8030720b
SIOCDLIFADDR = 0x8118691d
SIOCGLIFADDR = 0xc118691c
SIOCGLIFPHYADDR = 0xc118694b
SIOCSLIFPHYADDR = 0x8118694a
)

27
vendor/golang.org/x/sys/unix/file_unix.go generated vendored Normal file
View File

@ -0,0 +1,27 @@
// Copyright 2017 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 unix
import (
"os"
"syscall"
)
// FIXME: unexported function from os
// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
func syscallMode(i os.FileMode) (o uint32) {
o |= uint32(i.Perm())
if i&os.ModeSetuid != 0 {
o |= syscall.S_ISUID
}
if i&os.ModeSetgid != 0 {
o |= syscall.S_ISGID
}
if i&os.ModeSticky != 0 {
o |= syscall.S_ISVTX
}
// No mapping for Go's ModeTemporary (plan9 only).
return
}

View File

@ -1,5 +1,3 @@
// +build linux darwin freebsd openbsd netbsd dragonfly
// Copyright 2014 The Go Authors. All rights reserved. // Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
// +build linux,386 linux,arm // +build linux,386 linux,arm linux,mips linux,mipsle
// Copyright 2014 The Go Authors. All rights reserved. // Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style

88
vendor/golang.org/x/sys/unix/mkpost.go generated vendored Normal file
View File

@ -0,0 +1,88 @@
// Copyright 2016 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.
// +build ignore
// mkpost processes the output of cgo -godefs to
// modify the generated types. It is used to clean up
// the sys API in an architecture specific manner.
//
// mkpost is run after cgo -godefs; see README.md.
package main
import (
"bytes"
"fmt"
"go/format"
"io/ioutil"
"log"
"os"
"regexp"
)
func main() {
// Get the OS and architecture (using GOARCH_TARGET if it exists)
goos := os.Getenv("GOOS")
goarch := os.Getenv("GOARCH_TARGET")
if goarch == "" {
goarch = os.Getenv("GOARCH")
}
// Check that we are using the new build system if we should be.
if goos == "linux" && goarch != "sparc64" {
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
os.Stderr.WriteString("In the new build system, mkpost should not be called directly.\n")
os.Stderr.WriteString("See README.md\n")
os.Exit(1)
}
}
b, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatal(err)
}
// If we have empty Ptrace structs, we should delete them. Only s390x emits
// nonempty Ptrace structs.
ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`)
b = ptraceRexexp.ReplaceAll(b, nil)
// Replace the control_regs union with a blank identifier for now.
controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`)
b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64"))
// Remove fields that are added by glibc
// Note that this is unstable as the identifers are private.
removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`)
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
// We refuse to export private fields on s390x
if goarch == "s390x" && goos == "linux" {
// Remove cgo padding fields
removeFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`)
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
// Remove padding, hidden, or unused fields
removeFieldsRegex = regexp.MustCompile(`X_\S+`)
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
}
// Remove the first line of warning from cgo
b = b[bytes.IndexByte(b, '\n')+1:]
// Modify the command in the header to include:
// mkpost, our own warning, and a build tag.
replacement := fmt.Sprintf(`$1 | go run mkpost.go
// Code generated by the command above; see README.md. DO NOT EDIT.
// +build %s,%s`, goarch, goos)
cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`)
b = cgoCommandRegex.ReplaceAll(b, []byte(replacement))
// gofmt
b, err = format.Source(b)
if err != nil {
log.Fatal(err)
}
os.Stdout.Write(b)
}

38
vendor/golang.org/x/sys/unix/openbsd_pledge.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
// Copyright 2016 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.
// +build openbsd
// +build 386 amd64 arm
package unix
import (
"syscall"
"unsafe"
)
const (
SYS_PLEDGE = 108
)
// Pledge implements the pledge syscall. For more information see pledge(2).
func Pledge(promises string, paths []string) error {
promisesPtr, err := syscall.BytePtrFromString(promises)
if err != nil {
return err
}
promisesUnsafe, pathsUnsafe := unsafe.Pointer(promisesPtr), unsafe.Pointer(nil)
if paths != nil {
var pathsPtr []*byte
if pathsPtr, err = syscall.SlicePtrFromStrings(paths); err != nil {
return err
}
pathsUnsafe = unsafe.Pointer(&pathsPtr[0])
}
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(promisesUnsafe), uintptr(pathsUnsafe), 0)
if e != 0 {
return e
}
return nil
}

15
vendor/golang.org/x/sys/unix/pagesize_unix.go generated vendored Normal file
View File

@ -0,0 +1,15 @@
// Copyright 2017 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.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// For Unix, get the pagesize from the runtime.
package unix
import "syscall"
func Getpagesize() int {
return syscall.Getpagesize()
}

View File

@ -1,4 +1,4 @@
// Copyright 2011 The Go Authors. All rights reserved. // Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -13,9 +13,10 @@ import "unsafe"
// Round the length of a raw sockaddr up to align it properly. // Round the length of a raw sockaddr up to align it properly.
func cmsgAlignOf(salen int) int { func cmsgAlignOf(salen int) int {
salign := sizeofPtr salign := sizeofPtr
// NOTE: It seems like 64-bit Darwin and DragonFly BSD kernels // NOTE: It seems like 64-bit Darwin, DragonFly BSD and
// still require 32-bit aligned access to network subsystem. // Solaris kernels still require 32-bit aligned access to
if darwin64Bit || dragonfly64Bit { // network subsystem.
if darwin64Bit || dragonfly64Bit || solaris64Bit {
salign = 4 salign = 4
} }
return (salen + salign - 1) & ^(salign - 1) return (salen + salign - 1) & ^(salign - 1)
@ -62,7 +63,7 @@ func ParseSocketControlMessage(b []byte) ([]SocketControlMessage, error) {
func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) { func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) {
h := (*Cmsghdr)(unsafe.Pointer(&b[0])) h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
if h.Len < SizeofCmsghdr || int(h.Len) > len(b) { if h.Len < SizeofCmsghdr || uint64(h.Len) > uint64(len(b)) {
return nil, nil, EINVAL return nil, nil, EINVAL
} }
return h, b[cmsgAlignOf(SizeofCmsghdr):h.Len], nil return h, b[cmsgAlignOf(SizeofCmsghdr):h.Len], nil

View File

@ -21,8 +21,6 @@
// holds a value of type syscall.Errno. // holds a value of type syscall.Errno.
package unix // import "golang.org/x/sys/unix" package unix // import "golang.org/x/sys/unix"
import "unsafe"
// ByteSliceFromString returns a NUL-terminated slice of bytes // ByteSliceFromString returns a NUL-terminated slice of bytes
// containing the text of s. If s contains a NUL byte at any // containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, EINVAL). // location, it returns (nil, EINVAL).
@ -68,7 +66,4 @@ func (tv *Timeval) Nano() int64 {
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000 return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
} }
// use is a no-op, but the compiler cannot see that it is. func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
// Calling use(p) ensures that p is kept live until that point.
//go:noescape
func use(p unsafe.Pointer)

View File

@ -470,25 +470,11 @@ func Sysctl(name string) (string, error) {
} }
func SysctlArgs(name string, args ...int) (string, error) { func SysctlArgs(name string, args ...int) (string, error) {
mib, err := sysctlmib(name, args...) buf, err := SysctlRaw(name, args...)
if err != nil { if err != nil {
return "", err return "", err
} }
n := len(buf)
// Find size.
n := uintptr(0)
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
return "", err
}
if n == 0 {
return "", nil
}
// Read into buffer of that size.
buf := make([]byte, n)
if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil {
return "", err
}
// Throw away terminating NUL. // Throw away terminating NUL.
if n > 0 && buf[n-1] == '\x00' { if n > 0 && buf[n-1] == '\x00' {
@ -575,13 +561,19 @@ func Utimes(path string, tv []Timeval) error {
func UtimesNano(path string, ts []Timespec) error { func UtimesNano(path string, ts []Timespec) error {
if ts == nil { if ts == nil {
err := utimensat(AT_FDCWD, path, nil, 0)
if err != ENOSYS {
return err
}
return utimes(path, nil) return utimes(path, nil)
} }
// TODO: The BSDs can do utimensat with SYS_UTIMENSAT but it
// isn't supported by darwin so this uses utimes instead
if len(ts) != 2 { if len(ts) != 2 {
return EINVAL return EINVAL
} }
err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
if err != ENOSYS {
return err
}
// Not as efficient as it could be because Timespec and // Not as efficient as it could be because Timespec and
// Timeval have different types in the different OSes // Timeval have different types in the different OSes
tv := [2]Timeval{ tv := [2]Timeval{
@ -591,6 +583,16 @@ func UtimesNano(path string, ts []Timespec) error {
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
} }
func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
if ts == nil {
return utimensat(dirfd, path, nil, flags)
}
if len(ts) != 2 {
return EINVAL
}
return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
}
//sys futimes(fd int, timeval *[2]Timeval) (err error) //sys futimes(fd int, timeval *[2]Timeval) (err error)
func Futimes(fd int, tv []Timeval) error { func Futimes(fd int, tv []Timeval) error {
@ -608,9 +610,6 @@ func Futimes(fd int, tv []Timeval) error {
// TODO: wrap // TODO: wrap
// Acct(name nil-string) (err error) // Acct(name nil-string) (err error)
// Gethostuuid(uuid *byte, timeout *Timespec) (err error) // Gethostuuid(uuid *byte, timeout *Timespec) (err error)
// Madvise(addr *byte, len int, behav int) (err error)
// Mprotect(addr *byte, len int, prot int) (err error)
// Msync(addr *byte, len int, flags int) (err error)
// Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, err error) // Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, err error)
var mapper = &mmapper{ var mapper = &mmapper{
@ -626,3 +625,11 @@ func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, e
func Munmap(b []byte) (err error) { func Munmap(b []byte) (err error) {
return mapper.Munmap(b) return mapper.Munmap(b)
} }
//sys Madvise(b []byte, behav int) (err error)
//sys Mlock(b []byte) (err error)
//sys Mlockall(flags int) (err error)
//sys Mprotect(b []byte, prot int) (err error)
//sys Msync(b []byte, flags int) (err error)
//sys Munlock(b []byte) (err error)
//sys Munlockall() (err error)

View File

@ -76,32 +76,16 @@ func nametomib(name string) (mib []_C_int, err error) {
return buf[0 : n/siz], nil return buf[0 : n/siz], nil
} }
// ParseDirent parses up to max directory entries in buf, func direntIno(buf []byte) (uint64, bool) {
// appending the names to names. It returns the number return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
// bytes consumed from buf, the number of entries added }
// to names, and the new names slice.
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) { func direntReclen(buf []byte) (uint64, bool) {
origlen := len(buf) return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
for max != 0 && len(buf) > 0 { }
dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
if dirent.Reclen == 0 { func direntNamlen(buf []byte) (uint64, bool) {
buf = nil return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
break
}
buf = buf[dirent.Reclen:]
if dirent.Ino == 0 { // File absent in directory.
continue
}
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
var name = string(bytes[0:dirent.Namlen])
if name == "." || name == ".." { // Useless names
continue
}
max--
count++
names = append(names, name)
}
return origlen - len(buf), count, names
} }
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) //sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
@ -203,6 +187,11 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
return return
} }
func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error {
// Darwin doesn't support SYS_UTIMENSAT
return ENOSYS
}
/* /*
* Wrapped * Wrapped
*/ */
@ -211,6 +200,45 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(signum), 1) } func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(signum), 1) }
//sys ioctl(fd int, req uint, arg uintptr) (err error)
// ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
func IoctlSetTermios(fd int, req uint, value *Termios) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
func IoctlGetInt(fd int, req uint) (int, error) {
var value int
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
/* /*
* Exposed directly * Exposed directly
*/ */
@ -226,10 +254,13 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig
//sys Dup2(from int, to int) (err error) //sys Dup2(from int, to int) (err error)
//sys Exchangedata(path1 string, path2 string, options int) (err error) //sys Exchangedata(path1 string, path2 string, options int) (err error)
//sys Exit(code int) //sys Exit(code int)
//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
//sys Fchdir(fd int) (err error) //sys Fchdir(fd int) (err error)
//sys Fchflags(fd int, flags int) (err error) //sys Fchflags(fd int, flags int) (err error)
//sys Fchmod(fd int, mode uint32) (err error) //sys Fchmod(fd int, mode uint32) (err error)
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
//sys Flock(fd int, how int) (err error) //sys Flock(fd int, how int) (err error)
//sys Fpathconf(fd int, name int) (val int, err error) //sys Fpathconf(fd int, name int) (val int, err error)
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
@ -254,23 +285,23 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig
//sys Kqueue() (fd int, err error) //sys Kqueue() (fd int, err error)
//sys Lchown(path string, uid int, gid int) (err error) //sys Lchown(path string, uid int, gid int) (err error)
//sys Link(path string, link string) (err error) //sys Link(path string, link string) (err error)
//sys Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error)
//sys Listen(s int, backlog int) (err error) //sys Listen(s int, backlog int) (err error)
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys Mkdir(path string, mode uint32) (err error) //sys Mkdir(path string, mode uint32) (err error)
//sys Mkdirat(dirfd int, path string, mode uint32) (err error)
//sys Mkfifo(path string, mode uint32) (err error) //sys Mkfifo(path string, mode uint32) (err error)
//sys Mknod(path string, mode uint32, dev int) (err error) //sys Mknod(path string, mode uint32, dev int) (err error)
//sys Mlock(b []byte) (err error)
//sys Mlockall(flags int) (err error)
//sys Mprotect(b []byte, prot int) (err error)
//sys Munlock(b []byte) (err error)
//sys Munlockall() (err error)
//sys Open(path string, mode int, perm uint32) (fd int, err error) //sys Open(path string, mode int, perm uint32) (fd int, err error)
//sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error)
//sys Pathconf(path string, name int) (val int, err error) //sys Pathconf(path string, name int) (val int, err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) //sys Pread(fd int, p []byte, offset int64) (n int, err error)
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) //sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys read(fd int, p []byte) (n int, err error) //sys read(fd int, p []byte) (n int, err error)
//sys Readlink(path string, buf []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error)
//sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error)
//sys Rename(from string, to string) (err error) //sys Rename(from string, to string) (err error)
//sys Renameat(fromfd int, from string, tofd int, to string) (err error)
//sys Revoke(path string) (err error) //sys Revoke(path string) (err error)
//sys Rmdir(path string) (err error) //sys Rmdir(path string) (err error)
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
@ -291,11 +322,13 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64 //sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64
//sys Symlink(path string, link string) (err error) //sys Symlink(path string, link string) (err error)
//sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error)
//sys Sync() (err error) //sys Sync() (err error)
//sys Truncate(path string, length int64) (err error) //sys Truncate(path string, length int64) (err error)
//sys Umask(newmask int) (oldmask int) //sys Umask(newmask int) (oldmask int)
//sys Undelete(path string) (err error) //sys Undelete(path string) (err error)
//sys Unlink(path string) (err error) //sys Unlink(path string) (err error)
//sys Unlinkat(dirfd int, path string, flags int) (err error)
//sys Unmount(path string, flags int) (err error) //sys Unmount(path string, flags int) (err error)
//sys write(fd int, p []byte) (n int, err error) //sys write(fd int, p []byte) (n int, err error)
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
@ -335,9 +368,6 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig
// Add_profil // Add_profil
// Kdebug_trace // Kdebug_trace
// Sigreturn // Sigreturn
// Mmap
// Mlock
// Munlock
// Atsocket // Atsocket
// Kqueue_from_portset_np // Kqueue_from_portset_np
// Kqueue_portset // Kqueue_portset
@ -430,8 +460,6 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig
// Lio_listio // Lio_listio
// __pthread_cond_wait // __pthread_cond_wait
// Iopolicysys // Iopolicysys
// Mlockall
// Munlockall
// __pthread_kill // __pthread_kill
// __pthread_sigmask // __pthread_sigmask
// __sigwait // __sigwait
@ -485,7 +513,6 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig
// Sendmsg_nocancel // Sendmsg_nocancel
// Recvfrom_nocancel // Recvfrom_nocancel
// Accept_nocancel // Accept_nocancel
// Msync_nocancel
// Fcntl_nocancel // Fcntl_nocancel
// Select_nocancel // Select_nocancel
// Fsync_nocancel // Fsync_nocancel

View File

@ -11,8 +11,6 @@ import (
"unsafe" "unsafe"
) )
func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
@ -21,8 +19,6 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3) tv.Usec = int32(nsec % 1e9 / 1e3)

View File

@ -11,10 +11,6 @@ import (
"unsafe" "unsafe"
) )
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
@ -23,8 +19,6 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3) tv.Usec = int32(nsec % 1e9 / 1e3)

View File

@ -9,8 +9,6 @@ import (
"unsafe" "unsafe"
) )
func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
@ -19,8 +17,6 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3) tv.Usec = int32(nsec % 1e9 / 1e3)

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