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