github.com/asifdxtreme/cli@v6.1.3-0.20150123051144-9ead8700b4ae+incompatible/main/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 "runtime" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/cloudfoundry/cli/cf/api" 12 "github.com/cloudfoundry/cli/cf/app" 13 "github.com/cloudfoundry/cli/cf/command_factory" 14 "github.com/cloudfoundry/cli/cf/command_metadata" 15 "github.com/cloudfoundry/cli/cf/command_runner" 16 "github.com/cloudfoundry/cli/cf/configuration/config_helpers" 17 "github.com/cloudfoundry/cli/cf/configuration/core_config" 18 "github.com/cloudfoundry/cli/cf/configuration/plugin_config" 19 . "github.com/cloudfoundry/cli/cf/i18n" 20 "github.com/cloudfoundry/cli/cf/i18n/detection" 21 "github.com/cloudfoundry/cli/cf/manifest" 22 "github.com/cloudfoundry/cli/cf/net" 23 "github.com/cloudfoundry/cli/cf/panic_printer" 24 "github.com/cloudfoundry/cli/cf/requirements" 25 "github.com/cloudfoundry/cli/cf/terminal" 26 "github.com/cloudfoundry/cli/cf/trace" 27 "github.com/cloudfoundry/cli/plugin/rpc" 28 "github.com/codegangsta/cli" 29 ) 30 31 var deps = setupDependencies() 32 33 type cliDependencies struct { 34 termUI terminal.UI 35 configRepo core_config.Repository 36 pluginConfig plugin_config.PluginConfiguration 37 manifestRepo manifest.ManifestRepository 38 apiRepoLocator api.RepositoryLocator 39 gateways map[string]net.Gateway 40 teePrinter *terminal.TeePrinter 41 detector detection.Detector 42 } 43 44 func setupDependencies() (deps *cliDependencies) { 45 deps = new(cliDependencies) 46 47 deps.teePrinter = terminal.NewTeePrinter() 48 49 deps.termUI = terminal.NewUI(os.Stdin, deps.teePrinter) 50 51 deps.manifestRepo = manifest.NewManifestDiskRepository() 52 53 errorHandler := func(err error) { 54 if err != nil { 55 deps.termUI.Failed(fmt.Sprintf("Config error: %s", err)) 56 } 57 } 58 deps.configRepo = core_config.NewRepositoryFromFilepath(config_helpers.DefaultFilePath(), errorHandler) 59 deps.pluginConfig = plugin_config.NewPluginConfig(errorHandler) 60 deps.detector = &detection.JibberJabberDetector{} 61 62 T = Init(deps.configRepo, deps.detector) 63 64 terminal.UserAskedForColors = deps.configRepo.ColorEnabled() 65 terminal.InitColorSupport() 66 67 if os.Getenv("CF_TRACE") != "" { 68 trace.Logger = trace.NewLogger(os.Getenv("CF_TRACE")) 69 } else { 70 trace.Logger = trace.NewLogger(deps.configRepo.Trace()) 71 } 72 73 deps.gateways = map[string]net.Gateway{ 74 "auth": net.NewUAAGateway(deps.configRepo, deps.termUI), 75 "cloud-controller": net.NewCloudControllerGateway(deps.configRepo, time.Now, deps.termUI), 76 "uaa": net.NewUAAGateway(deps.configRepo, deps.termUI), 77 } 78 deps.apiRepoLocator = api.NewRepositoryLocator(deps.configRepo, deps.gateways) 79 80 return 81 } 82 83 func main() { 84 defer handlePanics(deps.teePrinter) 85 defer deps.configRepo.Close() 86 87 cmdFactory := command_factory.NewFactory(deps.termUI, deps.configRepo, deps.manifestRepo, deps.apiRepoLocator, deps.pluginConfig) 88 requirementsFactory := requirements.NewFactory(deps.termUI, deps.configRepo, deps.apiRepoLocator) 89 cmdRunner := command_runner.NewRunner(cmdFactory, requirementsFactory, deps.termUI) 90 pluginsConfig := plugin_config.NewPluginConfig(func(err error) { panic(err) }) 91 pluginList := pluginsConfig.Plugins() 92 93 var badFlags string 94 metaDatas := cmdFactory.CommandMetadatas() 95 //return only metadata for current command 96 metaDatas = mergePluginMetaData(metaDatas, pluginList) 97 98 if len(os.Args) > 1 { 99 flags := cmdFactory.GetCommandFlags(os.Args[1]) 100 totalArgs, _ := cmdFactory.GetCommandTotalArgs(os.Args[1]) 101 102 if args2skip := totalArgs + 2; len(os.Args) >= args2skip { 103 badFlags = matchArgAndFlags(flags, os.Args[args2skip:]) 104 } 105 106 if badFlags != "" { 107 badFlags = badFlags + "\n\n" 108 } 109 } 110 111 injectHelpTemplate(badFlags) 112 113 theApp := app.NewApp(cmdRunner, metaDatas...) 114 //command `cf` without argument 115 if len(os.Args) == 1 || os.Args[1] == "help" || requestHelp(os.Args[2:]) { 116 theApp.Run(os.Args) 117 } else if cmdFactory.CheckIfCoreCmdExists(os.Args[1]) { 118 callCoreCommand(os.Args[0:], theApp) 119 } else { 120 // run each plugin and find the method/ 121 // run method if exist 122 123 ran := rpc.RunMethodIfExists(theApp, os.Args[1:], deps.teePrinter, deps.teePrinter, pluginList) 124 if !ran { 125 theApp.Run(os.Args) 126 } 127 } 128 } 129 130 func gatewaySliceFromMap(gateway_map map[string]net.Gateway) []net.WarningProducer { 131 gateways := []net.WarningProducer{} 132 for _, gateway := range gateway_map { 133 gateways = append(gateways, gateway) 134 } 135 return gateways 136 } 137 138 func injectHelpTemplate(badFlags string) { 139 cli.CommandHelpTemplate = fmt.Sprintf(`%sNAME: 140 {{.Name}} - {{.Description}} 141 {{with .ShortName}} 142 ALIAS: 143 {{.}} 144 {{end}} 145 USAGE: 146 {{.Usage}}{{with .Flags}} 147 148 OPTIONS: 149 {{range .}} {{.}} 150 {{end}}{{else}} 151 {{end}}`, badFlags) 152 } 153 154 func handlePanics(printer terminal.Printer) { 155 panic_printer.UI = terminal.NewUI(os.Stdin, printer) 156 157 commandArgs := strings.Join(os.Args, " ") 158 stackTrace := generateBacktrace() 159 160 err := recover() 161 panic_printer.DisplayCrashDialog(err, commandArgs, stackTrace) 162 163 if err != nil { 164 os.Exit(1) 165 } 166 } 167 168 func generateBacktrace() string { 169 stackByteCount := 0 170 STACK_SIZE_LIMIT := 1024 * 1024 171 var bytes []byte 172 for stackSize := 1024; (stackByteCount == 0 || stackByteCount == stackSize) && stackSize < STACK_SIZE_LIMIT; stackSize = 2 * stackSize { 173 bytes = make([]byte, stackSize) 174 stackByteCount = runtime.Stack(bytes, true) 175 } 176 stackTrace := "\t" + strings.Replace(string(bytes), "\n", "\n\t", -1) 177 return stackTrace 178 } 179 180 func callCoreCommand(args []string, theApp *cli.App) { 181 err := theApp.Run(args) 182 if err != nil { 183 os.Exit(1) 184 } 185 gateways := gatewaySliceFromMap(deps.gateways) 186 187 warningsCollector := net.NewWarningsCollector(deps.termUI, gateways...) 188 warningsCollector.PrintWarnings() 189 } 190 191 func matchArgAndFlags(flags []string, args []string) string { 192 var badFlag string 193 var lastPassed bool 194 multipleFlagErr := false 195 196 Loop: 197 for _, arg := range args { 198 prefix := "" 199 200 //only take flag name, ignore value after '=' 201 arg = strings.Split(arg, "=")[0] 202 203 if arg == "--h" || arg == "-h" { 204 continue Loop 205 } 206 207 if strings.HasPrefix(arg, "--") { 208 prefix = "--" 209 } else if strings.HasPrefix(arg, "-") { 210 prefix = "-" 211 } 212 arg = strings.TrimLeft(arg, prefix) 213 214 //skip verification for negative integers, e.g. -i -10 215 if lastPassed { 216 lastPassed = false 217 if _, err := strconv.ParseInt(arg, 10, 32); err == nil { 218 continue Loop 219 } 220 } 221 222 if prefix != "" { 223 for _, flag := range flags { 224 if flag == arg { 225 lastPassed = true 226 continue Loop 227 } 228 } 229 230 if badFlag == "" { 231 badFlag = fmt.Sprintf("\"%s%s\"", prefix, arg) 232 } else { 233 multipleFlagErr = true 234 badFlag = badFlag + fmt.Sprintf(", \"%s%s\"", prefix, arg) 235 } 236 } 237 } 238 239 if multipleFlagErr && badFlag != "" { 240 badFlag = fmt.Sprintf("%s %s", T("Unknown flags:"), badFlag) 241 } else if badFlag != "" { 242 badFlag = fmt.Sprintf("%s %s", T("Unknown flag"), badFlag) 243 } 244 245 return badFlag 246 } 247 248 func mergePluginMetaData(coreMetas []command_metadata.CommandMetadata, pluginMetas map[string]plugin_config.PluginMetadata) []command_metadata.CommandMetadata { 249 for _, meta := range pluginMetas { 250 for _, cmd := range meta.Commands { 251 tmpMeta := command_metadata.CommandMetadata{} 252 if cmd.UsageDetails.Usage == "" { 253 tmpMeta.Usage = "N/A" 254 } else { 255 tmpMeta.Usage = cmd.UsageDetails.Usage 256 } 257 tmpMeta.Name = cmd.Name 258 tmpMeta.ShortName = cmd.Alias 259 tmpMeta.Description = cmd.HelpText 260 261 for k, v := range cmd.UsageDetails.Options { 262 tmpMeta.Flags = append(tmpMeta.Flags, cli.BoolFlag{Name: k, Usage: v}) 263 } 264 coreMetas = append(coreMetas, tmpMeta) 265 } 266 } 267 268 return coreMetas 269 } 270 271 func requestHelp(args []string) bool { 272 for _, v := range args { 273 if v == "-h" || v == "--help" { 274 return true 275 } 276 } 277 278 return false 279 }