scaffold/internal/command/new_project.go

140 lines
2.7 KiB
Go

package command
import (
"log"
"net/url"
"os"
"gitlab.com/wpetit/scaffold/internal/template"
"github.com/manifoldco/promptui"
"gitlab.com/wpetit/scaffold/internal/project"
"github.com/pkg/errors"
"github.com/urfave/cli/v2"
)
func newProjectCommand() *cli.Command {
return &cli.Command{
Name: "new",
Aliases: []string{"n"},
Usage: "generate a new project from a given template url",
ArgsUsage: "<URL>",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "directory",
Aliases: []string{"d"},
Usage: "Set destination to `DIR`",
Value: "./",
},
&cli.StringFlag{
Name: "manifest",
Aliases: []string{"m"},
Usage: "The scaffold manifest `FILE`",
Value: "scaffold.yml",
},
},
Action: newProjectAction,
}
}
func newProjectAction(c *cli.Context) error {
rawURL := c.Args().First()
projectURL, err := url.Parse(rawURL)
if err != nil {
return errors.Wrap(err, "could not parse url")
}
availableFetchers := []project.Fetcher{
project.NewGitFetcher(),
project.NewLocalFetcher(),
}
var fetcher project.Fetcher
for _, f := range availableFetchers {
if f.Match(projectURL) {
fetcher = f
break
}
}
vfs, err := fetcher.Fetch(projectURL)
if err != nil {
return errors.Wrap(err, "could not fetch project")
}
manifestFile := c.String("manifest")
manifestStat, err := vfs.Stat(manifestFile)
if err != nil && !os.IsNotExist(err) {
return errors.Wrap(err, "could not stat manifest file")
}
templateData := make(map[string]interface{})
if os.IsNotExist(err) {
log.Println("Could not find scaffold manifest.")
} else {
if manifestStat.IsDir() {
return errors.New("scaffold manifest is not a file")
}
log.Println("Loading template scaffold manifest...")
}
directory := c.String("directory")
return template.CopyDir(vfs, ".", directory, &template.Option{
TemplateData: templateData,
TemplateExt: ".gotpl",
IgnorePatterns: []string{manifestFile},
})
}
func promptForProjectName() (string, error) {
validate := func(input string) error {
if input == "" {
return errors.New("Project name cannot be empty")
}
return nil
}
prompt := promptui.Prompt{
Label: "Project Name",
Validate: validate,
}
return prompt.Run()
}
func promptForProjectNamespace() (string, error) {
validate := func(input string) error {
if input == "" {
return errors.New("Project namespace cannot be empty")
}
return nil
}
prompt := promptui.Prompt{
Label: "Project namespace",
Validate: validate,
}
return prompt.Run()
}
func promptForProjectType() (string, error) {
prompt := promptui.Select{
Label: "Project Type",
Items: []string{"web"},
}
_, result, err := prompt.Run()
return result, err
}