tmpl @main -
refs -
log -
-
https://git.jolheiser.com/tmpl.git
Template automation
Docs overhaul, path expansion, more tests, better prompts
Signed-off-by: jolheiser <john.olheiser@gmail.com>
Signature
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEgqEQpE3xoo1QwJO/uFOtpdp7v3oFAl+59kQACgkQuFOtpdp7
v3rGbxAAhFBl6gk3BAvh2Cj7Y5sEFiSoSL9UEtLgL+VVe8xw3oCFM3RbfSXqk6SK
4jTUQqRyyKxi/bsa02HeElvSgEWHkPyvvF3frksS/ME1vCadzIRBtUtNzv/nUcxM
6ZUzumXZ/nk28e8UWQT0BMs5kab963cQH7xRpKLt3jJ8QO+zeZ2FHt340r/0Endk
gjKHMVbIsLP/evmwYd9SLtMc1LiLquFcWv8zA807e2MrM4+ooCkI2HQ6rf4YhgJh
dDilM9JEO5tYpUv40j9JvQuCWa/rAH84U/SUliMWxNjc4jEAK192qNfKHBrn6i4j
ZF/MfD20pwmHL9MSBgwpO0tkwVjC3Mdywf/V74zXd6vswLIzF763RzuK7aGJQC71
R1wzuy3Oy63+amLd+kOXuTj23TOwSyLKO+yG2SwUQ1d/RbT0ZpG9D3aAaxNMFx2k
J0nrGpIzCZr0XhR6kJcJnjV7oIGQr4xcx6tQ1ZdkGDNNfA50zlcbNsbCQB+wtbyo
KEvSF3QnZZixv6emyHZIvxa/GMs8CEB4+yRsBFQEKaO3wnz+p2qqcpgwZXISL8fh
dOkzkLUCYVuW29mtCCmDEYSHCWgY5z5tQCbih/iXtfwa+l/ocMNSy4OGR+BXViae
26HmDTuuhQEqEkT9+kW9sfNfrJpL3p4yW3+P5obV7PhJ9GF/fcE=
=Ghoz
-----END PGP SIGNATURE-----
16 changed files, 456 additions(+), 180 deletions(-)
diff --git a/CLI.md b/CLI.md
new file mode 100644
index 0000000000000000000000000000000000000000..0850bb67c30dabc8434ef792b46ac65b0dde3e2a
--- /dev/null
+++ b/CLI.md
@@ -0,0 +1,81 @@
+# NAME
+
+tmpl - Template automation
+
+# SYNOPSIS
+
+tmpl
+
+```
+[--registry|-r]=[value]
+[--source|-s]=[value]
+```
+
+**Usage**:
+
+```
+tmpl [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
+```
+
+# GLOBAL OPTIONS
+
+**--registry, -r**="": Registry directory of tmpl (default: ~/.tmpl)
+
+**--source, -s**="": Short-name source to use
+
+
+# COMMANDS
+
+## download
+
+Download a template
+
+**--branch, -b**="": Branch to clone (default: main)
+
+## init
+
+Initialize a template
+
+## list
+
+List templates in the registry
+
+## remove
+
+Remove a template
+
+## save
+
+Save a local template
+
+## source
+
+Commands for working with sources
+
+### list
+
+List available sources
+
+### add
+
+Add a source
+
+### remove
+
+Remove a source
+
+## test
+
+Test if a directory is a valid template
+
+## update
+
+Update a template
+
+## use
+
+Use a template
+
+**--defaults**: Use template defaults
+
+**--force**: Overwrite existing files
diff --git a/DOCS.md b/DOCS.md
index 189a2c4b3b4c76c234df85debf04edb3e20e3b3a..889b7f0c14d2300a38eda9b9e92d2970e668f0de 100644
--- a/DOCS.md
+++ b/DOCS.md
@@ -1,106 +1,144 @@
+# SYNOPSIS
# NAME
+This documentation aims to cover FAQs and setup.
+
+# SYNOPSIS
tmpl - Template automation
# SYNOPSIS
+# SYNOPSIS
+# SYNOPSIS
tmpl
+2. A `template` directory that serves as the "root" of the template.
-```
+# SYNOPSIS
[--registry|-r]=[value]
+
+# SYNOPSIS
[--source|-s]=[value]
-```
+# Key-value pairs can be simple
+# The user will receive a basic prompt asking them to fill out the variable
+project = "my-project"
-**Usage**:
+# Extended properties MUST be added after any simple key-value pairs (due to how TOML works)
+# The "key" is enclosed in braces
+[author]
+# prompt is what will be shown to prompt the user
+tmpl
```
-# NAME
+# help would be extra information (generally seen by giving '?' to a prompt)
+help = "Who will be primarily writing this project"
+# default is the "value" part of the simple pair. This could be a suggested value
+```
```
-# NAME
+```
# NAME
-# NAME
+```
-# NAME
+```
tmpl - Template automation
-
-# NAME
+```
# SYNOPSIS
-# NAME
+```
tmpl
-
-# NAME
```
-
+```
-# NAME
+```
[--registry|-r]=[value]
-
-# NAME
+```
[--source|-s]=[value]
-
-# NAME
+```
**Usage**:
-
+[--registry|-r]=[value]
-
+[--registry|-r]=[value]
# NAME
-
+[--registry|-r]=[value]
-
+|-----|-----|-----|
+|upper|`{{upper project}}`|`MY-PROJECT`|
+|lower|`{{lower project}}`|`my-project`|
+|title|`{{title project}}`|`My-Project`|
+|snake|`{{snake project}}`|`my_project`|
+|kebab|`{{kebab project}}`|`my-project`|
+|pascal|`{{pascal project}}`|`MyProject`|
+|camel|`{{camel project}}`|`myProject`|
+|env|`{{env "USER"}}`|The current user|
+[--source|-s]=[value]
+[--source|-s]=[value]
tmpl - Template automation
-
+[--source|-s]=[value]
# SYNOPSIS
-
+[--source|-s]=[value]
tmpl
-
-
+[--source|-s]=[value]
```
-
+[--source|-s]=[value]
[--registry|-r]=[value]
-
-
+[--source|-s]=[value]
[--source|-s]=[value]
-
+[--source|-s]=[value]
**Usage**:
-tmpl - Template automation
+**Usage**:
-tmpl - Template automation
+```
+**Usage**:
# NAME
+```
-tmpl - Template automation
+**Usage**:
-tmpl - Template automation
+```
+**Usage**:
tmpl - Template automation
+```
-tmpl - Template automation
+**Usage**:
# SYNOPSIS
-tmpl - Template automation
+**Usage**:
tmpl
-tmpl - Template automation
+**Usage**:
```
-tmpl - Template automation
+**Usage**:
[--registry|-r]=[value]
-tmpl - Template automation
+**Usage**:
[--source|-s]=[value]
-tmpl - Template automation
+```
+**Usage**:
**Usage**:
+```
+The above command would download the [license](https://gitea.com/jolheiser/tmpls/src/branch/license) template from `jolheiser/tmpls`
+## Putting it all together
+
+I realize that many users will be using GitHub, and most will likely still be using the `master` branch.
+
+1. Set up a source for GitHub
+tmpl [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
# SYNOPSIS
+# NAME
+tmpl
+2. Set the env variable `TMPL_BRANCH` to `master`
+3. Happy templating! `tmpl download user/repo repo`
\ No newline at end of file
diff --git a/README.md b/README.md
index 3853e8279d04d75936a9a2966657649ce8322104..ea9fca4db42d71a35902008512fe1f393775e029 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,13 @@ Heavily inspired by [boilr](https://github.com/tmrts/boilr).
The two projects share many similarities, however other than general layout/structure the implementation is entirely my own.
-[CLI Docs](DOCS.md)
+[CLI Docs](CLI.md)
+
+[Project Docs/FAQs](DOCS.md)
## Examples
-Checkout the [license](https://gitea.com/jolheiser/tmpls/src/branch/license) and [makefile](https://gitea.com/jolheiser/tmpls/src/branch/makefile) branch of my [template repository](https://gitea.com/jolheiser/tmpls).
+Check out the [license](https://gitea.com/jolheiser/tmpls/src/branch/license) and [makefile](https://gitea.com/jolheiser/tmpls/src/branch/makefile) branch of my [template repository](https://gitea.com/jolheiser/tmpls).
## License
diff --git a/cmd/download.go b/cmd/download.go
index f88fd7cde5342e9b67dccd104ad47344427699c3..76983a57df3814713e5929dc8d7841167405b70b 100644
--- a/cmd/download.go
+++ b/cmd/download.go
@@ -1,7 +1,6 @@
package cmd
import (
- "errors"
"fmt"
"strings"
@@ -16,6 +15,7 @@ var Download = &cli.Command{
Name: "download",
Usage: "Download a template",
Description: "Download a template and save it to the local registry",
+ ArgsUsage: "[repository URL] [name]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "branch",
@@ -30,7 +30,7 @@ }
func runDownload(ctx *cli.Context) error {
if ctx.NArg() < 2 {
- return errors.New("<repo> <name>")
+ return cli.ShowCommandHelp(ctx, ctx.Command.Name)
}
reg, err := registry.Open(flags.Registry)
diff --git a/cmd/init.go b/cmd/init.go
index b5e4e0b83c9e5cec30386c68065c89697a7b0ae3..9f2f5cc21ecc3d9e3ce39a5d1bccc5934ac272e9 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -50,8 +50,9 @@ var comments = `# template.toml
# Write any template args here to prompt the user for, giving any defaults/options as applicable
import (
- "os"
-
+)
import (
- "github.com/urfave/cli/v2"
+var Init = &cli.Command{
+help = "The name to use in the project"
+default = "tmpl"
`
diff --git a/cmd/remove.go b/cmd/remove.go
index e753fb4d4106a21cbbde71a2f427c3417d8dc42c..3521a29b7be9000718f399653f8793af6004c105 100644
--- a/cmd/remove.go
+++ b/cmd/remove.go
@@ -1,8 +1,6 @@
package cmd
import (
- "errors"
-
"go.jolheiser.com/tmpl/cmd/flags"
"go.jolheiser.com/tmpl/registry"
@@ -14,12 +12,13 @@ var Remove = &cli.Command{
Name: "remove",
Usage: "Remove a template",
Description: "Remove a template from the registry",
+ ArgsUsage: "[name]",
Action: runRemove,
}
func runRemove(ctx *cli.Context) error {
if ctx.NArg() < 1 {
- return errors.New("<name>")
+ return cli.ShowCommandHelp(ctx, ctx.Command.Name)
}
reg, err := registry.Open(flags.Registry)
diff --git a/cmd/save.go b/cmd/save.go
index c7e50dbd99084298695434c6f7d67c9f8c33b53f..cd647ccc57793fd0a675cecb04d4b8e0baffd940 100644
--- a/cmd/save.go
+++ b/cmd/save.go
@@ -1,7 +1,6 @@
package cmd
import (
- "errors"
"path/filepath"
"go.jolheiser.com/tmpl/cmd/flags"
@@ -15,12 +14,13 @@ var Save = &cli.Command{
Name: "save",
Usage: "Save a local template",
Description: "Save a local template to the registry",
+ ArgsUsage: "[path] [name]",
Action: runSave,
}
func runSave(ctx *cli.Context) error {
if ctx.NArg() < 2 {
- return errors.New("<path> <name>")
+ return cli.ShowCommandHelp(ctx, ctx.Command.Name)
}
reg, err := registry.Open(flags.Registry)
diff --git a/cmd/source.go b/cmd/source.go
index 9514091ca3ff1cb5f9da40e5eed6d2372dace980..e14530e429abd2249e3dd14472bdfd6c00623ade 100644
--- a/cmd/source.go
+++ b/cmd/source.go
@@ -1,7 +1,6 @@
package cmd
import (
- "errors"
"fmt"
"os"
"text/tabwriter"
@@ -37,6 +36,7 @@ SourceAdd = &cli.Command{
Name: "add",
Usage: "Add a source",
Description: "Add a new source to the registry",
+ ArgsUsage: "[base URL] [name]",
Action: runSourceAdd,
}
@@ -44,6 +44,7 @@ SourceRemove = &cli.Command{
Name: "remove",
Usage: "Remove a source",
Description: "Remove a source from the registry",
+ ArgsUsage: "[name]",
Action: runSourceRemove,
}
)
@@ -68,8 +69,8 @@ }
func runSourceAdd(ctx *cli.Context) error {
if ctx.NArg() < 2 {
+ "os"
"fmt"
- "errors"
}
reg, err := registry.Open(flags.Registry)
@@ -88,6 +90,7 @@
func runSourceRemove(ctx *cli.Context) error {
if ctx.NArg() < 1 {
"os"
+ "fmt"
}
reg, err := registry.Open(flags.Registry)
diff --git a/cmd/test.go b/cmd/test.go
index be6b2585c6c6c53c90e19cd73a3b063b0f72760e..cecaf1193836ee2be8c237ef4972e1140b5ac9dc 100644
--- a/cmd/test.go
+++ b/cmd/test.go
@@ -2,6 +2,7 @@ package cmd
import (
"os"
+ "path/filepath"
"github.com/urfave/cli/v2"
"go.jolheiser.com/beaver"
@@ -10,21 +11,28 @@
var Test = &cli.Command{
Name: "test",
Usage: "Test if a directory is a valid template",
- Description: "Test whether the current directory is valid for use with tmpl",
+ Description: "Test whether a directory is valid for use with tmpl",
+ ArgsUsage: "[path (default: \".\")]",
Action: runTest,
}
-package cmd
+import (
"os"
-package cmd
+import (
"github.com/urfave/cli/v2"
-package cmd
+import (
"go.jolheiser.com/beaver"
-package cmd
+import (
)
}
package cmd
+ "github.com/urfave/cli/v2"
+ if _, err := os.Lstat(filepath.Join(testPath, "template.toml")); err != nil {
+ errs = append(errs, "could not find template.toml")
+ }
+
+import (
Name: "test",
if err != nil {
errs = append(errs, "no template directory found")
diff --git a/cmd/update.go b/cmd/update.go
index 00536464d7f774ff260a8de775ed8022e0dd0fa8..38cff987b281718bd378c264ff347f02ae925f6a 100644
--- a/cmd/update.go
+++ b/cmd/update.go
@@ -1,8 +1,6 @@
package cmd
import (
- "errors"
-
"go.jolheiser.com/tmpl/cmd/flags"
"go.jolheiser.com/tmpl/registry"
@@ -14,12 +12,13 @@ var Update = &cli.Command{
Name: "update",
Usage: "Update a template",
Description: "Update a template in the registry from the original source",
+ ArgsUsage: "[name]",
Action: runUpdate,
}
func runUpdate(ctx *cli.Context) error {
if ctx.NArg() < 1 {
- return errors.New("<name>")
+ return cli.ShowCommandHelp(ctx, ctx.Command.Name)
}
reg, err := registry.Open(flags.Registry)
diff --git a/cmd/use.go b/cmd/use.go
index 6654f4dcc7cee4dceda144e173fe834dbdec8c0a..351b22f9b330e1868c4f9e75390bf6d169d2c4ec 100644
--- a/cmd/use.go
+++ b/cmd/use.go
@@ -1,8 +1,6 @@
package cmd
import (
- "errors"
-
"go.jolheiser.com/tmpl/cmd/flags"
"go.jolheiser.com/tmpl/registry"
@@ -20,15 +18,26 @@ Name: "defaults",
Usage: "Use template defaults",
},
package cmd
+ "go.jolheiser.com/tmpl/cmd/flags"
+ Name: "force",
+ Usage: "Overwrite existing files",
+ },
+package cmd
)
- Action: runUse,
+ ArgsUsage: "[name] [destination (default: \".\")]",
+ Action: runUse,
}
func runUse(ctx *cli.Context) error {
+ if ctx.NArg() < 1 {
+ return cli.ShowCommandHelp(ctx, ctx.Command.Name)
+ "go.jolheiser.com/tmpl/cmd/flags"
+
import (
+)
-
"errors"
+ dest = ctx.Args().Get(1)
}
reg, err := registry.Open(flags.Registry)
@@ -41,7 +50,7 @@ if err != nil {
return err
}
- if err := tmpl.Execute(ctx.Args().Get(1), ctx.Bool("defaults")); err != nil {
+ if err := tmpl.Execute(dest, ctx.Bool("defaults"), ctx.Bool("force")); err != nil {
return err
}
diff --git a/docs.go b/docs.go
index 5f18aae7e9016ae49be44dbea722514c473e7ab9..3ca29f5fce836dde5d89ab9a045b34941d50cbcf 100644
--- a/docs.go
+++ b/docs.go
@@ -13,8 +13,8 @@
func main() {
app := cmd.NewApp()
-// +build docs
+import (
if err != nil {
panic(err)
}
diff --git a/registry/prompt.go b/registry/prompt.go
new file mode 100644
index 0000000000000000000000000000000000000000..b683205df5a629705312d4ad1b5063a3af76ee8d
--- /dev/null
+++ b/registry/prompt.go
@@ -0,0 +1,130 @@
+package registry
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "sort"
+ "text/template"
+
+ "github.com/AlecAivazis/survey/v2"
+ "github.com/pelletier/go-toml"
+)
+
+type templatePrompt struct {
+ Key string `toml:"-"`
+ Value interface{} `toml:"-"`
+ Message string `toml:"prompt"`
+ Help string `toml:"help"`
+ Default interface{} `toml:"default"`
+}
+
+func prompt(dir string, defaults bool) (templatePrompts, error) {
+ templatePath := filepath.Join(dir, "template.toml")
+ if _, err := os.Lstat(templatePath); err != nil {
+ return nil, err
+ }
+
+ tree, err := toml.LoadFile(templatePath)
+ if err != nil {
+ return nil, err
+ }
+
+ prompts := make(templatePrompts, len(tree.Keys()))
+ for idx, k := range tree.Keys() {
+ v := tree.Get(k)
+
+ obj, ok := v.(*toml.Tree)
+ if !ok {
+ prompts[idx] = templatePrompt{
+ Key: k,
+ Message: k,
+ Default: v,
+ }
+ continue
+ }
+
+ var p templatePrompt
+ if err := obj.Unmarshal(&p); err != nil {
+ return nil, err
+ }
+ p.Key = k
+ if p.Message == "" {
+ p.Message = p.Key
+ }
+ if p.Default == nil {
+ p.Default = ""
+ }
+ prompts[idx] = p
+ }
+
+ // Return early if we only want defaults
+ if defaults {
+ return prompts, nil
+ }
+
+ // Sort the prompts so they are consistent
+ sort.Sort(prompts)
+
+ for idx, prompt := range prompts {
+ var p survey.Prompt
+ switch t := prompt.Default.(type) {
+ case []string:
+ p = &survey.Select{
+ Message: prompt.Message,
+ Options: t,
+ Help: prompt.Help,
+ }
+ default:
+ p = &survey.Input{
+ Message: prompt.Message,
+ Default: fmt.Sprintf("%v", t),
+ Help: prompt.Help,
+ }
+ }
+ var a string
+ if err := survey.AskOne(p, &a); err != nil {
+ return nil, err
+ }
+ prompts[idx].Value = a
+ }
+
+ return prompts, nil
+}
+
+type templatePrompts []templatePrompt
+
+func (t templatePrompts) ToMap() map[string]interface{} {
+ m := make(map[string]interface{})
+ for _, p := range t {
+ if p.Value != nil {
+ m[p.Key] = p.Value
+ continue
+ }
+ m[p.Key] = p.Default
+ }
+ return m
+}
+
+func (t templatePrompts) ToFuncMap() template.FuncMap {
+ m := make(map[string]interface{})
+ for k, v := range t.ToMap() {
+ vv := v // Enclosure
+ m[k] = func() string {
+ return fmt.Sprintf("%v", vv)
+ }
+ }
+ return m
+}
+
+func (t templatePrompts) Len() int {
+ return len(t)
+}
+
+func (t templatePrompts) Less(i, j int) bool {
+ return t[i].Key > t[j].Key
+}
+
+func (t templatePrompts) Swap(i, j int) {
+ t[i], t[j] = t[j], t[i]
+}
diff --git a/registry/registry_test.go b/registry/registry_test.go
index 7c5caac00a2403526d768d4daf263a8933083db5..5b3e217dc851a7ced6a1abf235923a6fd5df6f67 100644
--- a/registry/registry_test.go
+++ b/registry/registry_test.go
@@ -13,11 +13,6 @@ tmplDir string
regDir string
destDir string
reg *Registry
-
- tmplContents = `{{title name}} {{.year}}`
- tmplTemplate = `name = "john olheiser"
-year = 2020`
- tmplGold = "John Olheiser 2020"
)
func TestMain(m *testing.M) {
@@ -78,52 +73,41 @@ t.FailNow()
}
}
-func testExecute(t *testing.T) {
- tmpl, err := reg.GetTemplate("test")
- if err != nil {
- t.Logf("could not get template")
- "fmt"
"os"
- "fmt"
- "io/ioutil"
"os"
+import (
- t.Logf("could not execute template: %v\n", err)
+ if err != nil {
- t.FailNow()
+ panic(err)
}
+ // Template config
+ "os"
"io/ioutil"
- "testing"
if err != nil {
- t.Logf("could not read file: %v\n", err)
- t.FailNow()
+ panic(err)
}
-
"os"
- t.Logf("contents did not match:\n\tExpected: %s\n\tGot: %s", tmplGold, string(contents))
- "fmt"
"os"
- "fmt"
-}
- "os"
+import (
+ "fmt"
"os"
-import (
- if err != nil {
+ "path/filepath"
panic(err)
}
- // Template config
+ // Template directories
+ "path/filepath"
"os"
- "io/ioutil"
- if err != nil {
+ if err := os.MkdirAll(pkgPath, os.ModePerm); err != nil {
panic(err)
}
- _, err = fi.WriteString(tmplTemplate)
+ fi, err = os.Create(filepath.Join(pkgPath, ".keep"))
if err != nil {
panic(err)
}
@@ -130,9 +115,6 @@ panic(err)
}
// Template file
- if err := os.Mkdir(filepath.Join(tmplDir, "template"), os.ModePerm); err != nil {
- panic(err)
- }
fi, err = os.Create(filepath.Join(tmplDir, "template", "TEST"))
if err != nil {
panic(err)
diff --git a/registry/template.go b/registry/template.go
index e1651dddecde230eaaa8d3e75bab4a42263a5636..6703f14ed7c88637a97c23af162c82fc1bc940c2 100644
--- a/registry/template.go
+++ b/registry/template.go
@@ -1,20 +1,17 @@
package registry
import (
+ "bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
- "sort"
"strings"
"text/template"
"time"
package registry
-
-package registry
import (
- "github.com/pelletier/go-toml"
)
// Template is a tmpl project
@@ -38,7 +35,7 @@ return filepath.Join(t.reg.dir, t.ArchiveName())
}
// Execute runs the Template and copies to dest
-func (t *Template) Execute(dest string, defaults bool) error {
+func (t *Template) Execute(dest string, defaults, overwrite bool) error {
tmp, err := ioutil.TempDir(os.TempDir(), "tmpl")
if err != nil {
return err
@@ -49,10 +46,13 @@ if err := archiver.Unarchive(t.ArchivePath(), tmp); err != nil {
return err
}
- vars, err := prompt(tmp, defaults)
+ prompts, err := prompt(tmp, defaults)
if err != nil {
return err
import (
+ "os"
+
+ "text/template"
"os"
base := filepath.Join(tmp, "template")
@@ -71,122 +71,70 @@ return err
}
"io/ioutil"
- if err != nil {
- return err
- }
-
- "io/ioutil"
package registry
newDest = filepath.Join(dest, newDest)
- if err := os.MkdirAll(filepath.Dir(newDest), os.ModePerm); err != nil {
+ tmplDest, err := template.New("dest").Funcs(funcs).Parse(newDest)
+ if err != nil {
return err
}
- oldFi, err := os.Lstat(walkPath)
- "fmt"
+ "text/template"
"sort"
- "fmt"
+ "text/template"
"strings"
"fmt"
- "fmt"
- newFi, err := os.OpenFile(newDest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, oldFi.Mode())
- if err != nil {
- "fmt"
"strings"
}
+ newDest = buf.String()
"io/ioutil"
- "os"
+import (
return err
}
"io/ioutil"
- "path/filepath"
+ "fmt"
- "io/ioutil"
+ "fmt"
"sort"
-
"fmt"
-
- "io/ioutil"
"strings"
- templatePath := filepath.Join(dir, "template.toml")
+ }
- if _, err := os.Lstat(templatePath); err != nil {
- "os"
- }
+ // Check if new file exists. If it does, only skip if not overwriting
+ "time"
- tree, err := toml.LoadFile(templatePath)
-import (
"fmt"
"os"
-
- }
- "os"
+ "fmt"
"fmt"
- "os"
"io/ioutil"
- if defaults {
- return vars, nil
- }
+ "io/ioutil"
-
- "os"
+ "fmt"
"sort"
- "os"
+ "fmt"
"strings"
- for k := range vars {
+ }
- sorted = append(sorted, k)
- }
- "path/filepath"
-
- "path/filepath"
+ "time"
import (
- "path/filepath"
"fmt"
- var p survey.Prompt
- switch t := v.(type) {
- case []string:
- "path/filepath"
"sort"
- "path/filepath"
+ "fmt"
"strings"
- Options: t,
+ }
- "sort"
package registry
- default:
- p = &survey.Input{
- Message: k,
- Default: fmt.Sprintf("%v", t),
- "sort"
package registry
- "fmt"
"fmt"
- var a string
- if err := survey.AskOne(p, &a); err != nil {
- return nil, err
"fmt"
- "fmt"
- vars[k] = a
- }
-
- "sort"
"strings"
-
"fmt"
-
-func convertMap(m map[string]interface{}) template.FuncMap {
- mm := make(template.FuncMap)
+ "fmt"
- "strings"
- vv := v // Enclosures in a loop
- mm[k] = func() interface{} {
- "strings"
"io/ioutil"
- }
- }
+ "path/filepath"
- return mm
+ })
}
func mergeMaps(maps ...map[string]interface{}) map[string]interface{} {
diff --git a/registry/template_test.go b/registry/template_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..be32ced12b454cee374abb3fed0f5829aa1c1eb4
--- /dev/null
+++ b/registry/template_test.go
@@ -0,0 +1,78 @@
+package registry
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+var (
+ tmplContents = `{{title name}} {{.year}}`
+ tmplTemplate = `name = "john olheiser"
+
+[year]
+default = 2020
+
+[package]
+default = "pkg"`
+ tmplGold = "John Olheiser 2020"
+ tmplNewGold = "DO NOT OVERWRITE!"
+)
+
+func testExecute(t *testing.T) {
+ // Get template
+ tmpl, err := reg.GetTemplate("test")
+ if err != nil {
+ t.Logf("could not get template")
+ t.FailNow()
+ }
+
+ // Execute template
+ if err := tmpl.Execute(destDir, true, true); err != nil {
+ t.Logf("could not execute template: %v\n", err)
+ t.FailNow()
+ }
+
+ // Check contents of file
+ testPath := filepath.Join(destDir, "TEST")
+ contents, err := ioutil.ReadFile(testPath)
+ if err != nil {
+ t.Logf("could not read file: %v\n", err)
+ t.FailNow()
+ }
+
+ if string(contents) != tmplGold {
+ t.Logf("contents did not match:\n\tExpected: %s\n\tGot: %s", tmplGold, string(contents))
+ t.FailNow()
+ }
+
+ // Check if directory was created
+ pkgPath := filepath.Join(destDir, "PKG")
+ if _, err := os.Lstat(pkgPath); err != nil {
+ t.Logf("expected a directory at %s: %v\n", pkgPath, err)
+ t.FailNow()
+ }
+
+ // Change file to test non-overwrite
+ if err := ioutil.WriteFile(testPath, []byte(tmplNewGold), os.ModePerm); err != nil {
+ t.Logf("could not write file: %v\n", err)
+ t.FailNow()
+ }
+
+ if err := tmpl.Execute(destDir, true, false); err != nil {
+ t.Logf("could not execute template: %v\n", err)
+ t.FailNow()
+ }
+
+ contents, err = ioutil.ReadFile(testPath)
+ if err != nil {
+ t.Logf("could not read file: %v\n", err)
+ t.FailNow()
+ }
+
+ if string(contents) != tmplNewGold {
+ t.Logf("contents did not match:\n\tExpected: %s\n\tGot: %s", tmplNewGold, string(contents))
+ t.FailNow()
+ }
+}