scaffold/internal/command/from_project.go

131 lines
2.8 KiB
Go

package command
import (
"fmt"
"net/url"
"os"
"forge.cadoles.com/wpetit/scaffold/internal/template"
"forge.cadoles.com/wpetit/scaffold/internal/project"
"github.com/pkg/errors"
"github.com/urfave/cli/v2"
)
func fromCommand() *cli.Command {
return &cli.Command{
Name: "from",
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",
},
&cli.StringSliceFlag{
Name: "ignore",
Aliases: []string{"i"},
Usage: "Ignore files matching pattern",
Value: cli.NewStringSlice(".git", ".git/**", "./.git/**/*"),
},
},
Action: fromAction,
}
}
func fromAction(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
}
}
if fetcher == nil {
return errors.Errorf("could not find any fetcher matching URL '%v'", projectURL)
}
vfs, err := fetcher.Fetch(projectURL)
if err != nil {
return errors.Wrap(err, "could not fetch project")
}
templateData := template.Data{}
manifestPath := c.String("manifest")
manifestFile, err := vfs.Open(manifestPath)
if err != nil {
if !os.IsNotExist(err) {
return errors.Wrapf(err, "could not read manifest '%s'", manifestPath)
}
fmt.Println("Could not find scaffold manifest.")
}
if manifestFile != nil {
defer manifestFile.Close()
fmt.Println("Loading scaffold manifest.")
manifest, err := template.Load(manifestFile)
if err != nil {
return errors.Wrapf(err, "could not load manifest '%s'", manifestPath)
}
if err := manifest.Validate(); err != nil {
return errors.Wrapf(err, "could not validate manifest '%s'", manifestPath)
}
fmt.Println("Prompting for templates variables.")
if err := template.Prompt(manifest, templateData); err != nil {
return errors.Wrap(err, "could not prompt for template data")
}
}
directory := c.String("directory")
ignore := c.StringSlice("ignore")
ignore = append(ignore, manifestPath)
fmt.Println("Generating project tree.")
err = template.CopyDir(vfs, ".", directory, &template.Option{
TemplateData: templateData,
TemplateExt: ".gotpl",
IgnorePatterns: ignore,
PreferredStrategy: template.Undefined,
})
if err != nil {
return err
}
fmt.Println("Done.")
return nil
}