forked from LaconicNetwork/kompose
Updated Vendoring
This commit is contained in:
+13
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/docker/libcompose/utils"
|
||||
composeYaml "github.com/docker/libcompose/yaml"
|
||||
"gopkg.in/yaml.v2"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -60,6 +61,18 @@ func Merge(existingServices *ServiceConfigs, environmentLookup EnvironmentLookup
|
||||
}
|
||||
baseRawServices := config.Services
|
||||
|
||||
for service, data := range baseRawServices {
|
||||
for key, value := range data {
|
||||
//check for "extends" key and check whether it is string or not
|
||||
if key == "extends" && reflect.TypeOf(value).Kind() == reflect.String {
|
||||
//converting string to map
|
||||
extendMap := make(map[interface{}]interface{})
|
||||
extendMap["service"] = value
|
||||
baseRawServices[service][key] = extendMap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if options.Interpolate {
|
||||
if err := InterpolateRawServiceMap(&baseRawServices, environmentLookup); err != nil {
|
||||
return "", nil, nil, nil, err
|
||||
|
||||
+7
-2
@@ -180,8 +180,13 @@ func resolveContextV2(inFile string, serviceData RawService) RawService {
|
||||
} else {
|
||||
current = path.Join(current, context)
|
||||
}
|
||||
|
||||
build["context"] = current
|
||||
if _, ok := serviceData["build"].(string); ok {
|
||||
//build is specified as a string containing a path to the build context
|
||||
serviceData["build"] = current
|
||||
} else {
|
||||
//build is specified as an object with the path specified under context
|
||||
build["context"] = current
|
||||
}
|
||||
|
||||
return serviceData
|
||||
}
|
||||
|
||||
+10
@@ -17,6 +17,16 @@ var (
|
||||
schemaV2 map[string]interface{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := setupSchemaLoaders(schemaDataV1, &schemaV1, &schemaLoaderV1, &constraintSchemaLoaderV1); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := setupSchemaLoaders(servicesSchemaDataV2, &schemaV2, &schemaLoaderV2, &constraintSchemaLoaderV2); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
environmentFormatChecker struct{}
|
||||
portsFormatChecker struct{}
|
||||
|
||||
-16
@@ -157,10 +157,6 @@ func invalidTypeMessage(service, key string, err gojsonschema.ResultError) strin
|
||||
}
|
||||
|
||||
func validate(serviceMap RawServiceMap) error {
|
||||
if err := setupSchemaLoaders(schemaDataV1, &schemaV1, &schemaLoaderV1, &constraintSchemaLoaderV1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceMap = convertServiceMapKeysToStrings(serviceMap)
|
||||
|
||||
dataLoader := gojsonschema.NewGoLoader(serviceMap)
|
||||
@@ -174,10 +170,6 @@ func validate(serviceMap RawServiceMap) error {
|
||||
}
|
||||
|
||||
func validateV2(serviceMap RawServiceMap) error {
|
||||
if err := setupSchemaLoaders(servicesSchemaDataV2, &schemaV2, &schemaLoaderV2, &constraintSchemaLoaderV2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceMap = convertServiceMapKeysToStrings(serviceMap)
|
||||
|
||||
dataLoader := gojsonschema.NewGoLoader(serviceMap)
|
||||
@@ -250,10 +242,6 @@ func generateErrorMessages(serviceMap RawServiceMap, schema map[string]interface
|
||||
}
|
||||
|
||||
func validateServiceConstraints(service RawService, serviceName string) error {
|
||||
if err := setupSchemaLoaders(schemaDataV1, &schemaV1, &schemaLoaderV1, &constraintSchemaLoaderV1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
service = convertServiceKeysToStrings(service)
|
||||
|
||||
var validationErrors []string
|
||||
@@ -289,10 +277,6 @@ func validateServiceConstraints(service RawService, serviceName string) error {
|
||||
}
|
||||
|
||||
func validateServiceConstraintsv2(service RawService, serviceName string) error {
|
||||
if err := setupSchemaLoaders(servicesSchemaDataV2, &schemaV2, &schemaLoaderV2, &constraintSchemaLoaderV2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
service = convertServiceKeysToStrings(service)
|
||||
|
||||
var validationErrors []string
|
||||
|
||||
+2
-1
@@ -249,8 +249,9 @@ func toStrings(s []interface{}) ([]string, error) {
|
||||
func toMap(s []string, sep string) map[string]string {
|
||||
m := map[string]string{}
|
||||
for _, v := range s {
|
||||
// Return everything past first sep
|
||||
values := strings.Split(v, sep)
|
||||
m[values[0]] = values[1]
|
||||
m[values[0]] = strings.SplitN(v, sep, 2)[1]
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
|
||||
// Done
|
||||
return keys, nil
|
||||
case token.ILLEGAL:
|
||||
fmt.Println("illegal")
|
||||
return nil, errors.New("illegal")
|
||||
default:
|
||||
return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
|
||||
}
|
||||
|
||||
+21
-1
@@ -33,6 +33,7 @@ type tomlOpts struct {
|
||||
}
|
||||
|
||||
var timeType = reflect.TypeOf(time.Time{})
|
||||
var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
|
||||
|
||||
// Check if the given marshall type maps to a TomlTree primitive
|
||||
func isPrimitive(mtype reflect.Type) bool {
|
||||
@@ -50,7 +51,7 @@ func isPrimitive(mtype reflect.Type) bool {
|
||||
case reflect.String:
|
||||
return true
|
||||
case reflect.Struct:
|
||||
return mtype == timeType
|
||||
return mtype == timeType || isCustomMarshaler(mtype)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
@@ -90,6 +91,20 @@ func isTree(mtype reflect.Type) bool {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -106,6 +121,9 @@ func Marshal(v interface{}) ([]byte, error) {
|
||||
return []byte{}, errors.New("Only a struct can be marshaled to TOML")
|
||||
}
|
||||
sval := reflect.ValueOf(v)
|
||||
if isCustomMarshaler(mtype) {
|
||||
return callCustomMarshaler(sval)
|
||||
}
|
||||
t, err := valueToTree(mtype, sval)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
@@ -178,6 +196,8 @@ func valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
|
||||
return valueToToml(mtype.Elem(), mval.Elem())
|
||||
}
|
||||
switch {
|
||||
case isCustomMarshaler(mtype):
|
||||
return callCustomMarshaler(mval)
|
||||
case isTree(mtype):
|
||||
return valueToTree(mtype, mval)
|
||||
case isTreeSlice(mtype):
|
||||
|
||||
+3
@@ -52,6 +52,9 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
|
||||
return strconv.FormatFloat(value, 'f', -1, 32), nil
|
||||
case string:
|
||||
return "\"" + encodeTomlString(value) + "\"", nil
|
||||
case []byte:
|
||||
b, _ := v.([]byte)
|
||||
return tomlValueStringRepresentation(string(b))
|
||||
case bool:
|
||||
if value {
|
||||
return "true", nil
|
||||
|
||||
+6
@@ -151,3 +151,9 @@ func ToIntSlice(i interface{}) []int {
|
||||
v, _ := ToIntSliceE(i)
|
||||
return v
|
||||
}
|
||||
|
||||
// ToDurationSlice casts an interface to a []time.Duration type.
|
||||
func ToDurationSlice(i interface{}) []time.Duration {
|
||||
v, _ := ToDurationSliceE(i)
|
||||
return v
|
||||
}
|
||||
|
||||
+29
@@ -1077,6 +1077,35 @@ func ToIntSliceE(i interface{}) ([]int, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ToDurationSliceE casts an interface to a []time.Duration type.
|
||||
func ToDurationSliceE(i interface{}) ([]time.Duration, error) {
|
||||
if i == nil {
|
||||
return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i)
|
||||
}
|
||||
|
||||
switch v := i.(type) {
|
||||
case []time.Duration:
|
||||
return v, nil
|
||||
}
|
||||
|
||||
kind := reflect.TypeOf(i).Kind()
|
||||
switch kind {
|
||||
case reflect.Slice, reflect.Array:
|
||||
s := reflect.ValueOf(i)
|
||||
a := make([]time.Duration, s.Len())
|
||||
for j := 0; j < s.Len(); j++ {
|
||||
val, err := ToDurationE(s.Index(j).Interface())
|
||||
if err != nil {
|
||||
return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i)
|
||||
}
|
||||
a[j] = val
|
||||
}
|
||||
return a, nil
|
||||
default:
|
||||
return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i)
|
||||
}
|
||||
}
|
||||
|
||||
// StringToDate attempts to parse a string into a time.Time type using a
|
||||
// predefined list of formats. If no suitable format is found, an error is
|
||||
// returned.
|
||||
|
||||
+2
-2
@@ -88,8 +88,8 @@ __handle_reply()
|
||||
local index flag
|
||||
flag="${cur%%=*}"
|
||||
__index_of_word "${flag}" "${flags_with_completion[@]}"
|
||||
COMPREPLY=()
|
||||
if [[ ${index} -ge 0 ]]; then
|
||||
COMPREPLY=()
|
||||
PREFIX=""
|
||||
cur="${cur#*=}"
|
||||
${flags_completion[${index}]}
|
||||
@@ -225,7 +225,7 @@ __handle_command()
|
||||
fi
|
||||
c=$((c+1))
|
||||
__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()
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ func AddTemplateFunc(name string, tmplFunc interface{}) {
|
||||
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.
|
||||
func AddTemplateFuncs(tmplFuncs template.FuncMap) {
|
||||
for k, v := range tmplFuncs {
|
||||
|
||||
+66
-124
@@ -66,6 +66,10 @@ type Command struct {
|
||||
pflags *flag.FlagSet
|
||||
// Flags that are declared specifically by this command (not inherited).
|
||||
lflags *flag.FlagSet
|
||||
// Inherited flags.
|
||||
iflags *flag.FlagSet
|
||||
// All persistent flags of cmd's parents.
|
||||
parentsPflags *flag.FlagSet
|
||||
// SilenceErrors is an option to quiet errors down stream
|
||||
SilenceErrors bool
|
||||
// Silence Usage is an option to silence usage when an error occurs.
|
||||
@@ -110,10 +114,8 @@ type Command struct {
|
||||
// is commands slice are sorted or not
|
||||
commandsAreSorted bool
|
||||
|
||||
flagErrorBuf *bytes.Buffer
|
||||
|
||||
args []string // actual args parsed from flags
|
||||
output *io.Writer // out writer if set in SetOutput(w)
|
||||
output io.Writer // out writer if set in SetOutput(w)
|
||||
usageFunc func(*Command) error // Usage can be defined by application
|
||||
usageTemplate string // Can be defined by Application
|
||||
flagErrorFunc func(*Command, error) error
|
||||
@@ -141,7 +143,7 @@ func (c *Command) SetArgs(a []string) {
|
||||
// SetOutput sets the destination for usage and error messages.
|
||||
// If output is nil, os.Stderr is used.
|
||||
func (c *Command) SetOutput(output io.Writer) {
|
||||
c.output = &output
|
||||
c.output = output
|
||||
}
|
||||
|
||||
// SetUsageFunc sets usage function. Usage can be defined by application.
|
||||
@@ -199,7 +201,7 @@ func (c *Command) OutOrStderr() io.Writer {
|
||||
|
||||
func (c *Command) getOut(def io.Writer) io.Writer {
|
||||
if c.output != nil {
|
||||
return *c.output
|
||||
return c.output
|
||||
}
|
||||
if c.HasParent() {
|
||||
return c.parent.getOut(def)
|
||||
@@ -341,8 +343,7 @@ func (c *Command) UsageTemplate() string {
|
||||
{{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}
|
||||
|
||||
Aliases:
|
||||
{{.NameAndAliases}}
|
||||
{{end}}{{if .HasExample}}
|
||||
{{.NameAndAliases}}{{end}}{{if .HasExample}}
|
||||
|
||||
Examples:
|
||||
{{ .Example }}{{end}}{{if .HasAvailableSubCommands}}
|
||||
@@ -547,32 +548,18 @@ func (c *Command) SuggestionsFor(typedName string) []string {
|
||||
|
||||
// VisitParents visits all parents of the command and invokes fn on each parent.
|
||||
func (c *Command) VisitParents(fn func(*Command)) {
|
||||
var traverse func(*Command) *Command
|
||||
|
||||
traverse = func(x *Command) *Command {
|
||||
if x != c {
|
||||
fn(x)
|
||||
}
|
||||
if x.HasParent() {
|
||||
return traverse(x.parent)
|
||||
}
|
||||
return x
|
||||
if c.HasParent() {
|
||||
fn(c.Parent())
|
||||
c.Parent().VisitParents(fn)
|
||||
}
|
||||
traverse(c)
|
||||
}
|
||||
|
||||
// Root finds root command.
|
||||
func (c *Command) Root() *Command {
|
||||
var findRoot func(*Command) *Command
|
||||
|
||||
findRoot = func(x *Command) *Command {
|
||||
if x.HasParent() {
|
||||
return findRoot(x.parent)
|
||||
}
|
||||
return x
|
||||
if c.HasParent() {
|
||||
return c.Parent().Root()
|
||||
}
|
||||
|
||||
return findRoot(c)
|
||||
return c
|
||||
}
|
||||
|
||||
// ArgsLenAtDash will return the length of f.Args at the moment when a -- was
|
||||
@@ -675,17 +662,6 @@ func (c *Command) preRun() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Command) errorMsgFromParse() string {
|
||||
s := c.flagErrorBuf.String()
|
||||
|
||||
x := strings.Split(s, "\n")
|
||||
|
||||
if len(x) > 0 {
|
||||
return x[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Execute Call execute to use the args (os.Args[1:] by default)
|
||||
// and run through the command tree finding appropriate matches
|
||||
// for commands and then corresponding flags.
|
||||
@@ -796,6 +772,7 @@ func (c *Command) initHelpCmd() {
|
||||
func (c *Command) ResetCommands() {
|
||||
c.commands = nil
|
||||
c.helpCommand = nil
|
||||
c.parentsPflags = nil
|
||||
}
|
||||
|
||||
// Sorts commands by their names.
|
||||
@@ -927,12 +904,8 @@ func (c *Command) DebugFlags() {
|
||||
}
|
||||
if x.HasFlags() {
|
||||
x.flags.VisitAll(func(f *flag.Flag) {
|
||||
if x.HasPersistentFlags() {
|
||||
if x.persistentFlag(f.Name) == nil {
|
||||
c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]")
|
||||
} else {
|
||||
c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]")
|
||||
}
|
||||
if x.HasPersistentFlags() && x.persistentFlag(f.Name) != nil {
|
||||
c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]")
|
||||
} else {
|
||||
c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]")
|
||||
}
|
||||
@@ -949,7 +922,6 @@ func (c *Command) DebugFlags() {
|
||||
}
|
||||
})
|
||||
}
|
||||
c.Println(x.flagErrorBuf)
|
||||
if x.HasSubCommands() {
|
||||
for _, y := range x.commands {
|
||||
debugflags(y)
|
||||
@@ -1090,11 +1062,9 @@ func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) f
|
||||
func (c *Command) Flags() *flag.FlagSet {
|
||||
if c.flags == nil {
|
||||
c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
if c.flagErrorBuf == nil {
|
||||
c.flagErrorBuf = new(bytes.Buffer)
|
||||
}
|
||||
c.flags.SetOutput(c.flagErrorBuf)
|
||||
c.flags.SetOutput(c.OutOrStderr())
|
||||
}
|
||||
|
||||
return c.flags
|
||||
}
|
||||
|
||||
@@ -1115,47 +1085,37 @@ func (c *Command) LocalNonPersistentFlags() *flag.FlagSet {
|
||||
func (c *Command) LocalFlags() *flag.FlagSet {
|
||||
c.mergePersistentFlags()
|
||||
|
||||
local := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
c.lflags.VisitAll(func(f *flag.Flag) {
|
||||
local.AddFlag(f)
|
||||
})
|
||||
if !c.HasParent() {
|
||||
flag.CommandLine.VisitAll(func(f *flag.Flag) {
|
||||
if local.Lookup(f.Name) == nil {
|
||||
local.AddFlag(f)
|
||||
}
|
||||
})
|
||||
if c.lflags == nil {
|
||||
c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
c.lflags.SetOutput(c.OutOrStderr())
|
||||
}
|
||||
return local
|
||||
c.lflags.SortFlags = c.Flags().SortFlags
|
||||
|
||||
addToLocal := func(f *flag.Flag) {
|
||||
if c.lflags.Lookup(f.Name) == nil && c.parentsPflags.Lookup(f.Name) == nil {
|
||||
c.lflags.AddFlag(f)
|
||||
}
|
||||
}
|
||||
c.Flags().VisitAll(addToLocal)
|
||||
c.PersistentFlags().VisitAll(addToLocal)
|
||||
return c.lflags
|
||||
}
|
||||
|
||||
// InheritedFlags returns all flags which were inherited from parents commands.
|
||||
func (c *Command) InheritedFlags() *flag.FlagSet {
|
||||
c.mergePersistentFlags()
|
||||
|
||||
inherited := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
if c.iflags == nil {
|
||||
c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
}
|
||||
|
||||
local := c.LocalFlags()
|
||||
|
||||
var rmerge func(x *Command)
|
||||
|
||||
rmerge = func(x *Command) {
|
||||
if x.HasPersistentFlags() {
|
||||
x.PersistentFlags().VisitAll(func(f *flag.Flag) {
|
||||
if inherited.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil {
|
||||
inherited.AddFlag(f)
|
||||
}
|
||||
})
|
||||
c.parentsPflags.VisitAll(func(f *flag.Flag) {
|
||||
if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil {
|
||||
c.iflags.AddFlag(f)
|
||||
}
|
||||
if x.HasParent() {
|
||||
rmerge(x.parent)
|
||||
}
|
||||
}
|
||||
|
||||
if c.HasParent() {
|
||||
rmerge(c.parent)
|
||||
}
|
||||
|
||||
return inherited
|
||||
})
|
||||
return c.iflags
|
||||
}
|
||||
|
||||
// NonInheritedFlags returns all flags which were not inherited from parent commands.
|
||||
@@ -1167,22 +1127,17 @@ func (c *Command) NonInheritedFlags() *flag.FlagSet {
|
||||
func (c *Command) PersistentFlags() *flag.FlagSet {
|
||||
if c.pflags == nil {
|
||||
c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
if c.flagErrorBuf == nil {
|
||||
c.flagErrorBuf = new(bytes.Buffer)
|
||||
}
|
||||
c.pflags.SetOutput(c.flagErrorBuf)
|
||||
c.pflags.SetOutput(c.OutOrStderr())
|
||||
}
|
||||
return c.pflags
|
||||
}
|
||||
|
||||
// ResetFlags is used in testing.
|
||||
func (c *Command) ResetFlags() {
|
||||
c.flagErrorBuf = new(bytes.Buffer)
|
||||
c.flagErrorBuf.Reset()
|
||||
c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
c.flags.SetOutput(c.flagErrorBuf)
|
||||
c.flags.SetOutput(c.OutOrStderr())
|
||||
c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
c.pflags.SetOutput(c.flagErrorBuf)
|
||||
c.pflags.SetOutput(c.OutOrStderr())
|
||||
}
|
||||
|
||||
// HasFlags checks if the command contains any flags (local plus persistent from the entire structure).
|
||||
@@ -1245,8 +1200,9 @@ func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
|
||||
flag = c.PersistentFlags().Lookup(name)
|
||||
}
|
||||
|
||||
if flag == nil && c.HasParent() {
|
||||
flag = c.parent.persistentFlag(name)
|
||||
if flag == nil {
|
||||
c.updateParentsPflags()
|
||||
flag = c.parentsPflags.Lookup(name)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1266,41 +1222,27 @@ func (c *Command) Parent() *Command {
|
||||
return c.parent
|
||||
}
|
||||
|
||||
// mergePersistentFlags merges c.PersistentFlags() to c.Flags()
|
||||
// and adds missing persistent flags of all parents.
|
||||
func (c *Command) mergePersistentFlags() {
|
||||
var rmerge func(x *Command)
|
||||
c.Flags().AddFlagSet(c.PersistentFlags())
|
||||
c.updateParentsPflags()
|
||||
c.Flags().AddFlagSet(c.parentsPflags)
|
||||
}
|
||||
|
||||
// Save the set of local flags
|
||||
if c.lflags == nil {
|
||||
c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
if c.flagErrorBuf == nil {
|
||||
c.flagErrorBuf = new(bytes.Buffer)
|
||||
}
|
||||
c.lflags.SetOutput(c.flagErrorBuf)
|
||||
addtolocal := func(f *flag.Flag) {
|
||||
c.lflags.AddFlag(f)
|
||||
}
|
||||
c.Flags().VisitAll(addtolocal)
|
||||
c.PersistentFlags().VisitAll(addtolocal)
|
||||
// updateParentsPflags updates c.parentsPflags by adding
|
||||
// new persistent flags of all parents.
|
||||
// If c.parentsPflags == nil, it makes new.
|
||||
func (c *Command) updateParentsPflags() {
|
||||
if c.parentsPflags == nil {
|
||||
c.parentsPflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
c.parentsPflags.SetOutput(c.OutOrStderr())
|
||||
c.parentsPflags.SortFlags = false
|
||||
}
|
||||
rmerge = func(x *Command) {
|
||||
if !x.HasParent() {
|
||||
flag.CommandLine.VisitAll(func(f *flag.Flag) {
|
||||
if x.PersistentFlags().Lookup(f.Name) == nil {
|
||||
x.PersistentFlags().AddFlag(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
if x.HasPersistentFlags() {
|
||||
x.PersistentFlags().VisitAll(func(f *flag.Flag) {
|
||||
if c.Flags().Lookup(f.Name) == nil {
|
||||
c.Flags().AddFlag(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
if x.HasParent() {
|
||||
rmerge(x.parent)
|
||||
}
|
||||
}
|
||||
|
||||
c.Root().PersistentFlags().AddFlagSet(flag.CommandLine)
|
||||
|
||||
rmerge(c)
|
||||
c.VisitParents(func(parent *Command) {
|
||||
c.parentsPflags.AddFlagSet(parent.PersistentFlags())
|
||||
})
|
||||
}
|
||||
|
||||
+26
-11
@@ -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
|
||||
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.
|
||||
Most code never instantiates this struct directly, and instead uses
|
||||
functions such as String(), BoolVar(), and Var(), and is therefore
|
||||
@@ -142,12 +142,13 @@ type FlagSet struct {
|
||||
parsed bool
|
||||
actual map[NormalizedName]*Flag
|
||||
orderedActual []*Flag
|
||||
sortedActual []*Flag
|
||||
formal map[NormalizedName]*Flag
|
||||
orderedFormal []*Flag
|
||||
sortedFormal []*Flag
|
||||
shorthands map[byte]*Flag
|
||||
args []string // arguments after flags
|
||||
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
|
||||
output io.Writer // nil means stderr; use out() accessor
|
||||
interspersed bool // allow interspersed option/non-option args
|
||||
@@ -200,13 +201,13 @@ func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
|
||||
// "--getUrl" which may also be translated to "geturl" and everything will work.
|
||||
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
|
||||
f.normalizeNameFunc = n
|
||||
f.orderedFormal = f.orderedFormal[:0]
|
||||
for k, v := range f.formal {
|
||||
delete(f.formal, k)
|
||||
nname := f.normalizeFlagName(string(k))
|
||||
f.formal[nname] = v
|
||||
f.orderedFormal = append(f.orderedFormal, v)
|
||||
f.sortedFormal = f.sortedFormal[:0]
|
||||
for k, v := range f.orderedFormal {
|
||||
delete(f.formal, NormalizedName(v.Name))
|
||||
nname := f.normalizeFlagName(v.Name)
|
||||
v.Name = string(nname)
|
||||
f.formal[nname] = v
|
||||
f.orderedFormal[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,9 +242,16 @@ func (f *FlagSet) SetOutput(output io.Writer) {
|
||||
// in primordial order if f.SortFlags is false, calling fn for each.
|
||||
// It visits all flags, even those not set.
|
||||
func (f *FlagSet) VisitAll(fn func(*Flag)) {
|
||||
if len(f.formal) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var flags []*Flag
|
||||
if f.SortFlags {
|
||||
flags = sortFlags(f.formal)
|
||||
if len(f.formal) != len(f.sortedFormal) {
|
||||
f.sortedFormal = sortFlags(f.formal)
|
||||
}
|
||||
flags = f.sortedFormal
|
||||
} else {
|
||||
flags = f.orderedFormal
|
||||
}
|
||||
@@ -280,9 +288,16 @@ func VisitAll(fn func(*Flag)) {
|
||||
// in primordial order if f.SortFlags is false, calling fn for each.
|
||||
// It visits only those flags that have been set.
|
||||
func (f *FlagSet) Visit(fn func(*Flag)) {
|
||||
if len(f.actual) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var flags []*Flag
|
||||
if f.SortFlags {
|
||||
flags = sortFlags(f.actual)
|
||||
if len(f.actual) != len(f.sortedActual) {
|
||||
f.sortedActual = sortFlags(f.actual)
|
||||
}
|
||||
flags = f.sortedActual
|
||||
} else {
|
||||
flags = f.orderedActual
|
||||
}
|
||||
|
||||
+25
-3
@@ -21,6 +21,7 @@ package viper
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@@ -719,7 +720,15 @@ func (v *Viper) GetSizeInBytes(key string) uint {
|
||||
// UnmarshalKey takes a single key and unmarshals it into a Struct.
|
||||
func UnmarshalKey(key string, rawVal interface{}) error { return v.UnmarshalKey(key, rawVal) }
|
||||
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
|
||||
@@ -886,7 +895,9 @@ func (v *Viper) find(lcaseKey string) interface{} {
|
||||
return cast.ToBool(flag.ValueString())
|
||||
case "stringSlice":
|
||||
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||
return strings.TrimSuffix(s, "]")
|
||||
s = strings.TrimSuffix(s, "]")
|
||||
res, _ := readAsCSV(s)
|
||||
return res
|
||||
default:
|
||||
return flag.ValueString()
|
||||
}
|
||||
@@ -953,7 +964,9 @@ func (v *Viper) find(lcaseKey string) interface{} {
|
||||
return cast.ToBool(flag.ValueString())
|
||||
case "stringSlice":
|
||||
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||
return strings.TrimSuffix(s, "]")
|
||||
s = strings.TrimSuffix(s, "]")
|
||||
res, _ := readAsCSV(s)
|
||||
return res
|
||||
default:
|
||||
return flag.ValueString()
|
||||
}
|
||||
@@ -963,6 +976,15 @@ func (v *Viper) find(lcaseKey string) interface{} {
|
||||
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 is case-insensitive for a key.
|
||||
func IsSet(key string) bool { return v.IsSet(key) }
|
||||
|
||||
Reference in New Issue
Block a user