// Run generates a new cli project. It returns exit code func (c *NewCommand) Run(args []string) int { var ( commands []skeleton.Command flags []skeleton.Flag frameworkStr string owner string skipTest bool verbose bool ) uflag := c.Meta.NewFlagSet("new", c.Help()) uflag.Var((*CommandFlag)(&commands), "command", "command") uflag.Var((*CommandFlag)(&commands), "c", "command (short)") uflag.Var((*FlagFlag)(&flags), "flag", "flag") uflag.Var((*FlagFlag)(&flags), "f", "flag (short)") uflag.StringVar(&frameworkStr, "framework", defaultFrameworkString, "framework") uflag.StringVar(&frameworkStr, "F", defaultFrameworkString, "framework (short)") uflag.StringVar(&owner, "owner", "", "owner") uflag.StringVar(&owner, "o", "", "owner (short)") uflag.BoolVar(&skipTest, "skip-test", false, "skip-test") uflag.BoolVar(&skipTest, "T", false, "skip-test (short)") uflag.BoolVar(&verbose, "verbose", false, "verbose") uflag.BoolVar(&verbose, "V", false, "verbose (short)") if err := uflag.Parse(args); err != nil { return 1 } parsedArgs := uflag.Args() if len(parsedArgs) != 1 { msg := fmt.Sprintf("Invalid arguments: %s", strings.Join(parsedArgs, " ")) c.UI.Error(msg) return 1 } name := parsedArgs[0] // TODO, should be configurable // or chagne direcotry to GOPATH/github.com/owner/output // Some gcli template assume command is executed // from GOPATH/github.com/owner output := name if _, err := os.Stat(output); !os.IsNotExist(err) { msg := fmt.Sprintf("Cannot create directory %s: file exists", output) c.UI.Error(msg) return 1 } framework, err := skeleton.FrameworkByName(frameworkStr) if err != nil { c.UI.Error(fmt.Sprintf("Failed to generate %q: %s", name, err.Error())) return 1 } // Use .gitconfig value. if owner == "" { owner, err = gitconfig.GithubUser() if err != nil { owner, err = gitconfig.Username() if err != nil { msg := "Cannot find owner name\n" + "By default, owener name is retrieved from `~/.gitcofig` file.\n" + "Please set one via -owner option or `~/.gitconfig` file." c.UI.Error(msg) return 1 } } } // Define Executable executable := &skeleton.Executable{ Name: name, Owner: owner, Commands: commands, Flags: flags, Version: skeleton.DefaultVersion, Description: skeleton.DefaultDescription, } // Channels to receive artifact path (result) and error artifactCh, errCh := make(chan string), make(chan error) // Define Skeleton skeleton := &skeleton.Skeleton{ Path: output, Framework: framework, SkipTest: skipTest, Executable: executable, ArtifactCh: artifactCh, ErrCh: errCh, Verbose: verbose, LogWriter: os.Stdout, } // Create project directory doneCh := skeleton.Generate() for { select { case artifact := <-artifactCh: c.UI.Output(fmt.Sprintf(" Created %s", artifact)) case err := <-errCh: c.UI.Error(fmt.Sprintf("Failed to generate %s: %s", output, err.Error())) // If some file are created before error happend // Should be cleanuped if _, err := os.Stat(output); !os.IsNotExist(err) { c.UI.Output(fmt.Sprintf("Cleanup %s", output)) os.RemoveAll(output) } return ExitCodeFailed case <-doneCh: c.UI.Info(fmt.Sprintf("====> Successfully generated %s", name)) return ExitCodeOK } } }
// Run generates a new cli project. It returns exit code func (c *NewCommand) Run(args []string) int { var ( commands []*skeleton.Command flags []*skeleton.Flag frameworkStr string owner string staticDir string vcsHost string current bool skipTest bool verbose bool ) uflag := c.Meta.NewFlagSet("new", c.Help()) uflag.Var((*CommandFlag)(&commands), "command", "command") uflag.Var((*CommandFlag)(&commands), "c", "command (short)") uflag.Var((*FlagFlag)(&flags), "flag", "flag") uflag.Var((*FlagFlag)(&flags), "f", "flag (short)") uflag.StringVar(&frameworkStr, "framework", defaultFrameworkString, "framework") uflag.StringVar(&frameworkStr, "F", defaultFrameworkString, "framework (short)") uflag.StringVar(&owner, "owner", "", "owner") uflag.StringVar(&owner, "o", "", "owner (short)") uflag.StringVar(&staticDir, "static-dir", "", "") uflag.StringVar(&vcsHost, "vcs", DefaultVCSHost, "") uflag.BoolVar(¤t, "current", false, "current") uflag.BoolVar(¤t, "C", false, "current") uflag.BoolVar(&skipTest, "skip-test", false, "skip-test") uflag.BoolVar(&skipTest, "T", false, "skip-test (short)") uflag.BoolVar(&verbose, "verbose", false, "verbose") uflag.BoolVar(&verbose, "V", false, "verbose (short)") if err := uflag.Parse(args); err != nil { return 1 } parsedArgs := uflag.Args() if len(parsedArgs) != 1 { msg := fmt.Sprintf("Invalid arguments: %s", strings.Join(parsedArgs, " ")) c.UI.Error(msg) return 1 } name := parsedArgs[0] // If owner is not provided, use .gitconfig value. if owner == "" { var err error owner, err = gitconfig.GithubUser() if err != nil { owner, err = gitconfig.Username() if err != nil { msg := "Cannot find owner name\n" + "By default, owener name is retrieved from `~/.gitcofig` file.\n" + "Please set one via -owner option or `~/.gitconfig` file." c.UI.Error(msg) return 1 } } } currentDir, err := os.Getwd() if err != nil { c.UI.Error(fmt.Sprintf( "Failed to get current directroy: %s", err)) return ExitCodeFailed } gopath := os.Getenv(EnvGoPath) if gopath == "" { c.UI.Error(fmt.Sprintf( "Failed to read GOPATH: it should not be empty")) return ExitCodeFailed } idealDir := filepath.Join(gopath, "src", vcsHost, owner) output := name if currentDir != idealDir && !current { c.UI.Output("") c.UI.Output(fmt.Sprintf("====> WARNING: You are not in the directory gcli expects.")) c.UI.Output(fmt.Sprintf(" The codes will be generated be in $GOPATH/src/%s/%s.", vcsHost, owner)) c.UI.Output(fmt.Sprintf(" Not in the current directory. This is because the output")) c.UI.Output(fmt.Sprintf(" codes use import path based on that path.")) c.UI.Output("") output = filepath.Join(idealDir, name) } if _, err := os.Stat(output); !os.IsNotExist(err) { msg := fmt.Sprintf("Cannot create directory %s: file exists", output) c.UI.Error(msg) return 1 } framework, err := skeleton.FrameworkByName(frameworkStr) if err != nil { c.UI.Error(fmt.Sprintf("Failed to generate %q: %s", name, err.Error())) return 1 } if staticDir == "" { localDir, err := c.LocalDir() if err != nil { c.UI.Error(err.Error()) return ExitCodeFailed } staticDir = filepath.Join(localDir, DefaultLocalStaticDir) } // Define Executable executable := &skeleton.Executable{ Name: name, Owner: owner, VCSHost: vcsHost, Commands: commands, Flags: flags, Version: skeleton.DefaultVersion, Description: skeleton.DefaultDescription, } // Channels to receive artifact path (result) and error artifactCh, errCh := make(chan string), make(chan error) // Define Skeleton skeleton := &skeleton.Skeleton{ Path: output, StaticDir: staticDir, Framework: framework, SkipTest: skipTest, Executable: executable, ArtifactCh: artifactCh, ErrCh: errCh, Verbose: verbose, LogWriter: os.Stdout, } // Create project directory doneCh := skeleton.Generate() for { select { case artifact := <-artifactCh: c.UI.Output(fmt.Sprintf(" Created %s", artifact)) case err := <-errCh: c.UI.Error(fmt.Sprintf("Failed to generate %s: %s", output, err.Error())) // If some file are created before error happend // Should be cleanuped if _, err := os.Stat(output); !os.IsNotExist(err) { c.UI.Output(fmt.Sprintf("Cleanup %s", output)) os.RemoveAll(output) } return ExitCodeFailed case <-doneCh: c.UI.Info(fmt.Sprintf("====> Successfully generated %s", name)) return ExitCodeOK } } }
// Run generates a new cli project. It returns exit code func (c *ApplyCommand) Run(args []string) int { var ( frameworkStr string owner string name string current bool skipTest bool verbose bool ) uflag := c.Meta.NewFlagSet("apply", c.Help()) uflag.StringVar(&frameworkStr, "framework", "", "framework") uflag.StringVar(&frameworkStr, "F", "", "framework (short)") uflag.BoolVar(¤t, "current", false, "current") uflag.BoolVar(¤t, "C", false, "current") uflag.BoolVar(&skipTest, "skip-test", false, "skip-test") uflag.BoolVar(&skipTest, "T", false, "skip-test (short)") uflag.BoolVar(&verbose, "verbose", false, "verbose") uflag.BoolVar(&verbose, "V", false, "verbose (short)") // These flags are supposed only to use in test uflag.StringVar(&owner, "owner", "", "owner (Should only for test)") uflag.StringVar(&name, "name", "", "name (Should only for test)") if err := uflag.Parse(args); err != nil { return 1 } parsedArgs := uflag.Args() if len(parsedArgs) != 1 { c.UI.Error("Invalid argument: Usage glic apply [options] FILE") return 1 } designFile := parsedArgs[0] c.UI.Info(fmt.Sprintf( "Use design template %q for generating new cli project", designFile)) // Check file is exist or not if _, err := os.Stat(designFile); os.IsNotExist(err) { c.UI.Error(fmt.Sprintf( "Design file does not exsit")) return 1 } // Decode design file as skeleton.Executable executable := skeleton.NewExecutable() if _, err := toml.DecodeFile(designFile, executable); err != nil { c.UI.Error(fmt.Sprintf( "Failed to decode design file %q: %s", designFile, err)) return 1 } if err := executable.Fix(); err != nil { c.UI.Error(fmt.Sprintf( "Failed to fix input value: %s", err)) return 1 } // validate executable if errs := executable.Validate(); len(errs) > 0 { c.UI.Error(fmt.Sprintf( "%q is not valid template file. It has %d errors:", designFile, len(errs))) for _, err := range errs { c.UI.Error(fmt.Sprintf( " * %s", err.Error())) } return ExitCodeFailed } currentDir, err := os.Getwd() if err != nil { c.UI.Error(fmt.Sprintf( "Failed to get current directroy: %s", err)) return ExitCodeFailed } gopath := os.Getenv(EnvGoPath) if gopath == "" { c.UI.Error(fmt.Sprintf( "Failed to read GOPATH: it should not be empty")) return ExitCodeFailed } idealDir := filepath.Join(gopath, "src", "github.com", owner) output := executable.Name if currentDir != idealDir && !current { c.UI.Output("") c.UI.Output(fmt.Sprintf("====> WARNING: You are not in the directory gcli expects.")) c.UI.Output(fmt.Sprintf(" The codes will be generated be in $GOPATH/src/github.com/%s.", owner)) c.UI.Output(fmt.Sprintf(" Not in the current directory. This is because the output")) c.UI.Output(fmt.Sprintf(" codes use import path based on that path.")) c.UI.Output("") output = filepath.Join(idealDir, name) } if _, err := os.Stat(output); !os.IsNotExist(err) { msg := fmt.Sprintf("Cannot create directory %s: file exists", output) c.UI.Error(msg) return 1 } // Check option input first and if it's specified use it if len(frameworkStr) == 0 { if len(executable.FrameworkStr) != 0 { // If FrameworStr is specified from design file use it frameworkStr = executable.FrameworkStr } else { frameworkStr = defaultFrameworkString } } fmt.Println(frameworkStr) framework, err := skeleton.FrameworkByName(frameworkStr) if err != nil { c.UI.Error(fmt.Sprintf("Failed to generate %q: %s", executable.Name, err.Error())) return 1 } if len(name) != 0 { executable.Name = name output = name } if len(owner) != 0 { executable.Owner = owner } // Channels to receive artifact path (result) and error artifactCh, errCh := make(chan string), make(chan error) // Define Skeleton skeleton := &skeleton.Skeleton{ Path: output, Framework: framework, SkipTest: skipTest, Executable: executable, ArtifactCh: artifactCh, ErrCh: errCh, Verbose: verbose, LogWriter: os.Stdout, } // Create project directory doneCh := skeleton.Generate() for { select { case artifact := <-artifactCh: c.UI.Output(fmt.Sprintf(" Created %s", artifact)) case err := <-errCh: c.UI.Error(fmt.Sprintf("Failed to generate %s: %s", output, err.Error())) // If some file are created before error happend // Should be cleanuped if _, err := os.Stat(output); !os.IsNotExist(err) { c.UI.Output(fmt.Sprintf("Cleanup %s", output)) os.RemoveAll(output) } return ExitCodeFailed case <-doneCh: c.UI.Info(fmt.Sprintf("====> Successfully generated %s", executable.Name)) return ExitCodeOK } } }
// Run generates a new cli project. It returns exit code func (c *ApplyCommand) Run(args []string) int { var ( frameworkStr string skipTest bool verbose bool owner string name string ) uflag := flag.NewFlagSet("apply", flag.ContinueOnError) uflag.Usage = func() { c.UI.Error(c.Help()) } uflag.StringVar(&frameworkStr, "framework", "", "framework") uflag.StringVar(&frameworkStr, "F", "", "framework (short)") uflag.BoolVar(&skipTest, "skip-test", false, "skip-test") uflag.BoolVar(&skipTest, "T", false, "skip-test (short)") uflag.BoolVar(&verbose, "verbose", false, "verbose") uflag.BoolVar(&verbose, "V", false, "verbose (short)") // These flags are supposed only to use in test uflag.StringVar(&owner, "owner", "", "owner (Should only for test)") uflag.StringVar(&name, "name", "", "name (Should only for test)") errR, errW := io.Pipe() errScanner := bufio.NewScanner(errR) uflag.SetOutput(errW) go func() { for errScanner.Scan() { c.UI.Error(errScanner.Text()) } }() if err := uflag.Parse(args); err != nil { return 1 } parsedArgs := uflag.Args() if len(parsedArgs) != 1 { c.UI.Error("Invalid argument: Usage glic apply [options] FILE") return 1 } designFile := parsedArgs[0] c.UI.Info(fmt.Sprintf( "Use design template %q for generating new cli project", designFile)) // Check file is exist or not if _, err := os.Stat(designFile); os.IsNotExist(err) { c.UI.Error(fmt.Sprintf( "Design file does not exsit")) return 1 } // Decode design file as skeleton.Executable executable := skeleton.NewExecutable() if _, err := toml.DecodeFile(designFile, executable); err != nil { c.UI.Error(fmt.Sprintf( "Failed to decode design file %q: %s", designFile, err)) return 1 } // validate executable if errs := executable.Validate(); len(errs) > 0 { c.UI.Error(fmt.Sprintf( "%q is not valid template file. It has %d errors:", designFile, len(errs))) for _, err := range errs { c.UI.Error(fmt.Sprintf( " * %s", err.Error())) } return ExitCodeFailed } output := executable.Name if _, err := os.Stat(output); !os.IsNotExist(err) { msg := fmt.Sprintf("Cannot create directory %s: file exists", output) c.UI.Error(msg) return 1 } // Check option input first and if it's specified use it if len(frameworkStr) == 0 { if len(executable.FrameworkStr) != 0 { // If FrameworStr is specified from design file use it frameworkStr = executable.FrameworkStr } else { frameworkStr = defaultFrameworkString } } fmt.Println(frameworkStr) framework, err := skeleton.FrameworkByName(frameworkStr) if err != nil { c.UI.Error(fmt.Sprintf("Failed to generate %q: %s", executable.Name, err.Error())) return 1 } // Run fix flag struct. complement empty variable. if len(executable.Flags) > 0 { fixedFlags := []skeleton.Flag{} for _, f := range executable.Flags { if err := f.Fix(); err != nil { c.UI.Error(fmt.Sprintf( "Failed to fix flag struct: %s", err.Error())) return 1 } fixedFlags = append(fixedFlags, f) } executable.Flags = fixedFlags } if len(name) != 0 { executable.Name = name output = name } if len(owner) != 0 { executable.Owner = owner } // Channels to receive artifact path (result) and error artifactCh, errCh := make(chan string), make(chan error) // Define Skeleton skeleton := &skeleton.Skeleton{ Path: output, Framework: framework, SkipTest: skipTest, Executable: executable, ArtifactCh: artifactCh, ErrCh: errCh, Verbose: verbose, LogWriter: os.Stdout, } // Create project directory doneCh := skeleton.Generate() for { select { case artifact := <-artifactCh: c.UI.Output(fmt.Sprintf(" Created %s", artifact)) case err := <-errCh: c.UI.Error(fmt.Sprintf("Failed to generate %s: %s", output, err.Error())) // If some file are created before error happend // Should be cleanuped if _, err := os.Stat(output); !os.IsNotExist(err) { c.UI.Output(fmt.Sprintf("Cleanup %s", output)) os.RemoveAll(output) } return ExitCodeFailed case <-doneCh: c.UI.Info(fmt.Sprintf("====> Successfully generated %s", executable.Name)) return ExitCodeOK } } }