github.com/yuk1ty/readygo@v0.2.1-0.20220502041311-7a0cf7a1a1aa/cmd/root.go (about)

     1  package cmd
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"os/exec"
     8  	"strings"
     9  
    10  	"github.com/spf13/cobra"
    11  )
    12  
    13  var rootCmd = &cobra.Command{
    14  	Use:   "readygo",
    15  	Short: "The easiest way to get started with Go.",
    16  	Long:  `readygo is a tiny CLI tool for creating basic Go project.`,
    17  	Run: func(cmd *cobra.Command, args []string) {
    18  		pkgName, err := parsePackagePath(cmd)
    19  		if err != nil {
    20  			fmt.Println(err)
    21  			return
    22  		}
    23  
    24  		name, err := parseDirectoryName(cmd, pkgName)
    25  		if err != nil {
    26  			fmt.Println(err)
    27  			return
    28  		}
    29  
    30  		layout, err := parseLayout(cmd)
    31  		if err != nil {
    32  			fmt.Println(err)
    33  			return
    34  		}
    35  
    36  		err = runCmd(pkgName, name, layout)
    37  		if err != nil {
    38  			fmt.Println(err)
    39  			return
    40  		}
    41  	},
    42  }
    43  
    44  func parsePackagePath(cmd *cobra.Command) (*string, error) {
    45  	pkgName, err := cmd.Flags().GetString("module-path")
    46  	if err != nil {
    47  		fmt.Println(err)
    48  		return nil, err
    49  	}
    50  	if pkgName == "" {
    51  		return nil, errors.New("[ERROR] Module path should be set! Please use `--module-path` option. For more details, please hit --help option")
    52  	}
    53  	return &pkgName, nil
    54  }
    55  
    56  func parseDirectoryName(cmd *cobra.Command, pkgPath *string) (*string, error) {
    57  	name, err := cmd.Flags().GetString("dir-name")
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  	if name == "" {
    62  		// e.g. If passed `github.com/yuk1ty/readygo` then extract `readygo`
    63  		splitted := strings.Split(*pkgPath, "/")
    64  		name = splitted[len(splitted)-1]
    65  	}
    66  	return &name, nil
    67  }
    68  
    69  const (
    70  	Default  = "default"
    71  	Standard = "standard"
    72  )
    73  
    74  func parseLayout(cmd *cobra.Command) (*string, error) {
    75  	layout, err := cmd.Flags().GetString("layout")
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	if layout != Default && layout != Standard {
    81  		return nil, fmt.Errorf("[ERROR] Layout name should be `%s` or `%s`", Default, Standard)
    82  	}
    83  
    84  	return &layout, nil
    85  }
    86  
    87  func runCmd(pkgName *string, dirName *string, layout *string) error {
    88  	err := os.Mkdir(*dirName, 0777)
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	err = os.Chdir(*dirName)
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	cmd := exec.Command("go", "mod", "init", *pkgName)
    99  	err = cmd.Run()
   100  	if err != nil {
   101  		return err
   102  	}
   103  
   104  	git := exec.Command("git", "init")
   105  	err = git.Run()
   106  	if err != nil {
   107  		return err
   108  	}
   109  
   110  	err = createGitIgnore()
   111  	if err != nil {
   112  		return err
   113  	}
   114  
   115  	err = createMainGo()
   116  	if err != nil {
   117  		return err
   118  	}
   119  
   120  	if *layout == Standard {
   121  		err = createStandardLayoutDirs()
   122  		if err != nil {
   123  			return err
   124  		}
   125  	}
   126  
   127  	return nil
   128  }
   129  
   130  func createMainGo() error {
   131  	mainGo := `package main
   132  
   133  import "fmt"
   134  
   135  func main() {
   136  	fmt.Println("Hello, world")
   137  }`
   138  
   139  	f, err := os.Create("main.go")
   140  	if err != nil {
   141  		return err
   142  	}
   143  	defer f.Close()
   144  
   145  	_, err = f.WriteString(mainGo)
   146  	if err != nil {
   147  		return err
   148  	}
   149  
   150  	return nil
   151  }
   152  
   153  func createGitIgnore() error {
   154  	gitignoreBoilerplate := `*.exe
   155  *.exe~
   156  *.dll
   157  *.so
   158  *.dylib
   159  *.test
   160  *.out
   161  vendor/	
   162  `
   163  	f, err := os.Create(".gitignore")
   164  	if err != nil {
   165  		return err
   166  	}
   167  	defer f.Close()
   168  
   169  	_, err = f.WriteString(gitignoreBoilerplate)
   170  	if err != nil {
   171  		return err
   172  	}
   173  	return nil
   174  }
   175  
   176  func createStandardLayoutDirs() error {
   177  	var dirs [3]string = [3]string{
   178  		"cmd",
   179  		"internal",
   180  		"pkg",
   181  	}
   182  
   183  	for _, name := range dirs {
   184  		err := os.Mkdir(name, 0777)
   185  		if err != nil {
   186  			return err
   187  		}
   188  	}
   189  	return nil
   190  }
   191  
   192  func Execute() {
   193  	err := rootCmd.Execute()
   194  	if err != nil {
   195  		os.Exit(1)
   196  	}
   197  }
   198  
   199  func init() {
   200  	rootCmd.Flags().StringP("module-path", "p", "", "Define your module path. This is used for go mod init [module path].")
   201  	rootCmd.Flags().StringP("dir-name", "n", "", "Define the directory name of your project. This can be omitted. If you do so, the name will be extracted from its package name.")
   202  	rootCmd.Flags().StringP("layout", "l", "default", "Define your project layout. You can choose `default` or `standard`. If you omit this option, the value becomes `default`.")
   203  }