mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2025-06-26 18:18:24 +00:00
[no-relnote] Migrate to urfave v3
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
This commit is contained in:
347
vendor/github.com/urfave/cli/v3/command_run.go
generated
vendored
Normal file
347
vendor/github.com/urfave/cli/v3/command_run.go
generated
vendored
Normal file
@@ -0,0 +1,347 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"slices"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
func (cmd *Command) parseArgsFromStdin() ([]string, error) {
|
||||
type state int
|
||||
const (
|
||||
stateSearchForToken state = -1
|
||||
stateSearchForString state = 0
|
||||
)
|
||||
|
||||
st := stateSearchForToken
|
||||
linenum := 1
|
||||
token := ""
|
||||
args := []string{}
|
||||
|
||||
breader := bufio.NewReader(cmd.Reader)
|
||||
|
||||
outer:
|
||||
for {
|
||||
ch, _, err := breader.ReadRune()
|
||||
if err == io.EOF {
|
||||
switch st {
|
||||
case stateSearchForToken:
|
||||
if token != "--" {
|
||||
args = append(args, token)
|
||||
}
|
||||
case stateSearchForString:
|
||||
// make sure string is not empty
|
||||
for _, t := range token {
|
||||
if !unicode.IsSpace(t) {
|
||||
args = append(args, token)
|
||||
}
|
||||
}
|
||||
}
|
||||
break outer
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch st {
|
||||
case stateSearchForToken:
|
||||
if unicode.IsSpace(ch) || ch == '"' {
|
||||
if ch == '\n' {
|
||||
linenum++
|
||||
}
|
||||
if token != "" {
|
||||
// end the processing here
|
||||
if token == "--" {
|
||||
break outer
|
||||
}
|
||||
args = append(args, token)
|
||||
token = ""
|
||||
}
|
||||
if ch == '"' {
|
||||
st = stateSearchForString
|
||||
}
|
||||
continue
|
||||
}
|
||||
token += string(ch)
|
||||
case stateSearchForString:
|
||||
if ch != '"' {
|
||||
token += string(ch)
|
||||
} else {
|
||||
if token != "" {
|
||||
args = append(args, token)
|
||||
token = ""
|
||||
}
|
||||
/*else {
|
||||
//TODO. Should we pass in empty strings ?
|
||||
}*/
|
||||
st = stateSearchForToken
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tracef("parsed stdin args as %v (cmd=%[2]q)", args, cmd.Name)
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
||||
// Run is the entry point to the command graph. The positional
|
||||
// arguments are parsed according to the Flag and Command
|
||||
// definitions and the matching Action functions are run.
|
||||
func (cmd *Command) Run(ctx context.Context, osArgs []string) (deferErr error) {
|
||||
_, deferErr = cmd.run(ctx, osArgs)
|
||||
return
|
||||
}
|
||||
|
||||
func (cmd *Command) run(ctx context.Context, osArgs []string) (_ context.Context, deferErr error) {
|
||||
tracef("running with arguments %[1]q (cmd=%[2]q)", osArgs, cmd.Name)
|
||||
cmd.setupDefaults(osArgs)
|
||||
|
||||
if v, ok := ctx.Value(commandContextKey).(*Command); ok {
|
||||
tracef("setting parent (cmd=%[1]q) command from context.Context value (cmd=%[2]q)", v.Name, cmd.Name)
|
||||
cmd.parent = v
|
||||
}
|
||||
|
||||
if cmd.parent == nil {
|
||||
if cmd.ReadArgsFromStdin {
|
||||
if args, err := cmd.parseArgsFromStdin(); err != nil {
|
||||
return ctx, err
|
||||
} else {
|
||||
osArgs = append(osArgs, args...)
|
||||
}
|
||||
}
|
||||
// handle the completion flag separately from the flagset since
|
||||
// completion could be attempted after a flag, but before its value was put
|
||||
// on the command line. this causes the flagset to interpret the completion
|
||||
// flag name as the value of the flag before it which is undesirable
|
||||
// note that we can only do this because the shell autocomplete function
|
||||
// always appends the completion flag at the end of the command
|
||||
tracef("checking osArgs %v (cmd=%[2]q)", osArgs, cmd.Name)
|
||||
cmd.shellCompletion, osArgs = checkShellCompleteFlag(cmd, osArgs)
|
||||
|
||||
tracef("setting cmd.shellCompletion=%[1]v from checkShellCompleteFlag (cmd=%[2]q)", cmd.shellCompletion && cmd.EnableShellCompletion, cmd.Name)
|
||||
cmd.shellCompletion = cmd.EnableShellCompletion && cmd.shellCompletion
|
||||
}
|
||||
|
||||
tracef("using post-checkShellCompleteFlag arguments %[1]q (cmd=%[2]q)", osArgs, cmd.Name)
|
||||
|
||||
tracef("setting self as cmd in context (cmd=%[1]q)", cmd.Name)
|
||||
ctx = context.WithValue(ctx, commandContextKey, cmd)
|
||||
|
||||
if cmd.parent == nil {
|
||||
cmd.setupCommandGraph()
|
||||
}
|
||||
|
||||
var rargs Args = &stringSliceArgs{v: osArgs}
|
||||
for _, f := range cmd.allFlags() {
|
||||
if err := f.PreParse(); err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
}
|
||||
|
||||
var args Args = &stringSliceArgs{rargs.Tail()}
|
||||
var err error
|
||||
|
||||
if cmd.SkipFlagParsing {
|
||||
tracef("skipping flag parsing (cmd=%[1]q)", cmd.Name)
|
||||
cmd.parsedArgs = args
|
||||
} else {
|
||||
cmd.parsedArgs, err = cmd.parseFlags(args)
|
||||
}
|
||||
|
||||
tracef("using post-parse arguments %[1]q (cmd=%[2]q)", args, cmd.Name)
|
||||
|
||||
if checkCompletions(ctx, cmd) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
tracef("setting deferErr from %[1]q (cmd=%[2]q)", err, cmd.Name)
|
||||
deferErr = err
|
||||
|
||||
cmd.isInError = true
|
||||
if cmd.OnUsageError != nil {
|
||||
err = cmd.OnUsageError(ctx, cmd, err, cmd.parent != nil)
|
||||
err = cmd.handleExitCoder(ctx, err)
|
||||
return ctx, err
|
||||
}
|
||||
fmt.Fprintf(cmd.Root().ErrWriter, "Incorrect Usage: %s\n\n", err.Error())
|
||||
if cmd.Suggest {
|
||||
if suggestion, err := cmd.suggestFlagFromError(err, ""); err == nil {
|
||||
fmt.Fprintf(cmd.Root().ErrWriter, "%s", suggestion)
|
||||
}
|
||||
}
|
||||
if !cmd.hideHelp() {
|
||||
if cmd.parent == nil {
|
||||
tracef("running ShowAppHelp")
|
||||
if err := ShowAppHelp(cmd); err != nil {
|
||||
tracef("SILENTLY IGNORING ERROR running ShowAppHelp %[1]v (cmd=%[2]q)", err, cmd.Name)
|
||||
}
|
||||
} else {
|
||||
tracef("running ShowCommandHelp with %[1]q", cmd.Name)
|
||||
if err := ShowCommandHelp(ctx, cmd, cmd.Name); err != nil {
|
||||
tracef("SILENTLY IGNORING ERROR running ShowCommandHelp with %[1]q %[2]v", cmd.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
if cmd.checkHelp() {
|
||||
return ctx, helpCommandAction(ctx, cmd)
|
||||
} else {
|
||||
tracef("no help is wanted (cmd=%[1]q)", cmd.Name)
|
||||
}
|
||||
|
||||
if cmd.parent == nil && !cmd.HideVersion && checkVersion(cmd) {
|
||||
ShowVersion(cmd)
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
for _, flag := range cmd.allFlags() {
|
||||
if err := flag.PostParse(); err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.After != nil && !cmd.Root().shellCompletion {
|
||||
defer func() {
|
||||
if err := cmd.After(ctx, cmd); err != nil {
|
||||
err = cmd.handleExitCoder(ctx, err)
|
||||
|
||||
if deferErr != nil {
|
||||
deferErr = newMultiError(deferErr, err)
|
||||
} else {
|
||||
deferErr = err
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
for _, grp := range cmd.MutuallyExclusiveFlags {
|
||||
if err := grp.check(cmd); err != nil {
|
||||
if cmd.OnUsageError != nil {
|
||||
err = cmd.OnUsageError(ctx, cmd, err, cmd.parent != nil)
|
||||
} else {
|
||||
_ = ShowSubcommandHelp(cmd)
|
||||
}
|
||||
return ctx, err
|
||||
}
|
||||
}
|
||||
|
||||
var subCmd *Command
|
||||
if cmd.parsedArgs.Present() {
|
||||
tracef("checking positional args %[1]q (cmd=%[2]q)", cmd.parsedArgs, cmd.Name)
|
||||
|
||||
name := cmd.parsedArgs.First()
|
||||
|
||||
tracef("using first positional argument as sub-command name=%[1]q (cmd=%[2]q)", name, cmd.Name)
|
||||
|
||||
if cmd.SuggestCommandFunc != nil && name != "--" {
|
||||
name = cmd.SuggestCommandFunc(cmd.Commands, name)
|
||||
}
|
||||
subCmd = cmd.Command(name)
|
||||
if subCmd == nil {
|
||||
hasDefault := cmd.DefaultCommand != ""
|
||||
isFlagName := slices.Contains(cmd.FlagNames(), name)
|
||||
|
||||
if hasDefault {
|
||||
tracef("using default command=%[1]q (cmd=%[2]q)", cmd.DefaultCommand, cmd.Name)
|
||||
}
|
||||
|
||||
if isFlagName || hasDefault {
|
||||
argsWithDefault := cmd.argsWithDefaultCommand(args)
|
||||
tracef("using default command args=%[1]q (cmd=%[2]q)", argsWithDefault, cmd.Name)
|
||||
if !reflect.DeepEqual(args, argsWithDefault) {
|
||||
subCmd = cmd.Command(argsWithDefault.First())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if cmd.parent == nil && cmd.DefaultCommand != "" {
|
||||
tracef("no positional args present; checking default command %[1]q (cmd=%[2]q)", cmd.DefaultCommand, cmd.Name)
|
||||
|
||||
if dc := cmd.Command(cmd.DefaultCommand); dc != cmd {
|
||||
subCmd = dc
|
||||
}
|
||||
}
|
||||
|
||||
// If a subcommand has been resolved, let it handle the remaining execution.
|
||||
if subCmd != nil {
|
||||
tracef("running sub-command %[1]q with arguments %[2]q (cmd=%[3]q)", subCmd.Name, cmd.Args(), cmd.Name)
|
||||
|
||||
// It is important that we overwrite the ctx variable in the current
|
||||
// function so any defer'd functions use the new context returned
|
||||
// from the sub command.
|
||||
ctx, err = subCmd.run(ctx, cmd.Args().Slice())
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// This code path is the innermost command execution. Here we actually
|
||||
// perform the command action.
|
||||
//
|
||||
// First, resolve the chain of nested commands up to the parent.
|
||||
var cmdChain []*Command
|
||||
for p := cmd; p != nil; p = p.parent {
|
||||
cmdChain = append(cmdChain, p)
|
||||
}
|
||||
slices.Reverse(cmdChain)
|
||||
|
||||
// Run Before actions in order.
|
||||
for _, cmd := range cmdChain {
|
||||
if cmd.Before == nil {
|
||||
continue
|
||||
}
|
||||
if bctx, err := cmd.Before(ctx, cmd); err != nil {
|
||||
deferErr = cmd.handleExitCoder(ctx, err)
|
||||
return ctx, deferErr
|
||||
} else if bctx != nil {
|
||||
ctx = bctx
|
||||
}
|
||||
}
|
||||
|
||||
// Run flag actions in order.
|
||||
// These take a context, so this has to happen after Before actions.
|
||||
for _, cmd := range cmdChain {
|
||||
tracef("running flag actions (cmd=%[1]q)", cmd.Name)
|
||||
if err := cmd.runFlagActions(ctx); err != nil {
|
||||
deferErr = cmd.handleExitCoder(ctx, err)
|
||||
return ctx, deferErr
|
||||
}
|
||||
}
|
||||
|
||||
if err := cmd.checkAllRequiredFlags(); err != nil {
|
||||
cmd.isInError = true
|
||||
_ = ShowSubcommandHelp(cmd)
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// Run the command action.
|
||||
if len(cmd.Arguments) > 0 {
|
||||
rargs := cmd.Args().Slice()
|
||||
tracef("calling argparse with %[1]v", rargs)
|
||||
for _, arg := range cmd.Arguments {
|
||||
var err error
|
||||
rargs, err = arg.Parse(rargs)
|
||||
if err != nil {
|
||||
tracef("calling with %[1]v (cmd=%[2]q)", err, cmd.Name)
|
||||
if cmd.OnUsageError != nil {
|
||||
err = cmd.OnUsageError(ctx, cmd, err, cmd.parent != nil)
|
||||
}
|
||||
err = cmd.handleExitCoder(ctx, err)
|
||||
return ctx, err
|
||||
}
|
||||
}
|
||||
cmd.parsedArgs = &stringSliceArgs{v: rargs}
|
||||
}
|
||||
|
||||
if err := cmd.Action(ctx, cmd); err != nil {
|
||||
tracef("calling handleExitCoder with %[1]v (cmd=%[2]q)", err, cmd.Name)
|
||||
deferErr = cmd.handleExitCoder(ctx, err)
|
||||
}
|
||||
|
||||
tracef("returning deferErr (cmd=%[1]q) %[2]q", cmd.Name, deferErr)
|
||||
return ctx, deferErr
|
||||
}
|
||||
Reference in New Issue
Block a user