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  }