github.com/mayra-cabrera/buffalo@v0.9.4-0.20170814145312-66d2e7772f11/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  		t, err := plush.Render(notInGoWorkspace, plush.NewContextWith(map[string]interface{}{
   111  			"name":     app.Name,
   112  			"gopath":   envy.GoPath(),
   113  			"current":  app.RootPath,
   114  			"username": u.Username,
   115  		}))
   116  		if err != nil {
   117  			return err
   118  		}
   119  		fmt.Println(t)
   120  		os.Exit(-1)
   121  	}
   122  	return nil
   123  }
   124  
   125  func goPath(root string) string {
   126  	gpMultiple := envy.GoPaths()
   127  	path := ""
   128  
   129  	for i := 0; i < len(gpMultiple); i++ {
   130  		if strings.HasPrefix(root, filepath.Join(gpMultiple[i], "src")) {
   131  			path = gpMultiple[i]
   132  			break
   133  		}
   134  	}
   135  	return path
   136  }
   137  
   138  func packagePath(rootPath string) string {
   139  	gosrcpath := strings.Replace(filepath.Join(goPath(rootPath), "src"), "\\", "/", -1)
   140  	rootPath = strings.Replace(rootPath, "\\", "/", -1)
   141  	return strings.Replace(rootPath, gosrcpath+"/", "", 2)
   142  }
   143  
   144  func genNewFiles() error {
   145  	packagePath := packagePath(app.RootPath)
   146  
   147  	data := map[string]interface{}{
   148  		"name":        app.Name,
   149  		"titleName":   inflect.Titleize(app.Name),
   150  		"packagePath": packagePath,
   151  		"actionsPath": packagePath + "/actions",
   152  		"modelsPath":  packagePath + "/models",
   153  		"withPop":     !app.SkipPop,
   154  		"withDep":     app.WithDep,
   155  		"withWebpack": !app.SkipWebpack && !app.API,
   156  		"skipYarn":    app.SkipYarn,
   157  		"withYarn":    !app.SkipYarn,
   158  		"dbType":      app.DBType,
   159  		"version":     Version,
   160  		"ciProvider":  app.CIProvider,
   161  		"asAPI":       app.API,
   162  		"asWeb":       !app.API,
   163  		"docker":      app.Docker,
   164  	}
   165  
   166  	g, err := app.Generator(data)
   167  	if err != nil {
   168  		return err
   169  	}
   170  	return g.Run(app.RootPath, data)
   171  }
   172  
   173  func init() {
   174  	pwd, _ := os.Getwd()
   175  
   176  	rootPath = pwd
   177  	app.RootPath = pwd
   178  
   179  	decorate("new", newCmd)
   180  	RootCmd.AddCommand(newCmd)
   181  	newCmd.Flags().BoolVar(&app.API, "api", false, "skip all front-end code and configure for an API server")
   182  	newCmd.Flags().BoolVarP(&app.Force, "force", "f", false, "delete and remake if the app already exists")
   183  	newCmd.Flags().BoolVarP(&app.Verbose, "verbose", "v", false, "verbosely print out the go get/install commands")
   184  	newCmd.Flags().BoolVar(&app.SkipPop, "skip-pop", false, "skips adding pop/soda to your app")
   185  	newCmd.Flags().BoolVar(&app.WithDep, "with-dep", false, "adds github.com/golang/dep to your app")
   186  	newCmd.Flags().BoolVar(&app.SkipWebpack, "skip-webpack", false, "skips adding Webpack to your app")
   187  	newCmd.Flags().BoolVar(&app.SkipYarn, "skip-yarn", false, "skip to use npm as the asset package manager")
   188  	newCmd.Flags().StringVar(&app.DBType, "db-type", "postgres", "specify the type of database you want to use [postgres, mysql, sqlite3]")
   189  	newCmd.Flags().StringVar(&app.Docker, "docker", "multi", "specify the type of Docker file to generate [none, multi, standard]")
   190  	newCmd.Flags().StringVar(&app.CIProvider, "ci-provider", "none", "specify the type of ci file you would like buffalo to generate [none, travis, gitlab-ci]")
   191  }
   192  
   193  func contains(s []string, e string) bool {
   194  	for _, a := range s {
   195  		if a == e {
   196  			return true
   197  		}
   198  	}
   199  	return false
   200  }
   201  
   202  var forbiddenAppNames = []string{"buffalo"}
   203  
   204  const notInGoWorkspace = `Oops! It would appear that you are not in your Go Workspace.
   205  
   206  Your $GOPATH is set to "<%= gopath %>".
   207  
   208  You are currently in "<%= current %>".
   209  
   210  The standard location for putting Go projects is something along the lines of "$GOPATH/src/github.com/<%= username %>/<%= name %>" (adjust accordingly).
   211  
   212  We recommend you go to "$GOPATH/src/github.com/<%= username %>/" and try "buffalo new <%= name %>" again.`
   213  
   214  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.
   215  
   216  We recommend reading this tutorial on setting everything up: https://www.goinggo.net/2016/05/installing-go-and-your-workspace.html
   217  
   218  When you're ready come back and try again. Don't worry, Buffalo will be right here waiting for you. :)`