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: "", 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 }