mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 21:02:26 -05:00 
			
		
		
		
	[bugfix] Fix Swagger spec and add test script (#2698)
* Add Swagger spec test script * Fix Swagger spec errors not related to statuses with polls * Add API tests that post a status with a poll * Fix creating a status with a poll from form params * Fix Swagger spec errors related to statuses with polls (this is the last error) * Fix Swagger spec warnings not related to unused definitions * Suppress a duplicate list update params definition that was somehow causing wrong param names * Add Swagger test to CI - updates Drone config - vendorizes go-swagger - fixes a file extension issue that caused the test script to generate JSON instead of YAML with the vendorized version * Put `Sample: ` on its own line everywhere * Remove unused id param from emojiCategoriesGet * Add 5 more pairs of profile fields to account update API Swagger * Remove Swagger prefix from dummy fields It makes the generated code look weird * Manually annotate params for statusCreate operation * Fix all remaining Swagger spec warnings - Change some models into operation parameters - Ignore models that already correspond to manually documented operation parameters but can't be trivially changed (those with file fields) * Documented that creating a status with scheduled_at isn't implemented yet * sign drone.yml * Fix filter API Swagger errors * fixup! Fix filter API Swagger errors --------- Co-authored-by: tobi <tobi.smethurst@protonmail.com>
This commit is contained in:
		
					parent
					
						
							
								68c8fe67cc
							
						
					
				
			
			
				commit
				
					
						fc3741365c
					
				
			
		
					 672 changed files with 135624 additions and 713 deletions
				
			
		
							
								
								
									
										714
									
								
								vendor/github.com/jessevdk/go-flags/parser.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										714
									
								
								vendor/github.com/jessevdk/go-flags/parser.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,714 @@ | |||
| // Copyright 2012 Jesse van den Kieboom. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| package flags | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"reflect" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
| 	"unicode/utf8" | ||||
| ) | ||||
| 
 | ||||
| // A Parser provides command line option parsing. It can contain several | ||||
| // option groups each with their own set of options. | ||||
| type Parser struct { | ||||
| 	// Embedded, see Command for more information | ||||
| 	*Command | ||||
| 
 | ||||
| 	// A usage string to be displayed in the help message. | ||||
| 	Usage string | ||||
| 
 | ||||
| 	// Option flags changing the behavior of the parser. | ||||
| 	Options Options | ||||
| 
 | ||||
| 	// NamespaceDelimiter separates group namespaces and option long names | ||||
| 	NamespaceDelimiter string | ||||
| 
 | ||||
| 	// EnvNamespaceDelimiter separates group env namespaces and env keys | ||||
| 	EnvNamespaceDelimiter string | ||||
| 
 | ||||
| 	// UnknownOptionsHandler is a function which gets called when the parser | ||||
| 	// encounters an unknown option. The function receives the unknown option | ||||
| 	// name, a SplitArgument which specifies its value if set with an argument | ||||
| 	// separator, and the remaining command line arguments. | ||||
| 	// It should return a new list of remaining arguments to continue parsing, | ||||
| 	// or an error to indicate a parse failure. | ||||
| 	UnknownOptionHandler func(option string, arg SplitArgument, args []string) ([]string, error) | ||||
| 
 | ||||
| 	// CompletionHandler is a function gets called to handle the completion of | ||||
| 	// items. By default, the items are printed and the application is exited. | ||||
| 	// You can override this default behavior by specifying a custom CompletionHandler. | ||||
| 	CompletionHandler func(items []Completion) | ||||
| 
 | ||||
| 	// CommandHandler is a function that gets called to handle execution of a | ||||
| 	// command. By default, the command will simply be executed. This can be | ||||
| 	// overridden to perform certain actions (such as applying global flags) | ||||
| 	// just before the command is executed. Note that if you override the | ||||
| 	// handler it is your responsibility to call the command.Execute function. | ||||
| 	// | ||||
| 	// The command passed into CommandHandler may be nil in case there is no | ||||
| 	// command to be executed when parsing has finished. | ||||
| 	CommandHandler func(command Commander, args []string) error | ||||
| 
 | ||||
| 	internalError error | ||||
| } | ||||
| 
 | ||||
| // SplitArgument represents the argument value of an option that was passed using | ||||
| // an argument separator. | ||||
| type SplitArgument interface { | ||||
| 	// String returns the option's value as a string, and a boolean indicating | ||||
| 	// if the option was present. | ||||
| 	Value() (string, bool) | ||||
| } | ||||
| 
 | ||||
| type strArgument struct { | ||||
| 	value *string | ||||
| } | ||||
| 
 | ||||
| func (s strArgument) Value() (string, bool) { | ||||
| 	if s.value == nil { | ||||
| 		return "", false | ||||
| 	} | ||||
| 
 | ||||
| 	return *s.value, true | ||||
| } | ||||
| 
 | ||||
| // Options provides parser options that change the behavior of the option | ||||
| // parser. | ||||
| type Options uint | ||||
| 
 | ||||
| const ( | ||||
| 	// None indicates no options. | ||||
| 	None Options = 0 | ||||
| 
 | ||||
| 	// HelpFlag adds a default Help Options group to the parser containing | ||||
| 	// -h and --help options. When either -h or --help is specified on the | ||||
| 	// command line, the parser will return the special error of type | ||||
| 	// ErrHelp. When PrintErrors is also specified, then the help message | ||||
| 	// will also be automatically printed to os.Stdout. | ||||
| 	HelpFlag = 1 << iota | ||||
| 
 | ||||
| 	// PassDoubleDash passes all arguments after a double dash, --, as | ||||
| 	// remaining command line arguments (i.e. they will not be parsed for | ||||
| 	// flags). | ||||
| 	PassDoubleDash | ||||
| 
 | ||||
| 	// IgnoreUnknown ignores any unknown options and passes them as | ||||
| 	// remaining command line arguments instead of generating an error. | ||||
| 	IgnoreUnknown | ||||
| 
 | ||||
| 	// PrintErrors prints any errors which occurred during parsing to | ||||
| 	// os.Stderr. In the special case of ErrHelp, the message will be printed | ||||
| 	// to os.Stdout. | ||||
| 	PrintErrors | ||||
| 
 | ||||
| 	// PassAfterNonOption passes all arguments after the first non option | ||||
| 	// as remaining command line arguments. This is equivalent to strict | ||||
| 	// POSIX processing. | ||||
| 	PassAfterNonOption | ||||
| 
 | ||||
| 	// Default is a convenient default set of options which should cover | ||||
| 	// most of the uses of the flags package. | ||||
| 	Default = HelpFlag | PrintErrors | PassDoubleDash | ||||
| ) | ||||
| 
 | ||||
| type parseState struct { | ||||
| 	arg        string | ||||
| 	args       []string | ||||
| 	retargs    []string | ||||
| 	positional []*Arg | ||||
| 	err        error | ||||
| 
 | ||||
| 	command *Command | ||||
| 	lookup  lookup | ||||
| } | ||||
| 
 | ||||
| // Parse is a convenience function to parse command line options with default | ||||
| // settings. The provided data is a pointer to a struct representing the | ||||
| // default option group (named "Application Options"). For more control, use | ||||
| // flags.NewParser. | ||||
| func Parse(data interface{}) ([]string, error) { | ||||
| 	return NewParser(data, Default).Parse() | ||||
| } | ||||
| 
 | ||||
| // ParseArgs is a convenience function to parse command line options with default | ||||
| // settings. The provided data is a pointer to a struct representing the | ||||
| // default option group (named "Application Options"). The args argument is | ||||
| // the list of command line arguments to parse. If you just want to parse the | ||||
| // default program command line arguments (i.e. os.Args), then use flags.Parse | ||||
| // instead. For more control, use flags.NewParser. | ||||
| func ParseArgs(data interface{}, args []string) ([]string, error) { | ||||
| 	return NewParser(data, Default).ParseArgs(args) | ||||
| } | ||||
| 
 | ||||
| // NewParser creates a new parser. It uses os.Args[0] as the application | ||||
| // name and then calls Parser.NewNamedParser (see Parser.NewNamedParser for | ||||
| // more details). The provided data is a pointer to a struct representing the | ||||
| // default option group (named "Application Options"), or nil if the default | ||||
| // group should not be added. The options parameter specifies a set of options | ||||
| // for the parser. | ||||
| func NewParser(data interface{}, options Options) *Parser { | ||||
| 	p := NewNamedParser(path.Base(os.Args[0]), options) | ||||
| 
 | ||||
| 	if data != nil { | ||||
| 		g, err := p.AddGroup("Application Options", "", data) | ||||
| 
 | ||||
| 		if err == nil { | ||||
| 			g.parent = p | ||||
| 		} | ||||
| 
 | ||||
| 		p.internalError = err | ||||
| 	} | ||||
| 
 | ||||
| 	return p | ||||
| } | ||||
| 
 | ||||
| // NewNamedParser creates a new parser. The appname is used to display the | ||||
| // executable name in the built-in help message. Option groups and commands can | ||||
| // be added to this parser by using AddGroup and AddCommand. | ||||
| func NewNamedParser(appname string, options Options) *Parser { | ||||
| 	p := &Parser{ | ||||
| 		Command:               newCommand(appname, "", "", nil), | ||||
| 		Options:               options, | ||||
| 		NamespaceDelimiter:    ".", | ||||
| 		EnvNamespaceDelimiter: "_", | ||||
| 	} | ||||
| 
 | ||||
| 	p.Command.parent = p | ||||
| 
 | ||||
| 	return p | ||||
| } | ||||
| 
 | ||||
| // Parse parses the command line arguments from os.Args using Parser.ParseArgs. | ||||
| // For more detailed information see ParseArgs. | ||||
| func (p *Parser) Parse() ([]string, error) { | ||||
| 	return p.ParseArgs(os.Args[1:]) | ||||
| } | ||||
| 
 | ||||
| // ParseArgs parses the command line arguments according to the option groups that | ||||
| // were added to the parser. On successful parsing of the arguments, the | ||||
| // remaining, non-option, arguments (if any) are returned. The returned error | ||||
| // indicates a parsing error and can be used with PrintError to display | ||||
| // contextual information on where the error occurred exactly. | ||||
| // | ||||
| // When the common help group has been added (AddHelp) and either -h or --help | ||||
| // was specified in the command line arguments, a help message will be | ||||
| // automatically printed if the PrintErrors option is enabled. | ||||
| // Furthermore, the special error type ErrHelp is returned. | ||||
| // It is up to the caller to exit the program if so desired. | ||||
| func (p *Parser) ParseArgs(args []string) ([]string, error) { | ||||
| 	if p.internalError != nil { | ||||
| 		return nil, p.internalError | ||||
| 	} | ||||
| 
 | ||||
| 	p.eachOption(func(c *Command, g *Group, option *Option) { | ||||
| 		option.clearReferenceBeforeSet = true | ||||
| 		option.updateDefaultLiteral() | ||||
| 	}) | ||||
| 
 | ||||
| 	// Add built-in help group to all commands if necessary | ||||
| 	if (p.Options & HelpFlag) != None { | ||||
| 		p.addHelpGroups(p.showBuiltinHelp) | ||||
| 	} | ||||
| 
 | ||||
| 	compval := os.Getenv("GO_FLAGS_COMPLETION") | ||||
| 
 | ||||
| 	if len(compval) != 0 { | ||||
| 		comp := &completion{parser: p} | ||||
| 		items := comp.complete(args) | ||||
| 
 | ||||
| 		if p.CompletionHandler != nil { | ||||
| 			p.CompletionHandler(items) | ||||
| 		} else { | ||||
| 			comp.print(items, compval == "verbose") | ||||
| 			os.Exit(0) | ||||
| 		} | ||||
| 
 | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	s := &parseState{ | ||||
| 		args:    args, | ||||
| 		retargs: make([]string, 0, len(args)), | ||||
| 	} | ||||
| 
 | ||||
| 	p.fillParseState(s) | ||||
| 
 | ||||
| 	for !s.eof() { | ||||
| 		var err error | ||||
| 		arg := s.pop() | ||||
| 
 | ||||
| 		// When PassDoubleDash is set and we encounter a --, then | ||||
| 		// simply append all the rest as arguments and break out | ||||
| 		if (p.Options&PassDoubleDash) != None && arg == "--" { | ||||
| 			s.addArgs(s.args...) | ||||
| 			break | ||||
| 		} | ||||
| 
 | ||||
| 		if !argumentIsOption(arg) { | ||||
| 			if (p.Options&PassAfterNonOption) != None && s.lookup.commands[arg] == nil { | ||||
| 				// If PassAfterNonOption is set then all remaining arguments | ||||
| 				// are considered positional | ||||
| 				if err = s.addArgs(s.arg); err != nil { | ||||
| 					break | ||||
| 				} | ||||
| 
 | ||||
| 				if err = s.addArgs(s.args...); err != nil { | ||||
| 					break | ||||
| 				} | ||||
| 
 | ||||
| 				break | ||||
| 			} | ||||
| 
 | ||||
| 			// Note: this also sets s.err, so we can just check for | ||||
| 			// nil here and use s.err later | ||||
| 			if p.parseNonOption(s) != nil { | ||||
| 				break | ||||
| 			} | ||||
| 
 | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		prefix, optname, islong := stripOptionPrefix(arg) | ||||
| 		optname, _, argument := splitOption(prefix, optname, islong) | ||||
| 
 | ||||
| 		if islong { | ||||
| 			err = p.parseLong(s, optname, argument) | ||||
| 		} else { | ||||
| 			err = p.parseShort(s, optname, argument) | ||||
| 		} | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			ignoreUnknown := (p.Options & IgnoreUnknown) != None | ||||
| 			parseErr := wrapError(err) | ||||
| 
 | ||||
| 			if parseErr.Type != ErrUnknownFlag || (!ignoreUnknown && p.UnknownOptionHandler == nil) { | ||||
| 				s.err = parseErr | ||||
| 				break | ||||
| 			} | ||||
| 
 | ||||
| 			if ignoreUnknown { | ||||
| 				s.addArgs(arg) | ||||
| 			} else if p.UnknownOptionHandler != nil { | ||||
| 				modifiedArgs, err := p.UnknownOptionHandler(optname, strArgument{argument}, s.args) | ||||
| 
 | ||||
| 				if err != nil { | ||||
| 					s.err = err | ||||
| 					break | ||||
| 				} | ||||
| 
 | ||||
| 				s.args = modifiedArgs | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if s.err == nil { | ||||
| 		p.eachOption(func(c *Command, g *Group, option *Option) { | ||||
| 			err := option.clearDefault() | ||||
| 			if err != nil { | ||||
| 				if _, ok := err.(*Error); !ok { | ||||
| 					err = p.marshalError(option, err) | ||||
| 				} | ||||
| 				s.err = err | ||||
| 			} | ||||
| 		}) | ||||
| 
 | ||||
| 		s.checkRequired(p) | ||||
| 	} | ||||
| 
 | ||||
| 	var reterr error | ||||
| 
 | ||||
| 	if s.err != nil { | ||||
| 		reterr = s.err | ||||
| 	} else if len(s.command.commands) != 0 && !s.command.SubcommandsOptional { | ||||
| 		reterr = s.estimateCommand() | ||||
| 	} else if cmd, ok := s.command.data.(Commander); ok { | ||||
| 		if p.CommandHandler != nil { | ||||
| 			reterr = p.CommandHandler(cmd, s.retargs) | ||||
| 		} else { | ||||
| 			reterr = cmd.Execute(s.retargs) | ||||
| 		} | ||||
| 	} else if p.CommandHandler != nil { | ||||
| 		reterr = p.CommandHandler(nil, s.retargs) | ||||
| 	} | ||||
| 
 | ||||
| 	if reterr != nil { | ||||
| 		var retargs []string | ||||
| 
 | ||||
| 		if ourErr, ok := reterr.(*Error); !ok || ourErr.Type != ErrHelp { | ||||
| 			retargs = append([]string{s.arg}, s.args...) | ||||
| 		} else { | ||||
| 			retargs = s.args | ||||
| 		} | ||||
| 
 | ||||
| 		return retargs, p.printError(reterr) | ||||
| 	} | ||||
| 
 | ||||
| 	return s.retargs, nil | ||||
| } | ||||
| 
 | ||||
| func (p *parseState) eof() bool { | ||||
| 	return len(p.args) == 0 | ||||
| } | ||||
| 
 | ||||
| func (p *parseState) pop() string { | ||||
| 	if p.eof() { | ||||
| 		return "" | ||||
| 	} | ||||
| 
 | ||||
| 	p.arg = p.args[0] | ||||
| 	p.args = p.args[1:] | ||||
| 
 | ||||
| 	return p.arg | ||||
| } | ||||
| 
 | ||||
| func (p *parseState) peek() string { | ||||
| 	if p.eof() { | ||||
| 		return "" | ||||
| 	} | ||||
| 
 | ||||
| 	return p.args[0] | ||||
| } | ||||
| 
 | ||||
| func (p *parseState) checkRequired(parser *Parser) error { | ||||
| 	c := parser.Command | ||||
| 
 | ||||
| 	var required []*Option | ||||
| 
 | ||||
| 	for c != nil { | ||||
| 		c.eachGroup(func(g *Group) { | ||||
| 			for _, option := range g.options { | ||||
| 				if !option.isSet && option.Required { | ||||
| 					required = append(required, option) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
| 
 | ||||
| 		c = c.Active | ||||
| 	} | ||||
| 
 | ||||
| 	if len(required) == 0 { | ||||
| 		if len(p.positional) > 0 { | ||||
| 			var reqnames []string | ||||
| 
 | ||||
| 			for _, arg := range p.positional { | ||||
| 				argRequired := (!arg.isRemaining() && p.command.ArgsRequired) || arg.Required != -1 || arg.RequiredMaximum != -1 | ||||
| 
 | ||||
| 				if !argRequired { | ||||
| 					continue | ||||
| 				} | ||||
| 
 | ||||
| 				if arg.isRemaining() { | ||||
| 					if arg.value.Len() < arg.Required { | ||||
| 						var arguments string | ||||
| 
 | ||||
| 						if arg.Required > 1 { | ||||
| 							arguments = "arguments, but got only " + fmt.Sprintf("%d", arg.value.Len()) | ||||
| 						} else { | ||||
| 							arguments = "argument" | ||||
| 						} | ||||
| 
 | ||||
| 						reqnames = append(reqnames, "`"+arg.Name+" (at least "+fmt.Sprintf("%d", arg.Required)+" "+arguments+")`") | ||||
| 					} else if arg.RequiredMaximum != -1 && arg.value.Len() > arg.RequiredMaximum { | ||||
| 						if arg.RequiredMaximum == 0 { | ||||
| 							reqnames = append(reqnames, "`"+arg.Name+" (zero arguments)`") | ||||
| 						} else { | ||||
| 							var arguments string | ||||
| 
 | ||||
| 							if arg.RequiredMaximum > 1 { | ||||
| 								arguments = "arguments, but got " + fmt.Sprintf("%d", arg.value.Len()) | ||||
| 							} else { | ||||
| 								arguments = "argument" | ||||
| 							} | ||||
| 
 | ||||
| 							reqnames = append(reqnames, "`"+arg.Name+" (at most "+fmt.Sprintf("%d", arg.RequiredMaximum)+" "+arguments+")`") | ||||
| 						} | ||||
| 					} | ||||
| 				} else { | ||||
| 					reqnames = append(reqnames, "`"+arg.Name+"`") | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if len(reqnames) == 0 { | ||||
| 				return nil | ||||
| 			} | ||||
| 
 | ||||
| 			var msg string | ||||
| 
 | ||||
| 			if len(reqnames) == 1 { | ||||
| 				msg = fmt.Sprintf("the required argument %s was not provided", reqnames[0]) | ||||
| 			} else { | ||||
| 				msg = fmt.Sprintf("the required arguments %s and %s were not provided", | ||||
| 					strings.Join(reqnames[:len(reqnames)-1], ", "), reqnames[len(reqnames)-1]) | ||||
| 			} | ||||
| 
 | ||||
| 			p.err = newError(ErrRequired, msg) | ||||
| 			return p.err | ||||
| 		} | ||||
| 
 | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	names := make([]string, 0, len(required)) | ||||
| 
 | ||||
| 	for _, k := range required { | ||||
| 		names = append(names, "`"+k.String()+"'") | ||||
| 	} | ||||
| 
 | ||||
| 	sort.Strings(names) | ||||
| 
 | ||||
| 	var msg string | ||||
| 
 | ||||
| 	if len(names) == 1 { | ||||
| 		msg = fmt.Sprintf("the required flag %s was not specified", names[0]) | ||||
| 	} else { | ||||
| 		msg = fmt.Sprintf("the required flags %s and %s were not specified", | ||||
| 			strings.Join(names[:len(names)-1], ", "), names[len(names)-1]) | ||||
| 	} | ||||
| 
 | ||||
| 	p.err = newError(ErrRequired, msg) | ||||
| 	return p.err | ||||
| } | ||||
| 
 | ||||
| func (p *parseState) estimateCommand() error { | ||||
| 	commands := p.command.sortedVisibleCommands() | ||||
| 	cmdnames := make([]string, len(commands)) | ||||
| 
 | ||||
| 	for i, v := range commands { | ||||
| 		cmdnames[i] = v.Name | ||||
| 	} | ||||
| 
 | ||||
| 	var msg string | ||||
| 	var errtype ErrorType | ||||
| 
 | ||||
| 	if len(p.retargs) != 0 { | ||||
| 		c, l := closestChoice(p.retargs[0], cmdnames) | ||||
| 		msg = fmt.Sprintf("Unknown command `%s'", p.retargs[0]) | ||||
| 		errtype = ErrUnknownCommand | ||||
| 
 | ||||
| 		if float32(l)/float32(len(c)) < 0.5 { | ||||
| 			msg = fmt.Sprintf("%s, did you mean `%s'?", msg, c) | ||||
| 		} else if len(cmdnames) == 1 { | ||||
| 			msg = fmt.Sprintf("%s. You should use the %s command", | ||||
| 				msg, | ||||
| 				cmdnames[0]) | ||||
| 		} else if len(cmdnames) > 1 { | ||||
| 			msg = fmt.Sprintf("%s. Please specify one command of: %s or %s", | ||||
| 				msg, | ||||
| 				strings.Join(cmdnames[:len(cmdnames)-1], ", "), | ||||
| 				cmdnames[len(cmdnames)-1]) | ||||
| 		} | ||||
| 	} else { | ||||
| 		errtype = ErrCommandRequired | ||||
| 
 | ||||
| 		if len(cmdnames) == 1 { | ||||
| 			msg = fmt.Sprintf("Please specify the %s command", cmdnames[0]) | ||||
| 		} else if len(cmdnames) > 1 { | ||||
| 			msg = fmt.Sprintf("Please specify one command of: %s or %s", | ||||
| 				strings.Join(cmdnames[:len(cmdnames)-1], ", "), | ||||
| 				cmdnames[len(cmdnames)-1]) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return newError(errtype, msg) | ||||
| } | ||||
| 
 | ||||
| func (p *Parser) parseOption(s *parseState, name string, option *Option, canarg bool, argument *string) (err error) { | ||||
| 	if !option.canArgument() { | ||||
| 		if argument != nil { | ||||
| 			return newErrorf(ErrNoArgumentForBool, "bool flag `%s' cannot have an argument", option) | ||||
| 		} | ||||
| 
 | ||||
| 		err = option.set(nil) | ||||
| 	} else if argument != nil || (canarg && !s.eof()) { | ||||
| 		var arg string | ||||
| 
 | ||||
| 		if argument != nil { | ||||
| 			arg = *argument | ||||
| 		} else { | ||||
| 			arg = s.pop() | ||||
| 
 | ||||
| 			if validationErr := option.isValidValue(arg); validationErr != nil { | ||||
| 				return newErrorf(ErrExpectedArgument, validationErr.Error()) | ||||
| 			} else if p.Options&PassDoubleDash != 0 && arg == "--" { | ||||
| 				return newErrorf(ErrExpectedArgument, "expected argument for flag `%s', but got double dash `--'", option) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if option.tag.Get("unquote") != "false" { | ||||
| 			arg, err = unquoteIfPossible(arg) | ||||
| 		} | ||||
| 
 | ||||
| 		if err == nil { | ||||
| 			err = option.set(&arg) | ||||
| 		} | ||||
| 	} else if option.OptionalArgument { | ||||
| 		option.empty() | ||||
| 
 | ||||
| 		for _, v := range option.OptionalValue { | ||||
| 			err = option.set(&v) | ||||
| 
 | ||||
| 			if err != nil { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		err = newErrorf(ErrExpectedArgument, "expected argument for flag `%s'", option) | ||||
| 	} | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		if _, ok := err.(*Error); !ok { | ||||
| 			err = p.marshalError(option, err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (p *Parser) marshalError(option *Option, err error) *Error { | ||||
| 	s := "invalid argument for flag `%s'" | ||||
| 
 | ||||
| 	expected := p.expectedType(option) | ||||
| 
 | ||||
| 	if expected != "" { | ||||
| 		s = s + " (expected " + expected + ")" | ||||
| 	} | ||||
| 
 | ||||
| 	return newErrorf(ErrMarshal, s+": %s", | ||||
| 		option, | ||||
| 		err.Error()) | ||||
| } | ||||
| 
 | ||||
| func (p *Parser) expectedType(option *Option) string { | ||||
| 	valueType := option.value.Type() | ||||
| 
 | ||||
| 	if valueType.Kind() == reflect.Func { | ||||
| 		return "" | ||||
| 	} | ||||
| 
 | ||||
| 	return valueType.String() | ||||
| } | ||||
| 
 | ||||
| func (p *Parser) parseLong(s *parseState, name string, argument *string) error { | ||||
| 	if option := s.lookup.longNames[name]; option != nil { | ||||
| 		// Only long options that are required can consume an argument | ||||
| 		// from the argument list | ||||
| 		canarg := !option.OptionalArgument | ||||
| 
 | ||||
| 		return p.parseOption(s, name, option, canarg, argument) | ||||
| 	} | ||||
| 
 | ||||
| 	return newErrorf(ErrUnknownFlag, "unknown flag `%s'", name) | ||||
| } | ||||
| 
 | ||||
| func (p *Parser) splitShortConcatArg(s *parseState, optname string) (string, *string) { | ||||
| 	c, n := utf8.DecodeRuneInString(optname) | ||||
| 
 | ||||
| 	if n == len(optname) { | ||||
| 		return optname, nil | ||||
| 	} | ||||
| 
 | ||||
| 	first := string(c) | ||||
| 
 | ||||
| 	if option := s.lookup.shortNames[first]; option != nil && option.canArgument() { | ||||
| 		arg := optname[n:] | ||||
| 		return first, &arg | ||||
| 	} | ||||
| 
 | ||||
| 	return optname, nil | ||||
| } | ||||
| 
 | ||||
| func (p *Parser) parseShort(s *parseState, optname string, argument *string) error { | ||||
| 	if argument == nil { | ||||
| 		optname, argument = p.splitShortConcatArg(s, optname) | ||||
| 	} | ||||
| 
 | ||||
| 	for i, c := range optname { | ||||
| 		shortname := string(c) | ||||
| 
 | ||||
| 		if option := s.lookup.shortNames[shortname]; option != nil { | ||||
| 			// Only the last short argument can consume an argument from | ||||
| 			// the arguments list, and only if it's non optional | ||||
| 			canarg := (i+utf8.RuneLen(c) == len(optname)) && !option.OptionalArgument | ||||
| 
 | ||||
| 			if err := p.parseOption(s, shortname, option, canarg, argument); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} else { | ||||
| 			return newErrorf(ErrUnknownFlag, "unknown flag `%s'", shortname) | ||||
| 		} | ||||
| 
 | ||||
| 		// Only the first option can have a concatted argument, so just | ||||
| 		// clear argument here | ||||
| 		argument = nil | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *parseState) addArgs(args ...string) error { | ||||
| 	for len(p.positional) > 0 && len(args) > 0 { | ||||
| 		arg := p.positional[0] | ||||
| 
 | ||||
| 		if err := convert(args[0], arg.value, arg.tag); err != nil { | ||||
| 			p.err = err | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		if !arg.isRemaining() { | ||||
| 			p.positional = p.positional[1:] | ||||
| 		} | ||||
| 
 | ||||
| 		args = args[1:] | ||||
| 	} | ||||
| 
 | ||||
| 	p.retargs = append(p.retargs, args...) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *Parser) parseNonOption(s *parseState) error { | ||||
| 	if len(s.positional) > 0 { | ||||
| 		return s.addArgs(s.arg) | ||||
| 	} | ||||
| 
 | ||||
| 	if len(s.command.commands) > 0 && len(s.retargs) == 0 { | ||||
| 		if cmd := s.lookup.commands[s.arg]; cmd != nil { | ||||
| 			s.command.Active = cmd | ||||
| 			cmd.fillParseState(s) | ||||
| 
 | ||||
| 			return nil | ||||
| 		} else if !s.command.SubcommandsOptional { | ||||
| 			s.addArgs(s.arg) | ||||
| 			return newErrorf(ErrUnknownCommand, "Unknown command `%s'", s.arg) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return s.addArgs(s.arg) | ||||
| } | ||||
| 
 | ||||
| func (p *Parser) showBuiltinHelp() error { | ||||
| 	var b bytes.Buffer | ||||
| 
 | ||||
| 	p.WriteHelp(&b) | ||||
| 	return newError(ErrHelp, b.String()) | ||||
| } | ||||
| 
 | ||||
| func (p *Parser) printError(err error) error { | ||||
| 	if err != nil && (p.Options&PrintErrors) != None { | ||||
| 		flagsErr, ok := err.(*Error) | ||||
| 
 | ||||
| 		if ok && flagsErr.Type == ErrHelp { | ||||
| 			fmt.Fprintln(os.Stdout, err) | ||||
| 		} else { | ||||
| 			fmt.Fprintln(os.Stderr, err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return err | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue