github.com/cheikhshift/buffalo@v0.9.5/buffalo/cmd/new.go (about) 1 package cmd 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "os/user" 8 "path/filepath" 9 "regexp" 10 "strings" 11 12 "github.com/gobuffalo/buffalo/generators/newapp" 13 "github.com/gobuffalo/envy" 14 "github.com/gobuffalo/plush" 15 "github.com/markbates/inflect" 16 "github.com/spf13/cobra" 17 ) 18 19 var rootPath string 20 var app = &newapp.App{} 21 22 var newCmd = &cobra.Command{ 23 Use: "new [name]", 24 Short: "Creates a new Buffalo application", 25 RunE: func(cmd *cobra.Command, args []string) error { 26 if !validDbType() { 27 return fmt.Errorf("Unknown db-type %s expecting one of postgres, mysql or sqlite3", app.DBType) 28 } 29 30 if len(args) == 0 { 31 return errors.New("you must enter a name for your new application") 32 } 33 34 app.Name = args[0] 35 36 if forbiddenName() { 37 return fmt.Errorf("name %s is not allowed, try a different application name", app.Name) 38 } 39 40 if nameHasIllegalCharacter(app.Name) { 41 return fmt.Errorf("name %s is not allowed, application name can only be contain [a-Z0-9-_]", app.Name) 42 } 43 44 if app.Name == "." { 45 app.Name = filepath.Base(app.RootPath) 46 } else { 47 app.RootPath = filepath.Join(app.RootPath, app.Name) 48 } 49 50 err := validateInGoPath() 51 if err != nil { 52 return err 53 } 54 55 s, _ := os.Stat(app.RootPath) 56 if s != nil { 57 if app.Force { 58 os.RemoveAll(app.RootPath) 59 } else { 60 return fmt.Errorf("%s already exists! Either delete it or use the -f flag to force", app.Name) 61 } 62 } 63 64 err = genNewFiles() 65 if err != nil { 66 return err 67 } 68 69 fmt.Printf("Congratulations! Your application, %s, has been successfully built!\n\n", app.Name) 70 fmt.Println("You can find your new application at:") 71 fmt.Println(app.RootPath) 72 fmt.Println("\nPlease read the README.md file in your new application for next steps on running your application.") 73 74 return nil 75 }, 76 } 77 78 func validDbType() bool { 79 return app.DBType == "postgres" || app.DBType == "mysql" || app.DBType == "sqlite3" 80 } 81 82 func forbiddenName() bool { 83 return contains(forbiddenAppNames, strings.ToLower(app.Name)) 84 } 85 86 var nameRX = regexp.MustCompile("^[\\w-]+$") 87 88 func nameHasIllegalCharacter(name string) bool { 89 return !nameRX.MatchString(name) 90 } 91 92 func validateInGoPath() error { 93 gpMultiple := envy.GoPaths() 94 95 var gp string 96 larp := strings.ToLower(app.RootPath) 97 for i := 0; i < len(gpMultiple); i++ { 98 lgpm := strings.ToLower(filepath.Join(gpMultiple[i], "src")) 99 if strings.HasPrefix(larp, lgpm) { 100 gp = gpMultiple[i] 101 break 102 } 103 } 104 105 if gp == "" { 106 u, err := user.Current() 107 if err != nil { 108 return err 109 } 110 pwd, _ := os.Getwd() 111 t, err := plush.Render(notInGoWorkspace, plush.NewContextWith(map[string]interface{}{ 112 "name": app.Name, 113 "gopath": envy.GoPath(), 114 "current": pwd, 115 "username": u.Username, 116 })) 117 if err != nil { 118 return err 119 } 120 fmt.Println(t) 121 os.Exit(-1) 122 } 123 return nil 124 } 125 126 func goPath(root string) string { 127 gpMultiple := envy.GoPaths() 128 path := "" 129 130 for i := 0; i < len(gpMultiple); i++ { 131 if strings.HasPrefix(root, filepath.Join(gpMultiple[i], "src")) { 132 path = gpMultiple[i] 133 break 134 } 135 } 136 return path 137 } 138 139 func packagePath(rootPath string) string { 140 gosrcpath := strings.Replace(filepath.Join(goPath(rootPath), "src"), "\\", "/", -1) 141 rootPath = strings.Replace(rootPath, "\\", "/", -1) 142 return strings.Replace(rootPath, gosrcpath+"/", "", 2) 143 } 144 145 func genNewFiles() error { 146 packagePath := packagePath(app.RootPath) 147 148 data := map[string]interface{}{ 149 "appPath": app.RootPath, 150 "name": app.Name, 151 "titleName": inflect.Titleize(app.Name), 152 "packagePath": packagePath, 153 "actionsPath": packagePath + "/actions", 154 "modelsPath": packagePath + "/models", 155 "withPop": !app.SkipPop, 156 "withDep": app.WithDep, 157 "withWebpack": !app.SkipWebpack && !app.API, 158 "skipYarn": app.SkipYarn, 159 "withYarn": !app.SkipYarn, 160 "dbType": app.DBType, 161 "version": Version, 162 "ciProvider": app.CIProvider, 163 "asAPI": app.API, 164 "asWeb": !app.API, 165 "docker": app.Docker, 166 } 167 168 g, err := app.Generator(data) 169 if err != nil { 170 return err 171 } 172 return g.Run(app.RootPath, data) 173 } 174 175 func init() { 176 pwd, _ := os.Getwd() 177 178 rootPath = pwd 179 app.RootPath = pwd 180 181 decorate("new", newCmd) 182 RootCmd.AddCommand(newCmd) 183 newCmd.Flags().BoolVar(&app.API, "api", false, "skip all front-end code and configure for an API server") 184 newCmd.Flags().BoolVarP(&app.Force, "force", "f", false, "delete and remake if the app already exists") 185 newCmd.Flags().BoolVarP(&app.Verbose, "verbose", "v", false, "verbosely print out the go get commands") 186 newCmd.Flags().BoolVar(&app.SkipPop, "skip-pop", false, "skips adding pop/soda to your app") 187 newCmd.Flags().BoolVar(&app.WithDep, "with-dep", false, "adds github.com/golang/dep to your app") 188 newCmd.Flags().BoolVar(&app.SkipWebpack, "skip-webpack", false, "skips adding Webpack to your app") 189 newCmd.Flags().BoolVar(&app.SkipYarn, "skip-yarn", false, "skip to use npm as the asset package manager") 190 newCmd.Flags().StringVar(&app.DBType, "db-type", "postgres", "specify the type of database you want to use [postgres, mysql, sqlite3]") 191 newCmd.Flags().StringVar(&app.Docker, "docker", "multi", "specify the type of Docker file to generate [none, multi, standard]") 192 newCmd.Flags().StringVar(&app.CIProvider, "ci-provider", "none", "specify the type of ci file you would like buffalo to generate [none, travis, gitlab-ci]") 193 } 194 195 func contains(s []string, e string) bool { 196 for _, a := range s { 197 if a == e { 198 return true 199 } 200 } 201 return false 202 } 203 204 var forbiddenAppNames = []string{"buffalo"} 205 206 const notInGoWorkspace = `Oops! It would appear that you are not in your Go Workspace. 207 208 Your $GOPATH is set to "<%= gopath %>". 209 210 You are currently in "<%= current %>". 211 212 The standard location for putting Go projects is something along the lines of "$GOPATH/src/github.com/<%= username %>/<%= name %>" (adjust accordingly). 213 214 We recommend you go to "$GOPATH/src/github.com/<%= username %>/" and try "buffalo new <%= name %>" again.` 215 216 const noGoPath = `You do not have a $GOPATH set. In order to work with Go, you must set up your $GOPATH and your Go Workspace. 217 218 We recommend reading this tutorial on setting everything up: https://www.goinggo.net/2016/05/installing-go-and-your-workspace.html 219 220 When you're ready come back and try again. Don't worry, Buffalo will be right here waiting for you. :)`