[v2] Support remote templates

This commit is contained in:
Lea Anthony
2021-06-27 20:14:51 +10:00
parent c2015b1d72
commit 6dec097184
5 changed files with 198 additions and 69 deletions

View File

@@ -18,9 +18,20 @@ The next steps to complete the template are:
You can test your template by running this command:
`wails init -name test -template /path/to/template`
`wails init -name test -t /path/to/your/new/template`
### Checklist
Once generated, do the following tests:
- Change into the new project directory and run `wails build`. A working binary should be generated in the `build/bin` project directory.
- Run `wails dev`. This will compile your backend and run it. You should be able to go into the frontend directory and run `npm run dev` (or whatever your dev command is) and this should run correctly. You should be able to then open a browser to your local dev server and the application should work.
- Run `wails dev`. This will compile your backend and run it. You should be able to go into the frontend directory and run `npm run dev` (or whatever your dev command is) and this should run correctly. You should be able to then open a browser to your local dev server and the application should work.
## Publishing your template
You can publish a template to a git repository and use it as follows:
`wails init -name test -t https://your/git/url`
EG:
`wails init -name test -t https://github.com/leaanthony/testtemplate`

View File

@@ -2,11 +2,12 @@ package initialise
import (
"fmt"
"github.com/wailsapp/wails/v2/pkg/buildassets"
"io"
"strings"
"time"
"github.com/wailsapp/wails/v2/pkg/buildassets"
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/initialise/templates"
"github.com/leaanthony/clir"
@@ -18,17 +19,11 @@ import (
// AddSubcommand adds the `init` command for the Wails application
func AddSubcommand(app *clir.Cli, w io.Writer) error {
// Load the template shortnames
validShortNames, err := templates.TemplateShortNames()
if err != nil {
return err
}
command := app.NewSubCommand("init", "Initialise a new Wails project")
// Setup template name flag
templateName := "vanilla"
description := "Name of template to use. Valid tempates: " + validShortNames.Join(" ")
description := "Name of built-in template to use, path to template or template url."
command.StringFlag("t", description, &templateName)
// Setup project name
@@ -72,14 +67,6 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
return err
}
// Validate output type
if !validShortNames.Contains(templateName) {
logger.Print(fmt.Sprintf("[ERROR] Template '%s' is not valid", templateName))
logger.Println("")
command.PrintHelp()
return nil
}
// Validate name
if len(projectName) == 0 {
logger.Println("ERROR: Project name required")
@@ -122,7 +109,7 @@ func initProject(options *templates.Options) error {
start := time.Now()
// Install the template
err := templates.Install(options)
remote, err := templates.Install(options)
if err != nil {
return err
}
@@ -152,6 +139,11 @@ func initProject(options *templates.Options) error {
if options.InitGit {
options.Logger.Println("Git repository initialised.")
}
if remote {
options.Logger.Println("\nNOTE: You have created a project using a remote template. The Wails project takes no responsibility for 3rd party templates. Only use remote templates that you trust.")
}
options.Logger.Println("")
options.Logger.Println(fmt.Sprintf("Initialised project '%s' in %s.", options.ProjectName, elapsed.Round(time.Millisecond).String()))
options.Logger.Println("")

View File

@@ -5,14 +5,19 @@ import (
"encoding/json"
"fmt"
gofs "io/fs"
"io/ioutil"
"log"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/go-git/go-git/v5"
"github.com/pkg/errors"
"github.com/leaanthony/debme"
"github.com/leaanthony/gosod"
"github.com/leaanthony/slicer"
"github.com/olekukonko/tablewriter"
"github.com/wailsapp/wails/v2/internal/fs"
"github.com/wailsapp/wails/v2/pkg/clilogger"
@@ -74,7 +79,7 @@ func parseTemplate(template gofs.FS) (Template, error) {
var result Template
data, err := gofs.ReadFile(template, "template.json")
if err != nil {
return result, err
return result, errors.Wrap(err, "Error parsing template")
}
err = json.Unmarshal(data, &result)
if err != nil {
@@ -84,26 +89,6 @@ func parseTemplate(template gofs.FS) (Template, error) {
return result, nil
}
// TemplateShortNames returns a slicer of short template names
func TemplateShortNames() (*slicer.StringSlicer, error) {
var result slicer.StringSlicer
// If the cache isn't loaded, load it
if templateCache == nil {
err := loadTemplateCache()
if err != nil {
return nil, err
}
}
for _, template := range templateCache {
result.Add(template.ShortName)
}
return &result, nil
}
// List returns the list of available templates
func List() ([]Template, error) {
@@ -175,12 +160,12 @@ func loadTemplateCache() error {
return nil
}
// Install the given template
func Install(options *Options) error {
// Install the given template. Returns true if the template is remote.
func Install(options *Options) (bool, error) {
// Get cwd
cwd, err := os.Getwd()
if err != nil {
return err
return false, err
}
// Did the user want to install in current directory?
@@ -189,7 +174,7 @@ func Install(options *Options) error {
// If the current directory is empty, use it
isEmpty, err := fs.DirIsEmpty(cwd)
if err != nil {
return err
return false, err
}
if isEmpty {
@@ -198,7 +183,7 @@ func Install(options *Options) error {
} else {
options.TargetDir = filepath.Join(cwd, options.ProjectName)
if fs.DirExists(options.TargetDir) {
return fmt.Errorf("cannot create project directory. Dir exists: %s", options.TargetDir)
return false, fmt.Errorf("cannot create project directory. Dir exists: %s", options.TargetDir)
}
}
@@ -206,21 +191,47 @@ func Install(options *Options) error {
// Get the absolute path of the given directory
targetDir, err := filepath.Abs(filepath.Join(cwd, options.TargetDir))
if err != nil {
return err
return false, err
}
options.TargetDir = targetDir
if !fs.DirExists(options.TargetDir) {
err := fs.Mkdir(options.TargetDir)
if err != nil {
return err
return false, err
}
}
}
// Get template
// Flag to indicate remote template
remoteTemplate := false
// Is this a shortname?
template, err := getTemplateByShortname(options.TemplateName)
if err != nil {
return err
// Is this a filepath?
templatePath, err := filepath.Abs(options.TemplateName)
if fs.DirExists(templatePath) {
templateFS := os.DirFS(templatePath)
template, err = parseTemplate(templateFS)
if err != nil {
return false, errors.Wrap(err, "Error installing template")
}
} else {
// git clone to temporary dir
tempdir, err := gitclone(options)
defer func(path string) {
err := os.RemoveAll(path)
if err != nil {
log.Fatal(err)
}
}(tempdir)
templateFS := os.DirFS(tempdir)
template, err = parseTemplate(templateFS)
if err != nil {
return false, err
}
remoteTemplate = true
}
}
// Use Gosod to install the template
@@ -255,15 +266,30 @@ func Install(options *Options) error {
// Extract the template
err = installer.Extract(options.TargetDir, templateData)
if err != nil {
return err
return false, err
}
err = generateIDEFiles(options)
if err != nil {
return err
return false, err
}
return nil
return remoteTemplate, nil
}
// Clones the given uri and returns the temporary cloned directory
func gitclone(options *Options) (string, error) {
// Create temporary directory
dirname, err := ioutil.TempDir("", "wails-template-*")
if err != nil {
return "", err
}
_, err = git.PlainClone(dirname, false, &git.CloneOptions{
URL: options.TemplateName,
})
return dirname, err
}
// OutputList prints the list of available tempaltes to the given logger