1
0
mirror of https://github.com/strongdm/comply synced 2025-12-06 14:24:12 +00:00

chore: migrate to go modules

This commit is contained in:
Carlos C
2019-07-14 13:51:10 -03:00
parent 87e8266f1b
commit c303b68201
125 changed files with 7334 additions and 2443 deletions

2
vendor/github.com/voxelbrain/goptions/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,2 @@
*.swp
.DS_Store

96
vendor/github.com/voxelbrain/goptions/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,96 @@
# Changelog
## 2.5.6
### Bug fixes
* Unexported fields are now ignored
### Minor changes
* Examples for Verbs and Remainder in documentation
## 2.5.4
### Bugfixes
* Fix typo in documentation
## 2.5.3
### Bugfixes
* Remove placeholders from LICENSE
* Add CONTROBUTORS
## 2.5.2
### Bugfixes
* Bring `examples/readme_example.go` and `README.md` up to date
* Rewrite formatter
## 2.5.1
### Bugfixes
* Make arrays of `goptions.Marshaler` work
## 2.5.0
### New features
* Add support for `int32` and `int64`
* Add support for `float32` and `float64`
### Bugfixes
* Fix a bug where the name of a unknown type would not be properly
printed
* Fix checks whether to use `os.Stdin` or `os.Stdout` when "-" is given for a
`*os.File`
* Fix an test example where the output to `os.Stderr` is apparently
not evaluated anymore.
## 2.4.1
### Bugfixes
* Code was not compilable due to temporary [maintainer](http://github.com/surma) idiocy
(Thanks [akrennmair](http://github.com/akrennmair))
## 2.4.0
### New features
* Gave `goptions.FlagSet` a `ParseAndFail()` method
## 2.3.0
### New features
* Add support for `time.Duration`
## 2.2.0
### New features
* Add support for `*net.TCPAddr`
* Add support for `*net/url.URL`
### Bugfixes
* Fix behaviour of `[]bool` fields
## 2.1.0
### New features
* `goptions.Verbs` is of type `string` and will have selected verb name as value
after parsing.
## 2.0.0
### Breaking changes
* Disallow multiple flag names for one member
* Remove `accumulate` option in favor of generic array support
### New features
* Add convenience function `ParseAndFail` to make common usage of the library
a one-liner (see `readme_example.go`)
* Add a `Marshaler` interface to enable thrid-party types
* Add support for slices (and thereby for mutiple flag definitions)
### Minor changes
* Refactoring to get more flexibility
* Make a flag's default value accessible in the template context

View File

@@ -0,0 +1,7 @@
Contributors
============
These people have contributed to goptions's design and implementation:
* Andreas Krennmair <https://github.com/akrennmair>
* GDG Berlin Golang <https://gplus.to/gdgberlingolang>

24
vendor/github.com/voxelbrain/goptions/LICENSE.txt generated vendored Normal file
View File

@@ -0,0 +1,24 @@
Copyright (c) 2012-2013, voxelbrain UG, Germany
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the voxelbrain UG nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL voxelbrain UG BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

114
vendor/github.com/voxelbrain/goptions/README.md generated vendored Normal file
View File

@@ -0,0 +1,114 @@
`goptions` implements a flexible parser for command line options.
Key targets were the support for both long and short flag versions, mutually
exclusive flags, and verbs. Flags and their corresponding variables are defined
by the tags in a (possibly anonymous) struct.
![](https://circleci.com/gh/voxelbrain/goptions.png?circle-token=27cd98362d475cfa8c586565b659b2204733f25c)
# Example
```go
package main
import (
"github.com/voxelbrain/goptions"
"os"
"time"
)
func main() {
options := struct {
Servers []string `goptions:"-s, --server, obligatory, description='Servers to connect to'"`
Password string `goptions:"-p, --password, description='Don\\'t prompt for password'"`
Timeout time.Duration `goptions:"-t, --timeout, description='Connection timeout in seconds'"`
Help goptions.Help `goptions:"-h, --help, description='Show this help'"`
goptions.Verbs
Execute struct {
Command string `goptions:"--command, mutexgroup='input', description='Command to exectute', obligatory"`
Script *os.File `goptions:"--script, mutexgroup='input', description='Script to exectute', rdonly"`
} `goptions:"execute"`
Delete struct {
Path string `goptions:"-n, --name, obligatory, description='Name of the entity to be deleted'"`
Force bool `goptions:"-f, --force, description='Force removal'"`
} `goptions:"delete"`
}{ // Default values goes here
Timeout: 10 * time.Second,
}
goptions.ParseAndFail(&options)
}
```
```
$ go run examples/readme_example.go --help
Usage: a.out [global options] <verb> [verb options]
Global options:
-s, --server Servers to connect to (*)
-p, --password Don't prompt for password
-t, --timeout Connection timeout in seconds (default: 10s)
-h, --help Show this help
Verbs:
delete:
-n, --name Name of the entity to be deleted (*)
-f, --force Force removal
execute:
--command Command to exectute (*)
--script Script to exectute
```
# Quick Reference
## goptions
Each field of your struct can be tagged with a `goptions`
```go
FieldName type `goptions:"-S, --long, options..."`
```
Where the short options (`-S`) are declared with a single dash and
long options (`--long`) are declared with two dashes. Either or
both may be declared.
After the short/long option names are one or more of the following:
### Global Options
* description='...'
* obligatory
* mutexgroup='GROUP_NAME'
### os.File specific
* create
* append
* rdonly
* wronly
* rdwr
* excl
* sync
* trunc
* perm=0777
## Supported Types
* bool
* string
* float64
* float32
* int
* int64
* int32
* goptions.Help
* *os.File
* *net.TCPAddr
* *url.URL
* time.Duration
---
Version 2.5.11

9
vendor/github.com/voxelbrain/goptions/circle.yml generated vendored Normal file
View File

@@ -0,0 +1,9 @@
version: 2
jobs:
build:
docker:
- image: circleci/golang
steps:
- checkout
- run: go get -d .
- run: go test

90
vendor/github.com/voxelbrain/goptions/flag.go generated vendored Normal file
View File

@@ -0,0 +1,90 @@
package goptions
import (
"fmt"
"reflect"
"strings"
)
// Flag represents a single flag of a FlagSet.
type Flag struct {
Short string
Long string
MutexGroups []string
Description string
Obligatory bool
WasSpecified bool
value reflect.Value
optionMeta map[string]interface{}
DefaultValue interface{}
}
// Return the name of the flag preceding the right amount of dashes.
// The long name is preferred. If no name has been specified, "<unspecified>"
// will be returned.
func (f *Flag) Name() string {
if len(f.Long) > 0 {
return "--" + f.Long
}
if len(f.Short) > 0 {
return "-" + f.Short
}
return "<unspecified>"
}
// NeedsExtraValue returns true if the flag expects a separate value.
func (f *Flag) NeedsExtraValue() bool {
// Explicit over implicit
if f.value.Type() == reflect.TypeOf(new([]bool)).Elem() ||
f.value.Type() == reflect.TypeOf(new(bool)).Elem() {
return false
}
if _, ok := f.value.Interface().(Help); ok {
return false
}
return true
}
// IsMulti returns true if the flag can be specified multiple times.
func (f *Flag) IsMulti() bool {
if f.value.Kind() == reflect.Slice {
return true
}
return false
}
func isShort(arg string) bool {
return strings.HasPrefix(arg, "-") && !strings.HasPrefix(arg, "--") && len(arg) >= 2
}
func isLong(arg string) bool {
return strings.HasPrefix(arg, "--") && len(arg) >= 3
}
func (f *Flag) Handles(arg string) bool {
return (isShort(arg) && arg[1:2] == f.Short) ||
(isLong(arg) && arg[2:] == f.Long)
}
func (f *Flag) Parse(args []string) ([]string, error) {
param, value := args[0], ""
if f.NeedsExtraValue() &&
(len(args) < 2 || (isShort(param) && len(param) > 2)) {
return args, fmt.Errorf("Flag %s needs an argument", f.Name())
}
if f.WasSpecified && !f.IsMulti() {
return args, fmt.Errorf("Flag %s can only be specified once", f.Name())
}
if isShort(param) && len(param) > 2 {
// Short flag cluster
args[0] = "-" + param[2:]
} else if f.NeedsExtraValue() {
value = args[1]
args = args[2:]
} else {
args = args[1:]
}
f.WasSpecified = true
return args, f.setValue(value)
}

240
vendor/github.com/voxelbrain/goptions/flagset.go generated vendored Normal file
View File

@@ -0,0 +1,240 @@
package goptions
import (
"errors"
"fmt"
"io"
"os"
"reflect"
"strings"
"sync"
)
// A FlagSet represents one set of flags which belong to one particular program.
// A FlagSet is also used to represent a subset of flags belonging to one verb.
type FlagSet struct {
// This HelpFunc will be called when PrintHelp() is called.
HelpFunc
// Name of the program. Might be used by HelpFunc.
Name string
helpFlag *Flag
remainderFlag *Flag
shortMap map[string]*Flag
longMap map[string]*Flag
verbFlag *Flag
// Global option flags
Flags []*Flag
// Verbs and corresponding FlagSets
Verbs map[string]*FlagSet
parent *FlagSet
}
// NewFlagSet returns a new FlagSet containing all the flags which result from
// parsing the tags of the struct. Said struct as to be passed to the function
// as a pointer.
// If a tag line is erroneous, NewFlagSet() panics as this is considered a
// compile time error rather than a runtme error.
func NewFlagSet(name string, v interface{}) *FlagSet {
structValue := reflect.ValueOf(v)
if structValue.Kind() != reflect.Ptr {
panic("Value type is not a pointer to a struct")
}
structValue = structValue.Elem()
if structValue.Kind() != reflect.Struct {
panic("Value type is not a pointer to a struct")
}
return newFlagset(name, structValue, nil)
}
// Internal version which skips type checking and takes the "parent"'s
// remainder flag as a parameter.
func newFlagset(name string, structValue reflect.Value, parent *FlagSet) *FlagSet {
var once sync.Once
r := &FlagSet{
Name: name,
Flags: make([]*Flag, 0),
HelpFunc: DefaultHelpFunc,
parent: parent,
}
if parent != nil && parent.remainderFlag != nil {
r.remainderFlag = parent.remainderFlag
}
var i int
// Parse Option fields
for i = 0; i < structValue.Type().NumField(); i++ {
// Skip unexported fields
if StartsWithLowercase(structValue.Type().Field(i).Name) {
continue
}
fieldValue := structValue.Field(i)
tag := structValue.Type().Field(i).Tag.Get("goptions")
flag, err := parseStructField(fieldValue, tag)
if err != nil {
panic(fmt.Sprintf("Invalid struct field: %s", err))
}
if fieldValue.Type().Name() == "Verbs" {
r.verbFlag = flag
break
}
if fieldValue.Type().Name() == "Help" {
r.helpFlag = flag
}
if fieldValue.Type().Name() == "Remainder" && r.remainderFlag == nil {
r.remainderFlag = flag
}
if len(tag) != 0 {
r.Flags = append(r.Flags, flag)
}
}
// Parse verb fields
for i++; i < structValue.Type().NumField(); i++ {
once.Do(func() {
r.Verbs = make(map[string]*FlagSet)
})
fieldValue := structValue.Field(i)
tag := structValue.Type().Field(i).Tag.Get("goptions")
r.Verbs[tag] = newFlagset(tag, fieldValue, r)
}
r.createMaps()
return r
}
var (
ErrHelpRequest = errors.New("Request for Help")
)
// Parse takes the command line arguments and sets the corresponding values
// in the FlagSet's struct.
func (fs *FlagSet) Parse(args []string) (err error) {
// Parse global flags
for len(args) > 0 {
if !((isLong(args[0]) && fs.hasLongFlag(args[0][2:])) ||
(isShort(args[0]) && fs.hasShortFlag(args[0][1:2]))) {
break
}
f := fs.FlagByName(args[0])
args, err = f.Parse(args)
if err != nil {
return
}
if f == fs.helpFlag && f.WasSpecified {
return ErrHelpRequest
}
}
// Process verb
if len(args) > 0 {
if verb, ok := fs.Verbs[args[0]]; ok {
fs.verbFlag.value.Set(reflect.ValueOf(Verbs(args[0])))
err := verb.Parse(args[1:])
if err != nil {
return err
}
args = args[0:0]
}
}
// Process remainder
if len(args) > 0 {
if fs.remainderFlag == nil {
return fmt.Errorf("Invalid trailing arguments: %v", args)
}
remainder := reflect.MakeSlice(fs.remainderFlag.value.Type(), len(args), len(args))
reflect.Copy(remainder, reflect.ValueOf(args))
fs.remainderFlag.value.Set(remainder)
}
// Check for unset, obligatory, single Flags
for _, f := range fs.Flags {
if f.Obligatory && !f.WasSpecified && len(f.MutexGroups) == 0 {
return fmt.Errorf("%s must be specified", f.Name())
}
}
// Check for multiple set Flags in one mutex group
// Check also for unset, obligatory mutex groups
mgs := fs.MutexGroups()
for _, mg := range mgs {
if !mg.IsValid() {
return fmt.Errorf("Exactly one of %s must be specified", strings.Join(mg.Names(), ", "))
}
}
return nil
}
func (fs *FlagSet) createMaps() {
fs.longMap = make(map[string]*Flag)
fs.shortMap = make(map[string]*Flag)
for _, flag := range fs.Flags {
fs.longMap[flag.Long] = flag
fs.shortMap[flag.Short] = flag
}
}
func (fs *FlagSet) hasLongFlag(fname string) bool {
_, ok := fs.longMap[fname]
return ok
}
func (fs *FlagSet) hasShortFlag(fname string) bool {
_, ok := fs.shortMap[fname]
return ok
}
func (fs *FlagSet) FlagByName(fname string) *Flag {
if isShort(fname) && fs.hasShortFlag(fname[1:2]) {
return fs.shortMap[fname[1:2]]
} else if isLong(fname) && fs.hasLongFlag(fname[2:]) {
return fs.longMap[fname[2:]]
}
return nil
}
// MutexGroups returns a map of Flag lists which contain mutually
// exclusive flags.
func (fs *FlagSet) MutexGroups() map[string]MutexGroup {
r := make(map[string]MutexGroup)
for _, f := range fs.Flags {
for _, mg := range f.MutexGroups {
if len(mg) == 0 {
continue
}
if _, ok := r[mg]; !ok {
r[mg] = make(MutexGroup, 0)
}
r[mg] = append(r[mg], f)
}
}
return r
}
// Prints the FlagSet's help to the given writer.
func (fs *FlagSet) PrintHelp(w io.Writer) {
fs.HelpFunc(w, fs)
}
func (fs *FlagSet) ParseAndFail(w io.Writer, args []string) {
err := fs.Parse(args)
if err != nil {
errCode := 0
if err != ErrHelpRequest {
errCode = 1
fmt.Fprintf(w, "Error: %s\n", err)
}
fs.PrintHelp(w)
os.Exit(errCode)
}
}
func StartsWithLowercase(s string) bool {
if len(s) <= 0 {
return false
}
return strings.ToLower(s)[0] == s[0]
}

99
vendor/github.com/voxelbrain/goptions/goptions.go generated vendored Normal file
View File

@@ -0,0 +1,99 @@
/*
package goptions implements a flexible parser for command line options.
Key targets were the support for both long and short flag versions, mutually
exclusive flags, and verbs. Flags and their corresponding variables are defined
by the tags in a (possibly anonymous) struct.
var options struct {
Name string `goptions:"-n, --name"`
Force bool `goptions:"-f, --force"`
Verbosity int `goptions:"-v, --verbose"`
}
Short flags can be combined (e.g. `-nfv`). Long flags take their value after a
separating space. The equals notation (`--long-flag=value`) is NOT supported
right now.
Every member of the struct which is supposed to catch a command line value
has to have a "goptions" tag. The contains the short and long flag names for this
member but can additionally specify any of these options below.
obligatory - Flag must be specified. Otherwise an error will be returned
when Parse() is called.
description='...' - Set the description for this particular flag. Will be
used by the HelpFunc.
mutexgroup='...' - Add this flag to a MutexGroup. Only one flag of the
ones sharing a MutexGroup can be set. Otherwise an error
will be returned when Parse() is called. If one flag in a
MutexGroup is `obligatory` one flag of the group must be
specified. A flag can be in multiple MutexGroups at once.
Depending on the type of the struct member, additional options might become available:
Type: *os.File
The given string is interpreted as a path to a file. If the string is "-"
os.Stdin or os.Stdout will be used. os.Stdin will be returned, if the
`rdonly` flag was set. os.Stdout will be returned, if `wronly` was set.
Available options:
Any combination of create, append, rdonly, wronly, rdwr,
excl, sync, trunc and perm can be specified and correspond directly with
the combination of the homonymous flags in the os package.
Type: *net.TCPAddr
The given string is interpreted as a tcp address. It is passed to
net.ResolvTCPAddr() with "tcp" as the network type identifier.
Type: *net/url.URL
The given string is parsed by net/url.Parse()
Type: time.Duration
The given string is parsed by time.ParseDuration()
If a member is a slice type, multiple definitions of the flags are possible. For each
specification the underlying type will be used.
var options struct {
Servers []string `goptions:"-s, --server, description='Servers to connect to'"`
}{}
goptions also has support for verbs. Each verb accepts its own set of flags which
take exactly the same tag format as global options. For an usage example of verbs
see the PrintHelp() example.
*/
package goptions
import (
"os"
"path/filepath"
)
const (
VERSION = "2.5.11"
)
var (
globalFlagSet *FlagSet
)
// ParseAndFail is a convenience function to parse os.Args[1:] and print
// the help if an error occurs. This should cover 90% of this library's
// applications.
func ParseAndFail(v interface{}) {
globalFlagSet = NewFlagSet(filepath.Base(os.Args[0]), v)
globalFlagSet.ParseAndFail(os.Stderr, os.Args[1:])
}
// Parse parses the command-line flags from os.Args[1:].
func Parse(v interface{}) error {
globalFlagSet = NewFlagSet(filepath.Base(os.Args[0]), v)
return globalFlagSet.Parse(os.Args[1:])
}
// PrintHelp renders the default help to os.Stderr.
func PrintHelp() {
if globalFlagSet == nil {
panic("Must call Parse() before PrintHelp()")
}
globalFlagSet.PrintHelp(os.Stderr)
}

72
vendor/github.com/voxelbrain/goptions/helpfunc.go generated vendored Normal file
View File

@@ -0,0 +1,72 @@
package goptions
import (
"io"
"sync"
"text/tabwriter"
"text/template"
)
// HelpFunc is the signature of a function responsible for printing the help.
type HelpFunc func(w io.Writer, fs *FlagSet)
// Generates a new HelpFunc taking a `text/template.Template`-formatted
// string as an argument. The resulting template will be executed with the FlagSet
// as its data.
func NewTemplatedHelpFunc(tpl string) HelpFunc {
var once sync.Once
var t *template.Template
return func(w io.Writer, fs *FlagSet) {
once.Do(func() {
t = template.Must(template.New("helpTemplate").Parse(tpl))
})
err := t.Execute(w, fs)
if err != nil {
panic(err)
}
}
}
const (
_DEFAULT_HELP = "\xffUsage: {{.Name}} [global options] {{with .Verbs}}<verb> [verb options]{{end}}\n" +
"\n" +
"Global options:\xff" +
"{{range .Flags}}" +
"\n\t" +
"\t{{with .Short}}" + "-{{.}}," + "{{end}}" +
"\t{{with .Long}}" + "--{{.}}" + "{{end}}" +
"\t{{.Description}}" +
"{{with .DefaultValue}}" +
" (default: {{.}})" +
"{{end}}" +
"{{if .Obligatory}}" +
" (*)" +
"{{end}}" +
"{{end}}" +
"\xff\n\n{{with .Verbs}}Verbs:\xff" +
"{{range .}}" +
"\xff\n {{.Name}}:\xff" +
"{{range .Flags}}" +
"\n\t" +
"\t{{with .Short}}" + "-{{.}}," + "{{end}}" +
"\t{{with .Long}}" + "--{{.}}" + "{{end}}" +
"\t{{.Description}}" +
"{{with .DefaultValue}}" +
" (default: {{.}})" +
"{{end}}" +
"{{if .Obligatory}}" +
" (*)" +
"{{end}}" +
"{{end}}" +
"{{end}}" +
"{{end}}" +
"\n"
)
// DefaultHelpFunc is a HelpFunc which renders the default help template and pipes
// the output through a text/tabwriter.Writer before flushing it to the output.
func DefaultHelpFunc(w io.Writer, fs *FlagSet) {
tw := tabwriter.NewWriter(w, 4, 4, 1, ' ', tabwriter.StripEscape|tabwriter.DiscardEmptyColumns)
NewTemplatedHelpFunc(_DEFAULT_HELP)(tw, fs)
tw.Flush()
}

5
vendor/github.com/voxelbrain/goptions/marshaler.go generated vendored Normal file
View File

@@ -0,0 +1,5 @@
package goptions
type Marshaler interface {
MarshalGoption(s string) error
}

48
vendor/github.com/voxelbrain/goptions/mutexgroup.go generated vendored Normal file
View File

@@ -0,0 +1,48 @@
package goptions
// A MutexGroup holds a set of flags which are mutually exclusive and cannot
// be specified at the same time.
type MutexGroup []*Flag
// IsObligatory returns true if exactly one of the flags in the MutexGroup has
// to be specified
func (mg MutexGroup) IsObligatory() bool {
for _, flag := range mg {
if flag.Obligatory {
return true
}
}
return false
}
func (mg MutexGroup) WasSpecified() bool {
for _, flag := range mg {
if flag.WasSpecified {
return true
}
}
return false
}
// IsValid checks if the flags in the MutexGroup describe a valid state.
// I.e. At most one has been specified or if it is an obligatory MutexGroup
// exactly one has been specified.
func (mg MutexGroup) IsValid() bool {
c := 0
for _, flag := range mg {
if flag.WasSpecified {
c++
}
}
return c <= 1 && (!mg.IsObligatory() || c == 1)
}
// Names is a convenience function to return the array of names of the flags
// in the MutexGroup.
func (mg MutexGroup) Names() []string {
r := make([]string, len(mg))
for i, flag := range mg {
r[i] = flag.Name()
}
return r
}

136
vendor/github.com/voxelbrain/goptions/options.go generated vendored Normal file
View File

@@ -0,0 +1,136 @@
package goptions
import (
"fmt"
"os"
"reflect"
"strconv"
"strings"
"time"
)
type optionFunc func(f *Flag, option, value string) error
type optionMap map[string]optionFunc
var (
typeOptionMap = map[reflect.Type]optionMap{
// Global options
nil: optionMap{
"description": description,
"obligatory": obligatory,
"mutexgroup": mutexgroup,
},
reflect.TypeOf(new(time.Time)).Elem(): optionMap{
"format": time_format,
},
reflect.TypeOf(new(*os.File)).Elem(): optionMap{
"create": initOptionMeta(file_create, "file_mode", 0),
"append": initOptionMeta(file_append, "file_mode", 0),
"rdonly": initOptionMeta(file_rdonly, "file_mode", 0),
"wronly": initOptionMeta(file_wronly, "file_mode", 0),
"rdwr": initOptionMeta(file_rdwr, "file_mode", 0),
"excl": initOptionMeta(file_excl, "file_mode", 0),
"sync": initOptionMeta(file_sync, "file_mode", 0),
"trunc": initOptionMeta(file_trunc, "file_mode", 0),
"perm": file_perm,
},
}
)
// Wraps another optionFunc and inits optionMeta[field] with value if it does
// not have one already.
func initOptionMeta(fn optionFunc, field string, init_value interface{}) optionFunc {
return func(f *Flag, option, value string) error {
if _, ok := f.optionMeta[field]; !ok {
f.optionMeta[field] = init_value
}
return fn(f, option, value)
}
}
func description(f *Flag, option, value string) error {
f.Description = strings.Replace(value, `\`, ``, -1)
return nil
}
func obligatory(f *Flag, option, value string) error {
f.Obligatory = true
return nil
}
func mutexgroup(f *Flag, option, value string) error {
if len(value) <= 0 {
return fmt.Errorf("Mutexgroup option needs a value")
}
for _, group := range strings.Split(value, ",") {
f.MutexGroups = append(f.MutexGroups, group)
}
return nil
}
func file_create(f *Flag, option, value string) error {
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_CREATE
return nil
}
func file_append(f *Flag, option, value string) error {
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_APPEND
return nil
}
func file_rdonly(f *Flag, option, value string) error {
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_RDONLY
return nil
}
func file_wronly(f *Flag, option, value string) error {
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_WRONLY
return nil
}
func file_rdwr(f *Flag, option, value string) error {
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_RDWR
return nil
}
func file_excl(f *Flag, option, value string) error {
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_EXCL
return nil
}
func file_sync(f *Flag, option, value string) error {
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_SYNC
return nil
}
func file_trunc(f *Flag, option, value string) error {
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_TRUNC
return nil
}
func file_perm(f *Flag, option, value string) error {
perm, err := strconv.ParseInt(value, 8, 32)
if err != nil {
return err
}
f.optionMeta["file_perm"] = uint32(perm)
return nil
}
func time_format(f *Flag, option, value string) error {
f.optionMeta["format"] = value
return nil
}
func optionMapForType(t reflect.Type) optionMap {
g := typeOptionMap[nil]
m, _ := typeOptionMap[t]
r := make(optionMap)
for k, v := range g {
r[k] = v
}
for k, v := range m {
r[k] = v
}
return r
}

14
vendor/github.com/voxelbrain/goptions/special_types.go generated vendored Normal file
View File

@@ -0,0 +1,14 @@
package goptions
// Help Defines the common help flag. It is handled separately as it will cause
// Parse() to return ErrHelpRequest.
type Help bool
// Verbs marks the point in the struct where the verbs start. Its value will be
// the name of the selected verb.
type Verbs string
// A remainder catches all excessive arguments. If both a verb and
// the containing options struct have a remainder field, only the latter one
// will be used.
type Remainder []string

68
vendor/github.com/voxelbrain/goptions/tagparser.go generated vendored Normal file
View File

@@ -0,0 +1,68 @@
package goptions
import (
"fmt"
"reflect"
"regexp"
"strings"
)
const (
_LONG_FLAG_REGEXP = `--[[:word:]-]+`
_SHORT_FLAG_REGEXP = `-[[:alnum:]]`
_QUOTED_STRING_REGEXP = `'((?:\\'|[^\\'])+)'`
_OPTION_REGEXP = `([[:word:]-]+)(?:=` + _QUOTED_STRING_REGEXP + `)?`
)
var (
optionRegexp = regexp.MustCompile(`^(` + strings.Join([]string{_SHORT_FLAG_REGEXP, _LONG_FLAG_REGEXP, _OPTION_REGEXP}, "|") + `)(?:,|$)`)
)
func parseStructField(fieldValue reflect.Value, tag string) (*Flag, error) {
f := &Flag{
value: fieldValue,
DefaultValue: fieldValue.Interface(),
optionMeta: make(map[string]interface{}),
}
for {
tag = strings.TrimSpace(tag)
if len(tag) == 0 {
break
}
idx := optionRegexp.FindStringSubmatchIndex(tag)
if idx == nil {
return nil, fmt.Errorf("Could not find a valid flag definition at the beginning of \"%s\"", tag)
}
option := tag[idx[2]:idx[3]]
if strings.HasPrefix(option, "--") {
if f.Long != "" {
return nil, fmt.Errorf("Multiple flags assigned to a member: %s", strings.Join([]string{"--" + f.Long, option}, ", "))
}
f.Long = option[2:]
} else if strings.HasPrefix(option, "-") {
if f.Short != "" {
return nil, fmt.Errorf("Multiple flags assigned to a member: %s", strings.Join([]string{"-" + f.Short, option}, ", "))
}
f.Short = option[1:]
} else {
option := tag[idx[4]:idx[5]]
value := ""
if idx[6] != -1 {
value = tag[idx[6]:idx[7]]
}
optionmap := optionMapForType(fieldValue.Type())
opf, ok := optionmap[option]
if !ok {
return nil, fmt.Errorf("Unknown option %s", option)
}
err := opf(f, option, value)
if err != nil {
return nil, fmt.Errorf("Option %s invalid: %s", option, err)
}
}
// Keep remainder
tag = tag[idx[1]:]
}
return f, nil
}

163
vendor/github.com/voxelbrain/goptions/valueparser.go generated vendored Normal file
View File

@@ -0,0 +1,163 @@
package goptions
import (
"fmt"
"net"
"net/url"
"os"
"reflect"
"strconv"
"time"
)
type valueParser func(f *Flag, val string) (reflect.Value, error)
var (
parserMap = map[reflect.Type]valueParser{
reflect.TypeOf(new(bool)).Elem(): boolValueParser,
reflect.TypeOf(new(string)).Elem(): stringValueParser,
reflect.TypeOf(new(float64)).Elem(): float64ValueParser,
reflect.TypeOf(new(float32)).Elem(): float32ValueParser,
reflect.TypeOf(new(int)).Elem(): intValueParser,
reflect.TypeOf(new(int64)).Elem(): int64ValueParser,
reflect.TypeOf(new(int32)).Elem(): int32ValueParser,
reflect.TypeOf(new(Help)).Elem(): helpValueParser,
reflect.TypeOf(new(*os.File)).Elem(): fileValueParser,
reflect.TypeOf(new(*net.TCPAddr)).Elem(): tcpAddrValueParser,
reflect.TypeOf(new(*url.URL)).Elem(): urlValueParser,
reflect.TypeOf(new(time.Duration)).Elem(): durationValueParser,
reflect.TypeOf(new(time.Time)).Elem(): timeValueParser,
}
)
func parseMarshalValue(value reflect.Value, s string) error {
newval := reflect.New(value.Type()).Elem()
if newval.Kind() == reflect.Ptr {
newptrval := reflect.New(value.Type().Elem())
newval.Set(newptrval)
}
err := newval.Interface().(Marshaler).MarshalGoption(s)
value.Set(newval)
return err
}
func (f *Flag) setValue(s string) (err error) {
defer func() {
if x := recover(); x != nil {
err = x.(error)
return
}
}()
if f.value.Type().Implements(reflect.TypeOf(new(Marshaler)).Elem()) {
return parseMarshalValue(f.value, s)
}
vtype := f.value.Type()
newval := reflect.New(vtype).Elem()
if f.value.Kind() == reflect.Slice {
vtype = f.value.Type().Elem()
if vtype.Implements(reflect.TypeOf(new(Marshaler)).Elem()) {
newval = reflect.New(vtype).Elem()
err := parseMarshalValue(newval, s)
f.value.Set(reflect.Append(f.value, newval))
return err
}
}
if parser, ok := parserMap[vtype]; ok {
val, err := parser(f, s)
if err != nil {
return err
}
if f.value.Kind() == reflect.Slice {
f.value.Set(reflect.Append(f.value, val))
} else {
f.value.Set(val)
}
return nil
} else {
return fmt.Errorf("Unsupported flag type: %s", f.value.Type())
}
panic("Invalid execution path")
}
func boolValueParser(f *Flag, val string) (reflect.Value, error) {
return reflect.ValueOf(true), nil
}
func stringValueParser(f *Flag, val string) (reflect.Value, error) {
return reflect.ValueOf(val), nil
}
func float64ValueParser(f *Flag, val string) (reflect.Value, error) {
floatval, err := strconv.ParseFloat(val, 64)
return reflect.ValueOf(float64(floatval)), err
}
func float32ValueParser(f *Flag, val string) (reflect.Value, error) {
floatval, err := strconv.ParseFloat(val, 32)
return reflect.ValueOf(float32(floatval)), err
}
func int64ValueParser(f *Flag, val string) (reflect.Value, error) {
intval, err := strconv.ParseInt(val, 10, 64)
return reflect.ValueOf(int64(intval)), err
}
func int32ValueParser(f *Flag, val string) (reflect.Value, error) {
intval, err := strconv.ParseInt(val, 10, 32)
return reflect.ValueOf(int32(intval)), err
}
func intValueParser(f *Flag, val string) (reflect.Value, error) {
intval, err := strconv.ParseInt(val, 10, 64)
return reflect.ValueOf(int(intval)), err
}
func fileValueParser(f *Flag, val string) (reflect.Value, error) {
mode := 0
if v, ok := f.optionMeta["file_mode"]; ok {
mode = v.(int)
}
if val == "-" {
if mode&1 == os.O_RDONLY {
return reflect.ValueOf(os.Stdin), nil
} else if mode&1 == os.O_WRONLY {
return reflect.ValueOf(os.Stdout), nil
}
} else {
perm := uint32(0644)
if v, ok := f.optionMeta["file_perm"].(uint32); ok {
perm = v
}
f, e := os.OpenFile(val, mode, os.FileMode(perm))
return reflect.ValueOf(f), e
}
panic("Invalid execution path")
}
func tcpAddrValueParser(f *Flag, val string) (reflect.Value, error) {
addr, err := net.ResolveTCPAddr("tcp", val)
return reflect.ValueOf(addr), err
}
func urlValueParser(f *Flag, val string) (reflect.Value, error) {
url, err := url.Parse(val)
return reflect.ValueOf(url), err
}
func durationValueParser(f *Flag, val string) (reflect.Value, error) {
d, err := time.ParseDuration(val)
return reflect.ValueOf(d), err
}
func timeValueParser(f *Flag, val string) (reflect.Value, error) {
format := time.RFC3339
if altFormat, ok := f.optionMeta["format"]; ok {
format = altFormat.(string)
}
d, err := time.Parse(format, val)
return reflect.ValueOf(d), err
}
func helpValueParser(f *Flag, val string) (reflect.Value, error) {
return reflect.Value{}, ErrHelpRequest
}