github.com/jghiloni/cli@v6.28.1-0.20170628223758-0ce05fe032a2+incompatible/main.go (about) 1 package main 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "reflect" 8 "strings" 9 10 "code.cloudfoundry.org/cli/cf/cmd" 11 "code.cloudfoundry.org/cli/command" 12 "code.cloudfoundry.org/cli/command/common" 13 "code.cloudfoundry.org/cli/command/v2" 14 "code.cloudfoundry.org/cli/util/configv3" 15 "code.cloudfoundry.org/cli/util/panichandler" 16 "code.cloudfoundry.org/cli/util/ui" 17 "github.com/jessevdk/go-flags" 18 log "github.com/sirupsen/logrus" 19 ) 20 21 type UI interface { 22 DisplayError(err error) 23 } 24 25 var ErrFailed = errors.New("command failed") 26 var ParseErr = errors.New("incorrect type for arg") 27 28 func main() { 29 defer panichandler.HandlePanic() 30 parse(os.Args[1:]) 31 } 32 33 func parse(args []string) { 34 parser := flags.NewParser(&common.Commands, flags.HelpFlag) 35 parser.CommandHandler = executionWrapper 36 extraArgs, err := parser.ParseArgs(args) 37 if err == nil { 38 return 39 } 40 41 if flagErr, ok := err.(*flags.Error); ok { 42 switch flagErr.Type { 43 case flags.ErrHelp, flags.ErrUnknownFlag, flags.ErrExpectedArgument, flags.ErrInvalidChoice: 44 _, found := reflect.TypeOf(common.Commands).FieldByNameFunc( 45 func(fieldName string) bool { 46 field, _ := reflect.TypeOf(common.Commands).FieldByName(fieldName) 47 return parser.Active != nil && parser.Active.Name == field.Tag.Get("command") 48 }, 49 ) 50 51 if found && flagErr.Type == flags.ErrUnknownFlag && parser.Active.Name == "set-env" { 52 newArgs := []string{} 53 for _, arg := range args { 54 if arg[0] == '-' { 55 newArgs = append(newArgs, fmt.Sprintf("%s%s", v2.WorkAroundPrefix, arg)) 56 } else { 57 newArgs = append(newArgs, arg) 58 } 59 } 60 parse(newArgs) 61 return 62 } 63 64 if flagErr.Type == flags.ErrUnknownFlag || flagErr.Type == flags.ErrExpectedArgument || flagErr.Type == flags.ErrInvalidChoice { 65 fmt.Fprintf(os.Stderr, "Incorrect Usage: %s\n\n", flagErr.Error()) 66 } 67 68 if found { 69 parse([]string{"help", parser.Active.Name}) 70 } else { 71 switch len(extraArgs) { 72 case 0: 73 parse([]string{"help"}) 74 case 1: 75 if !isOption(extraArgs[0]) || (len(args) > 1 && extraArgs[0] == "-a") { 76 parse([]string{"help", extraArgs[0]}) 77 } else { 78 parse([]string{"help"}) 79 } 80 default: 81 if isCommand(extraArgs[0]) { 82 parse([]string{"help", extraArgs[0]}) 83 } else { 84 parse(extraArgs[1:]) 85 } 86 } 87 } 88 89 if flagErr.Type == flags.ErrUnknownFlag || flagErr.Type == flags.ErrExpectedArgument || flagErr.Type == flags.ErrInvalidChoice { 90 os.Exit(1) 91 } 92 case flags.ErrRequired: 93 fmt.Fprintf(os.Stderr, "Incorrect Usage: %s\n\n", flagErr.Error()) 94 parse([]string{"help", args[0]}) 95 os.Exit(1) 96 case flags.ErrMarshal: 97 errMessage := strings.Split(flagErr.Message, ":") 98 fmt.Fprintf(os.Stderr, "Incorrect Usage: %s\n\n", errMessage[0]) 99 parse([]string{"help", args[0]}) 100 os.Exit(1) 101 case flags.ErrUnknownCommand: 102 cmd.Main(os.Getenv("CF_TRACE"), os.Args) 103 case flags.ErrCommandRequired: 104 if common.Commands.VerboseOrVersion { 105 parse([]string{"version"}) 106 } else { 107 parse([]string{"help"}) 108 } 109 default: 110 fmt.Fprintf(os.Stderr, "Unexpected flag error\ntype: %s\nmessage: %s\n", flagErr.Type, flagErr.Error()) 111 } 112 } else if err == ErrFailed { 113 os.Exit(1) 114 } else if err == ParseErr { 115 fmt.Println() 116 parse([]string{"help", args[0]}) 117 os.Exit(1) 118 } else { 119 fmt.Fprintf(os.Stderr, "Unexpected error: %s\n", err.Error()) 120 os.Exit(1) 121 } 122 } 123 124 func isCommand(s string) bool { 125 _, found := reflect.TypeOf(common.Commands).FieldByNameFunc( 126 func(fieldName string) bool { 127 field, _ := reflect.TypeOf(common.Commands).FieldByName(fieldName) 128 return s == field.Tag.Get("command") || s == field.Tag.Get("alias") 129 }) 130 131 return found 132 } 133 func isOption(s string) bool { 134 return strings.HasPrefix(s, "-") 135 } 136 137 func executionWrapper(cmd flags.Commander, args []string) error { 138 cfConfig, err := configv3.LoadConfig(configv3.FlagOverride{ 139 Verbose: common.Commands.VerboseOrVersion, 140 }) 141 if err != nil { 142 return err 143 } 144 145 defer func() { 146 configWriteErr := configv3.WriteConfig(cfConfig) 147 if configWriteErr != nil { 148 fmt.Fprintf(os.Stderr, "Error writing config: %s", configWriteErr.Error()) 149 } 150 }() 151 152 if extendedCmd, ok := cmd.(command.ExtendedCommander); ok { 153 commandUI, err := ui.NewUI(cfConfig) 154 if err != nil { 155 return err 156 } 157 158 log.SetOutput(os.Stderr) 159 log.SetLevel(log.Level(cfConfig.LogLevel())) 160 161 err = extendedCmd.Setup(cfConfig, commandUI) 162 if err != nil { 163 return handleError(err, commandUI) 164 } 165 return handleError(extendedCmd.Execute(args), commandUI) 166 } 167 168 return fmt.Errorf("command does not conform to ExtendedCommander") 169 } 170 171 func handleError(err error, commandUI UI) error { 172 if err == nil { 173 return nil 174 } 175 176 commandUI.DisplayError(err) 177 178 switch err.(type) { 179 case command.ArgumentCombinationError: 180 return ParseErr 181 case command.ParseArgumentError: 182 return ParseErr 183 case command.RequiredArgumentError: 184 return ParseErr 185 case command.ThreeRequiredArgumentsError: 186 return ParseErr 187 } 188 189 return ErrFailed 190 }