func (cli *DockerCli) Subcmd(name, signature, description string) *flag.FlagSet { flags := flag.NewFlagSet(name, flag.ContinueOnError) flags.Usage = func() { fmt.Fprintf(cli.err, "\nUsage: docker %s %s\n\n%s\n\n", name, signature, description) flags.PrintDefaults() os.Exit(2) } return flags }
// Run invokes the CLI with the given arguments. func (cli *CLI) Run(args []string) int { var githubAPIOpts GitHubAPIOpts var ghrOpts GhrOpts var stat bool var err error flags := flag.NewFlagSet(Name, flag.ContinueOnError) flags.SetOutput(cli.errStream) flags.Usage = func() { fmt.Fprint(cli.errStream, helpText) } // Options for GitHub API. flags.StringVar(&githubAPIOpts.OwnerName, []string{"u", "-username"}, "", "") flags.StringVar(&githubAPIOpts.RepoName, []string{"r", "-repository"}, "", "") flags.StringVar(&githubAPIOpts.Token, []string{"t", "-token"}, "", "") flags.StringVar(&githubAPIOpts.TargetCommitish, []string{"c", "-commitish"}, "", "") flags.BoolVar(&githubAPIOpts.Draft, []string{"-draft"}, false, "") flags.BoolVar(&githubAPIOpts.Prerelease, []string{"-prerelease"}, false, "") // Options to change ghr work. flags.IntVar(&ghrOpts.Parallel, []string{"p", "-parallel"}, -1, "") flags.BoolVar(&ghrOpts.Replace, []string{"-replace"}, false, "") flags.BoolVar(&ghrOpts.Delete, []string{"-delete"}, false, "") flags.BoolVar(&stat, []string{"-stat"}, false, "") // General options version := flags.Bool([]string{"v", "-version"}, false, "") debug := flags.Bool([]string{"-debug"}, false, "") // Parse all the flags if err := flags.Parse(args[1:]); err != nil { return ExitCodeParseFlagsError } // Show version. It also try to fetch latest version information from github if *version { fmt.Fprintf(cli.errStream, "ghr version %s, build %s \n", Version, GitCommit) select { case res := <-verCheckCh: if res != nil && res.Outdated { msg := fmt.Sprintf("Latest version of ghr is %s, please update it\n", res.Current) fmt.Fprint(cli.errStream, ColoredError(msg)) } case <-time.After(CheckTimeout): // do nothing } return ExitCodeOK } // Run as DEBUG mode if *debug { os.Setenv("GHR_DEBUG", "1") } // Set BaseURL _ = setBaseURL(&githubAPIOpts) // Set Token err = setToken(&githubAPIOpts) if err != nil { errMsg := fmt.Sprintf("Could not retrieve GitHub API Token.\n" + "Please set your Github API Token in the GITHUB_TOKEN env var.\n" + "Or set one via `-t` option.\n" + "See about GitHub API Token on https://github.com/blog/1509-personal-api-tokens\n", ) fmt.Fprint(cli.errStream, ColoredError(errMsg)) return ExitCodeTokenNotFound } // Set repository owner name. err = setOwner(&githubAPIOpts) if err != nil { errMsg := fmt.Sprintf("Could not retrieve repository user name: %s\n"+ "ghr try to retrieve git user name from `~/.gitcofig` file.\n"+ "Please set one via -u option or `~/.gitconfig` file.\n", err) fmt.Fprintf(cli.errStream, ColoredError(errMsg)) return ExitCodeOwnerNotFound } // Set repository owner name. err = setRepo(&githubAPIOpts) if err != nil { errMsg := fmt.Sprintf("Could not retrieve repository name: %s\n"+ "ghr try to retrieve github repository name from `.git/config` file.\n"+ "Please be sure you're in github repository. Or set one via `-r` options.\n", err) fmt.Fprintf(cli.errStream, ColoredError(errMsg)) return ExitCodeRepoNotFound } // Display statical information. if stat { err = ShowStat(cli.outStream, &githubAPIOpts) if err != nil { fmt.Fprintf(cli.errStream, ColoredError(err.Error())) return ExitCodeError } return ExitCodeOK } // Get the parsed arguments parsedArgs := flags.Args() if len(parsedArgs) != 2 { fmt.Fprintf(cli.errStream, ColoredError("Argument error: must specify two arguments - tag, path\n")) return ExitCodeBadArgs } // Get the tag of release and path tag, path := parsedArgs[0], parsedArgs[1] githubAPIOpts.TagName = tag // Get the asset to upload. assets, err := GetLocalAssets(path) if err != nil { errMsg := fmt.Sprintf("Failed to get assets from %s: %s\n"+ "Path must be included more than one file.\n", path, err) fmt.Fprintf(cli.errStream, ColoredError(errMsg)) return ExitCodeError } // Create release. err = CreateRelease(&ghrOpts, &githubAPIOpts) if err != nil { fmt.Fprintf(cli.errStream, ColoredError(err.Error())) return ExitCodeError } // Fetch All assets ID which is already on Github. // This is invorked when `--replace` option is used. if ghrOpts.Replace { err = FetchAssetID(assets, &githubAPIOpts) if err != nil { fmt.Fprintf(cli.errStream, ColoredError(err.Error())) return ExitCodeError } } // Use CPU efficiently cpu := runtime.NumCPU() runtime.GOMAXPROCS(cpu) // Limit amount of parallelism by number of logic CPU if ghrOpts.Parallel <= 0 { ghrOpts.Parallel = runtime.NumCPU() } // Start releasing doneCh, outCh, errCh := UploadAssets(assets, &ghrOpts, &githubAPIOpts) // Receive messages statusCh := make(chan bool) go func() { errOccurred := false for { select { case out := <-outCh: fmt.Fprintf(cli.outStream, out) case err := <-errCh: fmt.Fprintf(cli.errStream, ColoredError(err)) errOccurred = true case <-doneCh: statusCh <- errOccurred break } } }() // If more than one error is occured, return non-zero value errOccurred := <-statusCh if errOccurred { return ExitCodeRleaseError } return ExitCodeOK }
//FIXME Only used in tests func Parse(args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) { cmd := flag.NewFlagSet("run", flag.ContinueOnError) cmd.SetOutput(ioutil.Discard) cmd.Usage = nil return parseRun(cmd, args, sysInfo) }